派送成本预估逻辑

2020年12月10日 作者 涂世鼎

功能想达到效果: 所有订单的成本能准确计算出来
难点:末端报价千奇百怪,没什么规律
解决思想:分类找报价,先把大部分的地区报价规律化,根据已有的报价方式总结规律
解决方案:分类根据固定格式导入报价,计算报价时根据类型,写死的格式查找
结果:目前基本上涵盖了所有报价方式
缺点:产品经理导入报价不灵活,必须根据后端提供的几种格式导入报价

方案二: 灵活组排,按规则查找报价,导入任意组合

都在图里:

1.目前系统写的查找逻辑

 /**
     * 写死的查找顺序
     * @param logisticsId 派送商id
     * @param keys 参与查找报价的字段 {"GB","LHR","103","N"}
     * @param type 报价类型  1.邮编分区 2.国家邮编分区 3.目的港邮编分区 4.混合分区 其它或0.国家分区
     * @return
     */
    public static List<String> findLogistPriceKeys(String logisticsId,String [] keys,Integer type){
        List<String> returnKeys = new ArrayList<>();
        if(type == 1){
            //邮编找报价
            if (keys[2].length() >= 5) {
                returnKeys.add(logisticsId + keys[2].substring(0, 5));
            }
            returnKeys.add(logisticsId+keys[2].substring(0,3));
        }else if(type ==2){
            //国家+邮编找报价
            if (keys[2].length() >= 5) {
                returnKeys.add(logisticsId + keys[0] + keys[2].substring(0, 5));
            }
            returnKeys.add(logisticsId+keys[0]+keys[2].substring(0,3));
        }else if(type == 3){
            //按目的港+邮编找报价
            if (keys[2].length() >= 5) {
                returnKeys.add(logisticsId + keys[1] + keys[2].substring(0, 5));
            }
            returnKeys.add(logisticsId+keys[1]+keys[2].substring(0,3));

        }else if(type ==4){
            //混合查找
            //1.国家+港口+邮编+是否一票多件找
            if (keys[2].length() >= 5) {
                returnKeys.add(logisticsId + keys[0] + "-" + keys[1] + "-" + keys[2].substring(0, 5) + "-" + keys[3]);
            }
            returnKeys.add(logisticsId + keys[0] + "-" + keys[1] + "-" + keys[2].substring(0, 3) + "-" + keys[3]);
            //2.国家+邮编+是否一票多件找
            if (keys[2].length() >= 5) {
                returnKeys.add(logisticsId + keys[0] + "--" + keys[2].substring(0, 5) + "-" + keys[3]);
            }
            returnKeys.add(logisticsId + keys[0] + "--" + keys[2].substring(0, 3) + "-" + keys[3]);
            //3.国家+是否一票多件找
            returnKeys.add(logisticsId + keys[0] + "---" + keys[3]);

            //4.国家+港口+邮编
            if (keys[2].length() >= 5) {
                returnKeys.add(logisticsId + keys[0] + "-" + keys[1] + "-" + keys[2].substring(0, 5) + "-" );
            }
            returnKeys.add(logisticsId + keys[0] + "-" + keys[1] + "-" + keys[2].substring(0, 3) + "-" );
            //5.国家+邮编
            if (keys[2].length() >= 5) {
                returnKeys.add(logisticsId + keys[0] + "--" + keys[2].substring(0, 5) + "-" );
            }
            returnKeys.add(logisticsId + keys[0] + "--" + keys[2].substring(0, 3) + "-" );
            //6.国家
            returnKeys.add(logisticsId + keys[0] + "---");

        }else{
            //按国家查询
            returnKeys.add(logisticsId+keys[0]);
        }
        return returnKeys;
    }

2.按规律灵活组排(考虑是否要使用)

