Agency, agent, and provider customer resolution¶
mdlCustomerContact resolves agency, agent, and provider identifiers from source reference tables into local clsCustomer/clsContact records, caching the mapping in CUSTOMER_AGENCY, CUSTOMER_AGENT, or CUSTOMER_PROVIDER so future lookups skip record creation. These three flows are grouped on one page because agent resolution directly calls agency resolution, and all three apply the same source-effective/expiration-date check to decide whether the generated local record should be created inactive.
| Field | Value |
|---|---|
| Operation ID | OP-CC-09 |
| Trigger | mdlCustomerContact.GetCustomerInfoForAgent(dpi, agentID, create) or mdlCustomerContact.GetCustomerIDForProvider(dpi, providerID) |
| Inputs | AgentID (resolves its owning AgencyID first), AgencyID, or ProviderID; optional create flag (agent/agency path only) |
| Outputs | AgentInfo (agency/agent customer and contact IDs) or a provider CustomerID; newly created COMPANY/PERSON rows and their CUSTOMER_AGENCY/CUSTOMER_AGENT/CUSTOMER_PROVIDER mapping rows when no mapping existed |
| Primary components | mdlCustomerContact.GetCustomerInfoForAgent, mdlCustomerContact.CreateAgency, mdlCustomerContact.CreateAgent, mdlCustomerContact.GetCustomerIDForProvider |
| Entry point | Business\SAIF.Business.CustomerContact\mdlCustomerContact.vb |
Steps¶
- Resolve an agent's owning agency.
GetCustomerInfoForAgent(dpi, agentID, create)readsAGENTto find the agent'sAgencyID(SQL-063, AGENT). If no agency ID is found,GetCustomerInfoForAgentreturns anAgentInfowith a zeroAgencyCustomerIDand does not attempt agent creation. - Resolve or create the agency customer (
CreateAgency). - Look up an existing mapping in
CUSTOMER_AGENCYfor the agency ID (SQL-047, CUSTOMER_AGENCY). - If none exists and
createis true: readAGENCYfor the source record (SQL-046, AGENCY), then build a newclsCustomerwithCustomerTypeCode = "AGNCY",InternalReferenceIDset to the agency ID,CustomerNamefromagency_name, andTaxIDfromagency_feid. - Determine active status (BR-008): if
agency_exp_dateis empty andagency_eff_dateis in the future, or ifagency_exp_dateis in the past, setCust.IsActive = Falsebefore saving. - Save the new customer (SQL-018 inserts the
CUSTOMER_AGENCYmapping row, CUSTOMER_AGENCY, after theCOMPANYrow itself saves through Customer CRUD with child persistence).- On a mapping-insert row count ≠ 1: roll back by calling
Cust.Delete()andCust.Save(), leavingCustID = 0.
- On a mapping-insert row count ≠ 1: roll back by calling
- Resolve or create the agent contact (
CreateAgent). - Look up an existing mapping in
CUSTOMER_AGENTfor the agent ID (SQL-049, CUSTOMER_AGENT).- Uncertain / likely defect: the lookup query binds
inAgentInfo.AgencyIDto theagent_num = :IDfilter instead of the agent's own ID, which could return the wrong (or no) mapping when agency and agent identifiers differ.*
- Uncertain / likely defect: the lookup query binds
- If none exists and
createis true: ensure the agency customer exists viaCreateAgency(...)(step 2), then readAGENTfor the source record (SQL-048, AGENT). - Add a new
clsCustomerContactunder the agency customer'sContactswithRelationshipCode = "AGENT"andTitleset fromagent_name; set the contact'sAlternateName,EffectiveDate, and (if present)ExpirationDate. - Determine active status (BR-008): if
EffectiveDateis in the future, or a realExpirationDatehas already passed, setContact.IsActive = False. - Save the customer cascade — this persists the new
PERSONrow and theCOMPANY_PERSONrelationship (see Customer-contact relationship CRUD) — then insert theCUSTOMER_AGENTmapping row (SQL-019, CUSTOMER_AGENT).- On a mapping-insert row count ≠ 1: roll back by removing the new contact from
Cust.Contactsand re-saving, leaving the agent unresolved.
- On a mapping-insert row count ≠ 1: roll back by removing the new contact from
- Resolve or create the provider customer.
GetCustomerIDForProvider(dpi, providerID): - Look up an existing mapping in
CUSTOMER_PROVIDERfor the provider ID (SQL-059, CUSTOMER_PROVIDER). - If none exists: read
PROVIDERjoined toPROVIDER_TAX_IDon the provider's primary tax ID (SQL-060, PROVIDER, PROVIDER_TAX_ID), and build a newclsCustomerwithCustomerTypeCode = "MPROV",CustomerNamefromregistered_name, andTaxIDfromprimary_tax_id. - Determine active status (BR-008): the same effective/expiration date check as agency resolution sets
Cust.IsActive = Falsewhen the source tax-ID record is not currently effective. - Provider address creation code exists in source but is commented out, so no address is created from the provider's registered address even when the customer is active.*
- Save the new customer, then insert the
CUSTOMER_PROVIDERmapping row (SQL-024, CUSTOMER_PROVIDER).- On a mapping-insert row count ≠ 1: roll back by calling
Cust.Delete()andCust.Save(), leavingCustID = 0.
- On a mapping-insert row count ≠ 1: roll back by calling
Process flow¶
The following diagram visualizes the agency → agent chain and the parallel provider flow.
flowchart TD
Start([GetCustomerInfoForAgent]) --> AgentAgency[Read AGENT to find AgencyID]
AgentAgency --> AgencyFound{AgencyID > 0?}
AgencyFound -->|No| ReturnEmpty([Return AgentInfo with no customer])
AgencyFound -->|Yes| CreateAgent[CreateAgent]
CreateAgent --> AgentMapped{CUSTOMER_AGENT<br>mapping exists?}
AgentMapped -->|Yes| ReturnAgent([Return existing customer/contact IDs])
AgentMapped -->|No, create=true| CreateAgency[CreateAgency]
CreateAgency --> AgencyMapped{CUSTOMER_AGENCY<br>mapping exists?}
AgencyMapped -->|Yes| AgencyReady
AgencyMapped -->|No, create=true| ReadAgency[Read AGENCY; check dates;<br>save new COMPANY; insert mapping]
ReadAgency --> AgencyReady[AgencyCustomerID resolved]
AgencyReady --> ReadAgent[Read AGENT; add clsCustomerContact<br>RelationshipCode=AGENT; check dates]
ReadAgent --> SaveAgent[Save customer cascade;<br>insert CUSTOMER_AGENT mapping]
SaveAgent --> RowsAgent{Mapping insert rows = 1?}
RowsAgent -->|No| RollbackAgent([Remove contact; re-save; unresolved])
RowsAgent -->|Yes| ReturnAgent
StartP([GetCustomerIDForProvider]) --> ProviderMapped{CUSTOMER_PROVIDER<br>mapping exists?}
ProviderMapped -->|Yes| ReturnProvider([Return existing CustomerID])
ProviderMapped -->|No| ReadProvider[Read PROVIDER + PROVIDER_TAX_ID;<br>check dates; save new COMPANY]
ReadProvider --> InsertProviderMap[Insert CUSTOMER_PROVIDER mapping]
InsertProviderMap --> RowsProvider{Rows = 1?}
RowsProvider -->|No| RollbackProvider([Delete and re-save; CustID = 0])
RowsProvider -->|Yes| ReturnProvider
Failure and edge-case behavior¶
- All three creation paths roll back the newly created
clsCustomer(or, for agent, remove the new contact) when the mapping-table insert fails, so a failed mapping insert never leaves an orphaned mapping-less customer withCustIDreported as non-zero — but the customer/contact row itself may still exist in an unmapped state pending garbage collection by a later process.* - Generated agency, agent, and provider records can be persisted inactive from the moment of creation when the source effective/expiration dates indicate the relationship is not currently in force (BR-008).
- The
CreateAgentexisting-mapping lookup is suspected to bind the wrong identifier (AgencyIDinstead of the agent's own ID) to itsagent_numfilter, which could cause repeated re-creation attempts or a false match against an unrelated agent record.* - Provider address creation is present in source as commented-out code, so provider-based customers are never given an address through this flow even though the query already retrieves address fields.*
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
Related documentation¶
Sources¶
Business\SAIF.Business.CustomerContact\mdlCustomerContact.vbBusiness\SAIF.Business.CustomerContact\AgentInfo.vb