Ejemplo n.º 1
0
 // 根据拆分规则及商品列表取得可能的Rule列表(排序后的)(商品列表中任一商品都不支持的Rule不返回)
 public List <List <RuleEntity> > GetRuleEntities(SplitPrinciple splitPrinciple, List <ProductEntity> pel)
 {
     return(GetRuleEntities(ruleEntityList, pel));
 }
Ejemplo n.º 2
0
        // TODO(liuxin)(算法升级):把所有可能全返回,外层在此基础上再跑,最终把所有可能全集中到一起判断最优解
        public Tuple <SplitedOrder, List <ProductEntity> > Split(List <ProductEntity> productList, /*int totalQuantity, */ SplitPrinciple splitPrinciple, bool withTax)
        {
            var result = Tuple.Create(new SplitedOrder(), productList);

            if ((productList == null) || (productList.Count <= 0) || splitPrinciple == SplitPrinciple.SpeedFirst)
            {
                // 无单可拆,直接返回
                return(result);
            }

            var productListCount = productList.Count;
            var resultGroups     = getEntities(productList).Select(l => Split(SplitPackage.SplitV1.Common.Common.CloneProductEntityList(productList), l, withTax)).ToList();
            var msgs             = Enumerable.Repeat(string.Format("RuleEntity.Split({0}, {1}, {2}) alternative:", "productList.Count=" + productListCount, "splitPrinciple=" + splitPrinciple, "withTax=" + withTax), 1)
                                   .Concat(resultGroups.Select(ret => string.Format("    ({0}, {1})", ret.Item1, "[" + string.Join(", ", ret.Item2) + "]")));

            LogHelper.Logger.Info(string.Join(Environment.NewLine, msgs));
            var resultGroup = resultGroups.GroupBy(t => t.Item2.Count).OrderBy(g => g.Key).FirstOrDefault();

            if (resultGroup != null)
            {
                switch (splitPrinciple)
                {
                case SplitPrinciple.QuanlityFirst:
                    result = resultGroup.OrderBy(t => t.Item1.OrderList.Count).FirstOrDefault() ?? result;
                    break;

                case SplitPrinciple.PriceFirst:
                case SplitPrinciple.LogisticsFirst:
                default:
                    result = resultGroup.OrderBy(t => t.Item1.CalculateLogisticsCost()).FirstOrDefault() ?? result;
                    break;
                }
            }

            return(result);
        }
Ejemplo n.º 3
0
        private Tuple <SplitedOrder, List <ProductEntity> > SplitOnceWithOrganization(List <ProductEntity> productList, List <RuleEntity> rules, SplitPrinciple splitPrinciple)
        {
            var splitedOrder = new SplitedOrder();

            var restProductList = productList;

            for (int i = 0; i < rules.Count && restProductList.Count > 0; i++)
            {
                var tuple = rules[i].Split(restProductList, splitPrinciple, false);
                splitedOrder.AddSubOrderRange(tuple.Item1);
                restProductList = tuple.Item2;
            }

            return(Tuple.Create(splitedOrder, restProductList));
        }
Ejemplo n.º 4
0
        private Tuple <SplitedOrder, bool, List <ProductEntity> > SplitOnce(List <ProductEntity> productList, List <RuleEntity> rules, SplitPrinciple splitPrinciple)
        {
            var splitedOrder = new SplitedOrder();

            var restProductList = productList;

            for (int i = 0; i < rules.Count && restProductList.Count > 0; i++)
            {
                var tuple = rules[i].Split(restProductList, splitPrinciple, false);
                splitedOrder.AddSubOrderRange(tuple.Item1);
                restProductList = tuple.Item2;
            }

            bool isTax = false;

            if (splitPrinciple != SplitPrinciple.LogisticsFirst && restProductList.Count > 0)
            {
                // 没拆完,按含税方式拆一遍
                //for (int i = 0; i < rules.Count && restProductList.Count > 0; i++)
                //{
                //    var tuple = rules[i].Split(restProductList, splitPrinciple, true);
                //    isTax |= tuple.Item1.OrderList.Count > 0;
                //    splitedOrder.AddSubOrderRange(tuple.Item1);
                //    restProductList = tuple.Item2;
                //}

                //if (restProductList.Count > 0)
                {
                    // 还有剩余就按BC拆
                    isTax = true;
                    //var subOrder = new SubOrder("-1", null, null, null, null, restProductList.SelectMany(pe => pe.OrderInfo).ToList())
                    //{
                    //    LogisticsUnitPrice = decimal.MaxValue,
                    //    LogisticsCost = decimal.MaxValue,
                    //    TaxCost = decimal.MaxValue,
                    //};
                    //splitedOrder.AddSubOrder(subOrder);
                    splitedOrder.AddSubOrderRange(bcRuleEntity.Split(restProductList));
                    restProductList.Clear();
                }
            }
            return(Tuple.Create(splitedOrder, isTax, restProductList));
        }
