Test every Current Account feature - RodrigoMattosoSilveira/EnterpriseRemoteSystems GitHub Wiki

1. Start from a clean local manual dataset

From the project root:

cd /Users/rodrigosilveira/projects/EnterpriseRemoteSystems

make manual-testdata-local-reset
python3 scripts/verify-manual-testdata.py

Expected:

✅ Manual seed verification passed.

Then start the local app normally.

2. Set local API helpers

API=http://localhost:8080/api/v1
ACTOR=bootstrap-admin
TENANT=default

api_get() {
  curl -sS \
    -H "X-Actor-ID: $ACTOR" \
    -H "X-Tenant-ID: $TENANT" \
    "$@"
}

api_post() {
  curl -sS \
    -H "Content-Type: application/json" \
    -H "X-Actor-ID: $ACTOR" \
    -H "X-Tenant-ID: $TENANT" \
    "$@"
}

Confirm the actor resolves:

api_get "$API/authz/current-actor" | python3 -m json.tool

Expected:

bootstrap-admin
active actor
APPLICATION_ADMIN
effective permission includes *

3. Confirm existing outstanding receipts are visible

api_get "$API/receipts/outstanding?pageSize=10" | python3 -m json.tool

Expected:

HTTP success
data.items contains outstanding receipt records if the seed includes unreturned debit receipts
each item includes:
ledgerEntryId
entryType
sourceType
collaboratorId
amount
receiptNumber
status

This confirms the outstanding-receipt workbench still sees debit obligations.

4. Browser smoke: debit receipt visibility

Open:

http://localhost:5173/receipts/outstanding

Expected:

page loads as bootstrap-admin
outstanding receipts appear
each row is tied to a collaborator and debit ledger entry
no authorization error appears

Then open a collaborator with ledger activity:

http://localhost:5173/collaborators

Open their Current Account.

Expected:

debit ledger rows show receipt status or receipt action
receipt-linked debit rows have a printable receipt path
credit rows do not require receipt action

5. Create a normal expense and verify receipt obligation

In the UI:

  1. Go to New Expense.
  2. Choose an active collaborator.
  3. Choose a Canteen item.
  4. Create a small BRL expense.
  5. Open that collaborator’s Current Account.

Expected:

a new debit ledger entry appears for the expense
the debit entry shows a receipt obligation
the entry is included in outstanding receipts until returned

Now verify through API. Replace the collaborator ID:

COLLABORATOR_ID="<collaborator-id-from-url-or-ui>"


api_get "$API/current-accounts/$COLLABORATOR_ID/ledger-entries?direction=DEBIT&pageSize=5" \
  | python3 -m json.tool

NOTE: you might need to increase the page size to see the receipt.

Use this to find the collaborator ID

api_get "$API/collaborators?pageSize=200" \
  | python3 -c '
import json, sys
data = json.load(sys.stdin)["data"]["items"]
for c in data:
    text = " ".join(str(c.get(k, "")) for k in ["nickname", "firstName", "lastName", "personName", "personNickname"])
    if "Paulo" in text or "MT 16" in text:
        print(c["id"], text)
'

Expected for the new expense debit:

  • receipt is present
  • receipt.outstanding is true
  • receipt.status is not returned

Also confirm it appears in the outstanding workbench:

api_get "$API/receipts/outstanding?collaborator=$COLLABORATOR_ID&pageSize=10" \
  | python3 -m json.tool

Expected:

the new expense receipt appears.

6. Print and return the receipt

From the ledger-entry API output, capture the debit entry ID:

LEDGER_ENTRY_ID="<new-debit-ledger-entry-id>"

Print the receipt:

api_post -X POST "$API/ledger-entries/$LEDGER_ENTRY_ID/receipt/print" \
  | python3 -m json.tool

Expected:

receipt status advances to printed, or printed timestamp is set
no duplicate receipt is created

Return the signed receipt:

