# pos-debt-entry Specification

## Purpose
How debt is captured at the POS and bound to an order's lifecycle: validating the "Tiền nợ" input against a selected customer and the order total, deciding when that amount actually reaches the customer's ledger, freezing it once recorded, and reversing debt and reward points when an order is deleted.
## Requirements
### Requirement: The POS "Tiền nợ" input requires a selected customer
The Bán hàng (POS) screen SHALL only accept a value in the "Tiền nợ" input when a customer has been selected for the order. Submitting an order with a debt amount greater than zero but no valid customer attached SHALL be rejected.

#### Scenario: No customer selected
- **WHEN** the seller has not selected a customer on the POS screen
- **THEN** the "Tiền nợ" input is disabled and cannot be filled in

#### Scenario: Customer selected
- **WHEN** the seller has selected a customer on the POS screen
- **THEN** the "Tiền nợ" input becomes enabled and accepts a value

#### Scenario: Order submitted with a debt amount but no customer
- **WHEN** an order is submitted with a "Tiền nợ" amount greater than zero but no resolvable customer
- **THEN** the order is rejected with a validation error, and no debt is recorded

### Requirement: POS debt amount is entered independently, not derived from order total, but cannot exceed it
The "Tiền nợ" amount SHALL be whatever value the seller enters; it is not calculated from the order's total or paid amount. However, it SHALL NOT be greater than the order's `total` — the system rejects a debt amount that exceeds the order's total.

#### Scenario: Debt amount differs from order total but does not exceed it
- **WHEN** the seller enters a "Tiền nợ" amount that is less than the order's total
- **THEN** the order is accepted as-is, using the entered debt amount

#### Scenario: Debt amount exceeds order total
- **WHEN** the seller enters a "Tiền nợ" amount greater than the order's total
- **THEN** the order is rejected with a validation error

