Visma AccountView - CustomerUpdate
The CustomerUpdate function in the Visma AccountView connector synchronizes customer-related data from the AccountView ERP system into the App4Sales platform. This process involves retrieving customer records, including their core information, associated addresses, contact persons, item class value discounts, and dashboards. The synchronization runs periodically, pulling data from AccountView's REST API and updating the corresponding entities within the App4Sales database. It also handles the creation and updating of custom extra fields for search codes and relation groups.
3. Data Source Configuration
The connector retrieves customer data from the Visma AccountView REST API. Data is pulled from the API using HTTP GET requests. Authentication is performed using an OAuth 2.0 Bearer token (Settings.AccessToken) and a company ID (Settings.CompanyId) in the request headers.
API Endpoints and Business Objects:
Customer Data:
/accountviewdata(GET) using business objectar1.Payment Conditions:
/accountviewdata(GET) using business objectpt1.Prospect Data:
/accountviewdata(GET) using business objectCM1.Customer/Contact Update:
/accountviewdata(POST/PUT).
Key Query Parameters:
pagesize: Specifies the number of records per page (e.g., 500 for customers).fields: A comma-separated list of fields to retrieve from AccountView (e.g.,contact.sub_nr, contact.acct_name, ...).filtercontrolsourceX,filteroperatorX,filtervaluetypeX,filtervalueX: Used for filtering records (e.g., filtering out blocked customers, or specific account links for prospects).sortfields,sortorder: For ordering the retrieved data.lastkey: Used for pagination to retrieve subsequent pages of data.
Filtering Logic:
Customers marked as 'Blocked' in AccountView are not synchronized.
If
Settings.CustomFieldForCustomerSyncis configured, customers are filtered based on the boolean value of this custom field.Prospects are identified by filtering on
contact.acct_link = 0.
4. Data Mapping Table
Customer Core Fields
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
|
| Directly mapped. For new customers created within App4Sales, a code is generated using |
|
| Directly mapped. For prospects ( |
|
| Mapped as an integer percentage. |
|
| Mapped via |
|
| Directly mapped. Set to |
| Derived | Based on |
|
| Timestamp of creation. Truncated to seconds. If not available, defaults to |
|
| Timestamp of last modification. Truncated to seconds. If not available, defaults to |
|
| Directly mapped. Empty string values are converted to |
|
| Directly mapped. |
|
| Trimmed for whitespace. Can be inherited by addresses if empty. |
|
| Directly mapped. |
|
| Directly mapped. |
|
| Directly mapped. |
|
| Mapped from |
|
| Directly mapped. If empty, derived from the first 4 characters of |
|
| Directly mapped. Populated as a dropdown extra field. |
|
| Maps to a numeric ID representing the price list used by the customer. Subject to price deduplication migration logic. |
|
| If not specified by AccountView, defaults to the ID of the price list specified in |
|
| If |
|
| If |
| Derived | Retrieved from local cache, Portal API, or generated as a new GUID if not found. Reuses GUIDs for reactivated customers. |
| Base64 string from AccountView | Base64-encoded dashboard layout. Decoded and stored separately. Original field is set to |
|
| Processed from |
|
| Processed if |
Addresses
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
| Derived | Defaults to 'Visit' if not explicitly defined. Ensures both 'Visit' and 'Delivery' addresses exist, duplicating if only one is provided. |
|
| Combined street, house number, and addition. Parsed from AccountView |
| Derived from | Extracted from |
| Derived from | Extracted from |
| Derived from | Extracted from |
|
| Directly mapped. |
|
| Directly mapped. |
|
| If |
|
| Mapped via |
| Inherited from Customer or other Addresses/Contacts | Trimmed. If the address is the main address and its email is empty, it inherits the email from the customer or other available addresses/contacts. |
| Derived | Assigned from the parent customer's GUID. |
| Derived | Automatically set to |
| AccountView source | Used to indicate if an address is valid in the external system; prevents filtering out empty addresses. |
Contact Persons
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
| Derived from | If |
| Derived from | Parsed from |
| Derived from | Parsed from |
| Derived from | Parsed from |
|
| If empty, constructed from |
| Derived from | First letter of |
|
| Trimmed for whitespace. |
|
| Directly mapped. |
|
| Directly mapped. |
| Derived | Assigned from the parent customer's GUID. |
| Derived | Set to |
| XML payload | Deserialized from XML, converted to extra fields using |
| N/A | Set to |
Item Class Value Discounts
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
| Derived | Assigned from the parent customer's GUID. |
|
| The name of the item class. |
| Derived | Internal ID of the item class, resolved from |
| CSV/API | The percentage discount. Only discounts greater than 0 are processed. |
5. Special Logic & Filters
Invalid Customer Filtering: Customers with missing or empty
CustomerNameorCustomerCodeare considered invalid, logged as warnings, and excluded from the synchronization process.Customer Reactivation: The system attempts to reuse existing
CustomerGuidvalues for customers that were previously marked as inactive or deleted, preserving historical data like notes and order links.Password Handling: If the connector is running in 'Updater' mode (
UpdaterHelper.IsUpdateris true), any webshop passwords (PasswordWebshop) associated with customers or contact persons are cleared (set tonull) to ensure secure handling and prevent accidental synchronization of sensitive credentials.Dashboard Processing: Customer dashboards, received as Base64-encoded strings, are decoded and stored separately within the App4Sales database via
_customerDataManager.SaveDashboards. The originalCustomerDashboardfield on the customer object is then nulled out to optimize memory usage and avoid storing large Base64 strings directly in the main customer record.Default Action Price List: If a
DefaultActionPriceListCodeis configured in the connector's base settings and a customer does not have an explicit action price list assigned, the system automatically assigns the price list corresponding to the default code.Payment Condition Sanitization: Empty string values for
PaymentConditionCodeare converted tonullbefore being saved to prevent potential foreign key constraint issues in the database.Email Trimming: All email addresses associated with customers and contact persons are trimmed of leading and trailing whitespace to ensure data consistency.
Address Processing Logic:
Empty Address Filtering: Addresses that are entirely empty are filtered out unless they have an
ExternalId, indicating they are valid in the external system.Dummy Address Creation: If a customer has no valid addresses after filtering, but an ISO2 country code is available, a dummy 'Visit' address is created to preserve the country information.
Visit/Delivery Address Duplication: To ensure both 'Visit' and 'Delivery' address types exist for a customer, if only one is initially present, the existing address is duplicated to create the missing type. The duplicated address's
Modifiedstatus is set tofalse, andAddressIdandExternalIdare nulled to prevent conflicts.Last Resort Address Duplication: If no 'Visit' or 'Delivery' addresses are available but other address types exist, the primary existing address (either the main address or the first one found) is duplicated to create both 'Visit' and 'Delivery' address types.
Email Inheritance for Addresses: If an address is marked as the main address and its email field is empty, it attempts to inherit an email address from the customer's main email, another address on the same customer, or from a contact person associated with the customer.
ISO/Country Code Normalization: ISO2 country codes are mapped via
MappedCountriesContext. If an ISO2 code is missing, it attempts to derive it from the full country name. If the country name is missing, it defaults to the ISO2 code.Address Line Parsing: If a structured
AddressLine(containing Street, House Number, Addition) is not present, the system attempts to parseAddressLine1into these components. Conversely, ifAddressLinecomponents exist, they are formatted back intoAddressLine1.Main Address Designation: The system ensures that at least one 'Visit' and one 'Delivery' address are designated as the main address if multiple addresses of these types exist.
Dynamic Free Fields Conversion: For both customers and contact persons, dynamic free fields, initially stored as XML payloads (
DynamicFreeFields), are deserialized into a structured format, converted into App4Sales' internal extra field representation using predefined custom extra field contexts, and then re-serialized into XML for storage. Invalid XML characters are removed during this process.Contact Person
ContactIdGeneration: In 'Updater' mode, if a contact person'sContactIdis empty, a unique ID is generated based on the contact's hash code. For newly created customers, contact IDs are generated sequentially usingSettings.AccountViewContactCodeStartingNumber.Main Contact Person Logic: The system identifies and designates a main contact person for each customer. If a
MainContactPersonis explicitly provided, it is ensured to be part of the customer's contact list and marked as the main contact. If not, and contacts exist, the first available contact is designated as the main contact.Customer Notes Handling: Any existing 'Backoffice note' for a customer, identified by the
BackofficeUser, is deleted from theCustomerNotestable before new notes, sourced fromcustomer.CustomerNoteorcustomer.ExtraValues(AccountView'sCOMMENT1), are inserted.ERP Leading Data (Non-Updater): When not operating in 'Updater' mode, the system prioritizes existing App4Sales data for certain fields (
InternalCode,ExtraData,LanguageCode) if the incoming AccountView data provides empty values, ensuring that crucial information is not inadvertently overwritten.USA VAT Handling: For administrations configured for the USA (
Administration.IsUSAis true), VAT-related fields (VatCodeandVatLiable) on the customer object are explicitly cleared (set tonullandfalserespectively), as VAT handling differs in the USA.Processing Extra Data from CSV/FTP: The
ProcessExtraDataForCustomermethod is invoked ifextraCustomerDatais available (e.g., from CSV or FTP sources). This method overlays additional data onto the customer object, potentially overwriting standard customer properties if they exist in the extra data. It also extracts and processes:Free Fields: Any fields in the extra data's
UnknownElementsthat are prefixed withFreeField_are extracted and added to the customer'sFreeFieldList.Fixed Item Filters: If
SyncSettings.CustomerItemFilteris enabled, fields prefixed withItemFilter_inUnknownElementsare processed to construct and apply item class filters for the customer.
Price Deduplication Migration: Price list IDs (
UsesPriceFieldandActionPriceList) on customer objects are adjusted based on a stored migration lookup (KeySettings.GenericPriceListMigrations). This ensures that customers are linked to deduplicated price lists whenEnablePriceDeduplicationis active. If a migrated price list is not found,UsesPriceFielddefaults to1andActionPriceListis nulled.Batch Processing: Customer updates are processed in batches of 100 to optimize database operations and reduce resource consumption.
JINT Scripts: The connector executes custom JINT scripts at specific points in the update process:
BeforeUpdateCustomers: Executed before any customer processing within the `Update` method.UpdateCustomers: Executed after each batch of customers has been processed, and again at the very end of the entire update cycle.
Database Batch Updates: For efficiency, changes to customers, addresses, and item class value discounts are committed to the database using batch updates via stored procedures (e.g.,
OPTA4SUpdateCustomersBatch,OPTA4SUpdateAddressesBatch,OPTA4SUpdateItemClassValueDiscountsBatch).Error Handling: Comprehensive error logging is implemented at various stages, including during individual customer processing and batch database updates. In case of errors during customer processing, data update intervals for 'CustomerUpdate' are reset.
6. Domain Specifics / Extension Section
Customer Core Fields
The core customer record is updated with information such as customer code, name, discount percentage, language, VAT details, and payment conditions. Creation and modification timestamps are also synchronized. Special handling is in place for new customer codes and search codes. Customer GUIDs are managed to ensure data integrity and facilitate reactivation of previously inactive customers. For administrations in the USA, VAT-related fields are cleared to align with local regulations. Prospect customers have their names prefixed with '[P]'.
Addresses
The connector ensures that each customer has both 'Visit' and 'Delivery' address types. If only one is provided by AccountView, the other is automatically generated by duplicating the existing one. Address lines are parsed to extract street, house number, and addition components, and country codes (ISO2) are normalized. Email addresses for main addresses can be inherited from the customer or other contacts if not explicitly provided. Addresses marked with an ExternalId are considered valid even if otherwise empty.
Contacts
Contact persons are linked to their respective customers. The system manages contact IDs, generating new ones if necessary in 'Updater' mode. Full names are composed from or decomposed into first, middle, and last names. A main contact person is always designated for each customer. Email addresses are trimmed. Webshop passwords for contacts are cleared during updates in 'Updater' mode.
Extra Data & Free Fields
Extra customer data, potentially sourced from CSV or other file-based imports, can be used to overwrite standard customer fields. Additionally, any fields from the external data source prefixed with 'FreeField_' are converted into generic free fields for the customer. If SyncSettings.CustomerItemFilter is enabled, fields prefixed with 'ItemFilter_' are processed to define customer-specific item filters, which control what items a customer can see or order.
Discounts & Dashboards
Customer-specific item class value discounts (percentage discounts based on item classifications) are synchronized and stored. Only discounts greater than 0% are processed. Customer dashboards, represented as Base64-encoded layouts from AccountView, are extracted, decoded, and stored in a dedicated location in the App4Sales database. The Base64 string is then removed from the customer object to optimize performance and storage.
7. Related Settings & Prerequisites
This section lists the connector settings and prerequisites that influence the customer synchronization process:
CustomFieldForCustomerSync: (Connector Setting) Specifies a custom field in AccountView used to filter which customers are synchronized. Only customers where this field evaluates totruewill be processed.CustomerVatLiableCodes: (Connector Setting) A comma-separated list of VAT codes that indicate a customer is VAT liable. Used in conjunction withcontact.vat_codefrom AccountView.SyncProspects: (Connector Setting) If enabled, prospects are also synchronized from AccountView (using business objectCM1) and are prefixed with[P]in their customer name within App4Sales.AccountViewCustomerCodeStartingNumber: (Connector Setting) Defines the starting number for generating new customer codes when customers are created from within App4Sales.AccountViewContactCodeStartingNumber: (Connector Setting) Defines the starting number for generating new contact IDs for contact persons created from within App4Sales.SendContactAsAdministrationContact: (Connector Setting) If enabled, contact persons are sent to AccountView as 'Administration Contact'.SendContactAsMainContact: (Connector Setting) If enabled, contact persons are sent to AccountView as 'Main Contact'.UseUsernameAsEmployeeForNewCustomer: (Connector Setting) If enabled, the App4Sales username is mapped to theEmployeeNumberfield (contact.EMP_NR) in AccountView for new customers.CollectionAccountCodeForNewCustomer: (Connector Setting) If set, this code is mapped to theacct_nrfield in AccountView for new customers.SwapDeliveryAndVisitAddress: (Connector Setting) If enabled, the logic for determining visit and delivery addresses is swapped.CustomerItemFilter: (Sync Setting) If enabled, the connector processesItemFilter_prefixed fields from extra customer data to apply item class filters for customers.EnablePriceDeduplication: (Connector Base Setting / Sync Setting) If enabled, the system performs a migration of price list IDs to ensure that customers are linked to deduplicated price lists.DefaultActionPriceListCode: (Connector Base Setting) Defines a default action price list to be assigned to customers if they do not have one explicitly specified.Administration.IsUSA: (Administration Setting) This internal setting determines if the administration is based in the USA, influencing the clearing of VAT-related fields for customers.Custom JINT Scripts:
BeforeUpdateCustomers: Allows execution of custom logic before customers are processed.UpdateCustomers: Allows execution of custom logic after customer batches are processed.
8. Known Limitations
AccountView API Idiosyncrasies: The connector includes workarounds for specific behaviors observed in the AccountView API, such as inconsistencies in how filters (e.g., 'StartsWith' vs. 'Equal') and search operations on item descriptions function.
Implicit API Ordering for Pagination: The use of
lastkeyfor API pagination implies an assumption that the AccountView API maintains a consistent and predictable ordering of records across paginated requests. Deviations in this ordering could lead to missed or duplicated records.Potential Customer Code/Contact ID Conflicts: When generating new customer codes or contact IDs for new entities created in App4Sales, the system defaults to a starting number of
500000if the corresponding connector settings (AccountViewCustomerCodeStartingNumber,AccountViewContactCodeStartingNumber) are not explicitly configured or are set to zero. If existing customer or contact codes in AccountView fall within this auto-generated range, potential conflicts could arise.