Bendrinti naudojant


Įtraukti duomenų laukus į mokesčių integravimą naudojant plėtinį

Šiame straipsnyje paaiškinama, kaip naudoti X++ plėtinius norint įtraukti duomenų laukus į mokesčių integravimą. Šiuos laukus galima išplėsti iki mokesčių tarnybos mokesčių duomenų modelio ir naudoti mokesčių kodams nustatyti. Daugiau informacijos ieškokite Mokesčių konfigūracijų duomenų laukų pridėjimas.

Duomenų modelis

Duomenų modelio duomenis vykdo objektai ir su įdiegė klasės.

Toliau pateiktas pagrindinių objektų sąrašas:

  • AxClass /TaxIntegration dokumentoobjektas
  • AxClass / TaxIntegrationeilutės objektas
  • AxClass/TaxIntegrationTaxLineobjektas

Šioje iliustracijoje parodyta, kaip šie objektai yra susiję.

Duomenų modelio objekto ryšys. ]

Dokumento objekte gali būti daug eilutės objektų. Kiekviename objekte yra mokesčių tarnybos metaduomenys.

  • TaxIntegrationDocumentObject yra originAddress metaduomenų, kuriuose yra informacijos apie šaltinio adresą ir includingTax metaduomenis, kurie nurodo, ar eilutės suma apima PVM.
  • TaxIntegrationLineObject yra itemId ir quantity metaduomenys categoryId .

Banknotas

TaxIntegrationLineObject taip pat įdiegia mokesčio objektus.

integravimo eiga

Srauto duomenis valdo veikla.

Pagrindinės veiklos

  • AxClass /TaxIntegrationskaičiavimoActivityOnDocument
  • AxClass/TaxIntegrationCurrencyExchangeActivityOnDocument
  • AxClass/TaxIntegrationDataPersistenceActivityOnDocument
  • AxClass/TaxIntegrationDataRetrievalActivityOnDocument
  • AxClass/TaxIntegrationsettingRetrievalActivityOnDocument

Veiklos yra paleidžiamos tokia tvarka:

  1. Nustatomas nuskaitimas
  2. Duomenų nuskaitymas
  3. Skaičiavimo tarnyba
  4. Valiutos kursas
  5. Duomenų pastovumas

Pvz., pratęsite duomenų nuskaitą prieš skaičiavimo tarnybą.

Duomenų gavimo veiklos

Duomenų nuskaityme nuskaitomi duomenys iš duomenų bazės. Skirtingų operacijų adapterius galima nuskaityti duomenis iš skirtingų operacijų lentelių:

  • AxClass/ TaxIntegrationPurchTableDataRetrieval
  • AxClass / TaxIntegrationPurchParmTableDataRetrieval
  • AxClass / TaxIntegrationPurchREQTableDataRetrieval
  • AxClass / TaxIntegrationPurchRFQTableDataRetrieval
  • AxClass / TaxIntegrationVendInvoiceInfoTableDataRetrieval
  • AxClass / TaxIntegrationSalesTableDataRetrieval
  • AxClass / TaxIntegrationSalesParmDataRetrieval

Šie duomenų nuskaitymi duomenys kopijuojami iš duomenų bazės į ir TaxIntegrationDocumentObject į TaxIntegrationLineObject. Kadangi visos šios veiklos išplečia tą pačią abstrakčią šablono klasę, jos turi bendrus metodus.

Apskaičiavimo paslaugų veikla

Skaičiavimo paslaugos veikla yra sąsaja tarp mokesčių tarnybos ir mokesčių integravimo. Ši veikla yra atsakinga už šias funkcijas:

  1. Kurti užklausą.
  2. Užregistruokite užklausą mokesčių tarnybai.
  3. Gauti atsakymą iš mokesčių tarnybos.
  4. Atmesti atsakymą.

Duomenų laukas, kurį įtraukiate į užklausą, bus registruojamas kartu su kitais metaduomenimis.

Plėtinio diegimas

Šiame skyriuje pateikiami išsamūs veiksmai, paaiškinays, kaip įdiegti plėtinį. Jis naudoja išlaidų centrą ir projekto finansines dimensijas kaip pavyzdžius.

1 veiksmas. Įtraukti duomenų kintamąjį į objektų klasę

