文章目录
- 案例数据
- 实现思路
- 1、计算出平均金额
- 2、计算每个商品的金额
- 实现方案
- 1、订单 order 实体
- 2、订单明细 orderDetail 实体
- 3、实现类
- 4、测试启动
- 5、实现结果
在做电商项目的时候,会遇到要对订单明细进行纳税金额拆分,即将税额拆分到每个商品上,明确商品的税额,本文记录实现方案,方便备查。
案例数据
本案例模拟的相关数据
订单金额为100元【10000分】,税率为5%,即税额为5元【500分】
订单总金额【含税】 payAmount | 订单税额 rateAmount |
---|---|
100 | 3 |
商品数量,总数量为8个,包含3个商品,下表是各商品的数量。
商品信息 | 个数 |
---|---|
总数量 | 8 |
商品1 | 4 |
商品2 | 3 |
商品3 | 1 |
实现思路
1、计算出平均金额
即商品平均金额,税额平均金额,注意要向下取整,保证最后的金额不为负数。
类型 | 金额 |
---|---|
商品平均金额【订单金额/商品数量】 | 10000/8=1250 |
税额平均金额【税额/商品数量】 | 500/8=62 |
2、计算每个商品的金额
分为两种计算方式,
前n-1个商品计算方式:即计算每个商品的金额,税额,不含税金额,公式为 上一步计算的各项平均数,乘于商品数量,如商品1如下表所示。
类型 | 金额 |
---|---|
商品1金额【平均订单金额*商品数量】 | 1250*4=5000 |
商品1税额【税额平均金额*商品数量】 | 62*4=248 |
第n个商品计算方式:总的金额 减去 前n-1个商品累计的金额。
实现方案
1、订单 order 实体
order 实体,订单级别的字段,包含商品总数,支付总金额等
import java.io.Serializable;
import java.util.List;
@Data
public class Order implements Serializable{/*** 序列号*/private static final long serialVersionUID = 6652550451095312169L;/*** 订单号*/private String orderNo;/*** 支付金额*/private Long payAmount;/*** 税额*/private Long rateAmount;/*** 商品数量*/private Long skuNum;/*** 非含税金额*/private Long taxtedAmount;/*** 明细集合*/private List<OrderDetail> orderDetailList;
}
2、订单明细 orderDetail 实体
orderDetail 实体,订单明细级别的字段,包含商品明细,商品名称,商品数量等
import java.io.Serializable;
@Data
public class OrderDetail implements Serializable{/*** 序列号*/private static final long serialVersionUID = 7157867993602926767L;/*** 订单号*/private String orderNo;/*** 明细ID*/private String detailId;/*** 商品名称*/private String skuName;/*** 支付金额*/private Long payAmount;/*** 税额*/private Long rateAmount;/*** 非含税金额*/private Long taxtedAmount;/*** 商品数量*/private Long skuNum;
}
3、实现类
定义主体方法,实现税额和不含税金额的拆分
static List<OrderDetail> SplitOrderDetailTest(Order order) {System.out.println("进入拆分SplitOrderDetail方法,入参order为:" + order);List<OrderDetail> detailList = order.getOrderDetailList();// 商品金额long amount = order.getPayAmount();// 税额long rateAmount = order.getRateAmount();// 明细数量long skuNum = order.getSkuNum();// 平均商品成本金额,向下取整long aveAmount = (long) Math.floor(amount / skuNum);// 平均商品税额金额,向下取整long aveRateAmount = (long) Math.floor(rateAmount / skuNum);// 平均商品不含税金额【平均商品金额-平均商品税额金额】long aveNoRateAmount = aveAmount - aveRateAmount;System.out.println("计算完毕的rateAmount为:" + rateAmount + ",amount为:" + amount + ",skuNum为:" + skuNum + ",aveAmount为"+ aveAmount + ",aveRateAmount为:" + aveRateAmount + ",aveNoRateAmount为:" + aveNoRateAmount);// 累计拆分完 金额long detailSumAmount = 0l;// 累计拆分完 税额long rateSumAmount = 0l;// 累计拆分完 不含税金额long taxedSumAmount = 0l;System.out.println("当前detailList.size()为:" + detailList.size());for (int i=0; i < detailList.size()-1;i++) {System.out.println("当前遍历的detail为:" + JSON.toJSONString(detailList.get(i)));OrderDetail orderFinallyDetail = new OrderDetail();BeanUtils.copyProperties(detailList.get(i),orderFinallyDetail);if ( i < detailList.size()-1) {System.out.println("进入循环内:" + JSON.toJSONString(i));// 拆分完 金额【平均金额*商品数量】long detailAmount = aveAmount * detailList.get(i).getSkuNum();detailSumAmount = detailSumAmount + detailAmount;System.out.println("计算拆分完的金额detailAmount为:" + detailAmount + ",detailSumAmount为" + detailSumAmount);// 拆分完 税额【平均税额*商品数量】long rateDetailAmount = aveRateAmount * detailList.get(i).getSkuNum();rateSumAmount = rateSumAmount + rateDetailAmount;System.out.println("计算税额的rateDetailAmount为:" + rateDetailAmount + ",rateSumAmount为" + rateSumAmount);orderFinallyDetail.setRateAmount(rateDetailAmount);// 不含税金额【本成本拆分完金额 - 本成本拆分完税额】long taxedAmount = detailAmount - rateDetailAmount;taxedSumAmount = taxedSumAmount + taxedAmount;System.out.println("计算不含税税额的taxedAmount为:" + taxedAmount + ",taxedSumAmount为" + taxedSumAmount);orderFinallyDetail.setTaxtedAmount(taxedAmount);}// list末位采用倒挤方式取值else {// 末位税额【总税额-累计扣除的税额】long taxAmount = rateAmount - rateSumAmount;System.out.println("计算末位倒挤税额的taxAmount为:" + taxAmount);orderFinallyDetail.setRateAmount(taxAmount);// 末位不含税金额【(总金额-税额)-累计扣除的不含税金额】long taxedAmount = (amount - rateAmount) - taxedSumAmount;System.out.println("计算末位倒挤不含税税额的taxedAmount为:" + taxedAmount);orderFinallyDetail.setTaxtedAmount(taxedAmount);}System.out.println("保存的orderFinallyDetail的信息为:" + JSON.toJSONString(orderFinallyDetail));detailList.add(orderFinallyDetail);}return detailList;}
4、测试启动
模拟数据,调用方法
public static void main(String[] args) {Order order = new Order();order.setOrderNo("12345678");order.setSkuNum(8L);order.setPayAmount(10000L);order.setRateAmount(500L);List<OrderDetail> detailList = new ArrayList<>();// 商品1OrderDetail detailOne = new OrderDetail();detailOne.setDetailId("1111");detailOne.setOrderNo("12345678");detailOne.setSkuNum(4L);detailOne.setSkuName("商品1");detailList.add(detailOne);// 商品2OrderDetail detailTwo = new OrderDetail();detailTwo.setDetailId("2222");detailTwo.setOrderNo("12345678");detailTwo.setSkuNum(3L);detailTwo.setSkuName("商品2");detailList.add(detailTwo);// 商品3OrderDetail detailThree = new OrderDetail();detailThree.setDetailId("3333");detailThree.setOrderNo("12345678");detailThree.setSkuNum(1L);detailThree.setSkuName("商品3");detailList.add(detailThree);System.out.println("构造的detailList的信息为:" + JSON.toJSONString(detailList));order.setOrderDetailList(detailList);List<OrderDetail> detailFinallyList = SplitOrderDetailTest(order);System.out.println("拆分完的detailFinallyList明细信息为:" + JSON.toJSONString(detailFinallyList));}
5、实现结果
拆分结果如下所示。
{"detailId":"1111","orderNo":"12345678","rateAmount":248,"skuName":"商品1","skuNum":4,"taxtedAmount":4752},
{"detailId":"2222","orderNo":"12345678","rateAmount":186,"skuName":"商品2","skuNum":3,"taxtedAmount":3564},
{"detailId":"3333","orderNo":"12345678","rateAmount":66,"skuName":"商品3","skuNum":1,"taxtedAmount":1184}]