public async Task free_shipping_for_no_rates()
        {
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 370,
                SupplierID   = "010"
            };
            var method1 = new HSShipMethod
            {
                ID = "NO_SHIPPING_RATES",
                xp = new ShipMethodXP()
            };
            var worksheet = BuildOrderWorksheet(new HSLineItem[] { line1 });
            var estimates = BuildEstimates(new[] { method1 }, new[] { shipItem1 });
            var result    = await estimates.ApplyShippingLogic(worksheet, _oc, FREE_SHIPPING_DAYS);

            var methods = result[0].ShipMethods;

            Assert.AreEqual(1, methods.Count());
            Assert.AreEqual(0, methods[0].Cost);
            Assert.AreEqual(method1.Name, methods[0].Name);
            Assert.IsTrue(methods[0].xp.FreeShippingApplied);
        }
Exemple #2
0
        public async Task <HSLineItem> UpsertLineItem(string orderID, HSLineItem liReq, VerifiedUserContext user)
        {
            // get me product with markedup prices correct currency and the existing line items in parellel
            var productRequest           = _meProductCommand.Get(liReq.ProductID, user);
            var existingLineItemsRequest = ListAllAsync.List((page) => _oc.LineItems.ListAsync <HSLineItem>(OrderDirection.Outgoing, orderID, page: page, pageSize: 100, filters: $"Product.ID={liReq.ProductID}", accessToken: user.AccessToken));
            var orderRequest             = _oc.Orders.GetAsync(OrderDirection.Incoming, orderID);
            var existingLineItems        = await existingLineItemsRequest;
            var product       = await productRequest;
            var li            = new HSLineItem();
            var markedUpPrice = ValidateLineItemUnitCost(orderID, product, existingLineItems, liReq);

            liReq.UnitPrice = await markedUpPrice;
            var order = await orderRequest;

            Require.That(!order.IsSubmitted, new ErrorCode("Invalid Order Status", 400, "Order has already been submitted"));

            liReq.xp.StatusByQuantity = LineItemStatusConstants.EmptyStatuses;
            liReq.xp.StatusByQuantity[LineItemStatus.Open] = liReq.Quantity;

            var preExistingLi = ((List <HSLineItem>)existingLineItems).Find(eli => LineItemsMatch(eli, liReq));

            if (preExistingLi != null)
            {
                li = await _oc.LineItems.SaveAsync <HSLineItem>(OrderDirection.Incoming, orderID, preExistingLi.ID, liReq);
            }
            else
            {
                li = await _oc.LineItems.CreateAsync <HSLineItem>(OrderDirection.Incoming, orderID, liReq);
            }
            await _promotionCommand.AutoApplyPromotions(orderID);

            return(li);
        }
Exemple #3
0
        public static LineItemProductData MapToTemplateProduct(HSLineItem lineItem, LineItemStatusChange lineItemStatusChange, LineItemStatus status)
        {
            decimal lineTotal = 0M;

            if (status == LineItemStatus.ReturnDenied || status == LineItemStatus.CancelDenied && lineItemStatusChange.QuantityRequestedForRefund != lineItemStatusChange.Quantity)
            {
                int     quantityApproved      = lineItemStatusChange.QuantityRequestedForRefund - lineItemStatusChange.Quantity;
                decimal costPerUnitAfterTaxes = (decimal)(lineItemStatusChange.Refund / quantityApproved);
                lineTotal = Math.Round(costPerUnitAfterTaxes * lineItemStatusChange.Quantity, 2);
            }
            else
            {
                lineTotal = lineItemStatusChange.Refund ?? lineItem.LineTotal;
            }
            return(new LineItemProductData
            {
                ProductName = lineItem?.Product?.Name,
                ImageURL = lineItem?.xp?.ImageUrl,
                ProductID = lineItem?.ProductID,
                Quantity = lineItem?.Quantity,
                LineTotal = lineTotal,
                QuantityChanged = lineItemStatusChange?.Quantity,
                MessageToBuyer = lineItemStatusChange.Comment
            });
        }
        public void flatrateshipping_handle_second_tier()
        {
            // set shipping cost to $0 if line item cost is greater than $499.99
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 602,
                SupplierID   = "027"
            };
            var method1 = new HSShipMethod
            {
                Name = "FEDEX_GROUND",
                EstimatedTransitDays = 3,
                Cost = 60,
                xp   = new ShipMethodXP {
                }
            };
            var worksheet = BuildOrderWorksheet(line1);
            var estimates = BuildEstimates(new[] { method1 }, new[] { shipItem1 });
            var result    = ApplyFlatRateShipping(worksheet, estimates, "027", null);
            var methods   = result[0].ShipMethods;

            Assert.AreEqual(1, methods.Count());
            Assert.AreEqual(FLAT_RATE_SECOND_TIER, methods[0].Cost);
            Assert.AreEqual(method1.Name, methods[0].Name);
        }