Objekto klasėje yra duomenų kintamųjų ir getterių/seter metodų. Priklausomai nuo lauko lygio, TaxIntegrationDocumentObject duomenų TaxIntegrationLineObject lauką įtraukite į jį arba į jį. Toliau pavyzdyje naudojamas eilutės lygis ir failo vardas TaxIntegrationLineObject_Extension.xpp.

Banknotas

Jei duomenų laukas, į kurį pridedate, yra dokumento lygyje, pakeiskite failo vardą TaxIntegrationDocumentObject_Extension.xpp.

[ExtensionOf(classStr(TaxIntegrationLineObject))]
final class TaxIntegrationLineObject_Extension
{
    private OMOperatingUnitNumber costCenter;
    private ProjId projectId;

    /// <summary>
    /// Gets a costCenter.
    /// </summary>
    /// <returns>The cost center.</returns>
    public final OMOperatingUnitNumber getCostCenter()
    {
        return this.costCenter;
    }

    /// <summary>
    /// Sets the cost center.
    /// </summary>
    /// <param name = "_value">The cost center.</param>
    public final void setCostCenter(OMOperatingUnitNumber _value)
    {
        this.costCenter = _value;
    }

    /// <summary>
    /// Gets a project ID.
    /// </summary>
    /// <returns>The project ID.</returns>
    public final ProjId getProjectId()
    {
        return this.projectId;
    }

    /// <summary>
    /// Sets the project ID.
    /// </summary>
    /// <param name = "_value">The project ID.</param>
    public final void setProjectId(ProjId _value)
    {
        this.projectId = _value;
    }
}

Išlaidų centras ir projektas įtraukiami kaip privačios kintamieji. Sukurkite šių duomenų laukų getterio ir nustatymo metodus duomenims valdyti.

2 veiksmas. Nuskaityti duomenis iš duomenų bazės

Nurodykite operaciją ir pratęskite atitinkamas adapterio klases, kad gautumėte duomenis. Pavyzdžiui, jei naudojate pirkimo užsakymo operaciją , turite išplėsti ir TaxIntegrationPurchTableDataRetrieval TaxIntegrationVendInvoiceInfoTableDataRetrieval.

Banknotas

TaxIntegrationPurchParmTableDataRetrieval yra paveldėta iš TaxIntegrationPurchTableDataRetrieval. Jos keisti negalima, nebent skiriasi lentelių purchTable purchParmTable ir lentelių logika.

Jei duomenų laukas turi būti pridėtas prie visų operacijų, išplėskite visas DataRetrieval klases.

Kadangi visos duomenų nuskaitymos veiklos išplečia tą pačią šablono klasę, klasių struktūros, kintamieji ir metodai yra panašūs.

protected TaxIntegrationDocumentObject document;

/// <summary>
/// Copies to the document.
/// </summary>
protected abstract void copyToDocument()
{
    // It is recommended to implement as:
    //
    // this.copyToDocumentByDefault();
    // this.copyToDocumentFromHeaderTable();
    // this.copyAddressToDocument();
}
 
/// <summary>
/// Copies to the current line of the document.
/// </summary>
/// <param name = "_line">The current line of the document.</param>
protected abstract void copyToLine(TaxIntegrationLineObject _line)
{
    // It is recommended to implement as:
    //
    // this.copyToLineByDefault(_line);
    // this.copyToLineFromLineTable(_line);
    // this.copyQuantityAndTransactionAmountToLine(_line);
    // this.copyAddressToLine(_line);
    // this.copyToLineFromHeaderTable(_line);
}

Šiame pavyzdyje parodyta pagrindinė struktūra, kai PurchTable naudojama lentelė.

public class TaxIntegrationPurchTableDataRetrieval extends TaxIntegrationAbstractDataRetrievalTemplate
{
    protected PurchTable purchTable;
    protected PurchLine purchLine;

    // Query builder methods
    [Replaceable]
    protected SysDaQueryObject getDocumentQueryObject()
    [Replaceable]
    protected SysDaQueryObject getLineQueryObject()
    [Replaceable]
    protected SysDaQueryObject getDocumentChargeQueryObject()
    [Replaceable]
    protected SysDaQueryObject getLineChargeQueryObject()

