Skip to content

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

  1. Resolve an agent's owning agency. GetCustomerInfoForAgent(dpi, agentID, create) reads AGENT to find the agent's AgencyID (SQL-063, AGENT). If no agency ID is found, GetCustomerInfoForAgent returns an AgentInfo with a zero AgencyCustomerID and does not attempt agent creation.
  2. Resolve or create the agency customer (CreateAgency).
  3. Look up an existing mapping in CUSTOMER_AGENCY for the agency ID (SQL-047, CUSTOMER_AGENCY).
  4. If none exists and create is true: read AGENCY for the source record (SQL-046, AGENCY), then build a new clsCustomer with CustomerTypeCode = "AGNCY", InternalReferenceID set to the agency ID, CustomerName from agency_name, and TaxID from agency_feid.
  5. Determine active status (BR-008): if agency_exp_date is empty and agency_eff_date is in the future, or if agency_exp_date is in the past, set Cust.IsActive = False before saving.
  6. Save the new customer (SQL-018 inserts the CUSTOMER_AGENCY mapping row, CUSTOMER_AGENCY, after the COMPANY row itself saves through Customer CRUD with child persistence).
    • On a mapping-insert row count ≠ 1: roll back by calling Cust.Delete() and Cust.Save(), leaving CustID = 0.
  7. Resolve or create the agent contact (CreateAgent).
  8. Look up an existing mapping in CUSTOMER_AGENT for the agent ID (SQL-049, CUSTOMER_AGENT).
    • Uncertain / likely defect: the lookup query binds inAgentInfo.AgencyID to the agent_num = :ID filter instead of the agent's own ID, which could return the wrong (or no) mapping when agency and agent identifiers differ.*
  9. If none exists and create is true: ensure the agency customer exists via CreateAgency(...) (step 2), then read AGENT for the source record (SQL-048, AGENT).
  10. Add a new clsCustomerContact under the agency customer's Contacts with RelationshipCode = "AGENT" and Title set from agent_name; set the contact's AlternateName, EffectiveDate, and (if present) ExpirationDate.
  11. Determine active status (BR-008): if EffectiveDate is in the future, or a real ExpirationDate has already passed, set Contact.IsActive = False.
  12. Save the customer cascade — this persists the new PERSON row and the COMPANY_PERSON relationship (see Customer-contact relationship CRUD) — then insert the CUSTOMER_AGENT mapping row (SQL-019, CUSTOMER_AGENT).
    • On a mapping-insert row count ≠ 1: roll back by removing the new contact from Cust.Contacts and re-saving, leaving the agent unresolved.
  13. Resolve or create the provider customer. GetCustomerIDForProvider(dpi, providerID):
  14. Look up an existing mapping in CUSTOMER_PROVIDER for the provider ID (SQL-059, CUSTOMER_PROVIDER).
  15. If none exists: read PROVIDER joined to PROVIDER_TAX_ID on the provider's primary tax ID (SQL-060, PROVIDER, PROVIDER_TAX_ID), and build a new clsCustomer with CustomerTypeCode = "MPROV", CustomerName from registered_name, and TaxID from primary_tax_id.
  16. Determine active status (BR-008): the same effective/expiration date check as agency resolution sets Cust.IsActive = False when the source tax-ID record is not currently effective.
  17. 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.*
  18. Save the new customer, then insert the CUSTOMER_PROVIDER mapping row (SQL-024, CUSTOMER_PROVIDER).
    • On a mapping-insert row count ≠ 1: roll back by calling Cust.Delete() and Cust.Save(), leaving CustID = 0.

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 with CustID reported 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 CreateAgent existing-mapping lookup is suspected to bind the wrong identifier (AgencyID instead of the agent's own ID) to its agent_num filter, 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.

Sources

  • Business\SAIF.Business.CustomerContact\mdlCustomerContact.vb
  • Business\SAIF.Business.CustomerContact\AgentInfo.vb