Exemple #5
0
        public void CalculateAndUpdateLineTotalRefund(IEnumerable <RMALineItem> lineItemsToUpdate, HSOrderWorksheet orderWorksheet, CosmosListPage <RMA> allRMAsOnThisOrder, string supplierID)
        {
            IEnumerable <dynamic> orderWorksheetLines = orderWorksheet.OrderCalculateResponse.xp.TaxResponse.lines;

            foreach (RMALineItem rmaLineItem in lineItemsToUpdate)
            {
                if (!rmaLineItem.RefundableViaCreditCard)
                {
                    HSLineItem lineItemFromOrder = orderWorksheet.LineItems.FirstOrDefault(li => li.ID == rmaLineItem.ID);
                    rmaLineItem.LineTotalRefund = lineItemFromOrder.LineTotal / lineItemFromOrder.Quantity * rmaLineItem.QuantityProcessed;
                }
                else
                {
                    int     quantityToRefund       = rmaLineItem.QuantityProcessed;
                    dynamic orderWorksheetLineItem = orderWorksheetLines.FirstOrDefault(li => li.lineNumber == rmaLineItem.ID);

                    // Exempt products will have an exempt amount instead of a taxable amount.
                    decimal lineItemBaseCost = orderWorksheetLineItem.exemptAmount > 0 ? orderWorksheetLineItem.exemptAmount : orderWorksheetLineItem.taxableAmount;
                    decimal totalRefundIfReturningAllLineItems = (decimal)(lineItemBaseCost + orderWorksheetLineItem.tax);
                    double  taxableAmountPerSingleLineItem     = (double)(lineItemBaseCost / orderWorksheetLineItem.quantity);
                    double  taxPerSingleLineItem         = (double)(orderWorksheetLineItem.tax / orderWorksheetLineItem.quantity);
                    double  singleQuantityLineItemRefund = Math.Round(taxableAmountPerSingleLineItem + taxPerSingleLineItem, 2);
                    decimal expectedLineTotalRefund      = (decimal)singleQuantityLineItemRefund * quantityToRefund;

                    rmaLineItem.LineTotalRefund = ValidateExpectedLineTotalRefund(expectedLineTotalRefund, totalRefundIfReturningAllLineItems, allRMAsOnThisOrder, rmaLineItem, orderWorksheet, supplierID);
                }

                ApplyPercentToDiscount(rmaLineItem);

                rmaLineItem.Status = rmaLineItem.QuantityProcessed == rmaLineItem.QuantityRequested ? RMALineItemStatus.Complete : RMALineItemStatus.PartialQtyComplete;
            }
        }
        public void flatrateshipping_ignore_zerocost()
        {
            // don't transform methods if they are zero cost
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 0,
                SupplierID   = "027"
            };
            var method1 = new HSShipMethod
            {
                Name = "FEDEX_GROUND",
                EstimatedTransitDays = 3,
                Cost = 60,
                xp   = new ShipMethodXP {
                }
            };
            var worksheet = BuildOrderWorksheet(line1);
            var estimates = BuildEstimates(new[] { method1 }, new[] { shipItem1 });
            var result    = ApplyFlatRateShipping(worksheet, estimates, "027", null);
            var methods   = result[0].ShipMethods;

            Assert.AreEqual(1, methods.Count());
            Assert.AreEqual(method1.Cost, methods[0].Cost);
            Assert.AreEqual(method1.Name, methods[0].Name);
        }
        public async Task shipping_ignore_zerocostAsync()
        {
            // don't transform methods if they are zero cost
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 0,
                SupplierID   = "027"
            };
            var method1 = new HSShipMethod
            {
                Name = "FEDEX_GROUND",
                EstimatedTransitDays = 3,
                Cost = 60,
                xp   = new ShipMethodXP {
                }
            };
            var worksheet = BuildOrderWorksheet(new HSLineItem[] { line1 });
            var estimates = BuildEstimates(new[] { method1 }, new[] { shipItem1 });
            var result    = await estimates.ApplyShippingLogic(worksheet, _oc, FREE_SHIPPING_DAYS);

            var methods = result[0].ShipMethods;

            Assert.AreEqual(1, methods.Count());
            Assert.AreEqual(method1.Cost, methods[0].Cost);
            Assert.AreEqual(method1.Name, methods[0].Name);
        }