    // Data retrieval methods
    protected void copyToDocument()
    protected void copyToDocumentFromHeaderTable()
    protected void copyToLine(TaxIntegrationLineObject _line)
    protected void copyToLineFromLineTable(TaxIntegrationLineObject _line)
    ...
}

Iškvietus CopyToDocument metodą, buferis this.purchTable jau yra. Šio metodo paskirtis yra kopijuoti visus this.purchTable document reikiamus duomenis iš objekto naudojant klasėje sukurtą seterio DocumentObject metodą.

Taip pat šis metodas this.purchLine jau yra buferis CopyToLine . Šio metodo paskirtis yra kopijuoti visus this.purchLine _line reikiamus duomenis iš objekto naudojant klasėje sukurtą seterio LineObject metodą.

Pats efektyviausias būdas yra išplėsti ir CopyToDocument CopyToLine metodus. Tačiau pirmiausia rekomenduojame išbandyti ir copyToDocumentFromHeaderTable copyToLineFromLineTable metodus. Jei jie neveikia taip, kaip jums reikia, įtinkite savo metodą ir iškieskite jį CopyToDocument CopyToLine. Yra trys bendrosios situacijos, kuriose galite naudoti šį būdą:

  • Būtinas laukas yra arba PurchTable PurchLine Tokiu atveju galite išplėsti ir copyToDocumentFromHeaderTable copyToLineFromLineTable. Čia yra pavyzdžio kodas.

    /// <summary>
    /// Copies to the current line of the document from.
    /// </summary>
    /// <param name = "_line">The current line of the document.</param>
    protected void copyToLineFromLineTable(TaxIntegrationLineObject _line)
    {
        next copyToLineFromLineTable(_line);
        // if we already added XXX in TaxIntegrationLineObject
        _line.setXXX(this.purchLine.XXX);
    }
    
  • Reikalaujami duomenys nėra numatytoje operacijos lentelėje. Tačiau kai kurie ryšiai su numatytąja lentele yra sujungti, o lauką reikia naudoti daugelyje eilučių. Tokiu atveju pakeiskite lentelę arba getDocumentQueryObject pateikite getLineObject užklausą dėl ryšio sujungtų ryšių. Šiame pavyzdyje laukas Pristatyti dabar yra integruotas su pardavimo užsakymu eilutės lygiu.

    public class TaxIntegrationSalesTableDataRetrieval
    {
        protected MCRSalesLineDropShipment mcrSalesLineDropShipment;
    
        /// <summary>
        /// Gets the query for the lines of the document.
        /// </summary>
        /// <returns>The query for the lines of the document</returns>
        [Replaceable]
        protected SysDaQueryObject getLineQueryObject()
        {
            return SysDaQueryObjectBuilder::from(this.salesLine)
                .where(this.salesLine, fieldStr(SalesLine, SalesId)).isEqualToLiteral(this.salesTable.SalesId)
                .outerJoin(this.mcrSalesLineDropShipment)
                .where(this.mcrSalesLineDropShipment, fieldStr(MCRSalesLineDropShipment, SalesLine)).isEqualTo(this.salesLine, fieldStr(SalesLine, RecId))
                .toSysDaQueryObject();
        }
    }
    

    Šiame pavyzdyje buferis mcrSalesLineDropShipment paskelbiamas ir užklausa apibrėžiama getLineQueryObject. Užklausa naudoja ryšį MCRSalesLineDropShipment.SalesLine == SalesLine.RecId. Kol išplečiate šią situaciją, galite pakeisti savo sudaryti getLineQueryObject užklausos objektą. Tačiau atminkite tolesnius taškus:

    • Kadangi yra metodo grąžinama vertė getLineQueryObject , turite SysDaQueryObject sudaryti šį objektą naudodami SysDa būdą.
    • Negalima pašalinti buvusios lentelės.
  • Reikiami duomenys sudėtingu sujungimo ryšiu yra susiję su operacijų lentele arba ryšys nėra vienas su vienu (1:1), o su daugeliu (1:N). Šioje situacijoje dalykai tampa šiek tiek sudėtingi. Ši situacija taikoma finansinių dimensijų pavyzdyje.

    Tokiu atveju galite įdiegti savo metodą duomenims nuskaityti. Čia yra pavyzdžio kodas faile TaxIntegrationPurchTableDataRetrieval_Extension.xpp .

    [ExtensionOf(classStr(TaxIntegrationPurchTableDataRetrieval))]
    final class TaxIntegrationPurchTableDataRetrieval_Extension
    {
        private const str CostCenterKey = 'CostCenter';
        private const str ProjectKey = 'Project';
    
        /// <summary>
        /// Copies to the current line of the document from.
        /// </summary>
        /// <param name = "_line">The current line of the document.</param>
        protected void copyToLineFromLineTable(TaxIntegrationLineObject _line)
        {
            Map dimensionAttributeMap = this.getDimensionAttributeMapByDefaultDimension(this.purchline.DefaultDimension);
            if (dimensionAttributeMap.exists(CostCenterKey))
            {
                _line.setCostCenter(dimensionAttributeMap.lookup(CostCenterKey));
            }
            if (dimensionAttributeMap.exists(ProjectKey))
            {
                _line.setProjectId(dimensionAttributeMap.lookup(ProjectKey));
            }
            next copyToLineFromLineTable(_line);
        }
        private Map getDimensionAttributeMapByDefaultDimension(RefRecId _defaultDimension)
        {
            DimensionAttribute dimensionAttribute;
            DimensionAttributeValue dimensionAttributeValue;
            DimensionAttributeValueSetItem dimensionAttributeValueSetItem;
            Map ret = new Map(Types::String, Types::String);
    
            select Name, RecId from dimensionAttribute
                join dimensionAttributeValue
                    where dimensionAttributeValue.dimensionAttribute == dimensionAttribute.RecId
                join DimensionAttributeValueSetItem
                    where DimensionAttributeValueSetItem.DimensionAttributeValue == DimensionAttributeValue.RecId
                        && DimensionAttributeValueSetItem.DimensionAttributeValueSet == _defaultDimension;
    
            while(dimensionAttribute.RecId)
            {
                ret.insert(dimensionAttribute.Name, dimensionAttributeValue.DisplayValue);
                next dimensionAttribute;
            }
            return ret;
        }
    }
    

