Skip to content

Write the refunded invoice status, and keep nexus measurement intact - #3

Merged
sylvesterdamgaard merged 1 commit into
mainfrom
fix/refund-status
Jul 27, 2026
Merged

Write the refunded invoice status, and keep nexus measurement intact#3
sylvesterdamgaard merged 1 commit into
mainfrom
fix/refund-status

Conversation

@sylvesterdamgaard

Copy link
Copy Markdown
Contributor

InvoiceStatus::Refunded existed in the enum and was assigned nowhere in the app. Its only other appearance was the approval preview, which shows the operator status → refunded before they approve — the refund then executed and left the invoice paid. The console promised a transition the code never performed, to the one person whose job was to check it.

Set cumulatively: several partial refunds that together cover the invoice leave it fully reversed just as one full refund does. A partial refund still leaves it Paid, which is correct.

The part worth reviewing

The economic-nexus ledger filters on [Open, Paid]. Until now a fully-refunded invoice stayed Paid and was measured — so writing the real status would have silently reduced measured US sales as a side effect of an unrelated fix. That surfaces years later as a missed registration.

Refunded is therefore counted explicitly, which is also the safer reading: thresholds are generally stated on gross sales, and the errors are asymmetric — over-counting prompts a registration that may not be needed; under-counting misses one that is, which is back taxes plus penalties. Where a state permits netting returns, that's a per-state refinement against the dataset's rules, not a blanket exclusion to assume here.

This is the one judgement call in the PR — if you'd rather net refunds out of nexus sales, it's a one-line change plus a per-state rule.

Gate

pint · PHPStan level max (0 errors) · 1021 tests — green. Both tests verified to fail with the transition removed.

`InvoiceStatus::Refunded` existed in the enum and was assigned nowhere in the app.
Its only other appearance was RefundInvoiceAction's approval preview, which shows
the operator `status → refunded` before they approve — the refund then executed and
left the invoice `paid`. The console promised a transition the code never performed,
to the one person whose job was to check it.

Set cumulatively rather than per-refund: several partial refunds that together cover
the invoice leave it as fully reversed just as one full refund does. A partial refund
still leaves it `Paid`, which is correct — it IS paid, with part reversed, and the
credit notes carry the detail.

NEXUS CONSEQUENCE, handled deliberately rather than inherited. The economic-nexus
ledger filters on [Open, Paid]. Until now a fully-refunded invoice stayed `Paid` and
was measured; writing the real status would have silently dropped it, REDUCING
measured US sales as a side effect of an unrelated fix — the kind of change that
surfaces years later as a missed registration. `Refunded` is therefore counted
explicitly, which is also the safer reading: thresholds are generally stated on gross
sales, and the errors are asymmetric — over-counting prompts a registration that may
not be needed, under-counting misses one that is, which is back taxes plus penalties.
Where a state permits netting returns, that is a per-state refinement against the
dataset's rules, not a blanket exclusion.

Both tests verified to fail with the transition removed.
@sylvesterdamgaard
sylvesterdamgaard merged commit d9ce51c into main Jul 27, 2026
2 checks passed
@sylvesterdamgaard
sylvesterdamgaard deleted the fix/refund-status branch July 27, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant