电商之订单价税拆分实现方案

news2024/9/9 0:29:38

文章目录

  • 案例数据
  • 实现思路
    • 1、计算出平均金额
    • 2、计算每个商品的金额
  • 实现方案
    • 1、订单 order 实体
    • 2、订单明细 orderDetail 实体
    • 3、实现类
    • 4、测试启动
    • 5、实现结果

在做电商项目的时候,会遇到要对订单明细进行纳税金额拆分,即将税额拆分到每个商品上,明确商品的税额,本文记录实现方案,方便备查。

案例数据

本案例模拟的相关数据
订单金额100元【10000分】税率5%,即税额5元【500分】

订单总金额【含税】 payAmount订单税额 rateAmount
1003

商品数量,总数量为8个,包含3个商品,下表是各商品的数量。

商品信息个数
总数量8
商品14
商品23
商品31

实现思路

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<>();
        // 商品1
        OrderDetail detailOne = new OrderDetail();
        detailOne.setDetailId("1111");
        detailOne.setOrderNo("12345678");
        detailOne.setSkuNum(4L);
        detailOne.setSkuName("商品1");
        detailList.add(detailOne);
        // 商品2
        OrderDetail detailTwo = new OrderDetail();
        detailTwo.setDetailId("2222");
        detailTwo.setOrderNo("12345678");
        detailTwo.setSkuNum(3L);
        detailTwo.setSkuName("商品2");
        detailList.add(detailTwo);
        // 商品3
        OrderDetail 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}]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1917179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最优化(10):牛顿类、拟牛顿类算法

4.4 牛顿类算法——介绍了经典牛顿法及其收敛性&#xff0c;并介绍了修正牛顿法和非精确牛顿法&#xff1b; 4.5 拟牛顿类算法——引入割线方程&#xff0c;介绍拟牛顿算法以及拟牛顿矩阵更新方式&#xff0c;然后给出了拟牛顿法的全局收敛性&#xff0c;最后介绍了有限内存BFG…

【漏洞复现】宏景HCM-LoadOtherTreeServlet SQL注入

声明&#xff1a;本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动&#xff0c;将与本文档的作者或发布者无关。 一、漏洞描述 宏景HCM人力资源信息管理系统是一个全面的人力资源管理软件&#xff0c;它覆盖了人力资源管理的各个模块…

龙蜥Anolis OS基于开源项目制作openssh 9.8p1 rpm包 —— 筑梦之路

环境信息 制作过程和centos 7几乎没有区别&#xff0c;此处就不再赘述。 CentOS 7基于开源项目制作openssh9.8p1 rpm二进制包修复安全漏洞CVE-2024-6387 —— 筑梦之路_cve-2024-6387修复-CSDN博客 制作成果展示 tree RPMS/ RPMS/ └── x86_64├── openssh-9.8p1-1.an7.…

【Python 基础】第一个程序

第一个程序 虽然交互式环境对于一次运行一条 Python 指令很好&#xff0c;但要编写完整的 Python程序&#xff0c;就需要在文件编辑器中输入指令。“文件编辑器”类似于 Notepad 或 TextMate这样的文本编辑器&#xff0c;它有一些针对输入源代码的特殊功能。要在 IDLE 中打开文…

常用知识碎片 Vue3 ref和reactive (内含其他常用知识)

目录 ref和reactive ref reactive 总结&#xff1a; setup语法糖 语法糖是啥&#xff1f; Vue3 setup语法糖 Vue3 不使用setup语法糖示例&#xff1a; Vue3 使用setup语法糖示例&#xff1a; ref和eative主要区别 ref和reactive 在 Vue 3 中&#xff0c;ref 和 reac…

linux radix-tree 基数树实现详解

radix tree&#xff0c;又称做基数树&#xff0c;是一种适合于构建key(index)与value(item)相关联的数据结构。内核中使用非常广泛。本文主要聚焦linux内核基数树的代码实现,大量注释过的代码。 radix-tree组织结构如下: 1、数据结构 /** The bottom two bits of the slot de…

SQL 针对上面的salaries表emp_no字段创建索引idx_emp_no

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 针对salaries…

LabVIEW滤波器性能研究

为了研究滤波器的滤波性能&#xff0c;采用LabVIEW设计了一套滤波器性能研究系统。该系统通过LabVIEW中的波形生成函数&#xff0c;输出幅值及频率可调的正弦波和白噪声两种信号&#xff0c;并将白噪声与正弦波叠加&#xff0c;再通过滤波器输出纯净的正弦波信号。系统通过FFT&…

