sr-npm 2.0.17 → 2.0.19

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.
@@ -5,14 +5,14 @@ on:
5
5
  branches:
6
6
  - main
7
7
  workflow_dispatch:
8
-
8
+
9
9
  permissions:
10
10
  contents: write
11
11
  packages: write
12
12
 
13
13
  jobs:
14
14
  update-sites:
15
- uses: psdevteamenterprise/ci-workflows/.github/workflows/publish-and-notify.yml@main
15
+ uses: psdevteamenterprise/ci-workflows/.github/workflows/update-and-notify.yml@main
16
16
  with:
17
17
  sites_to_update: "[{repo: 'psdevteamenterprise/tests-site', secret: 'WIX_PS_API_KEY'},
18
18
  {repo: 'psdevteamenterprise/external-template', secret: 'WIX_SR_API_KEY'},
@@ -0,0 +1,61 @@
1
+ const CAREERS_MULTI_BOXES_PAGE_CONSTS={
2
+ FILTER_REPEATER: '#filterReapter',
3
+ JOBS_REPEATER: '#jobsReapter',
4
+ JOBS_REPEATER_ITEM_TITLE: '#jobTitle',
5
+ JOBS_REPEATER_ITEM_LOCATION: '#locationLabel',
6
+ JOBS_REPEATER_ITEM_EMPLOYMENT_TYPE: '#employmentTypeLabel',
7
+ TotalJobsCountText: '#totalJobsCountText',
8
+ FILTER_LABEL: '#FilterTextInput',
9
+ FILTER_CHECKBOX_CONTAINER: '#FilterCheckBoxContainer',
10
+ FILTER_REPEATER_ITEM_CHECKBOX: '#filterCheckBox',
11
+ SELECTED_VALUES_REPEATER: '#selectedValuesReapter',
12
+ SELECTED_VALUES_REPEATER_ITEM_LABEL: '#selectedValueLabel',
13
+ DESELECT_BUTTON_ID: '#deselectFilterValueButton',
14
+ CLEAR_ALL_BUTTON_ID: '#clearAllButton',
15
+ PAGE_BUTTON_NEXT: '#nextPageButton',
16
+ PAGE_BUTTON_PREVIOUS: '#previousPageButton',
17
+ paginationCurrentText: '#paginationCurrent',
18
+ paginationTotalCountText: '#paginationTotalCount',
19
+ PRIMARY_SEARCH_RESULTS: '#resultsRepeater',
20
+ SEARCH_BUTTON: '#searchButton',
21
+ SECONDARY_SEARCH_INPUT: '#secondarySearchInput',
22
+ JOBS_MULTI_STATE_BOX:"#jobsMultiStateBox",
23
+ PRIMARY_SEARCH_INPUT: '#primarySearchInput',
24
+ JOB_RESULTS_REPEATER: '#jobResultsRepeater',
25
+ JOB_RESULTS_REPEATER_ITEM: '#jobResultsRepeaterItem',
26
+ CATEGORY_RESULTS_REPEATER: '#categoryResultsRepeater',
27
+ CATEGORY_RESULTS_REPEATER_ITEM: '#categoryResultsRepeaterItem',
28
+ PRIMARY_SEARCH_MULTI_BOX: '#primarySearchMultiBox',
29
+ PRIMARY_SEARCH_POSITION_BUTTON: '#primarySearchPositionButton',
30
+ PRIMARY_SEARCH_CATEGORY_BUTTON: '#primarySearchCategoryButton',
31
+ RESULTS_CONTAINER: '#resultsContainer',
32
+ PRIMARY_SEARCH_BUTTON: '#primarySearchButton',
33
+
34
+ }
35
+
36
+ const CATEGORY_CUSTOM_FIELD_ID_IN_CMS='5cd8c873c9e77c0008aa7d23';
37
+
38
+ const fieldTitlesInCMS={
39
+ "brand": "Brands",
40
+ category: "Category",
41
+ visibility: "Visibility",
42
+ }
43
+
44
+ const FiltersIds={
45
+ Category: 'Category',
46
+ "Company Segment": 'CompanySegment',
47
+ Location: 'Location',
48
+ "Store Name": 'StoreName',
49
+ "Employment Type": 'employmentType',
50
+ "Contract Type": 'contractType',
51
+ Brands: 'Brands',
52
+ Visibility: 'Visibility',
53
+ }
54
+
55
+
56
+ module.exports = {
57
+ CAREERS_MULTI_BOXES_PAGE_CONSTS,
58
+ FiltersIds,
59
+ fieldTitlesInCMS,
60
+ CATEGORY_CUSTOM_FIELD_ID_IN_CMS,
61
+ }
@@ -5,6 +5,11 @@ const COLLECTIONS = {
5
5
  TEMPLATE_TYPE: 'templateType',
6
6
  SECRET_MANAGER_MIRROR: 'SecretManagerMirror',
7
7
  BRANDS: 'Brands',
8
+ CUSTOM_VALUES:'CustomValues',
9
+ CUSTOM_FIELDS:'CustomFields',
10
+ SITE_CONFIGS: 'SiteConfigs',
11
+ SUPPORT_TEAMS: 'SupportTeams',
12
+
8
13
  }
