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/backend/data.js CHANGED
@@ -1,288 +1,378 @@
1
1
  const { items: wixData } = require('@wix/data');
2
- import { fetchPositionsFromSRAPI, fetchJobDescription } from './fetchPositionsFromSRAPI';
3
- import { chunkedBulkOperation } from './utils';
4
-
5
- // Utility function to normalize city names
6
- function normalizeCityName(city) {
7
- if (!city) return city;
8
- // Remove accents/diacritics, trim whitespace
9
- return city.normalize('NFD').replace(/\p{Diacritic}/gu, '').trim();
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
- export async function saveDataJobsToCMS() {
13
- const positions = await fetchPositionsFromSRAPI();
14
- // bulk insert to jobs collection without descriptions first
15
- const jobsData = positions.content.map((position) => {
16
- const basicJob = {
17
- _id: position.id,
18
- title: position.title,
19
- department: position.department.label,
20
- cityText: normalizeCityName(position.location.city),
21
- location: position.location,
22
- country: position.location.country,
23
- remote: position.location.remote,
24
- language: position.language.label,
25
- postingStatus: position.postingStatus,
26
- jobDescription: null // Will be filled later
27
- }
28
- return basicJob;
29
- });
30
-
31
- const chunkSize = 1000;
32
- let totalSaved = 0;
33
- const totalChunks = Math.ceil(jobsData.length / chunkSize);
34
-
35
- console.log(`Processing ${jobsData.length} jobs in ${totalChunks} chunks of max ${chunkSize} items each`);
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
- await chunkedBulkOperation({
38
- items: jobsData,
39
- chunkSize,
40
- processChunk: async (chunk, chunkNumber) => {
41
- console.log(`Saving chunk ${chunkNumber}/${totalChunks}: ${chunk.length} jobs`);
42
- try {
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
- export async function saveJobsDescriptionsToCMS() {
59
-
60
- console.log('🚀 Starting job descriptions update process for ALL jobs using pagination...');
61
-
62
- try {
63
- let jobsWithNoDescriptions = await getJobsWithNoDescriptions();
64
- let totalUpdated = 0;
65
- let totalFailed = 0;
66
- let totalProcessed = 0;
67
- let pageNumber = 1;
68
-
69
- // Start with the first page query - limit to 100 jobs per page
70
- // let jobsQuery = await wixData.query("Jobs").limit(300).find();
71
-
72
- console.log(`Total jobs in database without descriptions: ${jobsWithNoDescriptions.totalCount}`);
73
-
74
- if (jobsWithNoDescriptions.totalCount === 0) {
75
- console.log('No jobs found in database');
76
- return { success: true, message: 'No jobs found' };
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
- export async function aggregateJobsByFieldToCMS({ field, collection }) {
161
- console.log(`counting jobs per ${field}.`);
162
- let jobsPerField = {};
163
- let cityLocations = {};
164
- let query = wixData.query("Jobs").limit(1000);
165
- let results = await query.find();
166
- let page = 1;
167
- do {
168
- console.log(`Page ${page}: ${results.items.length} jobs.`);
169
- for (const job of results.items) {
170
- if (!job[field])
171
- {
172
- throw new Error(`Job ${job._id} has no ${field} field`);
173
- }
174
- jobsPerField[job[field]] = (jobsPerField[job[field]] || 0) + 1;
175
- if (field === 'cityText' && !cityLocations[job[field]]) {
176
- cityLocations[job[field]] = job.location;
177
- }
178
- }
179
- if (results.hasNext()) {
180
- results = await results.next();
181
- page++;
182
- }
183
- } while (results.hasNext());
184
- let toSave = [];
185
- if (field === 'cityText') {
186
- toSave = Object.entries(jobsPerField).map(([value, amount]) => {
187
- const loc = cityLocations[value] || {};
188
- value = normalizeCityName(value);
189
-
190
- return {
191
- title: value,
192
- _id: value.replace(/\s+/g, ''),
193
- count: amount,
194
- location: loc,
195
- countryCode: loc.countryCode,
196
- country: loc.country,
197
- region: loc.region,
198
- city: loc.city,
199
- manual: loc.manual.toString(),
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
- else{
208
- // Prepare array for bulkSave
209
- toSave = Object.entries(jobsPerField).map(([value, amount]) => ({
210
- title: value,
211
- _id: value.replace(/\s+/g, ''),
212
- count: amount
213
- }));
214
- }
215
- if (toSave.length === 0) {
216
- console.log('No jobs found.');
217
- return { success: true, message: 'No jobs to save.' };
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
- const saveResult = await wixData.bulkSave(collection, toSave);
222
- console.log(`Saved ${toSave.length} ${field} counts to ${collection}.`);
223
- return { success: true, saved: toSave.length, result: saveResult };
224
- } catch (err) {
225
- console.error(`Error saving jobs per ${field}:`, err);
226
- return { success: false, error: err.message };
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
- export async function referenceJobsToField({
237
- referenceField, // e.g., "city" or "department"
238
- sourceCollection, // e.g., "cities" or "departments"
239
- jobField, // e.g., "cityText" or "department"
240
-
241
- }) {
242
- // Fetch all source items (cities or departments)
243
- const sources = await wixData.query(sourceCollection).limit(1000).find();
244
- const sourceMap = {};
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
- // Fetch all jobs
250
- let jobsResults = await wixData.query("Jobs").limit(1000).find();
251
- let jobsToUpdate = [];
252
- console.log('jobsResults',jobsResults.items);
253
-
254
- do {
255
- for (const job of jobsResults.items) {
256
- const refId = sourceMap[job[jobField]];
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
- // Bulk update in chunks of 1000
278
- const chunkSize = 1000;
279
- await chunkedBulkOperation({
280
- items: jobsToUpdate,
281
- chunkSize,
282
- processChunk: async (chunk) => {
283
- await wixData.bulkUpdate("Jobs", chunk);
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
- return { success: true, updated: jobsToUpdate.length };
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
+ };