abmp-npm 2.0.72 → 2.0.73
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/jobs.js
CHANGED
|
@@ -97,6 +97,24 @@ async function scheduleNormalizeMemberEmailsTask() {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Schedules setting ALL addresses for ALL members that have any address to STATE_CITY_ZIP
|
|
102
|
+
* (show city/state/zip, hide the street). Manually triggered one-off maintenance task.
|
|
103
|
+
*/
|
|
104
|
+
async function scheduleSetAddressesToCityStateTask() {
|
|
105
|
+
try {
|
|
106
|
+
console.log('scheduleSetAddressesToCityState started!');
|
|
107
|
+
return await taskManager().schedule({
|
|
108
|
+
name: TASKS_NAMES.scheduleSetAddressesToCityState,
|
|
109
|
+
data: {},
|
|
110
|
+
type: 'scheduled',
|
|
111
|
+
});
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error(`Failed to scheduleSetAddressesToCityState: ${error.message}`);
|
|
114
|
+
throw new Error(`Failed to scheduleSetAddressesToCityState: ${error.message}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
100
118
|
/**
|
|
101
119
|
* Runs the daily pull execution check (watchdog).
|
|
102
120
|
* @param {Object} [options]
|
|
@@ -135,5 +153,6 @@ module.exports = {
|
|
|
135
153
|
scheduleFixPrimaryAddressForMembersTask,
|
|
136
154
|
scheduleFixUrlsWithSpacesTask,
|
|
137
155
|
scheduleNormalizeMemberEmailsTask,
|
|
156
|
+
scheduleSetAddressesToCityStateTask,
|
|
138
157
|
runDailyPullExecutionCheck,
|
|
139
158
|
};
|
|
@@ -0,0 +1,160 @@
|
|
|
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
|
+
};
|
package/backend/tasks/consts.js
CHANGED
|
@@ -22,6 +22,8 @@ const TASKS_NAMES = {
|
|
|
22
22
|
fixPrimaryAddressChunk: 'fixPrimaryAddressChunk',
|
|
23
23
|
scheduleFixUrlsWithSpaces: 'scheduleFixUrlsWithSpaces',
|
|
24
24
|
fixUrlsWithSpacesChunk: 'fixUrlsWithSpacesChunk',
|
|
25
|
+
scheduleSetAddressesToCityState: 'scheduleSetAddressesToCityState',
|
|
26
|
+
setAddressesToCityStateChunk: 'setAddressesToCityStateChunk',
|
|
25
27
|
scheduleNormalizeMemberEmails: 'scheduleNormalizeMemberEmails',
|
|
26
28
|
normalizeMemberEmailsChunk: 'normalizeMemberEmailsChunk',
|
|
27
29
|
dailyPullExecutionCheck: 'dailyPullExecutionCheck',
|
|
@@ -8,6 +8,10 @@ const {
|
|
|
8
8
|
scheduleFixPrimaryAddressForMembers,
|
|
9
9
|
fixPrimaryAddressChunk,
|
|
10
10
|
} = require('./address-primary-methods');
|
|
11
|
+
const {
|
|
12
|
+
scheduleSetAddressesToCityState,
|
|
13
|
+
setAddressesToCityStateChunk,
|
|
14
|
+
} = require('./address-visibility-methods');
|
|
11
15
|
const { TASKS_NAMES } = require('./consts');
|
|
12
16
|
const { dailyPullExecutionCheck } = require('./daily-pull-check-methods');
|
|
13
17
|
const {
|
|
@@ -207,6 +211,20 @@ const TASKS = {
|
|
|
207
211
|
shouldSkipCheck: () => false,
|
|
208
212
|
estimatedDurationSec: 80,
|
|
209
213
|
},
|
|
214
|
+
[TASKS_NAMES.scheduleSetAddressesToCityState]: {
|
|
215
|
+
name: TASKS_NAMES.scheduleSetAddressesToCityState,
|
|
216
|
+
getIdentifier: () => 'SHOULD_NEVER_SKIP',
|
|
217
|
+
process: scheduleSetAddressesToCityState,
|
|
218
|
+
shouldSkipCheck: () => false,
|
|
219
|
+
estimatedDurationSec: 80,
|
|
220
|
+
},
|
|
221
|
+
[TASKS_NAMES.setAddressesToCityStateChunk]: {
|
|
222
|
+
name: TASKS_NAMES.setAddressesToCityStateChunk,
|
|
223
|
+
getIdentifier: task => task.data,
|
|
224
|
+
process: setAddressesToCityStateChunk,
|
|
225
|
+
shouldSkipCheck: () => false,
|
|
226
|
+
estimatedDurationSec: 80,
|
|
227
|
+
},
|
|
210
228
|
[TASKS_NAMES.scheduleNormalizeMemberEmails]: {
|
|
211
229
|
name: TASKS_NAMES.scheduleNormalizeMemberEmails,
|
|
212
230
|
getIdentifier: () => 'SHOULD_NEVER_SKIP',
|
package/package.json
CHANGED
package/pages/personalDetails.js
CHANGED
|
@@ -975,31 +975,18 @@ async function personalDetailsOnReady({
|
|
|
975
975
|
});
|
|
976
976
|
}
|
|
977
977
|
|
|
978
|
-
async function handleItemDelete(event, getTextSelector, arrayRef, matchField, renderFn) {
|
|
979
|
-
const result = await wixWindow.openLightbox(LIGHTBOX_NAMES.DELETE_CONFIRM);
|
|
980
|
-
|
|
981
|
-
if (result && result.toDelete) {
|
|
982
|
-
const $clickedItem = _$w.at(event.context);
|
|
983
|
-
const textToRemove = $clickedItem(getTextSelector).text;
|
|
984
|
-
|
|
985
|
-
arrayRef.splice(
|
|
986
|
-
0,
|
|
987
|
-
arrayRef.length,
|
|
988
|
-
...arrayRef.filter(item =>
|
|
989
|
-
typeof item === 'string' ? item !== textToRemove : item[matchField] !== textToRemove
|
|
990
|
-
)
|
|
991
|
-
);
|
|
992
|
-
|
|
993
|
-
renderFn();
|
|
994
|
-
checkFormChanges(FORM_SECTION_HANDLER_MAP.BUSINESS_SERVICES);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
978
|
async function setInterestData() {
|
|
999
979
|
const interestsData = await getInterestAll();
|
|
1000
980
|
|
|
1001
|
-
_$w('#removeServiceButton').onClick(event => {
|
|
1002
|
-
|
|
981
|
+
_$w('#removeServiceButton').onClick(async event => {
|
|
982
|
+
const itemId = event.context.itemId;
|
|
983
|
+
const result = await wixWindow.openLightbox(LIGHTBOX_NAMES.DELETE_CONFIRM);
|
|
984
|
+
|
|
985
|
+
if (result && result.toDelete) {
|
|
986
|
+
selectedServices = selectedServices.filter(service => service._id !== itemId);
|
|
987
|
+
renderServices();
|
|
988
|
+
checkFormChanges(FORM_SECTION_HANDLER_MAP.BUSINESS_SERVICES);
|
|
989
|
+
}
|
|
1003
990
|
});
|
|
1004
991
|
|
|
1005
992
|
if (Array.isArray(interestsData) && interestsData.length > 0) {
|
|
@@ -1077,7 +1064,7 @@ async function personalDetailsOnReady({
|
|
|
1077
1064
|
}
|
|
1078
1065
|
|
|
1079
1066
|
function renderServices() {
|
|
1080
|
-
setupRepeater('#servicesRepeater', selectedServices);
|
|
1067
|
+
setupRepeater('#servicesRepeater', [...selectedServices]);
|
|
1081
1068
|
}
|
|
1082
1069
|
|
|
1083
1070
|
function setupRepeater(repeaterId, data) {
|
|
@@ -1339,14 +1326,21 @@ async function personalDetailsOnReady({
|
|
|
1339
1326
|
const addTestimonialButton = _$w('#addTestimonialButton');
|
|
1340
1327
|
|
|
1341
1328
|
addTestimonialButton.onClick(handleAddTestimonial);
|
|
1342
|
-
_$w('#deleteTestimonialButton').onClick(event => {
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1329
|
+
_$w('#deleteTestimonialButton').onClick(async event => {
|
|
1330
|
+
const data = _$w('#testimonialRepeater').data || [];
|
|
1331
|
+
const clickedIndex = data.findIndex(item => item._id === event.context.itemId);
|
|
1332
|
+
const result = await wixWindow.openLightbox(LIGHTBOX_NAMES.DELETE_CONFIRM);
|
|
1333
|
+
|
|
1334
|
+
if (
|
|
1335
|
+
result &&
|
|
1336
|
+
result.toDelete &&
|
|
1337
|
+
clickedIndex > 0 &&
|
|
1338
|
+
Array.isArray(itemMemberObj.testimonial)
|
|
1339
|
+
) {
|
|
1340
|
+
itemMemberObj.testimonial.splice(clickedIndex - 1, 1);
|
|
1341
|
+
renderTestimonials();
|
|
1342
|
+
checkFormChanges(FORM_SECTION_HANDLER_MAP.BUSINESS_SERVICES);
|
|
1343
|
+
}
|
|
1350
1344
|
});
|
|
1351
1345
|
|
|
1352
1346
|
renderTestimonials();
|