api_post -X POST \
  -d '{
    "signedDocumentRef": "manual-test/bite-27c-signed-receipt.pdf",
    "notes": "Bite 27C manual receipt return test"
  }' \
  "$API/ledger-entries/$LEDGER_ENTRY_ID/receipt/return" \
  | python3 -m json.tool

Expected:

receipt status becomes returned/signed/closed according to the app’s current naming
outstanding becomes false
signedDocumentRef is stored

Re-check outstanding receipts:

api_get "$API/receipts/outstanding?collaborator=$COLLABORATOR_ID&pageSize=10" \
  | python3 -m json.tool

Expected:

the returned receipt no longer appears as outstanding.

7. Create a grams-of-gold expense and verify receipt obligation

In the UI:

  1. Go to New Expense.
  2. Select an active collaborator.
  3. Select an Administrative item.
  4. Select currency grams of gold.
  5. Save the expense.

Expected:

Current Account gets a gold-gram debit
the gold debit has a receipt obligation
it appears in outstanding receipts

API check:

api_get "$API/current-accounts/$COLLABORATOR_ID/ledger-entries?direction=DEBIT&pageSize=10" \
  | python3 -m json.tool

Expected:

the new GOLD_GRAM debit has receipt
receipt.outstanding is true

8. Verify receipt backfill is idempotent

Run a dry run if supported by the current endpoint behavior; otherwise run the normal backfill on local only:

api_post -X POST \
  -d '{
    "reasonCode": "MANUAL_TEST",
    "reasonText": "Bite 27C receipt backfill manual check"
  }' \
  "$API/receipts/backfill-debit-ledger-entries" \
  | python3 -m json.tool

Expected:

existing receipt obligations are recognized
created receipt count should be 0 in a clean post-Bite-27C local database, unless old local data contained pre-existing debit entries without receipts
running it a second time should not create duplicates

Run it again:

api_post -X POST \
  -d '{
    "reasonCode": "MANUAL_TEST",
    "reasonText": "Bite 27C receipt backfill idempotency check"
  }' \
  "$API/receipts/backfill-debit-ledger-entries" \
  | python3 -m json.tool

Expected:

no duplicate receipts
created count remains 0

9. Verify ledger correction creates receipt coverage when replacement is a debit

Find a credit or debit ledger entry that is correctable from the Current Account screen, then use the UI correction flow if available.

Preferred UI test:

  1. Open collaborator Current Account.
  2. Pick a correctable ledger entry.
  3. Replace it with a debit amount.
  4. Provide reason code/text.
  5. ave.

Expected:

reversal/replacement succeeds
any debit created by the correction has a receipt
no debit appears without a receipt
outstanding receipts includes the new debit receipt if not returned

API verification:

api_get "$API/current-accounts/$COLLABORATOR_ID/ledger-entries?direction=DEBIT&includeInactive=true&pageSize=20" \
  | python3 -m json.tool

Expected:

every active debit entry has a receipt
inactive correction reversal rows should not create unexpected duplicate obligations unless they are debit-producing active obligations by design

10. Verify settlement preview blocks outstanding receipts

Use a collaborator with at least one outstanding receipt.

api_get "$API/collaborators/$COLLABORATOR_ID/settlement-preview" \
  | python3 -m json.tool

Expected:

canClose: false
blockingReasons includes OUTSTANDING_RECEIPTS
outstandingReceipts > 0

Then return all outstanding receipts for that collaborator and call preview again.

Expected:

OUTSTANDING_RECEIPTS disappears

if there are no other blockers, canClose becomes true

11. Verify zero-gold settlement creates a receipt obligation

Choose a collaborator with positive gold balance.

Call settlement preview first:

api_get "$API/collaborators/$COLLABORATOR_ID/settlement-preview" \
  | python3 -m json.tool

Then post zero-gold on local only:

REQ_ID="manual-zero-gold-$(date +%s)"