Exemple #8
0
 public static ZohoLineItem Map(ZohoLineItem zItem, HSLineItem item, Supplier supplier)
 {
     zItem.purchase_description = $"{item.Product.Name ?? item.Variant?.Name} {item.Variant?.xp?.SpecCombo ?? item.SKU()}".Trim();
     zItem.purchase_rate        = item.UnitPrice.HasValue ? Math.Round(decimal.ToDouble(item.UnitPrice.Value), 2) : 0;
     zItem.manufacturer         = supplier.Name;
     return(zItem);
 }
Exemple #9
0
 public static LineItemProductData MapLineItemToProduct(HSLineItem lineItem) =>
 lineItem == null ? null :
 new LineItemProductData()
 {
     ProductName = lineItem?.Product?.Name,
     ImageURL    = lineItem?.xp?.ImageUrl,
     ProductID   = lineItem?.ProductID,
     Quantity    = lineItem?.Quantity,
     LineTotal   = lineItem?.LineTotal,
 };
Exemple #10
0
 public static ZohoLineItem Map(ZohoLineItem zItem, HSLineItem item)
 {
     zItem.item_type            = "sales_and_purchases";
     zItem.name                 = $"{item.Variant?.Name ?? item.Product.Name} {item.Variant?.xp?.SpecCombo ?? item.SKU()}".Trim();
     zItem.description          = $"{item.Variant?.Name ?? item.Product.Name} {item.Variant?.xp?.SpecCombo ?? item.SKU()}".Trim();
     zItem.purchase_description = $"{item.Variant?.Name ?? item.Product.Name} {item.Variant?.xp?.SpecCombo ?? item.SKU()}".Trim();
     zItem.rate                 = item.UnitPrice.HasValue ? Math.Round(decimal.ToDouble(item.UnitPrice.Value), 2) : 0;
     zItem.unit                 = item.Product.xp?.UnitOfMeasure?.Unit;
     zItem.avatax_tax_code      = item.Product.xp?.Tax.Code;
     return(zItem);
 }
Exemple #11
0
 public static LineItemProductData MapToTemplateProduct(HSLineItem lineItem, LineItemStatusChange lineItemStatusChange)
 {
     return(new LineItemProductData
     {
         ProductName = lineItem?.Product?.Name,
         ImageURL = lineItem?.xp?.ImageUrl,
         ProductID = lineItem?.ProductID,
         Quantity = lineItem?.Quantity,
         LineTotal = lineItem?.LineTotal,
         QuantityChanged = lineItemStatusChange?.Quantity
     });
 }
