Settlement Accounting¶
Sticky converts Amazon settlement reports or current Finances API transactions into a balanced, A2X-style journal preview. The first release is limited to eComHD's US marketplace and the Hemani Holdings chart of accounts.
Safety posture¶
- QuickBooks posting and scheduled automatic posting use separate seller-level kill switches. The scheduled runner refuses to act unless both are enabled.
- The generator remains preview-only. A separate nightly posting step handles
only exception-free
preview_readybatches. - Generated batches are either
preview_readyorblocked. - Approved batches and every batch with a posting attempt are immutable to preview regeneration.
- A batch cannot be ready unless its debits equal credits and the complete settlement source total equals Amazon's stated payout within one cent.
- Approval stores a SHA-256 hash of the exact QBO request. Posting refuses if the source rows or approved payload change.
- A posting run requires an exact payload approval hash and live QBO
duplicate/readback verification for every journal. The scheduled path records
sticky-auto-policyas the policy approver; exception batches are never eligible.
Data flow¶
pull_settlement.pydownloads Amazon settlement TSVs.- Every report row is stored, including legitimate identical rows. The first copy keeps the legacy content hash; repeated copies receive deterministic duplicate ordinals and hashes.
- Header timestamps populate
settlement_start,settlement_end, anddeposit_date;report_total_amountpreserves Amazon's payout control total. generate_settlement_journals.pyapplies the configurable rules inaccounting.account_mapping_rules.- Order principal is split by brand through
accounting.brand_account_mappings. Catalog gaps can be resolved by explicitaccounting.sku_brand_rules. - Liquidation rows use an ASIN in Amazon's SKU field. Sticky resolves that ASIN back to the catalog SKU/title and posts liquidation principal to the applicable brand child account.
accounting.non_posting_accountsblocks parent/control accounts at preview and posting time.400 Sales - Amazon FBA US(QBO id125) is explicitly non-posting.- Settlements spanning a calendar month are split into monthly journal
segments using
Amazon Carried Balances. The final segment posts the payout toGNTY Clearing 6153.
Historical groups that are no longer available from the Reports API use a second lossless path:
sync_financial_event_groups.pyrecords Amazon's exact group id, boundary, transfer date, beginning balance, and payout control total.pull_financial_transactions_by_group.pycalls Finances v2024-06-19 with aFINANCIAL_EVENT_GROUP_IDfilter and stores every compressed response page with a SHA-256 digest. Transfer transactions are retained as evidence but excluded from the next group's settlement activity.normalize_financial_transaction_groups.pyconverts the nested transaction breakdowns to settlement-report categories. It creates a beginning-balance component only when that amount is mathematically required to reconcile the group. Explicit reserve debits and credits map to A2X's Current Reserve and Previous Reserve categories.validate_financial_transaction_groups.pyrequires contiguous pages, matching hashes, unique transaction ids, and an exact group control total.generate_financial_group_journals.pyapplies the same account, brand, carry, non-posting, and QBO safety rules as report-based previews.
Amazon is retiring the legacy v0 financial-event-detail operation on
2026-08-28. Sticky uses v0 only to enumerate financial event groups and uses
the supported v2024-06-19 listTransactions operation for detail.
A2X handoff and recovered backlog¶
The cutoff is defined by source streams, not an arbitrary date:
- Final primary A2X journal:
A2XUS-01Mar-10Mar-441. - Final secondary A2X journal:
A2XUS-01Mar-11Mar-379. - First missing primary Amazon group starts
2025-03-10T16:02:06Z. - First missing secondary Amazon group starts
2025-03-12T06:49:24Z.
The post-A2X register contains 147 closed USD groups totaling $813,367.65. Calendar-month splitting produced 177 journal entries. On 2026-08-03, all 177 were posted and read back successfully as QBO journal entries 10535 through 10711. Every document number is unique, every posting attempt is verified, and no line uses non-posting QBO account 125. Automatic posting remains disabled. That sentence describes the August 3 backlog close. Migration 0051 later enables the separate fail-closed scheduled policy for new, exception-free eComHD batches.
Source coverage for those 177 previews is:
- 66 entries from 47 groups recovered wholly from Finances v2024-06-19.
- 71 entries from 61 groups whose legacy report rows were provisional and were replaced as preview inputs by exact Finances transactions.
- 40 entries from 39 lossless, exactly matched settlement reports.
Positive Amazon amounts become credits; negative amounts become debits. This produces the same accounting direction observed in Hemani Holdings' historical A2X journals for sales, fees, refunds, tax, reimbursements, reserves, storage, and settlement clearing.
Commands¶
Recover and validate the historical Finances source without contacting QBO:
/usr/bin/python3 scripts/sync_financial_event_groups.py \
--seller ecomhd_us --start 2025-03-01 --end 2026-07-31
/usr/bin/python3 scripts/pull_financial_transactions_by_group.py \
--seller ecomhd_us --unmatched-only
/usr/bin/python3 scripts/validate_financial_transaction_groups.py \
--seller ecomhd_us --unmatched-only
/usr/bin/python3 scripts/normalize_financial_transaction_groups.py \
--seller ecomhd_us --unmatched-only
/usr/bin/python3 scripts/generate_financial_group_journals.py \
--seller ecomhd_us --unmatched-only --dry-run
Use --match-method posted_dates_and_closest_total instead of
--unmatched-only for the 61 provisional legacy-report groups.
Generate and store the ten most recent previews:
Generate one preview without writing it:
/usr/bin/python3 scripts/generate_settlement_journals.py \
--seller ecomhd_us --settlement-id 27217869441 --dry-run
Inspect readiness:
SELECT settlement_id, document_number, status, clearing_amount,
reconciliation_difference, unmapped_source_amount
FROM accounting.journal_batches
ORDER BY transaction_date DESC;
Journal document numbers use STKUS-DDMon-DDMon-NNN. The five-character
prefix keeps the complete value within QuickBooks Online's 21-character
DocNumber limit.
Guarded QBO workflow¶
Show the exact journal request without contacting QBO:
Run read-only live checks against the RPP HH connection. This verifies the
source fingerprint, balance, active account ids/names, and absence of the
DocNumber in QBO:
/usr/bin/python3 scripts/post_settlement_journal.py \
--batch-id 47 --preflight \
--confirm-document STKUS-28Jul-30Jul-441
Approval and posting are separate commands. Approval records the reviewer, time, and exact payload hash:
/usr/bin/python3 scripts/post_settlement_journal.py \
--batch-id 47 --approve \
--approved-by '<reviewer>' \
--confirm-document STKUS-28Jul-30Jul-441
The later --post command requires the typed DocNumber again. It claims the
batch in Postgres before any external side effect, checks QBO for duplicates a
second time after the claim, sends one JournalEntry, and reads the entry back
by DocNumber. Attempts are stored in
accounting.journal_posting_attempts; approval, claim, POST, and readback
events are append-only in accounting.journal_posting_events.
A network timeout or QBO 5xx leaves the batch in posting with an ambiguous
attempt. It must be reconciled by DocNumber and is never retried blindly. A
successful POST is never automatically deleted if readback fails.
Production status and 2025 audit control¶
The recovered backlog was fully posted on 2026-08-03. The final checks found
177 stored batches, 177 QBO STKUS journals, 177 unique document numbers, 177
verified attempts, and zero unposted batches.
The scheduled fail-closed policy is now live for new eComHD work. A production check on 2026-08-26 found 193 stored batches through 2026-08-23, all 193 posted, 193 verified posting attempts, and no non-verified attempt. Exception batches remain ineligible for automatic posting.
For Sticky's post-A2X portion of 2025:
- 47 Amazon financial groups and 194,036 source transactions passed the raw page, hash, duplicate-id, and group-control validator with zero mismatches.
- Amazon transaction activity from 2025-03-10 through 2025-12-31 totaled $584,469.82. The actual non-control lines in the 61 QBO Sticky journals for 2025 total exactly $584,469.82.
- Amazon's signed payout controls for the 42 closed post-cutoff groups paid in 2025 totaled $563,965.04. The actual signed QBO clearing lines total exactly $563,965.04.
- Unmapped source amount and reconciliation difference are both zero.
The complete calendar-year audit is a bridge: retain the existing A2X journals through the two documented March cutoffs, then use Sticky from the first missing primary and secondary groups onward. The A2X-side January-to-cutoff audit remains separate from the proven Sticky post-cutoff totals above.