abmp-npm 2.0.76 → 2.0.78
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/package.json +8 -1
- package/pages/Home.js +27 -55
- package/pages/index.js +0 -1
- package/public/Utils/personalDetailsUtils.js +5 -1
- package/public/Utils/sharedUtils.js +32 -0
- package/public/consts.js +0 -1
- package/.claude/worktrees/fix-save-button-disable/.husky/pre-commit +0 -19
- package/.claude/worktrees/fix-save-button-disable/.prettierignore +0 -7
- package/.claude/worktrees/fix-save-button-disable/.prettierrc.json +0 -16
- package/.claude/worktrees/fix-save-button-disable/README.md +0 -1
- package/.claude/worktrees/fix-save-button-disable/backend/README-member-contact-flows.md +0 -136
- package/.claude/worktrees/fix-save-button-disable/backend/__tests__/daily-pull-execution-check.test.js +0 -124
- package/.claude/worktrees/fix-save-button-disable/backend/__tests__/ensure-unique-urls-in-batch.test.js +0 -129
- package/.claude/worktrees/fix-save-button-disable/backend/__tests__/login-email-sync.test.js +0 -49
- package/.claude/worktrees/fix-save-button-disable/backend/__tests__/transient-retry-and-bulk-lookup.test.js +0 -129
- package/.claude/worktrees/fix-save-button-disable/backend/__tests__/url-uniqueness.test.js +0 -194
- package/.claude/worktrees/fix-save-button-disable/backend/automations-methods.js +0 -13
- package/.claude/worktrees/fix-save-button-disable/backend/cms-data-methods.js +0 -251
- package/.claude/worktrees/fix-save-button-disable/backend/consts.js +0 -58
- package/.claude/worktrees/fix-save-button-disable/backend/contacts-methods.js +0 -67
- package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/bulk-process-methods.js +0 -222
- package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/consts.js +0 -39
- package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/index.js +0 -5
- package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/process-member-methods.js +0 -213
- package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/schedule-methods.js +0 -41
- package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/sync-to-cms-methods.js +0 -161
- package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/utils.js +0 -151
- package/.claude/worktrees/fix-save-button-disable/backend/data-hooks.js +0 -29
- package/.claude/worktrees/fix-save-button-disable/backend/dev-only-methods.js +0 -58
- package/.claude/worktrees/fix-save-button-disable/backend/elevated-modules.js +0 -18
- package/.claude/worktrees/fix-save-button-disable/backend/forms-methods.js +0 -52
- package/.claude/worktrees/fix-save-button-disable/backend/http-functions/httpFunctions.js +0 -86
- package/.claude/worktrees/fix-save-button-disable/backend/http-functions/index.js +0 -3
- package/.claude/worktrees/fix-save-button-disable/backend/http-functions/interests.js +0 -35
- package/.claude/worktrees/fix-save-button-disable/backend/index.js +0 -19
- package/.claude/worktrees/fix-save-button-disable/backend/jobs.js +0 -158
- package/.claude/worktrees/fix-save-button-disable/backend/login/generate-member-session-token.js +0 -27
- package/.claude/worktrees/fix-save-button-disable/backend/login/index.js +0 -8
- package/.claude/worktrees/fix-save-button-disable/backend/login/qa-login-methods.js +0 -54
- package/.claude/worktrees/fix-save-button-disable/backend/login/sso-methods.js +0 -159
- package/.claude/worktrees/fix-save-button-disable/backend/member-contact-orchestration.js +0 -111
- package/.claude/worktrees/fix-save-button-disable/backend/members-area-methods.js +0 -88
- package/.claude/worktrees/fix-save-button-disable/backend/members-data-methods.js +0 -789
- package/.claude/worktrees/fix-save-button-disable/backend/pac-api-methods.js +0 -54
- package/.claude/worktrees/fix-save-button-disable/backend/routers/index.js +0 -3
- package/.claude/worktrees/fix-save-button-disable/backend/routers/methods.js +0 -191
- package/.claude/worktrees/fix-save-button-disable/backend/routers/utils.js +0 -128
- package/.claude/worktrees/fix-save-button-disable/backend/search-filters-methods.js +0 -124
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-primary-methods.js +0 -256
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-visibility-methods.js +0 -160
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/consts.js +0 -34
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/daily-pull-check-methods.js +0 -78
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/email-normalize-methods.js +0 -134
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/index.js +0 -10
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/migration-methods.js +0 -46
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-configs.js +0 -251
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-helpers-methods.js +0 -433
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-process-methods.js +0 -606
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-migration-methods.js +0 -378
- package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-space-fix-methods.js +0 -174
- package/.claude/worktrees/fix-save-button-disable/backend/utils.js +0 -277
- package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/extract-duplicate-url-groups.js +0 -201
- package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-ids.js +0 -159
- package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-urls.js +0 -201
- package/.claude/worktrees/fix-save-button-disable/eslint.config.js +0 -120
- package/.claude/worktrees/fix-save-button-disable/index.js +0 -5
- package/.claude/worktrees/fix-save-button-disable/package-lock.json +0 -12160
- package/.claude/worktrees/fix-save-button-disable/package.json +0 -60
- package/.claude/worktrees/fix-save-button-disable/pages/ContactUs.js +0 -129
- package/.claude/worktrees/fix-save-button-disable/pages/Home.js +0 -779
- package/.claude/worktrees/fix-save-button-disable/pages/LearnMore.js +0 -27
- package/.claude/worktrees/fix-save-button-disable/pages/LoadingPage.js +0 -29
- package/.claude/worktrees/fix-save-button-disable/pages/Profile.js +0 -354
- package/.claude/worktrees/fix-save-button-disable/pages/QAPage.js +0 -39
- package/.claude/worktrees/fix-save-button-disable/pages/SaveAlerts.js +0 -13
- package/.claude/worktrees/fix-save-button-disable/pages/SelectBannerImages.js +0 -46
- package/.claude/worktrees/fix-save-button-disable/pages/deleteConfirm.js +0 -19
- package/.claude/worktrees/fix-save-button-disable/pages/index.js +0 -12
- package/.claude/worktrees/fix-save-button-disable/pages/personalDetails.js +0 -2486
- package/.claude/worktrees/fix-save-button-disable/public/Utils/homePage.js +0 -798
- package/.claude/worktrees/fix-save-button-disable/public/Utils/personalDetailsUtils.js +0 -25
- package/.claude/worktrees/fix-save-button-disable/public/Utils/sharedUtils.js +0 -235
- package/.claude/worktrees/fix-save-button-disable/public/consts.js +0 -113
- package/.claude/worktrees/fix-save-button-disable/public/index.js +0 -5
- package/.claude/worktrees/fix-save-button-disable/public/messages.js +0 -16
- package/.claude/worktrees/fix-save-button-disable/public/sso-auth-methods.js +0 -43
- package/.husky/pre-commit +0 -19
- package/.prettierignore +0 -7
- package/.prettierrc.json +0 -16
- package/backend/__tests__/daily-pull-execution-check.test.js +0 -124
- package/backend/__tests__/ensure-unique-urls-in-batch.test.js +0 -129
- package/backend/__tests__/login-email-sync.test.js +0 -49
- package/backend/__tests__/transient-retry-and-bulk-lookup.test.js +0 -129
- package/backend/__tests__/url-uniqueness.test.js +0 -194
- package/dev-only-scripts/extract-duplicate-url-groups.js +0 -201
- package/dev-only-scripts/find-duplicate-ids.js +0 -159
- package/dev-only-scripts/find-duplicate-urls.js +0 -201
- package/eslint.config.js +0 -120
- package/pages/contactForLocation.js +0 -28
|
@@ -1,606 +0,0 @@
|
|
|
1
|
-
const { taskManager } = require('psdev-task-manager');
|
|
2
|
-
|
|
3
|
-
const { COLLECTIONS } = require('../../public/consts');
|
|
4
|
-
const { COMPILED_FILTERS_FIELDS, CONFIG_KEYS, LOGIN_EMAIL_SYNC_STATUS } = require('../consts');
|
|
5
|
-
const { changeWixMembersEmails, summarizeLoginEmailOutcomes } = require('../daily-pull/utils');
|
|
6
|
-
const { wixData } = require('../elevated-modules');
|
|
7
|
-
const {
|
|
8
|
-
getAllEmptyAboutYouMembers,
|
|
9
|
-
getAllMembersWithExternalImages,
|
|
10
|
-
getMembersWithWixUrl,
|
|
11
|
-
getAllMembersWithoutContactFormEmail,
|
|
12
|
-
findMemberByWixDataId,
|
|
13
|
-
bulkSaveMembers,
|
|
14
|
-
getAllUpdatedLoginEmails,
|
|
15
|
-
getMembersByIds,
|
|
16
|
-
createContactAndMemberIfNew,
|
|
17
|
-
getAllMembersWithWixMemberId,
|
|
18
|
-
} = require('../members-data-methods');
|
|
19
|
-
const {
|
|
20
|
-
getCompleteStateList,
|
|
21
|
-
getAreasOfPracticeList,
|
|
22
|
-
getStateCityMap,
|
|
23
|
-
getCompiledFiltersOptions,
|
|
24
|
-
} = require('../search-filters-methods');
|
|
25
|
-
const { chunkArray, getSiteConfigs } = require('../utils');
|
|
26
|
-
|
|
27
|
-
const { TASKS_NAMES } = require('./consts');
|
|
28
|
-
const {
|
|
29
|
-
updateMemberRichContent,
|
|
30
|
-
updateMemberProfileImage,
|
|
31
|
-
getAWSTokens,
|
|
32
|
-
uploadMembersSitemap,
|
|
33
|
-
} = require('./tasks-helpers-methods');
|
|
34
|
-
|
|
35
|
-
const scheduleTaskForEmptyAboutYouMembers = async () => {
|
|
36
|
-
const createTasksFromMembers = members => {
|
|
37
|
-
const memberIds = members.map(member => member._id);
|
|
38
|
-
return {
|
|
39
|
-
name: TASKS_NAMES.convertHtmlToRichContent,
|
|
40
|
-
data: { memberIds },
|
|
41
|
-
type: 'scheduled',
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
const members = await getAllEmptyAboutYouMembers();
|
|
45
|
-
console.log('starting to schedule tasks for empty about you members');
|
|
46
|
-
const membersChunks = chunkArray(members, 1000);
|
|
47
|
-
for (const chunk of membersChunks) {
|
|
48
|
-
const toScheduleTask = createTasksFromMembers(chunk);
|
|
49
|
-
await taskManager().schedule(toScheduleTask);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
//this funciton takes ~0.5 seconds per member
|
|
54
|
-
const convertAboutYouHtmlToRichContent = async membersIds => {
|
|
55
|
-
const result = {};
|
|
56
|
-
|
|
57
|
-
// Process members in chunks of 30
|
|
58
|
-
const chunks = chunkArray(membersIds, 30);
|
|
59
|
-
|
|
60
|
-
for (const chunk of chunks) {
|
|
61
|
-
console.log(`Processing chunk of ${chunk.length} members`);
|
|
62
|
-
|
|
63
|
-
// Process each chunk concurrently using Promise.all
|
|
64
|
-
const chunkPromises = chunk.map(async memberId => {
|
|
65
|
-
console.log('memberId ======', memberId);
|
|
66
|
-
try {
|
|
67
|
-
await updateMemberRichContent(memberId);
|
|
68
|
-
return { memberId, success: true };
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error('error in updating member', error);
|
|
71
|
-
return { memberId, success: false };
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// Wait for all promises in the chunk to complete
|
|
76
|
-
const chunkResults = await Promise.all(chunkPromises);
|
|
77
|
-
|
|
78
|
-
// Update result object with chunk results
|
|
79
|
-
chunkResults.forEach(({ memberId, success }) => {
|
|
80
|
-
result[memberId] = success;
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return result;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
async function compileFiltersOptions(field) {
|
|
88
|
-
const getNonCompiledFilter = field => {
|
|
89
|
-
const filterMap = {
|
|
90
|
-
[COMPILED_FILTERS_FIELDS.COMPILED_STATE_LIST]: getCompleteStateList,
|
|
91
|
-
[COMPILED_FILTERS_FIELDS.COMPILED_AREAS_OF_PRACTICES]: getAreasOfPracticeList,
|
|
92
|
-
[COMPILED_FILTERS_FIELDS.COMPILED_STATE_CITY_MAP]: getStateCityMap,
|
|
93
|
-
};
|
|
94
|
-
const filterFunction = filterMap[field];
|
|
95
|
-
if (!filterFunction) {
|
|
96
|
-
throw new Error(`Unknown filter field: ${field}`);
|
|
97
|
-
}
|
|
98
|
-
return filterFunction();
|
|
99
|
-
};
|
|
100
|
-
const [nonCompiledFilterData, compiledFiltersOptions] = await Promise.all([
|
|
101
|
-
getNonCompiledFilter(field),
|
|
102
|
-
getCompiledFiltersOptions(),
|
|
103
|
-
]);
|
|
104
|
-
compiledFiltersOptions[field] = nonCompiledFilterData;
|
|
105
|
-
await wixData.save(COLLECTIONS.COMPILED_STATE_CITY_MAP, compiledFiltersOptions);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const scheduleTaskForExternalProfileImages = async () => {
|
|
109
|
-
const createImageMigrationTasksFromMembers = members => {
|
|
110
|
-
const memberIds = members.map(member => member._id);
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
name: TASKS_NAMES.convertExternalProfilesToWixImages,
|
|
114
|
-
data: { memberIds },
|
|
115
|
-
type: 'scheduled',
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
const members = await getAllMembersWithExternalImages();
|
|
119
|
-
console.log('Starting to schedule tasks for external profile image migration');
|
|
120
|
-
const membersChunks = chunkArray(members, 300);
|
|
121
|
-
for (const chunk of membersChunks) {
|
|
122
|
-
const toScheduleTask = createImageMigrationTasksFromMembers(chunk);
|
|
123
|
-
await taskManager().schedule(toScheduleTask);
|
|
124
|
-
}
|
|
125
|
-
console.log(`Scheduled ${members.length} members for profile image migration`);
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const convertExternalProfilesToWixImages = async membersIds => {
|
|
129
|
-
const result = {};
|
|
130
|
-
|
|
131
|
-
// Process members in chunks of 30 (optimal concurrent processing)
|
|
132
|
-
const chunks = chunkArray(membersIds, 30);
|
|
133
|
-
|
|
134
|
-
for (const chunk of chunks) {
|
|
135
|
-
console.log(`Processing profile image chunk of ${chunk.length} members`);
|
|
136
|
-
|
|
137
|
-
// Process each chunk concurrently using Promise.all
|
|
138
|
-
const chunkPromises = chunk.map(async memberId => {
|
|
139
|
-
console.log('Processing profile image for member:', memberId);
|
|
140
|
-
try {
|
|
141
|
-
const updateResult = await updateMemberProfileImage(memberId);
|
|
142
|
-
return {
|
|
143
|
-
memberId,
|
|
144
|
-
success: updateResult.success,
|
|
145
|
-
message: updateResult.message,
|
|
146
|
-
};
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.error('Error updating member profile image:', error);
|
|
149
|
-
return { memberId, success: false, error: error.message };
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
const chunkResults = await Promise.all(chunkPromises);
|
|
154
|
-
|
|
155
|
-
// Log results for this chunk
|
|
156
|
-
chunkResults.forEach(result => {
|
|
157
|
-
if (result.success) {
|
|
158
|
-
console.log(`✅ Successfully processed profile image for member ${result.memberId}`);
|
|
159
|
-
} else {
|
|
160
|
-
console.error(
|
|
161
|
-
`❌ Failed to process profile image for member ${result.memberId}: ${result.error}`
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Add small delay between chunks to avoid overwhelming the media manager
|
|
167
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return result;
|
|
171
|
-
};
|
|
172
|
-
const updateSiteMapS3 = async () => {
|
|
173
|
-
const relevantMembers = await getMembersWithWixUrl();
|
|
174
|
-
console.log('number of profiles to upload', relevantMembers.length);
|
|
175
|
-
const [tokens, siteAssociation] = await Promise.all([
|
|
176
|
-
getAWSTokens(),
|
|
177
|
-
getSiteConfigs(CONFIG_KEYS.SITE_ASSOCIATION),
|
|
178
|
-
]);
|
|
179
|
-
// const creds = await getNewStsSessionToken(tokens.AWS_ACCESS_KEY_ID, tokens.AWS_SECRET_ACCESS_KEY, 3600);
|
|
180
|
-
// console.log("creds",creds); // verify it’s fresh
|
|
181
|
-
try {
|
|
182
|
-
const chunkSize = 10000;
|
|
183
|
-
console.log('Total items will be split into', relevantMembers.length / chunkSize);
|
|
184
|
-
const chunks = chunkArray(relevantMembers, chunkSize);
|
|
185
|
-
console.log(`Uploading ${chunks.length} sitemap files...`);
|
|
186
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
187
|
-
const index = i + 1;
|
|
188
|
-
const fileName = `profiles-sitemap-${index}.xml`;
|
|
189
|
-
console.log(
|
|
190
|
-
`Uploading chunk ${index}/${chunks.length} -> ${fileName} (${chunks[i].length} items)`
|
|
191
|
-
);
|
|
192
|
-
await uploadMembersSitemap({
|
|
193
|
-
members: chunks[i],
|
|
194
|
-
tokens,
|
|
195
|
-
destinationFileName: fileName,
|
|
196
|
-
siteAssociation,
|
|
197
|
-
});
|
|
198
|
-
console.log(`Uploaded ${fileName}`);
|
|
199
|
-
}
|
|
200
|
-
console.log('All sitemap files uploaded successfully');
|
|
201
|
-
} catch (e) {
|
|
202
|
-
console.error('Sitemap upload failed:', e?.message || e);
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Schedules tasks to migrate contactFormEmail for all members who don't have it set
|
|
208
|
-
* This function gets all members missing contactFormEmail and schedules batch processing tasks
|
|
209
|
-
*/
|
|
210
|
-
const scheduleContactFormEmailMigration = async () => {
|
|
211
|
-
try {
|
|
212
|
-
console.log('Starting to schedule contactFormEmail migration tasks');
|
|
213
|
-
const createContactFormEmailMigrationTask = (members, chunkIndex) => {
|
|
214
|
-
const memberIds = members.map(member => member._id);
|
|
215
|
-
return {
|
|
216
|
-
name: TASKS_NAMES.migrateContactFormEmails,
|
|
217
|
-
data: { memberIds, chunkIndex },
|
|
218
|
-
type: 'scheduled',
|
|
219
|
-
};
|
|
220
|
-
};
|
|
221
|
-
const membersToMigrate = await getAllMembersWithoutContactFormEmail();
|
|
222
|
-
console.log(`Found ${membersToMigrate.length} members needing contactFormEmail migration`);
|
|
223
|
-
if (membersToMigrate.length === 0) {
|
|
224
|
-
console.log('No members need contactFormEmail migration');
|
|
225
|
-
return {
|
|
226
|
-
success: true,
|
|
227
|
-
message: 'No members need migration',
|
|
228
|
-
totalMembers: 0,
|
|
229
|
-
tasksScheduled: 0,
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Process in chunks of 500 members per task (smaller chunks for reliability)
|
|
234
|
-
const membersChunks = chunkArray(membersToMigrate, 500);
|
|
235
|
-
console.log(`Creating ${membersChunks.length} migration tasks`);
|
|
236
|
-
|
|
237
|
-
for (let chunkIndex = 0; chunkIndex < membersChunks.length; chunkIndex++) {
|
|
238
|
-
const chunk = membersChunks[chunkIndex];
|
|
239
|
-
const migrationTask = createContactFormEmailMigrationTask(chunk, chunkIndex);
|
|
240
|
-
await taskManager().schedule(migrationTask);
|
|
241
|
-
console.log(`Scheduled task for chunk ${chunkIndex} with ${chunk.length} members`);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
console.log(
|
|
245
|
-
`Successfully scheduled ${membersChunks.length} tasks for ${membersToMigrate.length} members`
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
return {
|
|
249
|
-
success: true,
|
|
250
|
-
message: `Scheduled ${membersChunks.length} tasks for ${membersToMigrate.length} members`,
|
|
251
|
-
totalMembers: membersToMigrate.length,
|
|
252
|
-
tasksScheduled: membersChunks.length,
|
|
253
|
-
};
|
|
254
|
-
} catch (error) {
|
|
255
|
-
const errorMessage = `Failed to schedule contactFormEmail migration: ${error.message}`;
|
|
256
|
-
console.error(errorMessage);
|
|
257
|
-
throw new Error(errorMessage);
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Migrates contactFormEmail for a batch of members
|
|
263
|
-
* Sets contactFormEmail to the same value as the member's current email
|
|
264
|
-
* @param {Object} data - Data object with memberIds and chunkIndex
|
|
265
|
-
* @param {Array} data.memberIds - Array of member IDs to process
|
|
266
|
-
* @param {number} data.chunkIndex - Index of the chunk
|
|
267
|
-
* @returns {Promise<Object>} - Result object with success/failure counts
|
|
268
|
-
*/
|
|
269
|
-
const migrateContactFormEmails = async data => {
|
|
270
|
-
const { memberIds, chunkIndex } = data;
|
|
271
|
-
const result = {
|
|
272
|
-
successful: 0,
|
|
273
|
-
failed: 0,
|
|
274
|
-
errors: [],
|
|
275
|
-
skipped: 0,
|
|
276
|
-
skippedIds: [],
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
console.log(
|
|
280
|
-
`Starting contactFormEmail migration for ${memberIds.length} members in chunk ${chunkIndex}`
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
try {
|
|
284
|
-
// Get all members for this batch
|
|
285
|
-
const memberPromises = memberIds.map(async memberId => {
|
|
286
|
-
try {
|
|
287
|
-
const member = await findMemberByWixDataId(memberId);
|
|
288
|
-
|
|
289
|
-
// Skip if member already has contactFormEmail set
|
|
290
|
-
if (member.contactFormEmail) {
|
|
291
|
-
console.log(`Member ${memberId} already has contactFormEmail set`);
|
|
292
|
-
result.skipped++;
|
|
293
|
-
result.skippedIds.push(memberId);
|
|
294
|
-
return null;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Skip if member doesn't have email
|
|
298
|
-
if (!member.email) {
|
|
299
|
-
console.log(`Member ${memberId} doesn't have email - skipping`);
|
|
300
|
-
result.skipped++;
|
|
301
|
-
result.skippedIds.push(memberId);
|
|
302
|
-
return null;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
return {
|
|
306
|
-
...member,
|
|
307
|
-
contactFormEmail: member.email,
|
|
308
|
-
};
|
|
309
|
-
} catch (error) {
|
|
310
|
-
console.error(`Error preparing member ${memberId}:`, error);
|
|
311
|
-
result.failed++;
|
|
312
|
-
result.errors.push({ memberId, error: error.message });
|
|
313
|
-
return null;
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
const membersToUpdate = (await Promise.all(memberPromises)).filter(Boolean);
|
|
318
|
-
|
|
319
|
-
if (membersToUpdate.length === 0) {
|
|
320
|
-
console.log('No members need updating in this batch');
|
|
321
|
-
return result;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
console.log(
|
|
325
|
-
`Started Updating ${membersToUpdate.length} members with contactFormEmail in chunk ${chunkIndex}`
|
|
326
|
-
);
|
|
327
|
-
|
|
328
|
-
// Process in smaller chunks for bulk update (1000 is Wix limit)
|
|
329
|
-
const updateChunks = chunkArray(membersToUpdate, 1000);
|
|
330
|
-
|
|
331
|
-
for (let chunkIndex = 0; chunkIndex < updateChunks.length; chunkIndex++) {
|
|
332
|
-
const chunk = updateChunks[chunkIndex];
|
|
333
|
-
try {
|
|
334
|
-
await bulkSaveMembers(chunk);
|
|
335
|
-
result.successful += chunk.length;
|
|
336
|
-
console.log(`✅ Successfully updated ${chunk.length} members in chunk ${chunkIndex}`);
|
|
337
|
-
} catch (error) {
|
|
338
|
-
console.error(`❌ Error updating chunk ${chunkIndex}:`, error);
|
|
339
|
-
result.failed += chunk.length;
|
|
340
|
-
result.errors.push({
|
|
341
|
-
chunk: chunkIndex,
|
|
342
|
-
error: error.message,
|
|
343
|
-
memberCount: chunk.length,
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
} catch (error) {
|
|
348
|
-
const errorMessage = `Failed to migrate contactFormEmail for chunk ${chunkIndex}: ${error.message}`;
|
|
349
|
-
console.error(errorMessage);
|
|
350
|
-
throw new Error(errorMessage);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
console.log(
|
|
354
|
-
`ContactFormEmail migration task completed: ${result.successful} successful, ${result.failed} failed, ${result.skipped} skipped, in chunk ${chunkIndex}`
|
|
355
|
-
);
|
|
356
|
-
return result;
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
Schedules tasks to sync updated emails from the updated login emails database
|
|
361
|
-
* This function gets all updated emails and schedules batch processing tasks
|
|
362
|
-
*/
|
|
363
|
-
const scheduleEmailSync = async () => {
|
|
364
|
-
try {
|
|
365
|
-
console.log('Starting to schedule email sync tasks');
|
|
366
|
-
const createEmailSyncTask = (chunk, chunkIndex) => {
|
|
367
|
-
//To reduce stored Items size inside task data
|
|
368
|
-
const emailUpdates = chunk.map(emailUpdate => ({
|
|
369
|
-
memberId: emailUpdate.memberId,
|
|
370
|
-
loginEmail: emailUpdate.loginEmail,
|
|
371
|
-
}));
|
|
372
|
-
return {
|
|
373
|
-
name: TASKS_NAMES.syncMemberLoginEmails,
|
|
374
|
-
data: { emailUpdates, chunkIndex },
|
|
375
|
-
type: 'scheduled',
|
|
376
|
-
};
|
|
377
|
-
};
|
|
378
|
-
const updatedEmails = await getAllUpdatedLoginEmails();
|
|
379
|
-
console.log(`Found ${updatedEmails.length} updated email records`);
|
|
380
|
-
|
|
381
|
-
if (updatedEmails.length === 0) {
|
|
382
|
-
console.log('No updated emails found');
|
|
383
|
-
return {
|
|
384
|
-
success: true,
|
|
385
|
-
message: 'No updated emails to sync',
|
|
386
|
-
totalEmails: 0,
|
|
387
|
-
tasksScheduled: 0,
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
const emailChunks = chunkArray(updatedEmails, 500);
|
|
392
|
-
console.log(`Creating ${emailChunks.length} email sync tasks`);
|
|
393
|
-
|
|
394
|
-
for (let chunkIndex = 0; chunkIndex < emailChunks.length; chunkIndex++) {
|
|
395
|
-
const chunk = emailChunks[chunkIndex];
|
|
396
|
-
const syncTask = createEmailSyncTask(chunk, chunkIndex);
|
|
397
|
-
await taskManager().schedule(syncTask);
|
|
398
|
-
console.log(`Scheduled task for chunk ${chunkIndex} with ${chunk.length} email updates`);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
console.log(
|
|
402
|
-
`Successfully scheduled ${emailChunks.length} tasks for ${updatedEmails.length} email updates`
|
|
403
|
-
);
|
|
404
|
-
|
|
405
|
-
return {
|
|
406
|
-
success: true,
|
|
407
|
-
message: `Scheduled ${emailChunks.length} tasks for ${updatedEmails.length} email updates`,
|
|
408
|
-
totalEmails: updatedEmails.length,
|
|
409
|
-
tasksScheduled: emailChunks.length,
|
|
410
|
-
};
|
|
411
|
-
} catch (error) {
|
|
412
|
-
const errorMessage = `Failed to schedule email sync: ${error.message}`;
|
|
413
|
-
console.error(errorMessage);
|
|
414
|
-
throw new Error(errorMessage);
|
|
415
|
-
}
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* Syncs member emails with updated login emails
|
|
420
|
-
* @param {Object} data - Data object with emailUpdates and chunkIndex
|
|
421
|
-
* @param {Array} data.emailUpdates - Array of email update objects with memberId and loginEmail
|
|
422
|
-
* @param {number} data.chunkIndex - Index of the chunk
|
|
423
|
-
* @returns {Object} - Result object with success/failure counts
|
|
424
|
-
*/
|
|
425
|
-
const syncMemberLoginEmails = async data => {
|
|
426
|
-
const { emailUpdates, chunkIndex } = data;
|
|
427
|
-
const result = {
|
|
428
|
-
successful: 0,
|
|
429
|
-
failed: 0,
|
|
430
|
-
skipped: 0,
|
|
431
|
-
skippedIds: [],
|
|
432
|
-
missingMemberIds: [],
|
|
433
|
-
errors: [],
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
console.log(
|
|
437
|
-
`Starting email sync for ${emailUpdates.length} email updates in chunk ${chunkIndex}`
|
|
438
|
-
);
|
|
439
|
-
|
|
440
|
-
try {
|
|
441
|
-
const memberIds = emailUpdates.map(update => update.memberId);
|
|
442
|
-
|
|
443
|
-
const existingMembers = await getMembersByIds(memberIds);
|
|
444
|
-
console.log(`Found ${existingMembers.length} existing members to update`);
|
|
445
|
-
const existingMemberIds = new Set(existingMembers.map(member => member.memberId));
|
|
446
|
-
const missingMemberIds = memberIds.filter(memberId => !existingMemberIds.has(memberId));
|
|
447
|
-
|
|
448
|
-
// Add missing member IDs to skipped count and log them
|
|
449
|
-
if (missingMemberIds.length > 0) {
|
|
450
|
-
console.log(
|
|
451
|
-
`Found ${missingMemberIds.length} members in emailUpdates but not in database:`,
|
|
452
|
-
missingMemberIds
|
|
453
|
-
);
|
|
454
|
-
result.missingMemberIds = result.missingMemberIds || [];
|
|
455
|
-
result.missingMemberIds.push(...missingMemberIds);
|
|
456
|
-
}
|
|
457
|
-
const emailUpdateMap = new Map();
|
|
458
|
-
emailUpdates.forEach(update => {
|
|
459
|
-
emailUpdateMap.set(update.memberId, update.loginEmail);
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
const membersToUpdate = [];
|
|
463
|
-
|
|
464
|
-
for (const member of existingMembers) {
|
|
465
|
-
const newEmail = emailUpdateMap.get(member.memberId);
|
|
466
|
-
|
|
467
|
-
if (!newEmail) {
|
|
468
|
-
console.log(`No email update found for member ${member.memberId}`);
|
|
469
|
-
result.skipped++;
|
|
470
|
-
result.skippedIds.push(member.memberId);
|
|
471
|
-
continue;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if (member.email === newEmail) {
|
|
475
|
-
console.log(`Email already up to date for member ${member.memberId}`);
|
|
476
|
-
result.skipped++;
|
|
477
|
-
result.skippedIds.push(member.memberId);
|
|
478
|
-
continue;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
membersToUpdate.push({
|
|
482
|
-
...member,
|
|
483
|
-
email: newEmail,
|
|
484
|
-
previousLoginEmail: member.email,
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
if (membersToUpdate.length === 0) {
|
|
489
|
-
console.log('No members need email updates in this batch', chunkIndex);
|
|
490
|
-
return result;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
console.log(
|
|
494
|
-
`Updating ${membersToUpdate.length} members with new emails in chunk ${chunkIndex}`
|
|
495
|
-
);
|
|
496
|
-
|
|
497
|
-
const updateChunks = chunkArray(membersToUpdate, 1000);
|
|
498
|
-
|
|
499
|
-
for (const chunk of updateChunks) {
|
|
500
|
-
try {
|
|
501
|
-
// Change Wix login emails first; only advance the CMS login email for the ones that
|
|
502
|
-
// succeeded. Failures keep their previous email (CMS stays consistent with Wix) and are
|
|
503
|
-
// reported in result.errors for manual handling.
|
|
504
|
-
const outcomes = await changeWixMembersEmails(chunk);
|
|
505
|
-
const { failedMemberIds } = summarizeLoginEmailOutcomes(outcomes);
|
|
506
|
-
const toSave = chunk.map(member => {
|
|
507
|
-
const { previousLoginEmail, ...restMember } = member;
|
|
508
|
-
if (failedMemberIds.has(member.memberId) && previousLoginEmail !== undefined) {
|
|
509
|
-
return { ...restMember, email: previousLoginEmail };
|
|
510
|
-
}
|
|
511
|
-
return restMember;
|
|
512
|
-
});
|
|
513
|
-
await bulkSaveMembers(toSave);
|
|
514
|
-
|
|
515
|
-
outcomes.forEach(outcome => {
|
|
516
|
-
if (outcome.status === LOGIN_EMAIL_SYNC_STATUS.UPDATED) {
|
|
517
|
-
result.successful++;
|
|
518
|
-
} else if (outcome.status === LOGIN_EMAIL_SYNC_STATUS.FAILED) {
|
|
519
|
-
result.failed++;
|
|
520
|
-
result.errors.push({
|
|
521
|
-
memberId: outcome.memberId,
|
|
522
|
-
wixMemberId: outcome.wixMemberId,
|
|
523
|
-
desiredEmail: outcome.desiredEmail,
|
|
524
|
-
error: outcome.error,
|
|
525
|
-
});
|
|
526
|
-
} else {
|
|
527
|
-
result.skipped++;
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
} catch (error) {
|
|
531
|
-
console.error(`❌ Error updating chunk ${chunkIndex}:`, error);
|
|
532
|
-
result.failed += chunk.length;
|
|
533
|
-
result.errors.push({
|
|
534
|
-
chunk: chunkIndex,
|
|
535
|
-
error: error.message,
|
|
536
|
-
memberCount: chunk.length,
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
console.log(
|
|
541
|
-
`Login Emails sync task completed: ${result.successful} synced, ${result.failed} failed, ${result.skipped} skipped`
|
|
542
|
-
);
|
|
543
|
-
|
|
544
|
-
return result;
|
|
545
|
-
} catch (error) {
|
|
546
|
-
const errorMessage = `Failed to syncMemberLoginEmails for chunk ${chunkIndex} of length ${emailUpdates.length} with error: ${error.message}`;
|
|
547
|
-
console.error(errorMessage);
|
|
548
|
-
throw new Error(errorMessage);
|
|
549
|
-
}
|
|
550
|
-
};
|
|
551
|
-
/**
|
|
552
|
-
* Schedules tasks to create contacts from members
|
|
553
|
-
* dev-only task, run only once by the developers
|
|
554
|
-
*/
|
|
555
|
-
const scheduleCreateContactsFromMembers = async () => {
|
|
556
|
-
const members = await getAllMembersWithWixMemberId();
|
|
557
|
-
console.log(
|
|
558
|
-
`Starting to schedule create contacts from members tasks for ${members.length} members in chunks of 500 members`
|
|
559
|
-
);
|
|
560
|
-
const membersChunks = chunkArray(members, 500);
|
|
561
|
-
for (let chunkIndex = 0; chunkIndex < membersChunks.length; chunkIndex++) {
|
|
562
|
-
const chunk = membersChunks[chunkIndex];
|
|
563
|
-
const toScheduleTask = {
|
|
564
|
-
name: TASKS_NAMES.createContactsFromMembers,
|
|
565
|
-
data: { chunk, chunkIndex },
|
|
566
|
-
type: 'scheduled',
|
|
567
|
-
};
|
|
568
|
-
await taskManager().schedule(toScheduleTask);
|
|
569
|
-
console.log(`Scheduled task for chunk ${chunkIndex} with ${chunk.length} members`);
|
|
570
|
-
}
|
|
571
|
-
console.log(`Successfully scheduled ${membersChunks.length} tasks for ${members.length} members`);
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
/**
|
|
575
|
-
* Creates contacts from members
|
|
576
|
-
* dev-only task, run only once by the developers
|
|
577
|
-
*/
|
|
578
|
-
const createContactsFromMembers = async data => {
|
|
579
|
-
const { chunk, chunkIndex } = data;
|
|
580
|
-
console.log(`Creating contacts from ${chunk.length} members in chunk ${chunkIndex}`);
|
|
581
|
-
const createPromises = chunk.map(member => createContactAndMemberIfNew(member, true));
|
|
582
|
-
const createResults = await Promise.all(createPromises);
|
|
583
|
-
console.log(
|
|
584
|
-
`Created ${createResults.length} contacts from ${chunk.length} members in chunk ${chunkIndex}`
|
|
585
|
-
);
|
|
586
|
-
const saveResult = await bulkSaveMembers(createResults);
|
|
587
|
-
console.log(
|
|
588
|
-
`Successfully saved ${saveResult.totalSaved} contacts from ${chunk.length} members in chunk ${chunkIndex}`
|
|
589
|
-
);
|
|
590
|
-
return saveResult;
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
module.exports = {
|
|
594
|
-
scheduleTaskForEmptyAboutYouMembers,
|
|
595
|
-
convertAboutYouHtmlToRichContent,
|
|
596
|
-
compileFiltersOptions,
|
|
597
|
-
scheduleTaskForExternalProfileImages,
|
|
598
|
-
convertExternalProfilesToWixImages,
|
|
599
|
-
updateSiteMapS3,
|
|
600
|
-
scheduleContactFormEmailMigration,
|
|
601
|
-
migrateContactFormEmails,
|
|
602
|
-
scheduleEmailSync,
|
|
603
|
-
syncMemberLoginEmails,
|
|
604
|
-
scheduleCreateContactsFromMembers, // run only once by the developers
|
|
605
|
-
createContactsFromMembers,
|
|
606
|
-
};
|