具有灵活数据模型、预定义税率、强大解析逻辑的税务库。

v1.0.2 2024-08-21 10:06 UTC

This package is auto-updated.

Last update: 2024-09-21 10:16:05 UTC


README

Build Status

PHP 5.5+ 税务管理库。

功能

  • 智能数据模型,适用于税率变化的金额("19% -> 21% 在1月1日")
  • 为欧盟国家和瑞士预定义税率。更多即将到来。
  • 具有所有主要用例逻辑的税务解析器。

需要 commerceguys/zone

关于库设计的幕后故事可以在 这篇博客文章 中找到。

在数据集中看不到您国家的税种和税率?给我们发一个PR!

数据模型

Zone 1-1 TaxType 1-n TaxRate 1-n TaxRateAmount

每种税种都有一个区域和一个或多个税率。每个税率都有一个或多个税率金额。

示例

  • 税种:法国增值税
  • 区域:"法国 (增值税)"(包括"法国无科西嘉"和"摩纳哥")
  • 税率:标准、中级、减税、超级减税
  • 标准税率的税率金额:19.6%(截至2014年1月1日),20%(自2014年1月1日起)

基本接口不强制设置器,因为服务类不需要它们。扩展接口(TaxTypeEntityInterface,(TaxRateEntityInterface,(TaxRateAmountEntityInterface))也提供为此目的,以及匹配的 TaxTypeTaxRateTaxRateAmount 类,它们可以用作示例或由Doctrine映射。

税务解析器

找到给定应税对象最适合的税种/税率/金额的过程称为解析。除了 应税对象 之外,还向系统传递一个包含客户和商店信息的 上下文对象

税务解析在三个步骤中进行

  1. 解析税种。
  2. 解析每个解析的税种的税率。
  3. 为每个解析的税率获取税率金额(通过调用 $rate->getAmount($date))。

通过调用注册的解析器(按优先级排序)解析税种和税率,直到其中一个返回结果。

包含的税种解析器

  • CanadaTaxTypeResolver(加拿大特定逻辑)

    商店按照客户所在省份/地区的税种来收取税费。

    如果从魁北克省的商店向安大略省的客户销售,则应用安大略省的HST(消费税)。

  • EuTaxTypeResolver(欧盟特定逻辑)

    一家法语商店销售实体产品(例如T恤)将对欧盟客户收取法国增值税。

    自2015年1月1日起,一家法语商店销售数字产品(例如电子书)将应用欧盟客户的税率(例如,德国客户 - 德国增值税等)。

    如果欧盟客户提供了增值税号,法语商店将收取0%的社区内部税率。

  • DefaultTaxTypeResolver(适用于大多数国家的逻辑)

    如果客户和商店属于同一区域,则返回匹配的税种。

    塞尔维亚商店向塞尔维亚客户销售,使用塞尔维亚增值税。

包含的税率解析器

用户将为以下内容创建自定义解析器

  • "纽约州T恤200美元以下不收税"
  • "9月1日学校用品免税(美国税收假日)"
  • "法国和其他国家的电子书减税率"。
  • "返回由$ taxable object引用的税种/税率(明确的供应地,例如"在西班牙提供培训的法国公司")

使用示例

use CommerceGuys\Tax\Repository\TaxTypeRepository;
use CommerceGuys\Tax\Resolver\TaxType\ChainTaxTypeResolver;
use CommerceGuys\Tax\Resolver\TaxType\CanadaTaxTypeResolver;
use CommerceGuys\Tax\Resolver\TaxType\EuTaxTypeResolver;
use CommerceGuys\Tax\Resolver\TaxType\DefaultTaxTypeResolver;
use CommerceGuys\Tax\Resolver\TaxRate\ChainTaxRateResolver;
use CommerceGuys\Tax\Resolver\TaxRate\DefaultTaxRateResolver;
use CommerceGuys\Tax\Resolver\TaxResolver;

// The repository, and the resolvers are usualy initialized by the
// container, this is just a verbose example.
$taxTypeRepository = new TaxTypeRepository();
$chainTaxTypeResolver = new ChainTaxTypeResolver();
$chainTaxTypeResolver->addResolver(new CanadaTaxTypeResolver($taxTypeRepository));
$chainTaxTypeResolver->addResolver(new EuTaxTypeResolver($taxTypeRepository));
$chainTaxTypeResolver->addResolver(new DefaultTaxTypeResolver($taxTypeRepository));
$chainTaxRateResolver = new ChainTaxRateResolver();
$chainTaxRateResolver->addResolver(new DefaultTaxRateResolver());
$resolver = new TaxResolver($chainTaxTypeResolver, $chainTaxRateResolver);

// You can also provide the customer's tax number (e.g. VAT number needed
// to trigger Intra-Community supply rules in EU), list of additional countries
// where the store is registered to collect tax, a different calculation date.
$context = new Context($customerAddress, $storeAddress);

$amounts = $resolver->resolveAmounts($taxable, $context);
// More rarely, if only the types or rates are needed:
$rates = $resolver->resolveRates($taxable, $context);
$types = $resolver->resolveTypes($taxable, $context);

信用