/**
     * 动态的查找顺序
     * @param ss 参与查找的字段项 {"GB","LHR","103","N"}  {1,2,3,4}
     * @param selected 每个字段项是否必需有 {0,0,0,0}
     * @param postIndex 邮编数组下标
     * @return
     */
    public static List<String> sortKeys(String[] ss,Integer[] selected,int postIndex){
        Set<Map<String,Object>> keyList = new HashSet<>();
        String postCode = ss[postIndex];
        //找出参与查找字段项顺序不变情况下的所有组合
        getArray(keyList,ss,new Integer[ss.length],0,selected,postIndex);

        //按设置好的数字大小排序,规则数组越后面越先查找规则
        List<Map<String, Object>> list = new ArrayList<>(keyList);
        Collections.sort(list, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> u1, Map<String, Object> u2) {
                Double diff =   Double.parseDouble(u2.get("key")+"")-Double.parseDouble(u1.get("key")+"");
                if (diff > 0) {
                    return 1;
                }else if (diff < 0) {
                    return -1;
                }
                return 0; //相等为0
            }
        });
        List<String> keys = new ArrayList<>();
        if(StringUtils.isNotEmpty(postCode) && postCode.length() > 5){
            ss[postIndex] = postCode.substring(0,5);
            keys.add(String.join("-",ss));
        }
        ss[postIndex] = postCode.substring(0,3);
        keys.add(String.join("-", ss));

        for(Map<String,Object> m:list){
            System.out.println(m.get("key"));
            System.out.println(m.get("value"));
            keys.add(String.valueOf(m.get("value")));
        }
        return keys;
    }
    public static void getArray(Set<Map<String,Object>> keyList,String[] ss,Integer[] indexs,Integer n,Integer[] selected,Integer postIndex){
        for(int b =0 ; b < ss.length;b++) {
            indexs[n]=b;
            if(n == (ss.length-1)){
                String[] ss1 = new String[ss.length];
                for (int c = 0; c < ss.length; c++) {
                    ss1[c] = ss[c] + "";
                }
                for (Integer i : indexs) {
                    ss1[i] = "";
                }
                boolean isSelected = true;
                for(int l = 0; l < ss1.length; l++){
                    if(StringUtils.isEmpty(ss1[l]) && selected[l] ==1){
                        isSelected = false;
                        break;
                    }
                }
                double index = 0;
                for (int x = 0; x < ss1.length; x++) {
                    if (StringUtils.isNotEmpty(ss1[x])) {
                        index = index + (x + 1) * Math.pow(10, x);
                    }
                }
                String postCode = ss1[postIndex];
                if(StringUtils.isNotEmpty(postCode) && postCode.length() > 5) {
                    ss1[postIndex] = postCode.substring(0,5);
                    String str1 = String.join("-", ss1);
                    if (!str1.equals("---") && isSelected) {
                        Map<String, Object> m = new HashMap<>();
                        m.put("key", index + 0.1);
                        m.put("value", str1);
                        keyList.add(m);
                    }
                }
                if(StringUtils.isNotEmpty(postCode)) {
                    ss1[postIndex] = postCode.substring(0, 3);
                }
                String str1 = String.join("-", ss1);
                if (!str1.equals("---") && isSelected) {
                    Map<String, Object> m = new HashMap<>();
                    m.put("key", index);
                    m.put("value", str1);
                    keyList.add(m);
                }
            }
            if(n<(ss.length-1)){
                getArray(keyList,ss,indexs,n+1,selected,postIndex);
            }
        }
    }

    public static void main(String[] args) {
        /**
         * 参选项按顺序排,数组下标越大越优先查询
         */
        String[] sss = new String[]{"GB","LHR","123456","N"};
        /**
         * 数组填1 必选
         */
        Integer[] selected = new Integer[]{0,0,0,0};
        List<String> sortList = LogisticsPriceKeyUtil.sortKeys(sss,selected,2);
        System.out.println("排序结果:---------------------");
        for(String sort : sortList) {
            System.out.println(sort);
        }
    }