/// <summary> /// When inventory inbound is created, find the inventory item that needs to be fullfilled /// and fullfil with item from inventory inbound /// </summary> /// <param name="db"></param> /// <param name="obj"></param> internal static void ProcessInventoryInboundCreation(NancyBlackDatabase db, InventoryInbound obj) { // ensures that only one thread will be doing this lock (InventoryAdminModule.LockObject) { db.Transaction(() => { var inboundItems = new List <InventoryItem>(); foreach (var item in obj.Items) { InventoryItem ivitm = new InventoryItem(); ivitm.InboundDate = obj.InboundDate; ivitm.InventoryInboundId = obj.Id; ivitm.ProductId = item.ProductId; ivitm.BuyingCost = item.Price; ivitm.BuyingTax = item.Tax; db.UpsertRecord(ivitm); inboundItems.Add(ivitm); } InventoryAdminModule.InboundCompleted(db, obj, inboundItems); }); } }
static InventoryAdminModule() { NancyBlackDatabase.ObjectUpdated += (db, table, obj) => { if (table == "SaleOrder") { InventoryAdminModule.ProcessSaleOrderUpdate(db, obj); } }; NancyBlackDatabase.ObjectCreated += (db, table, obj) => { if (table == "InventoryInbound") { InventoryAdminModule.ProcessInventoryInboundCreation(db, obj); } }; }
/// <summary> /// When Saleorder is set to waiting for order, generate InventoryItem for each item in the sale order /// TransformInventoryRequest event is called to finalize the list of items. /// </summary> /// <param name="db"></param> /// <param name="saleOrder"></param> internal static void ProcessSaleOrderUpdate(NancyBlackDatabase db, SaleOrder saleOrder, bool replay, DateTime now) { if (replay == false) { now = DateTime.Now; // only do when status is waiting for order if (saleOrder.Status != SaleOrderStatus.WaitingForOrder) { return; } // if previous status is already waiting for order - do nothing if (db.GetOlderVersions(saleOrder).First().Status == SaleOrderStatus.WaitingForOrder) { return; } } var currentSite = AdminModule.ReadSiteSettings(); // NOTE: We can't run it again since it can alter the amount // it is possible that admin may change amount in database //// ensures that all logic of sale order has been ran //saleOrder.UpdateSaleOrder(currentSite, db, false); // ensure that no inventory inbound can be run var totalDiscount = 0M; var items = new List <InventoryItem>(); foreach (var item in saleOrder.ItemsDetail) { if (item.CurrentPrice < 0) // dont take negative prices (coupon) { totalDiscount += item.CurrentPrice * -1; // record the discount continue; } // For each items in sale order, create an inventory item for (int i = 0; i < (int)item.Attributes.Qty; i++) { var ivitm = new InventoryItem() { SaleOrderId = saleOrder.Id, ProductId = item.Id, RequestedDate = now, IsFullfilled = false, SellingPrice = item.CurrentPrice }; items.Add(ivitm); if (item.CurrentPrice != item.Price) { totalDiscount += item.Price - item.CurrentPrice; } } } // distribute discount into items which has actual sell price var discountToDistribute = totalDiscount / items.Where(item => item.SellingPrice > 0).Count(); // discount is too great for some item, add it to the most expensive one if (items.Where(item => discountToDistribute > item.SellingPrice).Count() > 0) { var item = items.OrderByDescending(i => i.SellingPrice).First(); item.SellingPrice -= totalDiscount; if (currentSite.commerce.billing.vattype == "addvat") { item.SellingTax = item.SellingPrice * (100 + (int)currentSite.commerce.billing.vatpercent) / 100; } if (currentSite.commerce.billing.vattype == "includevat") { var priceWithoutTax = item.SellingPrice * 100 / (100 + (int)currentSite.commerce.billing.vatpercent); item.SellingTax = item.SellingPrice - priceWithoutTax; item.SellingPrice = priceWithoutTax; } } else // distribute it to items { foreach (var item in items) { if (item.SellingPrice > 0) { item.SellingPrice -= discountToDistribute; if (currentSite.commerce.billing.vattype == "addvat") { item.SellingTax = item.SellingPrice * (100 + (int)currentSite.commerce.billing.vatpercent) / 100; } if (currentSite.commerce.billing.vattype == "includevat") { var priceWithoutTax = item.SellingPrice * 100 / (100 + (int)currentSite.commerce.billing.vatpercent); item.SellingTax = item.SellingPrice - priceWithoutTax; item.SellingPrice = priceWithoutTax; } } } } InventoryAdminModule.TransformInventoryRequest(db, saleOrder, items); db.Transaction(() => { // before inserting... // if the inventory item for this sale order already fullfilled // it will remain in inventory but sale order removed // we will always create new inventory item for this sale order // and clear out old ones foreach (var item in db.Query <InventoryItem>().Where(ivt => ivt.SaleOrderId == saleOrder.Id).ToList()) { if (item.IsFullfilled) { item.Note = "Sale Order Id was removed because sale order which created this item has status set to WaitingForOrder Again"; item.SaleOrderId = 0; item.IsFullfilled = false; db.UpsertRecord(item); continue; // item already fullfilled, we leave it but remove sale order id } db.DeleteRecord(item); } foreach (var item in items) { db.UpsertRecord(item); } }); }
internal static void ProcessSaleOrderUpdate(NancyBlackDatabase db, SaleOrder saleOrder) { InventoryAdminModule.ProcessSaleOrderUpdate(db, saleOrder, false, DateTime.Now); }