985
edits
No edit summary |
|||
| Line 44: | Line 44: | ||
== Compliance Rule Loaders == | == Compliance Rule Loaders == | ||
You can create custom loaders and pass the loader data to compliance rules by specifying the loader name in the matchingLoaders array property | You can create custom loaders and pass the loader data to compliance rules by specifying the loader name in the matchingLoaders array property on the shift schedulable definition (both for the Scheduler and the Mobile App definition). | ||
Example loader that loads certificates<syntaxhighlight lang="javascript"> | Example loader that loads certificates.<syntaxhighlight lang="javascript"> | ||
{ | { | ||
name: "certificates", | name: "certificates", | ||
| Line 64: | Line 64: | ||
</syntaxhighlight>Note that for shift search in the mobile app, we recommend that you define a "candidateShifts" loader where you can pull the candidate's other shifts, so you can evaluate worktime regulations. E.g.:<syntaxhighlight lang="javascript"> | |||
{ | |||
name: "candidateShifts", | |||
objectName: "b3s__Shift__c", | |||
filterRecordsBy: function () { | |||
return "b3s__Contact__c = {1}" | |||
}, | |||
groupRecordsBy: "Id", | |||
fieldToLoad: ['b3s__Scheduled_Start_Time__c', 'b3s__Scheduled_End_Time__c', 'b3s__Contact__c'], | |||
filteringItems: function () { | |||
return [ | |||
`'${contextRecordId}'`, | |||
`'${contactUserId}'` | |||
] | |||
} | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 89: | Line 105: | ||
== Complete Examples == | == Complete Examples == | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
async ({ event, events, contactId, loaders, EvaluationResult }) => { | async ({ event, events, contactId, loaders, EvaluationResult }) => { | ||
if (!contactId) { | if (!contactId) { | ||
| Line 95: | Line 110: | ||
return []; | return []; | ||
} | } | ||
const | |||
const certificatesLoader = loaders.find((l) => l.name === 'certificates'); | |||
const contactCertificates = certificatesLoader?.loader?.grouped[contactId]; | |||
const certRequirementsLoader = loaders.find((l) => l.name === 'certRequirements'); | |||
const certRequirements = certRequirementsLoader?.loader.records; | |||
const eventAccountId = event.extendedProps.record?.b3s__Job__r?.b3o__Client_Account__c; | |||
const eventJobTypeId = event.extendedProps.record?.b3s__Job__r?.b3o__Job_Type__c; | |||
const eventSiteId = event.extendedProps.record?.b3s__Site__c; | |||
const accountCertRequirements = certRequirements.filter( | |||
(req) => req.b3s__Account__c != null && req.b3s__Account__c === eventAccountId, | |||
); | ); | ||
const | const jobTypeCertRequirements = certRequirements.filter( | ||
( | (req) => req.b3s__Job_Type__c != null && req.b3s__Job_Type__c === eventJobTypeId, | ||
); | |||
const siteCertRequirements = certRequirements.filter( | |||
(req) => req.b3s__Site__c != null && req.b3s__Site__c === eventSiteId, | |||
); | ); | ||
const getMissingCertificates = function (certificates = [], certRequirements = []) { | |||
const contactCertificateTypes = new Set(certificates.map((item) => item.b3o__Certificate_Type__c)); | |||
const missingCerts = certRequirements.filter( | |||
(certReq) => !contactCertificateTypes.has(certReq.b3s__Certificate_Type__c), | |||
); | |||
return missingCerts; | |||
}; | }; | ||
const getValidCertificates = function (certificates = [], certRequirements = []) { | |||
const contactCertificateTypes = new Set(certificates.map((item) => item.b3o__Certificate_Type__c)); | |||
const missingCerts = certRequirements.filter((certReq) => | |||
contactCertificateTypes.has(certReq.b3s__Certificate_Type__c), | |||
); | |||
return missingCerts; | |||
}; | |||
const missingCerts = getMissingCertificates(contactCertificates, [...accountCertRequirements, ...jobTypeCertRequirements, ...siteCertRequirements]); | |||
let results = []; | |||
for (const missingCert of missingCerts) { | |||
results.push( | |||
new EvaluationResult({ | new EvaluationResult({ | ||
event: event, | event: event, | ||
detail: | detail: `👎 Missing ${missingCert.b3s__Certificate_Type__r.Name}`, | ||
category: ' | category: 'Certificates', | ||
points: -50, | points: -50, | ||
isBlocking: true | |||
}), | }), | ||
); | |||
} | } | ||
const validCerts = getValidCertificates(contactCertificates, [...accountCertRequirements, ...jobTypeCertRequirements, ...siteCertRequirements]); | |||
for (const validCert of validCerts) { | |||
results.push( | |||
new EvaluationResult({ | new EvaluationResult({ | ||
event: event, | event: event, | ||
detail: | detail: `👍 Has ${validCert.b3s__Certificate_Type__r.Name}`, | ||
category: ' | category: 'Certificates', | ||
points: | points: 25, | ||
}), | }), | ||
); | |||
} | } | ||
} | return results; | ||
}] | |||
</syntaxhighlight> | </syntaxhighlight> | ||