Exemple #12
0
 public static ZohoLineItem Map(HSLineItem item)
 {
     return(new ZohoLineItem()
     {
         item_type = "sales_and_purchases",
         name = $"{item.Variant?.Name ?? item.Product.Name} {item.Variant?.xp?.SpecCombo ?? item.SKU()}".Trim(),
         rate = item.UnitPrice.HasValue ? Math.Round(decimal.ToDouble(item.UnitPrice.Value), 2) : 0,
         quantity = 1,
         description = $"{item.Variant?.Name ?? item.Product.Name} {item.Variant?.xp?.SpecCombo ?? item.SKU()}".Trim(),
         sku = item.SKU(),
         unit = item.Product.xp?.UnitOfMeasure?.Unit,
         avatax_tax_code = item.Product.xp?.Tax.Code
     });
 }
        public void flatrateshipping_multiple_methods_with_nonqualifyingflatrate()
        {
            // If DOESNT qualify for flat rate shipping then dont modify the rates
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var shipItem2 = new ShipEstimateItem
            {
                LineItemID = "Line2"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 250,
                SupplierID   = "027"
            };
            var line2 = new HSLineItem
            {
                ID           = "Line2",
                LineSubtotal = 130,
                SupplierID   = "027"
            };
            var method1 = new HSShipMethod
            {
                Name = "SOMETHING_ELSE",
                EstimatedTransitDays = 3,
                Cost = 60,
                xp   = new ShipMethodXP {
                }
            };
            var method2 = new HSShipMethod
            {
                Name = "PRIORITY_OVERNIGHT",
                EstimatedTransitDays = 1,
                Cost = 120,
                xp   = new ShipMethodXP {
                }
            };
            var worksheet = BuildOrderWorksheet(line1, line2);
            var estimates = BuildEstimates(new[] { method1, method2 }, new[] { shipItem1, shipItem2 });
            var result    = ApplyFlatRateShipping(worksheet, estimates, "027", null);
            var methods   = result[0].ShipMethods;

            Assert.AreEqual(2, methods.Count());
            Assert.AreEqual(method1.Cost, methods[0].Cost);
            Assert.AreEqual(method1.Name, methods[0].Name);
            Assert.AreEqual(method2.Cost, methods[1].Cost);
            Assert.AreEqual(method2.Name, methods[1].Name);
        }
        public void flatrateshipping_multiple_methods_with_qualifyingflatrate()
        {
            // If qualifies for flat rate shipping then the only rate that should be returned is the modified ground option
            // this test ensures the non-ground option is stripped out
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var shipItem2 = new ShipEstimateItem
            {
                LineItemID = "Line2"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 250,
                SupplierID   = "027"
            };
            var line2 = new HSLineItem
            {
                ID           = "Line2",
                LineSubtotal = 130,
                SupplierID   = "027"
            };
            var method1 = new HSShipMethod
            {
                Name = "FEDEX_GROUND",
                EstimatedTransitDays = 3,
                Cost = 60,
                xp   = new ShipMethodXP {
                }
            };
            var method2 = new HSShipMethod
            {
                Name = "PRIORITY_OVERNIGHT",
                EstimatedTransitDays = 1,
                Cost = 120,
                xp   = new ShipMethodXP {
                }
            };
            var worksheet = BuildOrderWorksheet(line1, line2);
            var estimates = BuildEstimates(new[] { method1, method2 }, new[] { shipItem1, shipItem2 });
            var result    = ApplyFlatRateShipping(worksheet, estimates, "027", null);
            var methods   = result[0].ShipMethods;

            Assert.AreEqual(1, methods.Count());
            Assert.AreEqual(FLAT_RATE_FIRST_TIER, methods[0].Cost);
            Assert.AreEqual(method1.Name, methods[0].Name);
        }
