abmp-npm 2.0.20 → 2.0.22
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 +50 -21
- package/backend/daily-pull/bulk-process-methods.js +1 -1
- package/backend/dev-only-methods.js +13 -1
- package/backend/forms-methods.js +3 -3
- package/backend/login/qa-login-methods.js +8 -31
- package/backend/login/sso-methods.js +7 -7
- package/backend/members-area-methods.js +11 -17
- package/backend/members-data-methods.js +77 -41
- package/backend/routers/methods.js +8 -1
- package/backend/routers/utils.js +4 -2
- package/backend/tasks/consts.js +2 -0
- package/backend/tasks/tasks-configs.js +16 -0
- package/backend/tasks/tasks-process-methods.js +44 -0
- package/package.json +1 -1
- package/pages/Home.js +9 -2
- package/public/Utils/homePage.js +10 -9
|
@@ -3,7 +3,33 @@ 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);
|
|
6
7
|
|
|
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
|
+
}
|
|
7
33
|
/**
|
|
8
34
|
* Generic contact update helper function
|
|
9
35
|
* @param {string} contactId - The contact ID in Wix CRM
|
|
@@ -55,27 +81,27 @@ async function updateContactEmail(contactId, newEmail) {
|
|
|
55
81
|
}
|
|
56
82
|
|
|
57
83
|
/**
|
|
58
|
-
* Updates contact names in Wix CRM
|
|
59
|
-
* @param {
|
|
60
|
-
* @param {string}
|
|
61
|
-
* @param {string}
|
|
84
|
+
* Updates contact names in Wix CRM for both contact and member
|
|
85
|
+
* @param {Object} params - Parameters object
|
|
86
|
+
* @param {string} params.wixContactId - The contact ID in Wix CRM
|
|
87
|
+
* @param {string} params.wixMemberId - The member ID in Wix CRM
|
|
88
|
+
* @param {string} params.firstName - The new first name
|
|
89
|
+
* @param {string} params.lastName - The new last name
|
|
62
90
|
*/
|
|
63
|
-
async function updateContactNames(
|
|
91
|
+
async function updateContactNames({ wixContactId, firstName, lastName }) {
|
|
64
92
|
if (!firstName && !lastName) {
|
|
65
|
-
throw new Error('
|
|
93
|
+
throw new Error('First name or last name is required');
|
|
66
94
|
}
|
|
67
95
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
'update contact names'
|
|
78
|
-
);
|
|
96
|
+
const createNameUpdate = currentInfo => ({
|
|
97
|
+
...currentInfo,
|
|
98
|
+
name: {
|
|
99
|
+
first: firstName || currentInfo?.name?.first || '',
|
|
100
|
+
last: lastName || currentInfo?.name?.last || '',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return await updateContactInfo(wixContactId, createNameUpdate, 'update contact names');
|
|
79
105
|
}
|
|
80
106
|
|
|
81
107
|
/**
|
|
@@ -97,18 +123,20 @@ const updateIfChanged = (existingValues, newValues, updater, argsBuilder) => {
|
|
|
97
123
|
* @param {Object} existingMemberData - Existing member data
|
|
98
124
|
*/
|
|
99
125
|
const updateMemberContactInfo = async (data, existingMemberData) => {
|
|
100
|
-
const {
|
|
101
|
-
|
|
126
|
+
const { wixContactId } = existingMemberData;
|
|
127
|
+
if (!wixContactId) {
|
|
128
|
+
throw new Error('Wix Contact ID is required');
|
|
129
|
+
}
|
|
102
130
|
const updateConfig = [
|
|
103
131
|
{
|
|
104
132
|
fields: ['contactFormEmail'],
|
|
105
133
|
updater: updateContactEmail,
|
|
106
|
-
args: ([email]) => [
|
|
134
|
+
args: ([email]) => [wixContactId, email],
|
|
107
135
|
},
|
|
108
136
|
{
|
|
109
137
|
fields: ['firstName', 'lastName'],
|
|
110
138
|
updater: updateContactNames,
|
|
111
|
-
args: ([firstName, lastName]) => [
|
|
139
|
+
args: ([firstName, lastName]) => [{ firstName, lastName, wixContactId }],
|
|
112
140
|
},
|
|
113
141
|
];
|
|
114
142
|
|
|
@@ -125,4 +153,5 @@ const updateMemberContactInfo = async (data, existingMemberData) => {
|
|
|
125
153
|
|
|
126
154
|
module.exports = {
|
|
127
155
|
updateMemberContactInfo,
|
|
156
|
+
createSiteContact,
|
|
128
157
|
};
|
|
@@ -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.wixMemberId && 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
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { COLLECTIONS } = require('../public/consts');
|
|
2
|
+
|
|
1
3
|
const { ensureUniqueUrlsInBatch } = require('./daily-pull/bulk-process-methods');
|
|
2
4
|
const { wixData } = require('./elevated-modules');
|
|
3
5
|
const { bulkSaveMembers } = require('./members-data-methods');
|
|
@@ -15,4 +17,14 @@ async function deduplicateURls(collectionName, duplicateUrlsList) {
|
|
|
15
17
|
return await bulkSaveMembers(membersWithUniqueUrls, collectionName);
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
async function copyContactIdToWixMemberId() {
|
|
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 };
|
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.wixContactId;
|
|
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.wixContactId;
|
|
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,
|
|
44
44
|
memberEmail: memberData.contactFormEmail,
|
|
45
45
|
};
|
|
46
46
|
await wixData.insert(COLLECTIONS.CONTACT_US_SUBMISSIONS, data);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { prepareMemberForQALogin, getQAUsers } = require('../members-data-methods');
|
|
2
2
|
const { getSecret } = require('../utils');
|
|
3
3
|
|
|
4
4
|
const validateQAUser = async userEmail => {
|
|
@@ -20,27 +20,23 @@ const validateQAUser = async userEmail => {
|
|
|
20
20
|
*/
|
|
21
21
|
const loginQAMember = async ({ userEmail, secret }, generateSessionToken) => {
|
|
22
22
|
try {
|
|
23
|
-
const userValidation = await
|
|
23
|
+
const [userValidation, qaSecret] = await Promise.all([
|
|
24
|
+
validateQAUser(userEmail),
|
|
25
|
+
getSecret('ABMP_QA_SECRET'),
|
|
26
|
+
]);
|
|
24
27
|
if (userValidation.error) {
|
|
25
28
|
return { success: false, error: userValidation.error };
|
|
26
29
|
}
|
|
27
|
-
|
|
28
|
-
const qaSecret = await getSecret('ABMP_QA_SECRET');
|
|
29
30
|
if (secret !== qaSecret) {
|
|
30
31
|
return { success: false, error: 'Invalid secret' };
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const result = await getMemberCMSId(userEmail);
|
|
36
|
-
if (!result.success) {
|
|
37
|
-
return { success: false, error: result.error };
|
|
38
|
-
}
|
|
39
|
-
|
|
34
|
+
const memberData = await prepareMemberForQALogin(userValidation.email);
|
|
35
|
+
const token = await generateSessionToken(memberData.email, qaSecret);
|
|
40
36
|
return {
|
|
41
37
|
success: true,
|
|
42
38
|
token,
|
|
43
|
-
memberCMSId:
|
|
39
|
+
memberCMSId: memberData._id,
|
|
44
40
|
};
|
|
45
41
|
} catch (error) {
|
|
46
42
|
console.error('QA login error:', error);
|
|
@@ -48,25 +44,6 @@ const loginQAMember = async ({ userEmail, secret }, generateSessionToken) => {
|
|
|
48
44
|
}
|
|
49
45
|
};
|
|
50
46
|
|
|
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
|
-
|
|
70
47
|
module.exports = {
|
|
71
48
|
loginQAMember,
|
|
72
49
|
};
|
|
@@ -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 { getCMSMemberByWixMemberId, prepareMemberForSSOLogin } = 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
|
+
getCMSMemberByWixMemberId(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 wix member 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 memberData = await prepareMemberForSSOLogin(payload);
|
|
137
|
+
console.log('memberDataCollectionId', memberData._id);
|
|
138
|
+
const sessionToken = await generateSessionToken(memberData.email);
|
|
139
139
|
const authObj = {
|
|
140
140
|
type: 'success',
|
|
141
|
-
memberId:
|
|
141
|
+
memberId: memberData._id,
|
|
142
142
|
sessionToken,
|
|
143
143
|
};
|
|
144
144
|
return authObj;
|
|
@@ -1,16 +1,11 @@
|
|
|
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 elevatedChangeLoginEmail = auth.elevate(authentication.changeLoginEmail);
|
|
4
5
|
|
|
5
|
-
function
|
|
6
|
-
const phones = Array.isArray(partner.phones) ? partner.phones : []; //some users don't have phones
|
|
6
|
+
function prepareMemberData(partner) {
|
|
7
7
|
const options = {
|
|
8
8
|
member: {
|
|
9
|
-
contact: {
|
|
10
|
-
...partner,
|
|
11
|
-
phones,
|
|
12
|
-
emails: [partner.contactFormEmail || partner.email],
|
|
13
|
-
},
|
|
14
9
|
loginEmail: partner.email,
|
|
15
10
|
},
|
|
16
11
|
};
|
|
@@ -22,9 +17,8 @@ async function createMemberFunction(member) {
|
|
|
22
17
|
}
|
|
23
18
|
const createSiteMember = async memberDetails => {
|
|
24
19
|
try {
|
|
25
|
-
const options =
|
|
26
|
-
|
|
27
|
-
return contactId;
|
|
20
|
+
const options = prepareMemberData(memberDetails);
|
|
21
|
+
return await createMemberFunction(options);
|
|
28
22
|
} catch (error) {
|
|
29
23
|
console.error(`Error in createSiteMember ${error.message}`);
|
|
30
24
|
throw error;
|
|
@@ -37,22 +31,22 @@ const getCurrentMember = async () => {
|
|
|
37
31
|
};
|
|
38
32
|
|
|
39
33
|
/**
|
|
40
|
-
* Updates Wix member login email if the member has a
|
|
41
|
-
* @param {Object} member - Member object with
|
|
34
|
+
* Updates Wix member login email if the member has a wixMemberId (registered Wix member)
|
|
35
|
+
* @param {Object} member - Member object with wixMemberId and email
|
|
42
36
|
* @param {Object} result - Result object to track Wix member updates
|
|
43
37
|
*/
|
|
44
38
|
async function updateWixMemberLoginEmail(member, result = {}) {
|
|
45
|
-
if (!member.
|
|
46
|
-
console.log(`Member ${member.memberId} has no
|
|
39
|
+
if (!member.wixMemberId) {
|
|
40
|
+
console.log(`Member ${member.memberId} has no wixMemberId - skipping Wix login email update`);
|
|
47
41
|
return;
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
try {
|
|
51
45
|
console.log(
|
|
52
|
-
`Updating Wix login email for member ${member.memberId} (
|
|
46
|
+
`Updating Wix login email for member ${member.memberId} (wixMemberId: ${member.wixMemberId})`
|
|
53
47
|
);
|
|
54
48
|
|
|
55
|
-
const updatedWixMember = await
|
|
49
|
+
const updatedWixMember = await elevatedChangeLoginEmail(member.wixMemberId, member.email);
|
|
56
50
|
|
|
57
51
|
console.log(
|
|
58
52
|
`✅ Successfully updated Wix login email for member ${member.memberId}: ${updatedWixMember.loginEmail}`
|
|
@@ -75,7 +69,7 @@ async function updateWixMemberLoginEmail(member, result = {}) {
|
|
|
75
69
|
}
|
|
76
70
|
result.wixMemberErrors.push({
|
|
77
71
|
memberId: member.memberId,
|
|
78
|
-
|
|
72
|
+
wixMemberId: member.wixMemberId,
|
|
79
73
|
email: member.email,
|
|
80
74
|
error: error.message,
|
|
81
75
|
});
|
|
@@ -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 } = require('./contacts-methods');
|
|
5
|
+
const { updateMemberContactInfo, createSiteContact } = 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,10 +43,16 @@ async function createContactAndMemberIfNew(memberData) {
|
|
|
43
43
|
phones: memberData.phones,
|
|
44
44
|
contactFormEmail: memberData.contactFormEmail || memberData.email,
|
|
45
45
|
};
|
|
46
|
-
const
|
|
46
|
+
const needsWixMember = !memberData.wixMemberId;
|
|
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
|
+
]);
|
|
47
52
|
let memberDataWithContactId = {
|
|
48
53
|
...memberData,
|
|
49
|
-
|
|
54
|
+
wixMemberId: newWixMemberId || memberData.wixMemberId,
|
|
55
|
+
wixContactId: newWixContactId || memberData.wixContactId,
|
|
50
56
|
};
|
|
51
57
|
const updatedResult = await updateMember(memberDataWithContactId);
|
|
52
58
|
memberDataWithContactId = {
|
|
@@ -94,10 +100,16 @@ async function findMemberById(memberId) {
|
|
|
94
100
|
const queryResult = await wixData
|
|
95
101
|
.query(COLLECTIONS.MEMBERS_DATA)
|
|
96
102
|
.eq('memberId', memberId)
|
|
103
|
+
.limit(2)
|
|
97
104
|
.find();
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
if (queryResult.items.length > 1) {
|
|
106
|
+
throw new Error(
|
|
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;
|
|
100
111
|
} catch (error) {
|
|
112
|
+
console.error('Error finding member by ID:', error);
|
|
101
113
|
throw new Error(`Failed to retrieve member data: ${error.message}`);
|
|
102
114
|
}
|
|
103
115
|
}
|
|
@@ -159,31 +171,32 @@ async function getMemberBySlug({
|
|
|
159
171
|
}
|
|
160
172
|
return matchingMembers[0] || null;
|
|
161
173
|
} catch (error) {
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
const errorMessage = `Error getting member by slug: ${slug} : ${error.message}`;
|
|
175
|
+
console.error(errorMessage);
|
|
176
|
+
throw new Error(errorMessage);
|
|
164
177
|
}
|
|
165
178
|
}
|
|
166
179
|
|
|
167
|
-
async function
|
|
168
|
-
if (!
|
|
169
|
-
throw new Error('
|
|
180
|
+
async function getCMSMemberByWixMemberId(wixMemberId) {
|
|
181
|
+
if (!wixMemberId) {
|
|
182
|
+
throw new Error('Wix Member ID is required');
|
|
170
183
|
}
|
|
171
184
|
try {
|
|
172
185
|
const members = await wixData
|
|
173
186
|
.query(COLLECTIONS.MEMBERS_DATA)
|
|
174
|
-
.eq('
|
|
187
|
+
.eq('wixMemberId', wixMemberId)
|
|
175
188
|
.limit(2)
|
|
176
189
|
.find()
|
|
177
190
|
.then(res => res.items);
|
|
178
191
|
if (members.length > 1) {
|
|
179
192
|
throw new Error(
|
|
180
|
-
`[
|
|
193
|
+
`[getCMSMemberByWixMemberId] Multiple members found with wixMemberId ${wixMemberId} membersIds are : [${members.map(member => member.memberId).join(', ')}]`
|
|
181
194
|
);
|
|
182
195
|
}
|
|
183
196
|
return members[0] || null;
|
|
184
197
|
} catch (error) {
|
|
185
198
|
throw new Error(
|
|
186
|
-
`[
|
|
199
|
+
`[getCMSMemberByWixMemberId] Failed to retrieve member by wixMemberId ${wixMemberId} data: ${error.message}`
|
|
187
200
|
);
|
|
188
201
|
}
|
|
189
202
|
}
|
|
@@ -456,41 +469,57 @@ const getQAUsers = async () => {
|
|
|
456
469
|
throw new Error(`Failed to get QA users: ${error.message}`);
|
|
457
470
|
}
|
|
458
471
|
};
|
|
459
|
-
|
|
472
|
+
/**
|
|
473
|
+
* Ensures member has a contact - creates one if missing
|
|
474
|
+
* @param {Object} memberData - Member data from DB
|
|
475
|
+
* @returns {Promise<Object>} - Member data with contact and member IDs
|
|
476
|
+
*/
|
|
477
|
+
async function ensureWixMemberAndContactExist(memberData) {
|
|
478
|
+
if (!memberData) {
|
|
479
|
+
throw new Error('Member data is required');
|
|
480
|
+
}
|
|
481
|
+
if (!memberData.wixContactId || !memberData.wixMemberId) {
|
|
482
|
+
const memberDataWithContactId = await createContactAndMemberIfNew(memberData);
|
|
483
|
+
return memberDataWithContactId;
|
|
484
|
+
}
|
|
485
|
+
return memberData;
|
|
486
|
+
}
|
|
487
|
+
async function prepareMemberForSSOLogin(data) {
|
|
460
488
|
try {
|
|
461
489
|
console.log('data', data);
|
|
462
490
|
const memberId = data?.pac?.cst_recno;
|
|
463
491
|
if (!memberId) {
|
|
464
|
-
|
|
465
|
-
console.error(errorMessage);
|
|
466
|
-
throw new Error(errorMessage);
|
|
492
|
+
throw new Error(`Member ID is missing in passed data ${JSON.stringify(data)}`);
|
|
467
493
|
}
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
.find()
|
|
472
|
-
.then(res => res.items);
|
|
473
|
-
if (!queryMemberResult.length || queryMemberResult.length > 1) {
|
|
474
|
-
throw new Error(
|
|
475
|
-
`Invalid Members count found in DB for email ${data.email} members count is : [${
|
|
476
|
-
queryMemberResult.length
|
|
477
|
-
}] membersIds are : [${queryMemberResult.map(member => member.memberId).join(', ')}]`
|
|
478
|
-
);
|
|
494
|
+
const memberData = await findMemberById(Number(memberId));
|
|
495
|
+
if (!memberData) {
|
|
496
|
+
throw new Error(`Member data not found for memberId ${memberId}`);
|
|
479
497
|
}
|
|
480
|
-
let memberData = queryMemberResult[0];
|
|
481
498
|
console.log('memberData', memberData);
|
|
482
|
-
|
|
483
|
-
if (isNewUser) {
|
|
484
|
-
const memberDataWithContactId = await createContactAndMemberIfNew(memberData);
|
|
485
|
-
console.log('memberDataWithContactId', memberDataWithContactId);
|
|
486
|
-
memberData = memberDataWithContactId;
|
|
487
|
-
}
|
|
488
|
-
return memberData;
|
|
499
|
+
return await ensureWixMemberAndContactExist(memberData);
|
|
489
500
|
} catch (error) {
|
|
490
|
-
console.error(
|
|
501
|
+
console.error(`Error in prepareMemberForSSOLogin: ${error.message}`);
|
|
491
502
|
throw error;
|
|
492
503
|
}
|
|
493
504
|
}
|
|
505
|
+
async function prepareMemberForQALogin(email) {
|
|
506
|
+
try {
|
|
507
|
+
console.log('qa email:', email);
|
|
508
|
+
if (!email) {
|
|
509
|
+
throw new Error(`Email is missing in passed data ${email}`);
|
|
510
|
+
}
|
|
511
|
+
const memberData = await getMemberByEmail(email);
|
|
512
|
+
if (!memberData) {
|
|
513
|
+
throw new Error(`Member data not found for email ${email}`);
|
|
514
|
+
}
|
|
515
|
+
console.log('memberData', memberData);
|
|
516
|
+
return await ensureWixMemberAndContactExist(memberData);
|
|
517
|
+
} catch (error) {
|
|
518
|
+
const errMsg = `[prepareMemberForQALogin] QA Login failed with error: ${error.message} for email: ${email}`;
|
|
519
|
+
console.error(errMsg);
|
|
520
|
+
throw new Error(errMsg);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
494
523
|
|
|
495
524
|
/**
|
|
496
525
|
* Tracks a button click with member and location info.
|
|
@@ -507,11 +536,11 @@ async function trackButtonClick({ pageName, buttonName }) {
|
|
|
507
536
|
return null;
|
|
508
537
|
}
|
|
509
538
|
|
|
510
|
-
const dbMember = await
|
|
539
|
+
const dbMember = await getCMSMemberByWixMemberId(wixMember._id);
|
|
511
540
|
|
|
512
541
|
if (!dbMember) {
|
|
513
542
|
console.warn(
|
|
514
|
-
`[trackButtonClick]: Member not found in MembersDataLatest for
|
|
543
|
+
`[trackButtonClick]: Member not found in MembersDataLatest for wixMemberId: ${wixMember._id}`
|
|
515
544
|
);
|
|
516
545
|
return null;
|
|
517
546
|
}
|
|
@@ -537,14 +566,20 @@ async function trackButtonClick({ pageName, buttonName }) {
|
|
|
537
566
|
}
|
|
538
567
|
}
|
|
539
568
|
|
|
569
|
+
async function getAllMembersWithWixMemberId() {
|
|
570
|
+
const membersQuery = wixData.query(COLLECTIONS.MEMBERS_DATA).isNotEmpty('wixMemberId');
|
|
571
|
+
return await queryAllItems(membersQuery);
|
|
572
|
+
}
|
|
573
|
+
|
|
540
574
|
module.exports = {
|
|
541
575
|
findMemberByWixDataId,
|
|
542
576
|
createContactAndMemberIfNew,
|
|
577
|
+
getAllMembersWithWixMemberId,
|
|
543
578
|
saveRegistrationData,
|
|
544
579
|
bulkSaveMembers,
|
|
545
580
|
findMemberById,
|
|
546
581
|
getMemberBySlug,
|
|
547
|
-
|
|
582
|
+
getCMSMemberByWixMemberId,
|
|
548
583
|
getAllEmptyAboutYouMembers,
|
|
549
584
|
updateMember,
|
|
550
585
|
getAllMembersWithExternalImages,
|
|
@@ -554,7 +589,8 @@ module.exports = {
|
|
|
554
589
|
getMembersByIds,
|
|
555
590
|
getMemberByEmail,
|
|
556
591
|
getQAUsers,
|
|
557
|
-
|
|
592
|
+
prepareMemberForSSOLogin,
|
|
593
|
+
prepareMemberForQALogin,
|
|
558
594
|
checkUrlUniqueness,
|
|
559
595
|
trackButtonClick,
|
|
560
596
|
};
|
|
@@ -126,9 +126,16 @@ const createRoutersHandlers = wixRouterMethods => {
|
|
|
126
126
|
};
|
|
127
127
|
return ok('profile', { ...profileData, defaultProfileImage }, seoData);
|
|
128
128
|
}
|
|
129
|
+
console.log(
|
|
130
|
+
`[profileRouter] Profile not found returning 404 for: ${JSON.stringify({
|
|
131
|
+
slug,
|
|
132
|
+
profileData,
|
|
133
|
+
showWixUrl: profileData?.showWixUrl,
|
|
134
|
+
})}`
|
|
135
|
+
);
|
|
129
136
|
return notFound();
|
|
130
137
|
} catch (error) {
|
|
131
|
-
console.error(error);
|
|
138
|
+
console.error(`Error in profileRouter for slug: ${slug} : ${error.message}`);
|
|
132
139
|
return sendStatus('500', 'Internal Server Error');
|
|
133
140
|
}
|
|
134
141
|
}
|
package/backend/routers/utils.js
CHANGED
|
@@ -104,13 +104,15 @@ const getMemberProfileData = async (slug, siteAssociation) => {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
if (!member) {
|
|
107
|
+
console.log(`[getMemberProfileData] Member not found for slug: ${slug}`);
|
|
107
108
|
return null;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
return transformMemberToProfileData(member, siteAssociation);
|
|
111
112
|
} catch (error) {
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
const errorMessage = `Error in getMemberProfileData for slug: ${slug} : ${error.message}`;
|
|
114
|
+
console.error(errorMessage);
|
|
115
|
+
throw new Error(errorMessage);
|
|
114
116
|
}
|
|
115
117
|
};
|
|
116
118
|
|
package/backend/tasks/consts.js
CHANGED
|
@@ -16,6 +16,8 @@ const TASKS_NAMES = {
|
|
|
16
16
|
migrateUrlsChunk: 'migrateUrlsChunk',
|
|
17
17
|
scheduleGenerateMissingUrls: 'scheduleGenerateMissingUrls',
|
|
18
18
|
generateUrlsChunk: 'generateUrlsChunk',
|
|
19
|
+
scheduleCreateContactsFromMembers: 'scheduleCreateContactsFromMembers',
|
|
20
|
+
createContactsFromMembers: 'createContactsFromMembers',
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
module.exports = {
|
|
@@ -16,6 +16,8 @@ const {
|
|
|
16
16
|
migrateContactFormEmails,
|
|
17
17
|
scheduleEmailSync,
|
|
18
18
|
syncMemberLoginEmails,
|
|
19
|
+
scheduleCreateContactsFromMembers,
|
|
20
|
+
createContactsFromMembers,
|
|
19
21
|
} = require('./tasks-process-methods');
|
|
20
22
|
const {
|
|
21
23
|
scheduleMigrateExistingUrls,
|
|
@@ -153,6 +155,20 @@ const TASKS = {
|
|
|
153
155
|
shouldSkipCheck: () => false,
|
|
154
156
|
estimatedDurationSec: 80,
|
|
155
157
|
},
|
|
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
|
+
},
|
|
156
172
|
};
|
|
157
173
|
|
|
158
174
|
module.exports = { TASKS };
|
|
@@ -13,6 +13,8 @@ const {
|
|
|
13
13
|
bulkSaveMembers,
|
|
14
14
|
getAllUpdatedLoginEmails,
|
|
15
15
|
getMembersByIds,
|
|
16
|
+
createContactAndMemberIfNew,
|
|
17
|
+
getAllMembersWithWixMemberId,
|
|
16
18
|
} = require('../members-data-methods');
|
|
17
19
|
const {
|
|
18
20
|
getCompleteStateList,
|
|
@@ -530,6 +532,46 @@ const syncMemberLoginEmails = async data => {
|
|
|
530
532
|
throw new Error(errorMessage);
|
|
531
533
|
}
|
|
532
534
|
};
|
|
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
|
+
};
|
|
533
575
|
|
|
534
576
|
module.exports = {
|
|
535
577
|
scheduleTaskForEmptyAboutYouMembers,
|
|
@@ -542,4 +584,6 @@ module.exports = {
|
|
|
542
584
|
migrateContactFormEmails,
|
|
543
585
|
scheduleEmailSync,
|
|
544
586
|
syncMemberLoginEmails,
|
|
587
|
+
scheduleCreateContactsFromMembers, // run only once by the developers
|
|
588
|
+
createContactsFromMembers,
|
|
545
589
|
};
|
package/package.json
CHANGED
package/pages/Home.js
CHANGED
|
@@ -211,9 +211,16 @@ const homePageOnReady = async ({
|
|
|
211
211
|
// 5) Location text
|
|
212
212
|
const mainAddress = getMainAddress(itemData.addressDisplayOption, addresses);
|
|
213
213
|
$item('#location').text = mainAddress || '';
|
|
214
|
+
|
|
215
|
+
// 6) Miles away
|
|
216
|
+
const isNearbyEnabled = _$w('#nearBy').checked;
|
|
214
217
|
const miles = itemData.distance ?? 0;
|
|
215
|
-
|
|
216
|
-
if (
|
|
218
|
+
|
|
219
|
+
if (isNearbyEnabled && miles) {
|
|
220
|
+
$item('#differenceInMiles').text = miles.toFixed(1);
|
|
221
|
+
$item('#milesAwayText').text = 'miles away';
|
|
222
|
+
} else {
|
|
223
|
+
$item('#differenceInMiles').text = '';
|
|
217
224
|
$item('#milesAwayText').text = '';
|
|
218
225
|
}
|
|
219
226
|
|
package/public/Utils/homePage.js
CHANGED
|
@@ -120,9 +120,11 @@ const createHomepageUtils = (_$w, filterProfiles) => {
|
|
|
120
120
|
});
|
|
121
121
|
async function handlePagination({ delta, pagination, searchResults, filter }) {
|
|
122
122
|
const newPage = pagination.currentPage + delta;
|
|
123
|
-
|
|
123
|
+
const maxPage = pagination.totalPages ? pagination.totalPages - 1 : 0;
|
|
124
|
+
if (newPage < 0 || newPage > maxPage) return;
|
|
125
|
+
|
|
124
126
|
newPage === 0 ? _$w('#previousPage').disable() : _$w('#previousPage').enable();
|
|
125
|
-
newPage ===
|
|
127
|
+
newPage === maxPage ? _$w('#nextPage').disable() : _$w('#nextPage').enable();
|
|
126
128
|
pagination.currentPage = newPage;
|
|
127
129
|
|
|
128
130
|
paginateSearchResults(searchResults, pagination);
|
|
@@ -466,22 +468,21 @@ const createHomepageUtils = (_$w, filterProfiles) => {
|
|
|
466
468
|
currentPageButtonIterator.collapse();
|
|
467
469
|
}
|
|
468
470
|
}
|
|
469
|
-
if (
|
|
471
|
+
if (totalPages === 0 || totalPages === 1) {
|
|
470
472
|
_$w('#previousPage').disable();
|
|
471
473
|
_$w('#nextPage').disable();
|
|
472
474
|
return;
|
|
473
475
|
}
|
|
474
476
|
if (currentPage === 0) {
|
|
475
477
|
_$w('#previousPage').disable();
|
|
476
|
-
|
|
478
|
+
} else {
|
|
479
|
+
_$w('#previousPage').enable();
|
|
477
480
|
}
|
|
478
|
-
if (currentPage
|
|
481
|
+
if (currentPage >= totalPages - 1) {
|
|
479
482
|
_$w('#nextPage').disable();
|
|
480
|
-
|
|
483
|
+
} else {
|
|
484
|
+
_$w('#nextPage').enable();
|
|
481
485
|
}
|
|
482
|
-
|
|
483
|
-
_$w('#previousPage').enable();
|
|
484
|
-
_$w('#nextPage').enable();
|
|
485
486
|
}
|
|
486
487
|
function paginateSearchResults(searchResults, pagination) {
|
|
487
488
|
updatePaginationUI(pagination);
|