Logic4 Connector - Create Customer
Overview
This document describes the process of creating new customer records in the Logic4 ERP system via the App4Sales platform. The customer creation flow is initiated from App4Sales, which then transforms the customer data into a Logic4-specific format and transmits it to the Logic4 API. The process includes creating the main customer record, associated visit and delivery addresses, and the primary contact person.
Trigger & Permissions
Customer creation is triggered when a new customer is submitted from the App4Sales platform. This functionality is enabled in the connector settings if either the Edit Customer or Create Customer internal flags are active.
Data Source Configuration
The Logic4 connector interacts with the Logic4 REST API at the base URL: https://api.logic4server.nl. Customer- related data is pushed to Logic4 using the following endpoints:
Add/Update Customer:
/v1/Relations/AddUpdateCustomer(HTTP POST)Add/Update Address:
/v1/Relations/AddUpdateAddress(HTTP POST)Add/Update Contact:
/v1/Relations/AddUpdateContact(HTTP POST)
Payload Mapping
Logic4 Customer Fields
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
CustomerCode | Customer.CustomerCode | Direct mapping. |
CustomerName | Customer.CustomerName | Direct mapping. |
CustomerGuid | Customer.CustomerGuid | If empty, a new GUID is generated by App4Sales. |
ContactFullName | Customer.MainContactPerson.FullName or Customer.ContactPersons.FirstOrDefault(x => x.IsMainContactPerson).FullName | Full name of the main contact person. |
VisitAddress1 | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Visit").AddressLine1 | |
VisitAddress2 | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Visit").AddressLine2 | |
VisitPostCode | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Visit").PostCode | |
VisitCity | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Visit").City | |
DeliveryAddress1 | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Delivery").AddressLine1 | |
DeliveryAddress2 | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Delivery").AddressLine2 | |
DeliveryPostCode | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Delivery").PostCode | |
DeliveryCity | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Delivery").City | |
Customer.MainContactPerson.Email or Customer.Email | Email from main contact person, falls back to customer email. | |
CustomerEmail | Customer.Email | Direct mapping. |
Fax | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Visit").Fax or Customer.Addresses.FirstOrDefault(e => e.AddressType == "Delivery").Fax | Fax from visit address, falls back to delivery address. |
Phone | Customer.MainContactPerson.Phonenumber or Customer.Phone | Phone number from main contact person, falls back to customer phone. |
CustomerPhone | Customer.Phone | Direct mapping. |
LastModified | Derived | Set to current UTC date and time. |
LanguageCode | Customer.LanguageCode | Direct mapping. |
CountryCode | Customer.Addresses.FirstOrDefault(e => e.AddressType == "Visit").Iso2 or Customer.Addresses.FirstOrDefault(e => e.AddressType == "Delivery").Iso2 | ISO2 country code from visit address, falls back to delivery address. Defaults to "nl" if not found. |
Discount | Customer.Discount | Customer discount, converted to string. |
UsesPrice | Customer.UsesPriceField | Converted to string. |
PaymentCondition | Customer.PaymentConditionCode | Direct mapping. |
IsVatLiable | Customer.VatLiable | "True" or "False" based on `Customer.VatLiable`. |
VatCode | Customer.VatCode | Direct mapping. |
Mobile | Customer.MainContactPerson.MobileNumber | Mobile number of the main contact person. |
ChamberOfCommerceCode | Customer.ChamberOfCommerceCode | Direct mapping. |
Website | Customer.Website | Direct mapping. |
UnknownElements | Customer.UnknownElements | Dynamic custom fields are appended as XML elements. |
Logic4 Customer Address Fields
Logic4 Field | Source Field (App4Sales Customer/XMLCustomer) | Logic/Notes |
Id | Derived | Logic4 Address ID, returned upon creation. |
DebtorId | Logic4 Customer ID (backofficeCustomerId) | The ID of the customer the address is associated with. |
Type | Constants.AddressTypes.Visit or Constants.AddressTypes.Delivery | Set to the integer representation of 'Visit' (3) or 'Delivery' (2) based on address type. |
City | XMLCustomer.VisitCity or XMLCustomer.DeliveryCity | Mapped from the corresponding address type in XMLCustomer. |
ZipCode | XMLCustomer.VisitPostCode or XMLCustomer.DeliveryPostCode | Mapped from the corresponding address type in XMLCustomer. |
Address2 | XMLCustomer.VisitAddress2 or XMLCustomer.DeliveryAddress2 | Mapped from the corresponding address type in XMLCustomer. |
Street | XMLCustomer.VisitAddress1 or XMLCustomer.DeliveryAddress1 | Mapped from the corresponding address type in XMLCustomer. |
CountryCode | Not explicitly mapped during address creation; potentially inherited from customer or defaulted by Logic4. | |
IsoCode | Not explicitly mapped during address creation; potentially inherited from customer or defaulted by Logic4. | |
HouseNumber | Not explicitly mapped from App4Sales Customer in current flow for Logic4CustomerAddress. | |
HouseNumberAddition | Not explicitly mapped from App4Sales Customer in current flow for Logic4CustomerAddress. | |
Not explicitly mapped during address creation; potentially handled by main contact. | ||
ContactName | Not explicitly mapped during address creation; potentially handled by main contact. | |
CompanyName | Not explicitly mapped during address creation; potentially inherited from customer. | |
TelephoneNumber | Not explicitly mapped during address creation; potentially handled by main contact. |
Logic4 Customer Contact Fields
Logic4 Field | Source Field (XMLCustomer) | Logic/Notes |
Id | Derived | Logic4 Contact ID, returned upon creation. |
DebtorId | Logic4 Customer ID (backofficeCustomerId) | The ID of the customer the contact is associated with. |
FirstName | XMLCustomer.ContactFullName | Derived from the full name using `GetFirstName()`. |
LastName | XMLCustomer.ContactFullName | Derived from the full name using `GetLastName()`. |
EmailAddress | XMLCustomer.Email | Direct mapping. |
MobileNumber | XMLCustomer.Mobile | Direct mapping. |
TelephoneNumber | XMLCustomer.Phone | Direct mapping. |
IsMainContact | Hardcoded | Set to |
Initials | XMLCustomer.ContactFullName | Derived from the full name using `GetInitials()`. |
Function | Not mapped | Not explicitly mapped in the `ToMainContactPerson` method. |
Gender | Not mapped | Not explicitly mapped in the `ToMainContactPerson` method. |
Validation & Defaults
If the incoming App4Sales customer has an empty
CustomerGuid, a new GUID is generated internally.The
CountryCodefor the customer defaults to "nl" if no country code is found in either the visit or delivery address.IsVatLiableis explicitly converted to "True" or "False" string based on the App4SalesCustomer.VatLiableboolean.If an email address is not provided by the main contact person, the system attempts to use the overall customer email. If neither is available, the email field for the contact person is set to an empty string.
Similarly, for phone numbers, the system prioritizes the main contact person's phone, then the customer's main phone, otherwise it defaults to an empty string.
The `Status` of the customer in Logic4 is set to `Active` (2).
The `Type` of the customer in Logic4 is set to `BusinessWithContact` (2).
IsMainContactfor the Logic4 customer contact is always set totrue.
Response & Error Handling
Upon successful customer creation in Logic4, the connector expects to receive a Logic4 customer ID. This ID is then assigned as the CustomerCode in App4Sales. If the Logic4 API does not return a customer ID, the operation is considered a failure, and an error message is generated: "No customercode retrieved from the ERP".
If the overall response from the connector (which encapsulates the Logic4 API call) does not indicate success, an exception is thrown, halting the customer creation process and surfacing the error message.
Special Logic & Filters
The system first creates the core customer record in Logic4.
Address Creation: After the main customer record is created, the connector attempts to create both a "Visit" address and a "Delivery" address in Logic4, if these are provided in the App4Sales customer data. Each address is sent to the
/v1/Relations/AddUpdateAddressendpoint individually.Main Contact Person Creation/Update: The connector then handles the main contact person. It first checks if a main contact person for the customer already exists in Logic4. If not, a new contact person is created using the data from the App4Sales customer's main contact person (or derived from the customer itself). If a main contact person is found, it is updated. The contact person data is sent to the
/v1/Relations/AddUpdateContactendpoint.Dynamic Fields: Any additional "unknown elements" (dynamic custom fields) present in the App4Sales customer object are serialized into the XML payload sent to the connector's internal
opta4snewcustomerscommand.
Related Settings & Prerequisites
Default User ID: The connector uses a default user ID for operations. This is primarily sourced from the connector settings (`DefaultUserId`) or a global application setting (`Logic4UserId`).
Customer Free Fields Configuration: The connector can be configured to map custom fields from App4Sales to Logic4. This is controlled by the `CustomerFreeFieldsConfiguration` setting, which is a JSON string defining the mapping of custom fields.
Known Limitations
The direct creation of addresses (Visit and Delivery) and contact persons does not utilize all potential fields from the App4Sales customer model. Specifically, fields like
HouseNumberandHouseNumberAdditionfor addresses, andFunctionandGenderfor contact persons, are not explicitly mapped during the `AddUpdateAddress` and `AddUpdateContact` API calls as shown in the provided code.The derivation logic for first name, last name, and initials from
ContactFullName(using helper methods likeGetFirstName()) was not explicitly detailed, implying potential reliance on a specific format for the full name.The system assumes the existence of a main contact person or attempts to derive one. While the method `InsertOrUpdateCustomerMainContactPerson` suggests handling both creation and update, the specifics of how an existing contact is updated (beyond just checking its existence) were not fully elaborated in the provided code flow.