Coding Question 45 minutesMedium
CRM Billing Synchronizer
Build an accurate, efficient sync across two changing systems. The CRM is the source of truth.
Question
Implement the synchronization function in sync.py. Read every customer, contract, and file from the CRM, then create or update the corresponding records in Billing. The CRM is the source of truth, and the grader will run your function twice with CRM changes between runs.
Function parameters
- crm
- A CrmApi object used to list and fetch CRM customers, contracts, and files.
- billing
- A BillingApi object used to find, create, and update Billing records and upload files.
Inputs and API responses
CRM
| Entity | Fields |
|---|---|
| Customer | id, name, city |
| Contract | id, customer_id, name, close_date |
| File | id, contract_id, file_name |
- These are Python dictionaries returned by the mock API, not JSON strings or direct database rows.
- A Customer has many Contracts.
- A Contract has many Files.
- file_name can be None.
crm.list_customers(limit=10, offset=0)
→ [{"id": "crm_cust_1", "name": "Customer 1", "city": "Austin"}, ...]
crm.list_contracts(limit=10, offset=0)
→ [{"id": "crm_cont_1", "customer_id": "crm_cust_1", "name": "Contract 1", "file_ids": ["crm_file_1"]}, ...]
crm.get_file("crm_file_1")
→ {"id": "crm_file_1", "contract_id": "crm_cont_1", "file_name": "file_1.pdf"}Billing
| Entity | Fields |
|---|---|
| Customer | id, external_id, name, city |
| Contract | id, external_id, customer_id, file_name |
- Each named CRM File becomes one Billing Contract.
Critical mapping
- Billing Customer.external_id = CRM Customer ID
- Billing Contract.external_id = CRM File ID, not Contract ID
Requirements
- Edit sync.py; it is the only writable file.
- Paginate all list endpoints; maximum limit is 10.
- Create and update Billing customers from CRM.
- Each CRM file with a file_name becomes exactly one Billing contract.
- Skip files whose file_name is None; they may become eligible on a later run.
- Create the Billing contract and upload its file as separate API calls.
- Treat find-method results as lists.
- Handle changes and retries on the second run without creating duplicate customers or contracts.
- Accuracy matters most; API efficiency breaks ties.
Editable
Test output
Run the challenge to test initial and incremental sync.