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

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

记录一次主单明细分包解决思路_第1张图片
解决思路草稿.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 map = new HashMap();
        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 strArr = new ArrayList();
            strArr = returnVoucher(map); //第一次取出不超过100的主单凭证号 AA         
            
            Map remMap = new HashMap(); 
            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 returnVoucher(Map map) {
        List strArr = new ArrayList();
        int sum = 0;

        Iterator> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry 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 returnRemoveMap(Map map, List listStr) {

        Iterator> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry 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 remMap) {
        int sum = 0;

        Iterator> it = remMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = it.next();
            sum = sum + Integer.valueOf(entry.getKey()); // key是明细条数
        }
        return sum;
    }
}
记录一次主单明细分包解决思路_第2张图片
模拟Console.png

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

你可能感兴趣的:(记录一次主单明细分包解决思路)