api_post -X POST \
  -d "{
    \"requestId\": \"$REQ_ID\",
    \"effectiveDate\": \"$(date +%F)\",
    \"reasonCode\": \"MANUAL_TEST\",
    \"reasonText\": \"Bite 27C zero-gold manual receipt enforcement test\",
    \"notes\": \"Local manual test\"
  }" \
  "$API/collaborators/$COLLABORATOR_ID/zero-gold" \
  | python3 -m json.tool

Expected:

settlement succeeds
response includes a debit ledger entry
the debit ledger entry includes receipt data
receipt is outstanding until returned

Then check:

api_get "$API/current-accounts/$COLLABORATOR_ID/ledger-entries?direction=DEBIT&pageSize=10" \
  | python3 -m json.tool

Expected:

zero-gold debit has exactly one receipt obligation.

12. Verify partial payout creates receipt obligations

Choose a collaborator with positive BRL and/or gold balance.

REQ_ID="manual-payout-$(date +%s)"

api_post -X POST \
  -d "{
    \"requestId\": \"$REQ_ID\",
    \"effectiveDate\": \"$(date +%F)\",
    \"brlAmount\": 1,
    \"goldGramAmount\": 0,
    \"reasonCode\": \"MANUAL_TEST\",
    \"reasonText\": \"Bite 27C partial payout manual receipt enforcement test\",
    \"notes\": \"Local manual test\"
  }" \
  "$API/collaborators/$COLLABORATOR_ID/payout" \
  | python3 -m json.tool

Expected:

payout succeeds if the collaborator has at least R$1 available
every debit ledger entry returned in ledgerEntries has receipt data
outstanding receipts includes the payout debit receipt

If the collaborator does not have BRL balance, use a small gold amount instead:

"brlAmount": 0, "goldGramAmount": 0.01

13. Verify close journey does not bypass receipt enforcement

Use a collaborator whose settlement preview has no blockers.

api_get "$API/collaborators/$COLLABORATOR_ID/settlement-preview" \
  | python3 -m json.tool

Expected before close:

canClose: true

Then close locally:

REQ_ID="manual-close-$(date +%s)"

api_post -X POST \
  -d "{
    \"requestId\": \"$REQ_ID\",
    \"effectiveDate\": \"$(date +%F)\",
    \"confirm\": true,
    \"reasonCode\": \"MANUAL_TEST\",
    \"reasonText\": \"Bite 27C close journey manual receipt enforcement test\",
    \"notes\": \"Local manual test\"
  }" \
  "$API/collaborators/$COLLABORATOR_ID/close" \
  | python3 -m json.tool

Expected:

close succeeds only if no blockers exist
if close creates debit settlement entries, every returned debit entry has receipt data
collaborator is removed from normal active collaborator list after close

If the close is blocked by outstanding receipts, that is acceptable and expected. Return receipts first, then retry with a different request ID.

14. Confirm no active debit without receipt remains

This is the final safety check.

Use SQLite locally. Adjust the DB file path if your local setup uses a different one:

sqlite3 backend/app.local.db <<'SQL'
SELECT le.id,
       le.collaborator_id,
       le.source_type,
       le.source_id,
       le.amount,
       le.effective_date
FROM ledger_entries le
LEFT JOIN receipts r ON r.ledger_entry_id = le.id
WHERE le.direction = 'DEBIT'
  AND le.active = 1
  AND r.id IS NULL;
SQL
```bash

Expected:

no rows

Also check for duplicate receipt obligations on a single active debit:

```bash
sqlite3 backend/app.local.db <<'SQL'
SELECT le.id,
       COUNT(r.id) AS receipt_count
FROM ledger_entries le
JOIN receipts r ON r.ledger_entry_id = le.id
WHERE le.direction = 'DEBIT'
  AND le.active = 1
GROUP BY le.id
HAVING COUNT(r.id) <> 1;
SQL
```bash

Expected:

no rows

These two SQL checks are the most important Bite 27C promotion checks.