美文网首页Java基础
记录一次主单明细分包解决思路

记录一次主单明细分包解决思路

作者: 莫问以 | 来源:发表于2019-06-26 15:45 被阅读2次

    项目背景:建行收到财政发来的公务卡垫款xml报文存库,报文格式分主单和明细,主单不包含收款账号,明细单包含收款账号,即一个主单包含多个明细(明细确定不超过500,但具体多少,未知)!建行公务卡支付需按照明细支付,支付完成以后,需按主单生成清算单到人行做清算,也是主单+明细的情况,但是明细单有一个要求,不能超过500,超过500必须分包,而且必须保证一个主单的明细单必须在一个清算单中,不能存在一个主单对应的明细单在两个清算单中,而且必须保证清算单最少(不能10个公务卡,生成10张清算单)。

    解决思路草稿.png

    比如说主单A包含450条明细单,主单B包含300条明细单,主单C包含200条明细单,那么这种情况就只能生成3张清算单,如果主单D包含10条明细单,那么也只能生成3张清算单,虽然人行清算也是按照明细单做清算,但是为了三方对账方便(主要还是财政),建行规则必须按照这种业务逻辑生成!

    所以依据草稿(解决思路),理了一下业务逻辑:

    1、取出Map<明细条数,公务卡主单凭证号>
    2、求Map明细条数的Sum
    3、明细合计<499,则生成一个清算单,>499考虑递归,最终合计小于499为出口
    

    模拟业务逻辑,代码如下:

    package xf;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public class Person {
        public static void main(String[] args) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("79", "主单凭证号1"); // 1111
            map.put("68", "主单凭证号2");
            map.put("57", "主单凭证号3");
            map.put("46", "主单凭证号4");
            map.put("35", "主单凭证号5");
            map.put("24", "主单凭证号6");
            map.put("12", "主单凭证号7"); // 1111
            map.put("1", "主单凭证号8"); // 1111
    
            int count = SumList(map);
            System.out.println("合计条数========" + count);
    
            if (count < 100) {
                System.out.println("就一笔清算单");
            }
            if (count > 100) {
                System.out.println("清算明细单超过100======================================");
                
                List<String> strArr = new ArrayList<String>();
                strArr = returnVoucher(map); //第一次取出不超过100的主单凭证号 AA         
                
                Map<String, String> remMap = new HashMap<String, String>(); 
                remMap = returnRemoveMap(map, strArr); //第一次剔除AA
                
                // 统计remMap明细条数
                int sum = SumList(remMap);
                
                boolean turn = true;
                int n = 0;
                int m = 0;
                
                while (turn) {
                    if (sum < 100) {
                        // 直接生成最后一笔清算
                        System.err.println("我是最后一笔清算 我是出口 递归函数出口!");
                        strArr = returnVoucher(remMap); //剩下的
                        for (String str : strArr) {
                            System.err.println("最后剩下的凭证号==" + str);
                        }
                        turn = false;
                        break; // 出口
                    }
                    if (sum > 100) {
                        // 循环
                        n++;
                        m++;
                        System.err.println("生成第" + n + "笔清算!"); //此时的strArr刚好是第一次取出来的
                        remMap = returnRemoveMap(remMap, strArr); // 在剔除
                        System.out.println("第" + m + "次剔除!");
                            
                        sum = SumList(remMap); // 判断条数
                        System.out.println("统计明细条数===" + sum);
                        
                        strArr = returnVoucher(remMap);
                    }
                }
            }
        }
    
        // 取出明细合计小于499的任意主单
        public static List<String> returnVoucher(Map<String, String> map) {
            List<String> strArr = new ArrayList<String>();
            int sum = 0;
    
            Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                sum = sum + Integer.valueOf(entry.getKey()); // key是明细条数
                if (sum < 100) {
                    strArr.add(entry.getValue());
                    // System.out.println("key= " + entry.getKey() + " and value= "
                    // + entry.getValue());
                } else {
                    break;
                }
            }
    
            return strArr;
        }
    
        // 剔除list 返回剩余Map
        public static Map<String, String> returnRemoveMap(Map<String, String> map, List<String> listStr) {
    
            Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                for (String str : listStr) {
                    if (str.equals(entry.getValue())) {
                        // map.remove(entry.getKey()); //map移除元素必须用迭代器
                        it.remove();
                    }
                }
            }
    
            return map;
        }
     
    //统计明细条数的sum
        public static Integer SumList(Map<String, String> remMap) {
            int sum = 0;
    
            Iterator<Map.Entry<String, String>> it = remMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                sum = sum + Integer.valueOf(entry.getKey()); // key是明细条数
            }
            return sum;
        }
    }
    
    模拟Console.png

    main函数汇总的map,模拟数据库中取出的Map,该业务逻辑需要注意的是,并非合计数除以500的结果+1就是最少清算单条数,这个就是该业务最大难点,比方说:
    主单A包含450条明细单
    主单B包含300条明细单
    主单C包含200条明细单
    主单D包含100条明细单
    主单E包含350条明细单
    虽然明细合计为1400,但是必须生成4张清算单,这是必须要注意到的地方!

    相关文章

      网友评论

        本文标题:记录一次主单明细分包解决思路

        本文链接:https://www.haomeiwen.com/subject/gzvqcctx.html