Overview
Customer-as-company lets a Counterpoint customer that represents a business transfer to iPaaS.com as a company, with the people named on it as that company's contacts. With Adobe Commerce/Magento 2 B2B connected, each company then arrives in Adobe Commerce as a B2B company, with one contact as its company administrator (the Super User) and the other as a company user. Orders those contacts place in Adobe Commerce are recorded in Counterpoint against the company's customer number.
What changes for Counterpoint customers you mark as companies:
The customer transfers to iPaaS.com as a company, carrying its billing address and every ship-to address.
Contact 1 and Contact 2 on the customer each transfer as their own iPaaS.com customer, related to the company.
A contact's email address in iPaaS.com carries a CONTCT_1: or CONTCT_2: prefix. This keeps each contact unique in iPaaS.com, and it is removed again when the contact is written to Adobe Commerce.
The contact types you set in Counterpoint decide which contact is the Super User.
New customers only. Customer-as-company is for company customers you create for it in Counterpoint: new customer records that have never transferred to iPaaS.com. With a company marker that only those new customers carry (see Choose the company marker), every existing customer, including existing customers whose Name type is Business, keeps transferring as a customer. Switching an existing customer to a company in place is not supported; if it happens, see Repairing a customer that was switched to a company in place.
Customers you do not mark as companies keep transferring as customers. Some changes in this guide apply to every record, and are listed under Before you start.
Who needs this guide: subscriptions installed before customer-as-company was released. A subscription keeps the mappings it was installed with, so each change below must be made in your own subscriptions. Subscribers or their MiSP make these changes; the Counterpoint server step in Step 1 is for whoever administers the Counterpoint server.
At a glance
Warning: switching customer-as-company on with a marker that existing customers carry corrupts their records. If customers already in iPaaS.com carry the marker, for example because Customer-as-company Field is CUST_NAM_TYP (Counterpoint's Name type) and Customer-as-company Field Value is B (Business), each of them is switched to a company in place on its next change, and each must then be repaired by hand. The integration has no safeguard against this: it does not check whether a marked customer is already in iPaaS.com, so it neither converts that customer's records nor keeps the customer transferring as a customer. Use a dedicated marker that only your new companies carry (see Choose the company marker), and check it before you switch customer-as-company on (Step 5).
New customers only: create each company as a new Counterpoint customer. Never set the marker on an existing customer; if that happens, see Repairing a customer that was switched to a company in place.
A dedicated marker: mark companies with a field that no existing customer carries, such as a new custom field (see Choose the company marker).
The marker before E-commerce customer: a new company must carry the marker before it is first saved as an e-commerce customer with an Email 1 (Step 6).
Both directions: make the Adobe Commerce Customer TO iPaaS.com changes in Step 4, so that changes made in Adobe Commerce keep contacts' email addresses and the phone numbers on customers' addresses.
Contacts come from Counterpoint: keep contact details there, and once a company is in Adobe Commerce, keep its Email 1 unchanged, and do not change a contact's email address in Adobe Commerce. To replace a contact, remove the previous one first, or the new person can take over the previous person's Adobe Commerce account (see Changing or removing contacts).
Before you start
NCR Counterpoint integration version: use the release that adds customer-as-company. You can tell it is installed when the NCR Counterpoint subscription's settings include Customer-as-company Field and Customer-as-company Field Value. Your MiSP or iPaaS.com Support can move the subscription to it.
Adobe Commerce/Magento 2 integration version: 1.4.10 or later. Earlier versions write the CONTCT_1: / CONTCT_2: prefix into Adobe Commerce, which rejects it as an invalid email address. 1.4.10 also keeps an existing Adobe Commerce customer's addresses when it links a contact to that customer.
One iPaaS.com company: the NCR Counterpoint and Adobe Commerce/Magento 2 subscriptions must belong to the same iPaaS.com company, so the companies and contacts Counterpoint creates are the ones Adobe Commerce receives.
Adobe Commerce B2B: the store must have the B2B company feature enabled.
Record your current mappings for every collection this guide changes, so you can put them back if needed.
Try it in a test environment first. Create one company through the whole flow (Step 6) and check the results (Step 7) before changing production.
Automatic transfers: the steps assume that customer changes transfer automatically in both directions between Counterpoint, iPaaS.com and Adobe Commerce, and company changes from Counterpoint through iPaaS.com to Adobe Commerce, as they do once change notifications and the Outbound Data Flows are on. Several steps must be done in the order given because of that.
Leave the two customer-as-company settings blank until Step 5. While they are blank, no customer is transferred as a company, and customers keep transferring as customers. If skipped: marked customers start transferring as companies before the collections and mappings below are in place, and fail or arrive incomplete. These changes do apply to every record as soon as you make them:
the customer billing address gains a phone number (Step 3);
orders, tickets and refunds follow the customer they are linked to before matching by email address (Step 3);
the Adobe Commerce TaxClassId, RegionId, CustomerGroupId, CustomerId, EmailAddress and PhoneNumber changes (Step 4).
Step 1: Prepare the Counterpoint data
The contact type fields (optional)
Customer-as-company can read two Counterpoint customer custom fields to decide each contact's role:
USER_CONTCT_1_TYP: the type for Contact 1.
USER_CONTCT_2_TYP: the type for Contact 2.
Allowed values:
S (or SuperUser): Super User, the company administrator in Adobe Commerce.
A (or Admin): Admin User.
Blank, or Counterpoint's no-selection value !: not designated.
Any other value: User.
The fields are optional. Without them, Contact 1 is the Super User and Contact 2 is a User. If you add them to your Counterpoint installation, whoever administers the Counterpoint server must regenerate the Counterpoint data dictionary cache afterwards so the integration can read them; the steps are under Generate the data dictionary cache in the NCR Counterpoint Installation Instructions. If skipped: the integration cannot read the type fields, and every company gets the default roles, with Contact 1 as the Super User.
Admin User and User are both assigned to the company in Adobe Commerce as ordinary company users. At the time this documentation was written, the integration does not give an Admin User any extra Adobe Commerce permissions; set those in Adobe Commerce if you need them.
Choosing the Super User
Every company needs exactly one Super User. The two type fields combine like this:
Contact 2 always takes its own type: S is the Super User, A an Admin User, anything else a User.
Contact 1 takes its own type when one is set: S is the Super User, A an Admin User, any other value a User.
Contact 1 with no type (blank or !) is the Super User by default, unless Contact 2 is S, in which case Contact 1 is a User.
Contact 1 has a type but neither contact is S: the company is stopped with CRPT-VALD-1013.
Both contacts are S: the company is stopped with CRPT-VALD-1012.
Contact 1 typed S but not transferred (for example, it has no name): the company is stopped with CRPT-BIZL-1008.
Contact 1 with no type and no name, and Contact 2 not S: the company has no Super User. Counterpoint raises no error, but Adobe Commerce refuses the company with MAGE-BIZL-1022.
Choose the company marker
In Step 5 you name a Counterpoint customer field and a value, and every customer whose field holds that value transfers as a company on its next change. Because customer-as-company is for new customers only, choose a field that only your new company customers will carry:
Use a dedicated field. For example, a new customer custom field such as USER_B2B_COMPANY set to Y, or a customer profile field your business uses for nothing else, such as PROF_ALPHA_5 (a Profile field) set to B2B. Set it only on the new customers you create as companies, never on an existing customer.
Never use a field that existing customers carry, such as the Name type. With CUST_NAM_TYP (Name type) and B (Business), or any other field and value that customers already in iPaaS.com hold, switching customer-as-company on corrupts the records of every existing customer that carries it. Each one is switched to a company in place on its next change: iPaaS.com gains a company record and new contact records beside the customer's existing record, which stops receiving the customer's changes, and Adobe Commerce creates an account for each contact that has none and, where the customer already has an account there, refuses Contact 1, whose email address belongs to that account, and the company. The integration neither prevents this nor corrects it. Clearing the marker or the settings afterwards stops further switches but removes nothing, and each customer must be repaired by hand (see Repairing a customer that was switched to a company in place).
A custom field must first be added to your Counterpoint installation, and whoever administers the Counterpoint server must then regenerate the Counterpoint data dictionary cache (see Generate the data dictionary cache in the NCR Counterpoint Installation Instructions). A profile field needs no setup. If skipped: the integration cannot read the custom field, so no customer transfers as a company; the transfer's activity log shows a warning that the field is not a Counterpoint customer field or custom field.
Matching: spell the field name exactly as Counterpoint does, including capitalization. The value is matched ignoring capitalization and surrounding spaces.
A customer reaches iPaaS.com only if it passes two checks, so make sure your companies pass both:
CPWebhooks change notifications: as installed, CPWebhooks reports a customer's changes only while it is flagged as an e-commerce customer and has an Email 1.
Your Customer TO iPaaS.com filter: a company's contacts are sent through Add/Update NCR Counterpoint Customer TO iPaaS.com, so the company customer must pass that collection's filter. For example, if your filter sends only e-commerce customers, flag each company as an e-commerce customer. Otherwise the company arrives without contacts: a Contact 1 typed S then stops it with CRPT-BIZL-1008, and otherwise Adobe Commerce refuses it for having no Super User.
What each new company customer needs
A new Counterpoint customer: its own customer number, created for the company and never transferred to iPaaS.com before. To make an existing business a company, see An existing business that should become a company.
Email 1: required, and unique among your e-commerce customers (where a new company shares an existing customer's Email 1, see An existing business that should become a company). It is the company's email address and Contact 1's email address. Adobe Commerce requires a company email address, and Contact 1 has no usable address without it.
Contact names: Contact 1 and Contact 2 hold each contact's own full name, for example Jane Smith. The first name is everything before the last space and the last name is the last word; a one-word name is used as both. A contact with no name is not transferred.
Custom contact fields: where your customer form also shows the contacts in custom fields (USER_CONTCT_1 and USER_CONTCT_2, for example on a Custom tab), they must hold the same names as the standard Contact 1 and Contact 2 fields. The integration reads each contact's name from the standard fields and its type from the custom type fields.
Email 2: Contact 2's own email address. A Contact 2 with no Email 2 falls back to Email 1 and carries the same address as Contact 1, so when the two are written to Adobe Commerce, whichever is written second is refused (MAGE-BIZL-1023). Because the integration creates a company's contacts in Adobe Commerce before the company itself, that stops the whole company. Give every Contact 2 its own Email 2.
The Super User's email address: the Super User, a contact typed S or, when neither is, an untyped Contact 1, must have its own address, Email 1 for Contact 1 and Email 2 for Contact 2, or the company is stopped with CRPT-VALD-1014.
Contact email addresses in Adobe Commerce: each contact's address must differ from the other contact's, and must not belong to an existing Adobe Commerce customer, unless you mean to move that account to the company (see An existing business that should become a company).
Avoid a + in email addresses. On some Adobe Commerce stores an address containing + cannot be looked up: the Super User is not found, contacts are not linked to existing Adobe Commerce customers, and an existing Adobe Commerce company is not matched, so the company is refused.
Customer category: required. The company's category becomes its Adobe Commerce customer group, named after the category; a company with no category is refused. The templates do not assign a default category, and the integration cannot choose one for you, because which group a company belongs in is your business decision. Assign a Counterpoint category to each company, or add a mapping to your subscription that supplies one.
A name that is unique within its category: iPaaS.com refuses a new company whose name and department match another company's, and the company's department carries its Counterpoint category code, so two companies with the same name and the same category cannot both transfer. Give each company a distinct name.
Phone 1: required. It becomes the company's telephone number and the telephone on the company's and the contacts' billing addresses, which Adobe Commerce requires.
Billing address: complete, with a state or region that is valid for its country.
First name and Last name on the company record: these become the recipient name on the company's and the contacts' billing addresses, which Adobe Commerce requires.
The marker, before E-commerce customer: the customer must already carry the company marker in the save that first makes it an e-commerce customer with an Email 1, because that is the save CPWebhooks reports to iPaaS.com. Create the customer with the marker set and E-commerce customer not yet flagged, complete everything above, and flag it as an e-commerce customer last (Step 6). A new customer saved as an e-commerce customer before its marker transfers as an ordinary customer, and setting the marker afterwards switches it to a company in place. If its Email 1 also belongs to a customer already in iPaaS.com, it is linked to that customer's iPaaS.com record instead of getting its own: its data overwrites that record and, through it, that customer's Adobe Commerce account, and the other Counterpoint customer loses its link to the record.
Check the data before you flag a company as an e-commerce customer
The read-only query in Readiness query at the end of this guide lists the customers it selects and the data problems above that it can find in Counterpoint. It changes no Counterpoint data. Its header names the lines to adjust: to check one new company before you flag it as an e-commerce customer, keep your marker line and replace the e-commerce line with its customer number (for example AND c.CUST_NO = '123456';), so the query also confirms the customer carries the marker; to check all your companies, change the marker line to your marker. Run it in SQL Server Management Studio against your Counterpoint company database, check that its first result lists the customers you meant to check, fix what it reports, and run it again until it returns no BLOCKS rows. Its CHECK rows include a warning when a customer has sales recorded in Counterpoint, which suggests an existing customer rather than a new one, and a warning when another customer has the same name and category. It cannot see Adobe Commerce: a contact whose email address already belongs to an Adobe Commerce account shows only when the company transfers (see An existing business that should become a company).
Step 2: Add the company collections to the Counterpoint subscription
Add these five collections to the NCR Counterpoint subscription. Create the company collection first, then the four child collections beneath it. Enter every value, formula and filter exactly as shown. The NCR Counterpoint to iPaaS.com Company Mapping Documentation explains each collection and mapping.
Add/Update NCR Counterpoint Company TO iPaaS.com
Collection type: Customer Company
Direction: TO iPaaS.com
Sync type: Add/Update
Parent collection: none
Mapping filter: none
The company itself. It has no filter: every customer that matches the settings in Step 5 transfers as a company, and a Manual Sync of it transfers any customer number you give it as a company.
Mappings (6):
AccountNumber: Field, from CUST_NO
Categories: Dynamic Formula,
return await ConvertCustomerCategoriesToiPaaSIdListAsync(CATEG_COD);Department: Field, from CATEG_COD
EmailAddress: Field, from EMAIL_ADRS_1
Name: Field, from NAM
PhoneNumber: Field, from PHONE_1
Add/Update NCR Counterpoint Company Billing Address TO iPaaS.com
Collection type: Customer Company Address
Direction: TO iPaaS.com
Sync type: Add/Update
Parent collection: Add/Update NCR Counterpoint Company TO iPaaS.com
Mapping filter:
SourceTypeName == "ParentOnly"
The company's billing address, read from the company customer itself.
Mappings (11):
Address1: Dynamic Formula,
Parent.ADRS_1Address2: Dynamic Formula,
Parent.ADRS_2Address3: Dynamic Formula,
Parent.ADRS_3City: Dynamic Formula,
Parent.CITYCountry: Dynamic Formula,
Coalesce(Parent.CNTRY,"United States")FirstName: Dynamic Formula,
Parent.FST_NAMIsPrimaryBilling: Static,
trueLastName: Dynamic Formula,
Parent.LST_NAMPhoneNumber: Dynamic Formula,
Parent.PHONE_1PostalCode: Dynamic Formula,
Parent.ZIP_CODRegion: Dynamic Formula,
Parent.STATE
Add/Update NCR Counterpoint Company Ship-To Address TO iPaaS.com
Collection type: Customer Company Address
Direction: TO iPaaS.com
Sync type: Add/Update
Parent collection: Add/Update NCR Counterpoint Company TO iPaaS.com
Mapping filter:
SourceTypeName != "ParentOnly"
Every Counterpoint ship-to address on the company customer, with the default ship-to address as the primary shipping address.
Mappings (11):
Address1: Field, from ADRS_1
Address2: Field, from ADRS_2
Address3: Field, from ADRS_3
City: Field, from CITY
Company: Dynamic Formula,
(SHIP_NAM_TYP == "B" ? NAM : null)Country: Dynamic Formula,
Coalesce(CNTRY,"United States")FirstName: Field, from FST_NAM
IsPrimaryShipping: Dynamic Formula,
(SHIP_ADRS_ID == "(DEFAULT)" ? true : false)LastName: Field, from LST_NAM
PostalCode: Field, from ZIP_COD
Region: Field, from STATE
Add/Update NCR Counterpoint Company Contact 1 Relationship TO iPaaS.com
Collection type: Company Relationship
Direction: TO iPaaS.com
Sync type: Add/Update
Parent collection: Add/Update NCR Counterpoint Company TO iPaaS.com
Mapping filter:
var t1 = GetCustomField_CPHive(Parent, "USER_CONTCT_1_TYP");
var c1 = t1 == null ? "" : t1.ToString().Trim().ToUpper().Replace(" ", "");
var t2 = GetCustomField_CPHive(Parent, "USER_CONTCT_2_TYP");
var c2 = t2 == null ? "" : t2.ToString().Trim().ToUpper().Replace(" ", "");
// "!" is Counterpoint's no-selection value: an unset Type is undesignated, and contact 1 is then the Super User by default.
if (c1 == "!") { c1 = ""; }
if (c2 == "!") { c2 = ""; }
var su1 = c1 == "S" || c1 == "SUPERUSER";
var su2 = c2 == "S" || c2 == "SUPERUSER";
if (su1 && su2) { throw new Exception("CRPT-VALD-1012 - Counterpoint customer " + Parent.CUST_NO + " has both Contact 1 and Contact 2 designated Super User. Designate exactly one contact as Super User." + " - https://support.ipaas.com/en/articles/16003194-ncr-counterpoint-error-messages"); }
if (c1 != "" && !su1 && !su2) { throw new Exception("CRPT-VALD-1013 - Counterpoint customer " + Parent.CUST_NO + " has no contact designated Super User. Designate Contact 1 or Contact 2 as Super User." + " - https://support.ipaas.com/en/articles/16003194-ncr-counterpoint-error-messages"); }
var su1Default = c1 == "" && !su2 && !string.IsNullOrWhiteSpace(Convert.ToString(Parent.CONTCT_1));
if ((su1 || su1Default) && string.IsNullOrEmpty(Parent.EMAIL_ADRS_1)) { throw new Exception("CRPT-VALD-1014 - Contact 1 of Counterpoint customer " + Parent.CUST_NO + " is the Super User, by its type or by default, but the customer has no Email 1, so the Super User would receive no email address. Enter Contact 1's email address in Email 1." + " - https://support.ipaas.com/en/articles/16003194-ncr-counterpoint-error-messages"); }
var contactId = await GetSpaceportIdAsync(Parent.CUST_NO + ":CONTCT_1", "Customer", SpaceportSystemId);
if (contactId == null) { if (su1) { throw new Exception("CRPT-BIZL-1008 - Contact 1 of Counterpoint customer " + Parent.CUST_NO + " is designated Super User but was not sent to iPaaS.com as a customer. Check that Contact 1 has a name in Counterpoint and that the customer passes the Customer TO iPaaS.com filter." + " - https://support.ipaas.com/en/articles/16003194-ncr-counterpoint-error-messages"); } return false; }
return true;
Relates Contact 1 to the company and sets its role. The filter stops the company with a coded error when the contact types break the rules in Step 1. It skips the relationship quietly when Contact 1 was not transferred, unless Contact 1 is typed S, which raises CRPT-BIZL-1008.
Mappings (3):
IsPrimary: Static,
trueRelatedToId: Dynamic Formula,
await GetSpaceportIdAsync(Parent.CUST_NO + ":CONTCT_1", "Customer", SpaceportSystemId)Type: Dynamic Formula:
// Adobe Commerce/Magento 2 pre-creates only relationship types containing "user" before assigning them to the company.
// An unset Type ("!" is Counterpoint's no-selection value) is undesignated: contact 1 is then the Super User unless contact 2 is designated Super User.
var t1 = GetCustomField_CPHive(Parent, "USER_CONTCT_1_TYP");
var c1 = t1 == null ? "" : t1.ToString().Trim().ToUpper().Replace(" ", "");
if (c1 == "!") { c1 = ""; }
if (c1 == "S" || c1 == "SUPERUSER") { return "Super User"; }
if (c1 == "A" || c1 == "ADMIN") { return "Admin User"; }
if (c1 != "") { return "User"; }
var t2 = GetCustomField_CPHive(Parent, "USER_CONTCT_2_TYP");
var c2 = t2 == null ? "" : t2.ToString().Trim().ToUpper().Replace(" ", "");
return (c2 == "S" || c2 == "SUPERUSER") ? "User" : "Super User";
Add/Update NCR Counterpoint Company Contact 2 Relationship TO iPaaS.com
Collection type: Company Relationship
Direction: TO iPaaS.com
Sync type: Add/Update
Parent collection: Add/Update NCR Counterpoint Company TO iPaaS.com
Mapping filter:
var t1 = GetCustomField_CPHive(Parent, "USER_CONTCT_1_TYP");
var c1 = t1 == null ? "" : t1.ToString().Trim().ToUpper().Replace(" ", "");
var su1 = c1 == "S" || c1 == "SUPERUSER";
var t2 = GetCustomField_CPHive(Parent, "USER_CONTCT_2_TYP");
var c2 = t2 == null ? "" : t2.ToString().Trim().ToUpper().Replace(" ", "");
var su2 = c2 == "S" || c2 == "SUPERUSER";
if (su2 && string.IsNullOrEmpty(Parent.EMAIL_ADRS_2)) { throw new Exception("CRPT-VALD-1014 - Contact 2 of Counterpoint customer " + Parent.CUST_NO + " is designated Super User but the customer has no Email 2, so the Super User would receive Contact 1's email address. Enter Contact 2's email address in Email 2." + " - https://support.ipaas.com/en/articles/16003194-ncr-counterpoint-error-messages"); }
var contactId = await GetSpaceportIdAsync(Parent.CUST_NO + ":CONTCT_2", "Customer", SpaceportSystemId);
if (contactId == null) { if (su2) { throw new Exception("CRPT-BIZL-1008 - Contact 2 of Counterpoint customer " + Parent.CUST_NO + " is designated Super User but was not sent to iPaaS.com as a customer. Check that Contact 2 has a name in Counterpoint and that the customer passes the Customer TO iPaaS.com filter." + " - https://support.ipaas.com/en/articles/16003194-ncr-counterpoint-error-messages"); } return false; }
return true;
Relates Contact 2 to the company and sets its role.
Mappings (3):
IsPrimary: Static,
falseRelatedToId: Dynamic Formula,
await GetSpaceportIdAsync(Parent.CUST_NO + ":CONTCT_2", "Customer", SpaceportSystemId)Type: Dynamic Formula:
// Adobe Commerce/Magento 2 pre-creates only relationship types containing "user" before assigning them to the company.
var designation = GetCustomField_CPHive(Parent, "USER_CONTCT_2_TYP");
if (designation == null) { return "User"; }
var code = designation.ToString().Trim().ToUpper().Replace(" ", "");
if (code == "S" || code == "SUPERUSER") { return "Super User"; }
if (code == "A" || code == "ADMIN") { return "Admin User"; }
return "User";
If skipped: without the company collection, a marked customer's changes stop reaching iPaaS.com at all; without the relationship collections, a company has no Super User, and Adobe Commerce refuses it (MAGE-BIZL-1022).
Step 3: Change the existing Counterpoint collections
Subscriptions installed from older templates may show older collection names; each is given below.
Add/Update NCR Counterpoint Customer FROM iPaaS.com
Named CP Customer From iPaaS on older subscriptions.
Mapping filter: this collection ships with no filter. Add the one below. It stops a company's contacts from being written to Counterpoint, and stops any other customer that matches a Counterpoint customer that transfers as a company, by its link or by that customer's Email 1 or Email 2 (CRPT-BIZL-1007). If skipped: an iPaaS.com customer that shares a company's email address can be written over the company's Counterpoint customer, and each change to a contact that comes back from Adobe Commerce fails on its way to Counterpoint (CRPT-BIZL-1006).
If your collection already has a filter: put your own conditions at the very top of the filter below, each in the form
if (!(<your condition>)) { return false; }. For example, a filter ofEmailAddress != nullbecomesif (!(EmailAddress != null)) { return false; }. At the top, your conditions still apply while the settings are blank.
// Customer-as-company guard for NCR Counterpoint. Runs only while the Customer-as-company presets are set.
// Company contacts are never sent to Counterpoint, and a customer that matches a Counterpoint customer that transfers to
// iPaaS.com as a company, by its link or by that customer's Email 1 or Email 2, is stopped with error CRPT-BIZL-1007 instead.
string asCompanyField = GetSubscriptionSettingValue("Customer-as-company Field");
string asCompanyValue = GetSubscriptionSettingValue("Customer-as-company Field Value");
if (string.IsNullOrWhiteSpace(asCompanyField) || string.IsNullOrWhiteSpace(asCompanyValue))
{ return true; }
string linked = Convert.ToString(await GetExternalIdAsync(Id, "Customer", SpaceportSystemId));
if (!string.IsNullOrEmpty(linked) && linked.Contains(":CONTCT_"))
{ return false; }
string byEmail1 = null;
string byEmail2 = null;
if (string.IsNullOrEmpty(linked) && !string.IsNullOrWhiteSpace(EmailAddress))
{
byEmail1 = await CustomerFromEmailAsync(EmailAddress);
byEmail2 = await CustomerFromFieldAsync(EmailAddress, "EMAIL_ADRS_2");
}
string company = null;
string target = null;
foreach (var candidate in new string[] { linked, byEmail1, byEmail2 })
{
if (company == null && !string.IsNullOrEmpty(candidate))
{
var found = Convert.ToString(await GetSpaceportIdAsync(candidate, "Company", SpaceportSystemId));
if (!string.IsNullOrEmpty(found)) { company = found; target = candidate; }
}
}
if (company != null)
{
string reason = target == linked ? "it is linked to" : (target == byEmail1 ? "its email address is the Email 1 of" : "its email address is the Email 2 of");
string effect = target == linked || target == byEmail1 ? "sending it would overwrite the company's Counterpoint record" : "sending it would create a second Counterpoint customer with that contact's address";
string action = target == linked ? "See this error's resolution before changing the link." : "Give the customer an email address that does not belong to the company.";
throw new Exception("CRPT-BIZL-1007 - iPaaS.com customer " + Id + " was not sent to Counterpoint because " + reason + " Counterpoint customer " + target + ", which transfers to iPaaS.com as company " + company + "; " + effect + ". " + action + " - https://support.ipaas.com/en/articles/16003194-ncr-counterpoint-error-messages");
}
return true;
Add/Update NCR Counterpoint Customer TO iPaaS.com
Named CP Customer To iPaaS on older subscriptions.
Mapping filter: the template default is
IS_ECOMM_CUST=="Y". Replace it with the filter below, which keeps that check as its first line. It stops a company customer from also transferring as an ordinary customer. If skipped: a Manual Sync or resync of a company's customer number creates a second, ordinary iPaaS.com customer carrying the company's email address, which Adobe Commerce then matches to the company's Super User.If you changed the default filter: replace the filter's first check (the two lines starting
// Only e-commerce customers transfer.) with your own conditions, each in the formif (!(<your condition>)) { return false; }, and keep the rest.
// Only e-commerce customers transfer.
if (IS_ECOMM_CUST != "Y") { return false; }
// Customer-as-company: a Counterpoint customer that transfers to iPaaS.com as a company is never also sent as a customer. A
// plain-id transfer (a resync) is not routed to the company, so without this it would create a second customer carrying the
// company's email address. Company contacts, and every customer while the Customer-as-company presets are blank, pass as before.
if (Convert.ToString(CUST_NO).Contains(":CONTCT_")) { return true; }
if (string.IsNullOrWhiteSpace(GetSubscriptionSettingValue("Customer-as-company Field")) || string.IsNullOrWhiteSpace(GetSubscriptionSettingValue("Customer-as-company Field Value"))) { return true; }
return string.IsNullOrEmpty(Convert.ToString(await GetSpaceportIdAsync(CUST_NO, "Company", SpaceportSystemId)));
FirstName: change from the Field mapping on FST_NAM to this Dynamic Formula. Contacts get their own first name; every other customer keeps FST_NAM. If skipped (with LastName below): contacts reach Adobe Commerce with the company's name instead of their own.
// A company contact's record carries the company's first/last name; take the contact's own name (NAM) instead.
if (!Convert.ToString(CUST_NO).Contains(":CONTCT_")) { return FST_NAM; }
var contactName = Convert.ToString(NAM).Trim();
var cut = contactName.LastIndexOf(" ");
return cut > 0 ? contactName.Substring(0, cut).Trim() : contactName;
LastName: change from the Field mapping on LST_NAM to this Dynamic Formula.
// A company contact's record carries the company's first/last name; take the contact's own name (NAM) instead.
if (!Convert.ToString(CUST_NO).Contains(":CONTCT_")) { return LST_NAM; }
var contactName = Convert.ToString(NAM).Trim();
var cut = contactName.LastIndexOf(" ");
return cut > 0 ? contactName.Substring(cut + 1).Trim() : contactName;
Company: replace the formula
(CUST_NAM_TYP == "B" ? NAM : null)with this one. A contact belongs to its company through the relationship, so its own record carries no company name.
// A company contact belongs to its iPaaS.com company through the relationship records; its own name is not a company.
return Convert.ToString(CUST_NO).Contains(":CONTCT_") ? null : (CUST_NAM_TYP == "B" ? NAM : null);
Add/Update NCR Counterpoint Customer Billing Address TO iPaaS.com
Named CP Customer Billing Address To iPaaS on older subscriptions.
PhoneNumber: add a Dynamic Formula mapping,
Parent.PHONE_1. Adobe Commerce, by default, requires a telephone number on every customer address. This applies to every customer, not only contacts. If skipped: Adobe Commerce refuses the addresses (MAGE-EXTN-1001, "telephone" is required), which stops each contact and with it the company.
The five transaction collections
In each of these collections, replace the CUST_NO formula. Older names are in brackets.
Add NCR Counterpoint Order FROM iPaaS.com (CP Order Header From iPaaS)
Add NCR Counterpoint Sale Ticket FROM iPaaS.com (CP Sale Ticket From iPaaS)
Add NCR Counterpoint Deposit Ticket FROM iPaaS.com (CP Deposit Ticket From iPaaS)
Add NCR Counterpoint Item Refund FROM iPaaS.com (CP Item Refund From iPaaS)
Add NCR Counterpoint Deposit Refund FROM iPaaS.com (CP Deposit Refund From iPaaS)
Very old subscriptions may name the refund collections differently, for example CP Refund From iPaaS. Whatever the name, change every Counterpoint collection that sends transactions FROM iPaaS.com and whose CUST_NO mapping is one of the formulas below.
The formula it replaces is CustomerFromEmail(EmailAddress) or return await CustomerFromEmailAsync(EmailAddress);. The new formula first follows the customer the transaction is linked to, so an order placed by either of a company's contacts is recorded against the company's customer number, even when another Counterpoint customer has the same email address. Where the transaction has no linked customer, it matches the email address as before. If skipped: an order placed by Contact 2 reaches Counterpoint without a customer number, and an order whose email address several Counterpoint customers share can be recorded against the wrong one.
// Follow the transaction's iPaaS.com customer link first: a customer-as-company contact is linked to "<CUST_NO>:CONTCT_n", so its
// orders post to the company's Counterpoint customer; any other linked customer posts to its own CUST_NO. Without a link (guest
// orders, or a source that does not set it), match the email address as before.
var ipaasCustomerId = Convert.ToString(CustomerId);
if (!string.IsNullOrEmpty(ipaasCustomerId) && ipaasCustomerId != "0")
{
var linked = Convert.ToString(await GetExternalIdAsync(ipaasCustomerId, "Customer", SpaceportSystemId));
if (!string.IsNullOrEmpty(linked))
{
var cut = linked.IndexOf(":CONTCT_");
return cut > 0 ? linked.Substring(0, cut) : linked;
}
}
return await CustomerFromEmailAsync(EmailAddress);
Step 4: Change the Adobe Commerce/Magento 2 subscription
Integration version: 1.4.10 or later (see Before you start). If skipped: Adobe Commerce rejects the contacts' prefixed email addresses as invalid, which stops every company.
Collections: the subscription needs these three collections. If one is missing, add it with the mappings listed in its published mapping documentation:
Add/Update Adobe Commerce/Magento 2 Customer FROM iPaaS.com (named M2 Customer Add/Update From iPaaS on older subscriptions), which creates each contact in Adobe Commerce: iPaaS.com to Adobe Commerce/Magento 2 Customer Mapping Documentation;
Add/Update Adobe Commerce/Magento 2 Customer Category FROM iPaaS.com (M2 Customer Category From iPaaS), which creates the customer groups: iPaaS.com to Adobe Commerce/Magento 2 Customer Category Mapping Documentation;
Add/Update Adobe Commerce/Magento 2 Company FROM iPaaS.com (M2 Company Add/ Update From iPaaS), which creates the companies: iPaaS.com to Adobe Commerce/Magento 2 Company Mapping Documentation.
Outbound Data Flows: leave the company flow off for now. You turn it on in Step 6, after the first company is through. If the flow that sends customers to Adobe Commerce is already on, it stays on; if it is not, turning it on sends every changed iPaaS.com customer to Adobe Commerce, so decide that separately. With it on, company contacts' changes in Counterpoint reach their Adobe Commerce accounts too (see Changing or removing contacts).
No change for the email prefix: 1.4.10 removes it. Add/Update Adobe Commerce/Magento 2 Customer FROM iPaaS.com's Email stays the Field mapping from EmailAddress, and Add/Update Adobe Commerce/Magento 2 Company FROM iPaaS.com's SuperUserId stays
await GetSuperUserId(Id);.
Add/Update Adobe Commerce/Magento 2 Customer Category FROM iPaaS.com
TaxClassId: if your subscription's formula names the tax class Retail Customer 1, a placeholder, change it to name a customer tax class that exists in your store. Retail Customer is the default customer tax class Adobe Commerce creates:
await GetTaxIdByName("Retail Customer");If skipped: a name that matches no tax class in your store makes customer group updates fail (MAGE-EXTN-1001), and with them every company transfer that updates its group (MAGE-BIZL-1017).
ExcludeWebsiteIds: this collection ships with the example website name Excluded Website. Replace it with the websites you want excluded, or remove the mapping if none should be excluded.
Add/Update Adobe Commerce/Magento 2 Company FROM iPaaS.com
RegionId: replace the formula with this one. The original read the region only from an address custom field, so a company whose billing address carries a standard region, as Counterpoint's state does (for example TN), got no region and Adobe Commerce rejected it. The new formula falls back to the address's standard region. If skipped: Adobe Commerce rejects every company from Counterpoint, because each one's billing address carries a standard region.
var country=FieldFromFirstMatch(Addresses, "IsPrimaryBilling == true", "Country");
var customFields=FieldFromFirstMatch(Addresses, "IsPrimaryBilling == true", "CustomFields");
string regionValue = null;
if(customFields != null){
var regionId = GetCustomFieldValue(customFields, "region_id");
if(regionId != null && !string.IsNullOrEmpty(regionId.ToString())){ regionValue = regionId.ToString(); }
}
// Fallback: the address's standard Region (a region code or name) when the region_id custom field is not set.
if(string.IsNullOrEmpty(regionValue)){
var region = FieldFromFirstMatch(Addresses, "IsPrimaryBilling == true", "Region");
if(region != null && !string.IsNullOrEmpty(region.ToString())){ regionValue = region.ToString(); }
}
if(country != null && !string.IsNullOrEmpty(country.ToString()) && !string.IsNullOrEmpty(regionValue)){
var validRegionId= await GetRegionIdUsingCountryCodeAndRegionNameOrCode(country.ToString(),regionValue);
if(!string.IsNullOrEmpty(validRegionId)){
return validRegionId;
}
}
return null;
CustomerGroupId: replace the formula with this one. The original took the company's first category. iPaaS.com does not yet remove a company's earlier category assignments, so a company whose Counterpoint category changed kept its first customer group. The new formula takes the category named by the company's Department, which Counterpoint's company collection sets to the current category code on every transfer, and the first category only when none matches. If skipped: a company stays in its first customer group after its category changes in Counterpoint, and a group changed by hand in Adobe Commerce is set back on the company's next transfer.
// The company's customer group follows its current category. iPaaS.com does not yet remove a company's earlier category
// assignments, so Categories can still hold old ones; the category named by Department wins where the source sets it
// (NCR Counterpoint writes the customer's category code there). Otherwise the first category is used, as before.
string groupName = null;
if (Categories != null)
{
foreach (var category in Categories)
{
if (groupName == null && !string.IsNullOrEmpty(Department) && string.Equals(category.CategoryName, Department, StringComparison.OrdinalIgnoreCase)) { groupName = category.CategoryName; }
}
if (groupName == null) { groupName = Categories.FirstOrDefault()?.CategoryName; }
}
if (groupName == null) {return 0;}
else{ var id = await GetCategoryIdByName(groupName); return ConvertToInt(id); }
Add/Update Adobe Commerce/Magento 2 Order TO iPaaS.com and Add Adobe Commerce/Magento 2 Deposit Ticket TO iPaaS.com
Named M2 Order Header To iPaaS and M2 Deposit Ticket Add Only To iPaaS on older subscriptions.
CustomerId: add this Dynamic Formula mapping to both collections. It links each order, and its deposit ticket, to the iPaaS.com customer that the Adobe Commerce customer is linked to, which is what lets Counterpoint record the order against the company. Guest orders get no value from it. If skipped: orders are matched to Counterpoint by email address alone, so an order placed by Contact 2 is not recorded against the company.
// Link the transaction to the iPaaS.com customer that the order's Adobe Commerce/Magento 2 customer is linked to (the order
// prerequisite makes sure that link exists), so the destination can follow it. Guest orders stay unlinked.
var magentoCustomerId = Convert.ToString(CustomerId);
if (string.IsNullOrEmpty(magentoCustomerId) || magentoCustomerId == "0") { return null; }
return await GetSpaceportIdAsync(magentoCustomerId, "Customer", SpaceportSystemId);
Add/Update Adobe Commerce/Magento 2 Customer TO iPaaS.com and Add/Update Adobe Commerce/Magento 2 Customer Address TO iPaaS.com
Named M2 Customer To iPaaS and M2 Customer Address To iPaaS on older subscriptions. With customers syncing both ways, they bring each change made to an Adobe Commerce account back to iPaaS.com.
EmailAddress (Customer TO iPaaS.com): change from the Field mapping on Email to this Dynamic Formula. Adobe Commerce holds a company contact's email address without its CONTCT_1: or CONTCT_2: prefix, so the Field mapping writes the address without the prefix over the contact's iPaaS.com address each time the contact's account changes in Adobe Commerce. The formula keeps a contact's iPaaS.com address; every other customer still takes its Adobe Commerce address, including email address changes. If skipped: each change made in Adobe Commerce to a contact's account removes the prefix from the contact's iPaaS.com address until the company's next Counterpoint change, and while it is missing, a Counterpoint customer with the same email address can be linked to the contact and overwrite it.
// A Counterpoint company contact keeps its iPaaS.com address (CONTCT_1:<email> or CONTCT_2:<email>): Counterpoint owns it, and
// Adobe Commerce holds it without the prefix. Every other customer takes its Adobe Commerce address, so email changes still flow.
// DestinationValue (the iPaaS.com customer being updated) is null when the transfer adds a customer.
var current = DestinationValue == null ? null : Convert.ToString(DestinationValue.EmailAddress);
if (!string.IsNullOrEmpty(current) && (current.StartsWith("CONTCT_1:", StringComparison.OrdinalIgnoreCase) || current.StartsWith("CONTCT_2:", StringComparison.OrdinalIgnoreCase)))
return current;
return Email;
PhoneNumber (Customer Address TO iPaaS.com): add a Field mapping from Telephone. If skipped: each change made in Adobe Commerce rewrites the customer's iPaaS.com addresses without their phone number, clearing the billing telephone that Step 3 adds and Adobe Commerce requires, so the customer's next transfer to Adobe Commerce is refused.
Step 5: Switch customer-as-company on
First, check that no existing customer carries your marker. Run the readiness query (see Readiness query) with its marker line set to your marker. No company has been flagged as an e-commerce customer yet, so its first result must be empty: every customer it lists is an existing customer that carries your marker. Setting the two settings would switch each of them to a company in place on its next change, corrupting its records until it is repaired by hand. If the query lists any customer, choose a different marker (see Choose the company marker) before you continue.
On the NCR Counterpoint subscription, set both settings (see NCR Counterpoint Connections and Settings):
Customer-as-company Field: your company marker field from Step 1, for example USER_B2B_COMPANY or PROF_ALPHA_5.
Customer-as-company Field Value: the value that marks a company, for example Y or B2B.
Customers without the marker are not affected. They keep transferring as customers, to iPaaS.com and on to Adobe Commerce as before, and iPaaS.com can still send them back to Counterpoint.
From now on, the next change to a customer that carries the marker transfers it as a company, through the existing customer change notifications; there is no separate company notification to enable.
If you poll Counterpoint customers on a schedule instead of, or as well as, receiving change notifications, add the same schedule, with the same filter, for Add/Update NCR Counterpoint Company TO iPaaS.com: the customer poll now skips companies, and the company poll picks them up. The company poll transfers every customer its filter selects that carries the marker, whether or not it is an e-commerce customer yet, so give it a filter that selects e-commerce customers only. A company transferred by a scheduled poll arrives with its billing address but without its ship-to addresses; to transfer a company's ship-to addresses, run Manual Sync on Add/Update NCR Counterpoint Company TO iPaaS.com with its customer number.
Step 6: Create a company
For each new company, in this order:
Customer category to iPaaS.com: if the company's category is not already in iPaaS.com, run Manual Sync on Add/Update NCR Counterpoint Customer Category TO iPaaS.com (CP Customer Category To iPaaS on older subscriptions) with the Counterpoint category code.
Customer group in Adobe Commerce: run Manual Sync on Add/Update Adobe Commerce/Magento 2 Customer Category FROM iPaaS.com with the iPaaS.com customer category record's id, so the group exists before the contacts are created.
The customer in Counterpoint: create it with the company marker set and E-commerce customer not yet flagged, complete everything under What each new company customer needs, and check it with the readiness query, selected by its customer number. If you flag it first: it transfers as an ordinary customer, and setting the marker afterwards switches it to a company in place; with another customer's Email 1, it also takes over that customer's iPaaS.com record.
Flag it as an e-commerce customer. That save transfers the company to iPaaS.com: the company, its addresses, both contacts and their relationships. Without change notifications, run Manual Sync on Add/Update NCR Counterpoint Company TO iPaaS.com with the customer number; a Manual Sync of Add/Update NCR Counterpoint Company TO iPaaS.com transfers any customer number you give it as a company, marker or not, so use it only for a company. Do not Manual Sync a company's customer number on Add/Update NCR Counterpoint Customer TO iPaaS.com: a plain customer number there creates an ordinary customer carrying the company's email address.
The company, to Adobe Commerce: while the company flow is off (Step 4), run Manual Sync on Add/Update Adobe Commerce/Magento 2 Company FROM iPaaS.com with the iPaaS.com company record's id (the number on the company record in iPaaS.com, not its name). Once the flow is on, this happens automatically. The integration creates both contacts in Adobe Commerce first, then the company, with the Super User as its administrator and the other contact assigned as a company user.
Check the company (Step 7). In Dashboard / Integration Monitoring / Error Logs, MAGE-BIZL-1023 means a contact's email address belongs to an Adobe Commerce account that is already linked to another iPaaS.com customer: see An existing business that should become a company.
Once the first company is right, turn on the Adobe Commerce subscription's Outbound Data Flows for companies and customer categories (and for customers, if you decided to in Step 4), so later changes transfer automatically.
Step 7: Check the result
In iPaaS.com:
The company exists with its billing and ship-to addresses and its category.
Each contact exists with its own first and last name, and an email address starting CONTCT_1: or CONTCT_2:.
The company's relationships show one Super User, and the other contact as Admin User or User.
In Adobe Commerce:
The company exists with the Super User as its company administrator, and the category's customer group.
Both contacts are assigned to the company, with email addresses that have no prefix.
A change made in Adobe Commerce (in a test environment): change one contact's telephone number in Adobe Commerce, then run Manual Sync on Add/Update Adobe Commerce/Magento 2 Customer TO iPaaS.com with the contact's Adobe Commerce customer id. In iPaaS.com, the contact's email address still starts CONTCT_1: or CONTCT_2: (if not, check the Step 4 EmailAddress change), and its billing address still has a phone number (if not, check the Step 4 PhoneNumber change).
Orders (in a test environment): place a test order for each contact, for example as an admin-created order in Adobe Commerce; contacts created by the integration have no storefront password until they set one. The iPaaS.com transaction is linked to that contact, and the Counterpoint order carries the company's customer number. In production, a test order creates a real Counterpoint document.
An existing business that should become a company
Do not set the marker on the business's existing Counterpoint customer: that switches it to a company in place. Create a new Counterpoint customer for the company instead, as in Step 6, marked before it is flagged as an e-commerce customer.
If a contact's email address belongs to the existing customer's Adobe Commerce account, which is usual when Contact 1 uses the business's email address, Adobe Commerce refuses that contact with MAGE-BIZL-1023, and the company with MAGE-BIZL-1018, because the account is linked to the existing customer's iPaaS.com record. The failed transfer is requeued for a later retry. Choose one of the following:
Give the contact its own email address: change it in Counterpoint. The change transfers the company again, and a Manual Sync of Add/Update Adobe Commerce/Magento 2 Company FROM iPaaS.com with the company's iPaaS.com id then creates a new Adobe Commerce account for the contact. The existing customer keeps its own account and order history.
Move the existing Adobe Commerce account to the contact: the shopper keeps their login and order history as the company's contact. In this order, with steps 2 and 3 done one straight after the other:
In Counterpoint, take the existing customer off e-commerce. Its changes then no longer reach iPaaS.com, so none of them can link the account back to it. If skipped: with the customer Outbound Data Flow on, a change to the existing customer can link the account back to it before step 3, and the company is refused again (MAGE-BIZL-1023).
In iPaaS.com, open the existing customer's record and remove its Adobe Commerce/Magento 2 external ID, and the Adobe Commerce/Magento 2 external ID on each of its addresses. Without the address change, the account's addresses stay linked to the existing customer's, and every later change to the account in Adobe Commerce fails with NFND-1003. Until step 3 claims the account, a change to the account in Adobe Commerce can link it back to the existing customer. Keep the existing customer's iPaaS.com record after step 3: where your subscription sends customer deletions to Adobe Commerce, deleting a record still reaches the Adobe Commerce account it was linked to, even after that link is removed (see Deleting records in iPaaS.com), and after step 3 that account is the contact's.
Run Manual Sync on Add/Update Adobe Commerce/Magento 2 Company FROM iPaaS.com with the company's iPaaS.com id. The contact links to the account by email address, and the account joins the company as that contact (the Super User, for Contact 1). It keeps its order history and its addresses, takes the contact's name, and gains the company's billing address. If the company is still refused with MAGE-BIZL-1023, something linked the account back to the existing customer after step 2 (for example, an order placed with it): repeat steps 2 and 3.
If the existing customer should stay an e-commerce customer, give it a different Email 1 now, then flag it as an e-commerce customer again: it gets a new Adobe Commerce account of its own. While it is an e-commerce customer with the same address as the contact, each change to it is sent to Adobe Commerce and refused with MAGE-BIZL-1023, because the account belongs to the contact.
If the existing customer has no Adobe Commerce account, nothing refuses the company, and the contact gets a new account; still take the existing customer off e-commerce or give it a different Email 1, because once the contact holds the address, each change to the existing customer is refused the same way. Then resolve the refused transfers' errors in Dashboard / Integration Monitoring / Error Logs. The existing Counterpoint customer keeps its own history; nothing is moved to the new customer.
Repairing a customer that was switched to a company in place
A customer is switched to a company in place when the marker is set on an existing customer, one that has already transferred to iPaaS.com. The automatic transfers then do this:
The customer transfers as a company. iPaaS.com gets a company record and new contact records, whose email addresses start CONTCT_1: and CONTCT_2:, beside the customer's existing iPaaS.com record.
The existing iPaaS.com record stops receiving the customer's Counterpoint changes, and sending it back to Counterpoint is refused with CRPT-BIZL-1007, each time it is tried.
If the customer has an Adobe Commerce account: the company transfer to Adobe Commerce creates an account for any contact that has none yet (typically Contact 2), then refuses Contact 1 with MAGE-BIZL-1023, because its address belongs to the customer's account, and the company with MAGE-BIZL-1018. The failed transfer is requeued, and fails the same way until the customer is repaired.
If the customer never reached Adobe Commerce: nothing refuses the company. Adobe Commerce gets the company and a new account for each contact, with Contact 1's as the company administrator.
Both repairs start by clearing the marker. While the company exists, the customer's Counterpoint changes then go nowhere: they are not routed to the company, and the Customer TO iPaaS.com filter holds the customer back. So no automatic transfer re-creates the company or its contacts while you repair it, however long that takes. If skipped: a Counterpoint change during a repair runs the company transfer again, which re-creates what you have just removed, such as a contact record or its relationship.
Deleting records in iPaaS.com: at the time this documentation was written, where your Adobe Commerce subscription sends customer deletions to Adobe Commerce, deleting a contact record in iPaaS.com also deletes the Adobe Commerce account linked to it, even an account the shopper had before, and even after you remove the record's Adobe Commerce/Magento 2 external ID. Before you delete a contact record whose Adobe Commerce account should stay, turn off the customer/deleted trigger in the Adobe Commerce subscription's Outbound Data Flows and wait a minute before you delete the record; wait a few more minutes before you turn it back on. Turning it back on does not delete the account afterwards. Company deletions are not sent to Adobe Commerce.
Repair 1: make it a customer again
In Counterpoint, clear the marker.
If the company reached Adobe Commerce: in Adobe Commerce, delete the company.
In iPaaS.com, delete the new contact records (their email addresses start CONTCT_1: and CONTCT_2:).
In Adobe Commerce, delete the accounts the company transfer created for the contacts, where deleting their records did not.
In iPaaS.com, delete the company record. Do this last: until then the customer's changes still go nowhere, so it cannot transfer to Adobe Commerce and meet a contact's account that holds its email address.
In Counterpoint, make any change to the customer. It transfers as a customer again, catches up on the changes made while it was switched, and transfers on to Adobe Commerce: to its own account, or to a new account if it never had one. iPaaS.com can send it back to Counterpoint again.
Resolve the errors in Dashboard / Integration Monitoring / Error Logs.
Repair 2: finish the conversion to a company
If the company reached Adobe Commerce (the customer never had an Adobe Commerce account), nothing more is needed: the company keeps updating from Counterpoint, in iPaaS.com and Adobe Commerce. Leave the customer's existing iPaaS.com record in place; it is no longer updated.
If the company was refused, this keeps the customer's existing iPaaS.com record and Adobe Commerce account, and makes them the company's Contact 1:
In Counterpoint, clear the marker.
In iPaaS.com, on the company record, remove the relationship to the new Contact 1, then delete that new Contact 1 record (its email address starts CONTCT_1:). Keep this order: a relationship to a deleted record stops the company from transferring to Adobe Commerce.
Move the existing record's NCR Counterpoint links to Contact 1. External IDs can be removed in iPaaS.com; adding one is done through the iPaaS.com API or its MCP server, or by your MiSP or iPaaS.com Support. On the customer's existing iPaaS.com record:
remove the NCR Counterpoint external ID that is the customer number, for example 123456, and add 123456:CONTCT_1;
on its billing address, remove the NCR Counterpoint external ID 123456|BILL, and add 123456:CONTCT_1|BILL. Without the address change, the contact gets a second billing address, and sending the contact to Adobe Commerce fails;
leave its Adobe Commerce/Magento 2 external ID as it is.
In Counterpoint, set the marker again. That change transfers the company: the existing record becomes Contact 1 (its email address gains CONTCT_1:, and its billing address is updated in place), it is related to the company as Contact 1's type decides (the Super User by default), and the changes made during the repair catch up.
Run Manual Sync on Add/Update Adobe Commerce/Magento 2 Company FROM iPaaS.com with the company's iPaaS.com id. Adobe Commerce accepts the company: the existing account keeps its order history and, when Contact 1 is the Super User, becomes the company administrator; the other contact is assigned to the company. With the Adobe Commerce customer Outbound Data Flow on, the account then takes Contact 1's name from Counterpoint; with it off, it keeps the name it had in Adobe Commerce (see Changing or removing contacts).
Resolve the earlier errors in Dashboard / Integration Monitoring / Error Logs.
Changing or removing contacts
At the time this documentation was written:
Contact changes: changing a contact's name or email address in Counterpoint updates the contact in iPaaS.com. With the Adobe Commerce customer Outbound Data Flow on, as it is when customers sync both ways, that update is sent on to the contact's Adobe Commerce account too. With it off, Adobe Commerce receives a contact only when its account is first created or linked.
Changes made in Adobe Commerce: customers sync both ways, so a change to a contact's account in Adobe Commerce, by the shopper or a store admin, updates the contact in iPaaS.com with the Adobe Commerce values, except its email address: with the Step 4 EmailAddress formula, the contact keeps its CONTCT_1: or CONTCT_2: address (for the Super User's account, see The Super User's email address in Adobe Commerce below). The contact is not written to Counterpoint.
Contacts are kept by position: Contact 1 and Contact 2 are the same iPaaS.com records, whoever holds them. Entering a different person as Contact 2 turns the existing contact record into the new person. With the customer Outbound Data Flow on, the change reaches Adobe Commerce too, so the new person takes over the previous person's Adobe Commerce account, with its login and order history; with it off, the account stays the previous person's and the new person gets none. If you skip the removal: either way, the wrong person ends up on an account, so always remove the previous Contact 2 first (below), then enter the new person. Entering a different person as Contact 1 changes Email 1, which stops the company until Contact 1 is put back (see Changing Email 1); with the flow on, the new person also takes over Contact 1's Adobe Commerce account. The removal below is for Contact 2 only.
Changing Email 1: on a company that is already in Adobe Commerce, for example by entering a different person as Contact 1 (see also Contacts are kept by position) or swapping the two contacts, this stops the company's transfers to Adobe Commerce with MAGE-EXTN-1001 ("super_user_id" is required). With the Adobe Commerce customer Outbound Data Flow on, swapping the two contacts also stops both contacts' own transfers to Adobe Commerce with MAGE-EXTN-1001 ("A customer with the same email address already exists in an associated website"), because each contact's new address still belongs to the other contact's account. Putting the contacts back as they were, names and email addresses both, restores them all; then resolve the errors in Dashboard / Integration Monitoring / Error Logs. Keep Email 1 unchanged once the company is in Adobe Commerce.
The Super User's email address in Adobe Commerce: changing it there, for example when the shopper edits their account, does not change the contact, which keeps its Counterpoint address. With the Adobe Commerce customer Outbound Data Flow on, the change lasts only until the company's next transfer from Counterpoint, which a change to the company there starts: that transfer sends the contact to Adobe Commerce again with its Counterpoint address, and the shopper must then sign in with that address again. With the flow off, the change stops the company's transfers to Adobe Commerce with MAGE-EXTN-1001 ("super_user_id" is required), because the company's transfer to Adobe Commerce finds its administrator by the email address Counterpoint gives the contact; changing it back restores them, and then resolve the errors in Dashboard / Integration Monitoring / Error Logs. Either way, do not change a contact's email address in Adobe Commerce. If a shopper has changed it, change it back there (or, with the flow on, make a change to the company in Counterpoint) and tell the shopper which address to sign in with. A contact's email address is changed in Counterpoint (see Contact changes), with two exceptions: Contact 1's is the company's Email 1, which must stay unchanged once the company is in Adobe Commerce (see Changing Email 1); and with the flow off, a change to the Super User's address in Counterpoint does not reach its account, which stops the company's transfers as above.
Moving the Super User: from one contact to the other, this changes the relationship types in iPaaS.com, but Adobe Commerce keeps the company's existing administrator. Change the administrator in Adobe Commerce if you need to.
Removing a contact: clearing Contact 2 in Counterpoint removes nothing; its iPaaS.com record, its relationship to the company and its Adobe Commerce company user all stay. If Contact 2 is the Super User, first make Contact 1 the Super User (see Choosing the Super User) and change the company administrator in Adobe Commerce to Contact 1's account. Then:
In Adobe Commerce, remove the person from the company, or deactivate their account; the integration leaves them assigned, and until then they can still buy for the company.
In Counterpoint, clear the company's marker, and clear Contact 2 (and the matching custom contact field), Email 2 and Contact 2's type. With the marker cleared, the company's changes go nowhere, so nothing adds the contact back while you work.
In iPaaS.com, on the company record, remove the relationship to that contact, then delete the contact's record (its email address starts CONTCT_2:). Keep this order: a relationship to a deleted record stops the company from transferring to Adobe Commerce. Where your subscription sends customer deletions to Adobe Commerce, deleting the record also deletes the person's Adobe Commerce account, even with its Adobe Commerce/Magento 2 external ID removed; to keep it, turn off the customer/deleted trigger first (see Deleting records in iPaaS.com).
To add a different person as Contact 2, enter them in Counterpoint now, with their own Email 2.
In Counterpoint, set the company's marker again, in a save that keeps it an e-commerce customer with an Email 1. That change transfers the company, with every change made while it was paused: a person entered in step 4 is created as a new iPaaS.com record and a new Adobe Commerce account. The account is assigned to the company when the company's transfer to Adobe Commerce completes, so check the assignment after that, not as soon as the account appears.
Error reference
Errors appear in Dashboard / Integration Monitoring / Error Logs. The CRPT- and MAGE- codes below are also described in the NCR Counterpoint Error Messages and Adobe Commerce/Magento 2 Error Messages articles.
CRPT-VALD-1012: both contacts are designated Super User. Designate exactly one.
CRPT-VALD-1013: Contact 1 has a type but no contact is designated Super User. Designate Contact 1 or Contact 2 as S.
CRPT-VALD-1014: the Super User contact, designated or by default, has no email address of its own. Enter it in Email 1 (Contact 1) or Email 2 (Contact 2).
CRPT-BIZL-1005: a contact could not be transferred to iPaaS.com as a customer. Check the contact's name and email address.
CRPT-BIZL-1006: a company contact was sent back to Counterpoint. Contacts exist only in iPaaS.com and cannot be written to Counterpoint.
CRPT-BIZL-1007: an iPaaS.com customer was not written to Counterpoint because it matches a customer that transfers as a company: it is linked to it, or carries its Email 1 or Email 2. The message says which.
For a customer that was switched to a company in place, see Repairing a customer that was switched to a company in place.
For any other customer, one that carries a company's Email 1 or Email 2: change its email address. It is then created in Counterpoint as a new customer.
CRPT-BIZL-1008: the designated Super User contact was not sent to iPaaS.com. Check that the contact has a name and that the company passes the Customer TO iPaaS.com filter.
MAGE-BIZL-1017: the company's customer group could not be created in Adobe Commerce, so the company was not transferred. Check the customer category transfer, including TaxClassId (Step 4).
MAGE-BIZL-1018: a contact could not be created in Adobe Commerce while preparing the company, so the company was not transferred. Check the contact's data and email address; MAGE-BIZL-1023 is the usual cause. It also happens when the company has a relationship to a deleted contact record: remove that relationship (see Changing or removing contacts).
MAGE-BIZL-1022: the company's Super User does not exist in iPaaS.com, or is already the Super User of another Adobe Commerce company.
MAGE-BIZL-1023: the Adobe Commerce customer with this email address is already linked to a different iPaaS.com customer. For a new company, see An existing business that should become a company; for a customer that was switched to a company in place, see Repairing a customer that was switched to a company in place.
MAGE-EXTN-1001 ("super_user_id" is required): the company's Super User, or the Adobe Commerce company itself, could not be matched by email address. Usually the company's Email 1 changed after the company reached Adobe Commerce, or the Super User's email address was changed in Adobe Commerce and the company transferred before the address was put back (see The Super User's email address in Adobe Commerce), or the address contains a + (see What each new company customer needs).
MAGE-EXTN-1001 ("A customer with the same email address already exists in an associated website") on a contact: the contact's email address from Counterpoint belongs to a different Adobe Commerce account. If the company's two contacts were swapped, swap them back (see Changing Email 1). Otherwise, for Contact 2, give it an Email 2 that no other Adobe Commerce account uses; for Contact 1, put Email 1 back to the address it had.
NFND-1003 ("Address Id ... does not exist") on a customer transfer from Adobe Commerce: the account's addresses are still linked to another iPaaS.com customer's addresses, typically after the account was moved to a company contact. Remove the Adobe Commerce/Magento 2 external ID from that customer's addresses (see An existing business that should become a company).
Troubleshooting
No customer transfers as a company: check the spelling and capitalization of the field in Customer-as-company Field. A name that is not a Counterpoint customer field or custom field treats every customer as an ordinary customer, with only a warning in the log.
A company never arrives in iPaaS.com: check that it is flagged as an e-commerce customer and has an Email 1; otherwise CPWebhooks reports no change for it. Manual Sync (Step 6, item 4) still works.
Existing customers are transferring as companies: the marker is a field your existing customers already carry, such as the Name type. Point Customer-as-company Field at a dedicated field (Step 1), and set it on each company that should stay a company. That stops further switches, and leaves each customer that switched by mistake as if its marker were cleared. Then repair each one (see Repairing a customer that was switched to a company in place), starting from step 2 of the repair; for Repair 2, set the new marker on it in step 4.
A company arrives without contacts: check that the company passes your Customer TO iPaaS.com filter and that Contact 1 and Contact 2 hold names.
How it behaves afterwards
At the time this documentation was written:
Contact email addresses keep their CONTCT_1: / CONTCT_2: prefix in iPaaS.com by design. Adobe Commerce receives them without it, and matches its existing customers without it.
Keep contact details in Counterpoint. A contact's name and email address come from Counterpoint. For what a change there does in Adobe Commerce, see Changing or removing contacts.
An order placed by a registered Adobe Commerce customer is recorded in Counterpoint against the customer that customer is linked to: the company, for a company's contacts. A guest order is linked only where iPaaS.com already has a customer with its email address; otherwise Counterpoint matches it by email address.
Gift card tickets are not linked to the contact who bought them; they are linked only where iPaaS.com already has a customer with the same email address, and otherwise matched by email address.
A company's customer categories are added to, not replaced, when they change in Counterpoint, and its last category cannot be removed. The company's Adobe Commerce customer group follows its current category once the CustomerGroupId change in Step 4 is made; without it, the group stays on the first category.
While a customer's company exists in iPaaS.com, clearing its marker stops its Counterpoint changes altogether: they are not routed to the company, and the Customer TO iPaaS.com filter holds the customer back. The repairs use this as a pause. To make it a customer again, follow Repair 1.
Readiness query
Copy this read-only query into SQL Server Management Studio and run it against your Counterpoint company database, as described in Check the data before you flag a company as an e-commerce customer (Step 1) and in Step 5. Before you run it, adjust the lines its BEFORE RUNNING header names: your company marker, your Customer TO iPaaS.com filter, and the contact fields where your installation does not have them. For the Step 5 check, an empty first result is the result you want.
-- CPHive customer-as-company: readiness check -- READ ONLY
--
-- Lists the Counterpoint customers it selects (by default, those that will transfer to iPaaS.com as companies)
-- and the problems it can find in Counterpoint that would stop one (or one of its contacts) from reaching
-- iPaaS.com or Adobe Commerce/Magento 2 B2B, including signs that a customer is not a new one. It cannot see
-- Adobe Commerce, so an email address that already belongs to an Adobe Commerce account shows only when the
-- company transfers. It changes no Counterpoint data (it only uses temporary tables): run it in SQL Server
-- Management Studio against your Counterpoint company database, fix the data it reports in Counterpoint, and
-- run it again until part 2 returns no BLOCKS rows. Part 1 must list the customers you meant to check: an empty
-- Part 1 means the selection matched nothing, not that there are no problems.
--
-- Before you switch customer-as-company on, run it once with your marker: Part 1 must then be EMPTY. No company
-- has been flagged as an e-commerce customer yet, so every customer it lists is an existing customer that carries
-- your marker, and switching on would turn each one into a company in place, corrupting its records until it
-- is repaired by hand.
--
-- The checks follow the integration's company routing, its contacts, and the Type rules of the Contact 1 /
-- Contact 2 relationship collections.
--
-- BEFORE RUNNING
-- 1. The two lines marked <== YOUR COMPANY MARKER and <== YOUR CUSTOMER TO iPaaS.com FILTER select
-- the customers to check.
-- - All your companies: the marker line ships as the example marker PROF_ALPHA_5 = 'B2B'. Change it to
-- the Customer-as-company Field and Value on your NCR Counterpoint subscription. The next line limits
-- it to e-commerce customers, as the Customer TO iPaaS.com filter does; change it too if your filter
-- differs.
-- - One new company, before you flag it as an e-commerce customer: keep your marker line and replace the
-- e-commerce line with its customer number, for example
-- AND c.CUST_NO = '123456';
-- Part 1 then lists it only if it carries the marker.
-- 2. The contact type fields USER_CONTCT_1_TYP / USER_CONTCT_2_TYP are custom fields. If your
-- installation does not have them, in the two lines marked <== TYPE FIELD replace
-- c.USER_CONTCT_1_TYP and c.USER_CONTCT_2_TYP with NULL , and keep the rest of each line.
-- 3. The custom contact name fields USER_CONTCT_1 / USER_CONTCT_2 must match the standard Contact 1 and
-- Contact 2. If your installation does not have them, in the two lines marked <== CONTACT FIELD
-- replace c.USER_CONTCT_1 and c.USER_CONTCT_2 with c.CONTCT_1 and c.CONTCT_2 , and keep the rest
-- of each line.
--
-- OUTPUT
-- Part 1: one row per company. Save it as a CSV if iPaaS.com or your MiSP is comparing it with your
-- iPaaS.com data.
-- Part 2: one row per problem. SEVERITY is
-- BLOCKS the company, or its Super User, will not reach Adobe Commerce until this is fixed;
-- CHECK not always an error: read the DETAIL and decide.
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#co') IS NOT NULL DROP TABLE #co;
IF OBJECT_ID('tempdb..#em') IS NOT NULL DROP TABLE #em;
SELECT
c.CUST_NO,
c.NAM,
NULLIF(LTRIM(RTRIM(c.FST_NAM)), '') AS FST_NAM,
NULLIF(LTRIM(RTRIM(c.LST_NAM)), '') AS LST_NAM,
NULLIF(LTRIM(RTRIM(c.CONTCT_1)), '') AS CONTCT_1,
NULLIF(LTRIM(RTRIM(c.CONTCT_2)), '') AS CONTCT_2,
NULLIF(LTRIM(RTRIM(c.USER_CONTCT_1)), '') AS USER_CONTCT_1, -- <== CONTACT FIELD
NULLIF(LTRIM(RTRIM(c.USER_CONTCT_2)), '') AS USER_CONTCT_2, -- <== CONTACT FIELD
NULLIF(LTRIM(RTRIM(c.EMAIL_ADRS_1)), '') AS EMAIL_1,
NULLIF(LTRIM(RTRIM(c.EMAIL_ADRS_2)), '') AS EMAIL_2,
NULLIF(LTRIM(RTRIM(c.PHONE_1)), '') AS PHONE_1,
NULLIF(LTRIM(RTRIM(c.ADRS_1)), '') AS ADRS_1,
NULLIF(LTRIM(RTRIM(c.CITY)), '') AS CITY,
NULLIF(LTRIM(RTRIM(c.STATE)), '') AS STATE,
NULLIF(LTRIM(RTRIM(c.ZIP_COD)), '') AS ZIP_COD,
NULLIF(LTRIM(RTRIM(c.CATEG_COD)), '') AS CATEG_COD,
c.IS_ECOMM_CUST,
COALESCE(c.FST_SAL_DAT, c.LST_SAL_DAT) AS FIRST_SALE,
-- The integration reads a type as: trimmed, upper case, spaces removed; "!" (no selection) is unset.
NULLIF(NULLIF(UPPER(REPLACE(LTRIM(RTRIM(CAST(c.USER_CONTCT_1_TYP AS varchar(20)))), ' ', '')), ''), '!') AS TYPE_1, -- <== TYPE FIELD
NULLIF(NULLIF(UPPER(REPLACE(LTRIM(RTRIM(CAST(c.USER_CONTCT_2_TYP AS varchar(20)))), ' ', '')), ''), '!') AS TYPE_2 -- <== TYPE FIELD
INTO #co
FROM dbo.AR_CUST AS c
WHERE c.PROF_ALPHA_5 = 'B2B' -- <== YOUR COMPANY MARKER
AND c.IS_ECOMM_CUST = 'Y'; -- <== YOUR CUSTOMER TO iPaaS.com FILTER (only these customers reach iPaaS.com)
-- Every e-commerce customer's addresses, normalized once, for the shared-address checks.
SELECT CUST_NO, NAM, 'Email 1' AS WHICH, LOWER(LTRIM(RTRIM(EMAIL_ADRS_1))) AS EMAIL
INTO #em
FROM dbo.AR_CUST
WHERE IS_ECOMM_CUST = 'Y' AND NULLIF(LTRIM(RTRIM(EMAIL_ADRS_1)), '') IS NOT NULL
UNION ALL
SELECT CUST_NO, NAM, 'Email 2', LOWER(LTRIM(RTRIM(EMAIL_ADRS_2)))
FROM dbo.AR_CUST
WHERE IS_ECOMM_CUST = 'Y' AND NULLIF(LTRIM(RTRIM(EMAIL_ADRS_2)), '') IS NOT NULL;
-- Part 1: the companies ----------------------------------------------------------------------------
SELECT CUST_NO, NAM, EMAIL_1 AS EMAIL_ADRS_1, EMAIL_2 AS EMAIL_ADRS_2, CONTCT_1, CONTCT_2,
ISNULL(TYPE_1, '') AS CONTCT_1_TYP, ISNULL(TYPE_2, '') AS CONTCT_2_TYP, IS_ECOMM_CUST
FROM #co
ORDER BY CUST_NO;
-- Part 2: the problems -----------------------------------------------------------------------------
WITH co AS (
SELECT *,
CASE WHEN TYPE_1 IN ('S', 'SUPERUSER') THEN 1 ELSE 0 END AS SU_1,
CASE WHEN TYPE_2 IN ('S', 'SUPERUSER') THEN 1 ELSE 0 END AS SU_2
FROM #co
),
problems AS (
-- The company's own data
SELECT CUST_NO, 'BLOCKS' AS SEVERITY, 'No Email 1' AS [CHECK],
'Email 1 is the company''s email address and Contact 1''s. Counterpoint also sends no change notification for a customer without it.' AS DETAIL
FROM co WHERE EMAIL_1 IS NULL
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'No category',
'The category becomes the company''s Adobe Commerce customer group, and the templates assign none. Assign one in Counterpoint, or supply one with your own mapping.'
FROM co WHERE CATEG_COD IS NULL
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'No Phone 1', 'Phone 1 is the company''s telephone number and the telephone on its billing addresses.' FROM co WHERE PHONE_1 IS NULL
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'Incomplete billing address',
'Missing:' + CASE WHEN ADRS_1 IS NULL THEN ' Address 1' ELSE '' END + CASE WHEN CITY IS NULL THEN ' City' ELSE '' END
+ CASE WHEN STATE IS NULL THEN ' State' ELSE '' END + CASE WHEN ZIP_COD IS NULL THEN ' Zip code' ELSE '' END
FROM co WHERE ADRS_1 IS NULL OR CITY IS NULL OR STATE IS NULL OR ZIP_COD IS NULL
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'No first or last name', 'First name and Last name are the recipient name on the billing addresses.' FROM co WHERE FST_NAM IS NULL OR LST_NAM IS NULL
UNION ALL
SELECT CUST_NO, 'CHECK', 'Not an e-commerce customer yet',
'Counterpoint sends no change notification for it until it is an e-commerce customer. Once this query shows no BLOCKS rows and the customer carries your company marker, flag it as an e-commerce customer: that save transfers the company.'
FROM co WHERE ISNULL(IS_ECOMM_CUST, 'N') <> 'Y'
UNION ALL
SELECT CUST_NO, 'CHECK', 'Looks like an existing customer',
'Counterpoint records sales for this customer (first sale ' + CONVERT(varchar(10), FIRST_SALE, 23) + '), so it looks like an existing customer rather than a new one created for the company. If it has ever transferred to iPaaS.com, setting the marker switches it to a company in place, which is not supported: see An existing business that should become a company in the guide.'
FROM co WHERE FIRST_SALE IS NOT NULL
-- The contact types (the same rules the relationship collections apply)
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'CRPT-VALD-1012', 'Both contacts are designated Super User. Designate exactly one.' FROM co WHERE SU_1 = 1 AND SU_2 = 1
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'CRPT-VALD-1013', 'Contact 1 has type ' + TYPE_1 + ' and no contact is designated Super User. Designate Contact 1 or Contact 2 as S.' FROM co WHERE TYPE_1 IS NOT NULL AND SU_1 = 0 AND SU_2 = 0
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'CRPT-VALD-1014', 'Contact 2 is designated Super User but there is no Email 2.' FROM co WHERE SU_2 = 1 AND EMAIL_2 IS NULL
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'CRPT-BIZL-1008', 'Contact ' + CASE WHEN SU_1 = 1 THEN '1' ELSE '2' END + ' is designated Super User but has no name, so it is not transferred.'
FROM co WHERE (SU_1 = 1 AND CONTCT_1 IS NULL) OR (SU_2 = 1 AND CONTCT_2 IS NULL)
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'No Super User', 'Contact 1 has no name and no type, and Contact 2 is not designated S, so the company has no Super User (Adobe Commerce refuses it with MAGE-BIZL-1022).'
FROM co WHERE CONTCT_1 IS NULL AND TYPE_1 IS NULL AND SU_2 = 0
UNION ALL
SELECT CUST_NO, 'CHECK', 'Contact name fields differ',
'The custom contact fields must hold the same names as the standard fields. Different:'
+ CASE WHEN UPPER(ISNULL(CONTCT_1, '')) <> UPPER(ISNULL(USER_CONTCT_1, '')) THEN ' Contact 1' ELSE '' END
+ CASE WHEN UPPER(ISNULL(CONTCT_2, '')) <> UPPER(ISNULL(USER_CONTCT_2, ''))
THEN CASE WHEN UPPER(ISNULL(CONTCT_1, '')) <> UPPER(ISNULL(USER_CONTCT_1, '')) THEN ' and Contact 2' ELSE ' Contact 2' END ELSE '' END
+ '. The integration reads the standard fields.'
FROM co WHERE UPPER(ISNULL(CONTCT_1, '')) <> UPPER(ISNULL(USER_CONTCT_1, '')) OR UPPER(ISNULL(CONTCT_2, '')) <> UPPER(ISNULL(USER_CONTCT_2, ''))
-- Contact 2's email address
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'Contact 2 has no Email 2', 'Contact 2 falls back to Email 1, the same address as Contact 1, so Adobe Commerce refuses one of the two contacts (MAGE-BIZL-1023), which stops the company. Enter Contact 2''s own address in Email 2.'
FROM co WHERE CONTCT_2 IS NOT NULL AND EMAIL_2 IS NULL
UNION ALL
SELECT CUST_NO, 'BLOCKS', 'Email 2 is the same as Email 1', 'Contact 2 would share Contact 1''s address, so Adobe Commerce refuses one of the two contacts (MAGE-BIZL-1023), which stops the company.'
FROM co WHERE CONTCT_2 IS NOT NULL AND EMAIL_2 IS NOT NULL AND LOWER(EMAIL_2) = LOWER(EMAIL_1)
UNION ALL
SELECT CUST_NO, 'CHECK', 'A + in an email address', 'On some Adobe Commerce stores an address containing + cannot be looked up.'
FROM co WHERE EMAIL_1 LIKE '%+%' OR (CONTCT_2 IS NOT NULL AND EMAIL_2 LIKE '%+%')
-- Addresses shared with another e-commerce customer
UNION ALL
SELECT co.CUST_NO, 'CHECK', 'Email 1 shared',
'Email 1 is also ' + e.WHICH + ' of customer ' + e.CUST_NO + ' (' + ISNULL(e.NAM, '') + '). If that customer is in Adobe Commerce, Contact 1 is refused (MAGE-BIZL-1023).'
FROM co JOIN #em AS e ON e.EMAIL = LOWER(co.EMAIL_1) AND e.CUST_NO <> co.CUST_NO
UNION ALL
SELECT co.CUST_NO, 'CHECK', 'Email 2 shared',
'Email 2 is also ' + e.WHICH + ' of customer ' + e.CUST_NO + ' (' + ISNULL(e.NAM, '') + '). If that customer is in Adobe Commerce, Contact 2 is refused (MAGE-BIZL-1023).'
FROM co JOIN #em AS e ON e.EMAIL = LOWER(co.EMAIL_2) AND e.CUST_NO <> co.CUST_NO
WHERE co.CONTCT_2 IS NOT NULL
-- iPaaS.com requires a new company's name and department to be unique, and the Department mapping carries the category code
UNION ALL
SELECT co.CUST_NO, 'CHECK', 'Name and category shared',
'Customer ' + x.CUST_NO + ' (e-commerce: ' + ISNULL(x.IS_ECOMM_CUST, 'N') + ') has the same name and category. If both transfer to iPaaS.com as companies, iPaaS.com refuses the second: a new company''s name and department must be unique, and the Department mapping carries the category code. Give each company a distinct name.'
FROM co JOIN dbo.AR_CUST AS x
ON x.CUST_NO <> co.CUST_NO
AND UPPER(LTRIM(RTRIM(x.NAM))) = UPPER(LTRIM(RTRIM(co.NAM)))
AND ISNULL(UPPER(LTRIM(RTRIM(x.CATEG_COD))), '') = ISNULL(UPPER(co.CATEG_COD), '')
)
SELECT p.CUST_NO, co.NAM, p.SEVERITY, p.[CHECK], p.DETAIL
FROM problems AS p JOIN co ON co.CUST_NO = p.CUST_NO
ORDER BY p.CUST_NO, CASE p.SEVERITY WHEN 'BLOCKS' THEN 0 ELSE 1 END, p.[CHECK];
DROP TABLE #em;
DROP TABLE #co;
