×

通过JS实现对预付款进行核销

hqy hqy 发表于2025-12-03 00:11:00 浏览16 评论0

抢沙发发表评论

“核销”(verification 或 deduction)通常指将预付款(prepay)金额按 FIFO(First In First Out,先入先出)原则分配到订单产品(prolist)中,即从预付款单按 amount 升序(从小到大)排序后,逐个扣减订单产品的 amount,直到一方金额耗尽。

假如我们现在有个需求:
通过预付款单核销订单产品,按 amount 从小到大排序去核销预付款。
















// 预付款const prepays = [  { id: 101, amount: 2000 },  { id: 102, amount: 500 },  { id: 103, amount: 800 },  { id: 104, amount: 300 }];
// 订单产品const prolist = [  { id: 201, amount: 1500 },  { id: 202, amount: 1000 },  { id: 203, amount: 80 },  { id: 204, amount: 1300 }];


图片

实现代码

图片




































// 1. 按 amount 从小到大排序预付款const sortedPrepays = [...prepays].sort((a, b) => a.amount - b.amount);// 2. 深拷贝订单数组(避免修改原数据)const orders = prolist.map(item => ({ ...item }));// 3. 核销明细记录const details = [];// 4. 核销逻辑:双指针方式let prepayIndex = 0; // 当前处理的预付款索引for (let i = 0; i < orders.length && prepayIndex < sortedPrepays.length; ) {  const order = orders[i];  const prepay = sortedPrepays[prepayIndex];  // 本次可核销金额 = min(订单剩余, 预付款剩余)  const deduct = Math.min(order.amount, prepay.amount);  // 记录核销明细  details.push({    prepayId: prepay.id,    proId: order.id,    deducted: deduct  });  // 扣减  order.amount -= deduct;  sortedPrepays[prepayIndex].amount -= deduct;  // 判断是否用完  if (order.amount === 0) {    i++; // 订单核销完,进入下一个订单  }  if (sortedPrepays[prepayIndex].amount === 0) {    prepayIndex++; // 预付款用完,进入下一笔  }}// 5. 输出结果console.log("核销明细:", details);console.log("剩余预付款:", sortedPrepays.filter(p => p.amount > 0));console.log("剩余订单:", orders.filter(o => o.amount > 0));













// 输出结果核销明细: [  { prepayId: 104, proId: 201, deducted: 300 },  { prepayId: 102, proId: 201, deducted: 500 },  { prepayId: 103, proId: 201, deducted: 700 },  { prepayId: 103, proId: 202, deducted: 100 },  { prepayId: 101, proId: 202, deducted: 900 },  { prepayId: 101, proId: 203, deducted: 80 },  { prepayId: 101, proId: 204, deducted: 920 }]剩余预付款: []剩余订单: [ { id: 204, amount: 380 } ]


图片


图片


封装成函数(可复用)


























function verifyByPrepayAsc(prepays, prolist) {  const sortedPrepays = [...prepays].sort((a, b) => a.amount - b.amount);  const orders = prolist.map(p => ({ ...p }));  const details = [];  let pi = 0;  for (let i = 0; i < orders.length && pi < sortedPrepays.length; ) {    const deduct = Math.min(orders[i].amount, sortedPrepays[pi].amount);    details.push({      prepayId: sortedPrepays[pi].id,      proId: orders[i].id,      deducted: deduct    });    orders[i].amount -= deduct;    sortedPrepays[pi].amount -= deduct;    if (orders[i].amount === 0) i++;    if (sortedPrepays[pi].amount === 0) pi++;  }  return {    details,    remainingPrepays: sortedPrepays.filter(p => p.amount > 0),    remainingOrders: orders.filter(o => o.amount > 0)  };}// 使用const result = verifyByPrepayAsc(prepays, prolist);console.log(result);
总结:使用 sort + 双指针循环即可实现 按预付款金额从小到大核销,逻辑清晰,适合前端或 Node.js 环境。


打赏

本文链接:https://www.jingber.cn/post/3852.html 转载需授权!

分享到:

群贤毕至

访客

您的IP地址是: