Transactions and Sync
Atomic split sequence, Elasticsearch synchronization, Redis status, and post-transaction audit behavior.
š¤ Sachin Sharmaš
Updated: May 2, 2026š·ļø featureš·ļø backendš·ļø transactionš·ļø elasticsearchš·ļø redisš·ļø activity-log
Transaction behavior
All DB writes for the split run inside transaction.atomic(). If any step fails, the full transaction rolls back and no partial split state remains.
A) Pre-transaction calculations
Before entering the transaction, the backend prepares in-memory objects:
- Compute split-side financials (
get_bill_calculations()). - Update parent bill values by subtracting split values (
update_original_bill(...)). - Prepare split bill object (
get_split_bill(new_source, calculations)):- generate new
labBillId - set default and computed billing attributes
- apply insurance-field reset when destination source is non-insurance
- set
orderNumberby appending~{step}to the parent bill's order number
- generate new
B) In-transaction operations (execution order)
- Persist split bill (
split_bill.save()). - Persist updated parent bill (
original_bill.save()). - Create zero-amount payment bootstrap (
create_payment(split_bill)). - Create conditional sample clones (
create_collected_sample()). - Shift report relations and sample mapping (
shift_lab_reports(...)). - Shift selected billing lines (
shift_update_billing_info(...)). - Copy bill approval row if present (
create_bill_approval(...)). - Migrate AOE responses and patient consents (
create_shift_consents(...)). - Copy unresolved missing-details rows if present (
create_missing_details(...)). - Shift and copy ICD rows (
shift_create_billing_icd(...)). - Process attachments (
create_shift_attachments(...)). - Shift org test count ledger rows (
shift_org_test_count_ledger(...)). - Shift and copy billing modifiers (
shift_create_billing_modifiers(...)). - Clone symptoms relation rows (
create_symptoms_user_bill_relation(...)).
Consent and AOE migration (step 8)
create_shift_consents handles two form types: AOE and patient consent.
AOE (create_shift_aoe)
- Bill-level AOE ā cloned to the split bill. A new
QuestionValuerow is created with the split bill as the owner. - Test/Profile-level AOE ā shifted to the split bill. The existing
QuestionValuerow is updated to reference the split bill if the linkedlabReportIdis in the set of moved reports. - Promotion/Store-level AOE ā not handled; left on the parent bill.
Patient Consent (create_shift_patient_consent)
- A new
LabFormrecord is created for the split bill (cloned from the parent, with a newlab_form_slugUUID). Revoked forms are excluded. - Patient/Bill-level
LabFormLinkedProcessesā cloned and linked to the newLabForm. - Test/Profile-level
LabFormLinkedProcessesā shifted to the newLabFormwhen the linkedprocess_idmaps to one of the moved tests. QuestionValueresponses for moved reports ā shifted (FK update) to reference the split bill.QuestionValueresponses for non-moved (patient/bill-level) ā cloned to the split bill.
Post-transaction updates
These run after a successful commit. A failure here does not roll back the split.
Elasticsearch synchronization
- Re-index moved
LabReportRelationdocuments inpatient_reports. - Bulk update uses
labReportIdas the document key, preserving report identity while updating bill context. - After ES sync, each report broadcasts a
patient_reportsevent via Pusher. - A
getLatestSamplesPusher event is sent per moved sample for live UI refresh.
Redis cache invalidation
Billing-level keys (always):
FINANCE_GRAPH_{lab_id}bill_companies_{lab_id}billing_services_{lab_id}COLLECTION_GRAPH_{lab_id}FINANCE_EXCEPTIONS_{lab_id}
Batch/sample-level keys (when new samples were created):
centreBatch_{batch_id}centreBatch_{batch_id}_Pending
Organization ledger update
A Fusion webhook is sent to /manageLedgerBalance/ with a negative-amount entry for the split bill:
amount=-split_bill.billTotalAmountnote_entry=truefor PREPAID organisations;falsefor POSTPAID- Payload includes lab, org, bill, amount, actor context, and a comment identifying the originating parent bill
- Only executed when
organization.manageLedgeris enabled
Activity and audit logging
- Write
ActivityLogwithlog_context = BILL_SPLITand billing category for the split bill (category id3). - Write a second
ActivityLogfor the parent bill (category id17) recording the update caused by the split. - Log payload includes bill-level diff data, original and split bill IDs and
labBillIds, and movedBillingInfoIDs.