构建电子商务税务引擎
Posted: Wed Dec 11, 2024 7:24 am
在 Squarespace,我们构建并维护 Commerce,这是一个一体化 DIY 平台,可让商家在其网站内经营在线商店。我们的商家在世界各地销售各种各样的产品。尽管商家分布广泛,但所有商家都承担着一个共同的责任:他们必须对销售收入征税,并将这些税款转交给当地政府。
作为一个 DIY 平台,Squarespace 处理税收的方式是让商家输入他们需要收取的税率,然后提供一个可以将这些税率应用于购物车的计算器。因此,Squarespace 的作用不是了解特定税收制度的确切细节,而是提供一个可以有效模拟最常见税收制度的工具。税法可能非常复杂,因此创建这样的工具并非易事。
要求
Squarespace 的税务计算器在第一次迭代中仅支持不含 萨尔瓦多 whatsapp 电话号码列表 税价格,其输出的会计详细信息数量不足以提供欧盟等地区所需的复杂发票。为了更好地支持广泛的商家,我们决定从头开始重建我们的计算器,并牢记以下目标:
支持不含税和含税价格
美国和加拿大通常会在产品价格中添加销售税(例如,一款售价 10.00 美元的产品,如果税率为 10%,则收据为 11.00 美元)。然而,世界其他地区则倾向于在产品价格中包含税费;在欧盟,一款售价 10.00 欧元的产品,如果税率为 10%,则总价仍为 10.00 欧元,但据了解,该价格中的 0.91 欧元已预留用于纳税。我们的计算器需要处理这两种计税方式。
支持特定类型产品的免税
在许多国家和美国各州,特定类型的服务是免税的,因此 Squarespace 允许商家指定某项服务是否需要纳税。我们的计算器需要支持此功能。
输出有关计算的非常高级别的细节

我们的其他系统,例如我们的发票渲染器,需要知道非常详细的详细信息,例如哪些确切的产品被征税,给定的折扣对税收总额的影响有多大,哪些司法管辖区对哪些产品征税,等等。
查看完整尺寸
在发票上显示额外税务详情的选项。这些详情是通过我们新计算器提供的详细会计信息实现的。
在发票上显示额外税务详情的选项。这些详情是通过我们新计算器提供的详细会计信息实现的。
技术目标
和任何好的重建一样,我们希望借此机会为所有新功能奠定坚实的技术基础。这次重建的主要工程目标是:
将计算器与任何产品价格或税率来源分离开来。引擎不应该关心税率是来自我们的数据库、外部税率服务还是其他地方。
使其可测试!并通过一套强大的单元测试进行跟踪。
要非常谨慎地对待数值精度和舍入。
使用 Java 最佳实践:
尽可能使对象 100% 不可变
保持班级规模小、重点突出
避免使用多个参数的方法
在适当的地方使用函数式编程模式:列表转换、过滤操作等(Java 8 太棒了!)
作为一个 DIY 平台,Squarespace 处理税收的方式是让商家输入他们需要收取的税率,然后提供一个可以将这些税率应用于购物车的计算器。因此,Squarespace 的作用不是了解特定税收制度的确切细节,而是提供一个可以有效模拟最常见税收制度的工具。税法可能非常复杂,因此创建这样的工具并非易事。
要求
Squarespace 的税务计算器在第一次迭代中仅支持不含 萨尔瓦多 whatsapp 电话号码列表 税价格,其输出的会计详细信息数量不足以提供欧盟等地区所需的复杂发票。为了更好地支持广泛的商家,我们决定从头开始重建我们的计算器,并牢记以下目标:
支持不含税和含税价格
美国和加拿大通常会在产品价格中添加销售税(例如,一款售价 10.00 美元的产品,如果税率为 10%,则收据为 11.00 美元)。然而,世界其他地区则倾向于在产品价格中包含税费;在欧盟,一款售价 10.00 欧元的产品,如果税率为 10%,则总价仍为 10.00 欧元,但据了解,该价格中的 0.91 欧元已预留用于纳税。我们的计算器需要处理这两种计税方式。
支持特定类型产品的免税
在许多国家和美国各州,特定类型的服务是免税的,因此 Squarespace 允许商家指定某项服务是否需要纳税。我们的计算器需要支持此功能。
输出有关计算的非常高级别的细节

我们的其他系统,例如我们的发票渲染器,需要知道非常详细的详细信息,例如哪些确切的产品被征税,给定的折扣对税收总额的影响有多大,哪些司法管辖区对哪些产品征税,等等。
查看完整尺寸
在发票上显示额外税务详情的选项。这些详情是通过我们新计算器提供的详细会计信息实现的。
在发票上显示额外税务详情的选项。这些详情是通过我们新计算器提供的详细会计信息实现的。
技术目标
和任何好的重建一样,我们希望借此机会为所有新功能奠定坚实的技术基础。这次重建的主要工程目标是:
将计算器与任何产品价格或税率来源分离开来。引擎不应该关心税率是来自我们的数据库、外部税率服务还是其他地方。
使其可测试!并通过一套强大的单元测试进行跟踪。
要非常谨慎地对待数值精度和舍入。
使用 Java 最佳实践:
尽可能使对象 100% 不可变
保持班级规模小、重点突出
避免使用多个参数的方法
在适当的地方使用函数式编程模式:列表转换、过滤操作等(Java 8 太棒了!)