abmp-npm 2.0.77 → 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.
Files changed (99) hide show
  1. package/package.json +8 -1
  2. package/.claude/skills/wix-data-query/SKILL.md +0 -167
  3. package/.claude/skills/wix-data-query/references/backup-archive.md +0 -136
  4. package/.claude/skills/wix-data-query/references/members-data-latest.md +0 -125
  5. package/.claude/skills/wix-data-query/references/recipes.md +0 -264
  6. package/.claude/worktrees/fix-save-button-disable/.husky/pre-commit +0 -19
  7. package/.claude/worktrees/fix-save-button-disable/.prettierignore +0 -7
  8. package/.claude/worktrees/fix-save-button-disable/.prettierrc.json +0 -16
  9. package/.claude/worktrees/fix-save-button-disable/README.md +0 -1
  10. package/.claude/worktrees/fix-save-button-disable/backend/README-member-contact-flows.md +0 -136
  11. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/daily-pull-execution-check.test.js +0 -124
  12. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/ensure-unique-urls-in-batch.test.js +0 -129
  13. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/login-email-sync.test.js +0 -49
  14. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/transient-retry-and-bulk-lookup.test.js +0 -129
  15. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/url-uniqueness.test.js +0 -194
  16. package/.claude/worktrees/fix-save-button-disable/backend/automations-methods.js +0 -13
  17. package/.claude/worktrees/fix-save-button-disable/backend/cms-data-methods.js +0 -251
  18. package/.claude/worktrees/fix-save-button-disable/backend/consts.js +0 -58
  19. package/.claude/worktrees/fix-save-button-disable/backend/contacts-methods.js +0 -67
  20. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/bulk-process-methods.js +0 -222
  21. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/consts.js +0 -39
  22. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/index.js +0 -5
  23. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/process-member-methods.js +0 -213
  24. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/schedule-methods.js +0 -41
  25. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/sync-to-cms-methods.js +0 -161
  26. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/utils.js +0 -151
  27. package/.claude/worktrees/fix-save-button-disable/backend/data-hooks.js +0 -29
  28. package/.claude/worktrees/fix-save-button-disable/backend/dev-only-methods.js +0 -58
  29. package/.claude/worktrees/fix-save-button-disable/backend/elevated-modules.js +0 -18
  30. package/.claude/worktrees/fix-save-button-disable/backend/forms-methods.js +0 -52
  31. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/httpFunctions.js +0 -86
  32. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/index.js +0 -3
  33. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/interests.js +0 -35
  34. package/.claude/worktrees/fix-save-button-disable/backend/index.js +0 -19
  35. package/.claude/worktrees/fix-save-button-disable/backend/jobs.js +0 -158
  36. package/.claude/worktrees/fix-save-button-disable/backend/login/generate-member-session-token.js +0 -27
  37. package/.claude/worktrees/fix-save-button-disable/backend/login/index.js +0 -8
  38. package/.claude/worktrees/fix-save-button-disable/backend/login/qa-login-methods.js +0 -54
  39. package/.claude/worktrees/fix-save-button-disable/backend/login/sso-methods.js +0 -159
  40. package/.claude/worktrees/fix-save-button-disable/backend/member-contact-orchestration.js +0 -111
  41. package/.claude/worktrees/fix-save-button-disable/backend/members-area-methods.js +0 -88
  42. package/.claude/worktrees/fix-save-button-disable/backend/members-data-methods.js +0 -789
  43. package/.claude/worktrees/fix-save-button-disable/backend/pac-api-methods.js +0 -54
  44. package/.claude/worktrees/fix-save-button-disable/backend/routers/index.js +0 -3
  45. package/.claude/worktrees/fix-save-button-disable/backend/routers/methods.js +0 -191
  46. package/.claude/worktrees/fix-save-button-disable/backend/routers/utils.js +0 -128
  47. package/.claude/worktrees/fix-save-button-disable/backend/search-filters-methods.js +0 -124
  48. package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-primary-methods.js +0 -256
  49. package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-visibility-methods.js +0 -160
  50. package/.claude/worktrees/fix-save-button-disable/backend/tasks/consts.js +0 -34
  51. package/.claude/worktrees/fix-save-button-disable/backend/tasks/daily-pull-check-methods.js +0 -78
  52. package/.claude/worktrees/fix-save-button-disable/backend/tasks/email-normalize-methods.js +0 -134
  53. package/.claude/worktrees/fix-save-button-disable/backend/tasks/index.js +0 -10
  54. package/.claude/worktrees/fix-save-button-disable/backend/tasks/migration-methods.js +0 -46
  55. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-configs.js +0 -251
  56. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-helpers-methods.js +0 -433
  57. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-process-methods.js +0 -606
  58. package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-migration-methods.js +0 -378
  59. package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-space-fix-methods.js +0 -174
  60. package/.claude/worktrees/fix-save-button-disable/backend/utils.js +0 -277
  61. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/extract-duplicate-url-groups.js +0 -201
  62. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-ids.js +0 -159
  63. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-urls.js +0 -201
  64. package/.claude/worktrees/fix-save-button-disable/eslint.config.js +0 -120
  65. package/.claude/worktrees/fix-save-button-disable/index.js +0 -5
  66. package/.claude/worktrees/fix-save-button-disable/package-lock.json +0 -12160
  67. package/.claude/worktrees/fix-save-button-disable/package.json +0 -60
  68. package/.claude/worktrees/fix-save-button-disable/pages/ContactUs.js +0 -129
  69. package/.claude/worktrees/fix-save-button-disable/pages/Home.js +0 -779
  70. package/.claude/worktrees/fix-save-button-disable/pages/LearnMore.js +0 -27
  71. package/.claude/worktrees/fix-save-button-disable/pages/LoadingPage.js +0 -29
  72. package/.claude/worktrees/fix-save-button-disable/pages/Profile.js +0 -354
  73. package/.claude/worktrees/fix-save-button-disable/pages/QAPage.js +0 -39
  74. package/.claude/worktrees/fix-save-button-disable/pages/SaveAlerts.js +0 -13
  75. package/.claude/worktrees/fix-save-button-disable/pages/SelectBannerImages.js +0 -46
  76. package/.claude/worktrees/fix-save-button-disable/pages/deleteConfirm.js +0 -19
  77. package/.claude/worktrees/fix-save-button-disable/pages/index.js +0 -12
  78. package/.claude/worktrees/fix-save-button-disable/pages/personalDetails.js +0 -2486
  79. package/.claude/worktrees/fix-save-button-disable/public/Utils/homePage.js +0 -798
  80. package/.claude/worktrees/fix-save-button-disable/public/Utils/personalDetailsUtils.js +0 -25
  81. package/.claude/worktrees/fix-save-button-disable/public/Utils/sharedUtils.js +0 -235
  82. package/.claude/worktrees/fix-save-button-disable/public/consts.js +0 -113
  83. package/.claude/worktrees/fix-save-button-disable/public/index.js +0 -5
  84. package/.claude/worktrees/fix-save-button-disable/public/messages.js +0 -16
  85. package/.claude/worktrees/fix-save-button-disable/public/sso-auth-methods.js +0 -43
  86. package/.husky/pre-commit +0 -19
  87. package/.prettierignore +0 -7
  88. package/.prettierrc.json +0 -16
  89. package/backend/__tests__/daily-pull-execution-check.test.js +0 -124
  90. package/backend/__tests__/ensure-unique-urls-in-batch.test.js +0 -129
  91. package/backend/__tests__/login-email-sync.test.js +0 -49
  92. package/backend/__tests__/map-link.test.js +0 -115
  93. package/backend/__tests__/transient-retry-and-bulk-lookup.test.js +0 -129
  94. package/backend/__tests__/url-uniqueness.test.js +0 -194
  95. package/backend/__tests__/url-validation.test.js +0 -69
  96. package/dev-only-scripts/extract-duplicate-url-groups.js +0 -201
  97. package/dev-only-scripts/find-duplicate-ids.js +0 -159
  98. package/dev-only-scripts/find-duplicate-urls.js +0 -201
  99. package/eslint.config.js +0 -120
