/// <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> /// 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); }
/// <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> /// Sets the adjustment type /// </summary> /// <param name="invoiceAddItems"></param> /// <param name="invoiceOrderShipment"></param> /// <returns></returns> public virtual InvoiceAdjustmentType SetInvoiceAdjustmentType(InvoiceAddItems invoiceAddItems, InvoiceOrderShipment invoiceOrderShipment) { if (invoiceOrderShipment.Invoice != null) { // If there is more than one item it's adding products if (invoiceAddItems.IsAddProduct) { return(InvoiceAdjustmentType.AddProducts); } // If there are any with 0 for qty it's a delete if (invoiceAddItems.Items.Any(x => x.Quantity <= 0)) { return(InvoiceAdjustmentType.DeleteProduct); } // Lastly see if any updates if (invoiceAddItems.Items.Any(x => x.NeedsUpdating)) { return(InvoiceAdjustmentType.UpdateProductDetails); } } // Default type which is ignored return(InvoiceAdjustmentType.General); }