---
title: "CancellationHistory – API-Referenz · Quittio"
description: "What the earlier partial cancellations of an invoice cancelled per VAT group (category and rate), so that the VAT of the next partial cancellation is rounded cumulatively."
canonical_url: "https://quittio.dev/docs/api/Quittio/Core/Corrections/CancellationHistory"
locale: de
meta:
  "og:description": "What the earlier partial cancellations of an invoice cancelled per VAT group (category and rate), so that the VAT of the next partial cancellation is rounded cumulatively."
  "og:image": "https://quittio.dev/og/quittio-de.jpg"
  "og:image:alt": "Quittio: E-Rechnungen für PHP und Laravel. Rechtssicher, validiert, archiviert, mit geprüfter Beispielrechnung."
  "og:image:height": "630"
  "og:image:type": image/jpeg
  "og:image:width": "1200"
  "og:title": "CancellationHistory – API-Referenz · Quittio"
  "twitter:image": "https://quittio.dev/og/quittio-de.jpg"
  "twitter:image:alt": "Quittio: E-Rechnungen für PHP und Laravel. Rechtssicher, validiert, archiviert, mit geprüfter Beispielrechnung."
---

> Index of every page on this site: [llms.txt](https://quittio.dev/llms.txt)

[API reference](https://quittio.dev/docs/api) / [Quittio](https://quittio.dev/docs/api/Quittio) \\ [Core](https://quittio.dev/docs/api/Quittio/Core) \\ [Corrections](https://quittio.dev/docs/api/Quittio/Core/Corrections)

# CancellationHistory

final readonly class in quittio/core

`Quittio\Core\Corrections\CancellationHistory` · [Source](https://github.com/Quittio/quittio/blob/v0.7.1/packages/core/src/Corrections/CancellationHistory.php#L57)

What the earlier partial cancellations of an invoice cancelled per VAT group (category and rate), so that the VAT of the next partial cancellation is rounded cumulatively.

VAT is rounded per document and VAT group (BR-CO-17). Rounded per partial cancellation on its own, the cancellations together can differ from the original by a cent per earlier part (e.g. 9.67 + 9.67 + 9.66 net at 19 %: 3 × 1.84 = 5.52 against 5.51). With a history, per group:

S = taxable amount of the earlier cancellations + taxable amount of this one target = round2(S × rate / 100), half up like the calculator; the original's VAT (BT-117) when this cancellation closes the group (all its lines are then cancelled completely) VAT = target − VAT of the earlier cancellations

After every cancellation the VAT cancelled so far is that of the taxable amount cancelled so far, and once all lines are cancelled exactly the original's VAT (1.84, 1.83, 1.84 = 5.51 in the example). For an original whose VAT another system rounded (BT-117 ≠ round2(BT-116 × rate)), the target is round2(S × BT-117 / BT-116): its rounding difference is spread over the parts in proportion to their taxable amounts instead of falling on the part that closes the group.

In gross price mode the taxable amount follows the same way from the gross amount G of the lines: N = round2(G cancelled so far / (1 + rate / 100)) as for the original (GrossPriceConverter), the original's BT-116 when the group closes, minus the taxable amount already cancelled. The taxable amounts of all cancellations then add up exactly to the original's, and so do the rounding amounts (BT-114).

Every cancellation therefore differs from round2(own taxable amount × rate) (or × the original's effective rate) by at most 0.01, which BR-CO-17 tolerates, and its VAT keeps the sign of its taxable amount (0.00 on 0.00); assertFits() rejects a history for which this would not hold. The VAT total in accounting currency (BT-111) follows the same way: round2(VAT cancelled so far × exchange rate), and the original's BT-111 when the cancellation closes all groups.

Amounts are signed in the original's direction: a credit note that cancels an invoice and the invoice that cancels a credit note count with their amounts, a negative invoice (strategy negative\_invoice) with its amounts negated.

## Properties \#

| Property | Type | Description |
| --- | --- | --- |
| `$closes` readonly | `list<string>` | keys of the VAT groups whose lines are all cancelled completely once this cancellation is issued, including groups closed earlier |
| `$groups` readonly | `array<string, array{taxable: Brick\Math\BigDecimal, tax: Brick\Math\BigDecimal, taxInTaxCurrency: ?Brick\Math\BigDecimal, Quittio\Core\Corrections\gross?: ?Brick\Math\BigDecimal}>` | per VAT group (key: DeclaredAmounts::breakdownKey()) the taxable amount (BT-116) and VAT (BT-117) of the earlier cancellations together, their share of BT-111 (null if unknown) and, in gross price mode, the gross amount of their lines (Σ quantity × price including VAT; null or missing if unknown), in the original's direction |

## Methods \#

| Method | Description |
| --- | --- |
| `->__construct()` | |
| `->align()` | The VAT of a calculated partial cancellation of $original aligned with this history: per VAT group the target minus the VAT already cancelled, and BT-111 the same way. In gross price mode the taxable amount of a group is aligned as well (the net amount of the gross amount cancelled so far minus the taxable amount already cancelled), unless that differs by more than 0.01 from the net amount of the cancellation's own gross amount (a history that does not match): then it keeps its own. Otherwise its taxable amounts stay as they are. Amounts are signed like the cancellation. |
| `->assertFits()` | Rejects a history that does not fit $original, checked with the calculated partial cancellation $cancellation and its aligned VAT breakdown $aligned (align()): |
| `->closes()` | |
| `::entries()` | The VAT groups of an issued (calculated) cancellation of $original in the original's direction, with their share of BT-111 (distributed in proportion to their VAT; null without BT-111) and, in gross price mode, the gross amount of their lines (null otherwise). |
| `->gross()` | Gross amount of the earlier cancellations of a group in gross price mode; null if unknown. |
| `->matches()` | Whether an issued cancellation of $original carries the VAT this history gives it; false e.g. after another partial cancellation was issued meanwhile. |
| `->tax()` | |
| `->taxable()` | |
| `->taxInTaxCurrency()` | BT-111 of the earlier cancellations together; null if a share is unknown. |
| `->withCancellation()` | The history after an issued (calculated) cancellation of $original, e.g. to keep it without the Managed layer; $closes as in the constructor, for the next cancellation. |

### `__construct()`#

```
public function __construct(
    array<string, array{taxable: BigDecimal, tax: BigDecimal, taxInTaxCurrency: ?BigDecimal, gross?: ?BigDecimal}> $groups = [],
    list<string> $closes = [],
)
```

| Parameter | Type | Description |
| --- | --- | --- |
| `$groups` | `array<string, array{taxable: Brick\Math\BigDecimal, tax: Brick\Math\BigDecimal, taxInTaxCurrency: ?Brick\Math\BigDecimal, Quittio\Core\Corrections\gross?: ?Brick\Math\BigDecimal}>` = `[]` | per VAT group (key: DeclaredAmounts::breakdownKey()) the taxable amount (BT-116) and VAT (BT-117) of the earlier cancellations together, their share of BT-111 (null if unknown) and, in gross price mode, the gross amount of their lines (Σ quantity × price including VAT; null or missing if unknown), in the original's direction |
| `$closes` | `list<string>` = `[]` | keys of the VAT groups whose lines are all cancelled completely once this cancellation is issued, including groups closed earlier |

### `align()`#

```
public function align(
    InvoiceData $original,
    InvoiceData $cancellation,
): array{breakdown: list<VatBreakdown>, taxInTaxCurrency: ?BigDecimal}
```

The VAT of a calculated partial cancellation of $original aligned with this history: per VAT group the target minus the VAT already cancelled, and BT-111 the same way. In gross price mode the taxable amount of a group is aligned as well (the net amount of the gross amount cancelled so far minus the taxable amount already cancelled), unless that differs by more than 0.01 from the net amount of the cancellation's own gross amount (a history that does not match): then it keeps its own. Otherwise its taxable amounts stay as they are. Amounts are signed like the cancellation.

| Parameter | Type | Description |
| --- | --- | --- |
| `$original` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |
| `$cancellation` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |

<dl><dt>Returns</dt>
<dd><code>array{breakdown: list&lt;<a href="https://quittio.dev/docs/api/Quittio/Core/Data/Totals/VatBreakdown">VatBreakdown</a>&gt;, taxInTaxCurrency: ?Brick\Math\BigDecimal}</code> – taxInTaxCurrency is null without VAT accounting currency (BT-6), exchange rate or known BT-111 of the earlier cancellations</dd></dl>

### `assertFits()`#

```
public function assertFits(
    InvoiceData $original,
    InvoiceData $cancellation,
    list<VatBreakdown> $aligned,
): void
```

Rejects a history that does not fit $original, checked with the calculated partial cancellation $cancellation and its aligned VAT breakdown $aligned (align()):

- every VAT group of the history and every group it closes must exist in the original,
- the taxable amount cancelled so far (before and including this cancellation) must not exceed per group the sum of the magnitudes of the original's line net amounts,
- every aligned VAT amount must differ by at most 0.01 from round2(own taxable amount × rate) (for an original whose VAT another system rounded, × its effective rate BT-117 / BT-116) and keep the sign of its taxable amount (0.00 on a taxable amount of 0.00).

A history built from the earlier cancellations as issued (withCancellation(), the Managed ledger) always fits.

| Parameter | Type | Description |
| --- | --- | --- |
| `$original` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |
| `$cancellation` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |
| `$aligned` | `list< [VatBreakdown](https://quittio.dev/docs/api/Quittio/Core/Data/Totals/VatBreakdown)>` | |

<dl><dt>Throws</dt>
<dd><code><a href="https://quittio.dev/docs/api/Quittio/Core/Exceptions/InvalidArgumentException">InvalidArgumentException</a></code></dd>
</dl>

### `closes()`#

```
public function closes(string $key): bool
```

| Parameter | Type | Description |
| --- | --- | --- |
| `$key` | `string` | |

<dl><dt>Returns</dt>
<dd><code>bool</code></dd>
</dl>

### `entries()`#

```
public static function entries(
    InvoiceData $original,
    InvoiceData $cancellation,
): list<array{key: string, category: VatCategory, rate: ?BigDecimal, taxable: BigDecimal, tax: BigDecimal, taxInTaxCurrency: ?BigDecimal, gross: ?BigDecimal}>
```

static

The VAT groups of an issued (calculated) cancellation of $original in the original's direction, with their share of BT-111 (distributed in proportion to their VAT; null without BT-111) and, in gross price mode, the gross amount of their lines (null otherwise).

| Parameter | Type | Description |
| --- | --- | --- |
| `$original` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |
| `$cancellation` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |

<dl><dt>Returns</dt>
<dd><code>list&lt;array{key: string, category: <a href="https://quittio.dev/docs/api/Quittio/Core/Enums/VatCategory">VatCategory</a>, rate: ?Brick\Math\BigDecimal, taxable: Brick\Math\BigDecimal, tax: Brick\Math\BigDecimal, taxInTaxCurrency: ?Brick\Math\BigDecimal, gross: ?Brick\Math\BigDecimal}&gt;</code></dd>
</dl>

### `gross()`#

```
public function gross(string $key): ?BigDecimal
```

Gross amount of the earlier cancellations of a group in gross price mode; null if unknown.

| Parameter | Type | Description |
| --- | --- | --- |
| `$key` | `string` | |

<dl><dt>Returns</dt>
<dd><code>?Brick\Math\BigDecimal</code></dd>
</dl>

### `matches()`#

```
public function matches(InvoiceData $original, InvoiceData $cancellation): bool
```

Whether an issued cancellation of $original carries the VAT this history gives it; false e.g. after another partial cancellation was issued meanwhile.

| Parameter | Type | Description |
| --- | --- | --- |
| `$original` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |
| `$cancellation` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |

<dl><dt>Returns</dt>
<dd><code>bool</code></dd>
</dl>

### `tax()`#

```
public function tax(string $key): BigDecimal
```

| Parameter | Type | Description |
| --- | --- | --- |
| `$key` | `string` | |

<dl><dt>Returns</dt>
<dd><code>Brick\Math\BigDecimal</code></dd>
</dl>

### `taxable()`#

```
public function taxable(string $key): BigDecimal
```

| Parameter | Type | Description |
| --- | --- | --- |
| `$key` | `string` | |

<dl><dt>Returns</dt>
<dd><code>Brick\Math\BigDecimal</code></dd>
</dl>

### `taxInTaxCurrency()`#

```
public function taxInTaxCurrency(): ?BigDecimal
```

BT-111 of the earlier cancellations together; null if a share is unknown.

<dl><dt>Returns</dt>
<dd><code>?Brick\Math\BigDecimal</code></dd>
</dl>

### `withCancellation()`#

```
public function withCancellation(
    InvoiceData $original,
    InvoiceData $cancellation,
    list<string> $closes = [],
): self
```

The history after an issued (calculated) cancellation of $original, e.g. to keep it without the Managed layer; $closes as in the constructor, for the next cancellation.

| Parameter | Type | Description |
| --- | --- | --- |
| `$original` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |
| `$cancellation` | `[InvoiceData](https://quittio.dev/docs/api/Quittio/Core/Data/InvoiceData)` | |
| `$closes` | `list<string>` = `[]` | |

<dl><dt>Returns</dt>
<dd><code>self</code></dd>
</dl>

```json
{"@context":"https://schema.org","@graph":[{"@id":"https://quittio.dev/#website","@type":"WebSite","description":"E-Rechnungen für PHP und Laravel: ZUGFeRD, XRechnung und Peppol erstellen, prüfen, lesen und archivieren.","inLanguage":"de-DE","name":"Quittio","url":"https://quittio.dev/","publisher":{"@id":"https://quittio.dev/#identity"},"workTranslation":{"@id":"https://quittio.dev/en#website"}},{"@id":"https://quittio.dev/docs/api/Quittio/Core/Corrections/CancellationHistory#webpage","@type":"WebPage","description":"What the earlier partial cancellations of an invoice cancelled per VAT group (category and rate), so that the VAT of the next partial cancellation is rounded cumulatively.","name":"CancellationHistory – API-Referenz","url":"https://quittio.dev/docs/api/Quittio/Core/Corrections/CancellationHistory","isPartOf":{"@id":"https://quittio.dev/#website"},"potentialAction":[{"@type":"ReadAction","target":["https://quittio.dev/docs/api/Quittio/Core/Corrections/CancellationHistory"]}],"primaryImageOfPage":{"@id":"https://quittio.dev/#logo"}},{"@id":"https://quittio.dev/#identity","@type":"Organization","description":"Open-Source-Bibliothek für E-Rechnungen in PHP und Laravel (ZUGFeRD, XRechnung, Peppol) und Quittio Managed.","email":"kontakt@niklasforst.de","legalName":"Niklas Forst – Softwareentwicklung","name":"Quittio","url":"https://quittio.dev","founder":{"@type":"Person","name":"Niklas Forst","url":"https://quittio.dev/ueber"},"logo":{"@id":"https://quittio.dev/#logo"},"sameAs":["https://github.com/Quittio/quittio","https://packagist.org/packages/quittio/quittio"]},{"@id":"https://quittio.dev/#logo","@type":"ImageObject","caption":"Quittio","contentUrl":"https://quittio.dev/logo.png","inLanguage":"de-DE","url":"https://quittio.dev/logo.png"}]}
```