Exemple #15
0
        public async Task default_shipping_for_no_rates()
        {
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 370,
                SupplierID   = "010"
            };
            var worksheet = BuildOrderWorksheet(new HSLineItem[] { line1 });
            var estimates = BuildEstimates(new HSShipMethod[] { }, new[] { shipItem1 });
            var result    = await estimates.CheckForEmptyRates(20, 5).ApplyShippingLogic(worksheet, _oc, FREE_SHIPPING_DAYS);

            var methods = result[0].ShipMethods;

            Assert.AreEqual(1, methods.Count());
            Assert.AreEqual(20, methods[0].Cost);
        }
        public void flatrateshipping_handle_first_tier_multiple_lines()
        {
            // set shipping cost to $29.99 if line item cost is between 0.01$ and $499.99
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Line1"
            };
            var shipItem2 = new ShipEstimateItem
            {
                LineItemID = "Line2"
            };
            var line1 = new HSLineItem
            {
                ID           = "Line1",
                LineSubtotal = 200,
                SupplierID   = "027"
            };
            var line2 = new HSLineItem
            {
                ID           = "Line2",
                LineSubtotal = 250,
                SupplierID   = "027"
            };
            var method1 = new HSShipMethod
            {
                Name = "FEDEX_GROUND",
                EstimatedTransitDays = 3,
                Cost = 60,
                xp   = new ShipMethodXP {
                }
            };
            var worksheet = BuildOrderWorksheet(line1, line2);
            var estimates = BuildEstimates(new[] { method1 }, new[] { shipItem1, shipItem2 });
            var result    = ApplyFlatRateShipping(worksheet, estimates, "027", null);
            var methods   = result[0].ShipMethods;

            Assert.AreEqual(1, methods.Count());
            Assert.AreEqual(FLAT_RATE_FIRST_TIER, methods[0].Cost);
            Assert.AreEqual(method1.Name, methods[0].Name);
        }
Exemple #17
0
        private Dictionary <LineItemStatus, int> BuildNewLineItemStatusByQuantity(LineItemStatusChange lineItemStatusChange, HSLineItem existingLineItem, LineItemStatus newLineItemStatus)
        {
            Dictionary <LineItemStatus, int> statusDictionary = existingLineItem.xp.StatusByQuantity;
            var quantitySetting = lineItemStatusChange.Quantity;

            // increment
            statusDictionary[newLineItemStatus] += quantitySetting;


            var validPreviousStates = LineItemStatusConstants.ValidPreviousStateLineItemChangeMap[newLineItemStatus];

            // decrement
            foreach (LineItemStatus status in validPreviousStates)
            {
                if (statusDictionary[status] != 0)
                {
                    if (statusDictionary[status] <= quantitySetting)
                    {
                        quantitySetting         -= statusDictionary[status];
                        statusDictionary[status] = 0;
                    }
                    else
                    {
                        statusDictionary[status] -= quantitySetting;
                        quantitySetting           = 0;
                    }
                }
            }


            return(statusDictionary);
        }
 public async Task <HSLineItem> UpsertLineItem(string orderID, [FromBody] HSLineItem li)
 {
     return(await _lineItemCommand.UpsertLineItem(orderID, li, UserContext));
 }
Exemple #19
0
 public static string SKU(this HSLineItem item)
 {
     return(item.Product == null ? "" : $"{item.Product.ID}-{item.Variant?.ID}".TrimEnd("-"));
 }
