UNPKG

@openinc/parse-server-opendash

Version:
333 lines (331 loc) 13 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.init = init; const cron = __importStar(require("cron")); const cron_1 = require("cron"); const __1 = require(".."); const openware_1 = require("../features/openware"); const types_1 = require("../types"); const excludeFields = [ "ACL", "updatedAt", "objectId", "tenant", "source", "unitInfo", "tag", "article", ]; const standardFields = [ "start", //date "ordernr", //0 "status", //1 "articlenr", //2 "articlename", //3 "setup_time", //4 "duration", //5 "order_quantity", //6 "targettime", //7 ]; const defaultValueTypes = [ { unit: "", name: "ordernr", type: "String" }, //0 { unit: "", name: "status", type: "String" }, //1 { unit: "", name: "articlenr", type: "String" }, //2 { unit: "", name: "articlename", type: "String" }, //3 { unit: "ms", name: "setup_time", type: "Number" }, //4 { unit: "ms", name: "duration", type: "Number" }, //5 { unit: "#", name: "order_quantity", type: "Number" }, //6 { unit: "ms", name: "targettime", type: "Number" }, //7 ]; async function init() { scheduleOrderStartedStatusCheck("0 * * * * *"); (0, __1.beforeSaveHook)(types_1.MES_Order, async (request) => { const { object, original, user } = request; // Non-sync client & Server times. ALlow 1 minute difference const nowThresholded = Date.now() - 60000; await (0, __1.defaultHandler)(request); await (0, __1.defaultAclHandler)(request, { allowCustomACL: true, allowTenantUserWrite: true, }); if (!object.tag) { const source = await object.get("source")?.fetch({ useMasterKey: true }); if (!source || !source.tag) { throw new Error("No source found in order. Cannot start order."); } object.set("tag", source.tag); } if (!object.get("articlenr")) { const article = await object .get("article") ?.fetch({ useMasterKey: true }); if (article) { object.set("articlenr", article.get("artnr")); object.set("articlename", article?.get("name")); object.set("targettime", object.targettime ? object.targettime : article?.get("targettime") || 0); } } if (object.get("status") === "canceled") { } // If the order is started and has a source, it is running if (object.get("start") && object.get("start").getTime() > nowThresholded && object.get("source") && !object.get("status")) { object.set("status", "running"); } if (object.get("start") && object.get("start").getTime() > Date.now() && object.get("source") && !object.get("status")) { object.set("status", "planned"); } // If the order is started and has no source, it is unknown if (object.get("start") && object.get("start").getTime() < nowThresholded && !object.get("source")) { object.set("status", "unknown"); } // If the order has been started and ended, it is done if (object.get("start") && object.get("duration") && (object.get("status") === "running" || object.get("status") === "planned")) { object.set("status", "done"); } }); (0, __1.afterSaveHook)(types_1.MES_Order, async (request) => { const { object, original, user } = request; try { if (original) { // If the order is canceled, publish it as canceled if (object.get("status") === "canceled" && original.get("status") !== "canceled") { const data = await object2OWItem(object); await (0, openware_1.publishDataItem)(data, user?.getEmail(), true); return; } // If the order is rescheduled, publish it as rescheduled if ((original?.get("start")?.getTime() || 0) !== (object.get("start")?.getTime() || 0)) { console.log("-".repeat(20)); console.log("Publishing rescheduled order"); console.log("-".repeat(20)); const rescheduled = await object2OWItem(original); rescheduled.values[0].value[0] = "rescheduled"; await (0, openware_1.publishDataItem)(rescheduled, user?.getEmail(), true); return; } } if (object.get("status") === "canceled") { // If order was canceled before, do not publish it return; } const data = await object2OWItem(object); await (0, openware_1.publishDataItem)(data, user?.getEmail(), true); // Publish all running orders separately to make use of these as reference values if (object.get("status") === "running") { const runningData = { ...data }; runningData.id = "ow_mes_order_running"; runningData.name = "Order_Running"; console.log("-".repeat(20)); console.log("Publishing running order " + object.id); console.log("-".repeat(20)); await (0, openware_1.publishDataItem)(runningData, user?.getEmail(), true); } } catch (e) { console.error(e); console.log("Order Data not published:" + e.message, e); } }); } async function object2OWItem(object) { const tag = object.get("tag"); const configString = await new Parse.Query("OD3_Config") .equalTo("key", "ow.mes.unitInfo") .descending("priority") .first({ useMasterKey: true }); const fieldInfos = JSON.parse(configString?.get("value") || "{}"); if (!tag || tag === "") { throw new Error("No tag found in source. Cannot publish DataItem."); } const schemaQ = new Parse.Schema("OD3_MES_Order"); //@ts-expect-error const schema = await schemaQ.get({ useMasterKey: true }); const fields = schema.fields; const extraVType = await createCustomValueTypes(object, fields, fieldInfos); const values = await createValueArrayForObject(object, extraVType, fields); const valueTypes = [...defaultValueTypes, ...extraVType]; return { id: "ow_mes_order", name: "Order", source: tag, meta: {}, valueTypes, values, }; } function createCustomValueTypes(object, fields, fieldInfos) { const keyObject = object.toJSON(); return Object.keys(keyObject) .filter((field) => { return !(excludeFields.indexOf(field) !== -1 || standardFields.indexOf(field) !== -1); }) .filter((field) => fields[field].type === "String" || fields[field].type === "Number" || fields[field].type === "Boolean") .map((field) => { const fieldData = fields[field]; switch (fieldData.type) { case "String": return { unit: "", name: field, type: "String", }; case "Number": return { unit: fieldInfos[field]?.unit || "", name: field, type: "Number", }; case "Boolean": return { unit: "", name: field, type: "Boolean", }; case "Date": return { unit: "ms", name: field, type: "Number", }; default: return { unit: "", name: field, type: "String", }; } }); } async function createValueArrayForObject(object, extraValues, fields) { const values = []; const status = object.get("status"); const ordernr = object.get("ordernr"); // const articleData = await object.get("article")?.fetch(); const article = object?.get("articlename"); const articlenr = object?.get("articlenr"); const setup_time = object.get("setup_time"); const duration = object.get("duration"); const order_quantity = object.get("order_quantity"); const targettime = object.get("targettime"); /* { unit: "", name: "ordernr", type: "String" }, //0 { unit: "", name: "status", type: "String" }, //1 { unit: "", name: "articlenr", type: "String" }, //2 { unit: "", name: "articlename", type: "String" }, //3 { unit: "ms", name: "setup_time", type: "Number" }, //4 { unit: "ms", name: "duration", type: "Number" }, //5 { unit: "#", name: "order_quantity", type: "Number" }, //6 { unit: "ms", name: "targettime", type: "Number" }, //7 */ values.push(ordernr || "unknown"); //0 values.push(status || "unknown"); //1 values.push(articlenr); //2 values.push(article); //3 values.push(setup_time ?? 0); //4 values.push(duration ?? 0); //5 values.push(order_quantity ?? 0); //6 values.push(targettime ?? 0); //7 for (const extraValue of extraValues) { let value = object.get(extraValue.name); if (value && fields[extraValue.name].type === "Date") { if (value instanceof Date) { value = value.getTime(); } } values.push(value); } return [{ date: object.get("start").getTime(), value: values }]; } function scheduleOrderStartedStatusCheck(cronInterval) { const job = new cron_1.CronJob(cronInterval, // cronTime () => { const date = new Date(Date.now() - 24 * 60 * 60 * 1000); //Orders of last 24 hours const query = new Parse.Query(types_1.MES_Order); query.greaterThanOrEqualTo("start", date); query.find({ useMasterKey: true }).then((orders) => { orders.forEach((order) => { const status = order.get("status"); if (!status) { if (order.get("tag")) { if (order.get("start").getTime() < Date.now()) { order.set("status", "running"); order.save(null, { useMasterKey: true }); } else { order.set("status", "planned"); order.save(null, { useMasterKey: true }); } } else { order.set("status", "unknown"); order.save(null, { useMasterKey: true }); } } else { if (status === "unknown" || status === "planned") { if (order.get("start").getTime() < Date.now()) { order.set("status", "running"); order.save(null, { useMasterKey: true }); } } } }); }); }, () => { const dt = cron.sendAt(cronInterval); }, // onComplete true, // start "Europe/Berlin" // timeZone ); }