> For the complete documentation index, see [llms.txt](https://docs.solutioo.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.solutioo.de/differenzbesteuerung-entwicklerdokumentation/differenzbesteuerung_dev_en_us/reference.md).

# Developer documentation

> **App 0.28.1.2 · Development preview · Updated 29 October 2026.** This reference describes the public AL calculation and report columns. There is no released external posting, import or Shopware API. Production approval and final delivery acceptance remain open.

## 1. Extension model and supported scope

The standalone core app depends on Microsoft Application. Test/build tools are not runtime dependencies. There is no released Shopware bridge. Use the documented calculation interface and reviewed report datasets; internal posting services are not supported extension points.

## 2. Development environment, dependencies and versions

Use Microsoft AL, Runtime 17.0 and Microsoft Application 28.0.0.0 or later as declared in the manifest. Core identity: app ID `6ca3568c-f86e-4868-b5db-bed61a866e62`, name `solutioo Margin Tax`, publisher `solutioo`, documented version `0.28.1.2`. Runtime checks currently cover BC 28.5. Your symbols must match the installed object profile. Development and Marketplace IDs must not be interchanged over existing data.

## 3. Authentication, permissions and company context

The calculation codeunit runs inside an AL session. It needs no separate OAuth connection and reads or writes no business data. Calling it requires execute permission on `Margin Tax Calculation SOU`, included in `MARGIN TAX USER SOU`. Reporting against tables needs suitable separate read permissions and remains company-scoped. Production roles do not include the privileged test API. Fiscal enums are intentionally closed to arbitrary extension values.

## 4. Events, APIs and extension points

### Public AL calculation

Codeunit `Margin Tax Calculation SOU` in namespace `Solutioo.MarginTax` exposes exactly these signatures:

```al
procedure Calculate(PurchasePrice: Decimal; SalesPrice: Decimal; VATRate: Decimal;
    Precision: Decimal; var GrossMargin: Decimal; var TaxableBase: Decimal; var VATAmount: Decimal)
procedure CalculateAggregate(Purchases: Decimal; Sales: Decimal; VATRate: Decimal;
    Precision: Decimal; var TaxableBase: Decimal; var VATAmount: Decimal)
procedure InvoiceNotice(Classification: Enum "Margin Tax Class SOU"): Text[100]
```

`Calculate` computes an ordinary individual-scheme supply and limits ordinary tax to zero for non-positive margins. It neither posts nor decides legal eligibility. `CalculateAggregate` is pure arithmetic over non-negative totals. It does not perform annual accumulation, signed corrections, previous-period reconciliation or posting.

`InvoiceNotice` returns the fixed German notice for `UsedGoods`, `Art` and `CollectorsAntiques`; other values raise an error. The statutory wording intentionally remains German independently of the interface language. It does not validate acquisition eligibility.

No public integration/business events or webhooks are stated for this version. Subscribers to standard Microsoft events are not public events published by this app. New fiscal enum values require explicit business handling and tests; third-party values must not silently bypass eligibility checks.

### Reporting data and customer layouts

Acquisition and fiscal evidence is company-scoped and append-only. Extensions must not directly insert fiscal transactions or alter posted evidence. Any future bridge requires a separately approved facade. Purchase prices and margins must stay out of customer interfaces.

`Standard Sales - Invoice` and `Standard Sales - Credit Memo` receive:

| Column                  | Meaning for a customer layout                          |
| ----------------------- | ------------------------------------------------------ |
| `MarginSchemeSOU`       | The line uses margin taxation.                         |
| `MarginSchemeNoticeSOU` | The classification-dependent statutory notice.         |
| `HideLineVATSOU`        | Hide the VAT rate and VAT amount for this margin line. |

These columns contain no purchase basis or internal margin values. A custom layout must use them actively. The app also supplies its own RDLC invoice and credit reports. Credit output retains the original object and invoice reference. All standard required document information must remain intact.

From version 0.21, the own and extended standard reports verify the complete posted document against immutable acquisition/sales evidence before output. Normal AL writes cannot redefine the posted SOU flags. Missing margin lines or inconsistent historical flags stop output. The guard does not replace correct dataset handling in your custom layout.

### Historical evidence and internal boundaries

`Margin Tax Movement SOU` records actual aggregate-scheme sources. `Margin Tax Settlement SOU` records cumulative annual totals, posted adjustments, revisions and the last included source number. A historical report must filter by year, VAT date through period end **and** source number through `Last Movement No.`. Filtering only by date can incorrectly include later backdated documents. `Margin Tax Entry SOU` distinguishes sales, reversals and aggregate settlements and records the scheme.

`Margin Tax Stock Entry SOU` records reviewed transitions and final losses. Original acquisition scheme and purchase price remain historical values. The effective scheme and remaining individual basis at the sales date are resolved from dated stock history. Do not infer them solely from an item flag or original acquisition scheme. `Margin Tax Movement SOU.Stock Entry No.` links the source to its reviewed basis history.

`Margin Return Entry SOU` links actual return item entries to the original acquisition, source sale and reversal or vendor return. `Margin Tax Entry SOU.Inbound Item Entry No.` identifies the consumed original or returned inbound entry; `Return Item Entry No.` identifies the actual return receipt. The original acquisition number remains the fiscal identity. This table is neither an import API nor automatic migration of earlier physical returns.

`Margin Tax Movement SOU.Return Item Entry No.` links purchase-total corrections to immutable vendor-return evidence. The correction period is explicit reviewed business input. Internal permits are not persistent modes for bypassing validation.

`Margin Price Credit SOU` retains financial reductions, before/after values, review details and standard cost references. `Margin Tax Entry SOU.Price Credit No.` and `Margin Tax Movement SOU.Price Credit No.` link the correction. Correction quantity is zero. A stock transition retains the last included price credit as `Price Credit Cutoff No.`.

The internal `FiscalPurchaseSOU` extension of standard enum `Purchase Applies-to Document Type` identifies the exact original purchase for a standard item charge. `Purch.-Post.OnPostItemChargeLineOnAfterPostItemCharge`, with `IncludeSender`, provides the running posting instance; its `PostItemCharge` creates the cost-related value entry in the same transaction. This is not a general import interface. The app does not directly insert its own standard value entries.

`Margin VAT Rate SOU` retains reviewed effective dates and source references. `Margin Tax Entry SOU.Tax Point Date` is separate from the reporting period. `Posted VAT Bus. Group` and `Posted VAT Prod. Group` retain original posted configuration for later corrections. Used configuration is immutable.

The writing services for validation, documents, posting, aggregate settlement, stock, returns, price credits, corrections, payments, evidence, VAT reconciliation, guards and export are internal. `internalsVisibleTo` grants access only to the separate test extension. That privileged QA surface belongs only in a sandbox and must not be delivered to customers.

## 5. Complete example

The complete minimal project below calls only the public calculation. Select an object ID allocated to your own extension; `50100` is an example. Install the matching core and download its symbols. Execute permission on both the example and calculation codeunits is required.

`app.json`:

```json
{
  "id": "e63dbbdf-bb68-44b2-99ea-b4515ee454b1",
  "name": "Margin Tax Calculation Example",
  "publisher": "solutioo",
  "version": "1.0.0.0",
  "platform": "28.0.0.0",
  "application": "28.0.0.0",
  "runtime": "17.0",
  "target": "Cloud",
  "idRanges": [
    {
      "from": 50100,
      "to": 50100
    }
  ],
  "dependencies": [
    {
      "id": "6ca3568c-f86e-4868-b5db-bed61a866e62",
      "name": "solutioo Margin Tax",
      "publisher": "solutioo",
      "version": "0.28.1.2"
    }
  ]
}
```

`CalculationExample.Codeunit.al`:

```al
namespace Solutioo.MarginTax.Example;
using Solutioo.MarginTax;

codeunit 50100 "Margin Calculation Example"
{
    procedure CheckExample()
    var
        Calculation: Codeunit "Margin Tax Calculation SOU";
        GrossMargin: Decimal;
        TaxableBase: Decimal;
        VATAmount: Decimal;
    begin
        Calculation.Calculate(100, 150, 19, 0.01, GrossMargin, TaxableBase, VATAmount);
        if (GrossMargin <> 50) or (TaxableBase <> 42.02) or (VATAmount <> 7.98) then
            Error('Unexpected margin calculation result.');
    end;
}
```

`CheckExample()` expects EUR 50 gross margin, EUR 42.02 taxable base and EUR 7.98 VAT from EUR 100 purchase, EUR 150 sale, 19 percent and 0.01 precision. A mismatch raises an error. The example creates no reviewed acquisition or posted transaction. The public implementation is unchanged; native calculation tests are included in the passing selected [verification scope](https://docs.solutioo.de/differenzbesteuerung/differenzbesteuerung_en_us/updates).

## 6. Transactions, retries and error behaviour

`Calculate` and `CalculateAggregate` require non-negative input prices/totals, a VAT rate greater than zero and no greater than 100, and positive rounding precision. Invalid input raises AL `Error`. Outputs are `var Decimal`; do not overwrite posted evidence with the result. Both methods are deterministic and write no data. There is no idempotency ID or background job.

`Calculate` first rounds `SalesPrice - PurchasePrice`. For a zero or negative margin it leaves taxable base and VAT at zero. Otherwise VAT is `Round(GrossMargin * VATRate / (100 + VATRate), Precision)`, and taxable base is gross margin less VAT. `CalculateAggregate` delegates to that arithmetic; it is not the internal annual settlement engine.

`InvoiceNotice` raises an error for excluded classifications. Internal posting and standard-ledger transactions are not exposed through these public calculation methods.

## 7. Testing and debugging

Selected current checks ran on BC 28.5 in a separate Dev sandbox with synthetic data. Earlier checks apply only to their actual packages and environments. The package manifest disables debugging, source download and source in symbols. Use a controlled source build for internal debugging; it does not replace a customer-approved package.

The separate test app uses function rollback and privileged sandbox actions. Its permissions are not ordinary-user permissions. Test actual roles separately and record version, source commit, package identity, company/environment and result. Never send real tax declarations, external orders or customer shipments from synthetic tests.

## 8. Compatibility, changes and deprecations

There is no approved production Marketplace baseline yet. Do not blindly change object identities or fields between development and Marketplace profiles. Compare public signatures, schemas and report columns against the actual delivered package at every upgrade. An internal API creates no public compatibility promise. Consult the [version and acceptance status](https://docs.solutioo.de/differenzbesteuerung/differenzbesteuerung_en_us/updates).

## 9. Technical FAQ and support

**Can `CalculateAggregate` post a settlement?** No. It is pure arithmetic without annual or source context. Writing services remain internal.

**Can another extension import or change margin evidence directly?** No released external posting/migration API exists. Direct changes to evidence are unsupported. Internal permits are not a public bypass.

**What must a custom layout implement?** Use `HideLineVATSOU` and the classification-dependent notice, retain the other required standard information and pass full document validation. Extending the dataset alone does not change the layout.

For technical support, provide app/BC versions, your extension version, a minimal reproduction, actual role and a sanitized error through the agreed [support route](https://docs.solutioo.de/differenzbesteuerung/differenzbesteuerung_en_us/support). Never publish purchase prices or margins in public issues or screenshots.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.solutioo.de/differenzbesteuerung-entwicklerdokumentation/differenzbesteuerung_dev_en_us/reference.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
