abmp-npm 2.0.42 → 2.0.43
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/daily-pull/process-member-methods.js +16 -1
- package/backend/routers/utils.js +1 -6
- package/backend/tasks/address-primary-methods.js +211 -0
- package/backend/tasks/consts.js +2 -0
- package/backend/tasks/index.js +1 -0
- package/backend/tasks/tasks-configs.js +18 -0
- package/package.json +1 -1
- package/pages/personalDetails.js +5 -14
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { ADDRESS_STATUS_TYPES } = require('../../public/consts');
|
|
1
2
|
const { findMemberById, getMemberBySlug } = require('../members-data-methods');
|
|
2
3
|
const { isValidArray, generateGeoHash } = require('../utils');
|
|
3
4
|
|
|
@@ -82,7 +83,21 @@ async function generateUpdatedMemberData({ inputMemberData, currentPageNumber })
|
|
|
82
83
|
|
|
83
84
|
// Only add address data for new members
|
|
84
85
|
if (!existingDbMember && isValidArray(inputMemberData.addresses)) {
|
|
85
|
-
|
|
86
|
+
const normalizedAddresses = inputMemberData.addresses.map((address, index) => {
|
|
87
|
+
const key = address?.key || `address_${index}`;
|
|
88
|
+
const rawStatus = address?.addressStatus;
|
|
89
|
+
const resolvedStatus =
|
|
90
|
+
index === 0 && rawStatus === ADDRESS_STATUS_TYPES.DONT_SHOW
|
|
91
|
+
? ADDRESS_STATUS_TYPES.STATE_CITY_ZIP
|
|
92
|
+
: rawStatus || ADDRESS_STATUS_TYPES.STATE_CITY_ZIP;
|
|
93
|
+
return {
|
|
94
|
+
...address,
|
|
95
|
+
key,
|
|
96
|
+
addressStatus: resolvedStatus,
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
updatedMemberData.addresses = normalizedAddresses;
|
|
100
|
+
updatedMemberData.addressDisplayOption = [{ key: normalizedAddresses[0].key, isMain: true }];
|
|
86
101
|
}
|
|
87
102
|
|
|
88
103
|
return { ...updatedMemberData, isNewToDb: !existingDbMember };
|
package/backend/routers/utils.js
CHANGED
|
@@ -66,11 +66,6 @@ function transformMemberToProfileData(member, siteAssociation) {
|
|
|
66
66
|
numeric: true,
|
|
67
67
|
})
|
|
68
68
|
) || [];
|
|
69
|
-
|
|
70
|
-
const phones = Array.isArray(member.phones) ? member.phones : [];
|
|
71
|
-
const toShowPhone = member.toShowPhone || '';
|
|
72
|
-
const phone = toShowPhone && phones.includes(toShowPhone) ? toShowPhone : '';
|
|
73
|
-
|
|
74
69
|
return {
|
|
75
70
|
mainAddress,
|
|
76
71
|
testimonials: member.testimonial || [],
|
|
@@ -89,7 +84,7 @@ function transformMemberToProfileData(member, siteAssociation) {
|
|
|
89
84
|
bookingUrl: member.bookingUrl,
|
|
90
85
|
aboutService: member.aboutService,
|
|
91
86
|
businessName: (member.showBusinessName && member.businessName) || '',
|
|
92
|
-
phone,
|
|
87
|
+
phone: member.toShowPhone || '',
|
|
93
88
|
areasOfPractices,
|
|
94
89
|
gallery: member.gallery,
|
|
95
90
|
bannerImages: member.bannerImages,
|
|
@@ -0,0 +1,211 @@
|
|
|
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 <= 1) {
|
|
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 multiple 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 skippedNoMultiAddress = [];
|
|
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 <= 1) {
|
|
124
|
+
result.skipped++;
|
|
125
|
+
result.skippedIds.push(member.memberId);
|
|
126
|
+
if (skippedNoMultiAddress.length < 20) {
|
|
127
|
+
skippedNoMultiAddress.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 (skippedNoMultiAddress.length > 0) {
|
|
195
|
+
console.log(`Skipped (<=1 address) sample: ${skippedNoMultiAddress.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
|
+
module.exports = {
|
|
209
|
+
scheduleFixPrimaryAddressForMembers,
|
|
210
|
+
fixPrimaryAddressChunk,
|
|
211
|
+
};
|
package/backend/tasks/consts.js
CHANGED
|
@@ -18,6 +18,8 @@ const TASKS_NAMES = {
|
|
|
18
18
|
generateUrlsChunk: 'generateUrlsChunk',
|
|
19
19
|
scheduleCreateContactsFromMembers: 'scheduleCreateContactsFromMembers',
|
|
20
20
|
createContactsFromMembers: 'createContactsFromMembers',
|
|
21
|
+
scheduleFixPrimaryAddressForMembers: 'scheduleFixPrimaryAddressForMembers',
|
|
22
|
+
fixPrimaryAddressChunk: 'fixPrimaryAddressChunk',
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
module.exports = {
|
package/backend/tasks/index.js
CHANGED
|
@@ -4,6 +4,10 @@ const {
|
|
|
4
4
|
syncMembersDataPerAction,
|
|
5
5
|
} = require('../daily-pull/sync-to-cms-methods');
|
|
6
6
|
|
|
7
|
+
const {
|
|
8
|
+
scheduleFixPrimaryAddressForMembers,
|
|
9
|
+
fixPrimaryAddressChunk,
|
|
10
|
+
} = require('./address-primary-methods');
|
|
7
11
|
const { TASKS_NAMES } = require('./consts');
|
|
8
12
|
const {
|
|
9
13
|
scheduleTaskForEmptyAboutYouMembers,
|
|
@@ -169,6 +173,20 @@ const TASKS = {
|
|
|
169
173
|
shouldSkipCheck: () => false,
|
|
170
174
|
estimatedDurationSec: 80,
|
|
171
175
|
},
|
|
176
|
+
[TASKS_NAMES.scheduleFixPrimaryAddressForMembers]: {
|
|
177
|
+
name: TASKS_NAMES.scheduleFixPrimaryAddressForMembers,
|
|
178
|
+
getIdentifier: () => 'SHOULD_NEVER_SKIP',
|
|
179
|
+
process: scheduleFixPrimaryAddressForMembers,
|
|
180
|
+
shouldSkipCheck: () => false,
|
|
181
|
+
estimatedDurationSec: 80,
|
|
182
|
+
},
|
|
183
|
+
[TASKS_NAMES.fixPrimaryAddressChunk]: {
|
|
184
|
+
name: TASKS_NAMES.fixPrimaryAddressChunk,
|
|
185
|
+
getIdentifier: task => task.data,
|
|
186
|
+
process: fixPrimaryAddressChunk,
|
|
187
|
+
shouldSkipCheck: () => false,
|
|
188
|
+
estimatedDurationSec: 80,
|
|
189
|
+
},
|
|
172
190
|
};
|
|
173
191
|
|
|
174
192
|
module.exports = { TASKS };
|
package/package.json
CHANGED
package/pages/personalDetails.js
CHANGED
|
@@ -2122,19 +2122,16 @@ async function personalDetailsOnReady({
|
|
|
2122
2122
|
const phoneToRemove = currentData.find(item => item._id === phoneId);
|
|
2123
2123
|
|
|
2124
2124
|
if (phoneToRemove) {
|
|
2125
|
+
if (itemMemberObj.toShowPhone === phoneToRemove.phoneNumber) {
|
|
2126
|
+
itemMemberObj.toShowPhone = null;
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2125
2129
|
if (itemMemberObj.phones) {
|
|
2126
2130
|
itemMemberObj.phones = itemMemberObj.phones.filter(
|
|
2127
2131
|
phone => phone !== phoneToRemove.phoneNumber
|
|
2128
2132
|
);
|
|
2129
2133
|
}
|
|
2130
2134
|
|
|
2131
|
-
// Clear toShowPhone if it was the removed phone or if it's no longer in the list
|
|
2132
|
-
// (handles format mismatch e.g. "(406)655-4940" vs "(406) 655-4940")
|
|
2133
|
-
const remainingPhones = Array.isArray(itemMemberObj.phones) ? itemMemberObj.phones : [];
|
|
2134
|
-
if (itemMemberObj.toShowPhone && !remainingPhones.includes(itemMemberObj.toShowPhone)) {
|
|
2135
|
-
itemMemberObj.toShowPhone = null;
|
|
2136
|
-
}
|
|
2137
|
-
|
|
2138
2135
|
const updatedData = currentData.filter(item => item._id !== phoneId);
|
|
2139
2136
|
renderPhonesList(updatedData);
|
|
2140
2137
|
checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
|
|
@@ -2155,13 +2152,7 @@ async function personalDetailsOnReady({
|
|
|
2155
2152
|
}
|
|
2156
2153
|
|
|
2157
2154
|
function getToShowPhone() {
|
|
2158
|
-
|
|
2159
|
-
const toShow = itemMemberObj.toShowPhone || null;
|
|
2160
|
-
// Never expose toShowPhone when phones is empty, so save payload clears it in CMS
|
|
2161
|
-
if (phones.length === 0) return null;
|
|
2162
|
-
// If toShowPhone is not in the list (e.g. format mismatch), treat as none selected
|
|
2163
|
-
if (toShow && !phones.includes(toShow)) return null;
|
|
2164
|
-
return toShow;
|
|
2155
|
+
return itemMemberObj.toShowPhone || null;
|
|
2165
2156
|
}
|
|
2166
2157
|
|
|
2167
2158
|
function getContactAndBookingData() {
|