public int New(OrderNew viewModel) { Order order = null; order = new Order() { Address1 = viewModel.Address1, Address2 = viewModel.Address2, City = viewModel.City, CountryId = viewModel.CountryCode, Country = db.Countries.First(c => c.Id == viewModel.CountryCode.ToLower()), Email = viewModel.Email, Firstname = viewModel.Firstname, Name = viewModel.Name, Salutation = viewModel.Salutation, Zip = viewModel.Zip, Comment = viewModel.Comment }; var productIdsAndQtys = viewModel.Products.ToDictionary( k => k.Id, v => v.Qty); new ShopService().PlaceOrder(db, order, productIdsAndQtys); return order.Id; }
/// <summary> /// Versandkosten berechnen. /// </summary> /// <param name="order"></param> /// <returns></returns> public decimal CalculateShippingCosts(Order order) { if (order.Country == null) { throw new AppException("Für die Versandkosten muss ein Land angegeben sein!"); } return order.OrderLines.Sum(ol => order.Country.ShippingCost(ol.Product.ShippingCategory)); }
/// <summary> /// Bestellung abgeben. /// </summary> /// <param name="order"></param> /// <param name="productIdsAndQtys"></param> public void PlaceOrder(Entities db, Order order, IDictionary<int, int> productIdsAndQtys) { using (var transaction = new TransactionScope()) { // Bestellung mit Datum versehen und in DB speichern. order.CreatedAt = DateTime.Now; // Die Bestellung muss erstmal ohne Bestellzeilen gespeichert werden, // damit wir eine BestellID aus der DB haben. db.Orders.Add(order); db.SaveChanges(); foreach (var id in productIdsAndQtys.Keys) { var product = db.Products .Include(p => p.ShippingCategory) // Brauchen wird für die Versandkostenberechnung. .FirstOrDefault(x => x.Id == id); var qty = productIdsAndQtys[id]; if (product == null) { throw new AppException(string.Format( "Das Produkt mit der Id {0} ist nicht verfügbar!", id)); } // Nicht mehr genug vom Produkt auf Lager? if (product.Available < qty) { throw new AppException(string.Format( "Von {0} ist/sind nur noch {1} Stück auf Lager. Bitte Menge anpassen.", product.Name, product.Available)); } // Menge abziehen. product.Available -= qty; // Produkte zur Bestellung hinzufügen. order.OrderLines.Add(new OrderLine() { OrderId = order.Id, ProductId = id, Product = product, Qty = qty }); } // ...speichern. db.SaveChanges(); // Preis berechnen order.SubTotalPrice = CalculateSubTotalPrice(order); // Versandkosten berechnen order.ShippingCosts = CalculateShippingCosts(order); // Validierung. var vc = new ValidationContext(order, null, null); Validator.ValidateObject(order, vc, true); // ...speichern. db.SaveChanges(); // Bestätigungsmail verschicken. var mailBody = Nustache.Core.Render.StringToString(db.Parameters.First().MailMessageOrdered, order); MailService.SendMailToCustomer(order.Email, "Deine Bestellung bei lillypark.com", mailBody); transaction.Complete(); } // Benachrichtgung an den Shopinhaber, dass eine neue // Bestellung eingegangen ist. // INFO: Wenn das Verschicken fehlschlägt, soll die Bestellung dennoch angenommen werden. var ownerMailBody = string.Format(@" Hi Lilly/Hoonie, guckst Du <a href=""http://lillypark.com/orders/details/{0}"">hier</a>. Liebe Grüße, Dein WebShop", order.Id); MailService.SendMailToOwner("Eine neue Bestellung ist eingegangen.", ownerMailBody); }
/// <summary> /// Markiert einen Auftrag als verschickt. /// </summary> /// <param name="order"></param> public void ShipOrder(Entities db, Order order, string mailBody) { if (order == null) { throw new ArgumentNullException("order"); } order.ShippedAt = DateTime.Now; // Email an den Kunden schicken. MailService.SendMailToCustomer(order.Email, "Deine Bestellung wurde verschickt", mailBody); db.SaveChanges(); }
/// <summary> /// Markiert einen Auftrag als bezahlt. /// </summary> /// <param name="order"></param> public void PayOrder(Entities db, Order order, string mailBody=null) { if (order == null) { throw new ArgumentNullException("order"); } order.PaidAt = DateTime.Now; // TODO: Vielleicht hat der Kunde schon vorher gezahlt? // Wenn kein Bestätigungs-Mail-Body angegeben wurde, // müssen wir den selber erstellen. var body = mailBody == null ? Nustache.Core.Render.StringToString(db.Parameters.First().MailMessagePaid, order) : mailBody; // Email an den Kunden schicken. MailService.SendMailToCustomer(order.Email, "Wir haben Deine Bezahlung erhalten", body); db.SaveChanges(); }
/// <summary> /// Berechnet den Preis aller Bestellzeilen (ohne Versandkosten oder ähnlichem). /// </summary> /// <param name="order"></param> /// <returns></returns> public decimal CalculateSubTotalPrice(Order order) { return order.OrderLines .Select(ol => ol.Product.Price * ol.Qty) .Sum(); }
/// <summary> /// Place a new order from an existing cart. /// </summary> /// <param name="cartId"></param> /// <param name="request"></param> /// <returns></returns> public Order CreateOrder(int cartId, CreateOrderRequest request) { // Validate request. var vc = new ValidationContext(request); Validator.ValidateObject(request, vc, true); lock (_orderLock) // Only one order at a time. { using (var tx = new TransactionScope()) { using (var db = new Entities()) { // Get cart. var cart = db.Carts .Include(i => i.LineItems.Select(l => l.Product)) .Single(c => c.Id == cartId); if (cart.OrderId.HasValue) { throw new ApplicationException(string.Format( "Dieser Warenkorb ({0} wurde bereits bestellt!", cartId)); } // Calcualte costs and taxes. var shippingCosts = _ShippingService.CalculateShippingCosts(cartId, request.DeliveryAddress.CountryId); var tax = _TaxService.TaxForCountry(cartId, request.DeliveryAddress.CountryId); var da = request.DeliveryAddress; // Create new Order. var order = new Order { // Adressen Address1 = da.Address1, Address2 = da.Address2, City = da.City, CountryId = da.CountryId, Email = da.Email, Firstname = da.Firstname, Name = da.Lastname, Salutation = da.Salutation, Zip = da.Zip, ShippingCosts = shippingCosts, Tax = tax, SubTotalPrice = cart.Subtotal, Total = cart.Subtotal + shippingCosts + tax, CreatedAt = DateTime.UtcNow }; // Order speicher. db.Orders.Add(order); db.SaveChanges(); // Alle Lineitems der Order zuweisen. foreach (var lineItem in cart.LineItems) { if (lineItem.Product == null) { throw new ApplicationException(string.Format( "Das Produkt mit der Id {0} ist nicht verfügbar!", lineItem.ProductId)); } if (lineItem.Product.Available < lineItem.Qty) { throw new ApplicationException(string.Format( "Von {0} ist/sind nur noch {1} Stück auf Lager. Bitte Menge anpassen.", lineItem.Product.Name, lineItem.Product.Available)); } lineItem.Product.Available -= lineItem.Qty; lineItem.OrderId = order.Id; } // Mark cart as ordered. cart.OrderId = order.Id; // Bestätigungsmail verschicken. //var mailBody = Nustache.Core.Render.StringToString(db.Parameters.First().MailMessageOrdered, order); //MailService.SendMailToCustomer(order.Email, "Deine Bestellung bei lillypark.com", mailBody); // Commit! tx.Complete(); return order; } } } }
public virtual ActionResult Index(PostOrderNew viewModel) { if (ModelState.IsValid) { try { var order = new Order() { Address1 = viewModel.Address1, Address2 = viewModel.Address2, City = viewModel.City, CountryId = viewModel.CountryCode, Country = db.Countries.First(c => c.Id == viewModel.CountryCode.ToLower()), Email = viewModel.Email, Firstname = viewModel.Firstname, Name = viewModel.Name, Salutation = viewModel.Salutation, Zip = viewModel.Zip, Comment = viewModel.Comment }; var productIdsAndQtys = viewModel.Products.ToDictionary( k => k.Id, v => v.Qty); new ShopService().PlaceOrder(db, order, productIdsAndQtys); return viewModel.UsesPayPal ? RedirectToAction("create", "paypal", new { orderId = order.Id }) : RedirectToAction("success", new { id = order.Id }); } catch (AppException e) { Error(e.Message); } } // ViewModel um die Länder anreichern. var vm = new OrderNew(db.Countries); return View("index", Mapper.Map(viewModel, vm)); }