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

v0.7.1 2015-11-25 22:15 UTC

This package is not auto-updated.

Last update: 2024-09-18 19:12:43 UTC


README

Build Status

PHP 5.4+ 税务管理库。

特性

  • 智能数据模型,适用于税率变动的情况(例如:“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日起)

基本接口不强制设置器,因为服务类不需要。扩展接口(TaxTypeEntityInterfaceTaxRateEntityInterfaceTaxRateAmountEntityInterface)也提供了相应的功能,以及匹配的TaxTypeTaxRateTaxRateAmount类,这些类可以用作示例或由Doctrine映射。

税务解析器

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

税务解析分为三个步骤

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

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

包含的税种解析器

  • CanadaTaxTypeResolver(加拿大特定逻辑)

    商店按照客户居住地的省份/地区的税法收取税费。

    如果从魁北克省的商店向安大略省的客户销售,则适用安大略省的HST。

  • EuTaxTypeResolver(欧盟特定逻辑)

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

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

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

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

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

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

包含的税率解析器

用户会为以下创建自定义解析器

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

用法示例

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);

致谢