税务集成入口代码

本文介绍如何将新交易整合到税务整合中。 在开始使用税务集成之前,需要一些“入口代码”,以便您可以绕过传统的税务引擎并使用新的逻辑。 本文就来介绍一下如何引入这个入口代码。

查找代码点

第一步是找到入口代码的代码点。 该代码点应满足以下条件:

  • 代码点应位于传统税务引擎计算税款之前,以便可以绕过税务计算。 此外,代码点应该只绕过税收计算。 不应绕过任何其他流程。

  • 该代码应处于包含可用于初始化 TaxIntegrationDocumentObject 对象的基本交易信息的上下文中。 该对象可以通过两种方式初始化:

    • 来自交易头表记录本身
    • 通过表 ID 和记录 ID 来区分事务的头表记录

通常,如果必须集成的交易已经得到传统税务引擎的支持,则它应该具有 TaxCalculation 类的特定派生类,例如 TaxSales 销售订单或 TaxPurch 采购订单。 此类是一个理想的代码点。 目前,所有交易(例如采购订单和销售订单)都是通过这种方式完成的。 您可以参考 TaxPurch.calculateTax()TaxSales.calc()

如果传统税务引擎不支持该交易,则您应该创建子类 Tax。 本文不涉及这种情况。

实施税收一体化入口

本例使用销售订单的入口代码 TaxSales.xpp

TaxAmount calc()
{
    TaxAmount taxAmount;
    if (Tax::isTaxIntegrationEnabledForBusinessProcess(TaxIntegrationBusinessProcess::Sales))
    {
        taxAmount = this.calcUsingTaxIntegration();
        return taxAmount;
    }
    boolean                  moreLines;
    TaxBaseCur               baseAmount;
    ...
}
  • Tax::isTaxIntegrationEnabledForBusinessProcess() 用于确定某项交易是否采用了税务集成。 此行是一个开关,可让您从前端启用税务整合交易。

    此开关可通过 税务计算参数 页面( 税务 设置 税务配置 税务计算 )上 常规选项卡的>功能设置>部分中的>业务流程字段进行控制。

    税务计算参数页面上的业务流程字段

  • TaxIntegrationBusinessProcess 是一种枚举(enum)类型,当前有五个值: 销售采购库存 (用于转移订单)、 自由文本发票日记帐。 如果新交易未涵盖这五个值,您可以为新交易添加一个新的业务流程枚举值。

  • 所有的逻辑都包裹在 this.calcUsingTaxIntegration()中。

calcUsingTaxIntegration 方法

calcUsingTaxIntegration 方法是准备 TaxIntegrationDocumentObject 对象并调用 TaxIntegrationFacade::calculate(document)的代码。 以下示例使用采购订单。

private TaxAmount calcUsingTaxIntegration()
{
    // code on lock
    ...
    TaxAmountCur taxAmount;
    try
    {
        TaxIntegrationDocumentObject document;
        document = TaxIntegrationDocumentObject::constructWithRecord(purchCalcTax.getSource());
        this.setFieldsForLegacyTax();
        this.setFieldsForTaxIntegrationDocumentObject(document);
        TaxIntegrationFacade::calculate(document);
        amountInclTaxMap = document.getAmountIncludingTax();
        amountExclTaxMap = document.getAmountExcludingTax();
        ...
        taxAmount = this.finalizeCalculationForTaxIntegration(
            TaxParameters::isBankExchRateEnabled_W() && purchCalcTax.vendInvoiceInfoTable(),
            doIsolateTransactionScopeTrue);
    }
    // code on error handling
    ...
    return taxAmount;
}

此代码完成以下步骤。

  1. 通过以下两种方式之一构造 TaxIntegrationDocumentObject 对象:

    • TaxIntegrationDocumentObject::constructWithRecord(Common _record) 接收交易头表记录作为其参数。 这种方法是首选,因为它避免了数据持久性活动中事务表中的字段更新时发生冲突。
    • TaxIntegrationDocumentObject::construct(RefTableId _tableId, RefRecId _recId) 接收一个表 ID 和一个记录 ID 作为其参数,以区分事务的头表记录。 但是,由于从数据库中重新选择了头表记录,因此可能会发生冲突。
  2. 使用 setter 方法设置 TaxIntegrationDocumentObject 对象的基本信息。 在上面的例子中,这一步是通过 this.setFieldsForTaxIntegrationDocumentObject(document) 方法完成的。

  3. TaxIntegrationFacade::calculate(document) 被称为触发真正的税务整合流程。

  4. 获取 amountIncludingTax 与现有税务调整功能兼容的地图。

  5. 调用 this.finalizeCalculationForTaxIntegration() 方法来处理 TaxUncommitted。 仅当交易使用 TaxUncommitted时才需要此步骤。

  6. 退还税额。

设置文档对象的字段

this.setFieldsForTaxIntegrationDocumentObject() 该方法初始化应税文件的基本数据字段,以便在后续活动中使用。

大多数数据字段都应在数据检索活动中检索。 然而,其中一些设置在这里的原因如下:

  • 该字段是基础字段,在数据检索活动之前使用。 示例包括 headingTableIdheadingRecId
  • 仅在此上下文中才可以访问该字段。 例如,税收对象由 _document.setLegacyTax(this);
  • 在这里设置一些字段很方便,因为可以使用本地方法和 TradeCalcTax 子类​​中的方法,避免与数据检索类重复的代码。 示例包括单据日期、发票日期和交货日期。

在调用外观之前根据新的交易设置数据字段。 通常,可以通过入口点上下文中的 TradeCalcTax 对象检索数据。 例如, SalesFormLetterSalesCalcTax_Sales 销售订单的对象, purchCalcTax 是采购订单的对象, custInvoiceCalcTax 是自由文本发票的对象。

下面的例子来自 TaxPurch.xpp

protected void setFieldsForTaxIntegrationDocumentObject(TaxIntegrationDocumentObject _document)
{
    _document.setTransactionDate(this.taxDate);
    // This deliveryDateMarkup() is for header.
    _document.setDeliveryDate(salesFormLetter.deliveryDateMarkup());
    _document.setDocumentDate(salesFormLetter.documentDate());
    _document.setInvoiceDate(salesFormLetter.invoiceDate());
    _document.setTransactionCurrencyCode(salesFormLetter.currencyCode());
    _document.setCompany(this.getCompany());
    _document.setHeadingTableId(this.headingTableId());
    _document.setHeadingRecId(this.headingRecId());
    // this sign is used as sign in TmpTaxWorkTrans, 1 for purchase and -1 for sales.
    _document.setSign(-1);
    _document.setSource(TaxModuleType::Sales);
    _document.setBusinessProcess(TaxIntegrationBusinessProcess::Sales);
    _document.setPrepaid(this.isPrePayment());
    _document.setEUROTriangulation(this.getTriangulation());
    _document.setLegacyTax(this);
    _document.setShouldSkipDocumentCharge(skipTableMarkup);
    _document.setShouldSkipLineCharge(skipLineMarkup);
}