📚目录
- 需求
- 业务解释
- 解决代码
- 效果
需求
按照一定规则将多笔流水的金额分配给多个订单,确保流水总金额和订单总金额一致。
业务解释
之前系统做了个功能,允许对订单进行录错退款,并且重新关联新的订单,审核通过完成后录错的订单自动变为废弃状态,而重新下单的则会变成正常的订单,这个功能的存在就是为了,门店在录订单可能会出现问题导致订单不正确的一种补救方式,但是这会有个问题录错的订单通常是使用二维码进行扫码支付会产生流水数据,这样财务对账的时候可以知道这边流水属于那个订单上的他们就好算工资,所以需要解决重新下单的订单关联上原订单的流水,并且他们重新下的订单总金额需要和原订单的总流水金额要一致,下面就是流水和订单关联的2种关系。
录错退款:允许一拆一,一拆多的模式
所以当一个订单出现多笔流水(图中关系二),然后这个订单还录错退款拆分了多个小订单(图中一对多个订单),那他们之间的金额该如何分配呢?
结果应该是这样的,订单的总金额和总流水需要对的上,至于一个流水的金额可以被才分成若干个小金额的订单,就如bill3流水才分成了三个小金额的订单100,200,200,这些订单相加的金额又等于流水的金额500。然后按照订单上看order7(300)=bill2(100)+bill3(200)
由多个流水中小订单金额相加等于,原订单的总金额。
{"bill2": {"order7": 100},"bill3": {"order5": 100,"order6": 200,"order7": 200}
}
或者可以按照这样分配
{"bill2": {"order5": 100},"bill3": {"order6": 200,"order7": 300}
}
解决代码
public static void main(String[] args) {Map<String, Long> billNoAndAmountMap = new HashMap<>();billNoAndAmountMap.put("billNo1",100L);billNoAndAmountMap.put("billNo2",100L);billNoAndAmountMap.put("billNo3",120L);Map<String, Long> orderAndAmountMap = new HashMap<>();orderAndAmountMap.put("orderNo1",60L);orderAndAmountMap.put("orderNo2",150L);orderAndAmountMap.put("orderNo3",110L);Map<String, Map<String, Long>> allocation = flowAndOrderAmountAllocation(billNoAndAmountMap, orderAndAmountMap);System.out.println("分配完成后的结果:\n"+ JSONUtil.toJsonStr(allocation));}/*** 流水与订单的金额分配** @param billNoAndAmountMap 流水集合* @param orderAndAmountMap 多个订单和金额的Map* @return <billNo,<orderNo,amount>>*/public static Map<String, Map<String, Long>> flowAndOrderAmountAllocation(Map<String, Long> billNoAndAmountMap, Map<String, Long> orderAndAmountMap) {Map<String, Map<String, Long>> result = new TreeMap<>();// 确认传入的总金额可以对应上long billAmountTotal = billNoAndAmountMap.values().stream().mapToLong(Long::valueOf).sum();long orderAmountTotal = orderAndAmountMap.values().stream().mapToLong(Long::valueOf).sum();if (billAmountTotal != orderAmountTotal) {throw new RuntimeException("传参流水与订单的金额累加不一致");}List<String> allocationOrder = new ArrayList<>();long remainingBillAmount = billAmountTotal;for (Map.Entry<String, Long> billEntry : billNoAndAmountMap.entrySet()) {String billNo = billEntry.getKey();long billAmount = billEntry.getValue();Map<String, Long> orderMap = new TreeMap<>();for (Map.Entry<String, Long> orderEntry : orderAndAmountMap.entrySet()) {String orderNo = orderEntry.getKey();if (allocationOrder.contains(orderNo)) {continue;}long orderAmount = orderEntry.getValue();if (orderAmount > billAmount) {long orderSurplusAmount = orderAmount - billAmount;orderAmount = billAmount;orderEntry.setValue(orderSurplusAmount);} else {allocationOrder.add(orderNo);}billAmount -= orderAmount;orderMap.put(orderNo, orderAmount);if (billAmount == 0L) {break;}}result.put(billNo, orderMap);remainingBillAmount -= billAmount;if (remainingBillAmount == 0L) {break;}}return result;}
效果
运行结果
分配完成后的结果:
{"billNo1":{"orderNo3":100},"billNo2":{"orderNo1":60,"orderNo2":30,"orderNo3":10},"billNo3":{"orderNo2":120}}