@@ -1,256 +0,0 @@
1
- const { taskManager } = require('psdev-task-manager');
2
-
3
- const { COLLECTIONS } = require('../../public/consts');
4
- const { wixData } = require('../elevated-modules');
5
- const { bulkSaveMembers, getMembersByIds } = require('../members-data-methods');
6
- const { chunkArray, queryAllItems } = require('../utils');
7
-
8
- const { TASKS_NAMES } = require('./consts');
9
-
10
- const CHUNK_SIZE = 1000;
11
-
12
- const getAddressKey = (address, index) =>
13
- address?.key || address?.addressid || address?.addressId || `address_${index}`;
14
-
15
- const hasPrimaryAddress = addressDisplayOption =>
16
- Array.isArray(addressDisplayOption) &&
17
- addressDisplayOption.some(option => option?.isMain === true);
18
-
19
- /**
20
- * Schedules tasks to fix members with multiple addresses and no primary address.
21
- */
22
- async function scheduleFixPrimaryAddressForMembers() {
23
- console.log('=== Scheduling Fix Primary Address Tasks ===');
24
-
25
- try {
26
- const membersQuery = await wixData
27
- .query(COLLECTIONS.MEMBERS_DATA)
28
- .isNotEmpty('addresses')
29
- .limit(1000);
30
- const members = await queryAllItems(membersQuery);
31
- console.log(`Fetched ${members.length} members with addresses`);
32
-
33
- const membersToFix = members.filter(member => {
34
- const addresses = Array.isArray(member.addresses) ? member.addresses : [];
35
- if (addresses.length === 0) {
36
- return false;
37
- }
38
- return !hasPrimaryAddress(member.addressDisplayOption);
39
- });
40
-
41
- const memberIds = [
42
- ...new Set(
43
- membersToFix
44
- .map(member => Number(member.memberId))
45
- .filter(memberId => Number.isFinite(memberId) && memberId > 0)
46
- ),
47
- ];
48
- console.log(`Members with addresses and no primary: ${memberIds.length}`);
49
-
50
- if (memberIds.length === 0) {
51
- console.log('No members need primary address fixes');
52
- return {
53
- success: true,
54
- message: 'No members need primary address fixes',
55
- totalMembers: 0,
56
- tasksScheduled: 0,
57
- };
58
- }
59
-
60
- const chunks = chunkArray(memberIds, CHUNK_SIZE);
61
- for (let i = 0; i < chunks.length; i++) {
62
- const chunk = chunks[i];
63
- const task = {
64
- name: TASKS_NAMES.fixPrimaryAddressChunk,
65
- data: {
66
- memberIds: chunk,
67
- chunkIndex: i,
68
- totalChunks: chunks.length,
69
- },
70
- type: 'scheduled',
71
- };
72
- await taskManager().schedule(task);
73
- console.log(`Scheduled task ${i + 1}/${chunks.length} (${chunk.length} members)`);
74
- }
75
-
76
- const result = {
77
- success: true,
78
- message: `Scheduled ${chunks.length} tasks for ${memberIds.length} members`,
79
- totalMembers: memberIds.length,
80
- tasksScheduled: chunks.length,
81
- };
82
-
83
- console.log('=== Scheduling Complete ===');
84
- console.log(`Sample memberIds: ${memberIds.slice(0, 10).join(', ')}`);
85
- console.log(JSON.stringify(result, null, 2));
86
-
87
- return result;
88
- } catch (error) {
89
- console.error('Error scheduling primary address fix:', error);
90
- throw error;
91
- }
92
- }
93
-
94
- /**
95
- * Processes a chunk of members and sets the first address as primary
96
- * when a member has multiple addresses and no primary address.
97
- */
98
- async function fixPrimaryAddressChunk(data) {
99
- const { memberIds, chunkIndex, totalChunks } = data;
100
- console.log(
101
- `Processing primary address fix chunk ${chunkIndex + 1}/${totalChunks} (${memberIds.length} members)`
102
- );
103
-
104
- const result = {
105
- successful: 0,
106
- failed: 0,
107
- skipped: 0,
108
- errors: [],
109
- skippedIds: [],
110
- failedIds: [],
111
- };
112
- const skippedNoAddress = [];
113
- const skippedHasPrimary = [];
114
- const updatedIds = [];
115
-
116
- try {
117
- const members = await getMembersByIds(memberIds);
118
- console.log(`Loaded ${members.length} members for this chunk`);
119
- const membersToUpdate = [];
120
-
121
- members.forEach(member => {
122
- const addresses = Array.isArray(member.addresses) ? member.addresses : [];
123
- if (addresses.length === 0) {
124
- result.skipped++;
125
- result.skippedIds.push(member.memberId);
126
- if (skippedNoAddress.length < 20) {
127
- skippedNoAddress.push(member.memberId);
128
- }
129
- return;
130
- }
131
- if (hasPrimaryAddress(member.addressDisplayOption)) {
132
- result.skipped++;
133
- result.skippedIds.push(member.memberId);
134
- if (skippedHasPrimary.length < 20) {
135
- skippedHasPrimary.push(member.memberId);
136
- }
137
- return;
138
- }
139
-
140
- const firstKey = getAddressKey(addresses[0], 0);
141
- const normalizedAddresses = addresses.map((address, index) => {
142
- if (index !== 0 || address?.key) {
143
- return address;
144
- }
145
- return { ...address, key: firstKey };
146
- });
147
-
148
- const updatedDisplayOptions = Array.isArray(member.addressDisplayOption)
149
- ? member.addressDisplayOption.map(option => ({
150
- ...option,
151
- isMain: false,
152
- }))
153
- : [];
154
-
155
- const existingOption = updatedDisplayOptions.find(option => option?.key === firstKey);
156
- if (existingOption) {
157
- existingOption.isMain = true;
158
- } else {
159
- updatedDisplayOptions.push({ key: firstKey, isMain: true });
160
- }
161
-
162
- membersToUpdate.push({
163
- ...member,
164
- addresses: normalizedAddresses,
165
- addressDisplayOption: updatedDisplayOptions,
166
- });
167
- if (updatedIds.length < 20) {
168
- updatedIds.push(member.memberId);
169
- }
170
- });
171
-
172
- if (membersToUpdate.length === 0) {
173
- console.log('No members need updating in this batch');
174
- return result;
175
- }
176
-
177
- try {
178
- await bulkSaveMembers(membersToUpdate);
179
- result.successful += membersToUpdate.length;
180
- console.log(`✅ Successfully updated ${membersToUpdate.length} members`);
181
- if (updatedIds.length > 0) {
182
- console.log(`Updated memberIds (sample): ${updatedIds.join(', ')}`);
183
- }
184
- } catch (error) {
185
- console.error('❌ Error bulk saving members:', error);
186
- result.failed += membersToUpdate.length;
187
- result.failedIds.push(...membersToUpdate.map(member => member.memberId));
188
- result.errors.push({
189
- error: error.message,
190
- memberCount: membersToUpdate.length,
191
- });
192
- }
193
-
194
- if (skippedNoAddress.length > 0) {
195
- console.log(`Skipped (no addresses) sample: ${skippedNoAddress.join(', ')}`);
196
- }
197
- if (skippedHasPrimary.length > 0) {
198
- console.log(`Skipped (already has primary) sample: ${skippedHasPrimary.join(', ')}`);
199
- }
200
-
201
- return result;
202
- } catch (error) {
203
- console.error(`Error processing primary address fix chunk ${chunkIndex}:`, error);
204
- throw error;
205
- }
206
- }
207
-
208
- /**
209
- * Returns count of members with addresses but no primary address.
210
- */
211
- async function countMembersMissingPrimaryAddress() {
212
- console.log('=== Counting Members Missing Primary Address ===');
213
-
214
- try {
215
- const membersQuery = await wixData
216
- .query(COLLECTIONS.MEMBERS_DATA)
217
- .isNotEmpty('addresses')
218
- .limit(1000);
219
- const members = await queryAllItems(membersQuery);
220
- console.log(`Fetched ${members.length} members with addresses`);
221
-
222
- const membersToFix = members.filter(member => {
223
- const addresses = Array.isArray(member.addresses) ? member.addresses : [];
224
- if (addresses.length === 0) {
225
- return false;
226
- }
227
- return !hasPrimaryAddress(member.addressDisplayOption);
228
- });
229
-
230
- const memberIds = [
231
- ...new Set(
232
- membersToFix
233
- .map(member => Number(member.memberId))
234
- .filter(memberId => Number.isFinite(memberId) && memberId > 0)
235
- ),
236
- ];
237
-
238
- const result = {
239
- success: true,
240
- totalMembers: memberIds.length,
241
- sampleMemberIds: memberIds.slice(0, 20),
242
- };
243
-
244
- console.log(JSON.stringify(result, null, 2));
245
- return result;
246
- } catch (error) {
247
- console.error('Error counting members missing primary address:', error);
248
- throw error;
249
- }
250
- }
251
-
252
- module.exports = {
253
- scheduleFixPrimaryAddressForMembers,
254
- fixPrimaryAddressChunk,
255
- countMembersMissingPrimaryAddress,
256
- };
@@ -1,160 +0,0 @@
1
- const { taskManager } = require('psdev-task-manager');
2
-
3
- const { COLLECTIONS, ADDRESS_STATUS_TYPES } = require('../../public/consts');
4
- const { wixData } = require('../elevated-modules');
5
- const { bulkSaveMembers, getMembersByIds } = require('../members-data-methods');
6
- const { chunkArray, queryAllItems } = require('../utils');
7
-
8
- const { TASKS_NAMES } = require('./consts');
9
-
10
- const CHUNK_SIZE = 1000;
11
-
12
- // Target visibility for every address: show city / state / zip, hide the street address.
13
- const TARGET_STATUS = ADDRESS_STATUS_TYPES.STATE_CITY_ZIP;
14
-
15
- const getMemberAddresses = member => (Array.isArray(member.addresses) ? member.addresses : []);
16
-
17
- /**
18
- * Whether a member has at least one address not already at the target status.
19
- * @param {Object} member
20
- * @returns {boolean}
21
- */
22
- const needsCityStateUpdate = member =>
23
- getMemberAddresses(member).some(address => address && address.addressStatus !== TARGET_STATUS);
24
-
25
- /**
26
- * Sets every address on a member to STATE_CITY_ZIP (other address fields are preserved).
27
- * @param {Object} member
28
- * @returns {Array} the member's addresses with addressStatus set to STATE_CITY_ZIP
29
- */
30
- const setAddressesToCityState = member =>
31
- getMemberAddresses(member).map(address => ({
32
- ...address,
33
- addressStatus: TARGET_STATUS,
34
- }));
35
-
36
- /**
37
- * Schedules tasks to set ALL addresses for ALL members to STATE_CITY_ZIP (show city/state/zip,
38
- * hide the street). Manually triggered (not cron-wired).
39
- */
40
- async function scheduleSetAddressesToCityState() {
41
- console.log('=== Scheduling Set Addresses To City/State Tasks ===');
42
-
43
- try {
44
- const membersQuery = await wixData
45
- .query(COLLECTIONS.MEMBERS_DATA)
46
- .isNotEmpty('addresses')
47
- .limit(1000);
48
- const members = await queryAllItems(membersQuery);
49
- console.log(`Fetched ${members.length} members with addresses`);
50
-
51
- // Only members that still have an address not at the target status need updating.
52
- const memberIds = [
53
- ...new Set(
54
- members
55
- .filter(needsCityStateUpdate)
56
- .map(member => Number(member.memberId))
57
- .filter(memberId => Number.isFinite(memberId) && memberId > 0)
58
- ),
59
- ];
60
- console.log(`Members needing a city/state update: ${memberIds.length}`);
61
-
62
- if (memberIds.length === 0) {
63
- console.log('No members need their addresses set to city/state');
64
- return {
65
- success: true,
66
- message: 'No members need their addresses set to city/state',
67
- totalMembers: 0,
68
- tasksScheduled: 0,
69
- };
70
- }
71
-
72
- const chunks = chunkArray(memberIds, CHUNK_SIZE);
73
- for (let i = 0; i < chunks.length; i++) {
74
- const chunk = chunks[i];
75
- await taskManager().schedule({
76
- name: TASKS_NAMES.setAddressesToCityStateChunk,
77
- data: {
78
- memberIds: chunk,
79
- chunkIndex: i,
80
- totalChunks: chunks.length,
81
- },
82
- type: 'scheduled',
83
- });
84
- console.log(`Scheduled task ${i + 1}/${chunks.length} (${chunk.length} members)`);
85
- }
86
-
87
- const result = {
88
- success: true,
89
- message: `Scheduled ${chunks.length} tasks for ${memberIds.length} members`,
90
- totalMembers: memberIds.length,
91
- tasksScheduled: chunks.length,
92
- };
93
- console.log('=== Scheduling Complete ===');
94
- console.log(JSON.stringify(result, null, 2));
95
- return result;
96
- } catch (error) {
97
- console.error('Error scheduling set-addresses-to-city-state:', error);
98
- throw error;
99
- }
100
- }
101
-
102
- /**
103
- * Processes a chunk of members and sets every address to STATE_CITY_ZIP.
104
- * @param {Object} data
105
- * @param {Array<number|string>} data.memberIds
106
- * @param {number} data.chunkIndex
107
- * @param {number} data.totalChunks
108
- */
109
- async function setAddressesToCityStateChunk(data) {
110
- const { memberIds, chunkIndex, totalChunks } = data;
111
- console.log(
112
- `Processing set-city-state chunk ${chunkIndex + 1}/${totalChunks} (${memberIds.length} members)`
113
- );
114
-
115
- const result = { successful: 0, failed: 0, skipped: 0, errors: [], failedIds: [] };
116
-
117
- try {
118
- const members = await getMembersByIds(memberIds);
119
- console.log(`Loaded ${members.length} members for this chunk`);
120
-
121
- const membersToUpdate = [];
122
- members.forEach(member => {
123
- // Skip members that have no address or are already all at the target status.
124
- if (!needsCityStateUpdate(member)) {
125
- result.skipped++;
126
- return;
127
- }
128
- membersToUpdate.push({
129
- ...member,
130
- addresses: setAddressesToCityState(member),
131
- });
132
- });
133
-
134
- if (membersToUpdate.length === 0) {
135
- console.log('No members need updating in this batch');
136
- return result;
137
- }
138
-
139
- try {
140
- await bulkSaveMembers(membersToUpdate);
141
- result.successful += membersToUpdate.length;
142
- console.log(`✅ Set addresses to city/state for ${membersToUpdate.length} members`);
143
- } catch (error) {
144
- console.error('❌ Error bulk saving members:', error);
145
- result.failed += membersToUpdate.length;
146
- result.failedIds.push(...membersToUpdate.map(member => member.memberId));
147
- result.errors.push({ error: error.message, memberCount: membersToUpdate.length });
148
- }
149
-
150
- return result;
151
- } catch (error) {
152
- console.error(`Error processing set-city-state chunk ${chunkIndex}:`, error);
153
- throw error;
154
- }
155
- }
156
-
157
- module.exports = {
158
- scheduleSetAddressesToCityState,
159
- setAddressesToCityStateChunk,
160
- };
@@ -1,34 +0,0 @@
1
- const TASKS_NAMES = {
2
- ScheduleDailyMembersDataSync: 'ScheduleDailyMembersDataSync',
3
- ScheduleMembersDataPerAction: 'ScheduleMembersDataPerAction',
4
- SyncMembers: 'SyncMembers',
5
- scheduleTaskForEmptyAboutYouMembers: 'scheduleTaskForEmptyAboutYouMembers',
6
- convertHtmlToRichContent: 'convertHtmlToRichContent',
7
- CompileFiltersOptions: 'CompileFiltersOptions',
8
- scheduleTaskForExternalProfileImages: 'scheduleTaskForExternalProfileImages',
9
- convertExternalProfilesToWixImages: 'convertExternalProfilesToWixImages',
10
- updateSiteMapS3: 'updateSiteMapS3',
11
- scheduleEmailSync: 'scheduleEmailSync',
12
- syncMemberLoginEmails: 'syncMemberLoginEmails',
13
- scheduleContactFormEmailMigration: 'scheduleContactFormEmailMigration',
14
- migrateContactFormEmails: 'migrateContactFormEmails',
15
- scheduleMigrateExistingUrls: 'scheduleMigrateExistingUrls',
16
- migrateUrlsChunk: 'migrateUrlsChunk',
17
- scheduleGenerateMissingUrls: 'scheduleGenerateMissingUrls',
18
- generateUrlsChunk: 'generateUrlsChunk',
19
- scheduleCreateContactsFromMembers: 'scheduleCreateContactsFromMembers',
20
- createContactsFromMembers: 'createContactsFromMembers',
21
- scheduleFixPrimaryAddressForMembers: 'scheduleFixPrimaryAddressForMembers',
22
- fixPrimaryAddressChunk: 'fixPrimaryAddressChunk',
23
- scheduleFixUrlsWithSpaces: 'scheduleFixUrlsWithSpaces',
24
- fixUrlsWithSpacesChunk: 'fixUrlsWithSpacesChunk',
25
- scheduleSetAddressesToCityState: 'scheduleSetAddressesToCityState',
26
- setAddressesToCityStateChunk: 'setAddressesToCityStateChunk',
27
- scheduleNormalizeMemberEmails: 'scheduleNormalizeMemberEmails',
28
- normalizeMemberEmailsChunk: 'normalizeMemberEmailsChunk',
29
- dailyPullExecutionCheck: 'dailyPullExecutionCheck',
30
- };
31
-
32
- module.exports = {
33
- TASKS_NAMES,
34
- };
@@ -1,78 +0,0 @@
1
- const { COLLECTIONS } = require('psdev-task-manager/public/consts');
2
-
3
- const { scheduleDailyPullTasks } = require('../daily-pull/schedule-methods');
4
- const { wixData } = require('../elevated-modules');
5
- const { queryAllItems } = require('../utils');
6
-
7
- const { TASKS_NAMES } = require('./consts');
8
-
9
- const DEFAULT_HOURS_BACK = 4;
10
-
11
- // The cron path (scheduleDailyPullTask) creates ScheduleMembersDataPerAction tasks
12
- // directly; ScheduleDailyMembersDataSync only exists when the pull is triggered via
13
- // the root task. Either one in the window is evidence the daily pull was scheduled.
14
- const DAILY_PULL_TASK_NAMES = [
15
- TASKS_NAMES.ScheduleMembersDataPerAction,
16
- TASKS_NAMES.ScheduleDailyMembersDataSync,
17
- ];
18
-
19
- /**
20
- * Detects whether the daily pull was scheduled in the lookback window.
21
- * If no daily pull task exists, re-schedules the same per-action tasks the cron
22
- * would have created, propagating the environment flags from the task data so a
23
- * test site's fallback pulls from the test PAC API.
24
- * @param {Object} [taskData]
25
- * @param {number} [taskData.hoursBack=4] - Lookback window in hours
26
- * @param {boolean} [taskData.isTestEnvironment=false] - Pull from the test PAC API on fallback
27
- * @param {boolean} [taskData.includeNone=false] - Include the NONE action on fallback
28
- * @returns {Promise<Object>} - Check result
29
- */
30
- async function dailyPullExecutionCheck(taskData) {
31
- const hoursBack =
32
- taskData?.hoursBack && Number.isFinite(taskData.hoursBack)
33
- ? taskData.hoursBack
34
- : DEFAULT_HOURS_BACK;
35
- const isTestEnvironment = Boolean(taskData?.isTestEnvironment);
36
- const includeNone = Boolean(taskData?.includeNone);
37
- const sinceDate = new Date(Date.now() - hoursBack * 60 * 60 * 1000);
38
-
39
- console.log('dailyPullExecutionCheck started', {
40
- hoursBack,
41
- sinceDate,
42
- isTestEnvironment,
43
- includeNone,
44
- });
45
-
46
- const dailyPullTasksQuery = wixData
47
- .query(COLLECTIONS.TASKS)
48
- .hasSome('name', DAILY_PULL_TASK_NAMES)
49
- .ge('_createdDate', sinceDate);
50
-
51
- const dailyPullTasks = await queryAllItems(dailyPullTasksQuery);
52
- const dailyPullScheduled = dailyPullTasks.length > 0;
53
-
54
- const result = {
55
- success: dailyPullScheduled,
56
- sinceDate: sinceDate.toISOString(),
57
- checkedTaskNames: DAILY_PULL_TASK_NAMES,
58
- dailyPullTasksFound: dailyPullTasks.length,
59
- };
60
-
61
- if (!dailyPullScheduled) {
62
- console.log('No daily pull tasks found in window; re-scheduling per-action pull tasks', {
63
- hoursBack,
64
- isTestEnvironment,
65
- includeNone,
66
- });
67
- await scheduleDailyPullTasks({ isTestEnvironment, includeNone });
68
- result.fallbackScheduled = true;
69
- }
70
-
71
- console.log('dailyPullExecutionCheck result', JSON.stringify(result, null, 2));
72
-
73
- return result;
74
- }
75
-
76
- module.exports = {
77
- dailyPullExecutionCheck,
78
- };
@@ -1,134 +0,0 @@
1
- const { taskManager } = require('psdev-task-manager');
2
-
3
- const {
4
- bulkSaveMembers,
5
- getMembersByIds,
6
- getAllMembersNeedingEmailNormalization,
7
- memberNeedsEmailNormalization,
8
- } = require('../members-data-methods');
9
- const { chunkArray } = require('../utils');
10
-
11
- const { TASKS_NAMES } = require('./consts');
12
-
13
- const CHUNK_SIZE = 1000;
14
-
15
- /**
16
- * One-off backfill: schedules tasks to normalize (lowercase + trim) the email and
17
- * contactFormEmail fields of existing members so stored values match the normalize-on-write
18
- * behavior, keeping case-insensitive uniqueness lookups reliable.
19
- */
20
- async function scheduleNormalizeMemberEmails() {
21
- console.log('=== Scheduling Member Email Normalization ===');
22
-
23
- try {
24
- const members = await getAllMembersNeedingEmailNormalization();
25
- console.log(`Fetched ${members.length} members needing email normalization`);
26
-
27
- const memberIds = [
28
- ...new Set(
29
- members
30
- .map(member => Number(member.memberId))
31
- .filter(memberId => Number.isFinite(memberId) && memberId > 0)
32
- ),
33
- ];
34
- console.log(`Members to normalize: ${memberIds.length}`);
35
-
36
- if (memberIds.length === 0) {
37
- console.log('No members need email normalization');
38
- return {
39
- success: true,
40
- message: 'No members need email normalization',
41
- totalMembers: 0,
42
- tasksScheduled: 0,
43
- };
44
- }
45
-
46
- const chunks = chunkArray(memberIds, CHUNK_SIZE);
47
- for (let i = 0; i < chunks.length; i++) {
48
- const chunk = chunks[i];
49
- const task = {
50
- name: TASKS_NAMES.normalizeMemberEmailsChunk,
51
- data: {
52
- memberIds: chunk,
53
- chunkIndex: i,
54
- totalChunks: chunks.length,
55
- },
56
- type: 'scheduled',
57
- };
58
- await taskManager().schedule(task);
59
- console.log(`Scheduled task ${i + 1}/${chunks.length} (${chunk.length} members)`);
60
- }
61
-
62
- const result = {
63
- success: true,
64
- message: `Scheduled ${chunks.length} tasks for ${memberIds.length} members`,
65
- totalMembers: memberIds.length,
66
- tasksScheduled: chunks.length,
67
- };
68
-
69
- console.log('=== Scheduling Complete ===');
70
- console.log(JSON.stringify(result, null, 2));
71
-
72
- return result;
73
- } catch (error) {
74
- console.error('Error scheduling member email normalization:', error);
75
- throw error;
76
- }
77
- }
78
-
79
- /**
80
- * Processes a chunk of members, normalizing their email fields.
81
- * bulkSaveMembers normalizes on write, so we only need to select the members that still
82
- * have non-canonical values and save them.
83
- */
84
- async function normalizeMemberEmailsChunk(data) {
85
- const { memberIds, chunkIndex, totalChunks } = data;
86
- console.log(
87
- `Processing email normalization chunk ${chunkIndex + 1}/${totalChunks} (${memberIds.length} members)`
88
- );
89
-
90
- const result = {
91
- successful: 0,
92
- failed: 0,
93
- skipped: 0,
94
- errors: [],
95
- failedIds: [],
96
- };
97
-
98
- try {
99
- const members = await getMembersByIds(memberIds);
100
- console.log(`Loaded ${members.length} members for this chunk`);
101
-
102
- const membersToUpdate = members.filter(memberNeedsEmailNormalization);
103
- result.skipped = members.length - membersToUpdate.length;
104
-
105
- if (membersToUpdate.length === 0) {
106
- console.log('No members need updating in this batch');
107
- return result;
108
- }
109
-
110
- try {
111
- await bulkSaveMembers(membersToUpdate);
112
- result.successful += membersToUpdate.length;
113
- console.log(`✅ Successfully normalized ${membersToUpdate.length} members`);
114
- } catch (error) {
115
- console.error('❌ Error bulk saving members:', error);
116
- result.failed += membersToUpdate.length;
117
- result.failedIds.push(...membersToUpdate.map(member => member.memberId));
118
- result.errors.push({
119
- error: error.message,
120
- memberCount: membersToUpdate.length,
121
- });
122
- }
123
-
124
- return result;
125
- } catch (error) {
126
- console.error(`Error processing email normalization chunk ${chunkIndex}:`, error);
127
- throw error;
128
- }
129
- }
130
-
131
- module.exports = {
132
- scheduleNormalizeMemberEmails,
133
- normalizeMemberEmailsChunk,
134
- };
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- ...require('./tasks-configs'),
3
- ...require('./consts'),
4
- ...require('./tasks-process-methods'),
5
- ...require('./migration-methods'),
6
- ...require('./url-migration-methods'),
7
- ...require('./address-primary-methods'),
8
- ...require('./url-space-fix-methods'),
9
- ...require('./daily-pull-check-methods'),
10
- };