ServiceForms Dispatch Data Mapping and Destination Rule Methods

Derek Torres
Derek Torres
  • Updated

Dispatch Data Mappings

A dispatch rule can optionally define how data is prefilled into the dispatched form’s fields.  By default, the following data will be prefilled.

Below is a list of ServiceTrade API field names, and their corresponding ServiceForms field names:

ServiceTrade API field name

ServiceForms field name

GET /api/job/:jobId

job.id

servicetrade_job_id

job.number

servicetrade_job_number

job.description

servicetrade_job_description

job.location.name

servicetrade_location_name

job.location.address.street

servicetrade_location_street

job.location.address.city

servicetrade_location_city

job.location.address.state

servicetrade_location_state

job.location.address.postalCode

servicetrade_location_postal_code

job.customer.name

servicetrade_customer_name

job.customer.address.street

servicetrade_customer_street

job.customer.address.city

servicetrade_customer_city

job.customer.address.state

servicetrade_customer_state

job.customer.address.postalCode

servicetrade_customer_postal_code

job.location.primaryContact.name

servicetrade_contact_name

job.location.primaryContact.phone

servicetrade_contact_phone

job.location.primaryContact.mobile

servicetrade_contact_mobile

job.location.primaryContact.alternatePhone

servicetrade_contact_alt_phone

GET /api/appointment/:appointmentId

appointment.windowStart

servicetrade_appointment_start

appointment.windowEnd

servicetrade_appointment_end

GET /api/servicerequest?status=open,in_progress&appointmentId=:appointmentId

servicerequest[].id

servicetrade_services[].service_request_id

servicerequest[].description

servicetrade_services[].description

servicerequest[].serviceLine.name

servicetrade_services[].service_line

servicerequest[].asset.name

servicetrade_services[].asset_name

servicerequest[].asset.id

servicetrade_services[].asset_id

servicerequest[].deficiency.id

servicetrade_services[].deficiency_id

servicerequest[].windowStart

servicetrade_services[].start

servicerequest[].windowEnd

servicetrade_services[].end

servicerequest[].serviceRecurrence.frequency

servicetrade_services[].frequency

servicerequest[].serviceRecurrence.interval

servicetrade_services[].interval

servicerequest[].deficiency.id

servicetrade_services[].deficiency_id

servicerequest[].deficiency.description

servicetrade_services[].deficiency_description

servicerequest[].status

servicetrade_services[].status

GET /api/jobItem?jobId=:jobId

jobItem[].id

servicetrade_job_items[].id

jobItem[].quantity

servicetrade_job_items[].quantity

jobItem[].name

servicetrade_job_items[].name

jobItem[].libItem.code

servicetrade_job_items[].code

jobItem[].cost

servicetrade_job_items[].cost

jobItem[].serviceRequest.id

servicetrade_job_items[].service_id

jobItem[].serviceRequest.description

servicetrade_job_items[].service_description

GET /api/asset?appointmentId=:appointmentIdto get only this appointment’s assets

GET /api/asset?locationId=:locationIdto get ALL assets at this location

asset[].id

servicetrade_assets[].asset_id

asset[].name

servicetrade_assets[].name

asset[].serviceLine.name

servicetrade_assets[].service_line

asset[].properties.*

   Properties vary by asset definition

servicetrade_assets[].properties_*

   Properties vary by asset definition

Example:  properties_barcode

GET /api/deficiency?locationId=:locationId&status=new,verified

deficiency[].id

servicetrade_deficiencies[].deficiency_id

deficiency[].asset.id

servicetrade_deficiencies[].asset_id

deficiency[].severity

servicetrade_deficiencies[].severity

deficiency[].status

servicetrade_deficiencies[].status

deficiency[].description

servicetrade_deficiencies[].description

deficiency[].resolution

servicetrade_deficiencies[].resolution

deficiency[].serviceLine.name

servicetrade_deficiencies[].service_line

deficiency[].job.id

servicetrade_deficiencies[].job_id

deficiency[].reportedOn

servicetrade_deficiencies[].reported_date

GET /api/user/:userId

userId is the ID of the clocked-in technician who receives the dispatch

user.id

servicetrade_technician_id

user.name

servicetrade_technician_name

user.phone

servicetrade_technician_phone

user.email

servicetrade_technician_email

user.details

servicetrade_technician_details

GET /api/brand/:brandId

brandId is the ID of the brand associated with the job’s office

brand.displayName (or job vendor name if not set)

servicetrade_brand_display_name

