> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vinmake.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Adjustment notes

> Credit and debit notes that change what is owed without ever editing the original document. Immutability as a feature, not a constraint.

# Adjustment notes

Sub-ledger 6 was introduced by migration `0008`; the current issuance authority is migration `0068_adjustment_note_proposals`.

## The idea

A supplier reduces a bill.
A customer is credited for a return.
A quantity was wrong.

In a mutable system you edit the document.
In GreatBook the original bill or invoice is **never edited**; a note references it and changes its *derived* due.

This is the clearest place where [immutability](/greatbook/capabilities/immutability-and-hash-chain) and [derived balances](/greatbook/capabilities/derived-balances) pay off together.
Because `due` is derived rather than stored, a note does not have to reach into the original and change a number.
It adds a row, and the derivation accounts for it.

```
due = total - allocated - advance_applied + Σ(DEBIT notes) - Σ(CREDIT notes)
```

A **CREDIT** note lowers what is outstanding.
A **DEBIT** note raises it.

## Every new note is staged for a second person

`AdjustmentNoteProposalService.propose` derives the full note plan and stores it without posting.
The proposal names its target obligation, credit/debit direction, source discrepancy basis and reference, exact decimal amounts, currency, proposer, reason, request key, and content fingerprint.

Approval requires a different named person.
The service normalizes identities before comparing them, so case, surrounding whitespace, or the email form cannot turn one person into two.
Agent, service, placeholder, and same-person approvers are refused.

The approval and note issue happen in one transaction.
`approved` is therefore not a durable resting state: either the note, immutable journal, proposal attribution, and native links all commit, or the approval rolls back with the failed post.
The original bill or invoice remains unchanged.

Migration `0068` repeats the load-bearing rules in the database:

* an approved or posted proposal must name a decider distinct from its proposer;
* a staged proposal has no decider and every decided proposal does;
* every proposal carries both a discrepancy basis and the specific source reference;
* amounts are non-negative and `total = amount_pretax + vat_amount`;
* historical notes are not backfilled with invented issuer or proposal evidence.

<Warning>
  The engine service and migration are shipped, but this documentation cut did not find or exercise a public end-to-end adjustment-note proposal UI or API.
  The two-person issuance control is documented as an engine fact, not as a working production workflow claim.
</Warning>

## The four shapes

| Shape         | Meaning                            | Entry                                                                 |
| ------------- | ---------------------------------- | --------------------------------------------------------------------- |
| **AP CREDIT** | the supplier reduces what we owe   | `Dr 2000` (VAS 331) / `Cr <pretax GL>` / `Cr 1300` (VAS 133)          |
| **AP DEBIT**  | the supplier increases what we owe | `Dr <pretax GL>` / `Dr 1300` / `Cr 2000`                              |
| **AR CREDIT** | we reduce what the customer owes   | `Dr 4090` (VAS 521 contra-revenue) / `Dr 2100` (VAS 3331) / `Cr 1100` |
| **AR DEBIT**  | we increase what the customer owes | `Dr 1100` / `Cr 4000` (VAS 511) / `Cr 2100`                           |

Notice that every shape moves the VAT leg too.
A credit note that reduces a bill also reduces the recoverable input VAT, so the [VAT register](/greatbook/capabilities/subledgers/vat-statutory) and the `133` position stay tied.

A note that touches a stock account also posts a matching stock movement, so the [costing sub-ledger](/greatbook/capabilities/subledgers/inventory-costing) stays consistent with what was actually returned.

## What a note may not do

Three checks constrain a note against the document it adjusts:

| Rule                                                                    | Check             | Why                                                                                                    |
| ----------------------------------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------ |
| a note with a stated basis must link to a real source document          | `ADJ-BASIS-LINK`  | a note against nothing is an unexplained movement in AP or AR                                          |
| the note's quantity gap may not exceed the original document's quantity | `ADJ-QTY-CEILING` | crediting more units than were ever bought is a data error, not a business event                       |
| the note's VAT rate must match the original document's rate             | `ADJ-RATE-MATCH`  | a rate change between document and note produces a VAT position neither party's return will agree with |

Plus `ADJ-CATALOG` (the direction and target type are in the catalog), `ADJ-ORPHAN` (no note against a document that does not exist), `ADJ-AMOUNT` (amount matches quantity times price) and `ADJ-STOCK-COUNTERLEG` (a stock-touching note posted its movement).

Two explainable balances report the net adjustment impact on AP and on AR.

## Where it is enforced

| Concern                                                 | Code                                                       |
| ------------------------------------------------------- | ---------------------------------------------------------- |
| the four shapes, and the ceiling and rate-match sources | `backend/app/logics/finance/adjustments.py`                |
| the original note schema                                | migration `0008_adjustment_notes`                          |
| proposal lifecycle and two-person issuance              | `backend/app/services/adjustment_note_proposal_service.py` |
| proposal schema and database constraints                | migration `0068_adjustment_note_proposals`                 |
| the derivation of `due`                                 | `derive.obligation_due`                                    |
| the checks                                              | `close_checks.run_adjustment_checks`                       |

## The test that would fail if it broke

`backend/tests/test_adjustments.py` covers all four shapes and the constraint checks, and ties to the v12 worked data: a credit note moves a bill's due to 2,805,000 with the original document frozen, and a note against an invoice produces a negative due of 100 where the customer overpaid.
`backend/tests/test_adjustment_note_authority.py` covers distinct-human approval, exact plan re-derivation, stale state, database constraints, replay, atomicity, and deliberately null historical attribution.

<Note>
  A **negative** due is a legitimate outcome, not a bug: it is an overpayment.
  The check surface reports it rather than clamping it to zero, because clamping loses the fact that money is owed back.
</Note>

## Adjustment notes are not adjusting entries

Two similarly-named things, and they are different.

|                 | Adjustment note (this page)                            | [Adjusting entry](/greatbook/agents/accountant)                  |
| --------------- | ------------------------------------------------------ | ---------------------------------------------------------------- |
| What it adjusts | a specific bill or invoice                             | the books at period end                                          |
| Who raises it   | a business event: a supplier credit, a customer return | the Accountant, at close                                         |
| Examples        | credit note, debit note                                | FX revaluation, accrual, prepaid release, depreciation, reversal |
| Where it lives  | this sub-ledger                                        | `agents/accountant/adjustments.py`                               |
| Sub-ledger      | 6                                                      | none - it posts through the Bookkeeper's gate                    |

## What goes wrong without it

Editing the original is the alternative, and it breaks three things at once: the hash chain, the audit trail, and any downstream artifact that already quoted the old figure.

The softer failure is a "correction" booked as a fresh unrelated entry.
It nets to the right total and nothing links it to what it corrected, so the supplier statement reconciliation shows one bill you disagree about and one credit you cannot explain.

## Related

* [Immutability and the hash chain](/greatbook/capabilities/immutability-and-hash-chain) - why the original is frozen
* [Nothing stored that can be derived](/greatbook/capabilities/derived-balances) - why a note can change `due` without touching it
* [Settlement, rails and the AP/AR spine](/greatbook/capabilities/subledgers/settlement) - the obligations notes adjust
* [VN VAT and statutory tax](/greatbook/capabilities/subledgers/vat-statutory) - the VAT leg every note carries
