Audit and audited services¶
An audit is the aggregate record of how a bill's services were reviewed: the audit header carries bill-level totals and flags, each service on the bill gets its own audited-service line, each audited-service line can carry one or more payment adjustments, and the audit as a whole can accumulate error, warning, and informational messages. All four record types share the same bill-scoped lifecycle and the same rows-affected concurrency contract, and they are saved together whenever the audit is saved — either directly by a caller or as a cascade from Bill CRUD.
| Field | Value |
|---|---|
| Operation ID | OP-CB-02 |
| Trigger | clsBill.GenerateAudit() creates a new audit and its audited-service lines as part of a bill save; callers can also call clsAudit.NewAudit(...)/GetAudit(...) directly and edit the audited-service, adjustment, and message collections before calling Save() |
| Inputs | BillID; audit header fields (ChargeableCostFlag, PrintEobFlag, AuditReceiptDate, SpecialHandlingCode, total amounts); per-service audited fields (service/provider/date/amount/diagnosis/prescriber); adjustment code and amount per audited service; message category and text |
| Outputs | Populated clsAudit with its child collections on retrieve; persisted CBP_AUDIT, CBP_AUDITED_SERVICE, CBP_AUDITED_SERVICE_ADJUSTMENT, and CBP_AUDIT_MESSAGE rows on save; broken rules and DB-contention errors on failure |
| Primary components | clsAudit.NewAudit, clsAudit.GetAudit, clsAudit.OnSave, clsAuditedServiceCollection.NewAuditedService, clsAuditedServiceAdjustmentCollection.NewServiceAdjustment, clsAuditMessageCollection.NewMessage, clsAuditMessage.NewErrorMessage/NewWarningMessage/NewInformationMessage |
| Entry point | Business\SAIF.Business.Claim.Bill\Core\clsAudit.vb |
Steps¶
- Create a new audit.
clsAudit.Create()seedsBillIDfrom the criteria and creates empty child collections:clsAuditMessageCollection.NewMessageCollection,clsAuditedServiceAdjustmentCollection.NewAuditedServiceAdjustmentCollection, andclsAuditedServiceCollection.NewAuditedServiceCollection. - Retrieve an existing audit.
GetAudit(...)builds aCriteria(BillID)and retrieves throughMyCriteria.RetrieveSQL;AfterRetrieveloads the first row into the object, thenMarkOld(). - Insert the audit header.
BeforeInsert/AfterInsertwrite a single row intoCBP_AUDITwith the bill ID, flags, receipt date, special-handling code, and total amounts (SQL-003, CBP_AUDIT). - On a rows-affected value other than
1: add"Insert Failed"(BR-004). - Update the audit header.
BeforeUpdate/AfterUpdateupdateCBP_AUDITbyBILL_IDwith optimistic concurrency onUPDATE_NUM(SQL-032, CBP_AUDIT). - On a rows-affected value other than
1: add a DB-contention error (BR-004). - Delete the audit header.
BeforeDelete/AfterDeletedelete theCBP_AUDITrow for the bill (SQL-042, CBP_AUDIT); child collections are cleared rather than saved when the parent is deleted. - On a rows-affected value other than
1: add a DB-contention error (BR-004). - Stamp update fields (
OnSave).UpdateDate = NowandUpdateUserfrom the data-portal user are stamped on the header before every insert/update/delete. - Add a new audited-service line.
clsAuditedServiceCollection.NewAuditedService()auto-assigns the nextServiceIDasMax(existing) + 1(or1).NewAuditedService(inServiceID)instead requires an explicit service ID and first checks the collection for a duplicate. - If a line with that
ServiceIDalready exists: throw"Attempt to generate new Audit Service Line for service #<id> failed. - Service already exists."(BR-005). - Persist an audited-service line.
clsAuditedService.Create()seeds DPI,BillID,ServiceID, and update user. - Insert: writes the full audited-service row — service, provider, date, amount, diagnosis, and prescriber fields — into
CBP_AUDITED_SERVICE(SQL-004, CBP_AUDITED_SERVICE). - Update: updates nearly all service columns keyed by
BILL_ID + AUDITEDSERVICE_ID + UPDATE_NUM(SQL-033, CBP_AUDITED_SERVICE). - Delete: deletes by
BillIDandAuditedserviceID(SQL-043, CBP_AUDITED_SERVICE). - Each path enforces the shared concurrency rule (BR-004).
- Reference fields (claim bill type, original-bill code, bill status, diagnosis type) resolve through
mdlCBPSupportingDatacode maps, and service descriptions resolve through the linked service's description list.
Origin: The reference-code resolution (
GetClaimBillTypeCodeMap,GetOriginalBillCodeMap,GetBillStatusCodeMap,GetDiagnosisTypeCodeMap) is implemented bymdlCBPSupportingDatain this same library; the service-description lookup is implemented by Service reference lookups (clsServiceInfo.ServiceDescriptions). 9. Validate and track dirtiness across the aggregate.clsAuditedService.IsValid()validates its own state together with its nested adjustment collection and returnsErrorCount = 0;IsDirty()folds in the adjustment collection's dirty state, so a dirty adjustment makes its parent audited-service line dirty too. 10. Add a new service-level adjustment.clsAuditedServiceAdjustmentCollection.NewServiceAdjustment(...)creates the child viaclsAuditedServiceAdjustment.NewAuditedServiceAdjustment(...), sets the adjustment code and amount, and adds it to the list.clsAuditedServiceAdjustment.Create()seedsBillIDandAuditServiceID. - Insert: writes the adjustment row intoCBP_AUDITED_SERVICE_ADJUSTMENT(SQL-005, CBP_AUDITED_SERVICE_ADJUSTMENT). - Update: updates code/amount keyed byBILL_ID + AUDITSERVICE_ID + CODE + UPDATE_NUM(SQL-034, CBP_AUDITED_SERVICE_ADJUSTMENT). - Delete: byBillID,AuditServiceID, and adjustment code (SQL-044, CBP_AUDITED_SERVICE_ADJUSTMENT). - Each path enforces the shared concurrency rule (BR-004). -SettlementGroup,AdjustmentType, andAuditedAdjustmentCategoryall resolve throughmdlCBPSupportingDatareference maps (SQL-011, SQL-013). 11. Add a new audit message.clsAuditMessageCollection.NewMessage(...)optionally creates a temporary read-only in-memory message (assigning the next localMessageID) before always replacing it with a persisted-style object created viaNewWarningMessage,NewInformationMessage, orNewErrorMessage, which is then added to the collection. -Add(Item)on the collection is blocked directly and throws"Status can only be added via a Bill"* — the same guard text used byclsBillStatusCollection, so new messages can only be introduced through the factory methods. 12. Persist an audit message.clsAuditMessage.Create()assignsBillID, allocatesMessageIDthroughGetLegacyID(...)(legacy CBP sequence,CBPIDType.AuditError), sets the category, and sets the message text. - Insert: writes the message row intoCBP_AUDIT_MESSAGE(SQL-006, CBP_AUDIT_MESSAGE). - Update: updates text/category keyed byMESSAGE_ID + BILL_ID + UPDATE_NUM(SQL-035, CBP_AUDIT_MESSAGE). - Delete: byMessageIDandBillID(SQL-045, CBP_AUDIT_MESSAGE). - Each path enforces the shared concurrency rule (BR-004).
> **Origin**: `MessageID` allocation reuses the same `GetLegacyID` / `GetNextCBPSeqNum` sequence path as [Bill CRUD](bill-crud.md) step 1, calling the Oracle procedure `sp82385_get_next_bill_seqnum` with `CBP_AUDIT_ERROR`.
- Complete the save.
OnSaveComplete()on the audit header saves the audited-service, adjustment, and message collections after the header itself is inserted, updated, or deleted; if the audit was deleted, the child collections are cleared instead of saved.
Process flow¶
The following diagram visualizes how an audit and its three child record types are validated and persisted together.
flowchart TD
Start([Bill save triggers GenerateAudit,<br>or caller edits audit directly]) --> Header[Create/retrieve<br>Audit header]
Header --> HeaderSave[Insert/Update/Delete CBP_AUDIT]
HeaderSave --> Rows{RowsAffected = 1?}
Rows -->|No| Contention([Contention error])
Rows -->|Yes| Services[For each bill service:<br>NewAuditedService]
Services --> Dup{ServiceID already<br>on audit?}
Dup -->|Yes| DupErr([Duplicate-service exception])
Dup -->|No| SaveService[Insert/Update/Delete<br>CBP_AUDITED_SERVICE]
SaveService --> Adjust[Optional: NewServiceAdjustment<br>per audited service]
Adjust --> SaveAdjust[Insert/Update/Delete<br>CBP_AUDITED_SERVICE_ADJUSTMENT]
SaveService --> Messages[Optional: NewMessage<br>error / warning / information]
Messages --> SaveMsg[Insert/Update/Delete<br>CBP_AUDIT_MESSAGE]
SaveAdjust --> Done([Save returns success])
SaveMsg --> Done
Failure and edge-case behavior¶
- All four record types (audit header, audited service, adjustment, message) share the identical rows-affected concurrency contract; the caller cannot distinguish which table failed from the error text alone (BR-004).
- Adding a duplicate
ServiceIDto an audit throws immediately rather than returning a broken-rule collection entry, so callers must catch the exception or pre-check for an existing line (BR-005). - Deleting the audit header clears rather than saves its child collections, so a deleted audit never leaves orphaned or stale audited-service, adjustment, or message rows from the same save cycle.
clsAuditMessageCollection.Add()reuses the exact guard message text fromclsBillStatusCollection("Status can only be added via a Bill"), which does not describe audit messages — this appears to be copied guard text rather than a message-specific string.*clsAuditMessagefieldUpdateNumer(notUpdateNumber) is used in several places in source; this spelling is preserved here only to describe the code accurately, not as a documentation error.*
Related documentation¶
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
Sources¶
Business\SAIF.Business.Claim.Bill\Core\clsAudit.vbBusiness\SAIF.Business.Claim.Bill\Core\clsAuditCollection.vbBusiness\SAIF.Business.Claim.Bill\Core\clsAuditedService.vbBusiness\SAIF.Business.Claim.Bill\Core\clsAuditedServiceCollection.vbBusiness\SAIF.Business.Claim.Bill\Core\clsAuditedServiceAdjustment.vbBusiness\SAIF.Business.Claim.Bill\Core\clsAuditedServiceAdjustmentCollection.vbBusiness\SAIF.Business.Claim.Bill\Core\clsAuditMessage.vbBusiness\SAIF.Business.Claim.Bill\Core\clsAuditMessageCollection.vbBusiness\SAIF.Business.Claim.Bill\AuditSupport\BillStatus.vbBusiness\SAIF.Business.Claim.Bill\AuditSupport\BillType.vbBusiness\SAIF.Business.Claim.Bill\AuditSupport\OriginalBills.vbBusiness\SAIF.Business.Claim.Bill\AuditSupport\mdlCBPSupportingData.vb