Download Barcode_C8.ts.zip file
⤳ case study requires
Node.js TypeScript
From the barcode photography of a food product, the BPMN process extracts the barcode (EAN-13 format for simplification) as a string
If extraction succeeds then the checksum is computed and checked against the 13th number in the barcode
If checksum is correct then the country of the food product is computed from a BPMN business rule task, which is itself backed by a DMN diagram including a decision table
In parallel, the nutri-score of the food product
is retrieved from https://world.openfoodfacts.org
☛
│ .barcode # Node.js environment var. including the location of Camunda 8 Run
│ .process-application # Camunda Modeler config. file to deploy all BPMN/DMN files in one shot
│ package.json # Node.js config. file using quaggaJS lib. (https://serratus.github.io/quaggaJS)
│ README.md
│ tsconfig.json # TypeScript compiler options
│
├───resources
│ Barcode.bpmn # Once Camunda 8 Run launched, deploy and next instantiate it in Camunda Modeler
│ Get_barcode_country.dmn # Automatically deployed when deploying "Barcode.bpmn"
│
└───ts # TypeScript code as client app. of Camunda 8 Run
Barcode.ts # Main program
Extract_barcode_EAN_13_from_photography.ts # Use of quaggaJS lib.
Globals.d.ts # TypeScript compiler shim for quaggaJS lib.
rule order hit policy*)
*As an example, “France” (rule 2) and
“Monaco” (rule 4) share the same rule premise;
rule order hit policy then generates a list: [{“France”, 250}, {“Monaco”, 492}]
class Photography extends Dto.LosslessDto { photography?: string }
class Barcode_EAN_13 extends Dto.LosslessDto { barcode_EAN_13?: string }
const Extract_barcode_EAN_13_from_photography = client.createJobWorker<Photography, Barcode_EAN_13>({
type: 'Extract_barcode_EAN_13_from_photography', // 'type' field in model...
timeout: 10000, // Timeout for the job worker to complete the job before it is available for another worker poll...
maxJobsToActivate: 5, // Maximum number of jobs to process concurrently...
worker: 'Extract_barcode_EAN_13_from_photography worker',
jobHandler: async (job, log) => {
console.assert(job.variables.photography, "'job.variables.photography' untrue");
const barcode_EAN_13: null | string = await _Extract_barcode_EAN_13_from_photography(job.variables.photography);
if (barcode_EAN_13) return job.complete({barcode_EAN_13: barcode_EAN_13});
return job.error({variables: {}, errorCode: "extraction_error"}); // BPMN error...
}
});
nutri_score)
class Nutri_Score extends Dto.LosslessDto { nutri_score?: string; }
const Retrieve_Nutri_Score = client.createJobWorker<Nutri_Score, any>({
type: 'Retrieve_Nutri_Score',
timeout: 10000,
maxJobsToActivate: 5,
worker: 'Retrieve_Nutri_Score END execution listener',
jobHandler: (execution_listener, log) => {
console.assert(execution_listener.variables.nutri_score, "'execution_listener.variables.nutri_score' untrue");
console.info("Nutri-Score: " + execution_listener.variables.nutri_score);
return execution_listener.complete();
}
});