brand.webSite

servicetrade_brand_website

brand.details

servicetrade_brand_details

Destination Rule Methods

These methods can be called inside a destination rule to create/update data inside ServiceTrade.

createDeficiencies(deficienciesArray)

Creates a set of deficiencies from a given array.  Each array member should have the following properties:

  • assetId (int) - ID of asset to which deficiency should be added *Required
  • jobId (int) - ID of job on which deficiency is being reported *Required
  • severity (enum, one of:  ‘inoperable’, ‘deficient’, ‘suggested’) *Required
  • description (string) *Required
  • status (enum, one of:  ‘new’, ‘verified’, ‘fixed’) *Required
  • reportSource (enum, one of: ‘manual’, ‘mobile’) *Required
  • images (array)

For each deficiency, this method will construct and execute an API call like:

let deficiencyPayload = {
assetId: assetId,
severity: severity,
description: description,
status: status,
reportSource: reportSource,
jobId: jobId,
Images: []  // TODO
};
servicetrade.post('/deficiency', deficiencyPayload);

createAssets(assetsArray)

Creates a set of assets from a given array.  Each array member should have the following properties:

  • locationId (int) - ID of location to which asset should be added *Required
  • type (enum, one of the types listed in GET /api/assetDefinition) *Required
  • parentId (int) - ID of the asset which is the parent of the asset being added (optional; if not supplied, the top-level building asset will be used as the parent)
  • properties (object -- contents vary by asset definition) *Required

For each asset, this method will construct an API call like:

