/// <summary> /// Either adds new orderlineitems to an existing order on the invoice or creates a new one /// </summary> /// <param name="orderLineItem"></param> /// <param name="invoice"></param> /// <param name="invoiceAdjustmentResult"></param> internal InvoiceAdjustmentResult AddOrderLineItemsToInvoice(OrderLineItem orderLineItem, IInvoice invoice, InvoiceAdjustmentResult invoiceAdjustmentResult) { try { // We get this fresh, in case there have been orders added in the above method and then we want to add to existing // not create lots of individual orders var allOrders = GetOrdersByInvoiceKey(invoice.Key).ToArray(); // Order Key - Use this for adding products to existing orders var orderToAddTo = FirstEditableOrderOnInvoice(allOrders); // Need to add the order if (orderLineItem != null) { // The list of orders we will update var ordersToUpdate = new List <IOrder>(); // If null we create a new order if (orderToAddTo != null) { // Add the orderlineitems orderToAddTo.Items.Add(orderLineItem); ordersToUpdate.Add(orderToAddTo); } else { // We don't have an open order. So need to create a new one var order = CreateOrder(Core.Constants.OrderStatus.NotFulfilled, invoice.Key); order.OrderNumberPrefix = invoice.InvoiceNumberPrefix; order.Items.Add(orderLineItem); // Add the new order to the invoice ordersToUpdate.Add(order); } // Finally Save the orders Save(ordersToUpdate); } invoiceAdjustmentResult.Success = true; } catch (Exception ex) { MultiLogHelper.Error <OrderService>("Failed to adjust invoice", ex); invoiceAdjustmentResult.Success = false; invoiceAdjustmentResult.Message = ex.Message; } return(invoiceAdjustmentResult); }
/// <summary> /// Either adds new orderlineitems to an existing order on the invoice or creates a new one /// </summary> /// <param name="orderLineItems"></param> /// <param name="invoice"></param> /// <param name="invoiceAdjustmentResult"></param> /// <returns></returns> internal InvoiceAdjustmentResult AddOrderLineItemsToInvoice(List <OrderLineItem> orderLineItems, IInvoice invoice, InvoiceAdjustmentResult invoiceAdjustmentResult) { foreach (var orderLineItem in orderLineItems) { invoiceAdjustmentResult = AddOrderLineItemsToInvoice(orderLineItem, invoice, invoiceAdjustmentResult); if (!invoiceAdjustmentResult.Success) { return(invoiceAdjustmentResult); } } invoiceAdjustmentResult.Success = true; return(invoiceAdjustmentResult); }
/// <summary> /// Internal method to add products and orders to existing invoice /// </summary> /// <param name="invoiceOrderShipment"></param> /// <param name="invoiceAddItems"></param> /// <param name="invoiceAdjustmentResult"></param> public virtual InvoiceAdjustmentResult AddNewLineItemsToInvoice(InvoiceOrderShipment invoiceOrderShipment, IEnumerable <InvoiceAddItem> invoiceAddItems, InvoiceAdjustmentResult invoiceAdjustmentResult) { if (invoiceAdjustmentResult.InvoiceLineItemType == InvoiceLineItemType.Product) { // Get the current items in a dictionary so we can quickly check the SKU var currentLineItemsDict = invoiceOrderShipment.Invoice.Items.ToDictionary(x => x.Sku, x => x); // Store the orderlineitems var orderLineItems = new List <OrderLineItem>(); // Loop and add the new products as InvoiceLineItemDisplay to the InvoiceDisplay foreach (var invoiceAddItem in invoiceAddItems) { // If both null, just skip below if (invoiceAddItem.ProductVariant == null && invoiceAddItem.Product == null) { continue; } // Get the sku to check var sku = invoiceAddItem.Product == null ? invoiceAddItem.ProductVariant.Sku : invoiceAddItem.Product.Sku; // Product Pricing Enabled var productPricingEnabled = MerchelloContext.Gateways.Taxation.ProductPricingEnabled; // Create the lineitem var invoiceLineItem = invoiceAddItem.Product == null ? invoiceAddItem.ProductVariant.ToInvoiceLineItem(invoiceAddItem.Quantity, productPricingEnabled) : invoiceAddItem.Product.ToInvoiceLineItem(invoiceAddItem.Quantity, productPricingEnabled); // See if the current line items have this product/variant if (!currentLineItemsDict.ContainsKey(sku)) { invoiceOrderShipment.Invoice.Items.Add(invoiceLineItem); } else { // Already exists, just update qty // Update Quantities foreach (var currentLineItem in invoiceOrderShipment.Invoice.Items) { if (currentLineItem.Sku == sku) { // Update qty by one, as when adding they can only add one product at a time currentLineItem.Quantity++; // Break out of loop break; } } } if (invoiceOrderShipment.HasOrders && invoiceLineItem.IsShippable()) { // Add to Order orderLineItems.Add(invoiceLineItem.AsLineItemOf <OrderLineItem>()); } } // Need to add the order if (invoiceOrderShipment.HasOrders) { // Add to order or create a new one invoiceAdjustmentResult = ((OrderService)_orderService).AddOrderLineItemsToInvoice(orderLineItems, invoiceOrderShipment.Invoice, invoiceAdjustmentResult); if (!invoiceAdjustmentResult.Success) { // Just return if there is an error, don't save anything return(invoiceAdjustmentResult); } } // Now update invoice and save ((InvoiceService)_invoiceService).ReSyncInvoiceTotal(invoiceOrderShipment.Invoice, true); invoiceAdjustmentResult.Success = true; } else { invoiceAdjustmentResult.Success = false; invoiceAdjustmentResult.Message = "Only products can be added"; } return(invoiceAdjustmentResult); }
/// <summary> /// Delete products from an existing invoice /// </summary> /// <param name="invoiceOrderShipment"></param> /// <param name="invoiceAddItems"></param> /// <param name="invoiceAdjustmentResult"></param> public virtual InvoiceAdjustmentResult DeleteLineItemsFromInvoice(InvoiceOrderShipment invoiceOrderShipment, IEnumerable <InvoiceAddItem> invoiceAddItems, InvoiceAdjustmentResult invoiceAdjustmentResult) { // Get the items to be deleted in a dictionary by SKU too var skusToBeDeleted = invoiceAddItems.Where(x => x.Quantity <= 0).Select(x => x.OriginalSku); // Now get the correct items var toBeDeleted = invoiceOrderShipment.LineItems.Where(x => skusToBeDeleted.Contains(x.Sku)).ToArray(); // Can we delete var canDelete = true; // Check if we have an order if (invoiceAdjustmentResult.InvoiceLineItemType == InvoiceLineItemType.Product) { // Order needs saving var saveOrder = false; foreach (var lineItem in toBeDeleted) { if (lineItem.HasShipment) { // Cannot delete as this lineitem is in a shipment canDelete = false; } else { if (invoiceOrderShipment.HasOrders) { var order = invoiceOrderShipment.Orders.FirstOrDefault(x => x.Key == lineItem.OrderId); if (order != null) { // Remove this orderline item invoiceOrderShipment.Orders.FirstOrDefault(x => x.Key == lineItem.OrderId).Items.RemoveItem(lineItem.Sku); // Save the order saveOrder = true; } } // Remove invoice line item too invoiceOrderShipment.Invoice.Items.RemoveItem(lineItem.Sku); } // Found a product we can't delete so break if (canDelete == false) { break; } // Finally Save the order? if (saveOrder) { foreach (var order in invoiceOrderShipment.Orders.Where(x => x.Key == lineItem.OrderId)) { _orderService.Save(order); } saveOrder = false; } } } // If we can delete then do it. if (canDelete) { // Now update invoice and save as well as doing the tax ((InvoiceService)_invoiceService).ReSyncInvoiceTotal(invoiceOrderShipment.Invoice, true); // Set to true invoiceAdjustmentResult.Success = true; } else { const string message = "Unable to delete product because there is already an order that has a shipment with one of the products to be deleted. Either delete the shipment or use adjustments to reduce invoice."; MultiLogHelper.Warn <InvoiceApiController>(message); invoiceAdjustmentResult.Success = false; invoiceAdjustmentResult.Message = message; } return(invoiceAdjustmentResult); }
/// <summary> /// Updates a line item details /// </summary> /// <param name="invoiceOrderShipment"></param> /// <param name="invoiceAddItems"></param> /// <param name="invoiceAdjustmentResult"></param> /// <returns></returns> public virtual InvoiceAdjustmentResult UpdateCustomProductsOnInvoice(InvoiceOrderShipment invoiceOrderShipment, IEnumerable <InvoiceAddItem> invoiceAddItems, InvoiceAdjustmentResult invoiceAdjustmentResult) { var addItems = invoiceAddItems.ToArray(); // Get SKU's that need updating var skusToEdit = addItems.Where(x => x.NeedsUpdating).Select(x => x.OriginalSku); // Get the invoiceordershipmentlineitems var lineItems = invoiceOrderShipment.LineItems.Where(x => skusToEdit.Contains(x.Sku)); // Loops the items to be updated foreach (var iosLineItem in lineItems) { if (iosLineItem.HasShipment) { invoiceAdjustmentResult.Message = string.Format("Unable to update, as {0} is in a shipment.", iosLineItem.Name); invoiceAdjustmentResult.Success = false; return(invoiceAdjustmentResult); } } foreach (var invoiceAddItem in addItems) { // If we get here we're good to update // Do the order foreach (var order in invoiceOrderShipment.Orders) { foreach (var orderItem in order.Items) { if (orderItem.Sku == invoiceAddItem.OriginalSku) { orderItem.Sku = invoiceAddItem.OriginalSku; orderItem.Name = invoiceAddItem.OriginalName; orderItem.Quantity = invoiceAddItem.Quantity; orderItem.Price = invoiceAddItem.OriginalPrice; break; } } } // Do the invoice foreach (var invoiceItem in invoiceOrderShipment.Invoice.Items) { if (invoiceItem.Sku == invoiceAddItem.OriginalSku) { invoiceItem.Sku = invoiceAddItem.OriginalSku; invoiceItem.Name = invoiceAddItem.OriginalName; invoiceItem.Quantity = invoiceAddItem.Quantity; invoiceItem.Price = invoiceAddItem.OriginalPrice; break; } } } // If we get here we can update foreach (var order in invoiceOrderShipment.Orders) { _orderService.Save(order); } // Now update invoice and save as well as doing the tax ((InvoiceService)_invoiceService).ReSyncInvoiceTotal(invoiceOrderShipment.Invoice, true); // Set to true invoiceAdjustmentResult.Success = true; return(invoiceAdjustmentResult); }
public virtual HttpResponseMessage PutInvoiceNewProducts(InvoiceAddItems invoiceAddItems) { var response = Request.CreateResponse(HttpStatusCode.OK); try { if (invoiceAddItems.Items != null) { // Get the invoice and associated data var invoiceOrderShipment = _invoiceService.GetInvoiceOrderShipment(invoiceAddItems.InvoiceKey); if (invoiceOrderShipment.Invoice != null) { //var currentUser = Umbraco.UmbracoContext.Security.CurrentUser; var invoiceAdjustmentResult = new InvoiceAdjustmentResult(invoiceAddItems.LineItemType); // The adjustment type var invoiceAdjustmentType = SetInvoiceAdjustmentType(invoiceAddItems, invoiceOrderShipment); //// Use the merchello helper to get the prdoucts, so the data modifiers are triggered. var merchelloHelper = new MerchelloHelper(); // Get the product service var productService = merchelloHelper.Query.Product; // See if we can get the products foreach (var invoiceAddItem in invoiceAddItems.Items) { if (invoiceAddItems.IsAddProduct && invoiceAddItem.Key != Guid.Empty) { invoiceAddItem.ProductVariant = productService.GetProductVariantByKey(invoiceAddItem.Key); invoiceAddItem.Product = productService.GetByKey(invoiceAddItem.Key); // Complete the Sku too invoiceAddItem.Sku = invoiceAddItem.Product != null ? invoiceAddItem.Product.Sku : invoiceAddItem.ProductVariant.Sku; } else if (!string.IsNullOrWhiteSpace(invoiceAddItem.Sku)) { invoiceAddItem.ProductVariant = productService.GetProductVariantBySku(invoiceAddItem.Sku); invoiceAddItem.Product = productService.GetBySku(invoiceAddItem.Sku); } } // Work out the type of adjustment switch (invoiceAdjustmentType) { case InvoiceAdjustmentType.AddProducts: invoiceAdjustmentResult = AddNewLineItemsToInvoice(invoiceOrderShipment, invoiceAddItems.Items, invoiceAdjustmentResult); break; case InvoiceAdjustmentType.DeleteProduct: invoiceAdjustmentResult = DeleteLineItemsFromInvoice(invoiceOrderShipment, invoiceAddItems.Items, invoiceAdjustmentResult); break; case InvoiceAdjustmentType.UpdateProductDetails: invoiceAdjustmentResult = UpdateCustomProductsOnInvoice(invoiceOrderShipment, invoiceAddItems.Items, invoiceAdjustmentResult); break; } if (!invoiceAdjustmentResult.Success) { response = Request.CreateResponse(HttpStatusCode.Conflict, invoiceAdjustmentResult.Message); MultiLogHelper.Warn <InvoiceApiController>(invoiceAdjustmentResult.Message); } } else { response = Request.CreateResponse(HttpStatusCode.NotFound, "Invoice not found"); } } else { response = Request.CreateResponse(HttpStatusCode.NotFound, "No items to update"); } } catch (Exception ex) { MultiLogHelper.Error <InvoiceApiController>("Failed to adjust invoice", ex); response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); } return(response); }