Booking — Booking Reconciliation (roll call reconciliation)
Booking Reconciliation compares the actual roll call of a session (
TermAttendance) with the booked schedule: a child arrived early, was picked up late, or was absent. When the gap exceeds the grace threshold, the system generates a surcharge (invoice) or a refund (credit note) according toBookingReconciliationRule.
Unlike regular billing (generated from a confirmed booking), reconciliation reads the actual attendance after sign in/out, then issues the supplementary documents. Source file: Tux/src/Services/Tux.Service/BookingReconciliationService.cs; stored proc spBooking_GetBookingReconciliation; enums Tux/src/Tux.Core/Enums/BookingReconciliationType.cs.
Reconciliation types (BookingReconciliationType)
| Type | Code | When it triggers |
|---|---|---|
Early | 1 | Arrived earlier than TimeStart (early drop-off). |
Late | 2 | Picked up later than TimeEnd (late pickup). |
Absent | 3 | Absent (Absent/AbsentBatch). |
Refund | 4 | Fee refund. |
Reconciliation status (BookingReconciliationStatus)
Stored on TermAttendance.ReconciliationStatusId:
| Status | Code | Meaning |
|---|---|---|
Unreconciled | 0 | Not yet processed (potential candidate). |
Ignored | 1 | Skipped, no documents generated. |
Invoiced | 2 | Invoice generated. |
Credited | 3 | Credit note generated. |
SystemReconciled | 4 | Handled automatically by the system. |
Configuration: BookingReconciliationRule
The rule attaches at Business Unit level (scoped by OrgId/ProgramId/TypeId); Program points to it via Program.BookingReconciliationRuleId. A JSON blob holds the fee/refund details.
| Field | Meaning |
|---|---|
EarlyFeeEnabled / EarlyFeeGracePeriod | Enables the early-arrival fee + grace threshold (minutes). |
LateFeeEnabled / LateFeeGracePeriod | Enables the late-pickup fee + grace threshold (minutes). |
RefundEnabled | Enables the refund when absent. |
ReconciliationRuleBlob | JSON of BookingReconciliationChargeRuleModel (Early/Late/Refund). |
Each charge rule (BookingReconciliationChargeRuleModel) contains:
| Field | Meaning |
|---|---|
GracePeriod | Grace period (Early/Late only). |
ChargeCap | Fee cap. |
SessionRefundRate / EnrichmentRefundRate | Refund rate by session / add-on (Refund only). |
AdminAbsenceFee | Fixed fee per absent session (applied to the session line). |
DescriptionTemplate / ReferenceTemplate | Description & reference of the document line. |
ChargeRuleLines | The fee brackets (BookingReconciliationChargeRuleLineModel). |
Each rule line has a RangeTypeId (Relative=0 by minutes from the booked time / Absolute=1 by absolute time, Late only), Start/End, ChargeType (Per_X_Minute=1, Fixed=2), ChargeUnit, and ChargeRate.
Real-world example: A BU configures a session ending at 15:00,
LateFeeGracePeriod = 15, fee$1.5/minute. → Charge when a parent picks up late. → A child picked up at 17:00 → 120 minutes late, minus grace leaves 105 minutes → the invoice line "Late Pickup Charge" is computed per the rule brackets.
Selecting candidates (stored proc)
spBooking_GetBookingReconciliation selects TermAttendance records that satisfy all of:
IsActive = 1,ReconciliationStatusId = Unreconciled(0), within the date range, part of the Business Unit's active Term.TypeId ∈ { Booking(0), ClosureDay(9), Subscription(4) }.- Conditions by type:
| Type | Roll call condition | Time condition |
|---|---|---|
Early | EarlyFeeEnabled; status ∈ {In_SignedOut 50, SignedOut 60, In_SignedOutBatch 70, SignedOutBatch 80} | DATEDIFF(MINUTE, ActualTimeStart, TimeStart) > EarlyFeeGracePeriod |
Late | LateFeeEnabled; status ∈ | DATEDIFF(MINUTE, TimeEnd, ActualTimeEnd) > LateFeeGracePeriod |
Refund | RefundEnabled; status ∈ {Absent 30, AbsentBatch 40} | — |
⚠️ Only attendance that has signed out is a fee candidate (late pickup/early return). A session still signed in but not signed out is not ready for reconciliation — it is left out.
Real-world example: At the weekend ops clicks "Run Reconciliation" for a date range. → Gather the sessions where children were picked up late / arrived early / were absent for fee review. → The candidate list only includes signed-out attendance still
Unreconciled, not sessions where children are still present.
Reconciling (ReconcileAttendancesAsync)
Grouping & split rules (use ProgramCategory.InvoiceSplitRuleId):
| Split rule | Code | Groups by |
|---|---|---|
Account | 1 | The whole group (default). |
Attendee | 2 | Each attendee. |
Course | 3 | Each TermProgramSet. |
Attendee_Course | 4 | Each attendee × TermProgramSet pair. |
Processing constraints:
- One batch = one status: every model must share the same
StatusId; mixed statuses or an empty list →INVALID_MODEL_STATE. - Same Org: every attendance in the batch must share the same
OrgId. - Tax required: the BU must configure
DefaultTaxRateId+ an active TaxRate, otherwise →DEFAULT_TAX_RATE_NOT_FOUND. Tax is computed perLineAmountType(TaxInclusive/TaxExclusive/NoTax). Ignoredis simple: setReconciliationStatusId = Ignored,ReconciliationAmount = 0, generate no documents.- One attendance can produce multiple lines (multiple credit notes) when the model holds several items for the same session.
Generated documents
| Output | Value |
|---|---|
Invoice / CreditNote TypeId | BookingReconciliation (3). |
Line TypeId | BookingReconciliation (3), Quantity = 1, UnitPrice = ReconciliationAmount. |
ConfirmationTypeId | Admin_Confirm (401). |
PaymentOptionId | Inherited from the original booking's Billing. |
| Attendance after invoice | ReconciliationStatusId = Invoiced, ReconciliationAmount = line total. |
| Attendance after credit note | ReconciliationStatusId = Credited, ReconciliationAmount = −line total. |
Post-processing:
- Writes
TermBookingInvoiceLog/TermBookingCreditNoteLogper line (linkingTermBookingId,TermBookingLineId) so the Booking ID resolves on FinanceTransaction. - Schedules
SyncFinanceTransaction(Sync_Invoice_BookingNumbers/Sync_CreditNote_BookingNumbers) to refresh the projection booking numbers. - Creates
InvoiceScheduler/CreditNoteScheduler(statusReady) and sends the entity eventsCreate_Invoice_BookingReconciliation/Create_CreditNote_BookingReconciliation.
Key points
- Reconciliation reads the actual attendance and generates a surcharge invoice or a refund credit note — it does not modify the booking's original invoice.
- The grace threshold & fee amounts come from
BookingReconciliationRule; candidates only count attendance that has signed out and is stillUnreconciled. Ignoredis a valid ops choice (no documents generated), even for attendance that was once a fee candidate.- Tax required: missing
DefaultTaxRateId→ the whole batch fails before persisting.
Next: Data & external links.