3 veiksmas. Įtraukti duomenis į užklausą

Išplėskite copyToTaxableDocumentHeaderWrapperFromTaxIntegrationDocumentObject arba copyToTaxableDocumentLineWrapperFromTaxIntegrationLineObjectByLine metodą, norėdami įtraukti duomenis į užklausą. Čia yra pavyzdžio kodas faile TaxIntegrationCalculationActivityOnDocument_CalculationService_Extension.xpp .

[ExtensionOf(classStr(TaxIntegrationCalculationActivityOnDocument_CalculationService))]
final static class TaxIntegrationCalculationActivityOnDocument_CalculationService_Extension
{
    // Define the field name in the request
    private const str IOCostCenter = 'Cost Center';
    private const str IOProject = 'Project';
    // private const str IOEnumExample = 'Enum Example';

    /// <summary>
    /// Copies to <c>TaxableDocumentLineWrapper</c> from <c>TaxIntegrationLineObject</c> by line.
    /// </summary>
    /// <param name = "_destination"><c>TaxableDocumentLineWrapper</c>.</param>
    /// <param name = "_source"><c>TaxIntegrationLineObject</c>.</param>
    protected static void copyToTaxableDocumentLineWrapperFromTaxIntegrationLineObjectByLine(Microsoft.Dynamics.TaxCalculation.ApiContracts.TaxableDocumentLineWrapper _destination, TaxIntegrationLineObject _source)
    {
        next copyToTaxableDocumentLineWrapperFromTaxIntegrationLineObjectByLine(_destination, _source);
        // Set the field we need to integrated for tax service
        _destination.SetField(IOCostCenter, _source.getCostCenter());
        _destination.SetField(IOProject, _source.getProjectId());

        // If the field to be extended is an enum type, use enum2Symbol to convert an enum variable exampleEnum of ExampleEnumType to a string
        // _destination.SetField(IOEnumExample, enum2Symbol(enumNum(ExampleEnumType), _source.getExampleEnum()));
    }
}

Šiuo kodu yra _destination viršelio objektas, naudojamas užklausai sugeneruoti, ir _source yra TaxIntegrationLineObject objektas.

