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:
- Go to New Expense.
- Choose an active collaborator.
- Choose a Canteen item.
- Create a small BRL expense.
- 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:
- Go to New Expense.
- Select an active collaborator.
- Select an Administrative item.
- Select currency grams of gold.
- 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:
- Open collaborator Current Account.
- Pick a correctable ledger entry.
- Replace it with a debit amount.
- Provide reason code/text.
- 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.