/// <summary> /// Deletes a shipment /// </summary> /// <param name="shipment">Shipment</param> public virtual void DeleteShipment(Shipment shipment) { if (shipment == null) throw new ArgumentNullException("shipment"); _shipmentRepository.Delete(shipment); //event notification _eventPublisher.EntityDeleted(shipment); }
public void Can_save_and_load_shipment() { var shipment = new Shipment { Order = GetTestOrder(), TrackingNumber = "TrackingNumber 1", TotalWeight = 9.87M, ShippedDateUtc = new DateTime(2010, 01, 01), DeliveryDateUtc = new DateTime(2010, 01, 02), CreatedOnUtc = new DateTime(2010, 01, 03), }; var fromDb = SaveAndLoadEntity(shipment); fromDb.ShouldNotBeNull(); fromDb.TrackingNumber.ShouldEqual("TrackingNumber 1"); fromDb.TotalWeight.ShouldEqual(9.87M); fromDb.ShippedDateUtc.ShouldEqual(new DateTime(2010, 01, 01)); fromDb.DeliveryDateUtc.ShouldEqual(new DateTime(2010, 01, 02)); fromDb.CreatedOnUtc.ShouldEqual(new DateTime(2010, 01, 03)); }
public void Can_save_and_load_shipment_with_products() { var shipment = new Shipment { Order = GetTestOrder(), TrackingNumber = "TrackingNumber 1", ShippedDateUtc = new DateTime(2010, 01, 01), DeliveryDateUtc = new DateTime(2010, 01, 02), CreatedOnUtc = new DateTime(2010, 01, 03), }; shipment.ShipmentOrderProductVariants.Add(new ShipmentOrderProductVariant() { OrderProductVariantId = 1, Quantity = 2, }); var fromDb = SaveAndLoadEntity(shipment); fromDb.ShouldNotBeNull(); fromDb.ShipmentOrderProductVariants.ShouldNotBeNull(); (fromDb.ShipmentOrderProductVariants.Count == 1).ShouldBeTrue(); fromDb.ShipmentOrderProductVariants.First().Quantity.ShouldEqual(2); }
/// <summary> /// Sends a shipment delivered notification to a customer /// </summary> /// <param name="shipment">Shipment</param> /// <param name="languageId">Message language identifier</param> /// <returns>Queued email identifier</returns> public virtual int SendShipmentDeliveredCustomerNotification(Shipment shipment, int languageId) { if (shipment == null) throw new ArgumentNullException("shipment"); var order = shipment.Order; if (order == null) throw new Exception("Order cannot be loaded"); var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); var messageTemplate = GetLocalizedActiveMessageTemplate("ShipmentDelivered.CustomerNotification", languageId, store.Id); if (messageTemplate == null) return 0; //tokens var tokens = new List<Token>(); _messageTokenProvider.AddStoreTokens(tokens, store); _messageTokenProvider.AddShipmentTokens(tokens, shipment, languageId); _messageTokenProvider.AddOrderTokens(tokens, shipment.Order, languageId); _messageTokenProvider.AddCustomerTokens(tokens, shipment.Order.Customer); //event notification _eventPublisher.MessageTokensAdded(messageTemplate, tokens); var emailAccount = GetEmailAccountOfMessageTemplate(messageTemplate, languageId); var toEmail = order.BillingAddress.Email; var toName = string.Format("{0} {1}", order.BillingAddress.FirstName, order.BillingAddress.LastName); return SendNotification(messageTemplate, emailAccount, languageId, tokens, toEmail, toName); }
protected ShipmentDetailsModel PrepareShipmentDetailsModel(Shipment shipment) { if (shipment == null) throw new ArgumentNullException("shipment"); var order = shipment.Order; if (order == null) throw new Exception("order cannot be loaded"); var model = new ShipmentDetailsModel(); model.Id = shipment.Id; if (shipment.ShippedDateUtc.HasValue) model.ShippedDate = _dateTimeHelper.ConvertToUserTime(shipment.ShippedDateUtc.Value, DateTimeKind.Utc); if (shipment.DeliveryDateUtc.HasValue) model.DeliveryDate = _dateTimeHelper.ConvertToUserTime(shipment.DeliveryDateUtc.Value, DateTimeKind.Utc); //tracking number and shipment information model.TrackingNumber = shipment.TrackingNumber; var srcm = _shippingService.LoadShippingRateComputationMethodBySystemName(order.ShippingRateComputationMethodSystemName); if (srcm != null && srcm.PluginDescriptor.Installed && srcm.IsShippingRateComputationMethodActive(_shippingSettings)) { var shipmentTracker = srcm.ShipmentTracker; if (shipmentTracker != null) { model.TrackingNumberUrl = shipmentTracker.GetUrl(shipment.TrackingNumber); if (_shippingSettings.DisplayShipmentEventsToCustomers) { var shipmentEvents = shipmentTracker.GetShipmentEvents(shipment.TrackingNumber); if (shipmentEvents != null) foreach (var shipmentEvent in shipmentEvents) { var shipmentStatusEventModel = new ShipmentDetailsModel.ShipmentStatusEventModel(); var shipmentEventCountry = _countryService.GetCountryByTwoLetterIsoCode(shipmentEvent.CountryCode); shipmentStatusEventModel.Country = shipmentEventCountry != null ? shipmentEventCountry.GetLocalized(x => x.Name) : shipmentEvent.CountryCode; shipmentStatusEventModel.Date = shipmentEvent.Date; shipmentStatusEventModel.EventName = shipmentEvent.EventName; shipmentStatusEventModel.Location = shipmentEvent.Location; model.ShipmentStatusEvents.Add(shipmentStatusEventModel); } } } } //products in this shipment model.ShowSku = _catalogSettings.ShowProductSku; foreach (var sopv in shipment.ShipmentOrderProductVariants) { var opv = _orderService.GetOrderProductVariantById(sopv.OrderProductVariantId); if (opv == null) continue; var sopvModel = new ShipmentDetailsModel.ShipmentOrderProductVariantModel() { Id = sopv.Id, Sku = opv.ProductVariant.FormatSku(opv.AttributesXml, _productAttributeParser), ProductId = opv.ProductVariant.ProductId, ProductSeName = opv.ProductVariant.Product.GetSeName(), AttributeInfo = opv.AttributeDescription, QuantityOrdered = opv.Quantity, QuantityShipped = sopv.Quantity, }; //product name//product name if (!String.IsNullOrEmpty(opv.ProductVariant.GetLocalized(x => x.Name))) sopvModel.ProductName = string.Format("{0} ({1})", opv.ProductVariant.Product.GetLocalized(x => x.Name), opv.ProductVariant.GetLocalized(x => x.Name)); else sopvModel.ProductName = opv.ProductVariant.Product.GetLocalized(x => x.Name); model.Items.Add(sopvModel); } //order details model model.Order = PrepareOrderDetailsModel(order); return model; }
/// <summary> /// Marks a shipment as delivered /// </summary> /// <param name="shipment">Shipment</param> /// <param name="notifyCustomer">True to notify customer</param> public virtual void Deliver(Shipment shipment, bool notifyCustomer) { if (shipment == null) throw new ArgumentNullException("shipment"); var order = shipment.Order; if (order == null) throw new Exception("Order cannot be loaded"); if (shipment.DeliveryDateUtc.HasValue) throw new Exception("This shipment is already delivered"); shipment.DeliveryDateUtc = DateTime.UtcNow; _shipmentService.UpdateShipment(shipment); if (!order.HasItemsToAddToShipment() && !order.HasItemsToShip() && !order.HasItemsToDeliver()) order.ShippingStatusId = (int)ShippingStatus.Delivered; _orderService.UpdateOrder(order); //add a note order.OrderNotes.Add(new OrderNote() { Note = string.Format("Shipment# {0} has been delivered", shipment.Id), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); if (notifyCustomer) { //send email notification int queuedEmailId = _workflowMessageService.SendShipmentDeliveredCustomerNotification(shipment, order.CustomerLanguageId); if (queuedEmailId > 0) { order.OrderNotes.Add(new OrderNote() { Note = string.Format("\"Delivered\" email (to customer) has been queued. Queued email identifier: {0}.", queuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } } //check order status CheckOrderStatus(order); }
/// <summary> /// Send a shipment /// </summary> /// <param name="shipment">Shipment</param> /// <param name="notifyCustomer">True to notify customer</param> public virtual void Ship(Shipment shipment, bool notifyCustomer) { if (shipment == null) throw new ArgumentNullException("shipment"); var order = _orderService.GetOrderById(shipment.OrderId); if (order == null) throw new Exception("Order cannot be loaded"); if (shipment.ShippedDateUtc.HasValue) throw new Exception("This shipment is already shipped"); shipment.ShippedDateUtc = DateTime.UtcNow; _shipmentService.UpdateShipment(shipment); //check whether we have more items to ship if (order.HasItemsToAddToShipment() || order.HasItemsToShip()) order.ShippingStatusId = (int)ShippingStatus.PartiallyShipped; else order.ShippingStatusId = (int)ShippingStatus.Shipped; _orderService.UpdateOrder(order); //add a note order.OrderNotes.Add(new OrderNote() { Note = string.Format("Shipment# {0} has been sent", shipment.Id), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); if (notifyCustomer) { //notify customer int queuedEmailId = _workflowMessageService.SendShipmentSentCustomerNotification(shipment, order.CustomerLanguageId); if (queuedEmailId > 0) { order.OrderNotes.Add(new OrderNote() { Note = string.Format("\"Shipped\" email (to customer) has been queued. Queued email identifier: {0}.", queuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } } //check order status CheckOrderStatus(order); }
/// <summary> /// Convert a collection to a HTML table /// </summary> /// <param name="shipment">Shipment</param> /// <param name="languageId">Language identifier</param> /// <returns>HTML table of products</returns> protected virtual string ProductListToHtmlTable(Shipment shipment, int languageId) { var result = ""; var sb = new StringBuilder(); sb.AppendLine("<table border=\"0\" style=\"width:100%;\">"); #region Products sb.AppendLine(string.Format("<tr style=\"background-color:{0};text-align:center;\">", _templatesSettings.Color1)); sb.AppendLine(string.Format("<th>{0}</th>", _localizationService.GetResource("Messages.Order.Product(s).Name", languageId))); sb.AppendLine(string.Format("<th>{0}</th>", _localizationService.GetResource("Messages.Order.Product(s).Quantity", languageId))); sb.AppendLine("</tr>"); var table = shipment.ShipmentOrderProductVariants.ToList(); for (int i = 0; i <= table.Count - 1; i++) { var sopv = table[i]; var opv = _orderService.GetOrderProductVariantById(sopv.OrderProductVariantId); if (opv == null) continue; var productVariant = opv.ProductVariant; if (productVariant == null) continue; sb.AppendLine(string.Format("<tr style=\"background-color: {0};text-align: center;\">", _templatesSettings.Color2)); //product name string productName = ""; //product name if (!String.IsNullOrEmpty(opv.ProductVariant.GetLocalized(x => x.Name, languageId))) productName = string.Format("{0} ({1})", opv.ProductVariant.Product.GetLocalized(x => x.Name, languageId), opv.ProductVariant.GetLocalized(x => x.Name, languageId)); else productName = opv.ProductVariant.Product.GetLocalized(x => x.Name, languageId); sb.AppendLine("<td style=\"padding: 0.6em 0.4em;text-align: left;\">" + HttpUtility.HtmlEncode(productName)); //attributes if (!String.IsNullOrEmpty(opv.AttributeDescription)) { sb.AppendLine("<br />"); sb.AppendLine(opv.AttributeDescription); } //sku if (_catalogSettings.ShowProductSku) { var sku = opv.ProductVariant.FormatSku(opv.AttributesXml, _productAttributeParser); if (!String.IsNullOrEmpty(sku)) { sb.AppendLine("<br />"); sb.AppendLine(string.Format(_localizationService.GetResource("Messages.Order.Product(s).SKU", languageId), HttpUtility.HtmlEncode(sku))); } } sb.AppendLine("</td>"); sb.AppendLine(string.Format("<td style=\"padding: 0.6em 0.4em;text-align: center;\">{0}</td>", sopv.Quantity)); sb.AppendLine("</tr>"); } #endregion sb.AppendLine("</table>"); result = sb.ToString(); return result; }
public virtual void AddShipmentTokens(IList<Token> tokens, Shipment shipment, int languageId) { tokens.Add(new Token("Shipment.ShipmentNumber", shipment.Id.ToString())); tokens.Add(new Token("Shipment.TrackingNumber", shipment.TrackingNumber)); tokens.Add(new Token("Shipment.Product(s)", ProductListToHtmlTable(shipment, languageId), true)); tokens.Add(new Token("Shipment.URLForCustomer", string.Format("{0}orderdetails/shipment/{1}", _webHelper.GetStoreLocation(false), shipment.Id), true)); //event notification _eventPublisher.EntityTokensAdded(shipment, tokens); }
public ActionResult AddShipment(int orderId, FormCollection form, bool continueEditing) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageOrders)) return AccessDeniedView(); var order = _orderService.GetOrderById(orderId); if (order == null) //No order found with the specified id return RedirectToAction("List"); //a vendor should have access only to his products if (_workContext.CurrentVendor != null && !HasAccessToOrder(order)) return RedirectToAction("List"); var orderProductVariants = order.OrderProductVariants; //a vendor should have access only to his products if (_workContext.CurrentVendor != null) { orderProductVariants = orderProductVariants.Where(opv => HasAccessToOrderProductVariant(opv)).ToList(); } Shipment shipment = null; decimal? totalWeight = null; foreach (var opv in orderProductVariants) { //is shippable if (!opv.ProductVariant.IsShipEnabled) continue; //ensure that this product variant can be shipped (have at least one item to ship) var maxQtyToAdd = opv.GetTotalNumberOfItemsCanBeAddedToShipment(); if (maxQtyToAdd <= 0) continue; int qtyToAdd = 0; //parse quantity foreach (string formKey in form.AllKeys) if (formKey.Equals(string.Format("qtyToAdd{0}", opv.Id), StringComparison.InvariantCultureIgnoreCase)) { int.TryParse(form[formKey], out qtyToAdd); break; } //validate quantity if (qtyToAdd <= 0) continue; if (qtyToAdd > maxQtyToAdd) qtyToAdd = maxQtyToAdd; //ok. we have at least one item. let's create a shipment (if it does not exist) var opvTotalWeight = opv.ItemWeight.HasValue ? opv.ItemWeight * qtyToAdd : null; if (opvTotalWeight.HasValue) { if (!totalWeight.HasValue) totalWeight = 0; totalWeight += opvTotalWeight.Value; } if (shipment == null) { var trackingNumber = form["TrackingNumber"]; shipment = new Shipment() { OrderId = order.Id, TrackingNumber = trackingNumber, TotalWeight = null, ShippedDateUtc = null, DeliveryDateUtc = null, CreatedOnUtc = DateTime.UtcNow, }; } //create a shipment order product variant var sopv = new ShipmentOrderProductVariant() { OrderProductVariantId = opv.Id, Quantity = qtyToAdd, }; shipment.ShipmentOrderProductVariants.Add(sopv); } //if we have at least one item in the shipment, then save it if (shipment != null && shipment.ShipmentOrderProductVariants.Count > 0) { shipment.TotalWeight = totalWeight; _shipmentService.InsertShipment(shipment); SuccessNotification(_localizationService.GetResource("Admin.Orders.Shipments.Added")); return continueEditing ? RedirectToAction("ShipmentDetails", new {id = shipment.Id}) : RedirectToAction("Edit", new { id = orderId }); } else { ErrorNotification(_localizationService.GetResource("Admin.Orders.Shipments.NasroductsSelected")); return RedirectToAction("AddShipment", new { orderId = orderId }); } }
protected ShipmentModel PrepareShipmentModel(Shipment shipment, bool prepareProducts) { //measures var baseWeight = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId); var baseWeightIn = baseWeight != null ? baseWeight.Name : ""; var baseDimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId); var baseDimensionIn = baseDimension != null ? baseDimension.Name : ""; var model = new ShipmentModel() { Id = shipment.Id, OrderId = shipment.OrderId, TrackingNumber = shipment.TrackingNumber, TotalWeight = shipment.TotalWeight.HasValue ? string.Format("{0:F2} [{1}]", shipment.TotalWeight, baseWeightIn) : "", ShippedDate = shipment.ShippedDateUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(shipment.ShippedDateUtc.Value, DateTimeKind.Utc).ToString() : _localizationService.GetResource("Admin.Orders.Shipments.ShippedDate.NotYet"), CanShip = !shipment.ShippedDateUtc.HasValue, DeliveryDate = shipment.DeliveryDateUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(shipment.DeliveryDateUtc.Value, DateTimeKind.Utc).ToString() : _localizationService.GetResource("Admin.Orders.Shipments.DeliveryDate.NotYet"), CanDeliver = shipment.ShippedDateUtc.HasValue && !shipment.DeliveryDateUtc.HasValue, DisplayPdfPackagingSlip = _pdfSettings.Enabled, }; if (prepareProducts) { foreach (var sopv in shipment.ShipmentOrderProductVariants) { var opv = _orderService.GetOrderProductVariantById(sopv.OrderProductVariantId); if (opv == null) continue; //quantities var qtyInThisShipment = sopv.Quantity; var maxQtyToAdd = opv.GetTotalNumberOfItemsCanBeAddedToShipment(); var qtyOrdered = opv.Quantity; var qtyInAllShipments = opv.GetTotalNumberOfItemsInAllShipment(); var sopvModel = new ShipmentModel.ShipmentOrderProductVariantModel() { Id = sopv.Id, OrderProductVariantId = opv.Id, ProductVariantId = opv.ProductVariantId, FullProductName = opv.ProductVariant.FullProductName, Sku = opv.ProductVariant.FormatSku(opv.AttributesXml, _productAttributeParser), AttributeInfo = opv.AttributeDescription, ItemWeight = opv.ItemWeight.HasValue ? string.Format("{0:F2} [{1}]", opv.ItemWeight, baseWeightIn) : "", ItemDimensions = string.Format("{0:F2} x {1:F2} x {2:F2} [{3}]", opv.ProductVariant.Length, opv.ProductVariant.Width, opv.ProductVariant.Height, baseDimensionIn), QuantityOrdered = qtyOrdered, QuantityInThisShipment = qtyInThisShipment, QuantityInAllShipments = qtyInAllShipments, QuantityToAdd = maxQtyToAdd, }; model.Products.Add(sopvModel); } } return model; }
protected bool HasAccessToShipment(Shipment shipment) { if (shipment == null) throw new ArgumentNullException("shipment"); if (_workContext.CurrentVendor == null) //not a vendor; has access return true; var hasVendorProducts = false; var vendorId = _workContext.CurrentVendor.Id; foreach (var sopv in shipment.ShipmentOrderProductVariants) { var opv = _orderService.GetOrderProductVariantById(sopv.OrderProductVariantId); if (opv != null) { if (opv.ProductVariant.Product.VendorId == vendorId) { hasVendorProducts = true; break; } } } return hasVendorProducts; }