Banknotas

Nurodykite lauko pavadinimą, kuris naudojamas užklausoje kaip privatus const str. Eilutė turi būti lygiai tokia pati, kaip mazgo pavadinimas (ne žymė), įtrauktas į straipsnį Įtraukti duomenų laukus į mokesčių konfigūracijas.

Nustatykite lauką copyToTaxableDocumentLineWraobjectFromTaxIntegrationLineObjectByLine metode naudodami SetField metodą. Antrojo parametro duomenų tipas turi būti eilutė. Jei duomenų tipas nėra eilutė , konvertuoti jį į eilutę. Jei duomenų tipas yra X++ išvardijimas, rekomenduojame naudoti enum2Symbol metodą, kad išvardijimas vertę į eilutę. Mokesčių išvardijimas konfigūracijos pridėta vertė turi būti tokia pati, kaip ir išvardijimas pavadinimas. Toliau pateikiamas skirtumų tarp dviejų išvardijimas, žymės ir pavadinimo sąrašas.

  • Pavadinimo išvardijimas yra simbolinis kodo pavadinimas. enum2Symbol() gali konvertuoti išvardijimas vertę į jos pavadinimą.
  • Vertės vertė išvardijimas skaičiais.
  • Pageidaujamos kalbos išvardijimas gali skirtis. enum2Str() gali konvertuoti išvardijimas vertę į jos žymę.

Modelio priklausomybė

Norėdami sėkmingai sukurti projektą, modelio priklausomybei įtraukite šiuos nuorodų modelius:

  • Application Programos forma
  • Application Mokėjimo prašymas
  • Mokesčių modulis
  • Dimensijos, jei finansinė dimensija korespondentinės sąskaitos
  • Kiti reikalingi modeliai, nurodyti kode

Patikrinimas

Atlikę ankstesnius veiksmus, galite patikrinti savo keitimus.

  1. Finansuose eikite į Mokėtinas sumas ir pridėkite&debug=vs%2CconfirmExit> prie URL. Pavyzdžiui, https://usnconeboxax1aos.cloud.onebox.dynamics.com/?cmp=DEMF&mi=PurchTableListPage&debug=vs%2CconfirmExit& Galutinis> yra būtinas.
  2. Atidaryti pirkimo užsakymo puslapį ir pasirinkti Naujas, kad būtų sukurtas pirkimo užsakymas.
  3. Nustatykite pritaikyto lauko vertę ir pasirinkite PVM. Trikčių diagnostikos failas su prefiksu,TaxServiceTroubleshootingLog atsisiųstas automatiškai. Šiame faile yra operacijos informacija, užregistruota mokesčio apskaičiavimas aptarnavime.
  4. Patikrinkite, ar pritaikytas įtrauktas laukas yra mokesčių tarnybos skaičiavimo įvesties JSON skyriuje ir ar jo vertė teisinga. Jei vertė neteisinga, šiame dokumente du kartus patikrinkite veiksmus.

Failo pavyzdys:

===Tax service calculation input JSON:===
{
  "TaxableDocument": {
    "Header": [
      {
        "Lines": [
          {
            "Line Type": "Normal",
            "Item Code": "",
            "Item Type": "Item",
            "Quantity": 0.0,
            "Amount": 1000.0,
            "Currency": "EUR",
            "Transaction Date": "2022-1-26T00:00:00",
            ...
            /// The new fields added at line level
            "Cost Center": "003",
            "Project": "Proj-123"
          }
        ],
        "Amount include tax": true,
        "Business Process": "Journal",
        "Currency": "",
        "Vendor Account": "DE-001",
        "Vendor Invoice Account": "DE-001",
        ...
        // The new fields added at header level, no new fields in this example
        ...
      }
    ]
  },
}
...

Priedas

Šiame priede rodomas visas pavyzdinis kodas, skirtas finansinių dimensijų integravimui, išlaidų centrui ir projektui eilutės lygiu.

TaxIntegrationLineObject_Extension.xpp

[ExtensionOf(classStr(TaxIntegrationLineObject))]
final class TaxIntegrationLineObject_Extension
{
    private OMOperatingUnitNumber costCenter;
    private ProjId projectId;

