QuickBooksOnline - Customer Update
This function synchronizes customer data from QuickBooks Online to the App4Sales platform. It processes core customer information, associated addresses, contact persons, item class discounts, and customer-specific dashboards. The update runs in batches and incorporates various data transformations, validations, and conditional logic to ensure data integrity and consistency within App4Sales.
Data Source Configuration
Customer data is primarily received as a list of Customer objects from the QuickBooks Online connector. This data is typically pre-processed by the connector before being passed to this update handler.
Additionally, supplementary customer data (ExtraCustomerData) can be loaded, potentially from CSV files or a similar flat-file source, which provides extra fields that can override or extend the main customer properties.
Data Mapping Table: Customer
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
CustomerCode | Customer.CustomerCode | Mandatory. Used as a unique identifier. |
CustomerName | Customer.CustomerName | Mandatory. Display name for the customer. |
CustomerGuid | Customer.CustomerGuid | Unique identifier for the customer within App4Sales.
|
Created | Customer.Created | Timestamp of customer creation.
|
Sysmodified | Customer.Sysmodified | Timestamp of last modification. Truncated to seconds (milliseconds removed). |
PasswordWebshop | Customer.PasswordWebshop | Set to |
CustomerDashboard | Customer.CustomerDashboard | Base64 encoded dashboard layout.
|
LanguageCode | Customer.LanguageCode | Mapped language code.
|
ActionPriceList | Customer.ActionPriceList | ID of the action price list to apply.
|
PaymentConditionCode | Customer.PaymentConditionCode | Set to |
Customer.Email | Trimmed for whitespace. | |
DynamicFreeFields | Customer.DynamicFreeFields | XML payload containing extra ERP data.
|
VatCode | Customer.VatCode | Set to |
VatLiable | Customer.VatLiable | Set to |
FreeFields | Derived / CsvCustomer.UnknownElements | XML representation of custom free fields.
|
ItemFilter | Derived / CsvCustomer.UnknownElements | Defines a fixed item filter for the customer.
|
CustomerNote | Customer.CustomerNote | Customer-specific note.
|
InternalCode | Customer.InternalCode | ERP-specific internal code.
|
ExtraData | Customer.ExtraData | Additional extra data for the customer.
|
Data Mapping Table: Address
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
CustomerGuid | Customer.CustomerGuid | Inherited from the parent Customer. |
AddressId | Address.AddressId | If the source |
Iso2 | Address.Iso2 / Address.Country | Two-letter ISO country code.
|
Country | Address.Country / Address.Iso2 | Country name.
|
Address.Email / Customer.Email / ContactPerson.Email | Email address for the address.
| |
AddressType | Address.AddressType | Type of address (e.g., Visit, Delivery, Invoice).
|
AddressLine1 | Address.AddressLine1 / AddressLine.Street, AddressLine.Number, AddressLine.Addition | Full address line.
|
Street | AddressLine.Street (derived from Address.AddressLine1) | Extracted from the |
HouseNumber | AddressLine.Number (derived from Address.AddressLine1) | Extracted from the |
Addition | AddressLine.Addition (derived from Address.AddressLine1) | Extracted from the |
IsMainAddress | Address.IsMainAddress | For |
Data Mapping Table: Contact Person
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
CustomerGuid | Customer.CustomerGuid | Inherited from the parent Customer. |
ContactId | ContactPerson.ContactId | If |
PasswordWebshop | ContactPerson.PasswordWebshop | Set to |
ContactPerson.Email | Trimmed for whitespace. | |
DynamicFreeFields | ContactPerson.DynamicFreeFields | XML payload containing extra ERP data.
|
FullName | ContactPerson.FullName / ContactPerson.FirstName, ContactPerson.MiddleName, ContactPerson.LastName | Full name of the contact person.
|
FirstName | ContactPerson.FirstName | Populated from |
MiddleName | ContactPerson.MiddleName | Populated from |
LastName | ContactPerson.LastName | Populated from |
IsMainContactPerson | ContactPerson.IsMainContactPerson / Customer.MainContactPerson | Indicates if this is the main contact for the customer.
|
Initials | Derived from ContactPerson.FirstName | Derived from the first character of the |
Data Mapping Table: Item Class Value Discount
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
CustomerGuid | Customer.CustomerGuid | Inherited from the parent Customer. |
discount | ItemClassValueDiscount.discount | Only discounts with a value greater than 0 are processed and stored. |
Data Mapping Table: Dashboard
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
CustomerCode | Customer.CustomerCode | Identifies the customer to whom the dashboard belongs. |
DashboardData | Customer.CustomerDashboard | Base64 decoded content of the customer dashboard. |
Special Logic & Filters
Input Validation & Filtering:
Customers with empty or whitespace
CustomerNameor emptyCustomerCodeare considered invalid, logged, and skipped from the update process.
Batch Processing:
Customer records are processed in batches of 100 to optimize database operations.
Customer GUID & Reactivation:
For updater instances (
UpdaterHelper.IsUpdateris true), the system attempts to retrieve existingCustomerGuidvalues from an in-memory cache (_customerCodeLinksand_customerCodeGuidReactivationLinks).This includes logic to reactivate previously inactive customers by reusing their GUID, identified by customer codes starting with
~.If no GUID is found in the cache, it queries the Portal API. If still not found, a new GUID is generated.
Script Hooks:
BeforeUpdateCustomers: A script is executed before processing customer batches, allowing for pre-processing of customer data.UpdateCustomers: A script is executed after processing customer batches, allowing for post-processing or additional updates.
Price Deduplication:
If
EnablePriceDeduplicationis active (either inConnectorBaseSettingsor connector-specific settings), customerUsesPriceFieldandActionPriceListvalues are migrated to deduplicated price list IDs based onKeySettings.GenericPriceListMigrations.If a migrated price list ID does not exist,
UsesPriceFielddefaults to 1 andActionPriceListis set tonull.
Address Processing:
Invalid addresses (empty and no
ExternalId) are filtered out.If a customer has no valid addresses but an original ISO2 country code was provided, a dummy 'Visit' address is created to store the ISO2.
Logic ensures that both 'Visit' and 'Delivery' address types exist for a customer, creating a copy of an existing address if one is missing.
Addresses are normalized (e.g., email cleansing, ISO2 mapping, default address types).
Customer Note Handling:
If
CustomerNoteis provided, any existing 'BackOffice' notes for that customer are deleted from theCustomerNotestable. A new note is then inserted with 'BackOffice' as the sales representative.
USA VAT Logic:
For administrations configured as USA (
Administration.IsUSAis true),VatCodeis set tonullandVatLiableis set tofalse.
Extra Data & Free Fields Processing:
If
ExtraCustomerDatais available, properties are mapped to theCustomerobject based on matching property names.Unknown elements from
ExtraCustomerDatawith keys starting with 'FreeField_' are converted intoCustomerFreeFieldobjects and added to theFreeFieldList.Fixed item filters (keys starting with 'ItemFilter_' in
ExtraCustomerData.UnknownElements) are processed and converted into theItemFilterstring ifSyncSettings.CustomerItemFilteris enabled.
Invalid XML Characters:
Invalid XML characters are removed from
CustomerandContactPersondynamic free fields before processing.
Domain Specifics / Extension Section
Customer Core Fields
The customer core fields, such as CustomerCode and CustomerName, are fundamental for identifying and displaying customer records in App4Sales. The system enforces their presence, skipping any customer records lacking these essential identifiers. Customer GUIDs are managed to ensure continuity, even for previously inactive customers, enabling the retention of historical data like customer notes and order links. Price list assignments, both standard (UsesPriceField) and action-specific (ActionPriceList), are handled with consideration for deduplication settings and default configurations. Payment conditions are sanitized to prevent database inconsistencies, and VAT settings are automatically adjusted for USA-based administrations.
Addresses
Address processing is robust, ensuring data quality and completeness. The system filters out incomplete addresses unless an external identifier is present. It proactively creates dummy addresses for ISO2 codes if no valid addresses exist and ensures that every customer has both a 'Visit' and 'Delivery' address type, even if it means duplicating an existing address. Address data undergoes normalization, including email cleansing and country code mapping, to maintain consistency across the platform. The primary 'Visit' and 'Delivery' addresses are automatically identified if not explicitly marked.
Contacts
Contact persons associated with customers are managed with attention to detail. Contact identifiers are generated for updater instances if not provided. Email addresses are trimmed, and full names are intelligently parsed or constructed from individual name components. The system ensures a main contact person is designated for each customer, either by explicit source indication or by selecting the first available contact. Dynamic free fields for contacts are processed and invalid XML characters removed, allowing for flexible extension of contact information.
Extra Data & Free Fields
The connector supports extensive customization through extra data and free fields. Supplementary customer data, often from flat files, can directly override or extend standard customer properties. Unstructured 'UnknownElements' from this extra data are intelligently converted into App4Sales free fields based on specific naming conventions (e.g., 'FreeField_'). Similarly, fixed item filters for customers can be defined within this extra data, enabling granular control over product visibility based on item classes, provided the 'CustomerItemFilter' setting is enabled.
Discounts & Dashboards
Customer-specific item class value discounts are processed, with only positive discount values being stored. This allows for precise control over pricing based on product classifications. Customer dashboards, provided as Base64 encoded strings, are extracted, decoded, and stored separately to allow for personalized user interfaces within the App4Sales platform. Any existing customer notes from the 'BackOffice' are first cleared and then recreated based on the incoming data, ensuring the most up-to-date information is presented.
Related Settings & Prerequisites
Default Action Price List Code: Defines a default action price list to be applied to customers if they do not have one specified. Configurable via
ConnectorBaseSettings.Enable Price Deduplication: When enabled, customer price list assignments (standard and action price lists) are migrated to deduplicated versions based on system-wide price list migration settings. Configurable via
ConnectorBaseSettingsor connector-specific settings.Customer Item Filter: A setting that enables or disables the processing of fixed item filters from customer extra data. Configurable via
SyncSettings.Administration is USA: A system-wide setting that influences VAT handling for customers. If true, customer
VatCodeandVatLiablefields are set tonullandfalserespectively. Configurable viaAdministrationSession.CurrentSession.Administration.Mapped Languages: Requires configuration of language code mappings between the ERP system and App4Sales.
Mapped Countries: Requires configuration of country code mappings, influencing address normalization.
Custom Extra Fields: Configuration of custom extra fields for both customer and contact person entities, allowing for mapping of dynamic ERP data.
Scripting Service: The system utilizes a scripting service to execute custom logic via
BeforeUpdateCustomersandUpdateCustomersscripts, enabling flexible pre- and post-processing of customer data.
Known Limitations
No explicit limitations were observed in the CustomerUpdateHandler.cs code that would directly impact the functional scope for Application Administrators and Implementation Consultants.