9
14
  const JOBS_COLLECTION_FIELDS = {
10
15
  LOCATION: 'location',
@@ -23,12 +28,26 @@ const JOBS_COLLECTION_FIELDS = {
23
28
  REFER_FRIEND_LINK: 'referFriendLink',
24
29
  BRAND: 'brand',
25
30
  BRAND_REF: 'brandRef',
31
+ MULTI_REF_JOBS_CUSTOM_VALUES: 'multiRefJobsCustomValues',
32
+ EMPLOYMENT_TYPE: 'employmentType',
33
+ RELEASED_DATE: 'releasedDate',
34
+ REF_ID: 'refId',
26
35
  }
27
36
  const AMOUNT_OF_JOBS_PER_DEPARTMENT_COLLECTION_FIELDS = {
28
37
  TITLE: 'title',
29
38
  COUNT: 'count',
30
39
  IMAGE: 'image',
31
40
  }
41
+ const CUSTOM_VALUES_COLLECTION_FIELDS = {
42
+ TITLE: 'title',
43
+ CUSTOM_FIELD: 'customField',
44
+ MULTI_REF_JOBS_CUSTOM_VALUES: 'multiRefJobsCustomValues',
45
+ count: 'count',
46
+ JOB_IDS: 'jobIds',
47
+ }
48
+ const CUSTOM_FIELDS_COLLECTION_FIELDS = {
49
+ TITLE: 'title',
50
+ }
32
51
  const BRANDS_COLLECTION_FIELDS = {
33
52
  TITLE: 'title',
34
53
  COUNT: 'count',
@@ -39,6 +58,7 @@ const CITIES_COLLECTION_FIELDS = {
39
58
  LOCATION_ADDRESS: 'locationAddress',
40
59
  COUNT: 'count',
41
60
  COUNTRY: 'country',
61
+ JOB_IDS: 'jobIds',
42
62
  }
43
63
  const COLLECTIONS_FIELDS = {
44
64
  AMOUNT_OF_JOBS_PER_DEPARTMENT: [
@@ -52,6 +72,7 @@ const COLLECTIONS_FIELDS = {
52
72
  {key:'locationAddress', type: 'ADDRESS'},
53
73
  {key:'count', type: 'NUMBER'},
54
74
  {key:'country', type: 'TEXT'},
75
+ {key:'jobIds', type: 'ARRAY'},
55
76
  ],
56
77
  JOBS: [
57
78
  {key:'location', type: 'OBJECT'},
@@ -62,6 +83,7 @@ const COLLECTIONS_FIELDS = {
62
83
  {key:'language', type: 'TEXT'},
63
84
  {key:'remote', type: 'BOOLEAN'},
64
85
  {key:'jobDescription', type: 'OBJECT'},
86
+ {key:'multiRefJobsCustomValues', type: 'MULTI_REFERENCE', typeMetadata: { multiReference: { referencedCollectionId: COLLECTIONS.CUSTOM_VALUES,referencingFieldKey:JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,referencingDisplayName:JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES } } },
65
87
  {key:'cityText', type: 'TEXT'},
66
88
  {key:'applyLink', type: 'URL'},
67
89
  {key:'referFriendLink', type: 'URL'},
@@ -69,11 +91,18 @@ const COLLECTIONS_FIELDS = {
69
91
  {key:'departmentref', type: 'REFERENCE', typeMetadata: { reference: { referencedCollectionId: COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT } } },
70
92
  {key:'city', type: 'REFERENCE', typeMetadata: { reference: { referencedCollectionId: COLLECTIONS.CITIES } } },
71
93
  {key:'brandRef', type: 'REFERENCE', typeMetadata: { reference: { referencedCollectionId: COLLECTIONS.BRANDS } } },
72
- { key: 'image', type: 'IMAGE' },
94
+ {key: 'image', type: 'IMAGE' },
95
+ {key:'employmentType', type: 'TEXT'},
96
+ {key:'releasedDate', type: 'TEXT'},
97
+ {key:'refId', type: 'TEXT'},
73
98
  ],
74
99
  TEMPLATE_TYPE: [
75
100
  {key:'templateType', type: 'TEXT'},
76
101
  ],
102
+ SITE_CONFIGS: [
103
+ {key:'onlyBrandKeywordUrlParams', type: 'TEXT'},
104
+ {key:'customFields', type: 'TEXT'},
105
+ ],
77
106
  SECRET_MANAGER_MIRROR: [
78
107
  {key:'tokenName', type: 'TEXT'},
79
108
  {key:'value', type: 'TEXT'},
@@ -82,6 +111,16 @@ const COLLECTIONS_FIELDS = {
82
111
  {key:'title', type: 'TEXT'},
83
112
  { key: 'count', type: 'NUMBER' },
84
113
  ],
114
+ CUSTOM_VALUES: [
115
+ {key:'title', type: 'TEXT'},
116
+ {key:'customField', type: 'REFERENCE', typeMetadata: { reference: { referencedCollectionId: COLLECTIONS.CUSTOM_FIELDS } } },
117
+ {key:'count', type: 'NUMBER'},
118
+ {key:'multiRefJobsCustomValues', type: 'MULTI_REFERENCE', typeMetadata: { multiReference: { referencedCollectionId: COLLECTIONS.JOBS,referencingFieldKey:CUSTOM_VALUES_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,referencingDisplayName:CUSTOM_VALUES_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES } } },
119
+ {key:'jobIds', type: 'ARRAY'},
120
+ ],
121
+ CUSTOM_FIELDS: [
122
+ {key:'title', type: 'TEXT'},
123
+ ],
85
124
  };
86
125
 
87
126
 
@@ -104,6 +143,9 @@ const COLLECTIONS_FIELDS = {
104
143
  AMOUNT_OF_JOBS_PER_DEPARTMENT_COLLECTION_FIELDS,
105
144
  CITIES_COLLECTION_FIELDS,
106
145
  BRANDS_COLLECTION_FIELDS,
146
+ CUSTOM_FIELDS_COLLECTION_FIELDS,
147
+ CUSTOM_VALUES_COLLECTION_FIELDS,
107
148
  TEMPLATE_TYPE,
108
149
  TOKEN_NAME,
150
+
109
151
  };
package/backend/consts.js CHANGED
@@ -1,4 +1,4 @@
1
- const {saveJobsDataToCMS,saveJobsDescriptionsAndLocationApplyUrlToCMS,createCollections,aggregateJobs,referenceJobs,syncJobsFast} = require('./data')
1
+ const {saveJobsDataToCMS,saveJobsDescriptionsAndLocationApplyUrlReferencesToCMS,createCollections,aggregateJobs,referenceJobs,syncJobsFast} = require('./data')
2
2
 
3
3
 
4
4
  const QUERY_MAX_LIMIT = 1000;
@@ -6,7 +6,7 @@ const QUERY_MAX_LIMIT = 1000;
6
6
  const TASKS_NAMES = {
7
7
  SYNC_JOBS: 'syncJobsFromSRAPIToCMS',
8
8
  INSERT_JOBS_TO_CMS: 'insertJobsToCMS',
9
- INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_TO_CMS: 'insertJobsDescriptionsLocationApplyUrlToCMS',
9
+ INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_REFERENCES_TO_CMS: 'insertJobsDescriptionsLocationApplyUrlReferencesToCMS',
10
10
  AGGREGATE_JOBS_BY_FIELD_TO_CMS: 'aggregateJobsByFieldToCMS',
11
11
  REFERENCE_JOBS: 'referenceJobs',
12
12
  CREATE_COLLECTIONS: 'createCollections',
@@ -21,7 +21,7 @@ const TASKS = {
21
21
  childTasks: [
22
22
  { name: TASKS_NAMES.CREATE_COLLECTIONS},
23
23
  { name: TASKS_NAMES.INSERT_JOBS_TO_CMS },
24
- { name: TASKS_NAMES.INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_TO_CMS },
24
+ { name: TASKS_NAMES.INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_REFERENCES_TO_CMS },
25
25
  { name: TASKS_NAMES.AGGREGATE_JOBS_BY_FIELD_TO_CMS },
26
26
  {name: TASKS_NAMES.REFERENCE_JOBS},
27
27
  ],
@@ -42,10 +42,10 @@ const TASKS = {
42
42
  shouldSkipCheck:()=>false,
43
43
  estimatedDurationSec:20
44
44
  },
45
- [TASKS_NAMES.INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_TO_CMS]: {
46
- name: TASKS_NAMES.INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_TO_CMS,
45
+ [TASKS_NAMES.INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_REFERENCES_TO_CMS]: {
46
+ name: TASKS_NAMES.INSERT_JOBS_DESCRIPTIONS_LOCATION_APPLY_URL_REFERENCES_TO_CMS,
47
47
  getIdentifier:()=> "SHOULD_NEVER_SKIP",
48
- process:saveJobsDescriptionsAndLocationApplyUrlToCMS,
48
+ process:saveJobsDescriptionsAndLocationApplyUrlReferencesToCMS,
49
49
  shouldSkipCheck:()=>false,
50
50
  estimatedDurationSec:20
51
51
  },
@@ -72,17 +72,71 @@ const TASKS = {
72
72
  }
73
73
  }
74
74
 
75
-
76
-
77
-
78
75
  const TASK_TYPE = {
79
76
  SCHEDULED: 'scheduled',
80
77
  EVENT: 'event',
81
78
  };
82
79
 
83
- module.exports = {
84
- TASKS_NAMES,
85
- TASK_TYPE,
86
- TASKS,
87
- QUERY_MAX_LIMIT,
80
+ const supportTeamsPageIds={
81
+ PEOPLE_REPEATER: "#peopleRepeater",
82
+ PEOPLE_BUTTON: "#peopleButton",
83
+ PEOPLE_TITLE: "#peopleTitle",
84
+ RECENT_JOBS_REPEATER: "#recentJobsRepeater",
85
+ RECENT_JOBS_TITLE: "#recentJobsTitle",
86
+ RECENT_JOBS_BUTTON: "#recentJobsButton",
87
+ RECENT_JOBS_SECTION: "#recentJobsSection",
88
+ VIDEO_SECTION: "#videoSection",
89
+ VIDEO_TITLE: "#videoTitle",
90
+ VIDEO_PLAYER: "#videoPlayer",
91
+
92
+ RECENTLEY_ADDED_JOBS_ITEM: "#recentleyAddedJobsItem",
93
+ JOB_LOCATION: "#jobLocation",
94
+ JOB_TITLE: "#jobTitle",
95
+ TEAM_SUPPORT_DYNAMIC_DATASET: "#dynamicDataset",
96
+ valueToValueIdMap: {
97
+ "Human Resouces":"PeopleSupport",
98
+ "Merchandise - Buying":"Merchandise",
99
+ "Technology, Data and Digital":"InformationServices",
100
+ "Merchandise - Planning":"Merchandise",
101
+ "Digital":"ecommerceandDigital",// this field doesnt exists in the database
102
+ "Marketing and Market Media":"Marketing",
103
+ "Finance, Property and Legal":"Finance",// this field doesnt exists in the database
104
+ "Services":"ServicesInstallation",
105
+ "Merchandise - Design and Sourcing":"Merchandise",
106
+ "Store Operations":"Operations",// this field doesnt exists in the database
107
+ "Data":"InsightsandDataScience",// this field doesnt exists in the database
108
+ "Property":"Property",// this field doesnt exists in the database,
109
+ "Legal":"Legal",// this field doesnt exists in the database,
110
+ "Supply Chain and Logistics":"Logistics",
111
+ "Contact Centres":"CustomerEngagementCentres",// this field doesnt exists in the database
112
+ "Commercial":"CommercialSales",// this field doesnt exists in the database
113
+ },
114
+ excludeValues: new Set([
115
+ "Noel Leeming Commercial",
116
+ "Noel Leeming Services",
117
+ "Sustainability"
118
+ ])
119
+ }
120
+ const LINKS={
121
+ myApplication:'https://www.smartrecruiters.com/app/employee-portal/68246e5512d84f4c00a19e62/job-applications',
122
+ myReferrals:'https://www.smartrecruiters.com/app/referrals/',
123
+ login:'https://www.smartrecruiters.com/web-sso/saml/${companyId}/login',
124
+ }
125
+
126
+
127
+ const supportTeamsPageSections={
128
+ RECENT_JOBS: "recentJobs",
129
+ PEOPLE: "people",
130
+ VIDEO: "video",
131
+ }
132
+
133
+
134
+ module.exports = {
135
+ TASKS_NAMES,
136
+ TASK_TYPE,
137
+ TASKS,
138
+ QUERY_MAX_LIMIT,
139
+ supportTeamsPageIds,
140
+ LINKS,
141
+ supportTeamsPageSections,
88
142
  };
package/backend/data.js CHANGED
@@ -1,15 +1,25 @@
1
1
  const { items: wixData } = require('@wix/data');
2
2
  const { fetchPositionsFromSRAPI, fetchJobDescription } = require('./fetchPositionsFromSRAPI');
3
3
  const { createCollectionIfMissing } = require('@hisense-staging/velo-npm/backend');
4
- const { COLLECTIONS, COLLECTIONS_FIELDS,JOBS_COLLECTION_FIELDS,TEMPLATE_TYPE,TOKEN_NAME } = require('./collectionConsts');
4
+ const { COLLECTIONS, COLLECTIONS_FIELDS,JOBS_COLLECTION_FIELDS,TEMPLATE_TYPE,TOKEN_NAME,CUSTOM_VALUES_COLLECTION_FIELDS } = require('./collectionConsts');
5
5
  const { chunkedBulkOperation, countJobsPerGivenField, fillCityLocationAndLocationAddress ,prepareToSaveArray,normalizeString} = require('./utils');
6
6
  const { getAllPositions } = require('./queries');
7
- const { retrieveSecretVal, getTokenFromCMS } = require('./secretsData');
7
+ const { retrieveSecretVal, getTokenFromCMS ,getApiKeys} = require('./secretsData');
8
+
9
+ let customValuesToJobs = {}
10
+ let locationToJobs = {}
11
+ let siteconfig;
12
+ const EXCLUDED_CUSTOM_FIELDS = new Set(["Department","Country"]);
8
13
 
9
14
  function getBrand(customField) {
10
15
  return customField.find(field => field.fieldLabel === 'Brands')?.valueLabel;
11
16
  }
12
17
 
18
+ async function getSiteConfig() {
19
+ const queryresult = await wixData.query(COLLECTIONS.SITE_CONFIGS).find();
20
+ siteconfig = queryresult.items[0];
21
+ }
22
+
13
23
  function validatePosition(position) {
14
24
  if (!position.id) {
15
25
  throw new Error('Position id is required');
@@ -29,22 +39,22 @@ function validatePosition(position) {
29
39
  async function filterBasedOnBrand(positions) {
30
40
  try{
31
41
 
32
- const desiredBrand = await getTokenFromCMS(TOKEN_NAME.DESIRED_BRAND);
33
- validateSingleDesiredBrand(desiredBrand);
34
- console.log("filtering positions based on brand: ", desiredBrand);
35
- return positions.content.filter(position => {
36
- const brand = getBrand(position.customField);
37
- if (!brand) return false;
38
- return brand === desiredBrand;
39
- });
40
- } catch (error) {
41
- if(error.message==="[getTokenFromCMS], No desiredBrand found")
42
- {
43
- console.log("no desiredBrand found, fetching all positions")
44
- return positions.content;
42
+ const desiredBrand = await getTokenFromCMS(TOKEN_NAME.DESIRED_BRAND);
43
+ validateSingleDesiredBrand(desiredBrand);
44
+ console.log("filtering positions based on brand: ", desiredBrand);\
45
+ return positions.content.filter(position => {
46
+ const brand = getBrand(position.customField);
47
+ if (!brand) return false;
48
+ return brand === desiredBrand;
49
+ });
50
+ } catch (error) {
51
+ if(error.message==="[getTokenFromCMS], No desiredBrand found")
52
+ {
53
+ console.log("no desiredBrand found, fetching all positions")
54
+ return positions.content;
55
+ }
56
+ throw error;
45
57
  }
46
- throw error;
47
- }
48
58
  }
49
59
 
50
60
  function validateSingleDesiredBrand(desiredBrand) {
@@ -53,12 +63,60 @@ function validateSingleDesiredBrand(desiredBrand) {
53
63
  }
54
64
  }
55
65
 
66
+ function getLocation(position,basicJob) {
67
+ locationToJobs[basicJob.cityText] ? locationToJobs[basicJob.cityText].push(position.id) : locationToJobs[basicJob.cityText]=[position.id]
68
+
69
+ }
70
+
71
+ function getVisibility(position,customFieldsValues) {
72
+ if (!customFieldsValues["Visibility"]) {
73
+ customFieldsValues["Visibility"] = {};
74
+ }
75
+ let visibility;
76
+ position.visibility.toLowerCase()==="public"? visibility="external" : visibility="internal";
77
+ customFieldsValues["Visibility"][visibility] = visibility;
78
+ customValuesToJobs[visibility] ? customValuesToJobs[visibility].add(position.id) : customValuesToJobs[visibility]=new Set([position.id])
79
+ }
80
+
81
+ function getEmploymentType(position,customFieldsValues) {
82
+ if (!customFieldsValues["employmentType"]) {
83
+ customFieldsValues["employmentType"] = {};
84
+ }
85
+ customFieldsValues["employmentType"][position.typeOfEmployment.id] = position.typeOfEmployment.label;
86
+ customValuesToJobs[position.typeOfEmployment.id] ? customValuesToJobs[position.typeOfEmployment.id].add(position.id) : customValuesToJobs[position.typeOfEmployment.id]=new Set([position.id])
87
+ }
88
+
89
+ function getCustomFieldsAndValuesFromPosition(position,customFieldsLabels,customFieldsValues) {
90
+ const customFieldsArray = Array.isArray(position?.customField) ? position.customField : [];
91
+ for (const field of customFieldsArray) {
92
+ if(EXCLUDED_CUSTOM_FIELDS.has(field.fieldLabel)) continue; //country and department are not custom fields, they are already in the job object
93
+ const fieldId=normalizeString(field.fieldId)
94
+ const fieldLabel = field.fieldLabel;
95
+ const valueId=normalizeString(field.valueId)
96
+ const valueLabel = field.valueLabel
97
+ customFieldsLabels[fieldId] = fieldLabel
98
+ // Build nested dictionary: fieldId -> { valueId: valueLabel }
99
+ if (!customFieldsValues[fieldId]) {
100
+ customFieldsValues[fieldId] = {};
101
+ }
102
+
103
+ customFieldsValues[fieldId][valueId] = valueLabel;
104
+ customValuesToJobs[valueId] ? customValuesToJobs[valueId].add(position.id) : customValuesToJobs[valueId]=new Set([position.id])
105
+ }
106
+ }
56
107
  async function saveJobsDataToCMS() {
57
108
  const positions = await fetchPositionsFromSRAPI();
58
109
  const sourcePositions = await filterBasedOnBrand(positions);
110
+ const customFieldsLabels = {}
111
+ const customFieldsValues = {}
59
112
 
113
+ const {companyId,templateType} = await getApiKeys();
114
+ if(siteconfig===undefined) {
115
+ await getSiteConfig();
116
+ }
60
117
  // bulk insert to jobs collection without descriptions first
61
118
  const jobsData = sourcePositions.map(position => {
119
+
62
120
  const basicJob = {
63
121
  _id: position.id,
64
122
  title: position.name || '',
@@ -79,12 +137,26 @@ async function saveJobsDataToCMS() {
79
137
  country: position.location?.country || '',
80
138
  remote: position.location?.remote || false,
81
139
  language: position.language?.label || '',
82
- brand: getBrand(position.customField),
140
+ brand: siteconfig.disableMultiBrand==="false" ? getBrand(position.customField) : '',
83
141
  jobDescription: null, // Will be filled later
142
+ employmentType: position.typeOfEmployment.label,
143
+ releasedDate: position.releasedDate,
144
+ refId: position.refNumber
84
145
  };
146
+
147
+ getCustomFieldsAndValuesFromPosition(position,customFieldsLabels,customFieldsValues);
148
+ getEmploymentType(position,customFieldsValues);
149
+ getLocation(position,basicJob);
150
+ if(templateType===TEMPLATE_TYPE.INTERNAL){
151
+ getVisibility(position,customFieldsValues);
152
+ }
85
153
  return basicJob;
86
154
  });
87
155
 
156
+ if (siteconfig.customFields==="true") {
157
+ await populateCustomFieldsCollection(customFieldsLabels,templateType);
158
+ await populateCustomValuesCollection(customFieldsValues);
159
+ }
88
160
  // Sort jobs by title (ascending, case-insensitive, numeric-aware)
89
161
  jobsData.sort((a, b) => {
90
162
  const titleA = a.title || '';
@@ -119,15 +191,60 @@ async function saveJobsDataToCMS() {
119
191
  }
120
192
  },
121
193
  });
122
-
123
194
  console.log(`✓ All chunks processed. Total jobs saved: ${totalSaved}/${jobsData.length}`);
124
195
  }
125
196
 
126
- async function saveJobsDescriptionsAndLocationApplyUrlToCMS() {
197
+ async function insertJobsReference(valueId) {
198
+ await wixData.insertReference(COLLECTIONS.CUSTOM_VALUES, CUSTOM_VALUES_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,valueId, Array.from(customValuesToJobs[valueId]));
199
+ }
200
+
201
+ async function populateCustomFieldsCollection(customFields,templateType) {
202
+ let fieldstoinsert=[]
203
+ customFields["employmentType"] = "Employment Type";
204
+ if(templateType===TEMPLATE_TYPE.INTERNAL){
205
+ customFields["Visibility"] = "Visibility";
206
+ }
207
+ for(const ID of Object.keys(customFields)){
208
+ fieldstoinsert.push({
209
+ title: customFields[ID],
210
+ _id: ID,
211
+ })
212
+ }
213
+ await wixData.bulkSave(COLLECTIONS.CUSTOM_FIELDS, fieldstoinsert);
214
+ }
215
+ async function populateCustomValuesCollection(customFieldsValues) {
216
+ let valuesToinsert=[]
217
+ for (const fieldId of Object.keys(customFieldsValues)) {
218
+ const valuesMap = customFieldsValues[fieldId] || {};
219
+ for (const valueId of Object.keys(valuesMap)) {
220
+ valuesToinsert.push({
221
+ _id: valueId,
222
+ title: valuesMap[valueId],
223
+ customField: fieldId,
224
+ count:customValuesToJobs[valueId].size,
225
+ jobIds:Array.from(customValuesToJobs[valueId]),
226
+ })
227
+ }
228
+
229
+ }
230
+ await wixData.bulkSave(COLLECTIONS.CUSTOM_VALUES, valuesToinsert);
231
+ }
232
+ async function saveJobsDescriptionsAndLocationApplyUrlReferencesToCMS() {
127
233
  console.log('🚀 Starting job descriptions update process for ALL jobs');
128
234
 
129
235
  try {
130
236
  let jobsWithNoDescriptions = await getJobsWithNoDescriptions();
237
+ if (siteconfig.customFields==="true") {
238
+ let customValues=await getAllCustomValues();
239
+ console.log("inserting jobs references to custom values collection");
240
+ console.log("customValues: ",customValues)
241
+ console.log("customValues.items: ",customValues.items)
242
+ for (const value of customValues.items) {
243
+ await insertJobsReference(value._id);
244
+ }
245
+ console.log("inserted jobs references to custom values collection successfully");
246
+ }
247
+
131
248
  let totalUpdated = 0;
132
249
  let totalFailed = 0;
133
250
  let totalProcessed = 0;
@@ -156,7 +273,7 @@ async function saveJobsDescriptionsAndLocationApplyUrlToCMS() {
156
273
  const jobLocation = fetchJobLocation(jobDetails);
157
274
  const {applyLink , referFriendLink} = fetchApplyAndReferFriendLink(jobDetails);
158
275
 
159
-
276
+
160
277
  const updatedJob = {
161
278
  ...job,
162
279
  locationAddress: jobLocation,
@@ -220,7 +337,7 @@ async function aggregateJobsByFieldToCMS({ field, collection }) {
220
337
  console.log(`counting jobs per ${field}.`);
221
338
  let results = await getAllPositions();
222
339
  const { jobsPerField, cityLocations,citylocationAddress } = iterateOverAllJobs(results, field);
223
- const toSave = prepareToSaveArray(jobsPerField, cityLocations, field,citylocationAddress);
340
+ const toSave = prepareToSaveArray(jobsPerField, cityLocations, field,citylocationAddress,locationToJobs);
224
341
  if (toSave.length === 0) {
225
342
  console.log('No jobs found.');
226
343
  return { success: true, message: 'No jobs to save.' };
@@ -236,7 +353,10 @@ async function aggregateJobsByFieldToCMS({ field, collection }) {
236
353
  return { success: false, error: err.message };
237
354
  }
238
355
  }
239
-
356
+ async function getAllCustomValues() {
357
+ let customValuesQuery = await wixData.query(COLLECTIONS.CUSTOM_VALUES).limit(1000).find();
358
+ return customValuesQuery;
359
+ }
240
360
  async function getJobsWithNoDescriptions() {
241
361
  let jobswithoutdescriptionsQuery = await wixData
242
362
  .query(COLLECTIONS.JOBS)
@@ -280,6 +400,7 @@ async function referenceJobsToField({ referenceField, sourceCollection, jobField
280
400
  return rest;
281
401
  });
282
402
 
403
+
283
404
  // Bulk update in chunks of 1000
284
405
  const chunkSize = 1000;
285
406
  await chunkedBulkOperation({
@@ -325,11 +446,13 @@ function fetchJobLocation(jobDetails) {
325
446
  async function createCollections() {
326
447
  console.log("Creating collections");
327
448
  await Promise.all(
328
- [createCollectionIfMissing(COLLECTIONS.JOBS, JOBS_COLLECTION_FIELDS.JOBS,{ insert: 'ADMIN', update: 'ADMIN', remove: 'ADMIN', read: 'ANYONE' }),
449
+ [createCollectionIfMissing(COLLECTIONS.JOBS, COLLECTIONS_FIELDS.JOBS,{ insert: 'ADMIN', update: 'ADMIN', remove: 'ADMIN', read: 'ANYONE' }),
329
450
  createCollectionIfMissing(COLLECTIONS.CITIES, COLLECTIONS_FIELDS.CITIES),
330
451
  createCollectionIfMissing(COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT, COLLECTIONS_FIELDS.AMOUNT_OF_JOBS_PER_DEPARTMENT),
331
452
  createCollectionIfMissing(COLLECTIONS.SECRET_MANAGER_MIRROR, COLLECTIONS_FIELDS.SECRET_MANAGER_MIRROR),
332
- createCollectionIfMissing(COLLECTIONS.BRANDS, COLLECTIONS_FIELDS.BRANDS)
453
+ createCollectionIfMissing(COLLECTIONS.BRANDS, COLLECTIONS_FIELDS.BRANDS),
454
+ createCollectionIfMissing(COLLECTIONS.CUSTOM_VALUES, COLLECTIONS_FIELDS.CUSTOM_VALUES),
455
+ createCollectionIfMissing(COLLECTIONS.CUSTOM_FIELDS, COLLECTIONS_FIELDS.CUSTOM_FIELDS)
333
456
  ]);
334
457
  console.log("finished creating Collections");
335
458
  }
@@ -346,9 +469,15 @@ async function aggregateJobs() {
346
469
 
347
470
  async function referenceJobs() {
348
471
  console.log("Reference jobs");
472
+ if(siteconfig===undefined) {
473
+ await getSiteConfig();
474
+ }
349
475
  await referenceJobsToField({ referenceField: JOBS_COLLECTION_FIELDS.DEPARTMENT_REF, sourceCollection: COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT, jobField: JOBS_COLLECTION_FIELDS.DEPARTMENT });
350
476
  await referenceJobsToField({ referenceField: JOBS_COLLECTION_FIELDS.CITY, sourceCollection: COLLECTIONS.CITIES, jobField: JOBS_COLLECTION_FIELDS.CITY_TEXT });
351
- await referenceJobsToField({ referenceField: JOBS_COLLECTION_FIELDS.BRAND_REF, sourceCollection: COLLECTIONS.BRANDS, jobField: JOBS_COLLECTION_FIELDS.BRAND });
477
+ if(siteconfig.disableMultiBrand==="false"){
478
+ await referenceJobsToField({ referenceField: JOBS_COLLECTION_FIELDS.BRAND_REF, sourceCollection: COLLECTIONS.BRANDS, jobField: JOBS_COLLECTION_FIELDS.BRAND });
479
+ }
480
+
352
481
  console.log("finished referencing jobs");
353
482
  }
354
483
 
@@ -357,24 +486,30 @@ async function syncJobsFast() {
357
486
  await createCollections();
358
487
  await clearCollections();
359
488
  await fillSecretManagerMirror();
489
+
360
490
  console.log("saving jobs data to CMS");
361
491
  await saveJobsDataToCMS();
362
492
  console.log("saved jobs data to CMS successfully");
493
+
363
494
  console.log("saving jobs descriptions and location apply url to CMS");
364
- await saveJobsDescriptionsAndLocationApplyUrlToCMS();
495
+ await saveJobsDescriptionsAndLocationApplyUrlReferencesToCMS();
496
+
365
497
  console.log("saved jobs descriptions and location apply url to CMS successfully");
366
498
  await aggregateJobs();
367
499
  await referenceJobs();
368
500
  console.log("syncing jobs fast finished successfully");
369
501
  }
370
502
 
503
+
371
504
  async function clearCollections() {
372
505
  console.log("clearing collections");
373
506
  await Promise.all([
374
507
  wixData.truncate(COLLECTIONS.CITIES),
375
508
  wixData.truncate(COLLECTIONS.AMOUNT_OF_JOBS_PER_DEPARTMENT),
376
509
  wixData.truncate(COLLECTIONS.JOBS),
377
- wixData.truncate(COLLECTIONS.BRANDS)
510
+ wixData.truncate(COLLECTIONS.BRANDS),
511
+ wixData.truncate(COLLECTIONS.CUSTOM_VALUES),
512
+ wixData.truncate(COLLECTIONS.CUSTOM_FIELDS),
378
513
  ]);
379
514
  console.log("cleared collections successfully");
380
515
  }
@@ -423,7 +558,7 @@ module.exports = {
423
558
  aggregateJobs,
424
559
  createCollections,
425
560
  saveJobsDataToCMS,
426
- saveJobsDescriptionsAndLocationApplyUrlToCMS,
561
+ saveJobsDescriptionsAndLocationApplyUrlReferencesToCMS,
427
562
  aggregateJobsByFieldToCMS,
428
563
  referenceJobsToField,
429
564
  fillSecretManagerMirror,
@@ -1,8 +1,9 @@
1
1
  const { fetch } = require('wix-fetch');
2
2
  const { TEMPLATE_TYPE,TOKEN_NAME } = require('./collectionConsts');
3
3
  const { getTokenFromCMS,getApiKeys } = require('./secretsData');
4
+
4
5
  async function makeSmartRecruitersRequest(path,templateType) {
5
- const baseUrl = 'https://api.smartrecruiters.com';
6
+ const baseUrl = 'https://api.smartrecruiters.com';
6
7
  const fullUrl = `${baseUrl}${path}`;
7
8
 
8
9
  try {
package/backend/index.js CHANGED
@@ -4,4 +4,6 @@ module.exports = {
4
4
  ...require('./fetchPositionsFromSRAPI'),
5
5
  ...require('./consts'),
6
6
  ...require('./data'),
7
+ ...require('./careersMultiBoxesPageIds'),
8
+ ...require ('./secretsData'),
7
9
  };
@@ -1,4 +1,4 @@
1
- const { COLLECTIONS } = require('./collectionConsts');
1
+ const { COLLECTIONS,JOBS_COLLECTION_FIELDS } = require('./collectionConsts');
2
2
  const { items: wixData } = require('@wix/data');
3
3
 
4
4
 
@@ -18,7 +18,11 @@ async function getPositionsByField(field, value) {
18
18
  .then(result => result.items);
19
19
  }
20
20
 
21
- module.exports = {
22
- getAllPositions,
23
- getPositionsByField,
24
- };
21
+ async function getPositionWithMultiRefField(jobId)
22
+ {
23
+ return wixData
24
+ .queryReferenced(COLLECTIONS.JOBS,jobId,JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES)
25
+ .then(result => result.items);
26
+ }
27
+
28
+ module.exports = { getAllPositions, getPositionsByField, getPositionWithMultiRefField };