let assetPayload = {
locationId: locationId,
type: type,
parentId: parentId,
properties: properties
};
servicetrade.post('/asset’, assetPayload);

updateAssets(assetsArray)

Updates a set of assets from a given array.  Each array member should have the following properties:

  • assetId (int) - ID of the asset to be updated *Required
  • properties (object -- contents vary by asset definition)
  • status (enum, one of:  ‘active’, ‘inactive’)

For each asset, this method will construct an API call like:

let assetPayload = {
status: status,
properties: properties
};
servicetrade.put('/asset/’ + assetId, assetPayload);

createJobItems(jobItemsArray)

Creates a set of job items from a given array.  Each array member should have the following properties:

  • jobId (int) - ID of the job to which the job item should be added *Required
  • libItemId (int) - ID of lib item to use when creating the job item. *Required, unless ‘name’ and ‘serviceLineId’ are provided
  • name (string) [REQUIRED, unless ‘libItemId’ is provided]
  • serviceLineId (int) - ID of service line to use when creating the job item. *Required, unless ‘libItemId’ is provided AND referenced lib item has a service line assignment.
  • quantity (float) *Required
  • serviceRequestId (int) - ID of the service request to which the job item should be associated
  • source (object - see job item API documentation for details)

For each job item, this method will construct an API call like:

let jobItemPayload = {
jobId: jobId,
libItemId: libItemId,
name: name,
serviceLineId: serviceLineId,
serviceRequestId: serviceRequestId,
quantity: quantity,
source: source,
usedOn: Moment().format(‘X’) // Always today
};
servicetrade.post('/jobitem’, jobItemPayload);

createJobAttachments(attachmentsArray)

Creates a set of job attachments from the given array.  Each array member should have the following properties:

  • jobId (int) - ID of the job to which the attachment should be added *Required
  • attachmentUrl - the URL of the attachment *Required

Returns an array of attachment objects. Example:

/* creates a job attachment if the ‘Interesting Job Image’ question is answered */

let jobAttachmentsToCreate = [];
if (SF.answers.Interesting_Job_Image && SF.answers.Interesting_Job_Image.value) {
jobAttachmentsToCreate.push({
attachmentUrl: SF.answers.Interesting_Job_Image.value,
jobId: SF.job.id
});
}
await SF.createJobAttachments(jobAttachmentsToCreate);

createAssetAttachments(attachmentsArray)

Creates a set of asset attachments from the given array.  Each array member should have the following properties:

  • assetId (int) - ID of the asset to which the attachment should be added *Required
  • attachmentUrl - the URL of the attachment *Required

Returns an array of attachment objects. Example:

/* creates attachments on all assets that have the ‘Interesting Image’ question answered */
let assets = SF.answers.servicetrade_assets ? SF.answers.servicetrade_assets.values : [];

let assetAttachmentsToCreate = [];
for (let a of assets) {
const assetId = d.asset_id ? d.asset_id.value : null;
if (assetId && a.Interesting_Image && a.Interesting_Image.value) {
assetAttachmentsToCreate.push({
attachmentUrl: a.Interesting_Image.value,
assetId: assetId
});
}
}
await SF.createAssetAttachments(assetAttachmentsToCreate);

Example Destination Rule:

The content shown below will be entered by a user into the ‘code goes here’ box in https://app.moqups.com/BlmK9KQVCB/view/page/aeb147601

/* creates deficiencies for each asset that has a Visual or Functional test failure */

let assets = SF.answers.servicetrade_assets ? SF.answers.servicetrade_assets.values : [];

for (asset of assets) {
const assetId = asset.asset_id ? asset.asset_id.value : null;
if (!assetId) {
const assetPayload = {
locationId: SF.job.location.id,
type: 'hvac_unit',
properties: {
barcode: asset.properties_barcode ? asset.properties_barcode.value : null,
area_serviced: asset.properties_area_serviced ? asset.properties_area_serviced.value : null
}
};
const newAsset = await SF.createAssets([assetPayload]);
asset.asset_id = {value: newAsset[0].id};
}
}

const deficientAssets = assets.filter(v => {
return (v.Visual && v.Visual.value == 'Fail') || (v.Functional && v.Functional.value == 'Fail');
});


let deficienciesToCreate = [];
for (let d of deficientAssets) {
let description, deficiency, severity;
const assetId = d.asset_id ? d.asset_id.value : null;

const failFunctional = d.Functional && d.Functional.value == 'Fail';
const failVisual = d.Visual && d.Visual.value == 'Fail';

if (failVisual && !failFunctional) {
description = 'Visual test failure';
severity = 'deficient';
} else if (!failVisual && failFunctional) {
description = 'Functional test failure';
severity = 'inoperable';
} else {
description = 'Visual and functional test failure';
severity = 'inoperable';
}

let deficiencyPayload = {
assetId: assetId,
severity: severity,
description: description,
status: 'verified',
reportSource: 'mobile',
jobId: SF.job.id,
attachments: []
};
if (d.Visual_Failure_Image && d.Visual_Failure_Image.value) {
deficiencyPayload.attachments.push(d.Visual_Failure_Image.value);
}
if (d.Functional_Failure_Image && d.Functional_Failure_Image.value) {
deficiencyPayload.attachments.push(d.Functional_Failure_Image.value);
}
deficienciesToCreate.push(deficiencyPayload);
}
await SF.createDeficiencies(deficienciesToCreate);

Example of Device Magic Submission

// 20200124170428
// https://raw.githubusercontent.com/servicetrade/devicemagic/master/devicemagic-integration/devicemagic-submission-example.txt?token=AHOMPFIM3CX3EZ4TBVWIMA26GSSGU

{
"metadata": {
"device_id": "iPhone_B47461D1-D4D6-46BF-BBC0-70DBE8E0CC01",
"user_id": null,
"username": "Randolph Childress",
"submitted_at": "2019-11-27 10:09:02 -05:00",
"received_at": "2019-11-27 15:09:03 +00:00",
"submission_id": "42466896",
"device_submission_identifier": "F9875453-6E13-4710-8A4C-3F97C9B06F78",
"submission_counter": "1",
"form_name": "Inspection Job #17245299 - JHACO Supervisory Device",
"form_namespace": "http://www.devicemagic.com/xforms/903925e0-651f-0137-a3e7-0ab2d1506b92?a39a2330-f355-0137-0429-06b163b15006",
"form_version": "1.01"
},
"answers": {
"servicetrade_job_number": {
"value": "17245299"
},
"servicetrade_location_name": {
"value": "Jay Hospital"
},
"servicetrade_job_id": {
"value": "9801431"
},
"servicetrade_asset_list": {
"values": [
{
"servicetrade_asset_id": {
"value": "12560972"
},
"Zone_or_Address": {
"value": "A1"
},
"ID_____Area___Location": {
"value": "Front Door"
},
"Device_Type": {
"value": "Water Flow"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 1
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560981"
},
"Zone_or_Address": {
"value": "A1"
},
"ID_____Area___Location": {
"value": "Rear Entrance"
},
"Device_Type": {
"value": "Control Valve Supervisory Tamper Switch"
},
"Visual": {
"value": "Fail"
},
"Visual_Failure_Image": {
"value": "https://s3.amazonaws.com/hack-st-devicemagic-dev/servicetrade_asset_list%5B2%5D.Visual_Failure_Image.c97a45f0-f355-0137-6e84-028f45e3c9fe.JPEG"
},
"Functional": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 1
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 1
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560976"
},
"Zone_or_Address": {
"value": "A3"
},
"ID_____Area___Location": {
"value": "Office 123"
},
"Device_Type": {
"value": "Control Valve Supervisory Tamper Switch"
},
"Visual": {
"value": "Pass"
},
"Functional": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 1
},
"Control_Valve_Pass": {
"value": 1
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560982"
},
"Zone_or_Address": {
"value": "A4"
},
"ID_____Area___Location": {
"value": "Side Entrance"
},
"Device_Type": {
"value": "Control Valve Supervisory Tamper Switch"
},
"Visual": {
"value": "Pass"
},
"Functional": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 1
},
"Control_Valve_Pass": {
"value": 1
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560979"
},
"Zone_or_Address": {
"value": "B1"
},
"ID_____Area___Location": {
"value": "Office 555"
},
"Device_Type": {
"value": "Low/High Supervisory Pressure Switch"
},
"Visual": {
"value": "Pass"
},
"Functional": {
"value": "Fail"
},
"Functional_Failure_Image": {
"value": "https://s3.amazonaws.com/hack-st-devicemagic-dev/servicetrade_asset_list%5B5%5D.Functional_Failure_Image.c99df2f0-f355-0137-6e84-028f45e3c9fe.JPEG"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 1
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 1
}
},
{
"servicetrade_asset_id": {
"value": "12560973"
},
"Zone_or_Address": {
"value": "B14"
},
"ID_____Area___Location": {
"value": "Side Entrance"
},
"Device_Type": {
"value": "Water Flow"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 1
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560975"
},
"Zone_or_Address": {
"value": "B2"
},
"ID_____Area___Location": {
"value": "Back Door"
},
"Device_Type": {
"value": "Control Valve Supervisory Tamper Switch"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 1
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560980"
},
"Zone_or_Address": {
"value": "B8"
},
"ID_____Area___Location": {
"value": "Loading Dock"
},
"Device_Type": {
"value": "Low/High Supervisory Pressure Switch"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 1
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560977"
},
"Zone_or_Address": {
"value": "C14"
},
"ID_____Area___Location": {
"value": "Office 456"
},
"Device_Type": {
"value": "Water Flow"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 1
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560984"
},
"Zone_or_Address": {
"value": "C2"
},
"ID_____Area___Location": {
"value": "Office 234"
},
"Device_Type": {
"value": "Low/High Supervisory Pressure Switch"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 1
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560974"
},
"Zone_or_Address": {
"value": "C4"
},
"ID_____Area___Location": {
"value": "Back Door"
},
"Device_Type": {
"value": "Control Valve Supervisory Tamper Switch"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 1
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560978"
},
"Zone_or_Address": {
"value": "D6"
},
"ID_____Area___Location": {
"value": "Office 432"
},
"Device_Type": {
"value": "Water Flow"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 1
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 0
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
},
{
"servicetrade_asset_id": {
"value": "12560983"
},
"Zone_or_Address": {
"value": "D7"
},
"ID_____Area___Location": {
"value": "Office 995"
},
"Device_Type": {
"value": "Low/High Supervisory Pressure Switch"
},
"Visual": {
"value": "Pass"
},
"Is_Water_Flow": {
"value": 0
},
"Water_Flow_Pass": {
"value": 0
},
"Water_Flow_Fail": {
"value": 0
},
"Is_Control_Valve": {
"value": 0
},
"Control_Valve_Pass": {
"value": 0
},
"Control_Valve_Fail": {
"value": 0
},
"Is_Low_High": {
"value": 1
},
"Low_High_Pass": {
"value": 0
},
"Low_High_Fail": {
"value": 0
}
}
]
},
"Water_Flow_Device_Total": {
"value": 4
},
"Water_Flow_Device___Tested": {
"value": 0
},
"Water_Flow_Device___Passed": {
"value": 0
},
"Water_Flow_Device___Failed": {
"value": 0
},
"Control_Valve_Device_Total": {
"value": 5
},
"Control_Valve_Device___Tested": {
"value": 3
},
"Control_Valve_Device___Passed": {
"value": 2
},
"Control_Valve_Device___Failed": {
"value": 1
},
"Low_High_Device_Total": {
"value": 4
},
"Low_High_Device___Tested": {
"value": 1
},
"Low_High_Device___Passed": {
"value": 0
},
"Low_High_Device___Failed": {
"value": 1
}
}
}

 

Was this article helpful?

/