sr-npm 1.0.11 → 1.0.13
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/.prettierrc +16 -0
- package/backend/collectionConsts.js +76 -0
- package/backend/consts.js +55 -110
- package/backend/data.js +354 -264
- package/backend/fetchPositionsFromSRAPI.js +47 -40
- package/backend/index.js +5 -4
- package/backend/queries.js +15 -14
- package/backend/secretsData.js +14 -0
- package/backend/utils.js +81 -4
- package/index.js +4 -5
- package/package.json +14 -3
- package/pages/careersPage.js +457 -0
- package/pages/homePage.js +136 -0
- package/pages/index.js +6 -0
- package/pages/positionPage.js +34 -0
- package/public/filterUtils.js +39 -0
- package/public/index.js +6 -0
- package/public/mapUtils.js +16 -0
- package/public/utils.js +45 -0
- package/tests/fetchPositionsFromSRApiTest.spec.js +35 -0
- package/tests/testsUtils.js +7 -0
- package/.wix/debug.log +0 -111
package/backend/data.js
CHANGED
|
@@ -1,288 +1,378 @@
|
|
|
1
1
|
const { items: wixData } = require('@wix/data');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
const { fetchPositionsFromSRAPI, fetchJobDescription } = require('./fetchPositionsFromSRAPI');
|
|
3
|
+
const { createCollectionIfMissing } = require('@hisense-staging/velo-npm/backend');
|
|
4
|
+
const { COLLECTIONS, COLLECTIONS_FIELDS,JOBS_COLLECTION_FIELDS } = require('./collectionConsts');
|
|
5
|
+
const { chunkedBulkOperation, countJobsPerGivenField, fillCityLocationAndLocationAddress ,prepareToSaveArray,normalizeCityName} = require('./utils');
|
|
6
|
+
const { getAllPositions } = require('./queries');
|
|
7
|
+
const { getCompanyId } = require('./secretsData');
|
|
8
|
+
|
|
9
|
+
function validatePosition(position) {
|
|
10
|
+
if (!position.id) {
|
|
11
|
+
throw new Error('Position id is required');
|
|
12
|
+
}
|
|
13
|
+
if (!position.title) {
|
|
14
|
+
throw new Error('Position title is required');
|
|
15
|
+
}
|
|
16
|
+
if (!position.department || !position.department.label) {
|
|
17
|
+
throw new Error('Position department is required and must have a label');
|
|
18
|
+
}
|
|
19
|
+
if (!position.location || !position.location.city || typeof position.location.remote !== 'boolean') {
|
|
20
|
+
throw new Error('Position location is required and must have a city and remote');
|
|
21
|
+
}
|
|
22
|
+
|
|
10
23
|
}
|
|
11
24
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
async function saveJobsDataToCMS() {
|
|
26
|
+
const positions = await fetchPositionsFromSRAPI();
|
|
27
|
+
// bulk insert to jobs collection without descriptions first
|
|
28
|
+
const jobsData = positions.content.map(position => {
|
|
29
|
+
const basicJob = {
|
|
30
|
+
_id: position.id,
|
|
31
|
+
title: position.name || '',
|
|
32
|
+
department: position.department?.label || 'Other',
|
|
33
|
+
cityText: normalizeCityName(position.location?.city),
|
|
34
|
+
location: position.location && Object.keys(position.location).length > 0
|
|
35
|
+
? position.location
|
|
36
|
+
: {
|
|
37
|
+
countryCode: "",
|
|
38
|
+
country: "",
|
|
39
|
+
city: "",
|
|
40
|
+
postalCode: "",
|
|
41
|
+
address: "",
|
|
42
|
+
manual: false,
|
|
43
|
+
remote: false,
|
|
44
|
+
regionCode: ""
|
|
45
|
+
},
|
|
46
|
+
country: position.location?.country || '',
|
|
47
|
+
remote: position.location?.remote || false,
|
|
48
|
+
language: position.language?.label || '',
|
|
49
|
+
jobDescription: null, // Will be filled later
|
|
50
|
+
};
|
|
51
|
+
return basicJob;
|
|
52
|
+
});
|
|
36
53
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const result = await wixData.bulkSave("Jobs", chunk);
|
|
44
|
-
const saved = result.inserted + result.updated || chunk.length;
|
|
45
|
-
totalSaved += saved;
|
|
46
|
-
console.log(`✓ Chunk ${chunkNumber} saved successfully. Inserted: ${result.inserted}, Updated: ${result.updated}`);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.error(`✗ Error saving chunk ${chunkNumber}:`, error);
|
|
49
|
-
throw error;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
console.log(`✓ All chunks processed. Total jobs saved: ${totalSaved}/${jobsData.length}`);
|
|
54
|
+
// Sort jobs by title (ascending, case-insensitive, numeric-aware)
|
|
55
|
+
jobsData.sort((a, b) => {
|
|
56
|
+
const titleA = a.title || '';
|
|
57
|
+
const titleB = b.title || '';
|
|
58
|
+
return titleA.localeCompare(titleB, undefined, { sensitivity: 'base', numeric: true });
|
|
59
|
+
});
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
const chunkSize = 1000;
|
|
62
|
+
let totalSaved = 0;
|
|
63
|
+
const totalChunks = Math.ceil(jobsData.length / chunkSize);
|
|
57
64
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
console.log(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Process all pages using hasNext() pagination
|
|
80
|
-
do {
|
|
81
|
-
const currentPageJobs = jobsWithNoDescriptions.items;
|
|
82
|
-
console.log(`\n📄 Processing page ${pageNumber} with ${currentPageJobs.length} jobs...`);
|
|
83
|
-
|
|
84
|
-
// Process jobs in smaller chunks of 5 for API calls within each page
|
|
85
|
-
const API_CHUNK_SIZE = 80;
|
|
86
|
-
const pageChunks = Math.ceil(currentPageJobs.length / API_CHUNK_SIZE);
|
|
87
|
-
|
|
88
|
-
await chunkedBulkOperation({
|
|
89
|
-
items: currentPageJobs,
|
|
90
|
-
chunkSize: API_CHUNK_SIZE,
|
|
91
|
-
processChunk: async (chunk, chunkNumber) => {
|
|
92
|
-
console.log(` Processing API chunk ${chunkNumber}/${pageChunks} (${chunk.length} jobs)`);
|
|
93
|
-
const chunkPromises = chunk.map(async (job) => {
|
|
94
|
-
try {
|
|
95
|
-
// console.log(` Fetching description for: ${job.title} (${job._id})`);
|
|
96
|
-
const jobDetails = await fetchJobDescription(job._id);
|
|
97
|
-
const updatedJob = {
|
|
98
|
-
...job,
|
|
99
|
-
jobDescription: jobDetails.jobAd.sections
|
|
100
|
-
};
|
|
101
|
-
await wixData.update("Jobs", updatedJob);
|
|
102
|
-
// console.log(` ✅ Updated description for: ${job.title}`);
|
|
103
|
-
return { success: true, jobId: job._id, title: job.title };
|
|
104
|
-
} catch (error) {
|
|
105
|
-
console.error(` ❌ Failed to update ${job.title} (${job._id}):`, error);
|
|
106
|
-
return { success: false, jobId: job._id, title: job.title, error: error.message };
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
const chunkResults = await Promise.all(chunkPromises);
|
|
110
|
-
const chunkSuccesses = chunkResults.filter(r => r.success).length;
|
|
111
|
-
const chunkFailures = chunkResults.filter(r => !r.success).length;
|
|
112
|
-
totalUpdated += chunkSuccesses;
|
|
113
|
-
totalFailed += chunkFailures;
|
|
114
|
-
totalProcessed += chunk.length;
|
|
115
|
-
console.log(` API chunk ${chunkNumber} completed: ${chunkSuccesses} success, ${chunkFailures} failed`);
|
|
116
|
-
if (chunkNumber * API_CHUNK_SIZE < currentPageJobs.length) {
|
|
117
|
-
console.log(' Waiting 2 seconds before next API chunk...');
|
|
118
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
console.log(`📄 Page ${pageNumber} completed. Updated: ${totalUpdated}, Failed: ${totalFailed}, Total processed: ${totalProcessed}/${jobsWithNoDescriptions.totalCount}`);
|
|
124
|
-
|
|
125
|
-
// Check if there are more pages and get the next page
|
|
126
|
-
if (jobsWithNoDescriptions.hasNext()) {
|
|
127
|
-
console.log('🔄 Moving to next page...');
|
|
128
|
-
jobsWithNoDescriptions = await jobsWithNoDescriptions.next();
|
|
129
|
-
pageNumber++;
|
|
130
|
-
|
|
131
|
-
// Add a delay between pages
|
|
132
|
-
console.log('Waiting 3 seconds before next page...');
|
|
133
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
} while (jobsWithNoDescriptions.hasNext());
|
|
137
|
-
|
|
138
|
-
console.log(`\n✅ Finished updating ALL job descriptions using pagination!`);
|
|
139
|
-
console.log(`📊 Final Results:`);
|
|
140
|
-
console.log(` Total pages processed: ${pageNumber}`);
|
|
141
|
-
console.log(` Total jobs processed: ${totalProcessed}`);
|
|
142
|
-
console.log(` Total updated: ${totalUpdated}`);
|
|
143
|
-
console.log(` Total failed: ${totalFailed}`);
|
|
144
|
-
|
|
145
|
-
return {
|
|
146
|
-
success: true,
|
|
147
|
-
totalPages: pageNumber,
|
|
148
|
-
totalProcessed: totalProcessed,
|
|
149
|
-
totalUpdated: totalUpdated,
|
|
150
|
-
totalFailed: totalFailed,
|
|
151
|
-
message: `Successfully updated ${totalUpdated} job descriptions out of ${totalProcessed} total jobs across ${pageNumber} pages`
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
} catch (error) {
|
|
155
|
-
console.error('❌ Error in updateJobDescriptions:', error);
|
|
65
|
+
console.log(
|
|
66
|
+
`Processing ${jobsData.length} jobs in ${totalChunks} chunks of max ${chunkSize} items each`
|
|
67
|
+
);
|
|
68
|
+
console.log("truncating jobs collection");
|
|
69
|
+
await wixData.truncate(COLLECTIONS.JOBS);
|
|
70
|
+
await chunkedBulkOperation({
|
|
71
|
+
items: jobsData,
|
|
72
|
+
chunkSize,
|
|
73
|
+
processChunk: async (chunk, chunkNumber) => {
|
|
74
|
+
console.log(`Saving chunk ${chunkNumber}/${totalChunks}: ${chunk.length} jobs`);
|
|
75
|
+
try {
|
|
76
|
+
const result = await wixData.bulkSave(COLLECTIONS.JOBS, chunk);
|
|
77
|
+
const saved = result.inserted + result.updated || chunk.length;
|
|
78
|
+
totalSaved += saved;
|
|
79
|
+
console.log(
|
|
80
|
+
`✓ Chunk ${chunkNumber} saved successfully. Inserted: ${result.inserted}, Updated: ${result.updated}`
|
|
81
|
+
);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error(`✗ Error saving chunk ${chunkNumber}:`, error);
|
|
156
84
|
throw error;
|
|
157
|
-
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
console.log(`✓ All chunks processed. Total jobs saved: ${totalSaved}/${jobsData.length}`);
|
|
158
90
|
}
|
|
159
91
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
let
|
|
165
|
-
let
|
|
166
|
-
let
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
remote: loc.remote.toString(),
|
|
201
|
-
regionCode: loc.regionCode,
|
|
202
|
-
latitude: loc.latitude,
|
|
203
|
-
longitude: loc.longitude
|
|
92
|
+
async function saveJobsDescriptionsAndLocationApplyUrlToCMS() {
|
|
93
|
+
console.log('🚀 Starting job descriptions update process for ALL jobs');
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
let jobsWithNoDescriptions = await getJobsWithNoDescriptions();
|
|
97
|
+
let totalUpdated = 0;
|
|
98
|
+
let totalFailed = 0;
|
|
99
|
+
let totalProcessed = 0;
|
|
100
|
+
|
|
101
|
+
console.log(
|
|
102
|
+
`Total jobs in database without descriptions: ${jobsWithNoDescriptions?.items?.length}`
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
if (jobsWithNoDescriptions.items.length === 0) {
|
|
106
|
+
console.log('No jobs found in database');
|
|
107
|
+
return { success: true, message: 'No jobs found' };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
const API_CHUNK_SIZE = 80;
|
|
112
|
+
const pageChunks = Math.ceil(jobsWithNoDescriptions.items.length / API_CHUNK_SIZE);
|
|
113
|
+
|
|
114
|
+
await chunkedBulkOperation({
|
|
115
|
+
items: jobsWithNoDescriptions.items,
|
|
116
|
+
chunkSize: API_CHUNK_SIZE,
|
|
117
|
+
processChunk: async (chunk, chunkNumber) => {
|
|
118
|
+
console.log(` Processing API chunk ${chunkNumber}/${pageChunks} (${chunk.length} jobs)`);
|
|
119
|
+
const chunkPromises = chunk.map(async job => {
|
|
120
|
+
try {
|
|
121
|
+
const jobDetails = await fetchJobDescription(job._id);
|
|
122
|
+
const jobLocation = fetchJobLocation(jobDetails);
|
|
123
|
+
const {applyLink , referFriendLink} = fetchApplyAndReferFriendLink(jobDetails);
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
const updatedJob = {
|
|
127
|
+
...job,
|
|
128
|
+
locationAddress: jobLocation,
|
|
129
|
+
jobDescription: jobDetails.jobAd.sections,
|
|
130
|
+
applyLink: applyLink,
|
|
131
|
+
referFriendLink: referFriendLink,
|
|
204
132
|
};
|
|
133
|
+
await wixData.update(COLLECTIONS.JOBS, updatedJob);
|
|
134
|
+
return { success: true, jobId: job._id, title: job.title };
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error(` ❌ Failed to update ${job.title} (${job._id}):`, error);
|
|
137
|
+
return { success: false, jobId: job._id, title: job.title, error: error.message };
|
|
138
|
+
}
|
|
205
139
|
});
|
|
140
|
+
const chunkResults = await Promise.all(chunkPromises);
|
|
141
|
+
const chunkSuccesses = chunkResults.filter(r => r.success).length;
|
|
142
|
+
const chunkFailures = chunkResults.filter(r => !r.success).length;
|
|
143
|
+
totalUpdated += chunkSuccesses;
|
|
144
|
+
totalFailed += chunkFailures;
|
|
145
|
+
totalProcessed += chunk.length;
|
|
146
|
+
console.log(
|
|
147
|
+
` API chunk ${chunkNumber} completed: ${chunkSuccesses} success, ${chunkFailures} failed`
|
|
148
|
+
);
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
console.log(`\n✅ Finished updating ALL job descriptions`);
|
|
155
|
+
console.log(`📊 Final Results:`);
|
|
156
|
+
console.log(` Total jobs processed: ${totalProcessed}`);
|
|
157
|
+
console.log(` Total updated: ${totalUpdated}`);
|
|
158
|
+
console.log(` Total failed: ${totalFailed}`);
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
success: true,
|
|
162
|
+
totalProcessed: totalProcessed,
|
|
163
|
+
totalUpdated: totalUpdated,
|
|
164
|
+
totalFailed: totalFailed,
|
|
165
|
+
message: `Successfully updated ${totalUpdated} job descriptions out of ${totalProcessed} total jobs`,
|
|
166
|
+
};
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error('❌ Error in updateJobDescriptions:', error);
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
function iterateOverAllJobs(results, field) {
|
|
175
|
+
const jobsPerField = {};
|
|
176
|
+
const cityLocations = {};
|
|
177
|
+
const citylocationAddress = {};
|
|
178
|
+
countJobsPerGivenField(results, field, jobsPerField);
|
|
179
|
+
if (field === 'cityText') {
|
|
180
|
+
fillCityLocationAndLocationAddress(results, cityLocations,citylocationAddress);
|
|
206
181
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
182
|
+
return { jobsPerField, cityLocations,citylocationAddress };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function aggregateJobsByFieldToCMS({ field, collection }) {
|
|
186
|
+
console.log(`counting jobs per ${field}.`);
|
|
187
|
+
let results = await getAllPositions();
|
|
188
|
+
const { jobsPerField, cityLocations,citylocationAddress } = iterateOverAllJobs(results, field);
|
|
189
|
+
const toSave = prepareToSaveArray(jobsPerField, cityLocations, field,citylocationAddress);
|
|
190
|
+
if (toSave.length === 0) {
|
|
191
|
+
console.log('No jobs found.');
|
|
192
|
+
return { success: true, message: 'No jobs to save.' };
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
console.log("saving to collection: ", collection);
|
|
196
|
+
console.log("toSave: ", toSave);
|
|
197
|
+
const saveResult = await wixData.bulkSave(collection, toSave);
|
|
198
|
+
console.log(`Saved ${toSave.length} ${field} counts to ${collection}.`);
|
|
199
|
+
return { success: true, saved: toSave.length, result: saveResult };
|
|
200
|
+
} catch (err) {
|
|
201
|
+
console.error(`Error saving jobs per ${field}:`, err);
|
|
202
|
+
return { success: false, error: err.message };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function getJobsWithNoDescriptions() {
|
|
207
|
+
let jobswithoutdescriptionsQuery = await wixData
|
|
208
|
+
.query(COLLECTIONS.JOBS)
|
|
209
|
+
.limit(1000)
|
|
210
|
+
.isEmpty('jobDescription')
|
|
211
|
+
.find();
|
|
212
|
+
return jobswithoutdescriptionsQuery;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @param {Object} params
|
|
217
|
+
* @param {JOBS_COLLECTION_FIELDS.CITY|JOBS_COLLECTION_FIELDS.DEPARTMENT_REF} params.referenceField
|
|
218
|
+
* @param {COLLECTIONS.CITIES|COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT} params.sourceCollection
|
|
219
|
+
* @param {JOBS_COLLECTION_FIELDS.CITY_TEXT|JOBS_COLLECTION_FIELDS.DEPARTMENT} params.jobField
|
|
220
|
+
*/
|
|
221
|
+
async function referenceJobsToField({ referenceField, sourceCollection, jobField }) {
|
|
222
|
+
// Fetch all source items (cities or departments)
|
|
223
|
+
const sources = await wixData.query(sourceCollection).limit(1000).find();
|
|
224
|
+
const sourceMap = {};
|
|
225
|
+
for (const item of sources.items) {
|
|
226
|
+
sourceMap[item.title] = item._id;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Fetch all jobs
|
|
230
|
+
let jobsResults = await getAllPositions();
|
|
231
|
+
let jobsToUpdate = [];
|
|
232
|
+
|
|
233
|
+
for (const job of jobsResults) {
|
|
234
|
+
const refId = sourceMap[job[jobField]];
|
|
235
|
+
if (refId) {
|
|
236
|
+
jobsToUpdate.push({
|
|
237
|
+
...job,
|
|
238
|
+
[referenceField]: refId,
|
|
239
|
+
});
|
|
218
240
|
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Remove system fields that cannot be updated
|
|
244
|
+
jobsToUpdate = jobsToUpdate.map(job => {
|
|
245
|
+
const { _createdDate, _updatedDate, ...rest } = job;
|
|
246
|
+
return rest;
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Bulk update in chunks of 1000
|
|
250
|
+
const chunkSize = 1000;
|
|
251
|
+
await chunkedBulkOperation({
|
|
252
|
+
items: jobsToUpdate,
|
|
253
|
+
chunkSize,
|
|
254
|
+
processChunk: async chunk => {
|
|
255
|
+
await wixData.bulkUpdate(COLLECTIONS.JOBS, chunk);
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
return { success: true, updated: jobsToUpdate.length };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function fetchApplyAndReferFriendLink(jobDetails) {
|
|
263
|
+
return {applyLink: jobDetails.applyUrl, referFriendLink: jobDetails.referralUrl};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function fetchJobLocation(jobDetails) {
|
|
267
|
+
const jobLocation = {
|
|
268
|
+
location: {
|
|
269
|
+
latitude: parseFloat(jobDetails.location.latitude),
|
|
270
|
+
longitude: parseFloat(jobDetails.location.longitude)
|
|
271
|
+
},
|
|
272
|
+
city: jobDetails.location.city,
|
|
273
|
+
country: jobDetails.location.country,
|
|
274
|
+
formatted: [
|
|
275
|
+
jobDetails.location.city,
|
|
276
|
+
jobDetails.location.region,
|
|
277
|
+
jobDetails.location.regionCode,
|
|
278
|
+
jobDetails.location.country,
|
|
279
|
+
]
|
|
280
|
+
.filter(Boolean)
|
|
281
|
+
.join(', '),
|
|
282
|
+
streetAddress: {},
|
|
283
|
+
subdivision: '',
|
|
284
|
+
postalCode: '',
|
|
285
|
+
};
|
|
286
|
+
return jobLocation;
|
|
287
|
+
}
|
|
288
|
+
|
|
219
289
|
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
async function createCompanyIdCollectionAndFillIt() {
|
|
293
|
+
console.log("Creating CompanyId collection and filling it with the company ID");
|
|
294
|
+
await createCollectionIfMissing(COLLECTIONS.COMPANY_ID, COLLECTIONS_FIELDS.COMPANY_ID,null,'singleItem');
|
|
295
|
+
console.log("Getting the company ID ");
|
|
296
|
+
const companyId = await getCompanyId();
|
|
297
|
+
console.log("companyId is : ", companyId);
|
|
298
|
+
console.log("Inserting the company ID into the CompanyId collection");
|
|
220
299
|
try {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
300
|
+
await wixData.insert(COLLECTIONS.COMPANY_ID, {
|
|
301
|
+
companyId: companyId.value
|
|
302
|
+
});
|
|
303
|
+
console.log("company ID inserted into the CompanyId collection");
|
|
304
|
+
} catch (error) {
|
|
305
|
+
if (error.message.includes("WDE0074: An item with _id [SINGLE_ITEM_ID] already exists")) {
|
|
306
|
+
console.log("company ID already exists in the CompanyId collection");
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
227
311
|
}
|
|
228
|
-
}
|
|
229
312
|
|
|
230
|
-
async function getJobsWithNoDescriptions() {
|
|
231
313
|
|
|
232
|
-
let jobswithoutdescriptionsQuery = await wixData.query("Jobs").limit(1000).isEmpty("jobDescription").find(); // with 900 as the limit, 429 error won't happen
|
|
233
|
-
return jobswithoutdescriptionsQuery;
|
|
234
314
|
}
|
|
235
315
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
for (const item of sources.items) {
|
|
246
|
-
sourceMap[item.title] = item._id;
|
|
247
|
-
}
|
|
316
|
+
async function createCollections() {
|
|
317
|
+
console.log("Creating collections");
|
|
318
|
+
await Promise.all(
|
|
319
|
+
[createCollectionIfMissing(COLLECTIONS.JOBS, JOBS_COLLECTION_FIELDS.JOBS,{ insert: 'ADMIN', update: 'ADMIN', remove: 'ADMIN', read: 'ANYONE' }),
|
|
320
|
+
createCollectionIfMissing(COLLECTIONS.CITIES, COLLECTIONS_FIELDS.CITIES),
|
|
321
|
+
createCollectionIfMissing(COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT, COLLECTIONS_FIELDS.AMOUNT_OF_JOBS_PER_DEPARTMENT)
|
|
322
|
+
]);
|
|
323
|
+
console.log("finished creating Collections");
|
|
324
|
+
}
|
|
248
325
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (refId) {
|
|
258
|
-
jobsToUpdate.push({
|
|
259
|
-
...job,
|
|
260
|
-
[referenceField]: refId
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
if (jobsResults.hasNext()) {
|
|
265
|
-
jobsResults = await jobsResults.next();
|
|
266
|
-
} else {
|
|
267
|
-
break;
|
|
268
|
-
}
|
|
269
|
-
} while (true);
|
|
270
|
-
|
|
271
|
-
// Remove system fields that cannot be updated
|
|
272
|
-
jobsToUpdate = jobsToUpdate.map(job => {
|
|
273
|
-
const { _createdDate, _updatedDate, ...rest } = job;
|
|
274
|
-
return rest;
|
|
275
|
-
});
|
|
326
|
+
async function aggregateJobs() {
|
|
327
|
+
console.log("Aggregating jobs");
|
|
328
|
+
await Promise.all([
|
|
329
|
+
aggregateJobsByFieldToCMS({ field: JOBS_COLLECTION_FIELDS.DEPARTMENT, collection: COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT }),
|
|
330
|
+
aggregateJobsByFieldToCMS({ field: JOBS_COLLECTION_FIELDS.CITY_TEXT, collection: COLLECTIONS.CITIES })
|
|
331
|
+
]);
|
|
332
|
+
console.log("finished aggregating jobs");
|
|
333
|
+
}
|
|
276
334
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
335
|
+
async function referenceJobs() {
|
|
336
|
+
console.log("Reference jobs");
|
|
337
|
+
await referenceJobsToField({ referenceField: JOBS_COLLECTION_FIELDS.DEPARTMENT_REF, sourceCollection: COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT, jobField: JOBS_COLLECTION_FIELDS.DEPARTMENT });
|
|
338
|
+
await referenceJobsToField({ referenceField: JOBS_COLLECTION_FIELDS.CITY, sourceCollection: COLLECTIONS.CITIES, jobField: JOBS_COLLECTION_FIELDS.CITY_TEXT });
|
|
339
|
+
console.log("finished referencing jobs");
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async function syncJobsFast() {
|
|
343
|
+
console.log("Syncing jobs fast");
|
|
344
|
+
await createCompanyIdCollectionAndFillIt();
|
|
345
|
+
await createCollections();
|
|
346
|
+
await clearCollections();
|
|
347
|
+
console.log("saving jobs data to CMS");
|
|
348
|
+
await saveJobsDataToCMS();
|
|
349
|
+
console.log("saved jobs data to CMS successfully");
|
|
350
|
+
console.log("saving jobs descriptions and location apply url to CMS");
|
|
351
|
+
await saveJobsDescriptionsAndLocationApplyUrlToCMS();
|
|
352
|
+
console.log("saved jobs descriptions and location apply url to CMS successfully");
|
|
353
|
+
await aggregateJobs();
|
|
354
|
+
await referenceJobs();
|
|
355
|
+
console.log("syncing jobs fast finished successfully");
|
|
356
|
+
}
|
|
286
357
|
|
|
287
|
-
|
|
358
|
+
async function clearCollections() {
|
|
359
|
+
console.log("clearing collections");
|
|
360
|
+
await Promise.all([
|
|
361
|
+
wixData.truncate(COLLECTIONS.CITIES),
|
|
362
|
+
wixData.truncate(COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT),
|
|
363
|
+
wixData.truncate(COLLECTIONS.JOBS)
|
|
364
|
+
]);
|
|
365
|
+
console.log("cleared collections successfully");
|
|
288
366
|
}
|
|
367
|
+
|
|
368
|
+
module.exports = {
|
|
369
|
+
syncJobsFast,
|
|
370
|
+
referenceJobs,
|
|
371
|
+
aggregateJobs,
|
|
372
|
+
createCollections,
|
|
373
|
+
saveJobsDataToCMS,
|
|
374
|
+
saveJobsDescriptionsAndLocationApplyUrlToCMS,
|
|
375
|
+
aggregateJobsByFieldToCMS,
|
|
376
|
+
referenceJobsToField,
|
|
377
|
+
createCompanyIdCollectionAndFillIt,
|
|
378
|
+
};
|