Ejemplo n.º 5
0
        private SplitedOrder SplitOrder(string orderId, List <ProductEntity> productList, List <Product> badProductList, int totalQuantity, SplitPrinciple splitPrinciple)
        {
            Debug.Assert(splitPrinciple != SplitPrinciple.LogisticsFirst);

            var result = new SplitedOrder();

            List <List <RuleEntity> > ruleOptions = null;

            switch (splitPrinciple)
            {
            case SplitPrinciple.SpeedFirst:
                // BC
                break;

            //case SplitPrinciple.LogisticsFirst:
            case SplitPrinciple.QuanlityFirst:
            case SplitPrinciple.PriceFirst:
            default:
                ruleOptions = splitConfig.GetRuleEntities(splitPrinciple, productList);
                break;
            }

            if (ruleOptions != null && ruleOptions.Count > 0)
            {
                var splitResults = ruleOptions.Select(rules => SplitOnce(SplitPackage.Split.Common.Common.CloneProductEntityList(productList), rules, splitPrinciple)).ToList();
                var msgs         = Enumerable.Repeat(string.Format("Spliter.SplitOrder({0}, {1}, {2}, {3}) alternative:", "orderId=" + orderId, "productList.Count=" + productList.Count, "totalQuantity=" + totalQuantity, "splitPrinciple=" + splitPrinciple), 1)
                                   .Concat(splitResults.Select(ret => string.Format("    ({0}, {1}, {2})", ret.Item1, ret.Item2, "[" + string.Join(", ", ret.Item3) + "]")));
                LogHelper.Logger.Info(string.Join(Environment.NewLine, msgs));
                Tuple <SplitedOrder, bool, List <ProductEntity> > optimal = null;
                switch (splitPrinciple)
                {
                case SplitPrinciple.QuanlityFirst:
                    optimal = splitResults.OrderBy(t => t.Item2 ? 0 : 1)
                              .ThenBy(t => t.Item1.OrderList.Count)
                              .ThenBy(t => t.Item1.CalculateLogisticsAndTaxCost())
                              .FirstOrDefault();
                    break;

                case SplitPrinciple.PriceFirst:
                case SplitPrinciple.LogisticsFirst:
                default:
                    optimal = splitResults.OrderBy(t => t.Item2 ? 0 : 1)
                              .ThenBy(t => t.Item1.CalculateLogisticsAndTaxCost())
                              .ThenBy(t => t.Item1.OrderList.Count)
                              .FirstOrDefault();
                    break;
                }
                result = optimal != null ? optimal.Item1 : result;
            }
            else
            {
                // BC方式,计算跨境综合税
                result = bcRuleEntity.Split(productList);
            }

            if (badProductList != null && badProductList.Any())
            {
                var subOrder = new SubOrder("-2", null, null, null, null, null, badProductList)
                {
                    LogisticsUnitPrice = int.MaxValue,
                    LogisticsCost      = int.MaxValue,
                    TaxCost            = int.MaxValue,
                };
                result.AddSubOrder(subOrder);
            }

            result.OrderId = orderId;
            return(result);
        }
Ejemplo n.º 6
0
        private Tuple <SplitedOrder, bool, List <ProductEntity> > SplitOnce(List <ProductEntity> productList, List <RuleEntity> rules, SplitPrinciple splitPrinciple)
        {
            var splitedOrder    = new SplitedOrder();
            var restProductList = productList;

            for (int i = 0; i < rules.Count && restProductList.Count > 0; i++)
            {
                var tuple = rules[i].Split(restProductList, splitPrinciple, false);
                splitedOrder.AddSubOrderRange(tuple.Item1);
                restProductList = tuple.Item2;
            }
            bool isTax = false;

            if (splitPrinciple != SplitPrinciple.LogisticsFirst && restProductList.Count > 0)
            {
                isTax = true;
                splitedOrder.AddSubOrderRange(this.ReturnRemainPackage(restProductList));
                restProductList.Clear();
            }
            return(Tuple.Create(splitedOrder, isTax, restProductList));
        }
Ejemplo n.º 7
0
        private SplitedOrder SplitOrder(string orderId, List <ProductEntity> productList, List <Product> badProductList, int totalQuantity, SplitPrinciple splitPrinciple)
        {
            Debug.Assert(splitPrinciple != SplitPrinciple.LogisticsFirst);
            var result = new SplitedOrder();
            List <List <RuleEntity> > ruleOptions = null;

            switch (splitPrinciple)
            {
            case SplitPrinciple.SpeedFirst:
                break;

            case SplitPrinciple.QuanlityFirst:
            case SplitPrinciple.PriceFirst:
            default:
                ruleOptions = splitConfig.GetRuleEntities(splitPrinciple, productList);
                break;
            }
            if (ruleOptions != null && ruleOptions.Count > 0)
            {
                var splitResults = ruleOptions.Select(rules => SplitOnce(SplitPackage.SplitV1.Common.Common.CloneProductEntityList(productList), rules, splitPrinciple)).ToList();
                Tuple <SplitedOrder, bool, List <ProductEntity> > optimal = null;
                switch (splitPrinciple)
                {
                case SplitPrinciple.QuanlityFirst:
                    optimal = splitResults.OrderBy(t => t.Item2 ? 0 : 1)
                              .ThenBy(t => t.Item1.OrderList.Count)
                              .ThenBy(t => t.Item1.CalculateLogisticsAndTaxCost())
                              .FirstOrDefault();
                    break;

                case SplitPrinciple.PriceFirst:
                case SplitPrinciple.LogisticsFirst:
                default:
                    optimal = splitResults.OrderBy(t => t.Item2 ? 0 : 1)
                              .ThenBy(t => t.Item1.CalculateLogisticsAndTaxCost())
                              .ThenBy(t => t.Item1.OrderList.Count)
                              .FirstOrDefault();
                    break;
                }
                result = optimal != null ? optimal.Item1 : result;
            }
            else
            {
                // BC方式,计算跨境综合税
                result = this.ReturnRemainPackage(productList);
            }
            if (badProductList != null && badProductList.Any())
            {
                var subOrder = new SubOrder("-2", null, null, null, null, null, badProductList)
                {
                    LogisticsUnitPrice = int.MaxValue,
                    LogisticsCost      = int.MaxValue,
                    TaxCost            = int.MaxValue,
                };
                result.AddSubOrder(subOrder);
            }
            result.OrderId = orderId;
            return(result);
        }