diff --git a/adaptors/library/jobs/CommCare-FHIR.js b/adaptors/library/jobs/CommCare-FHIR.js index e4671535353f..4a9761a53fb9 100644 --- a/adaptors/library/jobs/CommCare-FHIR.js +++ b/adaptors/library/jobs/CommCare-FHIR.js @@ -1,108 +1,53 @@ // CommCare form submission mapped to the FHIR patient encounter standard, // submitted by Simon Kelly @ Dimagi. -encounter( - fields( - field('resourceType', 'Encounter'), - field('status', 'finished'), - field('type', function (state) { - return [ +encounter({ + resourceType: 'Encounter', + status: 'finished', + type: [{ coding: [{ system: 'momconnect:type', code: '8' }] }], + contained: [ + { + resourceType: 'Patient', + id: 'patient', + identifier: [ + { use: 'official', system: 'momconnect:sanid', value: $.data.properties.id_number }, + ], + name: [ { - coding: [ - { - system: 'momconnect:type', - code: '8', - }, - ], + use: 'official', + family: [$.data.properties.family_name], + given: [$.data.properties.given_name], + text: `${$.data.properties.given_name} ${$.data.properties.family_name}`, }, - ]; - }), - field('contained', function (state) { - return [ + ], + gender: 'female', + birthDate: $.data.properties.dob, + telecom: [{ system: 'phone', value: $.data.properties.msisdn }], + communication: [ { - resourceType: 'Patient', - id: 'patient', - identifier: [ - { - use: 'official', - system: 'momconnect:sanid', - value: dataValue('properties.id_number')(state), - }, - ], - name: [ - { - use: 'official', - family: [dataValue('properties.family_name')(state)], - given: [dataValue('properties.given_name')(state)], - text: dataValue('properties.given_name')(state).concat( - ' ', - dataValue('properties.family_name')(state) - ), - }, - ], - gender: 'female', - birthDate: dataValue('properties.dob')(state), - telecom: [ - { - system: 'phone', - value: dataValue('properties.msisdn')(state), - }, - ], - communication: [ - { - language: { - coding: [ - { - system: 'urn:ietf:bcp:47', - code: dataValue('properties.language_code')(state), - }, - ], - }, - preferred: true, - }, - ], - }, - { - resourceType: 'Observation', - id: 'edd', - code: { - coding: [ - { - system: 'http://loinc.org', - code: '11778-8', - display: 'Delivery date Estimated', - }, - ], + language: { + coding: [{ system: 'urn:ietf:bcp:47', code: $.data.properties.language_code }], }, - valueDateTime: dataValue('properties.edd')(state), - status: 'preliminary', - }, - ]; - }), - field('patient', function (state) { - return { - reference: '#patient', - }; - }), - field('period', function (state) { - return { - start: dataValue('properties.visit_date')(state), - }; - }), - field('extension', function (state) { - return [ - { - url: 'momconnect:mha', - valueInteger: 2, - }, - { - url: 'momconnect:swt', - valueInteger: 3, - }, - { - url: 'momconnect:dmsisdn', - valueString: '+27831111111', + preferred: true, }, - ]; - }) - ) -); + ], + }, + { + resourceType: 'Observation', + id: 'edd', + code: { + coding: [ + { system: 'http://loinc.org', code: '11778-8', display: 'Delivery date Estimated' }, + ], + }, + valueDateTime: $.data.properties.edd, + status: 'preliminary', + }, + ], + patient: { reference: '#patient' }, + period: { start: $.data.properties.visit_date }, + extension: [ + { url: 'momconnect:mha', valueInteger: 2 }, + { url: 'momconnect:swt', valueInteger: 3 }, + { url: 'momconnect:dmsisdn', valueString: '+27831111111' }, + ], +}); diff --git a/adaptors/library/jobs/Create-SMS-Linked-to-Contact-in-SF.js b/adaptors/library/jobs/Create-SMS-Linked-to-Contact-in-SF.js index 5c46f9602e6c..e57e7740b5ed 100644 --- a/adaptors/library/jobs/Create-SMS-Linked-to-Contact-in-SF.js +++ b/adaptors/library/jobs/Create-SMS-Linked-to-Contact-in-SF.js @@ -1,12 +1,6 @@ -create( - 'SMS__c', - fields( - field('text__c', dataValue('message_text')), - relationship( - 'Contact__r', - 'Contact_Phone_Number__c', - dataValue('from_number') - ), - field('date__c', dataValue('date')) - ) -); +// Create an SMS record in Salesforce linked to a Contact by phone number +create('SMS__c', { + text__c: $.data.message_text, + Contact__r: { Contact_Phone_Number__c: $.data.from_number }, + date__c: $.data.date, +}); diff --git a/adaptors/library/jobs/ODK-Create-Many-Records-Moving-In-And-Out-Of-Repeat-Blocks.js b/adaptors/library/jobs/ODK-Create-Many-Records-Moving-In-And-Out-Of-Repeat-Blocks.js index 1a16d46e4c3b..96eca8a8e2f6 100644 --- a/adaptors/library/jobs/ODK-Create-Many-Records-Moving-In-And-Out-Of-Repeat-Blocks.js +++ b/adaptors/library/jobs/ODK-Create-Many-Records-Moving-In-And-Out-Of-Repeat-Blocks.js @@ -3,53 +3,50 @@ blocks, submitted by Taylor Downs @ OpenFn. */ -beta.each( - '$.data.data[*]', - create( - 'ODK__c', - fields( - field('Event_Type__c', dataValue('event_type')), - field('Training_Type__c', dataValue('training_type')), - field('Event_Leader_ID__c', dataValue('leader')), - field('Event_Date__c', dataValue('date')), - field('metainstanceid__c', dataValue('*meta-instance-id*')) - ) - ) +// Step 1: Create a parent ODK record for each submission +each( + $.data.data, + create('ODK__c', { + Event_Type__c: $.data.event_type, + Training_Type__c: $.data.training_type, + Event_Leader_ID__c: $.data.leader, + Event_Date__c: $.data.date, + metainstanceid__c: $.data['*meta-instance-id*'], + }) ); -beta.each( - merge( - dataPath('data[*].attendee_new[*]'), - fields(field('parentId', lastReferenceValue('id'))) - ), - create( - 'ODK_Child_2__c', - fields( - field('ODK__c', dataValue('parentId')), - field('Barcode__c', dataValue('new_attendee_id')), - field('First_Name__c', dataValue('new_attendee_first_name')), - field('Last_Name__c', dataValue('new_attendee_last_name')), - field('Phone_Number__c', dataValue('new_attendee_phone')) - ) - ) +// Step 2: Flatten child records across all submissions, attaching the parent ID +fn(state => { + const parentId = state.references[state.references.length - 1].id; + return { + ...state, + newAttendees: state.data.data.flatMap(sub => + (sub.attendee_new || []).map(a => ({ ...a, parentId })) + ), + attendees: state.data.data.flatMap(sub => + (sub.attendee || []).map(a => ({ ...a, parentId })) + ), + }; +}); + +// Step 3: Create child records for new attendees +each( + $.newAttendees, + create('ODK_Child_2__c', { + ODK__c: $.data.parentId, + Barcode__c: $.data.new_attendee_id, + First_Name__c: $.data.new_attendee_first_name, + Last_Name__c: $.data.new_attendee_last_name, + Phone_Number__c: $.data.new_attendee_phone, + }) ); -beta.each( - merge( - dataPath('data[*].attendee[*]'), - fields( - field('parentId', function (state) { - return state.references[state.references.length - 1].id; - }) - // ^^ This will get the sfID of the 1st item created. - ) - ), - create( - 'ODK_Child_1__c', - fields( - field('ODK__c', dataValue('parentId')), - field('Barcode__c', dataValue('attendee_id')), - field('Late__c', dataValue('late')) - ) - ) +// Step 4: Create child records for existing attendees +each( + $.attendees, + create('ODK_Child_1__c', { + ODK__c: $.data.parentId, + Barcode__c: $.data.attendee_id, + Late__c: $.data.late, + }) ); diff --git a/adaptors/library/jobs/alter-state-before-operations.js b/adaptors/library/jobs/alter-state-before-operations.js index 9b3c103c583b..9ff06fed1bb6 100644 --- a/adaptors/library/jobs/alter-state-before-operations.js +++ b/adaptors/library/jobs/alter-state-before-operations.js @@ -1,31 +1,26 @@ -// Here, we make sure CommCare gives us an array to use in each(merge(...), ...) +// Pre-process: normalize data to an array and merge in parent-level fields. +// Use fn() + array.map() instead of merge() + dataPath() to enrich child items. fn(state => { - const idCards = state.data.form.ID_cards_given_to_vendor; - if (!Array.isArray(idCards)) { - state.data.form.ID_cards_given_to_vendor = [idCards]; - } - return state; + const { ID_cards_given_to_vendor, ID_vendor } = state.data.form; + const cards = Array.isArray(ID_cards_given_to_vendor) + ? ID_cards_given_to_vendor + : [ID_cards_given_to_vendor]; + + return { + ...state, + processedCards: cards.map(card => ({ + sp_id: card, + vendor_badge_code: ID_vendor, + distribution_date: state.data.form.meta.timeEnd, + })), + }; }); -// Now state has been changed, and we carry on... each( - merge( - dataPath('form.ID_cards_given_to_vendor[*]'), - fields( - field('Vendor_Id', dataValue('form.ID_vendor')), - field('form_finished_time', dataValue('form.meta.timeEnd')) - ) - ), - upsert( - 'Small_Packet__c', - 'sp_id__c', - fields( - field('sp_id__c', dataValue('ID_cards_given_to_vendor')), - relationship('Vendor__r', 'Badge_Code__c', dataValue('Vendor_Id')), - field( - 'Small_Packet_Distribution_Date__c', - dataValue('form_finished_time') - ) - ) - ) + $.processedCards, + upsert('Small_Packet__c', 'sp_id__c', { + sp_id__c: $.data.sp_id, + Vendor__r: { Badge_Code__c: $.data.vendor_badge_code }, + Small_Packet_Distribution_Date__c: $.data.distribution_date, + }) ); diff --git a/adaptors/library/jobs/async-and-array-dot-map.js b/adaptors/library/jobs/async-and-array-dot-map.js index 22c482c0cfe4..8d95bae6582b 100644 --- a/adaptors/library/jobs/async-and-array-dot-map.js +++ b/adaptors/library/jobs/async-and-array-dot-map.js @@ -1,63 +1,28 @@ +// Split large arrays into chunks, then post each chunk sequentially. +// Use separate each() calls instead of Promise.all with array.map. fn(state => { - console.log('Here we will await the result of a LOT of async operations.'); - - console.log('First we needed to break large arrays into smaller chunks.'); - function chunk(arr, chunkSize) { - var R = []; - for (var i = 0, len = arr.length; i < len; i += chunkSize) - R.push(arr.slice(i, i + chunkSize)); - return R; + function chunk(arr, size) { + const chunks = []; + for (let i = 0; i < arr.length; i += size) + chunks.push(arr.slice(i, i + size)); + return chunks; } - const clinicSets = chunk(state.data.Clinic, 10); - const patientSets = chunk(state.data.Patient, 10); - const visitSets = chunk(state.data.Visit, 10); - const deletedVisitSets = chunk(state.data.VisitDeleted, 10); - - console.log('Then we define a bunch of different async functions.'); - const postClinics = async cs => { - return post(state.configuration.inboxUrl, { - body: { clinics: cs }, - })(state); - }; - - const postPatients = async ps => { - return post(state.configuration.inboxUrl, { - body: { patients: ps }, - })(state); - }; - - const postVisits = async vs => { - return post(state.configuration.inboxUrl, { - body: { visits: vs }, - })(state); + return { + ...state, + clinicChunks: chunk($.data.Clinic, 10), + patientChunks: chunk($.data.Patient, 10), + visitChunks: chunk($.data.Visit, 10), + deletedVisitChunks: chunk($.data.VisitDeleted, 10), }; - - const postDeletedVisits = async dvs => { - return post(state.configuration.inboxUrl, { - body: { deletedVisits: dvs }, - })(state); - }; - - console.log( - 'Then we define a single function that wraps them all up and waits for all the individual functions to resolve.' - ); - async function makePosts() { - return Promise.all([ - ...clinicSets.map(item => postClinics(item)), - ...patientSets.map(item => postPatients(item)), - ...visitSets.map(item => postVisits(item)), - ...deletedVisitSets.map(item => postDeletedVisits(item)), - ]); - } - - console.log( - 'Then we return that function, forcing our next operation to await the result of this one.' - ); - return makePosts(); }); +each($.clinicChunks, post($.configuration.inboxUrl, { clinics: $.data })); +each($.patientChunks, post($.configuration.inboxUrl, { patients: $.data })); +each($.visitChunks, post($.configuration.inboxUrl, { visits: $.data })); +each($.deletedVisitChunks, post($.configuration.inboxUrl, { deletedVisits: $.data })); + fn(state => { - console.log('I show up AFTER those async functions are resolved.'); + console.log('All chunks posted successfully.'); return state; }); diff --git a/adaptors/library/jobs/async-findValue.js b/adaptors/library/jobs/async-findValue.js index a680b9aed1dc..da82749a76d6 100644 --- a/adaptors/library/jobs/async-findValue.js +++ b/adaptors/library/jobs/async-findValue.js @@ -1,35 +1,45 @@ -fn(async state => { - const dataArray = - state.data.body.st_grass_repeat || - state.data.body["plot_forest_area/st_grass_repeat"] || - []; - const dataGrass = []; +// For each item in the grass repeat array, look up a related Taxa ID with +// findValue, then upsert all the enriched records in a single operation. +fn(state => { const path = state.data.body.st_grass_repeat - ? "st_grass_repeat" - : "plot_forest_area/st_grass_repeat"; + ? 'st_grass_repeat' + : 'plot_forest_area/st_grass_repeat'; - for (let data of uniqueGrass) { - dataGrass.push({ - WCSPROGRAMS_TaxaID: await findValue({ - uuid: "WCSPROGRAMS_TaxaID", - relation: "WCSPROGRAMS_Taxa", - where: { - ScientificName: `%${state.handleValue( - data["st_grass_repeat/grass_species"] - )}%`, - }, - operator: { ScientificName: "like" }, - })(state), - UnknownSpeciesImage: data[`${path}/noknown`], - GrassPercent: data[`${path}/grass_perc`], - GrassHeight: data[`${path}/grass_height`], - AnswerId: state.data.body._id, - }); - } - - return upsertMany( - "WCSPROGRAMS_VegetationGrass", - "WCSPROGRAMS_VegetationGrassCode", - () => dataGrass - )(state); + state.grassPath = path; + state.answerId = state.data.body._id; + state.dataArray = state.data.body[path] || []; + state.dataGrass = []; + return state; }); + +each( + $.dataArray, + findValue({ + uuid: 'WCSPROGRAMS_TaxaID', + relation: 'WCSPROGRAMS_Taxa', + where: { + ScientificName: state => + `%${state.data[`${state.grassPath}/grass_species`]}%`, + }, + operator: { ScientificName: 'like' }, + }).then(state => { + const path = state.grassPath; + const item = state.dataArray[state.index]; + + // findValue writes the found uuid value to state.data + state.dataGrass.push({ + WCSPROGRAMS_TaxaID: state.data, + UnknownSpeciesImage: item[`${path}/noknown`], + GrassPercent: item[`${path}/grass_perc`], + GrassHeight: item[`${path}/grass_height`], + AnswerId: state.answerId, + }); + return state; + }) +); + +upsertMany( + 'WCSPROGRAMS_VegetationGrass', + 'WCSPROGRAMS_VegetationGrassCode', + state => state.dataGrass +); diff --git a/adaptors/library/jobs/bring-formId-into-data-array-then-create-parent-and-children-in-salesforce.js b/adaptors/library/jobs/bring-formId-into-data-array-then-create-parent-and-children-in-salesforce.js index 1fc698a9bdee..21a496ffdf91 100644 --- a/adaptors/library/jobs/bring-formId-into-data-array-then-create-parent-and-children-in-salesforce.js +++ b/adaptors/library/jobs/bring-formId-into-data-array-then-create-parent-and-children-in-salesforce.js @@ -1,78 +1,76 @@ +// Merge a top-level field into each array item using fn() + array.map(), +// then create parent and child records in Salesforce. + +// Step 1: Inject formId into each submission item +fn(state => ({ + ...state, + data: { + ...state.data, + data: state.data.data.map(item => ({ ...item, formId: state.data.formId })), + }, +})); + +// Step 2: Create a parent ODK submission record for each item each( - join('$.data.data[*]', '$.data.formId', 'formId'), - create( - 'ODK_Submission__c', - fields( - //bridgetest sandbox record type, comment out when not in use - field('RecordTypeId', '012J00000005hlb'), - //prduction record type, comment out when not in use - //field("RecordType", "XXXXXXXXXXXXXXXX"), - // or - //relationship("RecordType", "name", dataValue("recort_type_name")), - field('Record_Type_Name__c', dataValue('record_type_id')), - field('ODK_Form_Name__c', dataValue('formId')), - field('Site_School_ID_Number__c', dataValue('site')), - field('BT_Staff_ID__c', dataValue('recorded_by')), - field('Date__c', dataValue('today')), - field('Head_of_Household__c', dataValue('head_of_household')), - field( - 'Head_of_Household_Gender__c', - dataValue('head_of_household_gender') - ), - field('Head_of_Household_age__c', dataValue('head_of_household_age')), - field('Light_Source__c', dataValue('light_source')), - field('communication__c', dataValue('communication')), - field('transport__c', dataValue('transport')), - field( - 'number_of_children_in_household__c', - dataValue('number_of_children') - ), - field('school_visits__c', dataValue('school_visits')), - field('school_visit_reason__c', dataValue('school_visit_reason')), - field('Village__c', dataValue('village')), - field('ODK_Key__c', dataValue('*meta-instance-id*')) - ) - ) -), - each( - merge( - dataPath('individual_na[*]'), - fields( - field('metaId', dataValue('*meta-instance-id*')), - field('parentId', lastReferenceValue('id')), - field('village', dataValue('$data.village')) - ) + $.data.data, + create('ODK_Submission__c', { + RecordTypeId: '012J00000005hlb', + Record_Type_Name__c: $.data.record_type_id, + ODK_Form_Name__c: $.data.formId, + Site_School_ID_Number__c: $.data.site, + BT_Staff_ID__c: $.data.recorded_by, + Date__c: $.data.today, + Head_of_Household__c: $.data.head_of_household, + Head_of_Household_Gender__c: $.data.head_of_household_gender, + Head_of_Household_age__c: $.data.head_of_household_age, + Light_Source__c: $.data.light_source, + communication__c: $.data.communication, + transport__c: $.data.transport, + number_of_children_in_household__c: $.data.number_of_children, + school_visits__c: $.data.school_visits, + school_visit_reason__c: $.data.school_visit_reason, + Village__c: $.data.village, + ODK_Key__c: $.data['*meta-instance-id*'], + }) +); + +// Step 3: Flatten child individual records, attaching the parent Salesforce ID +fn(state => { + const parentId = state.references[state.references.length - 1].id; + return { + ...state, + individuals: state.data.data.flatMap((sub, _i) => + (sub.individual_na || []).map((child, j) => ({ + ...child, + metaId: sub['*meta-instance-id*'], + parentId, + village: sub.village, + childIndex: j, + })) ), - create( - 'ODK_Submission__c', - fields( - //bridgetest sandbox record type, comment out when not in use - field('RecordTypeId', '012J00000005hla'), - //prduction record type, comment out when not in use - //field("RecordType", "XXXXXXXXXXXXXXXX"), - // or - //relationship("RecordType", "name", dataValue("recort_type_name")), - field('Related_ODK_Submission__c', dataValue('parentId')), - field('family_name__c', dataValue('given_name')), - field('school_coded__c', dataValue('school_coded')), - field('school_type__c', dataValue('school_type')), - field('gender__c', dataValue('gender')), - field('Pays_School_Fees__c', dataValue('school_fees_yes_no')), - field('in_primary_school__c', dataValue('in_primary_school')), - field('School_Fee_Amount__c', dataValue('school_fees')), - field('Age__c', dataValue('age')), - field('surname__c', dataValue('surname')), - field('out_of_school_reason__c', dataValue('out_of_school_reason')), - field('class_level__c', dataValue('class_level')), - field( - 'other_out_of_school_reason__c', - dataValue('other_out_of_school_reason') - ), - field('Village__c', dataValue('village')), - // This is a concatenation, adding the unique child ID. - field('ODK_Key__c', function (state) { - return dataValue('metaId')(state).concat('(', index()(state), ')'); - }) - ) - ) - ); + }; +}); + +// Step 4: Create child individual records +each( + $.individuals, + create('ODK_Submission__c', { + RecordTypeId: '012J00000005hla', + Related_ODK_Submission__c: $.data.parentId, + family_name__c: $.data.given_name, + school_coded__c: $.data.school_coded, + school_type__c: $.data.school_type, + gender__c: $.data.gender, + Pays_School_Fees__c: $.data.school_fees_yes_no, + in_primary_school__c: $.data.in_primary_school, + School_Fee_Amount__c: $.data.school_fees, + Age__c: $.data.age, + surname__c: $.data.surname, + out_of_school_reason__c: $.data.out_of_school_reason, + class_level__c: $.data.class_level, + other_out_of_school_reason__c: $.data.other_out_of_school_reason, + Village__c: $.data.village, + // Concatenate unique child ID using parent meta ID and child index + ODK_Key__c: `${$.data.metaId}(${$.data.childIndex})`, + }) +); diff --git a/adaptors/library/jobs/complex-http-request-chains.js b/adaptors/library/jobs/complex-http-request-chains.js index eb81b091d2e5..5a60fef812e7 100644 --- a/adaptors/library/jobs/complex-http-request-chains.js +++ b/adaptors/library/jobs/complex-http-request-chains.js @@ -1,25 +1,18 @@ +// Chain multiple HTTP requests per array item. The first request runs as a +// top-level operation, then we use .then() to run the follow-up requests. each( - dataPath('someArray[*]'), - post( - 'https://en7a5l7u3izq6.x.pipedream.net/', - { - body: state => { - return { name: state.data.surname, age: state.data.age }; - }, - }, - state => { - console.log('in the callback'); - console.log(state.data); - get( - 'https://en7a5l7u3izq6.x.pipedream.net/', - {}, - // Note how we don't use: `put(args)(state)` because state is already - // provided by the parent operation, get(), to its callback... - put('https://en7a5l7u3izq6.x.pipedream.net/') - // ...but since we've called get() INSIDE an anonymous function, we'll - // need to pass state to it manually: get(args)(state)... - )(state); - return state; - } - ) + $.data.someArray, + post('https://en7a5l7u3izq6.x.pipedream.net/', { + name: $.data.surname, + age: $.data.age, + }).then(async state => { + console.log('posted:', state.data); + + // Step 2: GET a resource using the POST result + state = await get('https://en7a5l7u3izq6.x.pipedream.net/', {})(state); + console.log('got:', state.data); + + // Step 3: PUT using the GET result + return put('https://en7a5l7u3izq6.x.pipedream.net/')(state); + }) ); diff --git a/adaptors/library/jobs/complex-state-control.js b/adaptors/library/jobs/complex-state-control.js index 205e047ae3ae..3e788b3028cf 100644 --- a/adaptors/library/jobs/complex-state-control.js +++ b/adaptors/library/jobs/complex-state-control.js @@ -1,19 +1,12 @@ -// Example with language-salesforce +// Example with language-salesforce: use top-level sequential operations +// instead of wrapping in a Promise. +query('SELECT Name FROM Account'); + fn(state => { - // return state => { - return new Promise((resolve, reject) => { - query('SELECT Name FROM Account')(state) - .then(state => { - console.log(state.references[0].records); - console.log('doing stuff here'); - return state; - }) - .then(state => { - console.log('and in here'); - resolve(state); - }); - }); - // }; + console.log(state.references[0].records); + console.log('doing stuff here'); + console.log('and in here'); + return state; }); fn(state => { diff --git a/adaptors/library/jobs/concatenate-many-fields-with-nulls.js b/adaptors/library/jobs/concatenate-many-fields-with-nulls.js index b5f266e7989c..52edc84ff6fb 100644 --- a/adaptors/library/jobs/concatenate-many-fields-with-nulls.js +++ b/adaptors/library/jobs/concatenate-many-fields-with-nulls.js @@ -1,646 +1,324 @@ +// Use array.filter(Boolean).join(',') instead of arrayToString() with function(state) +// wrappers. Replace fields()/field()/relationship()/dataValue() with a plain object. each( - '$.data.data[*]', - create( - 'Verification__c', - fields( - field('RecordTypeId', '01236000000Q6PT'), - relationship( - 'Supplier__r', - 'Unique_Entity_ID__c', - dataValue('Unique_Entity_ID') - ), - field('Currency_ISO_Code__c', dataValue('Currency_ISO_Code')), - field('Date_Conducted__c', dataValue('Date_Conducted')), - field('ODK_Key__c', dataValue('*meta-instance-id*')), - field('Unique_Entity_ID__c', dataValue('Unique_Entity_ID')), - field('Interviewee__c', dataValue('Interviewee')), - field('Interviewee_Role__c', dataValue('Interviewee_Role')), - field( - 'Interviewee_Primary_Phone__c', - dataValue('Interviewee_Primary_Phone') - ), - field('Interviewee_Phone_2__c', dataValue('Interviewee_Phone_2')), - field('Interviewee_Phone_3__c', dataValue('Interviewee_Phone_3')), - field( - 'Interviewee_Primary_Email__c', - dataValue('Interviewee_Primary_Email') - ), - field('Trade_Name__c', dataValue('Trade_Name')), - field('Registered_Name__c', dataValue('Registered_Name')), - field('Location_Description__c', dataValue('Location_Description')), - field('Main_Office_Country__c', dataValue('Main_Office_Country')), - field('Main_Office_Region_Province_or_County__c', function (state) { - return arrayToString( - [ - dataValue('Main_Office_Region_Province_or_County_a')(state), - dataValue('Main_Office_Region_Province_or_County_b')(state), - dataValue('Main_Office_Region_Province_or_County_c')(state), - dataValue('Main_Office_Region_Province_or_County_d')(state), - ].filter(Boolean), - ',' - ); - }), - field('Main_Office_City__c', function (state) { - return arrayToString( - [ - dataValue('Main_Office_City_a')(state), - dataValue('Main_Office_City_b')(state), - dataValue('Main_Office_City_c')(state), - dataValue('Main_Office_City_d')(state), - ].filter(Boolean), - ',' - ); - }), - field( - 'Main_Office_Street_Address__c', - dataValue('Main_Office_Street_Address') - ), - field('Geolocation__Latitude__s', dataValue('gps:Latitude')), - field('Geolocation__Longitude__s', dataValue('gps:Longitude')), - field('Main_Contact_First__c', dataValue('Main_Contact_First')), - field('Main_Contact_Last__c', dataValue('Main_Contact_Last')), - field('Main_Contact_Role__c', dataValue('Main_Contact_Role')), - field('Main_Contact_Role_Other__c', dataValue('Main_Contact_Role_Other')), - field( - 'Main_Contact_Phone_Mobile__c', - dataValue('Main_Contact_Phone_Mobile') - ), - field('Main_Contact_Phone_Work__c', dataValue('Main_Contact_Phone_Work')), - field( - 'Main_Contact_Phone_Other__c', - dataValue('Main_Contact_Phone_Other') - ), - field('Main_Contact_Email_Work__c', dataValue('Main_Contact_Email_Work')), - field('General_Phone__c', dataValue('General_Phone')), - field('General_Email__c', dataValue('General_Email')), - field('Website__c', dataValue('Website')), - field('Interest_in_Website__c', dataValue('Interest_in_Website')), - field( - 'Hours_of_Operation_Start__c', - dataValue('Hours_of_Operation_Start') - ), - field('Hours_of_Operation_End__c', dataValue('Hours_of_Operation_End')), - field( - 'Hours_of_Operation_Other__c', - dataValue('Hours_of_Operation_Other') - ), - field( - 'Hours_of_Operation_Other_Start__c', - dataValue('Hours_of_Operation_Other_Start') - ), - field( - 'Hours_of_Operation_Other_End__c', - dataValue('Hours_of_Operation_Other_End') - ), - field( - 'Goods_and_Services_Description__c', - dataValue('Goods_and_Services_Description') - ), - field('Primary_Sector__c', dataValue('Primary_Sector')), - field('Primary_Subsectors__c', function (state) { - return arrayToString( - [ - dataValue('Primary_Subsectors_1')(state), - dataValue('Primary_Subsectors_2')(state), - dataValue('Primary_Subsectors_3')(state), - dataValue('Primary_Subsectors_4')(state), - dataValue('Primary_Subsectors_5')(state), - dataValue('Primary_Subsectors_6')(state), - dataValue('Primary_Subsectors_7')(state), - dataValue('Primary_Subsectors_8')(state), - dataValue('Primary_Subsectors_9')(state), - dataValue('Primary_Subsectors_10')(state), - dataValue('Primary_Subsectors_l1')(state), - dataValue('Primary_Subsectors_12')(state), - dataValue('Primary_Subsectors_13')(state), - dataValue('Primary_Subsectors_14')(state), - dataValue('Primary_Subsectors_15')(state), - dataValue('Primary_Subsectors_16')(state), - dataValue('Primary_Subsectors_17')(state), - dataValue('Primary_Subsectors_18')(state), - dataValue('Primary_Subsectors_19')(state), - dataValue('Primary_Subsectors_20')(state), - dataValue('Primary_Subsectors_21')(state), - ].filter(Boolean), - ',' - ); - }), - field('Other_Sectors__c', function (state) { - return arrayToString(dataValue('Other_Sectors')(state), ','); - }), - field('Other_Subsectors__c', function (state) { - return arrayToString( - [ - dataValue('Other_Subsectors_1')(state), - dataValue('Other_Subsectors_2')(state), - dataValue('Other_Subsectors_3')(state), - dataValue('Other_Subsectors_4')(state), - dataValue('Other_Subsectors_5')(state), - dataValue('Other_Subsectors_6')(state), - dataValue('Other_Subsectors_7')(state), - dataValue('Other_Subsectors_8')(state), - dataValue('Other_Subsectors_9')(state), - dataValue('Other_Subsectors_10')(state), - dataValue('Other_Subsectors_l1')(state), - dataValue('Other_Subsectors_12')(state), - dataValue('Other_Subsectors_13')(state), - dataValue('Other_Subsectors_14')(state), - dataValue('Other_Subsectors_15')(state), - dataValue('Other_Subsectors_16')(state), - dataValue('Other_Subsectors_17')(state), - dataValue('Other_Subsectors_18')(state), - dataValue('Other_Subsectors_19')(state), - dataValue('Other_Subsectors_20')(state), - dataValue('Other_Subsectors_21')(state), - ].filter(Boolean), - ',' - ); - }), - field( - 'Entity_and_Registration_1__c', - dataValue('Entity_and_Registration_1') - ), - field( - 'Entity_and_Registration_2__c', - dataValue('Entity_and_Registration_2') - ), - field( - 'Entity_and_Registration_3__c', - dataValue('Entity_and_Registration_3') - ), - field('Registration_Date__c', dataValue('Registration_Date')), - field('Registration_Active__c', dataValue('Registration_Active')), - field( - 'Business_Operation_Licenses__c', - dataValue('Business_Operation_Licenses') - ), - field( - 'Business_Operation_Certificates__c', - dataValue('Business_Operation_Certificates') - ), - field('Association_Memberships__c', dataValue('Association_Memberships')), - field('Vendor_List_Memberships__c', dataValue('Vendor_List_Memberships')), - field('Has_Marketing_Plan__c', dataValue('Has_Marketing_Plan')), - field('Number_of_Competitors__c', dataValue('Number_of_Competitors')), - field('Start_of_Operations__c', dataValue('Start_of_Operations')), - field('Primary_Language__c', dataValue('Primary_Language')), - field('Primary_Language_Other__c', dataValue('Primary_Language_Other')), - field('English_Speakers__c', dataValue('English_Speakers')), - field('Other_Languages__c', dataValue('Other_Languages')), - field( - 'Frequency_of_Internet_Access__c', - dataValue('Frequency_of_Internet_Access') - ), - field( - 'Method_of_Internet_Access__c', - dataValue('Method_of_Internet_Access') - ), - field( - 'Method_of_Internet_Access_Other__c', - dataValue('Method_of_Internet_Access_Other') - ), - field('Frequency_of_Email_Use__c', dataValue('Frequency_of_Email_Use')), - field('Type_of_Email_Use__c', dataValue('Type_of_Email_Use')), - field('Counties_Regions_Serviced__c', function (state) { - return arrayToString( - [ - dataValue('Counties_Regions_Serviced_a')(state), - dataValue('Counties_Regions_Serviced_b')(state), - dataValue('Counties_Regions_Serviced_c')(state), - dataValue('Counties_Regions_Serviced_d')(state), - ].filter(Boolean), - ',' - ); - }), - field('Additional_Branches__c', dataValue('Additional_Branches')), - field('Branch_Locations__c', function (state) { - return arrayToString( - [ - dataValue('Branch_Locations_a')(state), - dataValue('Branch_Locations_b')(state), - dataValue('Branch_Locations_c')(state), - dataValue('Branch_Locations_d')(state), - ].filter(Boolean), - ',' - ); - }), - field( - 'Majority_Local_or_Foreign__c', - dataValue('Majority_Local_or_Foreign') - ), - field('Num_of_Owners__c', dataValue('Num_of_Owners')), - field('Num_of_Female_Owners__c', dataValue('Num_of_Female_Owners')), - field('Num_of_Male_Owners__c', dataValue('Num_of_Male_Owners')), - field( - 'Primary_Owner_is_Same_as_Main_Contact__c', - dataValue('Primary_Owner_is_Same_as_Main_Contact') - ), - field('Primary_Owner__c', dataValue('Primary_Owner')), - field('Primary_Owner_Gender__c', dataValue('Primary_Owner_Gender')), - field( - 'Primary_Owner_Gender_Other__c', - dataValue('Primary_Owner_Gender_Other') - ), - field( - 'Primary_Owner_Nationality__c', - dataValue('Primary_Owner_Nationality') - ), - field( - 'Primary_Owner_Phone_Mobile__c', - dataValue('Primary_Owner_Phone_Mobile') - ), - field( - 'Primary_Owner_Phone_Work__c', - dataValue('Primary_Owner_Phone_Work') - ), - field( - 'Primary_Owner_Phone_Other__c', - dataValue('Primary_Owner_Phone_Other') - ), - field('Primary_Owner_Email__c', dataValue('Primary_Owner_Email')), - field('Num_of_Businesses_Owned__c', dataValue('Num_of_Businesses_Owned')), - field( - 'Names_of_Businesses_Owned__c', - dataValue('Names_of_Businesses_Owned') - ), - field('Num_of_Managers__c', dataValue('Num_of_Managers')), - field('Num_of_Female_Managers__c', dataValue('Num_of_Female_Managers')), - field('Num_of_Male_Managers__c', dataValue('Num_of_Male_Managers')), - field('Finance_Management__c', dataValue('Finance_Management')), - field( - 'Finance_Management_Other__c', - dataValue('Finance_Management_Other') - ), - field('Dedicated_HR_Manager__c', dataValue('Dedicated_HR_Manager')), - field( - 'Num_of_Permanent_Full_Time_Employees__c', - dataValue('Num_of_Permanent_Full_Time_Employees') - ), - field( - 'Num_of_Perm_Full_Time_Female_Employees__c', - dataValue('Num_of_Perm_Full_Time_Female_Employees') - ), - field( - 'Num_of_Perm_Full_Time_Male_Employees__c', - dataValue('Num_of_Perm_Full_Time_Male_Employees') - ), - field( - 'Num_of_Full_Time_Temporary_Employees__c', - dataValue('Num_of_Full_Time_Temporary_Employees') - ), - field( - 'Num_of_Full_Time_Temp_Female_Employees__c', - dataValue('Num_of_Full_Time_Temp_Female_Employees') - ), - field( - 'Num_of_Full_Time_Temp_Male_Employees__c', - dataValue('Num_of_Full_Time_Temp_Male_Employees') - ), - field( - 'Num_of_Local_Staff_Full_Part_Time__c', - dataValue('Num_of_Local_Staff_Full_Part_Time') - ), - field( - 'Num_of_Expatriate_Staff_Full_Part_Time__c', - dataValue('Num_of_Expatriate_Staff_Full_Part_Time') - ), - field( - 'International_Client_in_Past_Six_Months__c', - dataValue('International_Client_in_Past_Six_Months') - ), - field('Principal_Client_Name__c', dataValue('Principal_Client_Name')), - field( - 'Foreign_or_Domestic_Principal_Client__c', - dataValue('Foreign_or_Domestic_Principal_Client') - ), - field('Principal_Client_Sector__c', dataValue('Principal_Client_Sector')), - field( - 'Goods_Services_Provided_to_this_Client__c', - dataValue('Goods_Services_Provided_to_this_Client') - ), - field( - 'End_of_Last_Contract_with_this_Client__c', - dataValue('End_of_Last_Contract_with_this_Client') - ), - field( - 'Value_Goods_Services_Sold_Last_6_Months__c', - dataValue('Value_Goods_Services_Sold_Last_6_Months') - ), - field( - 'Value_Goods_Sold_Last_6_Months_USD__c', - dataValue('Value_Goods_Sold_Last_6_Months_USD') - ), - field( - 'Access_to_Finance_Constraint_Ranking__c', - dataValue('Access_to_Finance_Constraint_Ranking') - ), - field('Bank_Account__c', dataValue('Bank_Account')), - field('Bank_Guarantee__c', dataValue('Bank_Guarantee')), - field( - 'Satisfied_with_Current_Bank__c', - dataValue('Satisfied_with_Current_Bank') - ), - field( - 'Describe_Satisfaction_with_Current_Bank__c', - dataValue('Describe_Satisfaction_with_Current_Bank') - ), - field( - 'Has_Received_a_Formal_Loan__c', - dataValue('Has_Received_a_Formal_Loan') - ), - field('Formal_Loan_Provider__c', dataValue('Formal_Loan_Provider')), - field( - 'Formal_Loan_Amount_Received__c', - dataValue('Formal_Loan_Amount_Received') - ), - field( - 'Formal_Loan_Amount_Received_USD__c', - dataValue('Formal_Loan_Amount_Received_USD') - ), - field( - 'Date_Formal_Loan_Received__c', - dataValue('Date_Formal_Loan_Received') - ), - field('Formal_Loan_Purpose__c', dataValue('Formal_Loan_Purpose')), - field( - 'Formal_Loan_Purpose_Other__c', - dataValue('Formal_Loan_Purpose_Other') - ), - field('Formal_Loan_Repaid__c', dataValue('Formal_Loan_Repaid')), - field('Interested_in_Loan__c', dataValue('Interested_in_Loan')), - field('Interested_Loan_Amount__c', dataValue('Interested_Loan_Amount')), - field( - 'Interested_Loan_Amount_USD__c', - dataValue('Interested_Loan_Amount_USD') - ), - field( - 'Interested_Loan_Duration__c', - dataValue('Interested_Loan_Duration') - ), - field('Interested_Loan_Purpose__c', dataValue('Interested_Loan_Purpose')), - field( - 'Interested_Loan_Purpose_Other__c', - dataValue('Interested_Loan_Purpose_Other') - ), - field( - 'Formal_Loan_Confidence_Ranking__c', - dataValue('Formal_Loan_Confidence_Ranking') - ), - field( - 'Received_Loan_from_Family_Friends__c', - dataValue('Received_Loan_from_Family_Friends') - ), - field( - 'Family_Friend_Loan_Amount__c', - dataValue('Family_Friend_Loan_Amount') - ), - field( - 'Family_Friend_Loan_Amount_USD__c', - dataValue('Family_Friend_Loan_Amount_USD') - ), - field( - 'Received_Loan_from_Informal_Lenders__c', - dataValue('Received_Loan_from_Informal_Lenders') - ), - field( - 'Informal_Lender_Loan_Amount__c', - dataValue('Informal_Lender_Loan_Amount') - ), - field( - 'Informal_Lender_Loan_Amount_USD__c', - dataValue('Informal_Lender_Loan_Amount_USD') - ), - field( - 'Interested_in_Investor_Business_Partner__c', - dataValue('Interested_in_Investor_Business_Partner') - ), - field( - 'Total_Turnover_Previous_Month__c', - dataValue('Total_Turnover_Previous_Month') - ), - field( - 'Total_Turnover_Previous_Month_USD__c', - dataValue('Total_Turnover_Previous_Month_USD') - ), - field( - 'Total_Turnover_Previous_Fiscal_Year__c', - dataValue('Total_Turnover_Previous_Fiscal_Year') - ), - field( - 'Total_Turnover_Previous_Fiscal_Yr_USD__c', - dataValue('Total_Turnover_Previous_Fiscal_Yr_USD') - ), - field( - 'Total_Profit_Previous_Fiscal_Year__c', - dataValue('Total_Profit_Previous_Fiscal_Year') - ), - field( - 'Total_Profit_Previous_Fiscal_Year_USD__c', - dataValue('Total_Profit_Previous_Fiscal_Year_USD') - ), - field( - 'Accepted_Modes_of_Payment__c', - dataValue('Accepted_Modes_of_Payment') - ), - field( - 'Accepted_Modes_of_Payment_Other__c', - dataValue('Accepted_Modes_of_Payment_Other') - ), - field( - 'Avg_Expen_Spent_on_Imported_Goods_Year__c', - dataValue('Avg_Expen_Spent_on_Imported_Goods_Year') - ), - field( - 'Avg_Expen_Spent_on_Domestic_Goods_Year__c', - dataValue('Avg_Expen_Spent_on_Domestic_Goods_Year') - ), - field( - 'Avg_Expen_on_Domestic_Suppliers_Year__c', - dataValue('Avg_Expen_on_Domestic_Suppliers_Year') - ), - field( - 'Avg_Expen_on_Intl_Suppliers_Year__c', - dataValue('Avg_Expen_on_Intl_Suppliers_Year') - ), - field( - 'Avg_Expen_Spent_on_Salaries_Year__c', - dataValue('Avg_Expen_Spent_on_Salaries_Year') - ), - field( - 'Balance_Sheet_Statement_Available__c', - dataValue('Balance_Sheet_Statement_Available') - ), - field('Profit_Loss_Statement__c', dataValue('Profit_Loss_Statement')), - field('Directly_Imports_Goods__c', dataValue('Directly_Imports_Goods')), - field( - 'Avg_of_Total_Costs_from_Imports__c', - dataValue('Avg_of_Total_Costs_from_Imports') - ), - field('Highest_Costing_Import__c', dataValue('Highest_Costing_Import')), - field( - 'Origin_Country_of_Highest_Costing_Import__c', - dataValue('Origin_Country_of_Highest_Costing_Import') - ), - field('Other_Import_Countries__c', dataValue('Other_Import_Countries')), - field('Exports_Products__c', dataValue('Exports_Products')), - field( - 'Avg_of_Total_Revenue_from_Exports__c', - dataValue('Avg_of_Total_Revenue_from_Exports') - ), - field('Primary_Export__c', dataValue('Primary_Export')), - field('Destination_of_Exports__c', dataValue('Destination_of_Exports')), - field( - 'Profits_Expectation_Next_Six_Months__c', - dataValue('Profits_Expectation_Next_Six_Months') - ), - field( - 'Staff_Expectation_Next_Six_Months__c', - dataValue('Staff_Expectation_Next_Six_Months') - ), - field( - 'Int_l_Entities_Represent_Good_Opp__c', - dataValue('Int_l_Entities_Represent_Good_Opp') - ), - field( - 'Int_l_Concessionaires_Represent_Good_Opp__c', - dataValue('Int_l_Concessionaires_Represent_Good_Opp') - ), - field( - 'Sectors_Representing_Best_Local_Opps__c', - dataValue('Sectors_Presenting_Best_Local_Opps') - ), - field( - 'Obstacle_Working_with_Intl_Entities__c', - dataValue('Obstacle_Working_with_Intl_Entities') - ), - field( - 'Biggest_Challenge_Next_6_Months__c', - dataValue('Biggest_Challenge_Next_6_Months') - ), - field( - 'Second_Biggest_Challenge_Next_6_Months__c', - dataValue('Second_Biggest_Challenge_Next_6_Months') - ), - field( - 'Financial_Management_Ranking__c', - dataValue('Financial_Management_Ranking') - ), - field( - 'Access_to_Finance_Ranking__c', - dataValue('Access_to_Finance_Ranking') - ), - field('Administration_Ranking__c', dataValue('Administration_Ranking')), - field('Human_Resources_Ranking__c', dataValue('Human_Resources_Ranking')), - field( - 'Technical_Expertise_Ranking__c', - dataValue('Technical_Expertise_Ranking') - ), - field( - 'Training_Helps_Efficiency__c', - dataValue('Training_Helps_Efficiency') - ), - field( - 'Capacity_Building_Activities_Offered__c', - dataValue('Capacity_Building_Activities_Offered') - ), - field( - 'Capacity_Building_Offered_Other__c', - dataValue('Capacity_Building_Offered_Other') - ), - field( - 'Can_Provide_Quotations_WP_on_Request__c', - dataValue('Can_Provide_Quotations_WP_on_Request') - ), - field('Knows_What_a_Tender_is__c', dataValue('Knows_What_a_Tender_is')), - field( - 'Frequency_Checking_for_Tenders__c', - dataValue('Frequency_Checking_for_Tenders') - ), - field( - 'Has_Submitted_a_Tender_Bid__c', - dataValue('Has_Submitted_a_Tender_Bid') - ), - field( - 'Has_Won_Tenders_in_Past_Six_Months__c', - dataValue('Has_Won_Tenders_in_Past_Six_Months') - ), - field( - 'Details_of_Recently_Won_Tenders__c', - dataValue('Details_of_Recently_Won_Tenders') - ), - field( - 'Num_of_Gov_t_Bids_in_Last_Six_Months__c', - dataValue('Num_of_Govt_Bids_in_Last_Six_Months') - ), - field( - 'Num_of_Private_Bids_in_Last_Six_Months__c', - dataValue('Num_of_Private_Bids_in_Last_Six_Months') - ), - field( - 'Num_of_NGO_INGO_IO_Bids_Last_Six_Months__c', - dataValue('Num_of_NGO_INGO_IO_Bids_Last_Six_Months') - ), - field( - 'Main_Reason_for_Lost_Bids__c', - dataValue('Main_Reason_for_Lost_Bids') - ), - field( - 'Main_Reason_for_Lost_Bids_Other__c', - dataValue('Main_Reason_for_Lost_Bids_Other__c') - ), - field( - 'Main_Reason_for_Not_Bidding_on_Tenders__c', - dataValue('Main_Reason_for_Not_Bidding_on_Tenders') - ), - field( - 'Main_Reason_Not_Bidding_Tenders_Others__c', - dataValue('Main_Reason_Not_Bidding_Tenders_Others__c') - ), - field( - 'Planning_to_Bid_on_Future_Tenders__c', - dataValue('Planning_to_Bid_on_Tenders_in_the_Future') - ), - field( - 'Services_That_Would_Help_to_Win_Tenders__c', - dataValue('Services_That_Would_Help_to_Win_Tenders') - ), - field( - 'Interested_in_Future_BM_Communications__c', - dataValue('Interested_in_Future_BM_Communications') - ), - field( - 'Future_BM_Communications__c', - dataValue('Future_BM_Communications') - ), - field( - 'Interested_in_Attending_Future_Training__c', - dataValue('Interested_in_Attending_Future_Training') - ), - field( - 'Training_Most_Interested_in_Attending__c', - dataValue('Training_Most_Interested_in_Attending') - ), - field( - 'Training_Most_Interested_in_Other__c', - dataValue('Training_Most_Interested_in_Other') - ), - field( - 'Amount_Willing_to_Pay_for_Training__c', - dataValue('Amount_Willing_to_Pay_for_Training') - ), - field( - 'Amount_Willing_to_Pay_for_Training__c', - dataValue('Amount_Willing_to_Pay_for_Training') - ), - field( - 'Training_Interested_In_but_Not_Offered__c', - dataValue('Training_Interested_In_but_Not_Offered') - ), - field( - 'Advice_to_Entrepreneurs_in_your_Country__c', - dataValue('Advice_to_Entrepreneurs_in_your_Country') - ), - field('Interviewer_Comments__c', dataValue('Interviewer_Comments')) - ) - ) + $.data.data, + create('Verification__c', { + RecordTypeId: '01236000000Q6PT', + Supplier__r: { Unique_Entity_ID__c: $.data.Unique_Entity_ID }, + Currency_ISO_Code__c: $.data.Currency_ISO_Code, + Date_Conducted__c: $.data.Date_Conducted, + ODK_Key__c: $.data['*meta-instance-id*'], + Unique_Entity_ID__c: $.data.Unique_Entity_ID, + Interviewee__c: $.data.Interviewee, + Interviewee_Role__c: $.data.Interviewee_Role, + Interviewee_Primary_Phone__c: $.data.Interviewee_Primary_Phone, + Interviewee_Phone_2__c: $.data.Interviewee_Phone_2, + Interviewee_Phone_3__c: $.data.Interviewee_Phone_3, + Interviewee_Primary_Email__c: $.data.Interviewee_Primary_Email, + Trade_Name__c: $.data.Trade_Name, + Registered_Name__c: $.data.Registered_Name, + Location_Description__c: $.data.Location_Description, + Main_Office_Country__c: $.data.Main_Office_Country, + Main_Office_Region_Province_or_County__c: [ + $.data.Main_Office_Region_Province_or_County_a, + $.data.Main_Office_Region_Province_or_County_b, + $.data.Main_Office_Region_Province_or_County_c, + $.data.Main_Office_Region_Province_or_County_d, + ].filter(Boolean).join(','), + Main_Office_City__c: [ + $.data.Main_Office_City_a, + $.data.Main_Office_City_b, + $.data.Main_Office_City_c, + $.data.Main_Office_City_d, + ].filter(Boolean).join(','), + Main_Office_Street_Address__c: $.data.Main_Office_Street_Address, + Geolocation__Latitude__s: $.data['gps:Latitude'], + Geolocation__Longitude__s: $.data['gps:Longitude'], + Main_Contact_First__c: $.data.Main_Contact_First, + Main_Contact_Last__c: $.data.Main_Contact_Last, + Main_Contact_Role__c: $.data.Main_Contact_Role, + Main_Contact_Role_Other__c: $.data.Main_Contact_Role_Other, + Main_Contact_Phone_Mobile__c: $.data.Main_Contact_Phone_Mobile, + Main_Contact_Phone_Work__c: $.data.Main_Contact_Phone_Work, + Main_Contact_Phone_Other__c: $.data.Main_Contact_Phone_Other, + Main_Contact_Email_Work__c: $.data.Main_Contact_Email_Work, + General_Phone__c: $.data.General_Phone, + General_Email__c: $.data.General_Email, + Website__c: $.data.Website, + Interest_in_Website__c: $.data.Interest_in_Website, + Hours_of_Operation_Start__c: $.data.Hours_of_Operation_Start, + Hours_of_Operation_End__c: $.data.Hours_of_Operation_End, + Hours_of_Operation_Other__c: $.data.Hours_of_Operation_Other, + Hours_of_Operation_Other_Start__c: $.data.Hours_of_Operation_Other_Start, + Hours_of_Operation_Other_End__c: $.data.Hours_of_Operation_Other_End, + Goods_and_Services_Description__c: $.data.Goods_and_Services_Description, + Primary_Sector__c: $.data.Primary_Sector, + Primary_Subsectors__c: [ + $.data.Primary_Subsectors_1, + $.data.Primary_Subsectors_2, + $.data.Primary_Subsectors_3, + $.data.Primary_Subsectors_4, + $.data.Primary_Subsectors_5, + $.data.Primary_Subsectors_6, + $.data.Primary_Subsectors_7, + $.data.Primary_Subsectors_8, + $.data.Primary_Subsectors_9, + $.data.Primary_Subsectors_10, + $.data.Primary_Subsectors_l1, + $.data.Primary_Subsectors_12, + $.data.Primary_Subsectors_13, + $.data.Primary_Subsectors_14, + $.data.Primary_Subsectors_15, + $.data.Primary_Subsectors_16, + $.data.Primary_Subsectors_17, + $.data.Primary_Subsectors_18, + $.data.Primary_Subsectors_19, + $.data.Primary_Subsectors_20, + $.data.Primary_Subsectors_21, + ].filter(Boolean).join(','), + Other_Sectors__c: $.data.Other_Sectors, + Other_Subsectors__c: [ + $.data.Other_Subsectors_1, + $.data.Other_Subsectors_2, + $.data.Other_Subsectors_3, + $.data.Other_Subsectors_4, + $.data.Other_Subsectors_5, + $.data.Other_Subsectors_6, + $.data.Other_Subsectors_7, + $.data.Other_Subsectors_8, + $.data.Other_Subsectors_9, + $.data.Other_Subsectors_10, + $.data.Other_Subsectors_l1, + $.data.Other_Subsectors_12, + $.data.Other_Subsectors_13, + $.data.Other_Subsectors_14, + $.data.Other_Subsectors_15, + $.data.Other_Subsectors_16, + $.data.Other_Subsectors_17, + $.data.Other_Subsectors_18, + $.data.Other_Subsectors_19, + $.data.Other_Subsectors_20, + $.data.Other_Subsectors_21, + ].filter(Boolean).join(','), + Entity_and_Registration_1__c: $.data.Entity_and_Registration_1, + Entity_and_Registration_2__c: $.data.Entity_and_Registration_2, + Entity_and_Registration_3__c: $.data.Entity_and_Registration_3, + Registration_Date__c: $.data.Registration_Date, + Registration_Active__c: $.data.Registration_Active, + Business_Operation_Licenses__c: $.data.Business_Operation_Licenses, + Business_Operation_Certificates__c: $.data.Business_Operation_Certificates, + Association_Memberships__c: $.data.Association_Memberships, + Vendor_List_Memberships__c: $.data.Vendor_List_Memberships, + Has_Marketing_Plan__c: $.data.Has_Marketing_Plan, + Number_of_Competitors__c: $.data.Number_of_Competitors, + Start_of_Operations__c: $.data.Start_of_Operations, + Primary_Language__c: $.data.Primary_Language, + Primary_Language_Other__c: $.data.Primary_Language_Other, + English_Speakers__c: $.data.English_Speakers, + Other_Languages__c: $.data.Other_Languages, + Frequency_of_Internet_Access__c: $.data.Frequency_of_Internet_Access, + Method_of_Internet_Access__c: $.data.Method_of_Internet_Access, + Method_of_Internet_Access_Other__c: $.data.Method_of_Internet_Access_Other, + Frequency_of_Email_Use__c: $.data.Frequency_of_Email_Use, + Type_of_Email_Use__c: $.data.Type_of_Email_Use, + Counties_Regions_Serviced__c: [ + $.data.Counties_Regions_Serviced_a, + $.data.Counties_Regions_Serviced_b, + $.data.Counties_Regions_Serviced_c, + $.data.Counties_Regions_Serviced_d, + ].filter(Boolean).join(','), + Additional_Branches__c: $.data.Additional_Branches, + Branch_Locations__c: [ + $.data.Branch_Locations_a, + $.data.Branch_Locations_b, + $.data.Branch_Locations_c, + $.data.Branch_Locations_d, + ].filter(Boolean).join(','), + Majority_Local_or_Foreign__c: $.data.Majority_Local_or_Foreign, + Num_of_Owners__c: $.data.Num_of_Owners, + Num_of_Female_Owners__c: $.data.Num_of_Female_Owners, + Num_of_Male_Owners__c: $.data.Num_of_Male_Owners, + Primary_Owner_is_Same_as_Main_Contact__c: + $.data.Primary_Owner_is_Same_as_Main_Contact, + Primary_Owner__c: $.data.Primary_Owner, + Primary_Owner_Gender__c: $.data.Primary_Owner_Gender, + Primary_Owner_Gender_Other__c: $.data.Primary_Owner_Gender_Other, + Primary_Owner_Nationality__c: $.data.Primary_Owner_Nationality, + Primary_Owner_Phone_Mobile__c: $.data.Primary_Owner_Phone_Mobile, + Primary_Owner_Phone_Work__c: $.data.Primary_Owner_Phone_Work, + Primary_Owner_Phone_Other__c: $.data.Primary_Owner_Phone_Other, + Primary_Owner_Email__c: $.data.Primary_Owner_Email, + Num_of_Businesses_Owned__c: $.data.Num_of_Businesses_Owned, + Names_of_Businesses_Owned__c: $.data.Names_of_Businesses_Owned, + Num_of_Managers__c: $.data.Num_of_Managers, + Num_of_Female_Managers__c: $.data.Num_of_Female_Managers, + Num_of_Male_Managers__c: $.data.Num_of_Male_Managers, + Finance_Management__c: $.data.Finance_Management, + Finance_Management_Other__c: $.data.Finance_Management_Other, + Dedicated_HR_Manager__c: $.data.Dedicated_HR_Manager, + Num_of_Permanent_Full_Time_Employees__c: + $.data.Num_of_Permanent_Full_Time_Employees, + Num_of_Perm_Full_Time_Female_Employees__c: + $.data.Num_of_Perm_Full_Time_Female_Employees, + Num_of_Perm_Full_Time_Male_Employees__c: + $.data.Num_of_Perm_Full_Time_Male_Employees, + Num_of_Full_Time_Temporary_Employees__c: + $.data.Num_of_Full_Time_Temporary_Employees, + Num_of_Full_Time_Temp_Female_Employees__c: + $.data.Num_of_Full_Time_Temp_Female_Employees, + Num_of_Full_Time_Temp_Male_Employees__c: + $.data.Num_of_Full_Time_Temp_Male_Employees, + Num_of_Local_Staff_Full_Part_Time__c: + $.data.Num_of_Local_Staff_Full_Part_Time, + Num_of_Expatriate_Staff_Full_Part_Time__c: + $.data.Num_of_Expatriate_Staff_Full_Part_Time, + International_Client_in_Past_Six_Months__c: + $.data.International_Client_in_Past_Six_Months, + Principal_Client_Name__c: $.data.Principal_Client_Name, + Foreign_or_Domestic_Principal_Client__c: + $.data.Foreign_or_Domestic_Principal_Client, + Principal_Client_Sector__c: $.data.Principal_Client_Sector, + Goods_Services_Provided_to_this_Client__c: + $.data.Goods_Services_Provided_to_this_Client, + End_of_Last_Contract_with_this_Client__c: + $.data.End_of_Last_Contract_with_this_Client, + Value_Goods_Services_Sold_Last_6_Months__c: + $.data.Value_Goods_Services_Sold_Last_6_Months, + Value_Goods_Sold_Last_6_Months_USD__c: + $.data.Value_Goods_Sold_Last_6_Months_USD, + Access_to_Finance_Constraint_Ranking__c: + $.data.Access_to_Finance_Constraint_Ranking, + Bank_Account__c: $.data.Bank_Account, + Bank_Guarantee__c: $.data.Bank_Guarantee, + Satisfied_with_Current_Bank__c: $.data.Satisfied_with_Current_Bank, + Describe_Satisfaction_with_Current_Bank__c: + $.data.Describe_Satisfaction_with_Current_Bank, + Has_Received_a_Formal_Loan__c: $.data.Has_Received_a_Formal_Loan, + Formal_Loan_Provider__c: $.data.Formal_Loan_Provider, + Formal_Loan_Amount_Received__c: $.data.Formal_Loan_Amount_Received, + Formal_Loan_Amount_Received_USD__c: $.data.Formal_Loan_Amount_Received_USD, + Date_Formal_Loan_Received__c: $.data.Date_Formal_Loan_Received, + Formal_Loan_Purpose__c: $.data.Formal_Loan_Purpose, + Formal_Loan_Purpose_Other__c: $.data.Formal_Loan_Purpose_Other, + Formal_Loan_Repaid__c: $.data.Formal_Loan_Repaid, + Interested_in_Loan__c: $.data.Interested_in_Loan, + Interested_Loan_Amount__c: $.data.Interested_Loan_Amount, + Interested_Loan_Amount_USD__c: $.data.Interested_Loan_Amount_USD, + Interested_Loan_Duration__c: $.data.Interested_Loan_Duration, + Interested_Loan_Purpose__c: $.data.Interested_Loan_Purpose, + Interested_Loan_Purpose_Other__c: $.data.Interested_Loan_Purpose_Other, + Formal_Loan_Confidence_Ranking__c: $.data.Formal_Loan_Confidence_Ranking, + Received_Loan_from_Family_Friends__c: + $.data.Received_Loan_from_Family_Friends, + Family_Friend_Loan_Amount__c: $.data.Family_Friend_Loan_Amount, + Family_Friend_Loan_Amount_USD__c: $.data.Family_Friend_Loan_Amount_USD, + Received_Loan_from_Informal_Lenders__c: + $.data.Received_Loan_from_Informal_Lenders, + Informal_Lender_Loan_Amount__c: $.data.Informal_Lender_Loan_Amount, + Informal_Lender_Loan_Amount_USD__c: $.data.Informal_Lender_Loan_Amount_USD, + Interested_in_Investor_Business_Partner__c: + $.data.Interested_in_Investor_Business_Partner, + Total_Turnover_Previous_Month__c: $.data.Total_Turnover_Previous_Month, + Total_Turnover_Previous_Month_USD__c: + $.data.Total_Turnover_Previous_Month_USD, + Total_Turnover_Previous_Fiscal_Year__c: + $.data.Total_Turnover_Previous_Fiscal_Year, + Total_Turnover_Previous_Fiscal_Yr_USD__c: + $.data.Total_Turnover_Previous_Fiscal_Yr_USD, + Total_Profit_Previous_Fiscal_Year__c: + $.data.Total_Profit_Previous_Fiscal_Year, + Total_Profit_Previous_Fiscal_Year_USD__c: + $.data.Total_Profit_Previous_Fiscal_Year_USD, + Accepted_Modes_of_Payment__c: $.data.Accepted_Modes_of_Payment, + Accepted_Modes_of_Payment_Other__c: $.data.Accepted_Modes_of_Payment_Other, + Avg_Expen_Spent_on_Imported_Goods_Year__c: + $.data.Avg_Expen_Spent_on_Imported_Goods_Year, + Avg_Expen_Spent_on_Domestic_Goods_Year__c: + $.data.Avg_Expen_Spent_on_Domestic_Goods_Year, + Avg_Expen_on_Domestic_Suppliers_Year__c: + $.data.Avg_Expen_on_Domestic_Suppliers_Year, + Avg_Expen_on_Intl_Suppliers_Year__c: + $.data.Avg_Expen_on_Intl_Suppliers_Year, + Avg_Expen_Spent_on_Salaries_Year__c: + $.data.Avg_Expen_Spent_on_Salaries_Year, + Balance_Sheet_Statement_Available__c: + $.data.Balance_Sheet_Statement_Available, + Profit_Loss_Statement__c: $.data.Profit_Loss_Statement, + Directly_Imports_Goods__c: $.data.Directly_Imports_Goods, + Avg_of_Total_Costs_from_Imports__c: $.data.Avg_of_Total_Costs_from_Imports, + Highest_Costing_Import__c: $.data.Highest_Costing_Import, + Origin_Country_of_Highest_Costing_Import__c: + $.data.Origin_Country_of_Highest_Costing_Import, + Other_Import_Countries__c: $.data.Other_Import_Countries, + Exports_Products__c: $.data.Exports_Products, + Avg_of_Total_Revenue_from_Exports__c: + $.data.Avg_of_Total_Revenue_from_Exports, + Primary_Export__c: $.data.Primary_Export, + Destination_of_Exports__c: $.data.Destination_of_Exports, + Profits_Expectation_Next_Six_Months__c: + $.data.Profits_Expectation_Next_Six_Months, + Staff_Expectation_Next_Six_Months__c: + $.data.Staff_Expectation_Next_Six_Months, + Int_l_Entities_Represent_Good_Opp__c: + $.data.Int_l_Entities_Represent_Good_Opp, + Int_l_Concessionaires_Represent_Good_Opp__c: + $.data.Int_l_Concessionaires_Represent_Good_Opp, + Sectors_Representing_Best_Local_Opps__c: + $.data.Sectors_Presenting_Best_Local_Opps, + Obstacle_Working_with_Intl_Entities__c: + $.data.Obstacle_Working_with_Intl_Entities, + Biggest_Challenge_Next_6_Months__c: $.data.Biggest_Challenge_Next_6_Months, + Second_Biggest_Challenge_Next_6_Months__c: + $.data.Second_Biggest_Challenge_Next_6_Months, + Financial_Management_Ranking__c: $.data.Financial_Management_Ranking, + Access_to_Finance_Ranking__c: $.data.Access_to_Finance_Ranking, + Administration_Ranking__c: $.data.Administration_Ranking, + Human_Resources_Ranking__c: $.data.Human_Resources_Ranking, + Technical_Expertise_Ranking__c: $.data.Technical_Expertise_Ranking, + Training_Helps_Efficiency__c: $.data.Training_Helps_Efficiency, + Capacity_Building_Activities_Offered__c: + $.data.Capacity_Building_Activities_Offered, + Capacity_Building_Offered_Other__c: $.data.Capacity_Building_Offered_Other, + Can_Provide_Quotations_WP_on_Request__c: + $.data.Can_Provide_Quotations_WP_on_Request, + Knows_What_a_Tender_is__c: $.data.Knows_What_a_Tender_is, + Frequency_Checking_for_Tenders__c: $.data.Frequency_Checking_for_Tenders, + Has_Submitted_a_Tender_Bid__c: $.data.Has_Submitted_a_Tender_Bid, + Has_Won_Tenders_in_Past_Six_Months__c: + $.data.Has_Won_Tenders_in_Past_Six_Months, + Details_of_Recently_Won_Tenders__c: $.data.Details_of_Recently_Won_Tenders, + Num_of_Gov_t_Bids_in_Last_Six_Months__c: + $.data.Num_of_Govt_Bids_in_Last_Six_Months, + Num_of_Private_Bids_in_Last_Six_Months__c: + $.data.Num_of_Private_Bids_in_Last_Six_Months, + Num_of_NGO_INGO_IO_Bids_Last_Six_Months__c: + $.data.Num_of_NGO_INGO_IO_Bids_Last_Six_Months, + Main_Reason_for_Lost_Bids__c: $.data.Main_Reason_for_Lost_Bids, + Main_Reason_for_Lost_Bids_Other__c: + $.data.Main_Reason_for_Lost_Bids_Other__c, + Main_Reason_for_Not_Bidding_on_Tenders__c: + $.data.Main_Reason_for_Not_Bidding_on_Tenders, + Main_Reason_Not_Bidding_Tenders_Others__c: + $.data.Main_Reason_Not_Bidding_Tenders_Others__c, + Planning_to_Bid_on_Future_Tenders__c: + $.data.Planning_to_Bid_on_Tenders_in_the_Future, + Services_That_Would_Help_to_Win_Tenders__c: + $.data.Services_That_Would_Help_to_Win_Tenders, + Interested_in_Future_BM_Communications__c: + $.data.Interested_in_Future_BM_Communications, + Future_BM_Communications__c: $.data.Future_BM_Communications, + Interested_in_Attending_Future_Training__c: + $.data.Interested_in_Attending_Future_Training, + Training_Most_Interested_in_Attending__c: + $.data.Training_Most_Interested_in_Attending, + Training_Most_Interested_in_Other__c: + $.data.Training_Most_Interested_in_Other, + Amount_Willing_to_Pay_for_Training__c: + $.data.Amount_Willing_to_Pay_for_Training, + Training_Interested_In_but_Not_Offered__c: + $.data.Training_Interested_In_but_Not_Offered, + Advice_to_Entrepreneurs_in_your_Country__c: + $.data.Advice_to_Entrepreneurs_in_your_Country, + Interviewer_Comments__c: $.data.Interviewer_Comments, + }) ); diff --git a/adaptors/library/jobs/create-if-proposal.js b/adaptors/library/jobs/create-if-proposal.js index 08f90c5dcce5..8c626e91610d 100644 --- a/adaptors/library/jobs/create-if-proposal.js +++ b/adaptors/library/jobs/create-if-proposal.js @@ -2,27 +2,21 @@ // some condition in the source data is met. upsertIf( - // a path which resolves to true/false - dataValue('form.legal.allowedToSync'), + $.data.form.legal.allowedToSync, 'Patient__c', 'Patient_ID__c', - fields( - field('Name__c', dataValue('form.name')), - field('Patient_ID__c', dataValue('form.identification.govId')) - ) + { + Name__c: $.data.form.name, + Patient_ID__c: $.data.form.identification.govId, + } ); createIf( - // or a function which returns true/false - state => state.data.form.completedVisit === 'yes', + $.data.form.completedVisit === 'yes', 'Visit__c', - fields( - field('Date__c', dataValue('form.visit.visit_date')), - field('Type__c', 'checkup'), - relationship( - 'Patient__r', - 'Patient_ID__c', - dataValue('form.identification.govId') - ) - ) + { + Date__c: $.data.form.visit.visit_date, + Type__c: 'checkup', + Patient__r: { Patient_ID__c: $.data.form.identification.govId }, + } ); diff --git a/adaptors/library/jobs/getKoboData.js b/adaptors/library/jobs/getKoboData.js index 33443e6aea13..ec96f70fb752 100644 --- a/adaptors/library/jobs/getKoboData.js +++ b/adaptors/library/jobs/getKoboData.js @@ -1,60 +1,53 @@ -//Sample job to get Kobo data and post back to OpenFn Inbox +// Sample job to get Kobo data and post each submission back to an OpenFn inbox fn(state => { console.log(`Started at: ${new Date().toISOString()}`); - state.submissions = []; - state.data = { - surveys: [ - // ========================================================================= - //== TODO: Specify new forms to fetch here, including the Kobo form id, tag, name, and owner ==// - { id: 'aijj9FSpuCzMTRnMPGike8', tag: 'nrgt_historical', name: 'NRGT Makira 2017 - Test OpenFn', owner: 'bns' }, // example - //consider listing multiple forms - // ========================================================================= - - ].map(survey => ({ - formId: survey.id, - tag: survey.tag, - name: survey.name, - owner: survey.owner, - url: `https://kf.kobotoolbox.org/api/v2/assets/${survey.id}/data/?format=json`, - })), - }; - console.log(`Fetching data for ${state.data.surveys.length} surveys.`); - return state; -}); -each(dataPath('surveys[*]'), state => { - const { url, tag, formId, name, owner } = state.data; - return get(url, {}, state => { - state.data.submissions = state.data.results.map((submission, i) => { - return { - i, - // Here we append the tags defined above to the Kobo form submission data - form: tag, - formName: name, - formOwner: owner, - body: submission, - }; - }); - const count = state.data.submissions.length; - console.log(`Fetched ${count} submissions from ${formId} (${tag}).`); - //Once we fetch the data, we want to post each individual Kobo survey - //back to the OpenFn inbox to run through the jobs - return each(dataPath('submissions[*]'), state => { - console.log(`Posting ${state.data.i + 1} of ${count}...`); - // ========================================================================= - //== TODO: replace openfnInboxUrl with your OpenFn Project Inbox URL ====// - return post(openfnInboxUrl, { body: state => state.data })(state); - })(state); - // ========================================================================= - })(state); + const surveys = [ + // TODO: Add the Kobo form IDs, tags, names, and owners to fetch here + { id: 'aijj9FSpuCzMTRnMPGike8', tag: 'nrgt_historical', name: 'NRGT Makira 2017 - Test OpenFn', owner: 'bns' }, + ].map(survey => ({ + formId: survey.id, + tag: survey.tag, + name: survey.name, + owner: survey.owner, + url: `https://kf.kobotoolbox.org/api/v2/assets/${survey.id}/data/?format=json`, + })); + + console.log(`Fetching data for ${surveys.length} surveys.`); + return { ...state, surveys, submissions: [] }; }); +// Fetch submissions for each survey +each( + $.surveys, + fn(async state => { + const { url, tag, formId, name, owner } = state.data; + state = await get(url, {})(state); + + const newSubmissions = state.data.results.map((submission, i) => ({ + i, + form: tag, + formName: name, + formOwner: owner, + body: submission, + })); + + console.log(`Fetched ${newSubmissions.length} submissions from ${formId} (${tag}).`); + return { ...state, submissions: [...state.submissions, ...newSubmissions] }; + }) +); + +// Post each submission to the OpenFn inbox +// TODO: Replace with your OpenFn Project Inbox URL +each( + $.submissions, + post($.configuration.inboxUrl, $.data).then(state => { + console.log(`Posting submission ${state.data.i + 1}...`); + return state; + }) +); + fn(state => { console.log(`Finished at: ${new Date().toISOString()}`); - return { - data: { - message: "No cursor required. Job fetches all submission for given forms." - }, - references: [] - }; + return { ...state, data: { message: 'All submissions posted.' }, references: [] }; }); diff --git a/adaptors/library/jobs/promise-all-nested-requests.js b/adaptors/library/jobs/promise-all-nested-requests.js index a7164957d12e..e97b54667b4e 100644 --- a/adaptors/library/jobs/promise-all-nested-requests.js +++ b/adaptors/library/jobs/promise-all-nested-requests.js @@ -1,60 +1,46 @@ +// Fetch user details and course grades using async/await in fn(). +// Avoid nesting operations inside callbacks — use sequential awaits instead. each( - '$.enrolledUsers[10]', - fn(state => { + $.enrolledUsers.slice(0, 10), + fn(async state => { const { host } = state.configuration; const { id } = state.data; - const usersfields = []; - return get( - host, - { + + // Step 1: Get user details + state = await get(host, { + query: { + wstoken: state.token, + wsfunction: 'core_user_get_users_by_field', + field: 'id', + 'values[]': id, + moodlewsrestformat: 'json', + }, + })(state); + + const { phone1, address } = state.data[0]; + const user = { id, 'Teléfono móvil': phone1, Dirección: address, grades: [] }; + + // Step 2: Get grades for each course sequentially + for (const courseid of state.courseIds) { + state = await get(host, { query: { wstoken: state.token, - wsfunction: 'core_user_get_users_by_field', - field: 'id', - 'values[]': id, + wsfunction: 'gradereport_user_get_grade_items', + userid: id, + courseid, moodlewsrestformat: 'json', }, - }, - state => { - const { id, phone1, address } = state.data[0]; - const fields = [ - { id, 'Teléfono móvil': phone1, Dirección: address, grades: [] }, - ]; - console.log(state.courseIds); - let promises = []; - state.courseIds.forEach(courseid => { - promises.push( - get( - host, - { - query: { - wstoken: state.token, - wsfunction: 'gradereport_user_get_grade_items', - userid: id, - courseid, - moodlewsrestformat: 'json', - }, - }, - state => { - console.log('fetched'); - const { graderaw } = state.data.usergrades[0].gradeitems[0]; - const grades = [{ courseid, graderaw }]; - fields[0].grades.push(...grades); - } - )(state) - ); - }); + })(state); + + const { graderaw } = state.data.usergrades[0].gradeitems[0]; + user.grades.push({ courseid, graderaw }); + } - return Promise.all(promises).then(() => { - usersfields.push(...fields); - return { - ...state, - usersfields, - enrolledUsers: [], - response: [], - }; - }); - } - )(state); + return { + ...state, + usersfields: [...(state.usersfields || []), user], + enrolledUsers: [], + response: [], + }; }) ); diff --git a/adaptors/library/jobs/send-mail-in-mailgun.js b/adaptors/library/jobs/send-mail-in-mailgun.js index a257406a5154..02809660dde1 100644 --- a/adaptors/library/jobs/send-mail-in-mailgun.js +++ b/adaptors/library/jobs/send-mail-in-mailgun.js @@ -1,8 +1,6 @@ -send( - fields( - field('from', 'you@domain.com'), - field('to', dataValue('form.submission.respondantEmail')), - field('subject', 'Thanks for completing our survey.'), - field('text', 'Your message goes here.') - ) -); +send({ + from: 'you@domain.com', + to: $.data.form.submission.respondantEmail, + subject: 'Thanks for completing our survey.', + text: 'Your message goes here.', +}); diff --git a/adaptors/library/jobs/send-sms-from-salesforce-workflow.js b/adaptors/library/jobs/send-sms-from-salesforce-workflow.js index 4326810afe8e..48fd1e952254 100644 --- a/adaptors/library/jobs/send-sms-from-salesforce-workflow.js +++ b/adaptors/library/jobs/send-sms-from-salesforce-workflow.js @@ -1,20 +1,7 @@ -send( - fields( - field( - 'to_number', - dataValue( - 'Envelope.Body.notifications.Notification.sObject.phone_number__c' - ) - ), - field('message_type', 'sms'), - field('route_id', ''), - field('content', function (state) { - return 'Hey there. Your name is '.concat( - dataValue('Envelope.Body.notifications.Notification.sObject.name__c')( - state - ), - '.' - ); - }) - ) -); +send({ + to_number: + $.data.Envelope.Body.notifications.Notification.sObject.phone_number__c, + message_type: 'sms', + route_id: '', + content: `Hey there. Your name is ${$.data.Envelope.Body.notifications.Notification.sObject.name__c}.`, +}); diff --git a/adaptors/library/jobs/stripe-get-subscriptions.js b/adaptors/library/jobs/stripe-get-subscriptions.js index 568bb6332a63..930d3024b4d3 100644 --- a/adaptors/library/jobs/stripe-get-subscriptions.js +++ b/adaptors/library/jobs/stripe-get-subscriptions.js @@ -1,14 +1,16 @@ // Get subscription data -fn(state => { - state.subscriptions = state.data; - state.subscriptionsData = []; - return state; -}); +fn(state => ({ + ...state, + subscriptions: state.data, + subscriptionsData: [], +})); each( - '$.subscriptions', - get('subscriptions', $.data).then(state => { - state.subscriptionsData.push(state.data.data); - return state; - }) + $.subscriptions, + get('subscriptions', { id: $.data }) ); + +fn(state => ({ + ...state, + subscriptionsData: [...state.subscriptionsData, state.data.data], +})); diff --git a/adaptors/library/jobs/synchronous-http-request.js b/adaptors/library/jobs/synchronous-http-request.js index 918bd457297f..c06e0d17cda3 100644 --- a/adaptors/library/jobs/synchronous-http-request.js +++ b/adaptors/library/jobs/synchronous-http-request.js @@ -41,7 +41,7 @@ fn(async state => { console.log(`${countInbox} request to inbox`); await new Promise(resolve => setTimeout(resolve, 2000)); - await post(state.configuration.inboxUrl, { body: data })(state); + await post(state.configuration.inboxUrl, data)(state); }; console.log('For each one of our chunks, we send one by one awaiting response.'); diff --git a/adaptors/library/jobs/upsert-many-items-in-array-with-value-outside-array.js b/adaptors/library/jobs/upsert-many-items-in-array-with-value-outside-array.js index 6e828a8bb6c5..67fef894873a 100644 --- a/adaptors/library/jobs/upsert-many-items-in-array-with-value-outside-array.js +++ b/adaptors/library/jobs/upsert-many-items-in-array-with-value-outside-array.js @@ -1,21 +1,19 @@ +// When array items need a value from outside the array (e.g., a parent form field), +// use fn() + array.map() to merge the value into each item before iterating. +fn(state => ({ + ...state, + cards: state.data.form.ID_cards_given_to_vendor.map(card => ({ + sp_id: card, + vendor_badge_code: state.data.form.ID_vendor, + distribution_date: state.data.form.meta.timeEnd, + })), +})); + each( - merge( - dataPath('form.ID_cards_given_to_vendor[*]'), - fields( - field('Vendor_Id', dataValue('form.ID_vendor')), - field('form_finished_time', dataValue('form.meta.timeEnd')) - ) - ), - upsert( - 'Small_Packet__c', - 'sp_id__c', - fields( - field('sp_id__c', dataValue('ID_cards_given_to_vendor')), - relationship('Vendor__r', 'Badge_Code__c', dataValue('Vendor_Id')), - field( - 'Small_Packet_Distribution_Date__c', - dataValue('form_finished_time') - ) - ) - ) + $.cards, + upsert('Small_Packet__c', 'sp_id__c', { + sp_id__c: $.data.sp_id, + Vendor__r: { Badge_Code__c: $.data.vendor_badge_code }, + Small_Packet_Distribution_Date__c: $.data.distribution_date, + }) ); diff --git a/adaptors/library/jobs/workWithIdAfterInsertOrUpsert.js b/adaptors/library/jobs/workWithIdAfterInsertOrUpsert.js index 107844a12866..bb3538dde27d 100644 --- a/adaptors/library/jobs/workWithIdAfterInsertOrUpsert.js +++ b/adaptors/library/jobs/workWithIdAfterInsertOrUpsert.js @@ -1,35 +1,30 @@ -create('Patient__c', fields( - field('Name', 'John Doe'), - field('Age__c', state.data.age) -)); +create('Patient__c', { + Name: 'John Doe', + Age__c: $.data.age, +}); -// NOTE: After inserts, Salesforce will return an sfID and it will be kept in -// references. I'm using alterState here simply to log the output. It's not -// necessary. +// NOTE: After inserts, Salesforce returns the new record's sfID in state.references. fn(state => { console.log(state.references); - // References is an array: - // references: [ { id: 'a0J0B00000QY9TbUAL', success: true, errors: [] } ], + // references: [ { id: 'a0J0B00000QY9TbUAL', success: true, errors: [] } ] + return state; }); -//NOTE: We've even got some helper functions for accessing that last reference ID. -create('Visit__c', fields( - field('Date__c', state.data.date) - field('Patient__c', lastReferenceValue('id')) - // Or write it like this... - // field(Patient__c, state.references[0].id) -)); +// Access the sfID from the previous insert +create('Visit__c', { + Date__c: $.data.date, + Patient__c: $.references[0].id, +}); -// NOTE: You can't work directly with sfIDs on upserts, but you don't need to! -upsert('Patient__c', 'My_Ext_ID__c', fields( - field('Name', 'John Doe'), - field('Age__c', state.data.age), - field('My_Ext_ID__c', state.data.patientNumber) - // THIS unique ID is how you work with the record in SF. -)); +// NOTE: You can't work directly with sfIDs on upserts — use an external ID instead. +upsert('Patient__c', 'My_Ext_ID__c', { + Name: 'John Doe', + Age__c: $.data.age, + My_Ext_ID__c: $.data.patientNumber, +}); -create('Visit__c', fields( - field('Date__c', state.data.date), - // Related to the patient you just upserted... - relationship('Patient__r', 'My_Ext_ID__c', state.data.patientNumber) -)); +// Relate to the patient you just upserted via their external ID +create('Visit__c', { + Date__c: $.data.date, + Patient__r: { My_Ext_ID__c: $.data.patientNumber }, +}); diff --git a/adaptors/salesforce.md b/adaptors/salesforce.md index 35bdc376508a..45c403c436ea 100644 --- a/adaptors/salesforce.md +++ b/adaptors/salesforce.md @@ -123,9 +123,8 @@ Salesforce, use the external identifier of the related record. Examples: - If the metadata are standard objects or fields, then you do not need the `__r` to indicate there is a relationship. Example mapping: `Account.CustomAccountID__c: {AcctIdFromSourceData}` -- If using the OpenFn adaptor, you may also choose to leverage the - `relationship(...)` helper function in your job. Example mapping: - `relationship('Respondent__r', 'PersonID__c', dataValue('sourceField'))` +- If using the OpenFn adaptor, use a nested object to express the relationship in your job. Example mapping: + `{ Respondent__r: { PersonID__c: state.data.sourceField } }` #### Picklist fields diff --git a/docs/jobs/job-examples.md b/docs/jobs/job-examples.md index 99d4cebf9b04..be4f6e027edd 100644 --- a/docs/jobs/job-examples.md +++ b/docs/jobs/job-examples.md @@ -245,7 +245,7 @@ create('patient', state => ({ })); ``` -### merge many values into a child path +### Merge parent-level values into each child item ```js // Merge parent-level values into each child item before iterating @@ -270,10 +270,14 @@ each( ); ``` -### arrayToString +### Concatenate an array into a string ```js -arrayToString(arr, separator_string); +fn(state => { + // Join an array of values into a single string with a ", " separator + state.speciesList = state.data.target_species.join(', '); + return state; +}); ``` ### access an image URL from an ODK submission @@ -286,7 +290,7 @@ create('Photo__c', state => ({ })); ``` -### alterState (alter state) to make sure data is in an array +### Ensure data is in an array before iterating ```js // Here, we make sure CommCare gives us an array and merge parent-level fields