RFID技术革新养猪业,构建智能化养殖场

RFID技术作为无线射频识别技术的一种&#xff0c;凭借着非接触、高效识别的特性&#xff0c;在养殖业行业中得到了广泛的应用&#xff0c;为构建智能化、高效化的养殖场提供了强大的技术支持&#xff0c;给传统养殖业带来了一场前所未有的技术变革。以下是RFID技术在养猪行业不…

【Oracle】实验三 Oracle数据库的创建和管理

【实验目的】 掌握Oracle数据库的创建方法使用DBCA创建数据库在数据库中装入SCOTT用户及其表 【实验内容】 使用DBCA创建数据库&#xff0c;名为MYDB&#xff0c;找到其初始化文件(文本型和服务器型文件都要找到)&#xff0c;查看各类默认位置并记录下来(包括物理文件所在目…

SpringBoot源码阅读(8)——系统环境创建

SpringBoot创建系统应用上下文是在run方法&#xff0c;第301行。 ConfigurableEnvironment environment prepareEnvironment(listeners, bootstrapContext, applicationArguments);private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listen…

windows远程桌面到 Linux系统(Ubuntu:22.04)—— 安装xrdp软件

1、在Linux系统上安装xrdp软件 sudo apt update sudo apt install xrdp2、安装完成后&#xff0c;需要开启xrdp服务 sudo systemctl start xrdp sudo systemctl enable xrdp打印返回 Synchronizing state of xrdp.service with SysV service script with /lib/systemd/system…

【VSCode】设置背景图片

1.下载background插件&#xff1a;拓展程序→background→install安装→设置&#xff1a; 2.点击在 settings.json 中编辑&#xff1a; 3.将settings.json文件中所有代码注释&#xff0c;添加以下代码&#xff1a; {// 是否开启背景图显示"background.enabled": t…

【每天认识一个漏洞】sourcemap文件泄露漏洞

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 利用工具 油猴脚本sourcemap-searcher或burp hae插件 F12控制台输入sms()如果存在会有提示&#xff0c;然后打开看能够下载…

数字化时代的供应链管理综合解决方案

目录 引言背景与意义供应链管理综合解决方案的目标 &#x1f4c4;供应链管理系统主要功能系统优势 &#x1f4c4;物流管理系统主要功能系统优势 &#x1f4c4;订单管理系统主要功能应用场景 &#x1f4c4;仓储管理系统系统亮点主要功能系统优势 &#x1f4c4;商城管理系统主要功…

【机器学习】独立成分分析(ICA):解锁信号的隐秘面纱

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 独立成分分析&#xff08;ICA&#xff09;&#xff1a;解锁信号的隐秘面纱引言I…

LLM——langchain 与阿里 DashScop (通义千问大模型) 和 DashVector(向量数据库) 结合使用总结

文章目录 前言预览直接调用大模型使用 prompt template格式化输出使用上下文 RAG 增强检索 自定义 langchain AgentPromptTemplate 和 ChatPromptTemplate使用少量示例创建ChatPromptTemplate 前言 langchain 是一个面向大模型开发的框架&#xff0c;其中封装了很多核心组件&a…

旷野之间9 - 如何判断是AI编写的文章

一个人写作 人工智能创作的文章、博客、论文甚至书籍在整个互联网上越来越成为问题。 许多人都不确定如何辨别一件作品是由人工智能还是人类创作的。在这篇文章中&#xff0c;我将向您展示如何区分人类和机器人。 深度与原创性 首先要寻找的线索之一是缺乏深度或原创性。人工…

【以史为镜、以史明志,知史爱党、知史爱国】中华上下五千年之-五代十国

五代十国&#xff08;907年-960年&#xff09;是中国历史上的一段大分裂时期&#xff0c;也是对五代与十国的合称。 五代依次为 梁、 唐、 晋、 汉、 周五个朝代&#xff0c;史称 后梁、 后唐、 后晋、 后汉与 后周。 后梁- 五代第一个朝代 朱全忠&#xff08;朱温&#xff09;…

跨境电商必备技能:掌握亚马逊测评自养号技术

亚马逊自养号的环境搭建是一个至关重要的过程&#xff0c;它直接关系到账号的稳定性和安全性。以下是一个详细的搭建方案&#xff1a; 一、底层环境搭建 设备底层硬件参数的伪装阻断&#xff1a; 通过国外服务器在云端搭建一个安全终端&#xff0c;用于阻断平台对设备底层硬…