Exemple #20
0
        public async Task <decimal> ValidateLineItemUnitCost(string orderID, SuperHSMeProduct product, List <HSLineItem> existingLineItems, HSLineItem li)
        {
            if (product.PriceSchedule.UseCumulativeQuantity)
            {
                int totalQuantity = li?.Quantity ?? 0;
                foreach (HSLineItem lineItem in existingLineItems)
                {
                    if (li == null || !LineItemsMatch(li, lineItem))
                    {
                        totalQuantity += lineItem.Quantity;
                    }
                }
                decimal priceBasedOnQuantity = product.PriceSchedule.PriceBreaks.Last(priceBreak => priceBreak.Quantity <= totalQuantity).Price;
                foreach (HSLineItem lineItem in existingLineItems)
                {
                    // Determine markup for all specs for this existing line item
                    decimal lineItemTotal = priceBasedOnQuantity + GetSpecMarkup(lineItem.Specs, product.Specs);
                    if (lineItem.UnitPrice != lineItemTotal)
                    {
                        PartialLineItem lineItemToPatch = new PartialLineItem();
                        lineItemToPatch.UnitPrice = lineItemTotal;
                        await _oc.LineItems.PatchAsync <HSLineItem>(OrderDirection.Incoming, orderID, lineItem.ID, lineItemToPatch);
                    }
                }

                // Return the item total for the li being added or modified
                return(li == null ? 0 : priceBasedOnQuantity + GetSpecMarkup(li.Specs, product.Specs));
            }
            else
            {
                decimal lineItemTotal = 0;
                if (li != null)
                {
                    // Determine price including quantity price break discount
                    decimal priceBasedOnQuantity = product.PriceSchedule.PriceBreaks.Last(priceBreak => priceBreak.Quantity <= li.Quantity).Price;
                    // Determine markup for the 1 line item
                    lineItemTotal = priceBasedOnQuantity + GetSpecMarkup(li.Specs, product.Specs);
                }
                return(lineItemTotal);
            }
        }
        public void flatrateshipping_handle_multiple_estimates()
        {
            // set shipping cost to $0 if line item cost is greater than $499.99
            var shipItem1 = new ShipEstimateItem
            {
                LineItemID = "Supplier1Line1"
            };
            var shipitem2 = new ShipEstimateItem
            {
                LineItemID = "Supplier2Line1"
            };
            var line1 = new HSLineItem
            {
                ID           = "Supplier1Line1",
                LineSubtotal = 110,
                SupplierID   = "010"
            };
            var line2 = new HSLineItem
            {
                ID           = "Supplier1Line2",
                LineSubtotal = 125,
                SupplierID   = "010"
            };
            var line3 = new HSLineItem
            {
                ID           = "Supplier2Line1",
                LineSubtotal = 130,
                SupplierID   = "027"
            };
            var line4 = new HSLineItem
            {
                ID           = "Supplier2Line2",
                LineSubtotal = 180,
                SupplierID   = "027"
            };
            var method1 = new HSShipMethod
            {
                Name = "FEDEX_GROUND",
                EstimatedTransitDays = 1,
                Cost = 80,
                xp   = new ShipMethodXP {
                }
            };
            var method2 = new HSShipMethod
            {
                Name = "FEDEX_GROUND",
                EstimatedTransitDays = 3,
                Cost = 60,
                xp   = new ShipMethodXP {
                }
            };
            var worksheet = BuildOrderWorksheet(line1, line2, line3, line4);
            var estimates = BuildEstimates(new[] { method1 }, new[] { shipItem1 });

            estimates.AddRange(BuildEstimates(new[] { method2 }, new[] { shipitem2 }));
            var result = ApplyFlatRateShipping(worksheet, estimates, "027", null);

            Assert.AreEqual(2, result.Count());
            // compare first shipment item from first estimate (no changes because its not medline supplier)
            Assert.AreEqual(1, result[0].ShipMethods.Count());
            Assert.AreEqual(method1.Name, result[0].ShipMethods[0].Name);
            Assert.AreEqual(method1.Cost, result[0].ShipMethods[0].Cost);

            // compare first shipment item from second estimate (cost falls in first tier between $0.01 and $499.9)
            Assert.AreEqual(1, result[0].ShipMethods.Count());
            Assert.AreEqual(method2.Name, result[1].ShipMethods[0].Name);
            Assert.AreEqual(29.99M, result[1].ShipMethods[0].Cost);
        }