Uniconta Connector - Customer Update
This document describes the customer update process for the Uniconta connector, detailing how customer information is synchronized between Uniconta and the App4Sales platform. It covers both the retrieval of customer data from Uniconta into App4Sales and the sending of customer data from App4Sales to Uniconta. The synchronization includes core customer fields, addresses, contact persons, custom free fields, and associated price lists.
Data Source Configuration
The Uniconta connector connects to the Uniconta API. The following settings are used for authentication and environment selection:
Uniconta API Key: Used to authenticate with the Uniconta API.
Uniconta Username: The username for accessing Uniconta. If not specified in the administration session, a global setting is used.
Uniconta Password: The password for the Uniconta username. If not specified in the administration session, a global setting is used.
Company ID: The specific Uniconta company to connect to.
Data is pulled from Uniconta and pushed to Uniconta using the configured API credentials.
Data Mapping - App4Sales Customer (from Uniconta DebtorClient)
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
CustomerCode | unicontaCustomer._Account | Direct mapping of the Uniconta account number. |
CustomerName | unicontaCustomer._Name | Direct mapping of the Uniconta customer name. |
Discount | unicontaCustomer._LineDiscountPct / unicontaCustomer._EndDiscountPct | If 'UseLineDiscountPctInsteadOfEndDiscountPct' setting is true, uses _LineDiscountPct; otherwise, uses _EndDiscountPct. Cast to decimal. |
VatLiable | unicontaCustomer._Vat | True if _Vat field is not null or empty. |
Website | unicontaCustomer._Www | Direct mapping of the Uniconta website. |
Phone | unicontaCustomer._MobilPhone | Direct mapping of the Uniconta mobile phone. |
unicontaCustomer._ContactEmail | Direct mapping of the Uniconta contact email. | |
VatCode | unicontaCustomer._LegalIdent | Direct mapping of the Uniconta legal identifier. |
PaymentConditionCode | unicontaCustomer._Payment | Direct mapping of the Uniconta payment condition. |
InternalCode | unicontaCustomer.RowId.ToString() | The Uniconta internal row ID, converted to string. |
Currency | unicontaCustomer._Currency | Uniconta currency code, converted to string. If Uniconta currency is 'XXX', then it's mapped to an empty string. |
Sysmodified | unicontaCustomer.UpdatedAt | Last update timestamp from Uniconta. |
LanguageCode | unicontaCustomer._Language.ToString() | Uniconta language code, converted to string. |
CustomerManager | employees?.FirstOrDefault(x => x.Number == unicontaCustomer._Employee)?.Name | The name of the employee (customer manager) in Uniconta, based on the employee number. |
UsesPriceField | customerPriceList?.Id | If a price list is found in App4Sales matching unicontaCustomer._PriceList, its ID is used. Otherwise, defaults to 0. |
Data Mapping - App4Sales Address (from Uniconta DebtorClient)
Each Uniconta customer is mapped to two App4Sales addresses: a 'Visit' address and a 'Delivery' address.
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
Visit Address | Visit Address | Visit Address |
AddressLine1 | unicontaCustomer._Address1 | Direct mapping. |
AddressLine2 | unicontaCustomer._Address2 | Direct mapping. |
AddressLine3 | unicontaCustomer._Address3 | Direct mapping. |
Country | unicontaCustomer._Country | Determined by |
Iso2 | unicontaCustomer._Country | Determined by |
City | unicontaCustomer._City | Direct mapping. |
PostCode | unicontaCustomer._ZipCode | Direct mapping. |
AddressType | N/A | Hardcoded to 'Visit'. |
IsMainAddress | N/A | Hardcoded to 'true' for the visit address. |
Delivery Address | Delivery Address | Delivery Address |
AddressLine1 | unicontaCustomer._DeliveryAddress1 | Direct mapping. |
AddressLine2 | unicontaCustomer._DeliveryAddress2 | Direct mapping. |
AddressLine3 | unicontaCustomer._DeliveryAddress3 | Direct mapping. |
Country | unicontaCustomer._DeliveryCountry | Determined by |
Iso2 | unicontaCustomer._DeliveryCountry | Determined by |
City | unicontaCustomer._DeliveryCity | Direct mapping. |
PostCode | unicontaCustomer._DeliveryZipCode | Direct mapping. |
AddressType | N/A | Hardcoded to 'Delivery'. |
IsMainAddress | N/A | Defaulted to 'false' for the delivery address (only visit address is main). |
Data Mapping - App4Sales ContactPerson (from Uniconta DebtorClient and ContactClient)
The main contact person is derived directly from the Uniconta DebtorClient, and additional contacts are mapped from associated ContactClient objects.
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
Main Contact Person | Main Contact Person | Main Contact Person |
FirstName | unicontaCustomer._ContactPerson | Parsed from the full contact person name using |
LastName | unicontaCustomer._ContactPerson | Parsed from the full contact person name using |
Phonenumber | unicontaCustomer._MobilPhone / unicontaCustomer._Phone | If 'UseCustomerMobilePhoneAsMainContactPersonPhone' setting is true, uses _MobilPhone; otherwise, uses _Phone. |
MobileNumber | unicontaCustomer._MobilPhone | Direct mapping. |
unicontaCustomer._ContactEmail | Direct mapping. | |
Initials | unicontaCustomer._ContactPerson | Parsed from the full contact person name using |
FullName | unicontaCustomer._ContactPerson | Direct mapping. |
IsMainContactPerson | N/A | Hardcoded to 'true'. |
Additional Contact Persons (from unicontaCustomer.Contacts) | Additional Contact Persons (from unicontaCustomer.Contacts) | Additional Contact Persons (from unicontaCustomer.Contacts) |
FirstName | contact.Name | Parsed from the full contact name using |
MiddleName | contact.Name | Parsed from the full contact name using |
LastName | contact.Name | Parsed from the full contact name using |
MobileNumber | contact.Mobile | Direct mapping. |
contact.Email | Direct mapping. | |
Initials | contact.Name | Parsed from the full contact name using |
FullName | contact.Name | Direct mapping. |
IsMainContactPerson | N/A | Hardcoded to 'false'. |
Data Mapping - Uniconta Debtor (from App4Sales Customer)
When sending customer data from App4Sales to Uniconta, the App4Sales Customer object is converted to a Uniconta Debtor object.
Uniconta Field | Source Field (App4Sales Customer) | Logic/Notes |
_ContactEmail | customer.MainContactPerson?.Email | Email from the main contact person. |
_InvoiceEmail | customer.EmailAddressForStock / customer.Email | If customer.EmailAddressForStock is not empty, use it. Otherwise, use customer.Email. |
_Name | customer.CustomerName | Direct mapping. |
_ContactPerson | customer.MainContactPerson?.FullName | Full name of the main contact person. |
_Language | customer.LanguageCode | Parsed from App4Sales LanguageCode (case-insensitive). |
_MobilPhone | customer.MainContactPerson?.MobileNumber | Mobile number from the main contact person. |
_Phone | customer.Phone | Direct mapping. |
_LegalIdent | customer.VatCode | Direct mapping. |
_Www | customer.Website | Direct mapping. |
_PriceList | customerPriceList?.Code | The code of the selected price list. |
_Currency | customerPriceList?.ExternalCurrency | Parsed from the external currency of the selected price list. Defaults to 'XXX' if parsing fails. |
_Payment | customer.PaymentConditionCode | Direct mapping. |
_Address1 (Visit) | visitAddress.AddressLine1 | From the App4Sales 'Visit' address. |
_Address2 (Visit) | visitAddress.AddressLine2 | From the App4Sales 'Visit' address. |
_Address3 (Visit) | visitAddress.AddressLine3 | From the App4Sales 'Visit' address. |
_Country (Visit) | visitAddress.IsoCode | Converted from App4Sales ISO code to Uniconta CountryCode using |
_City (Visit) | visitAddress.City | From the App4Sales 'Visit' address. |
_ZipCode (Visit) | visitAddress.PostCode | From the App4Sales 'Visit' address. |
_DeliveryAddress1 | deliveryAddress.AddressLine1 | From the App4Sales 'Delivery' address. |
_DeliveryAddress2 | deliveryAddress.AddressLine2 | From the App4Sales 'Delivery' address. |
_DeliveryAddress3 | deliveryAddress.AddressLine3 | From the App4Sales 'Delivery' address. |
_DeliveryCity | deliveryAddress.City | From the App4Sales 'Delivery' address. |
_DeliveryCountry | deliveryAddress.IsoCode | Converted from App4Sales ISO code to Uniconta CountryCode using |
_DeliveryZipCode | deliveryAddress.PostCode | From the App4Sales 'Delivery' address. |
_PaymentMethod | customer.PaymentConditionCode | Parsed as a byte to Uniconta PaymentTypes enum. Only if PaymentConditionCode is not empty. |
_Account | customer.CustomerCode / "A4S " + connectorSettings.NextCustomerNumber.ToString() | If customer.CustomerCode is provided, it is used. Otherwise, a new customer code is generated using the "A4S " prefix and the 'NextCustomerNumber' setting. |
Data Mapping - Uniconta Debtor User Fields (from App4Sales Customer FreeFields and properties)
Custom free fields from App4Sales can be mapped to Uniconta user-defined fields based on the CustomerFreeFieldsConfiguration setting.
Uniconta User Field (PropertyName) | Source Field (App4Sales Customer) | Logic/Notes |
Configured PropertyName | customer.GetPropertyValue(customField.XmlName) / customer.UnknownElements[customField.XmlName] | The mapping is defined in the
|
Special Logic & Filters
Country Information Handling: The connector attempts to convert Uniconta country codes (
CountryCodeenum) to ISO2 country codes and then to display names. If this conversion fails for a customer's country, a warning is logged, and the customer's country and ISO2 fields in App4Sales will be null.Price List Association: When retrieving customers from Uniconta, if a customer's
_PriceListfield does not match any existing App4Sales price list code, a warning is logged, and theUsesPriceFieldin App4Sales defaults to 0.Customer Free Field Configuration: The mapping of App4Sales free fields to Uniconta user-defined fields is controlled by the
CustomerFreeFieldsConfigurationsetting, which expects a JSON array ofUnicontaCustomFieldMappingobjects. This allows flexible mapping of custom data.Customer Creation/Update Logic: When sending customer data to Uniconta:
If the App4Sales customer has a
CustomerCode, the existing Uniconta customer with that code is updated.If no
CustomerCodeis present, a new customer is inserted into Uniconta. The new customer's code is generated using the prefix "A4S " followed by the value of theNextCustomerNumbersetting. This setting is incremented after each new customer creation.
Payment Conditions: The connector updates payment conditions from Uniconta into App4Sales. Existing payment conditions in App4Sales that are no longer present in Uniconta are deleted, and new or updated ones are inserted/updated.
Customer Notes: Customer notes are retrieved from Uniconta (
UserNotesClientwithTableIdmatching Customers) and updated in the App4Sales database.
Domain Specifics
Customer Core Fields
The core customer record includes essential identity information such as CustomerCode and CustomerName. Commercial settings like Discount (line or end discount based on configuration), VatLiable status, and PaymentConditionCode are synchronized. The UsesPriceField in App4Sales is linked to Uniconta's price lists, allowing customers to have specific pricing. Customer language and assigned employee (customer manager) are also mapped.
Addresses
Each Uniconta customer typically results in two App4Sales addresses: a 'Visit' address and a 'Delivery' address.
Visit Address: Mapped from the primary address fields in Uniconta (
_Address1,_City,_ZipCode,_Country). This address is marked as the main address in App4Sales.Delivery Address: Mapped from the dedicated delivery address fields in Uniconta (
_DeliveryAddress1,_DeliveryCity,_DeliveryZipCode,_DeliveryCountry).Country Normalization: Country codes from Uniconta are converted to ISO2 codes and then to display names using a helper method. If this process fails, the country information for the address will be omitted.
Contacts
Contact persons are synchronized to App4Sales, with one designated as the main contact person.
Main Contact Person: Created from the
_ContactPersonand_ContactEmailfields of the Uniconta customer. The phone number for the main contact person can be configured to use either the customer's mobile phone or general phone number from Uniconta.Additional Contacts: Any additional contacts associated with the Uniconta customer (
unicontaCustomer.Contacts) are also synchronized as contact persons in App4Sales, but are not marked as the main contact.Name Parsing: First name, last name, and initials are parsed from the full contact name strings.
Extra Data & Free Fields
The connector supports flexible mapping of custom data from Uniconta's user-defined fields to App4Sales.
CustomerFreeFieldsConfiguration: This setting, provided as a JSON string, defines how Uniconta user fields are mapped. It allows mapping to existing App4Sales customer properties or to a generic list ofCustomerFreeFieldobjects if no direct property exists.Data Types: The mapping configuration specifies the expected data type (Boolean, DateTime, Double, Single, String) for correct value retrieval and assignment.
Discounts & Dashboards
While the current analysis of the provided code snippets (CustomersExtensions.cs, CustomersRepository.cs, UnicontaConnector.cs) does not explicitly show direct handling or mapping for "dashboards" or "item class value discounts" in the context of customer updates *from* Uniconta *to* App4Sales, the `InsertOrUpdateCustomerCommand` and `CreateCustomer` methods suggest that when App4Sales sends customer data to Uniconta, `CustomExtraFieldsContext.Instance.All(DbCustomExtraField.EntityCustomer)` are retrieved. This implies custom fields could potentially contain dashboard layouts or discount information. Further investigation would be required to confirm how these specific elements are handled if they are not part of the standard `DebtorClient` or `Customer` models. Customer notes are handled through `GetCustomerNotes` and updated in App4Sales.
Related Settings & Prerequisites
Uniconta Username: User credential for Uniconta API.
Uniconta Password: Password credential for Uniconta API.
Uniconta API Key: API key for Uniconta API.
Company ID: Specifies the Uniconta company to connect to.
UseLineDiscountPctInsteadOfEndDiscountPct: (Boolean) If true, the line discount percentage from Uniconta is used for the App4Sales
Discountfield; otherwise, the end discount percentage is used.UseCustomerMobilePhoneAsMainContactPersonPhone: (Boolean) If true, the customer's mobile phone number is used for the main contact person's phone number; otherwise, the general phone number is used.
CustomerFreeFieldsConfiguration: (JSON String) A JSON array of
UnicontaCustomFieldMappingobjects that defines how Uniconta user-defined fields are mapped to App4Sales customer properties or free fields. Example structure:[{ "ObjectName": "Customer", "PropertyName": "AddressLine3", "XmlName": "CustomerAddressLine3", "NameInApp": "Addressline 3", "PropertyType" : "string", "IsEntityField" : "false" }]NextCustomerNumber: (Integer) Used when creating new customers in Uniconta from App4Sales. Provides a sequential number for generating new customer codes with the "A4S " prefix.
UseCustomFieldForChamberOfCommerceCode: (String) Specifies the name of a Uniconta custom field that holds the Chamber of Commerce code.
Known Limitations
Country information lookup can fail for certain Uniconta country codes, leading to missing country data in App4Sales.
Customers from Uniconta without a matching price list in App4Sales will have their
UsesPriceFielddefaulted to 0, which might not accurately reflect their pricing in App4Sales.The current analysis of the provided code snippets does not explicitly show direct handling or mapping for "customer dashboards" or "customer-specific item class discounts" when customers are retrieved from Uniconta into App4Sales. It is assumed these would be handled via generic extra fields if configured.