    /// <summary>
    /// Gets a costCenter.
    /// </summary>
    /// <returns>The cost center.</returns>
    public final OMOperatingUnitNumber getCostCenter()
    {
        return this.costCenter;
    }

    /// <summary>
    /// Sets the cost center.
    /// </summary>
    /// <param name = "_value">The cost center.</param>
    public final void setCostCenter(OMOperatingUnitNumber _value)
    {
        this.costCenter = _value;
    }

    /// <summary>
    /// Gets a project ID.
    /// </summary>
    /// <returns>The project ID.</returns>
    public final ProjId getProjectId()
    {
        return this.projectId;
    }

    /// <summary>
    /// Sets the project ID.
    /// </summary>
    /// <param name = "_value">The project ID.</param>
    public final void setProjectId(ProjId _value)
    {
        this.projectId = _value;
    }
}

TaxIntegrationPurchTableDataRetrieval_Extension.xpp

[ExtensionOf(classStr(TaxIntegrationPurchTableDataRetrieval))]
final class TaxIntegrationPurchTableDataRetrieval_Extension
{
    private const str CostCenterKey = 'CostCenter';
    private const str ProjectKey = 'Project';

    /// <summary>
    /// Copies to the current line of the document from.
    /// </summary>
    /// <param name = "_line">The current line of the document.</param>
    protected void copyToLineFromLineTable(TaxIntegrationLineObject _line)
    {
        Map dimensionAttributeMap = this.getDimensionAttributeMapByDefaultDimension(this.purchline.DefaultDimension);
        if (dimensionAttributeMap.exists(CostCenterKey))
        {
            _line.setCostCenter(dimensionAttributeMap.lookup(CostCenterKey));
        }
        if (dimensionAttributeMap.exists(ProjectKey))
        {
            _line.setProjectId(dimensionAttributeMap.lookup(ProjectKey));
        }
        next copyToLineFromLineTable(_line);
    }
    private Map getDimensionAttributeMapByDefaultDimension(RefRecId _defaultDimension)
    {
        DimensionAttribute dimensionAttribute;
        DimensionAttributeValue dimensionAttributeValue;
        DimensionAttributeValueSetItem dimensionAttributeValueSetItem;
        Map ret = new Map(Types::String, Types::String);
        select Name, RecId from dimensionAttribute
            join dimensionAttributeValue
                where dimensionAttributeValue.dimensionAttribute == dimensionAttribute.RecId
            join DimensionAttributeValueSetItem
                where DimensionAttributeValueSetItem.DimensionAttributeValue == DimensionAttributeValue.RecId
                    && DimensionAttributeValueSetItem.DimensionAttributeValueSet == _defaultDimension;
        while(dimensionAttribute.RecId)
        {
            ret.insert(dimensionAttribute.Name, dimensionAttributeValue.DisplayValue);
            next dimensionAttribute;
        }
        return ret;
    }
}

TaxIntegrationCalculationActivityOnDocument_CalculationService_Extension.xpp

[ExtensionOf(classStr(TaxIntegrationCalculationActivityOnDocument_CalculationService))]
final static class TaxIntegrationCalculationActivityOnDocument_CalculationService_Extension
{
    // Define the field name in the request
    private const str IOCostCenter = 'Cost Center';
    private const str IOProject = 'Project';

    /// <summary>
    /// Copies to <c>TaxableDocumentLineWrapper</c> from <c>TaxIntegrationLineObject</c> by line.
    /// </summary>
    /// <param name = "_destination"><c>TaxableDocumentLineWrapper</c>.</param>
    /// <param name = "_source"><c>TaxIntegrationLineObject</c>.</param>
    protected static void copyToTaxableDocumentLineWrapperFromTaxIntegrationLineObjectByLine(Microsoft.Dynamics.TaxCalculation.ApiContracts.TaxableDocumentLineWrapper _destination, TaxIntegrationLineObject _source)
    {
        next copyToTaxableDocumentLineWrapperFromTaxIntegrationLineObjectByLine(_destination, _source);
        // Set the field we need to integrated for tax service
        _destination.SetField(IOCostCenter, _source.getCostCenter());
        _destination.SetField(IOProject, _source.getProjectId());
    }
}