abmp-npm 2.0.34 → 2.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +0 -3
- package/backend/README-member-contact-flows.md +136 -0
- package/backend/contacts-methods.js +9 -108
- package/backend/member-contact-orchestration.js +106 -0
- package/backend/members-area-methods.js +4 -0
- package/backend/members-data-methods.js +25 -16
- package/backend/utils.js +4 -0
- package/package.json +1 -1
package/.husky/pre-commit
CHANGED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Member–Contact Flows
|
|
2
|
+
|
|
3
|
+
How Wix **Members** (login identity) and **CRM Contacts** (form/submission identity) stay in sync in ABMP.
|
|
4
|
+
|
|
5
|
+
## Concepts
|
|
6
|
+
|
|
7
|
+
| Concept | Meaning |
|
|
8
|
+
| ---------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| **Single entity** | Member and contact use the same Wix ID (`wixContactId === wixMemberId`). One person, one record. |
|
|
10
|
+
| **Separate contact** | Member has a login email; contact has a different “form” email. Two Wix entities: one Member, one Contact. |
|
|
11
|
+
| **Login email** | `memberData.email` — used to sign in (Wix Member). |
|
|
12
|
+
| **Contact form email** | `memberData.contactFormEmail` — email used on forms; can differ from login. |
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 1. Login / first-time flow: `createContactAndMemberIfNew`
|
|
17
|
+
|
|
18
|
+
**Used when:** A user logs in or is created and we need to ensure they have both a Wix Member and (if needed) a CRM Contact.
|
|
19
|
+
|
|
20
|
+
**File:** `members-data-methods.js` → `createContactAndMemberIfNew(memberData)`
|
|
21
|
+
|
|
22
|
+
### Logic in short
|
|
23
|
+
|
|
24
|
+
- If no **Wix Member** → create one (login identity).
|
|
25
|
+
- If no **Wix Contact** and contact form email **differs** from login email → create a separate Contact.
|
|
26
|
+
- If contact form email **equals** login email → no separate contact; we use the member ID as the contact ID (single entity).
|
|
27
|
+
- Persist `wixMemberId` and `wixContactId` on the member record.
|
|
28
|
+
|
|
29
|
+
### Flow diagram
|
|
30
|
+
|
|
31
|
+
```mermaid
|
|
32
|
+
flowchart TD
|
|
33
|
+
A[createContactAndMemberIfNew] --> B{Has wixMemberId?}
|
|
34
|
+
B -->|No| C[Create Wix Member]
|
|
35
|
+
B -->|Yes| D{Has wixContactId?}
|
|
36
|
+
C --> D
|
|
37
|
+
D -->|No| E{contactFormEmail !== email?}
|
|
38
|
+
D -->|Yes| K[Keep existing IDs]
|
|
39
|
+
E -->|Yes| F[Create Wix Contact]
|
|
40
|
+
E -->|No| G[Use member ID as contact ID]
|
|
41
|
+
F --> H[Resolve IDs]
|
|
42
|
+
G --> H
|
|
43
|
+
K --> H
|
|
44
|
+
H[newWixContactId = createdContact OR memberId] --> I[Set wixMemberId, wixContactId on member]
|
|
45
|
+
I --> J[updateMember + return]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Parallel work
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
┌─────────────────────────────────────┐
|
|
52
|
+
│ createContactAndMemberIfNew │
|
|
53
|
+
└─────────────────────────────────────┘
|
|
54
|
+
│
|
|
55
|
+
┌───────────────────┴───────────────────┐
|
|
56
|
+
│ Promise.all([ │
|
|
57
|
+
│ runIf(needsWixMember, createMember), │
|
|
58
|
+
│ runIf(needsContact && differentEmail, │
|
|
59
|
+
│ createContact) │
|
|
60
|
+
│ ]) │
|
|
61
|
+
└───────────────────┬───────────────────┘
|
|
62
|
+
│
|
|
63
|
+
newWixContactId = createdWixContactId || newWixMemberId
|
|
64
|
+
(if no separate contact, member ID is the contact ID)
|
|
65
|
+
│
|
|
66
|
+
┌───────────────────┴───────────────────┐
|
|
67
|
+
│ updateMember({ ...memberData, │
|
|
68
|
+
│ wixMemberId, wixContactId }) │
|
|
69
|
+
└───────────────────────────────────────┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Outcome
|
|
73
|
+
|
|
74
|
+
| Scenario | wixMemberId | wixContactId |
|
|
75
|
+
| --------------------------------------- | ------------- | ----------------------------------- |
|
|
76
|
+
| New user, same email for login and form | New member ID | Same as wixMemberId (single entity) |
|
|
77
|
+
| New user, form email ≠ login email | New member ID | New contact ID (separate contact) |
|
|
78
|
+
| Existing user (already has both IDs) | Unchanged | Unchanged |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 2. Update contact email flow: `updateContactEmail`
|
|
83
|
+
|
|
84
|
+
**Used when:** User changes their contact/form email in the app and we need to update CRM and optionally the member record.
|
|
85
|
+
|
|
86
|
+
**File:** `member-contact-orchestration.js` → `updateContactEmail(newContactEmail, existingMemberData)` (used by `updateMemberContactInfo`).
|
|
87
|
+
|
|
88
|
+
### Logic in short
|
|
89
|
+
|
|
90
|
+
- **Single entity** (`wixContactId === wixMemberId`):
|
|
91
|
+
- If new email **equals** login → no change.
|
|
92
|
+
- If new email **differs** → create a new Contact with the new email and point the member to it (we now have a separate contact).
|
|
93
|
+
- **Separate contact** (different IDs):
|
|
94
|
+
- If new email **equals** login → delete the extra contact and set `wixContactId = wixMemberId` (collapse to single entity).
|
|
95
|
+
- If new email **differs** → update the existing contact’s email in CRM.
|
|
96
|
+
|
|
97
|
+
### Flow diagram
|
|
98
|
+
|
|
99
|
+
```mermaid
|
|
100
|
+
flowchart TD
|
|
101
|
+
A[updateContactEmail] --> B{contactEmail === loginEmail?}
|
|
102
|
+
B -->|Yes| C{Single entity?}
|
|
103
|
+
B -->|No| D{Single entity?}
|
|
104
|
+
C -->|Yes| E[No-op: already in sync]
|
|
105
|
+
C -->|No| F[Delete contact\nSet wixContactId = wixMemberId]
|
|
106
|
+
D -->|Yes| G[Create new Contact with new email\nUpdate member wixContactId]
|
|
107
|
+
D -->|No| H[Update existing contact email in CRM]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Decision table
|
|
111
|
+
|
|
112
|
+
| Single entity? | New email vs login | Action |
|
|
113
|
+
| -------------- | ------------------ | ----------------------------------------------------------------- |
|
|
114
|
+
| Yes | Same | No-op |
|
|
115
|
+
| Yes | Different | Create new Contact; set member’s `wixContactId` to new contact ID |
|
|
116
|
+
| No | Same | Delete Contact; set member’s `wixContactId = wixMemberId` |
|
|
117
|
+
| No | Different | Update existing Contact’s email in CRM (no member change) |
|
|
118
|
+
|
|
119
|
+
### Where it’s used
|
|
120
|
+
|
|
121
|
+
`updateContactEmail` is called from `updateMemberContactInfo` when the **contactFormEmail** field changes (e.g. profile or form update). So:
|
|
122
|
+
|
|
123
|
+
- **Login flow** → `createContactAndMemberIfNew` (ensure member + contact exist and IDs stored).
|
|
124
|
+
- **Profile/form email change** → `updateMemberContactInfo` → `updateContactEmail` (keep contact and member in sync).
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## File roles
|
|
129
|
+
|
|
130
|
+
| File | Role |
|
|
131
|
+
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| `contacts-methods.js` | Contact CRUD only: create/update/delete contact in Wix CRM. |
|
|
133
|
+
| `member-contact-orchestration.js` | Orchestration: when to create/update/delete contact and when to update member’s `wixContactId`. Uses injected `updateMember`. |
|
|
134
|
+
| `members-data-methods.js` | Member CRUD, `createContactAndMemberIfNew`; requires `updateMemberContactInfo` and calls `updateMember` once with its return value. |
|
|
135
|
+
|
|
136
|
+
Dependency direction: **members-data** → **member-contact-orchestration** → **contacts** (no cycle).
|
|
@@ -4,32 +4,31 @@ const { auth } = require('@wix/essentials');
|
|
|
4
4
|
const elevatedGetContact = auth.elevate(contacts.getContact);
|
|
5
5
|
const elevatedUpdateContact = auth.elevate(contacts.updateContact);
|
|
6
6
|
const elevatedCreateContact = auth.elevate(contacts.createContact);
|
|
7
|
+
const elevatedDeleteContact = auth.elevate(contacts.deleteContact);
|
|
8
|
+
|
|
9
|
+
const deleteSiteContact = contactId => elevatedDeleteContact(contactId);
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Create a contact in Wix CRM
|
|
10
13
|
* @param {Object} contactData - Contact data
|
|
11
|
-
* @param {boolean} allowDuplicates - Allow duplicates if contact with same email already exists, will be true only when handling existing members, after that should be removed
|
|
12
14
|
* @returns {Promise<Object>} - Contact data
|
|
13
15
|
*/
|
|
14
|
-
async function createSiteContact(contactData
|
|
16
|
+
async function createSiteContact(contactData) {
|
|
15
17
|
console.log('[createSiteContact]contactData', JSON.stringify(contactData, null, 2));
|
|
16
|
-
if (!contactData || !
|
|
18
|
+
if (!contactData || !contactData.contactFormEmail) {
|
|
17
19
|
throw new Error('Contact data is required');
|
|
18
20
|
}
|
|
19
|
-
const phones =
|
|
20
|
-
Array.isArray(contactData.phones) && contactData.phones.length > 0 ? contactData.phones : [];
|
|
21
21
|
const contactInfo = {
|
|
22
22
|
name: {
|
|
23
23
|
first: contactData.firstName,
|
|
24
24
|
last: contactData.lastName,
|
|
25
25
|
},
|
|
26
26
|
emails: {
|
|
27
|
-
items: [{ email: contactData.contactFormEmail
|
|
27
|
+
items: [{ email: contactData.contactFormEmail, primary: true }],
|
|
28
28
|
},
|
|
29
|
-
phones: { items: phones.map(phone => ({ phone })) },
|
|
30
29
|
};
|
|
31
30
|
console.log('[createSiteContact]contactInfo', JSON.stringify(contactInfo, null, 2));
|
|
32
|
-
const createContactResponse = await elevatedCreateContact(contactInfo
|
|
31
|
+
const createContactResponse = await elevatedCreateContact(contactInfo);
|
|
33
32
|
console.log(
|
|
34
33
|
'[createSiteContact]createContactResponse',
|
|
35
34
|
JSON.stringify(createContactResponse, null, 2)
|
|
@@ -51,7 +50,6 @@ async function updateContactInfo(contactId, updateInfoCallback, operationName) {
|
|
|
51
50
|
const contact = await elevatedGetContact(contactId);
|
|
52
51
|
const currentInfo = contact.info;
|
|
53
52
|
const updatedInfo = updateInfoCallback(currentInfo);
|
|
54
|
-
|
|
55
53
|
await elevatedUpdateContact(contactId, updatedInfo, contact.revision);
|
|
56
54
|
} catch (error) {
|
|
57
55
|
console.error(`Error in ${operationName}:`, error);
|
|
@@ -59,105 +57,8 @@ async function updateContactInfo(contactId, updateInfoCallback, operationName) {
|
|
|
59
57
|
}
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
/**
|
|
63
|
-
* Updates contact email in Wix CRM
|
|
64
|
-
* @param {string} contactId - The contact ID in Wix CRM
|
|
65
|
-
* @param {string} newEmail - The new email address
|
|
66
|
-
*/
|
|
67
|
-
async function updateContactEmail(contactId, newEmail) {
|
|
68
|
-
if (!newEmail) {
|
|
69
|
-
throw new Error('New email is required');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return await updateContactInfo(
|
|
73
|
-
contactId,
|
|
74
|
-
currentInfo => ({
|
|
75
|
-
...currentInfo,
|
|
76
|
-
emails: {
|
|
77
|
-
items: [
|
|
78
|
-
{
|
|
79
|
-
email: newEmail,
|
|
80
|
-
primary: true,
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
},
|
|
84
|
-
}),
|
|
85
|
-
'update contact email'
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Updates contact names in Wix CRM for both contact and member
|
|
91
|
-
* @param {Object} params - Parameters object
|
|
92
|
-
* @param {string} params.wixContactId - The contact ID in Wix CRM
|
|
93
|
-
* @param {string} params.wixMemberId - The member ID in Wix CRM
|
|
94
|
-
* @param {string} params.firstName - The new first name
|
|
95
|
-
* @param {string} params.lastName - The new last name
|
|
96
|
-
*/
|
|
97
|
-
async function updateContactNames({ wixContactId, firstName, lastName }) {
|
|
98
|
-
if (!firstName && !lastName) {
|
|
99
|
-
throw new Error('First name or last name is required');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const createNameUpdate = currentInfo => ({
|
|
103
|
-
...currentInfo,
|
|
104
|
-
name: {
|
|
105
|
-
first: firstName || currentInfo?.name?.first || '',
|
|
106
|
-
last: lastName || currentInfo?.name?.last || '',
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
return await updateContactInfo(wixContactId, createNameUpdate, 'update contact names');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Update fields if they have changed
|
|
115
|
-
* @param {Array} existingValues - Current values for comparison
|
|
116
|
-
* @param {Array} newValues - New values to compare against
|
|
117
|
-
* @param {Function} updater - Function to call if values changed
|
|
118
|
-
* @param {Function} argsBuilder - Function to build arguments for updater
|
|
119
|
-
*/
|
|
120
|
-
const updateIfChanged = (existingValues, newValues, updater, argsBuilder) => {
|
|
121
|
-
const hasChanged = existingValues.some((val, idx) => val !== newValues[idx]);
|
|
122
|
-
if (!hasChanged) return null;
|
|
123
|
-
return updater(...argsBuilder(newValues));
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Updates member contact information in CRM if fields have changed
|
|
128
|
-
* @param {Object} data - New member data
|
|
129
|
-
* @param {Object} existingMemberData - Existing member data
|
|
130
|
-
*/
|
|
131
|
-
const updateMemberContactInfo = async (data, existingMemberData) => {
|
|
132
|
-
const { wixContactId } = existingMemberData;
|
|
133
|
-
if (!wixContactId) {
|
|
134
|
-
throw new Error('Wix Contact ID is required');
|
|
135
|
-
}
|
|
136
|
-
const updateConfig = [
|
|
137
|
-
{
|
|
138
|
-
fields: ['contactFormEmail'],
|
|
139
|
-
updater: updateContactEmail,
|
|
140
|
-
args: ([email]) => [wixContactId, email],
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
fields: ['firstName', 'lastName'],
|
|
144
|
-
updater: updateContactNames,
|
|
145
|
-
args: ([firstName, lastName]) => [{ firstName, lastName, wixContactId }],
|
|
146
|
-
},
|
|
147
|
-
];
|
|
148
|
-
|
|
149
|
-
const updatePromises = updateConfig
|
|
150
|
-
.map(({ fields, updater, args }) => {
|
|
151
|
-
const existingValues = fields.map(field => existingMemberData[field]);
|
|
152
|
-
const newValues = fields.map(field => data[field]);
|
|
153
|
-
return updateIfChanged(existingValues, newValues, updater, args);
|
|
154
|
-
})
|
|
155
|
-
.filter(Boolean);
|
|
156
|
-
|
|
157
|
-
await Promise.all(updatePromises);
|
|
158
|
-
};
|
|
159
|
-
|
|
160
60
|
module.exports = {
|
|
161
|
-
updateMemberContactInfo,
|
|
162
61
|
createSiteContact,
|
|
62
|
+
updateContactInfo,
|
|
63
|
+
deleteSiteContact,
|
|
163
64
|
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrates syncing between Wix Members and CRM Contacts.
|
|
3
|
+
* Returns member data to save; caller does a single updateMember to avoid double-write.
|
|
4
|
+
*/
|
|
5
|
+
const { createSiteContact, updateContactInfo, deleteSiteContact } = require('./contacts-methods');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Updates contact email in CRM. Returns member patch { wixContactId } when member record
|
|
9
|
+
* must change; otherwise null. Caller merges and saves once.
|
|
10
|
+
*/
|
|
11
|
+
async function updateContactEmail(newContactEmail, existingMemberData) {
|
|
12
|
+
if (!newContactEmail) {
|
|
13
|
+
throw new Error('New email is required');
|
|
14
|
+
}
|
|
15
|
+
if (!existingMemberData || existingMemberData.wixContactId == null) {
|
|
16
|
+
throw new Error('Existing member data with wixContactId is required');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { wixContactId, wixMemberId, email: loginEmail } = existingMemberData;
|
|
20
|
+
const isSingleEntity = wixContactId === wixMemberId;
|
|
21
|
+
const contactEmailDiffersFromLogin = loginEmail !== newContactEmail;
|
|
22
|
+
|
|
23
|
+
if (!contactEmailDiffersFromLogin) {
|
|
24
|
+
if (isSingleEntity) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
await deleteSiteContact(wixContactId);
|
|
28
|
+
return { wixContactId: wixMemberId };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isSingleEntity) {
|
|
32
|
+
const newWixContactId = await createSiteContact({
|
|
33
|
+
firstName: existingMemberData.firstName,
|
|
34
|
+
lastName: existingMemberData.lastName,
|
|
35
|
+
contactFormEmail: newContactEmail,
|
|
36
|
+
});
|
|
37
|
+
return { wixContactId: newWixContactId };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await updateContactInfo(
|
|
41
|
+
wixContactId,
|
|
42
|
+
currentInfo => ({
|
|
43
|
+
...currentInfo,
|
|
44
|
+
emails: {
|
|
45
|
+
items: [{ email: newContactEmail, primary: true }],
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
'update contact email'
|
|
49
|
+
);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function updateContactNames({ wixContactId, firstName, lastName }) {
|
|
54
|
+
if (!firstName && !lastName) {
|
|
55
|
+
throw new Error('First name or last name is required');
|
|
56
|
+
}
|
|
57
|
+
const createNameUpdate = currentInfo => ({
|
|
58
|
+
...currentInfo,
|
|
59
|
+
name: {
|
|
60
|
+
first: firstName || currentInfo?.name?.first || '',
|
|
61
|
+
last: lastName || currentInfo?.name?.last || '',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
return await updateContactInfo(wixContactId, createNameUpdate, 'update contact names');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Syncs contact with member (email, names). Contact CRUD only; returns member data to save.
|
|
69
|
+
* Caller must call updateMember once with the result.
|
|
70
|
+
*/
|
|
71
|
+
async function updateMemberContactInfo(data, existingMemberData) {
|
|
72
|
+
const { wixContactId } = existingMemberData;
|
|
73
|
+
if (!wixContactId) {
|
|
74
|
+
throw new Error('Wix Contact ID is required');
|
|
75
|
+
}
|
|
76
|
+
const updateConfig = [
|
|
77
|
+
{
|
|
78
|
+
fields: ['contactFormEmail'],
|
|
79
|
+
updater: updateContactEmail,
|
|
80
|
+
args: ([email]) => [email, existingMemberData],
|
|
81
|
+
returnsMemberPatch: true,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
fields: ['firstName', 'lastName'],
|
|
85
|
+
updater: updateContactNames,
|
|
86
|
+
args: ([firstName, lastName]) => [{ firstName, lastName, wixContactId }],
|
|
87
|
+
returnsMemberPatch: false,
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
const results = await Promise.all(
|
|
92
|
+
updateConfig.map(async ({ fields, updater, args, returnsMemberPatch }) => {
|
|
93
|
+
const existingValues = fields.map(field => existingMemberData[field]);
|
|
94
|
+
const newValues = fields.map(field => data[field]);
|
|
95
|
+
const hasChanged = existingValues.some((val, idx) => val !== newValues[idx]);
|
|
96
|
+
if (!hasChanged) return null;
|
|
97
|
+
const result = await updater(...args(newValues));
|
|
98
|
+
return returnsMemberPatch ? result : null;
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const memberPatch = results.reduce((acc, patch) => (patch ? { ...acc, ...patch } : acc), {});
|
|
103
|
+
return { ...data, ...memberPatch };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { updateMemberContactInfo };
|
|
@@ -2,9 +2,10 @@ const { COLLECTIONS } = require('../public/consts');
|
|
|
2
2
|
const { isWixHostedImage } = require('../public/Utils/sharedUtils');
|
|
3
3
|
|
|
4
4
|
const { MEMBERSHIPS_TYPES } = require('./consts');
|
|
5
|
-
const {
|
|
5
|
+
const { createSiteContact } = require('./contacts-methods');
|
|
6
6
|
const { MEMBER_ACTIONS } = require('./daily-pull/consts');
|
|
7
7
|
const { wixData } = require('./elevated-modules');
|
|
8
|
+
const { updateMemberContactInfo } = require('./member-contact-orchestration');
|
|
8
9
|
const { createSiteMember, getCurrentMember } = require('./members-area-methods');
|
|
9
10
|
const {
|
|
10
11
|
chunkArray,
|
|
@@ -12,6 +13,7 @@ const {
|
|
|
12
13
|
queryAllItems,
|
|
13
14
|
generateGeoHash,
|
|
14
15
|
searchAllItems,
|
|
16
|
+
runIf,
|
|
15
17
|
} = require('./utils');
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -31,7 +33,10 @@ async function findMemberByWixDataId(memberId) {
|
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
const hasDifferentEmails = memberData =>
|
|
37
|
+
memberData.contactFormEmail && memberData.contactFormEmail !== memberData.email;
|
|
38
|
+
|
|
39
|
+
async function createContactAndMemberIfNew(memberData) {
|
|
35
40
|
if (!memberData) {
|
|
36
41
|
throw new Error('Member data is required');
|
|
37
42
|
}
|
|
@@ -41,19 +46,25 @@ async function createContactAndMemberIfNew(memberData, allowDuplicates = true) {
|
|
|
41
46
|
lastName: memberData.lastName,
|
|
42
47
|
email: memberData.email,
|
|
43
48
|
phones: memberData.phones,
|
|
44
|
-
contactFormEmail: memberData.contactFormEmail
|
|
49
|
+
contactFormEmail: memberData.contactFormEmail,
|
|
45
50
|
};
|
|
46
51
|
const needsWixMember = !memberData.wixMemberId;
|
|
47
52
|
const needsWixContact = !memberData.wixContactId;
|
|
53
|
+
const hasContactEmailDifferentFromLogin = hasDifferentEmails(memberData);
|
|
48
54
|
console.log('needsWixMember', needsWixMember);
|
|
49
55
|
console.log('needsWixContact', needsWixContact);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
console.log('hasContactEmailDifferentFromLogin', hasContactEmailDifferentFromLogin);
|
|
57
|
+
|
|
58
|
+
const [newWixMemberId, createdWixContactId] = await Promise.all([
|
|
59
|
+
runIf(needsWixMember, () => createSiteMember(toCreateMemberData)),
|
|
60
|
+
runIf(needsWixContact && hasContactEmailDifferentFromLogin, () =>
|
|
61
|
+
createSiteContact(toCreateMemberData)
|
|
62
|
+
),
|
|
55
63
|
]);
|
|
64
|
+
const memberContactId = newWixMemberId;
|
|
65
|
+
const newWixContactId = createdWixContactId || memberContactId;
|
|
56
66
|
console.log('newWixMemberId', newWixMemberId);
|
|
67
|
+
console.log('memberContactId', memberContactId);
|
|
57
68
|
console.log('newWixContactId', newWixContactId);
|
|
58
69
|
let memberDataWithContactId = {
|
|
59
70
|
...memberData,
|
|
@@ -281,9 +292,8 @@ async function saveRegistrationData(data, id) {
|
|
|
281
292
|
mergedData.locHash = generateGeoHash(data.addresses);
|
|
282
293
|
}
|
|
283
294
|
|
|
284
|
-
await updateMemberContactInfo(mergedData, existingMemberData);
|
|
285
|
-
|
|
286
|
-
const saveData = await updateMember(mergedData);
|
|
295
|
+
const dataToSave = await updateMemberContactInfo(mergedData, existingMemberData);
|
|
296
|
+
const saveData = await updateMember(dataToSave);
|
|
287
297
|
return {
|
|
288
298
|
type: 'success',
|
|
289
299
|
saveData,
|
|
@@ -480,15 +490,14 @@ const getQAUsers = async () => {
|
|
|
480
490
|
/**
|
|
481
491
|
* Ensures member has a contact - creates one if missing
|
|
482
492
|
* @param {Object} memberData - Member data from DB
|
|
483
|
-
* @param {boolean} [allowDuplicates=false] - If true, allows creating duplicate contacts (e.g. for SSO/QA login)
|
|
484
493
|
* @returns {Promise<Object>} - Member data with contact and member IDs
|
|
485
494
|
*/
|
|
486
|
-
async function ensureWixMemberAndContactExist(memberData
|
|
495
|
+
async function ensureWixMemberAndContactExist(memberData) {
|
|
487
496
|
if (!memberData) {
|
|
488
497
|
throw new Error('Member data is required');
|
|
489
498
|
}
|
|
490
499
|
if (!memberData.wixContactId || !memberData.wixMemberId) {
|
|
491
|
-
const memberDataWithContactId = await createContactAndMemberIfNew(memberData
|
|
500
|
+
const memberDataWithContactId = await createContactAndMemberIfNew(memberData);
|
|
492
501
|
return memberDataWithContactId;
|
|
493
502
|
}
|
|
494
503
|
return memberData;
|
|
@@ -505,7 +514,7 @@ async function prepareMemberForSSOLogin(data) {
|
|
|
505
514
|
throw new Error(`Member data not found for memberId ${memberId}`);
|
|
506
515
|
}
|
|
507
516
|
console.log('memberData', memberData);
|
|
508
|
-
return await ensureWixMemberAndContactExist(memberData
|
|
517
|
+
return await ensureWixMemberAndContactExist(memberData);
|
|
509
518
|
} catch (error) {
|
|
510
519
|
console.error(`Error in prepareMemberForSSOLogin: ${error.message}`);
|
|
511
520
|
throw error;
|
|
@@ -522,7 +531,7 @@ async function prepareMemberForQALogin(email) {
|
|
|
522
531
|
throw new Error(`Member data not found for email ${email}`);
|
|
523
532
|
}
|
|
524
533
|
console.log('memberData', memberData);
|
|
525
|
-
return await ensureWixMemberAndContactExist(memberData
|
|
534
|
+
return await ensureWixMemberAndContactExist(memberData);
|
|
526
535
|
} catch (error) {
|
|
527
536
|
const errMsg = `[prepareMemberForQALogin] QA Login failed with error: ${error.message} for email: ${email}`;
|
|
528
537
|
console.error(errMsg);
|
package/backend/utils.js
CHANGED
|
@@ -199,6 +199,9 @@ function encodeXml(value) {
|
|
|
199
199
|
function formatDateOnly(dateStr) {
|
|
200
200
|
return new Date(dateStr).toISOString().slice(0, 10);
|
|
201
201
|
}
|
|
202
|
+
|
|
203
|
+
const runIf = (condition, asyncFn) => (condition ? asyncFn() : Promise.resolve(null));
|
|
204
|
+
|
|
202
205
|
module.exports = {
|
|
203
206
|
getSiteConfigs,
|
|
204
207
|
retrieveAllItems,
|
|
@@ -218,4 +221,5 @@ module.exports = {
|
|
|
218
221
|
getMoreAddressesToDisplay,
|
|
219
222
|
isPAC_STAFF,
|
|
220
223
|
searchAllItems,
|
|
224
|
+
runIf,
|
|
221
225
|
};
|