### Requirement: POS debt is only recorded against the customer's balance when the order is completed, but the entered amount is preserved on the order regardless of status
A debt amount entered on the POS screen SHALL only be recorded as a `pos_debt` ledger entry (and reflected in the customer's `debt_total`) when the order is saved with a completed status (`done`). Saving the order as a draft SHALL NOT create any ledger entry or change `debt_total`, but the entered "Tiền nợ" amount SHALL still be stored on the order itself, so that reopening the draft later shows the previously entered value instead of appearing blank or reset.

#### Scenario: Order saved as draft with a debt amount
- **WHEN** an order with a "Tiền nợ" amount greater than zero is saved as a draft
- **THEN** no `pos_debt` ledger entry is created and the customer's `debt_total` is unchanged, but the order's stored debt amount reflects the entered value

#### Scenario: Reopening a draft that has a stored debt amount
- **WHEN** a draft order that was previously saved with a "Tiền nợ" amount is reopened for editing
- **THEN** the "Tiền nợ" input shows that previously entered amount, not zero or blank

#### Scenario: Order completed with a debt amount
- **WHEN** an order with a "Tiền nợ" amount greater than zero is saved with status `done`
- **THEN** a `pos_debt` ledger entry is created for that order and the customer's `debt_total` increases by that amount

#### Scenario: A draft with a stored debt amount is completed without resubmitting it
- **WHEN** a draft order that already has a stored debt amount is completed through an action that does not resubmit a "Tiền nợ" value (e.g. a one-click "finalize" action)
- **THEN** the order's previously stored debt amount is used to create the `pos_debt` ledger entry, rather than treating the debt as zero

### Requirement: An order's debt amount is frozen for good once it has ever been recorded to the ledger — independent of the order's current status
Once an order has ever had a `pos_debt` ledger entry recorded for it, the "Tiền nợ" value for that order SHALL become permanently read-only: editing that order afterwards SHALL NOT change its recorded debt amount, create an additional `pos_debt` entry, or alter the customer's `debt_total`, regardless of what value is submitted for "Tiền nợ" on that edit. This lock SHALL be determined by whether a `pos_debt` ledger entry exists for the order — NOT by whether the order's current `status` happens to be `done` — because completed orders can be reverted back to `draft` (a supported workflow) and then completed again; the lock must survive that round-trip so the debt is never recorded a second time. This applies even within the order's normal editable window (used for correcting items, notes, discount, or status). Adjusting a customer's debt after this point SHALL be done through the manual debt entry or repayment actions instead, not by re-editing the order.

#### Scenario: Editing a completed order does not change its debt
- **WHEN** an order that is already `done` and has a recorded debt amount is edited (e.g. its items or notes are changed)
- **THEN** the order's debt amount, its linked `pos_debt` ledger entry, and the customer's `debt_total` all remain unchanged, regardless of any "Tiền nợ" value submitted with the edit

#### Scenario: "Tiền nợ" input is disabled when editing a completed order
- **WHEN** an admin opens an order that is already `done` and has a recorded debt amount, for editing
- **THEN** the "Tiền nợ" input shows the order's recorded debt amount but is disabled

#### Scenario: Debt stays locked after a completed order is reverted back to draft
- **WHEN** an order that already has a recorded `pos_debt` entry is edited and its status is changed from `done` back to `draft`
- **THEN** the "Tiền nợ" input remains disabled and shows the previously recorded amount, and the customer's `debt_total` is not affected by this status change

#### Scenario: Re-completing a previously-done order does not record debt a second time
- **WHEN** an order that already has a recorded `pos_debt` entry is currently `draft` (because it was reverted from `done`), and it is completed (`status` set back to `done`) again
- **THEN** no additional `pos_debt` entry is created and the customer's `debt_total` does not increase again — this order contributes to `debt_total` exactly once, no matter how many times it moves between `draft` and `done`

#### Scenario: A draft that has never been completed remains fully editable
- **WHEN** an admin opens a draft order that has never had a `pos_debt` entry recorded (never yet completed)
- **THEN** the "Tiền nợ" input is enabled (once a customer is selected) and its value can be freely changed, exactly as for any other never-completed draft

#### Scenario: First-time completion still records debt normally
- **WHEN** a draft order that has never had a `pos_debt` entry is edited and completed for the first time with a "Tiền nợ" amount greater than zero
- **THEN** a `pos_debt` ledger entry is created and the customer's `debt_total` increases by that amount

### Requirement: Order detail page shows the recorded debt amount and whether it has actually been counted into the customer's debt
The order detail page SHALL display the order's debt amount when it is greater than zero, and SHALL indicate whether that amount has actually been posted to the customer's `debt_total` (`debt_locked`) or is still just a value staged on a draft that has never been completed — these are not the same thing, since a draft's debt amount has no effect on `debt_total` until the order is finalized.

#### Scenario: Viewing a completed order that has debt
- **WHEN** an admin views the detail page of an order whose debt amount is greater than zero and has been recorded to the ledger (`debt_locked`)
- **THEN** the page shows a "Tiền nợ" line with that amount, labeled as already counted into the customer's debt

#### Scenario: Viewing a draft order that has a staged but not-yet-counted debt amount
- **WHEN** an admin views the detail page of a draft order whose debt amount is greater than zero but has never been recorded to the ledger (not `debt_locked`)
- **THEN** the page shows a "Tiền nợ" line with that amount, labeled as not yet counted into the customer's debt

#### Scenario: Viewing an order with no debt
- **WHEN** an admin views the detail page of an order whose debt amount is zero
- **THEN** the page shows no "Tiền nợ" line

### Requirement: Deleting an order with linked debt voids that debt instead of leaving it orphaned
When an order that has a linked `pos_debt` ledger entry with a positive amount is deleted, the system SHALL reduce the customer's `debt_total` by the lesser of that entry's amount and the customer's current `debt_total`, and SHALL zero out the entry's amount (rather than leaving it pointing at a deleted order with its original amount still counted). The admin SHALL be shown, before confirming deletion, that the order has linked debt and that deleting it will void that debt.

#### Scenario: Deleting an order whose debt has not been touched since
- **WHEN** an order with a linked `pos_debt` entry of amount X is deleted, and the customer's `debt_total` is still at least X
- **THEN** the customer's `debt_total` decreases by X, and the linked entry's amount becomes 0

#### Scenario: Deleting an order after some of its debt has already been repaid elsewhere
- **WHEN** an order with a linked `pos_debt` entry of amount X is deleted, but the customer's current `debt_total` is less than X (because of repayments recorded since)
- **THEN** the customer's `debt_total` decreases only by its current value (down to 0, never negative), and the linked entry's amount becomes 0

#### Scenario: Confirming deletion of an order with linked debt
- **WHEN** an admin clicks to delete an order that has a recorded `pos_debt` ledger entry with a positive amount
- **THEN** the confirmation prompt states the debt amount that will be voided before the deletion proceeds

#### Scenario: Deleting an order with no debt
- **WHEN** an order with no linked debt (or a linked entry already at amount 0) is deleted
- **THEN** the customer's `debt_total` is unchanged

#### Scenario: Deleting a draft that has a staged debt amount but was never completed
- **WHEN** an admin deletes a draft order whose "Tiền nợ" field has a value greater than zero but which has never been completed (no `pos_debt` entry was ever recorded for it)
- **THEN** the confirmation prompt does NOT warn about voiding debt, and the customer's `debt_total` is unaffected, since that amount was never counted in the first place

### Requirement: Deleting an order also reverses reward points it awarded, so they cannot be earned twice
When an order that has awarded reward points to a customer (i.e. it was completed at least once) is deleted, the system SHALL reduce the customer's `points` balance by that order's `earned_point`, clamped at a minimum of zero — never below — since some of those points may already have been spent (e.g. redeemed for a gift) through a path that has no record of which order they originally came from. The admin SHALL be shown, before confirming deletion, how many points will be reversed when applicable.

#### Scenario: Deleting a completed order that awarded points
- **WHEN** an order that awarded X reward points to a customer is deleted, and the customer's current point balance is at least X
- **THEN** the customer's point balance decreases by X

#### Scenario: Deleting a completed order after some of its points were already spent
- **WHEN** an order that awarded X reward points is deleted, but the customer's current point balance is less than X (e.g. some points were redeemed for a gift since)
- **THEN** the customer's point balance decreases only down to zero, never negative

#### Scenario: Deleting a draft order that never awarded points
- **WHEN** an admin deletes a draft order that has never been completed (so it never awarded any points)
- **THEN** the customer's point balance is unaffected by the deletion

#### Scenario: Confirming deletion of an order that awarded points
- **WHEN** an admin clicks to delete an order that awarded reward points
- **THEN** the confirmation prompt also states how many points will be reversed, alongside any debt being voided

