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

维护者

详细信息

github.com/pavkatar/tax

源代码

安装: 287

依赖: 0

建议者: 0

安全: 0

星标: 0

关注者: 0

分支: 39

v0.8.7 2021-03-16 17:00 UTC

This package is auto-updated.

Last update: 2024-09-29 06:14:53 UTC


README

Build Status

PHP 5.5+ 税务管理库。

特性

  • 智能数据模型,适用于税率波动的情况(例如:“19% -> 21% 从1月1日开始”)
  • 为欧盟国家和瑞士预设税率。更多即将到来。
  • 具有针对所有主要用例的解析逻辑的税解析器。

需要 commerceguys/zone

关于库设计的背景故事可以在 这篇文章 中找到。

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

数据模型

区域 1-1 税种 1-n 税率 1-n 税额

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

示例

  • 税种:法国增值税
  • 区域:“法国(增值税)”(包括“法国(不含科西嘉)”和“摩纳哥”)
  • 税率:标准、中间、低、超级低
  • 标准的税率金额: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 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);

信用