CodeRigor

FREE LESSON

Capstone: clean, merge and reconcile

Compose an offline CSV/JSON sales pipeline with deterministic row provenance, rejection ledgers and reconcilable totals.

The capstone combines a sales CSV with a customer JSON export. It is small enough to inspect by hand, but deliberately contains the errors that make real pipelines misleading: inconsistent whitespace, bad dates, malformed currency, repeated ids, conflicting customer names and sales whose customer is absent. The goal is a useful report plus enough evidence to explain its scope.

The supplied helpers handle record boundaries and strict value parsing. You compose them into a deterministic policy called sales-v1. Successful output is JSON-serializable and preserves source order. It does not fetch files, call an API or establish the factual truth of the sales. The exact same local inputs should produce the exact same decisions and totals on every run.

Two sources, two ledgers, one explicit merge
start / 2
Every source row has an accepted or rejected destination before totals are calculated.
Two sources, two ledgers, one explicit merge
Every source row has an accepted or rejected destination before totals are calculated.

Separate envelope errors from record errors

A ragged CSV record or duplicate JSON member makes the document ambiguous and raises ValueError. A well-formed row with an impossible date is different: append its source position and first error code to sales_errors, then continue. Use data-record positions excluding the header. A quoted newline does not create a second data record, so physical line numbers are the wrong provenance here.

Normalize and validate a row before reserving its id. An invalid early sale must not prevent a later valid sale with that id from being kept. Compare repeated valid ids using the complete normalized business payload: amount spellings 2, 2.0 and $2.00 all become 200 cents and can be duplicates. Adding source_row before comparison would make every repetition appear different.

Python
sales = [{'cents': 500, 'customer_name': 'Ada'},
         {'cents': 225, 'customer_name': None},
         {'cents': -100, 'customer_name': 'Ada'}]
total = sum(row['cents'] for row in sales)
matched = sum(row['cents'] for row in sales if row['customer_name'] is not None)
print(total, matched)

The total is 625 cents; matched sales total 400 cents. The unmatched amount is valid evidence even though enrichment failed. Negative sales are refunds under this contract. Observed zero amounts must remain in the rows and accepted count.

Reconcile counts before trusting totals
start / 2
A rejection and an unmatched accepted row are different states.
Reconcile counts before trusting totals
A rejection and an unmatched accepted row are different states.

Make the report reviewable

Return customer and sale ledgers separately, keep original sale positions in source_row, and list unmatched source positions. Summary counts must reconcile accepted and rejected rows for each source independently. Do not use the post-filtered output index as a source position: after a rejected row, those numbers diverge. The policy identifier helps a reviewer distinguish future rule changes from changed source data.

Serialize with json.dumps(report, sort_keys=True, allow_nan=False) when an external representation is needed. Exact integer cents avoid rounding in totals. A production tool would additionally identify immutable input bytes, document sensitive-data handling, version the code and record an output destination. Those extensions require their own tests; a local fixture is evidence only for the contracts it exercises.

Before submitting, trace a bad first occurrence followed by a valid repeat, a customer conflict, an unmatched refund and a quoted multiline field. Explain which source row each ledger entry refers to. Then verify both count equations and independently recompute total and matched cents from the returned rows.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Review 57:13–1:23:00 for the CSV import/export workflow. Build the audit ledger and reconciliation from the authored contract; the capstone extends the lecture into a tested cleaning pipeline.