abmp-npm 1.1.104 → 1.1.108
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/backend/contacts-methods.js +20 -52
- package/backend/daily-pull/bulk-process-methods.js +1 -1
- package/backend/daily-pull/sync-to-cms-methods.js +6 -4
- package/backend/dev-only-methods.js +1 -13
- package/backend/forms-methods.js +3 -3
- package/backend/jobs.js +7 -2
- package/backend/login/qa-login-methods.js +31 -8
- package/backend/login/sso-methods.js +7 -7
- package/backend/members-area-methods.js +17 -18
- package/backend/members-data-methods.js +38 -72
- package/backend/pac-api-methods.js +19 -5
- package/backend/tasks/consts.js +0 -2
- package/backend/tasks/tasks-configs.js +1 -17
- package/backend/tasks/tasks-process-methods.js +0 -44
- package/package.json +2 -2
|
@@ -3,33 +3,7 @@ const { auth } = require('@wix/essentials');
|
|
|
3
3
|
|
|
4
4
|
const elevatedGetContact = auth.elevate(contacts.getContact);
|
|
5
5
|
const elevatedUpdateContact = auth.elevate(contacts.updateContact);
|
|
6
|
-
const elevatedCreateContact = auth.elevate(contacts.createContact);
|
|
7
6
|
|
|
8
|
-
/**
|
|
9
|
-
* Create a contact in Wix CRM
|
|
10
|
-
* @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
|
-
* @returns {Promise<Object>} - Contact data
|
|
13
|
-
*/
|
|
14
|
-
async function createSiteContact(contactData, allowDuplicates = false) {
|
|
15
|
-
if (!contactData || !(contactData.contactFormEmail || contactData.email)) {
|
|
16
|
-
throw new Error('Contact data is required');
|
|
17
|
-
}
|
|
18
|
-
const phones =
|
|
19
|
-
Array.isArray(contactData.phones) && contactData.phones.length > 0 ? contactData.phones : [];
|
|
20
|
-
const contactInfo = {
|
|
21
|
-
name: {
|
|
22
|
-
first: contactData.firstName,
|
|
23
|
-
last: contactData.lastName,
|
|
24
|
-
},
|
|
25
|
-
emails: {
|
|
26
|
-
items: [{ email: contactData.contactFormEmail || contactData.email, primary: true }],
|
|
27
|
-
},
|
|
28
|
-
phones: { items: phones.map(phone => ({ phone })) },
|
|
29
|
-
};
|
|
30
|
-
const createContactResponse = await elevatedCreateContact(contactInfo, { allowDuplicates });
|
|
31
|
-
return createContactResponse.contact._id;
|
|
32
|
-
}
|
|
33
7
|
/**
|
|
34
8
|
* Generic contact update helper function
|
|
35
9
|
* @param {string} contactId - The contact ID in Wix CRM
|
|
@@ -81,32 +55,27 @@ async function updateContactEmail(contactId, newEmail) {
|
|
|
81
55
|
}
|
|
82
56
|
|
|
83
57
|
/**
|
|
84
|
-
* Updates contact names in Wix CRM
|
|
85
|
-
* @param {
|
|
86
|
-
* @param {string}
|
|
87
|
-
* @param {string}
|
|
88
|
-
* @param {string} params.lastName - The new last name
|
|
58
|
+
* Updates contact names in Wix CRM
|
|
59
|
+
* @param {string} contactId - The contact ID in Wix CRM
|
|
60
|
+
* @param {string} firstName - The new first name
|
|
61
|
+
* @param {string} lastName - The new last name
|
|
89
62
|
*/
|
|
90
|
-
async function
|
|
91
|
-
//TODO: rethink if we should keep all info just in contact, meaning no need to update the member
|
|
63
|
+
async function updateContactNames(contactId, firstName, lastName) {
|
|
92
64
|
if (!firstName && !lastName) {
|
|
93
65
|
throw new Error('At least one name field is required');
|
|
94
66
|
}
|
|
95
67
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
].filter(Boolean);
|
|
108
|
-
|
|
109
|
-
return await Promise.all(updatePromises);
|
|
68
|
+
return await updateContactInfo(
|
|
69
|
+
contactId,
|
|
70
|
+
currentInfo => ({
|
|
71
|
+
...currentInfo,
|
|
72
|
+
name: {
|
|
73
|
+
first: firstName || currentInfo?.name?.first || '',
|
|
74
|
+
last: lastName || currentInfo?.name?.last || '',
|
|
75
|
+
},
|
|
76
|
+
}),
|
|
77
|
+
'update contact names'
|
|
78
|
+
);
|
|
110
79
|
}
|
|
111
80
|
|
|
112
81
|
/**
|
|
@@ -128,18 +97,18 @@ const updateIfChanged = (existingValues, newValues, updater, argsBuilder) => {
|
|
|
128
97
|
* @param {Object} existingMemberData - Existing member data
|
|
129
98
|
*/
|
|
130
99
|
const updateMemberContactInfo = async (data, existingMemberData) => {
|
|
131
|
-
const {
|
|
100
|
+
const { contactId } = existingMemberData;
|
|
132
101
|
|
|
133
102
|
const updateConfig = [
|
|
134
103
|
{
|
|
135
104
|
fields: ['contactFormEmail'],
|
|
136
105
|
updater: updateContactEmail,
|
|
137
|
-
args: ([email]) => [
|
|
106
|
+
args: ([email]) => [contactId, email],
|
|
138
107
|
},
|
|
139
108
|
{
|
|
140
109
|
fields: ['firstName', 'lastName'],
|
|
141
|
-
updater:
|
|
142
|
-
args: ([firstName, lastName]) => [
|
|
110
|
+
updater: updateContactNames,
|
|
111
|
+
args: ([firstName, lastName]) => [contactId, firstName, lastName],
|
|
143
112
|
},
|
|
144
113
|
];
|
|
145
114
|
|
|
@@ -156,5 +125,4 @@ const updateMemberContactInfo = async (data, existingMemberData) => {
|
|
|
156
125
|
|
|
157
126
|
module.exports = {
|
|
158
127
|
updateMemberContactInfo,
|
|
159
|
-
createSiteContact,
|
|
160
128
|
};
|
|
@@ -168,7 +168,7 @@ const bulkProcessAndSaveMemberData = async ({
|
|
|
168
168
|
const toChangeWixMembersEmails = [];
|
|
169
169
|
const toSaveMembersData = uniqueUrlsMembersData.map(member => {
|
|
170
170
|
const { isLoginEmailChanged, isNewToDb: _isNewToDb, ...restMemberData } = member;
|
|
171
|
-
if (member.
|
|
171
|
+
if (member.contactId && isLoginEmailChanged) {
|
|
172
172
|
toChangeWixMembersEmails.push(member);
|
|
173
173
|
}
|
|
174
174
|
return restMemberData; //we don't want to store the isLoginEmailChanged in the database, it's just a flag to know if we need to change the login email in Members area
|
|
@@ -9,9 +9,10 @@ const { bulkProcessAndSaveMemberData } = require('./bulk-process-methods');
|
|
|
9
9
|
const { SITES_WITH_INTERESTS_TO_MIGRATE } = require('./consts');
|
|
10
10
|
const { isUpdatedMember, isSiteAssociatedMember } = require('./utils');
|
|
11
11
|
|
|
12
|
-
async function syncMembersDataPerAction(
|
|
12
|
+
async function syncMembersDataPerAction(taskData) {
|
|
13
|
+
const { action, backupDate } = taskData;
|
|
13
14
|
try {
|
|
14
|
-
const firstPageResponse = await fetchPACMembers(1, action);
|
|
15
|
+
const firstPageResponse = await fetchPACMembers({ page: 1, action, backupDate });
|
|
15
16
|
|
|
16
17
|
if (
|
|
17
18
|
!firstPageResponse ||
|
|
@@ -48,6 +49,7 @@ async function syncMembersDataPerAction(action) {
|
|
|
48
49
|
data: {
|
|
49
50
|
pageNumber,
|
|
50
51
|
action,
|
|
52
|
+
...(backupDate ? { backupDate } : {}),
|
|
51
53
|
},
|
|
52
54
|
type: 'scheduled',
|
|
53
55
|
}));
|
|
@@ -74,11 +76,11 @@ async function syncMembersDataPerAction(action) {
|
|
|
74
76
|
* @returns {Promise<Object>} - Page synchronization result
|
|
75
77
|
*/
|
|
76
78
|
async function synchronizeSinglePage(taskObject) {
|
|
77
|
-
const { pageNumber, action } = taskObject.data;
|
|
79
|
+
const { pageNumber, action, backupDate } = taskObject.data;
|
|
78
80
|
try {
|
|
79
81
|
const [siteAssociation, memberDataResponse] = await Promise.all([
|
|
80
82
|
getSiteConfigs(CONFIG_KEYS.SITE_ASSOCIATION),
|
|
81
|
-
fetchPACMembers(pageNumber, action),
|
|
83
|
+
fetchPACMembers({ page: pageNumber, action, backupDate }),
|
|
82
84
|
]);
|
|
83
85
|
const addInterests = SITES_WITH_INTERESTS_TO_MIGRATE.includes(siteAssociation);
|
|
84
86
|
if (
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const { COLLECTIONS } = require('../public/consts');
|
|
2
|
-
|
|
3
1
|
const { ensureUniqueUrlsInBatch } = require('./daily-pull/bulk-process-methods');
|
|
4
2
|
const { wixData } = require('./elevated-modules');
|
|
5
3
|
const { bulkSaveMembers } = require('./members-data-methods');
|
|
@@ -17,14 +15,4 @@ async function deduplicateURls(collectionName, duplicateUrlsList) {
|
|
|
17
15
|
return await bulkSaveMembers(membersWithUniqueUrls, collectionName);
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
const query = wixData.query(COLLECTIONS.MEMBERS_DATA).isNotEmpty('contactId');
|
|
22
|
-
const members = await queryAllItems(query);
|
|
23
|
-
const updatedMembers = members.map(member => ({
|
|
24
|
-
...member,
|
|
25
|
-
wixMemberId: member.contactId,
|
|
26
|
-
}));
|
|
27
|
-
return await bulkSaveMembers(updatedMembers, COLLECTIONS.MEMBERS_DATA);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = { deduplicateURls, copyContactIdToWixMemberId };
|
|
18
|
+
module.exports = { deduplicateURls };
|
package/backend/forms-methods.js
CHANGED
|
@@ -16,7 +16,7 @@ const contactSubmission = async (data, memberDataId) => {
|
|
|
16
16
|
console.log('Member contact form is not enabled for user, skipping contact submission!');
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
let memberContactId = memberData.
|
|
19
|
+
let memberContactId = memberData.contactId;
|
|
20
20
|
if (!memberContactId) {
|
|
21
21
|
/**
|
|
22
22
|
* Create a member contact here since some members may have never logged in
|
|
@@ -27,7 +27,7 @@ const contactSubmission = async (data, memberDataId) => {
|
|
|
27
27
|
*/
|
|
28
28
|
console.info('Member contact id not found for user, creating new contact!');
|
|
29
29
|
const member = await createContactAndMemberIfNew(memberData);
|
|
30
|
-
memberContactId = member.
|
|
30
|
+
memberContactId = member.contactId;
|
|
31
31
|
}
|
|
32
32
|
console.log('memberContactId', memberContactId);
|
|
33
33
|
const emailTriggered = await triggerAutomation(automationEmailTriggerId, {
|
|
@@ -40,7 +40,7 @@ const contactSubmission = async (data, memberDataId) => {
|
|
|
40
40
|
data = {
|
|
41
41
|
...data,
|
|
42
42
|
phone: Number(data.phone),
|
|
43
|
-
memberContactId,
|
|
43
|
+
memberContactId: memberContactId,
|
|
44
44
|
memberEmail: memberData.contactFormEmail,
|
|
45
45
|
};
|
|
46
46
|
await wixData.insert(COLLECTIONS.CONTACT_US_SUBMISSIONS, data);
|
package/backend/jobs.js
CHANGED
|
@@ -13,12 +13,17 @@ async function runScheduledTasks() {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Schedule a daily pull task for the given backup date
|
|
18
|
+
* @param {string} backupDate - Optional. The date of the backup to pull in format YYYY-MM-DD
|
|
19
|
+
* @returns {Promise<void>}
|
|
20
|
+
*/
|
|
21
|
+
async function scheduleDailyPullTask(backupDate = null) {
|
|
17
22
|
try {
|
|
18
23
|
console.log('scheduleDailyPullTask started!');
|
|
19
24
|
return await taskManager().schedule({
|
|
20
25
|
name: TASKS_NAMES.ScheduleDailyMembersDataSync,
|
|
21
|
-
data: {},
|
|
26
|
+
data: backupDate ? { backupDate } : {}, // keeping it like this so it would be easier to understand which task was backed up which is not while looking into CMS.
|
|
22
27
|
type: 'scheduled',
|
|
23
28
|
});
|
|
24
29
|
} catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { getMemberByEmail, getQAUsers } = require('../members-data-methods');
|
|
2
2
|
const { getSecret } = require('../utils');
|
|
3
3
|
|
|
4
4
|
const validateQAUser = async userEmail => {
|
|
@@ -20,23 +20,27 @@ const validateQAUser = async userEmail => {
|
|
|
20
20
|
*/
|
|
21
21
|
const loginQAMember = async ({ userEmail, secret }, generateSessionToken) => {
|
|
22
22
|
try {
|
|
23
|
-
const
|
|
24
|
-
validateQAUser(userEmail),
|
|
25
|
-
getSecret('ABMP_QA_SECRET'),
|
|
26
|
-
]);
|
|
23
|
+
const userValidation = await validateQAUser(userEmail);
|
|
27
24
|
if (userValidation.error) {
|
|
28
25
|
return { success: false, error: userValidation.error };
|
|
29
26
|
}
|
|
27
|
+
|
|
28
|
+
const qaSecret = await getSecret('ABMP_QA_SECRET');
|
|
30
29
|
if (secret !== qaSecret) {
|
|
31
30
|
return { success: false, error: 'Invalid secret' };
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
const
|
|
35
|
-
|
|
33
|
+
const token = await generateSessionToken(userValidation.email, qaSecret);
|
|
34
|
+
|
|
35
|
+
const result = await getMemberCMSId(userEmail);
|
|
36
|
+
if (!result.success) {
|
|
37
|
+
return { success: false, error: result.error };
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
return {
|
|
37
41
|
success: true,
|
|
38
42
|
token,
|
|
39
|
-
memberCMSId:
|
|
43
|
+
memberCMSId: result.memberCMSId,
|
|
40
44
|
};
|
|
41
45
|
} catch (error) {
|
|
42
46
|
console.error('QA login error:', error);
|
|
@@ -44,6 +48,25 @@ const loginQAMember = async ({ userEmail, secret }, generateSessionToken) => {
|
|
|
44
48
|
}
|
|
45
49
|
};
|
|
46
50
|
|
|
51
|
+
async function getMemberCMSId(userEmail) {
|
|
52
|
+
try {
|
|
53
|
+
const userValidation = await validateQAUser(userEmail);
|
|
54
|
+
if (userValidation.error) {
|
|
55
|
+
return { success: false, error: userValidation.error };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const member = await getMemberByEmail(userEmail);
|
|
59
|
+
|
|
60
|
+
if (!member) {
|
|
61
|
+
return { success: false, error: `No Member found in DB matching email: ${userEmail}` };
|
|
62
|
+
}
|
|
63
|
+
return { success: true, memberCMSId: member._id };
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('Error getting member CMS ID:', error);
|
|
66
|
+
return { success: false, error: 'Failed to retrieve member data' };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
47
70
|
module.exports = {
|
|
48
71
|
loginQAMember,
|
|
49
72
|
};
|
|
@@ -5,7 +5,7 @@ const { decode } = require('jwt-js-decode');
|
|
|
5
5
|
const { CONFIG_KEYS, SSO_TOKEN_AUTH_API_URL } = require('../consts');
|
|
6
6
|
const { MEMBER_ACTIONS } = require('../daily-pull/consts');
|
|
7
7
|
const { getCurrentMember } = require('../members-area-methods');
|
|
8
|
-
const {
|
|
8
|
+
const { getMemberByContactId, getSiteMemberId } = require('../members-data-methods');
|
|
9
9
|
const {
|
|
10
10
|
formatDateToMonthYear,
|
|
11
11
|
getAddressDisplayOptions,
|
|
@@ -37,12 +37,12 @@ async function validateMemberToken(memberIdInput) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const [dbMember, siteConfigs] = await Promise.all([
|
|
40
|
-
|
|
40
|
+
getMemberByContactId(member._id),
|
|
41
41
|
getSiteConfigs(),
|
|
42
42
|
]);
|
|
43
43
|
const siteAssociation = siteConfigs[CONFIG_KEYS.SITE_ASSOCIATION];
|
|
44
44
|
const membersExternalPortalUrl = siteConfigs[CONFIG_KEYS.MEMBERS_EXTERNAL_PORTAL_URL];
|
|
45
|
-
console.log('dbMember by
|
|
45
|
+
console.log('dbMember by contact id is:', dbMember);
|
|
46
46
|
console.log('member._id', member._id);
|
|
47
47
|
|
|
48
48
|
if (!dbMember?._id) {
|
|
@@ -133,12 +133,12 @@ const authenticateSSOToken = async ({ token }, generateSessionToken) => {
|
|
|
133
133
|
if (isValidToken) {
|
|
134
134
|
const jwt = decode(responseToken);
|
|
135
135
|
const payload = jwt.payload;
|
|
136
|
-
const
|
|
137
|
-
console.log('
|
|
138
|
-
const sessionToken = await generateSessionToken(
|
|
136
|
+
const membersData = await getSiteMemberId(payload);
|
|
137
|
+
console.log('membersDataCollectionId', membersData._id);
|
|
138
|
+
const sessionToken = await generateSessionToken(membersData.email);
|
|
139
139
|
const authObj = {
|
|
140
140
|
type: 'success',
|
|
141
|
-
memberId:
|
|
141
|
+
memberId: membersData._id,
|
|
142
142
|
sessionToken,
|
|
143
143
|
};
|
|
144
144
|
return authObj;
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
const { auth } = require('@wix/essentials');
|
|
2
2
|
const { members, authentication } = require('@wix/members');
|
|
3
3
|
const elevatedCreateMember = auth.elevate(members.createMember);
|
|
4
|
-
const eleveatedChangeLoginEmail = auth.elevate(authentication.changeLoginEmail);
|
|
5
4
|
|
|
6
|
-
function
|
|
7
|
-
|
|
5
|
+
function prepareContactData(partner) {
|
|
6
|
+
const phones = Array.isArray(partner.phones) ? partner.phones : []; //some users don't have phones
|
|
8
7
|
const options = {
|
|
9
8
|
member: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// },
|
|
9
|
+
contact: {
|
|
10
|
+
...partner,
|
|
11
|
+
phones,
|
|
12
|
+
emails: [partner.contactFormEmail || partner.email],
|
|
13
|
+
},
|
|
16
14
|
loginEmail: partner.email,
|
|
17
15
|
},
|
|
18
16
|
};
|
|
@@ -24,8 +22,9 @@ async function createMemberFunction(member) {
|
|
|
24
22
|
}
|
|
25
23
|
const createSiteMember = async memberDetails => {
|
|
26
24
|
try {
|
|
27
|
-
const options =
|
|
28
|
-
|
|
25
|
+
const options = prepareContactData(memberDetails);
|
|
26
|
+
const contactId = await createMemberFunction(options);
|
|
27
|
+
return contactId;
|
|
29
28
|
} catch (error) {
|
|
30
29
|
console.error(`Error in createSiteMember ${error.message}`);
|
|
31
30
|
throw error;
|
|
@@ -38,22 +37,22 @@ const getCurrentMember = async () => {
|
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
/**
|
|
41
|
-
* Updates Wix member login email if the member has a
|
|
42
|
-
* @param {Object} member - Member object with
|
|
40
|
+
* Updates Wix member login email if the member has a contactId (registered Wix member)
|
|
41
|
+
* @param {Object} member - Member object with contactId and email
|
|
43
42
|
* @param {Object} result - Result object to track Wix member updates
|
|
44
43
|
*/
|
|
45
44
|
async function updateWixMemberLoginEmail(member, result = {}) {
|
|
46
|
-
if (!member.
|
|
47
|
-
console.log(`Member ${member.memberId} has no
|
|
45
|
+
if (!member.contactId) {
|
|
46
|
+
console.log(`Member ${member.memberId} has no contactId - skipping Wix login email update`);
|
|
48
47
|
return;
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
try {
|
|
52
51
|
console.log(
|
|
53
|
-
`Updating Wix login email for member ${member.memberId} (
|
|
52
|
+
`Updating Wix login email for member ${member.memberId} (contactId: ${member.contactId})`
|
|
54
53
|
);
|
|
55
54
|
|
|
56
|
-
const updatedWixMember = await
|
|
55
|
+
const updatedWixMember = await authentication.changeLoginEmail(member.contactId, member.email);
|
|
57
56
|
|
|
58
57
|
console.log(
|
|
59
58
|
`✅ Successfully updated Wix login email for member ${member.memberId}: ${updatedWixMember.loginEmail}`
|
|
@@ -76,7 +75,7 @@ async function updateWixMemberLoginEmail(member, result = {}) {
|
|
|
76
75
|
}
|
|
77
76
|
result.wixMemberErrors.push({
|
|
78
77
|
memberId: member.memberId,
|
|
79
|
-
|
|
78
|
+
contactId: member.contactId,
|
|
80
79
|
email: member.email,
|
|
81
80
|
error: error.message,
|
|
82
81
|
});
|
|
@@ -2,7 +2,7 @@ const { COLLECTIONS } = require('../public/consts');
|
|
|
2
2
|
const { isWixHostedImage } = require('../public/Utils/sharedUtils');
|
|
3
3
|
|
|
4
4
|
const { MEMBERSHIPS_TYPES } = require('./consts');
|
|
5
|
-
const { updateMemberContactInfo
|
|
5
|
+
const { updateMemberContactInfo } = require('./contacts-methods');
|
|
6
6
|
const { MEMBER_ACTIONS } = require('./daily-pull/consts');
|
|
7
7
|
const { wixData } = require('./elevated-modules');
|
|
8
8
|
const { createSiteMember, getCurrentMember } = require('./members-area-methods');
|
|
@@ -43,16 +43,10 @@ async function createContactAndMemberIfNew(memberData) {
|
|
|
43
43
|
phones: memberData.phones,
|
|
44
44
|
contactFormEmail: memberData.contactFormEmail || memberData.email,
|
|
45
45
|
};
|
|
46
|
-
const
|
|
47
|
-
const needsWixContact = !memberData.wixContactId;
|
|
48
|
-
const [newWixMemberId, newWixContactId] = await Promise.all([
|
|
49
|
-
needsWixMember ? createSiteMember(toCreateMemberData) : Promise.resolve(null),
|
|
50
|
-
needsWixContact ? createSiteContact(toCreateMemberData) : Promise.resolve(null),
|
|
51
|
-
]);
|
|
46
|
+
const contactId = await createSiteMember(toCreateMemberData);
|
|
52
47
|
let memberDataWithContactId = {
|
|
53
48
|
...memberData,
|
|
54
|
-
|
|
55
|
-
wixContactId: newWixContactId || memberData.wixContactId,
|
|
49
|
+
contactId,
|
|
56
50
|
};
|
|
57
51
|
const updatedResult = await updateMember(memberDataWithContactId);
|
|
58
52
|
memberDataWithContactId = {
|
|
@@ -100,16 +94,10 @@ async function findMemberById(memberId) {
|
|
|
100
94
|
const queryResult = await wixData
|
|
101
95
|
.query(COLLECTIONS.MEMBERS_DATA)
|
|
102
96
|
.eq('memberId', memberId)
|
|
103
|
-
.limit(2)
|
|
104
97
|
.find();
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
`Multiple members found with memberId ${memberId} members _ids are : [${queryResult.items.map(member => member._id).join(', ')}]`
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
return queryResult.items.length === 1 ? queryResult.items[0] : null;
|
|
98
|
+
|
|
99
|
+
return queryResult.items.length > 0 ? queryResult.items[0] : null;
|
|
111
100
|
} catch (error) {
|
|
112
|
-
console.error('Error finding member by ID:', error);
|
|
113
101
|
throw new Error(`Failed to retrieve member data: ${error.message}`);
|
|
114
102
|
}
|
|
115
103
|
}
|
|
@@ -176,26 +164,26 @@ async function getMemberBySlug({
|
|
|
176
164
|
}
|
|
177
165
|
}
|
|
178
166
|
|
|
179
|
-
async function
|
|
180
|
-
if (!
|
|
181
|
-
throw new Error('
|
|
167
|
+
async function getMemberByContactId(contactId) {
|
|
168
|
+
if (!contactId) {
|
|
169
|
+
throw new Error('Contact ID is required');
|
|
182
170
|
}
|
|
183
171
|
try {
|
|
184
172
|
const members = await wixData
|
|
185
173
|
.query(COLLECTIONS.MEMBERS_DATA)
|
|
186
|
-
.eq('
|
|
174
|
+
.eq('contactId', contactId)
|
|
187
175
|
.limit(2)
|
|
188
176
|
.find()
|
|
189
177
|
.then(res => res.items);
|
|
190
178
|
if (members.length > 1) {
|
|
191
179
|
throw new Error(
|
|
192
|
-
`[
|
|
180
|
+
`[getMemberByContactId] Multiple members found with contactId ${contactId} membersIds are : [${members.map(member => member.memberId).join(', ')}]`
|
|
193
181
|
);
|
|
194
182
|
}
|
|
195
183
|
return members[0] || null;
|
|
196
184
|
} catch (error) {
|
|
197
185
|
throw new Error(
|
|
198
|
-
`[
|
|
186
|
+
`[getMemberByContactId] Failed to retrieve member by contactId ${contactId} data: ${error.message}`
|
|
199
187
|
);
|
|
200
188
|
}
|
|
201
189
|
}
|
|
@@ -454,53 +442,38 @@ const getQAUsers = async () => {
|
|
|
454
442
|
throw new Error(`Failed to get QA users: ${error.message}`);
|
|
455
443
|
}
|
|
456
444
|
};
|
|
457
|
-
|
|
458
|
-
* Ensures member has a contact - creates one if missing
|
|
459
|
-
* @param {Object} memberData - Member data from DB
|
|
460
|
-
* @returns {Promise<Object>} - Member data with contact and member IDs
|
|
461
|
-
*/
|
|
462
|
-
async function ensureWixMemberAndContactExist(memberData) {
|
|
463
|
-
if (!memberData) {
|
|
464
|
-
throw new Error('Member data is required');
|
|
465
|
-
}
|
|
466
|
-
if (!memberData.wixContactId || !memberData.wixMemberId) {
|
|
467
|
-
const memberDataWithContactId = await createContactAndMemberIfNew(memberData);
|
|
468
|
-
return memberDataWithContactId;
|
|
469
|
-
}
|
|
470
|
-
return memberData;
|
|
471
|
-
}
|
|
472
|
-
async function prepareMemberForSSOLogin(data) {
|
|
445
|
+
async function getSiteMemberId(data) {
|
|
473
446
|
try {
|
|
474
447
|
console.log('data', data);
|
|
475
448
|
const memberId = data?.pac?.cst_recno;
|
|
476
449
|
if (!memberId) {
|
|
477
|
-
|
|
450
|
+
const errorMessage = `Member ID is missing in passed data ${JSON.stringify(data)}`;
|
|
451
|
+
console.error(errorMessage);
|
|
452
|
+
throw new Error(errorMessage);
|
|
478
453
|
}
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
454
|
+
const queryMemberResult = await wixData
|
|
455
|
+
.query(COLLECTIONS.MEMBERS_DATA)
|
|
456
|
+
.eq('memberId', Number(memberId))
|
|
457
|
+
.find()
|
|
458
|
+
.then(res => res.items);
|
|
459
|
+
if (!queryMemberResult.length || queryMemberResult.length > 1) {
|
|
460
|
+
throw new Error(
|
|
461
|
+
`Invalid Members count found in DB for email ${data.email} members count is : [${
|
|
462
|
+
queryMemberResult.length
|
|
463
|
+
}] membersIds are : [${queryMemberResult.map(member => member.memberId).join(', ')}]`
|
|
464
|
+
);
|
|
482
465
|
}
|
|
466
|
+
let memberData = queryMemberResult[0];
|
|
483
467
|
console.log('memberData', memberData);
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
async function prepareMemberForQALogin(email) {
|
|
491
|
-
try {
|
|
492
|
-
console.log('qa email:', email);
|
|
493
|
-
if (!email) {
|
|
494
|
-
throw new Error(`Email is missing in passed data ${email}`);
|
|
495
|
-
}
|
|
496
|
-
const memberData = await getMemberByEmail(email);
|
|
497
|
-
if (!memberData) {
|
|
498
|
-
throw new Error(`Member data not found for email ${email}`);
|
|
468
|
+
const isNewUser = !memberData.contactId;
|
|
469
|
+
if (isNewUser) {
|
|
470
|
+
const memberDataWithContactId = await createContactAndMemberIfNew(memberData);
|
|
471
|
+
console.log('memberDataWithContactId', memberDataWithContactId);
|
|
472
|
+
memberData = memberDataWithContactId;
|
|
499
473
|
}
|
|
500
|
-
|
|
501
|
-
return await ensureWixMemberAndContactExist(memberData);
|
|
474
|
+
return memberData;
|
|
502
475
|
} catch (error) {
|
|
503
|
-
console.error('Error in
|
|
476
|
+
console.error('Error in getSiteMemberId', error.message);
|
|
504
477
|
throw error;
|
|
505
478
|
}
|
|
506
479
|
}
|
|
@@ -520,11 +493,11 @@ async function trackButtonClick({ pageName, buttonName }) {
|
|
|
520
493
|
return null;
|
|
521
494
|
}
|
|
522
495
|
|
|
523
|
-
const dbMember = await
|
|
496
|
+
const dbMember = await getMemberByContactId(wixMember._id);
|
|
524
497
|
|
|
525
498
|
if (!dbMember) {
|
|
526
499
|
console.warn(
|
|
527
|
-
`[trackButtonClick]: Member not found in MembersDataLatest for
|
|
500
|
+
`[trackButtonClick]: Member not found in MembersDataLatest for contactId: ${wixMember._id}`
|
|
528
501
|
);
|
|
529
502
|
return null;
|
|
530
503
|
}
|
|
@@ -550,20 +523,14 @@ async function trackButtonClick({ pageName, buttonName }) {
|
|
|
550
523
|
}
|
|
551
524
|
}
|
|
552
525
|
|
|
553
|
-
async function getAllMembersWithWixMemberId() {
|
|
554
|
-
const membersQuery = wixData.query(COLLECTIONS.MEMBERS_DATA).isNotEmpty('wixMemberId');
|
|
555
|
-
return await queryAllItems(membersQuery);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
526
|
module.exports = {
|
|
559
527
|
findMemberByWixDataId,
|
|
560
528
|
createContactAndMemberIfNew,
|
|
561
|
-
getAllMembersWithWixMemberId,
|
|
562
529
|
saveRegistrationData,
|
|
563
530
|
bulkSaveMembers,
|
|
564
531
|
findMemberById,
|
|
565
532
|
getMemberBySlug,
|
|
566
|
-
|
|
533
|
+
getMemberByContactId,
|
|
567
534
|
getAllEmptyAboutYouMembers,
|
|
568
535
|
updateMember,
|
|
569
536
|
getAllMembersWithExternalImages,
|
|
@@ -573,8 +540,7 @@ module.exports = {
|
|
|
573
540
|
getMembersByIds,
|
|
574
541
|
getMemberByEmail,
|
|
575
542
|
getQAUsers,
|
|
576
|
-
|
|
577
|
-
prepareMemberForQALogin,
|
|
543
|
+
getSiteMemberId,
|
|
578
544
|
checkUrlUniqueness,
|
|
579
545
|
trackButtonClick,
|
|
580
546
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { PAC_API_URL } = require('./consts');
|
|
1
|
+
const { PAC_API_URL, BACKUP_API_URL } = require('./consts');
|
|
2
2
|
const { getSecret } = require('./utils');
|
|
3
3
|
|
|
4
4
|
const getHeaders = async () => {
|
|
@@ -8,8 +8,22 @@ const getHeaders = async () => {
|
|
|
8
8
|
};
|
|
9
9
|
return headers;
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {*} params
|
|
14
|
+
* @param {number} params.page - The page number to fetch
|
|
15
|
+
* @param {string} params.action - The action to fetch
|
|
16
|
+
* @param {string} [params.backupDate] - Optional. The backup date to fetch in format YYYY-MM-DD, use only to fetch from backup endpoint not from PAC endpoint.
|
|
17
|
+
* @returns {Promise<Object>} - The response from the API
|
|
18
|
+
*/
|
|
19
|
+
const fetchPACMembers = async ({ page, action, backupDate }) => {
|
|
20
|
+
const baseUrl = backupDate ? BACKUP_API_URL : PAC_API_URL;
|
|
21
|
+
const queryParams = { page, actionFilter: action };
|
|
22
|
+
if (backupDate) {
|
|
23
|
+
queryParams.date = backupDate;
|
|
24
|
+
}
|
|
25
|
+
const url = `${baseUrl}/Members?${new URLSearchParams(queryParams).toString()}`;
|
|
26
|
+
console.log(`Fetching PAC members from: ${url}`);
|
|
13
27
|
const headers = await getHeaders();
|
|
14
28
|
const fetchOptions = {
|
|
15
29
|
method: 'get',
|
|
@@ -18,14 +32,14 @@ const fetchPACMembers = async (pageNum, actionFilter) => {
|
|
|
18
32
|
const response = await fetch(url, fetchOptions);
|
|
19
33
|
const responseType = response.headers.get('content-type');
|
|
20
34
|
if (!responseType.includes('application/json')) {
|
|
21
|
-
const errorMessage = `[fetchPACMembers] got invalid responseType: ${responseType} for page ${
|
|
35
|
+
const errorMessage = `[fetchPACMembers] got invalid responseType: ${responseType} for page ${page} and actionFilter ${action}`;
|
|
22
36
|
console.error(errorMessage);
|
|
23
37
|
throw new Error(errorMessage);
|
|
24
38
|
}
|
|
25
39
|
if (response.ok) {
|
|
26
40
|
return response.json();
|
|
27
41
|
} else {
|
|
28
|
-
const errorMessage = `[fetchPACMembers] failed with status ${response.status} for page ${
|
|
42
|
+
const errorMessage = `[fetchPACMembers] failed with status ${response.status} for page ${page} and actionFilter ${action}`;
|
|
29
43
|
console.error(errorMessage);
|
|
30
44
|
throw new Error(errorMessage);
|
|
31
45
|
}
|
package/backend/tasks/consts.js
CHANGED
|
@@ -16,8 +16,6 @@ const TASKS_NAMES = {
|
|
|
16
16
|
migrateUrlsChunk: 'migrateUrlsChunk',
|
|
17
17
|
scheduleGenerateMissingUrls: 'scheduleGenerateMissingUrls',
|
|
18
18
|
generateUrlsChunk: 'generateUrlsChunk',
|
|
19
|
-
scheduleCreateContactsFromMembers: 'scheduleCreateContactsFromMembers',
|
|
20
|
-
createContactsFromMembers: 'createContactsFromMembers',
|
|
21
19
|
};
|
|
22
20
|
|
|
23
21
|
module.exports = {
|
|
@@ -16,8 +16,6 @@ const {
|
|
|
16
16
|
migrateContactFormEmails,
|
|
17
17
|
scheduleEmailSync,
|
|
18
18
|
syncMemberLoginEmails,
|
|
19
|
-
scheduleCreateContactsFromMembers,
|
|
20
|
-
createContactsFromMembers,
|
|
21
19
|
} = require('./tasks-process-methods');
|
|
22
20
|
const {
|
|
23
21
|
scheduleMigrateExistingUrls,
|
|
@@ -45,7 +43,7 @@ const TASKS = {
|
|
|
45
43
|
},
|
|
46
44
|
[TASKS_NAMES.ScheduleMembersDataPerAction]: {
|
|
47
45
|
name: TASKS_NAMES.ScheduleMembersDataPerAction,
|
|
48
|
-
getIdentifier: task => task.data
|
|
46
|
+
getIdentifier: task => task.data,
|
|
49
47
|
process: syncMembersDataPerAction,
|
|
50
48
|
shouldSkipCheck: () => false,
|
|
51
49
|
estimatedDurationSec: 6,
|
|
@@ -155,20 +153,6 @@ const TASKS = {
|
|
|
155
153
|
shouldSkipCheck: () => false,
|
|
156
154
|
estimatedDurationSec: 80,
|
|
157
155
|
},
|
|
158
|
-
[TASKS_NAMES.scheduleCreateContactsFromMembers]: {
|
|
159
|
-
name: TASKS_NAMES.scheduleCreateContactsFromMembers,
|
|
160
|
-
getIdentifier: () => 'SHOULD_NEVER_SKIP',
|
|
161
|
-
process: scheduleCreateContactsFromMembers,
|
|
162
|
-
shouldSkipCheck: () => false,
|
|
163
|
-
estimatedDurationSec: 80,
|
|
164
|
-
},
|
|
165
|
-
[TASKS_NAMES.createContactsFromMembers]: {
|
|
166
|
-
name: TASKS_NAMES.createContactsFromMembers,
|
|
167
|
-
getIdentifier: task => task.data,
|
|
168
|
-
process: createContactsFromMembers,
|
|
169
|
-
shouldSkipCheck: () => false,
|
|
170
|
-
estimatedDurationSec: 80,
|
|
171
|
-
},
|
|
172
156
|
};
|
|
173
157
|
|
|
174
158
|
module.exports = { TASKS };
|
|
@@ -13,8 +13,6 @@ const {
|
|
|
13
13
|
bulkSaveMembers,
|
|
14
14
|
getAllUpdatedLoginEmails,
|
|
15
15
|
getMembersByIds,
|
|
16
|
-
createContactAndMemberIfNew,
|
|
17
|
-
getAllMembersWithWixMemberId,
|
|
18
16
|
} = require('../members-data-methods');
|
|
19
17
|
const {
|
|
20
18
|
getCompleteStateList,
|
|
@@ -532,46 +530,6 @@ const syncMemberLoginEmails = async data => {
|
|
|
532
530
|
throw new Error(errorMessage);
|
|
533
531
|
}
|
|
534
532
|
};
|
|
535
|
-
/**
|
|
536
|
-
* Schedules tasks to create contacts from members
|
|
537
|
-
* dev-only task, run only once by the developers
|
|
538
|
-
*/
|
|
539
|
-
const scheduleCreateContactsFromMembers = async () => {
|
|
540
|
-
const members = await getAllMembersWithWixMemberId();
|
|
541
|
-
console.log(
|
|
542
|
-
`Starting to schedule create contacts from members tasks for ${members.length} members in chunks of 500 members`
|
|
543
|
-
);
|
|
544
|
-
const membersChunks = chunkArray(members, 500);
|
|
545
|
-
for (let chunkIndex = 0; chunkIndex < membersChunks.length; chunkIndex++) {
|
|
546
|
-
const chunk = membersChunks[chunkIndex];
|
|
547
|
-
const toScheduleTask = {
|
|
548
|
-
name: TASKS_NAMES.createContactsFromMembers,
|
|
549
|
-
data: { chunk, chunkIndex },
|
|
550
|
-
};
|
|
551
|
-
await taskManager().schedule(toScheduleTask);
|
|
552
|
-
console.log(`Scheduled task for chunk ${chunkIndex} with ${chunk.length} members`);
|
|
553
|
-
}
|
|
554
|
-
console.log(`Successfully scheduled ${membersChunks.length} tasks for ${members.length} members`);
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Creates contacts from members
|
|
559
|
-
* dev-only task, run only once by the developers
|
|
560
|
-
*/
|
|
561
|
-
const createContactsFromMembers = async data => {
|
|
562
|
-
const { chunk, chunkIndex } = data;
|
|
563
|
-
console.log(`Creating contacts from ${chunk.length} members in chunk ${chunkIndex}`);
|
|
564
|
-
const createPromises = chunk.map(member => createContactAndMemberIfNew(member));
|
|
565
|
-
const createResults = await Promise.all(createPromises);
|
|
566
|
-
console.log(
|
|
567
|
-
`Created ${createResults.length} contacts from ${chunk.length} members in chunk ${chunkIndex}`
|
|
568
|
-
);
|
|
569
|
-
const saveResult = await bulkSaveMembers(createResults);
|
|
570
|
-
console.log(
|
|
571
|
-
`Successfully saved ${saveResult.totalSaved} contacts from ${chunk.length} members in chunk ${chunkIndex}`
|
|
572
|
-
);
|
|
573
|
-
return saveResult;
|
|
574
|
-
};
|
|
575
533
|
|
|
576
534
|
module.exports = {
|
|
577
535
|
scheduleTaskForEmptyAboutYouMembers,
|
|
@@ -584,6 +542,4 @@ module.exports = {
|
|
|
584
542
|
migrateContactFormEmails,
|
|
585
543
|
scheduleEmailSync,
|
|
586
544
|
syncMemberLoginEmails,
|
|
587
|
-
scheduleCreateContactsFromMembers, // run only once by the developers
|
|
588
|
-
createContactsFromMembers,
|
|
589
545
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abmp-npm",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.108",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"check-cycles": "madge --circular .",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"csv-parser": "^3.0.0",
|
|
51
51
|
"ngeohash": "^0.6.3",
|
|
52
52
|
"phone": "^3.1.67",
|
|
53
|
-
"psdev-task-manager": "1.1.
|
|
53
|
+
"psdev-task-manager": "1.1.9",
|
|
54
54
|
"psdev-utils": "1.1.1"
|
|
55
55
|
}
|
|
56
56
|
}
|