@acorex-platform/module-maintenance-management-client 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/fesm2022/acorex-platform-module-maintenance-management-client-acorex-platform-module-maintenance-management-client-BiQlJxPX.mjs +2698 -0
  2. package/fesm2022/acorex-platform-module-maintenance-management-client-acorex-platform-module-maintenance-management-client-BiQlJxPX.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-module-maintenance-management-client-contracts.mjs +405 -0
  4. package/fesm2022/acorex-platform-module-maintenance-management-client-contracts.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-module-maintenance-management-client-create-or-get-work-report-draft.activity-xxvOfIxf.mjs +141 -0
  6. package/fesm2022/acorex-platform-module-maintenance-management-client-create-or-get-work-report-draft.activity-xxvOfIxf.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-module-maintenance-management-client-failure-register-status.provider-CLBaQy_e.mjs +181 -0
  8. package/fesm2022/acorex-platform-module-maintenance-management-client-failure-register-status.provider-CLBaQy_e.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-module-maintenance-management-client-fill-work-report-completion.command-Capowl1e.mjs +174 -0
  10. package/fesm2022/acorex-platform-module-maintenance-management-client-fill-work-report-completion.command-Capowl1e.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-maintenance-management-client-open-work-report-from-work-order.command-B0O4fWPt.mjs +105 -0
  12. package/fesm2022/acorex-platform-module-maintenance-management-client-open-work-report-from-work-order.command-B0O4fWPt.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-module-maintenance-management-client-record-work-report-assessment.activity-CxRfaf0G.mjs +152 -0
  14. package/fesm2022/acorex-platform-module-maintenance-management-client-record-work-report-assessment.activity-CxRfaf0G.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-module-maintenance-management-client-resolve-person-user-id.activity-nwXAJHkd.mjs +57 -0
  16. package/fesm2022/acorex-platform-module-maintenance-management-client-resolve-person-user-id.activity-nwXAJHkd.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-module-maintenance-management-client-resolve-work-order.activity-q5WM7Sv5.mjs +92 -0
  18. package/fesm2022/acorex-platform-module-maintenance-management-client-resolve-work-order.activity-q5WM7Sv5.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-module-maintenance-management-client-start-work-order-flow.command-B06a962Y.mjs +402 -0
  20. package/fesm2022/acorex-platform-module-maintenance-management-client-start-work-order-flow.command-B06a962Y.mjs.map +1 -0
  21. package/fesm2022/acorex-platform-module-maintenance-management-client-update-work-order-completed.activity-Di4R6LQl.mjs +89 -0
  22. package/fesm2022/acorex-platform-module-maintenance-management-client-update-work-order-completed.activity-Di4R6LQl.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-module-maintenance-management-client-update-work-order-in-progress.activity-CzkCCl1L.mjs +96 -0
  24. package/fesm2022/acorex-platform-module-maintenance-management-client-update-work-order-in-progress.activity-CzkCCl1L.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-module-maintenance-management-client-update-work-report-on-completion.activity-_B0SUFtQ.mjs +142 -0
  26. package/fesm2022/acorex-platform-module-maintenance-management-client-update-work-report-on-completion.activity-_B0SUFtQ.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-module-maintenance-management-client-validate-work-order-completion.activity-RA2zaQHH.mjs +83 -0
  28. package/fesm2022/acorex-platform-module-maintenance-management-client-validate-work-order-completion.activity-RA2zaQHH.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-list-command-Bh_6PS5w.mjs +153 -0
  30. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-list-command-Bh_6PS5w.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-status.provider-DvBk5kAW.mjs +186 -0
  32. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-status.provider-DvBk5kAW.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-work-report-column.component-Bf1WZWIS.mjs +163 -0
  34. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-work-report-column.component-Bf1WZWIS.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-workflow-column.component-Dth3Z9fW.mjs +320 -0
  36. package/fesm2022/acorex-platform-module-maintenance-management-client-work-order-workflow-column.component-Dth3Z9fW.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-module-maintenance-management-client-work-report-assessment.util-Da1HVAit.mjs +74 -0
  38. package/fesm2022/acorex-platform-module-maintenance-management-client-work-report-assessment.util-Da1HVAit.mjs.map +1 -0
  39. package/fesm2022/acorex-platform-module-maintenance-management-client-work-report-checklist-results-view.component-BSFW0Yt-.mjs +149 -0
  40. package/fesm2022/acorex-platform-module-maintenance-management-client-work-report-checklist-results-view.component-BSFW0Yt-.mjs.map +1 -0
  41. package/fesm2022/acorex-platform-module-maintenance-management-client.mjs +2 -0
  42. package/fesm2022/acorex-platform-module-maintenance-management-client.mjs.map +1 -0
  43. package/package.json +28 -0
  44. package/types/acorex-platform-module-maintenance-management-client-contracts.d.ts +1081 -0
  45. package/types/acorex-platform-module-maintenance-management-client.d.ts +54 -0
@@ -0,0 +1,2698 @@
1
+ import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/auth';
2
+ import { AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER, AXP_STATUS_PROVIDERS, AXPSearchCommandProvider, createEntityCommandOptions } from '@acorex-platform/framework-client/common';
3
+ import { AXPDebugService, AXP_MODULE_MANIFEST_PROVIDER, AXP_CATALOG_SCOPE_DEFINITION_PROVIDER, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, provideLazyProvider } from '@acorex-platform/framework-client/core';
4
+ import { AXPEntityStorageService, AXPEntityDefinitionRegistryService, AXPEntityDataSelectorService, AXPEntityService, AXP_ENTITY_STORAGE_MIDDLEWARE } from '@acorex-platform/framework-client/layout/entity';
5
+ import { AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/layout/widget-core';
6
+ import { AXPCommandService, provideCommandMiddleware, provideCommandSetups } from '@acorex-platform/framework-client/runtime';
7
+ import * as i0 from '@angular/core';
8
+ import { inject, Injectable, NgModule } from '@angular/core';
9
+ import { RootConfig, AXMWorkOrderSourceType, AXMWorkOrderStatus, AXMMaintenanceManagementCommandKeys, MM_CATALOG_SCOPE_MN, AXPAssetsMaintenancePermissionKeys, AXMMaintenanceManagementMenuKeys } from '@acorex-platform/module-maintenance-management-client/contracts';
10
+ import { AXDialogService } from '@acorex/components/dialog';
11
+ import { AXToastService } from '@acorex/components/toast';
12
+ import { isValidMultiLanguageObject, resolveMultiLanguageString, AXTranslationService, createMultiLanguageString } from '@acorex/core/translation';
13
+ import { AXP_IDENTIFIER_SERVICE } from '@acorex-platform/module-identifier-management-client';
14
+ import { isString, get, isNumber, defaultTo, isObject, isEmpty, isNil } from 'lodash';
15
+ import { AXPEntityCommandScope } from '@acorex-platform/framework-shared/entity';
16
+ import { AXPWidgetGroupEnum } from '@acorex-platform/framework-shared/widget-core';
17
+ import { AXPCommonMenuKeys, AXPCommonPermissionGroupKeys } from '@acorex-platform/module-common-client/contracts';
18
+ import { AXMAssetManagementCommandKeys } from '@acorex-platform/module-asset-management-client/contracts';
19
+
20
+ //#region ---- Workflow debug namespace ----
21
+ const AXM_WORK_ORDER_WORKFLOW_DEBUG_NAMESPACE = 'maintenance-management';
22
+ //#endregion
23
+
24
+ //#region ---- Imports ----
25
+ //#endregion
26
+ //#region ---- Manifest Definition ----
27
+ /**
28
+ * Maintenance Management Module Manifest.
29
+ * Defines module metadata, features, and provider references.
30
+ */
31
+ const MaintenanceManagementManifest = {
32
+ name: RootConfig.module.name,
33
+ version: '1.0.0',
34
+ title: RootConfig.module.title,
35
+ icon: RootConfig.module.icon,
36
+ i18n: RootConfig.config.i18n,
37
+ type: 'domain',
38
+ domain: 'asset-maintenance',
39
+ required: false,
40
+ // Module dependencies (optional)
41
+ };
42
+ //#endregion
43
+
44
+ //#region ---- Imports ----
45
+ //#endregion
46
+ //#region ---- Identifier rules ----
47
+ const MAINTENANCE_PLAN_CODE_RULE_ID = 'maintenance-plan-code';
48
+ const WORK_ORDER_NO_RULE_ID = 'work-order-no';
49
+ //#endregion
50
+ //#region ---- Helpers ----
51
+ const MAX_BY_DATE_OCCURRENCES = 10_000;
52
+ function isTruthyFlag(value) {
53
+ return [true, 'true', 1, '1'].includes(value);
54
+ }
55
+ function isMultiLanguageString(value) {
56
+ return isValidMultiLanguageObject(value);
57
+ }
58
+ /**
59
+ * Normalizes plain or multilingual labels into a bilingual {@link AXPMultiLanguageString}.
60
+ */
61
+ function normalizeMultiLanguageString(value, fallback) {
62
+ if (!value) {
63
+ return { 'en-US': fallback, 'fa-IR': fallback };
64
+ }
65
+ if (isString(value)) {
66
+ return { 'en-US': value, 'fa-IR': value };
67
+ }
68
+ if (isMultiLanguageString(value)) {
69
+ const en = resolveMultiLanguageString(value, 'en-US') || fallback;
70
+ const fa = resolveMultiLanguageString(value, 'fa-IR') || en;
71
+ return { 'en-US': en, 'fa-IR': fa };
72
+ }
73
+ return { 'en-US': fallback, 'fa-IR': fallback };
74
+ }
75
+ /**
76
+ * Resolves a display label for dialogs and messages (defaults to en-US).
77
+ */
78
+ function resolveDisplayLabel(value, fallback, locale = 'en-US') {
79
+ if (!value) {
80
+ return fallback;
81
+ }
82
+ if (isString(value)) {
83
+ return value;
84
+ }
85
+ return resolveMultiLanguageString(value, locale) || fallback;
86
+ }
87
+ function combineMultiLanguageTitle(left, leftFallback, right, rightFallback) {
88
+ const leftMl = normalizeMultiLanguageString(left, leftFallback);
89
+ const rightMl = normalizeMultiLanguageString(right, rightFallback);
90
+ return {
91
+ 'en-US': `${leftMl['en-US']} - ${rightMl['en-US']}`,
92
+ 'fa-IR': `${leftMl['fa-IR']} - ${rightMl['fa-IR']}`,
93
+ };
94
+ }
95
+ function toDate(value) {
96
+ if (value instanceof Date) {
97
+ return Number.isNaN(value.getTime()) ? undefined : new Date(value.getTime());
98
+ }
99
+ if (typeof value === 'string' && value.length > 0) {
100
+ const parsed = new Date(value);
101
+ return Number.isNaN(parsed.getTime()) ? undefined : parsed;
102
+ }
103
+ return undefined;
104
+ }
105
+ /** Treat schedule end dates as inclusive through the end of the calendar day. */
106
+ function toScheduleEndBoundary(value) {
107
+ const date = toDate(value);
108
+ if (!date) {
109
+ return undefined;
110
+ }
111
+ const boundary = new Date(date.getTime());
112
+ boundary.setHours(23, 59, 59, 999);
113
+ return boundary;
114
+ }
115
+ function toIsoString(date) {
116
+ return date.toISOString();
117
+ }
118
+ function inferScheduleMode(schedule) {
119
+ const mode = get(schedule, 'mode');
120
+ if (mode === 'hourly' ||
121
+ mode === 'daily' ||
122
+ mode === 'weekly' ||
123
+ mode === 'monthly' ||
124
+ mode === 'yearly') {
125
+ return mode;
126
+ }
127
+ const recurrence = get(schedule, 'recurrence');
128
+ switch (recurrence) {
129
+ case 'hourly':
130
+ return 'hourly';
131
+ case 'daily':
132
+ return 'daily';
133
+ case 'weekly':
134
+ return 'weekly';
135
+ case 'monthly':
136
+ return 'monthly';
137
+ case 'yearly':
138
+ return 'yearly';
139
+ default:
140
+ return 'daily';
141
+ }
142
+ }
143
+ function resolveScheduleInterval(schedule) {
144
+ const interval = get(schedule, 'interval');
145
+ return isNumber(interval) && interval > 0 ? interval : 1;
146
+ }
147
+ /**
148
+ * Anchor date for the first work-order occurrence (now, byDate, or onDemand).
149
+ */
150
+ function resolveScheduleAnchorDate(schedule, referenceDate = new Date()) {
151
+ if (!schedule) {
152
+ return undefined;
153
+ }
154
+ const startType = get(schedule, 'startCondition.type');
155
+ if (startType === 'onDemand') {
156
+ return undefined;
157
+ }
158
+ if (startType === 'now') {
159
+ return new Date(referenceDate.getTime());
160
+ }
161
+ const configuredStart = toDate(get(schedule, 'startCondition.startDate'));
162
+ if (configuredStart) {
163
+ return configuredStart;
164
+ }
165
+ return undefined;
166
+ }
167
+ function addScheduleInterval(anchor, mode, interval, step) {
168
+ const result = new Date(anchor.getTime());
169
+ const amount = step * interval;
170
+ switch (mode) {
171
+ case 'hourly':
172
+ result.setHours(result.getHours() + amount);
173
+ break;
174
+ case 'daily':
175
+ result.setDate(result.getDate() + amount);
176
+ break;
177
+ case 'weekly':
178
+ result.setDate(result.getDate() + amount * 7);
179
+ break;
180
+ case 'monthly':
181
+ result.setMonth(result.getMonth() + amount);
182
+ break;
183
+ case 'yearly':
184
+ result.setFullYear(result.getFullYear() + amount);
185
+ break;
186
+ }
187
+ return result;
188
+ }
189
+ function resolveOccurrenceScheduledEnd(scheduledStart, estimatedHours) {
190
+ if (!isNumber(estimatedHours) || estimatedHours <= 0) {
191
+ return undefined;
192
+ }
193
+ const end = new Date(scheduledStart.getTime());
194
+ end.setTime(end.getTime() + estimatedHours * 60 * 60 * 1000);
195
+ return toIsoString(end);
196
+ }
197
+ /**
198
+ * Resolves scheduled start dates for work orders from a maintenance plan schedule.
199
+ *
200
+ * - End `never`: first occurrence only (next ones are generated later).
201
+ * - End `afterOccurrences`: all occurrences up to the configured count.
202
+ * - End `byDate`: occurrences from anchor through end date (inclusive).
203
+ */
204
+ function resolveWorkOrderScheduledStarts(schedule, referenceDate = new Date()) {
205
+ if (!schedule) {
206
+ return [];
207
+ }
208
+ const anchor = resolveScheduleAnchorDate(schedule, referenceDate);
209
+ if (!anchor) {
210
+ return [];
211
+ }
212
+ const mode = inferScheduleMode(schedule);
213
+ const interval = resolveScheduleInterval(schedule);
214
+ const endType = defaultTo(get(schedule, 'endCondition.type'), 'never');
215
+ if (endType === 'never') {
216
+ return [anchor];
217
+ }
218
+ if (endType === 'afterOccurrences') {
219
+ const count = Math.max(1, defaultTo(get(schedule, 'endCondition.occurrences'), 1));
220
+ return Array.from({ length: count }, (_, step) => addScheduleInterval(anchor, mode, interval, step));
221
+ }
222
+ if (endType === 'byDate') {
223
+ const endDate = toScheduleEndBoundary(get(schedule, 'endCondition.endDate'));
224
+ if (!endDate) {
225
+ return [anchor];
226
+ }
227
+ const starts = [];
228
+ for (let step = 0; step < MAX_BY_DATE_OCCURRENCES; step += 1) {
229
+ const occurrence = addScheduleInterval(anchor, mode, interval, step);
230
+ if (occurrence.getTime() > endDate.getTime()) {
231
+ break;
232
+ }
233
+ starts.push(occurrence);
234
+ }
235
+ return starts;
236
+ }
237
+ return [anchor];
238
+ }
239
+ function resolveWorkOrderOccurrences(schedule, options) {
240
+ const referenceDate = options?.referenceDate ?? new Date();
241
+ const starts = resolveWorkOrderScheduledStarts(schedule, referenceDate);
242
+ const estimatedHours = options?.estimatedHours;
243
+ if (starts.length === 0) {
244
+ return [{}];
245
+ }
246
+ return starts.map((scheduledStart) => {
247
+ const scheduledEnd = resolveOccurrenceScheduledEnd(scheduledStart, estimatedHours);
248
+ return {
249
+ scheduledStart: toIsoString(scheduledStart),
250
+ ...(scheduledEnd ? { scheduledEnd } : {}),
251
+ };
252
+ });
253
+ }
254
+ /**
255
+ * Returns how many work orders will be created from a plan schedule (minimum 1 when schedule is absent or on-demand).
256
+ */
257
+ function countWorkOrdersToCreateFromSchedule(schedule, referenceDate = new Date()) {
258
+ return resolveWorkOrderOccurrences(schedule, { referenceDate }).length;
259
+ }
260
+ function resolveScheduledStart(schedule, referenceDate = new Date()) {
261
+ const starts = resolveWorkOrderScheduledStarts(schedule, referenceDate);
262
+ const first = starts[0];
263
+ return first ? toIsoString(first) : undefined;
264
+ }
265
+ /** Internal flag on plan create payloads; stripped before persistence when supported. */
266
+ const SUPPRESS_WORK_ORDER_PROMPT_FIELD = '__suppressWorkOrderPrompt';
267
+ /**
268
+ * Allocates and commits the next identifier code for programmatic entity creates.
269
+ * Validation runs before identifier middleware (order 5); the code must be on the payload.
270
+ * Uses `generate` (not `peek`) so back-to-back creates in a loop receive distinct codes.
271
+ */
272
+ async function allocateIdentifierCode(identifierService, sessionService, ruleId) {
273
+ const result = await identifierService.generate({
274
+ id: ruleId,
275
+ tenantId: sessionService.tenant?.id,
276
+ appId: sessionService.application?.id,
277
+ });
278
+ return result.code;
279
+ }
280
+ function buildMaintenancePlanPayload(asset, template, options) {
281
+ return {
282
+ ...(options?.code ? { code: options.code } : {}),
283
+ title: combineMultiLanguageTitle(template.title, template.code ?? 'Template', asset.title, asset.code ?? 'Asset'),
284
+ description: template.description,
285
+ assetId: asset.id,
286
+ maintenanceTypeId: template.maintenanceTypeId,
287
+ maintenanceTemplateId: template.id,
288
+ schedule: template.schedule ?? {
289
+ startCondition: { type: 'byDate', startDate: new Date().toISOString() },
290
+ },
291
+ estimatedHours: template.estimatedMinutes
292
+ ? Math.max(1, Math.ceil(template.estimatedMinutes / 60))
293
+ : undefined,
294
+ needPermission: !!template.needPermission,
295
+ needShutdown: !!template.needShutdown,
296
+ ...(options?.autoGeneratedPlan ? { autoGeneratedPlan: true } : {}),
297
+ ...(options?.suppressWorkOrderPrompt
298
+ ? { [SUPPRESS_WORK_ORDER_PROMPT_FIELD]: true }
299
+ : {}),
300
+ };
301
+ }
302
+ async function resolveMaintenanceTemplate(backend, templateEntityName, partial) {
303
+ if (!partial?.id) {
304
+ return null;
305
+ }
306
+ if (partial.maintenanceTypeId) {
307
+ return partial;
308
+ }
309
+ const loaded = (await backend
310
+ .getOne(templateEntityName, partial.id)
311
+ .catch(() => null));
312
+ return loaded?.maintenanceTypeId ? loaded : null;
313
+ }
314
+ function resolveRelationId(value) {
315
+ if (isString(value)) {
316
+ const trimmed = value.trim();
317
+ return trimmed || undefined;
318
+ }
319
+ if (isObject(value)) {
320
+ const id = get(value, 'id');
321
+ if (isString(id)) {
322
+ const trimmed = id.trim();
323
+ return trimmed || undefined;
324
+ }
325
+ }
326
+ return undefined;
327
+ }
328
+ /**
329
+ * Normalizes lookup-style relation values on a plan to plain ids for work-order generation.
330
+ */
331
+ function normalizePlanRelationIds(plan) {
332
+ return {
333
+ ...plan,
334
+ assetId: resolveRelationId(plan.assetId) ?? plan.assetId,
335
+ maintenanceTypeId: resolveRelationId(plan.maintenanceTypeId) ?? plan.maintenanceTypeId,
336
+ maintenanceTemplateId: resolveRelationId(plan.maintenanceTemplateId) ?? plan.maintenanceTemplateId,
337
+ assignedToId: resolveRelationId(plan.assignedToId) ?? plan.assignedToId,
338
+ priorityId: resolveRelationId(plan.priorityId) ?? resolveRelationId(plan.priority?.id) ?? plan.priorityId,
339
+ };
340
+ }
341
+ /**
342
+ * Merges persisted plan with create-time fields that may not be returned by `getOne` yet.
343
+ * Stored values win; missing work-order fields are filled from the create payload.
344
+ */
345
+ function mergeMaintenancePlanForWorkOrder(createPayload, stored, id) {
346
+ if (!stored && !createPayload) {
347
+ return null;
348
+ }
349
+ const merged = {
350
+ ...(createPayload ?? {}),
351
+ ...(stored ?? {}),
352
+ id: stored?.id ?? id,
353
+ };
354
+ delete merged[SUPPRESS_WORK_ORDER_PROMPT_FIELD];
355
+ if (!createPayload) {
356
+ return normalizePlanRelationIds(merged);
357
+ }
358
+ const fillIfMissing = (key) => {
359
+ const storedValue = merged[key];
360
+ const createValue = createPayload[key];
361
+ const storedEmpty = storedValue === undefined ||
362
+ storedValue === null ||
363
+ (typeof storedValue === 'string' && storedValue.trim() === '');
364
+ if (storedEmpty && createValue !== undefined && createValue !== null) {
365
+ merged[key] = createValue;
366
+ }
367
+ };
368
+ fillIfMissing('assetId');
369
+ fillIfMissing('maintenanceTypeId');
370
+ fillIfMissing('maintenanceTemplateId');
371
+ fillIfMissing('schedule');
372
+ fillIfMissing('title');
373
+ fillIfMissing('description');
374
+ fillIfMissing('needPermission');
375
+ fillIfMissing('needShutdown');
376
+ fillIfMissing('assignedToId');
377
+ fillIfMissing('assignedTo');
378
+ fillIfMissing('priorityId');
379
+ fillIfMissing('priority');
380
+ fillIfMissing('estimatedHours');
381
+ return normalizePlanRelationIds(merged);
382
+ }
383
+ /**
384
+ * Normalizes plan priority for work-order payload.
385
+ */
386
+ function resolvePlanPriorityId(plan) {
387
+ const priorityId = plan.priorityId?.trim() || plan.priority?.id?.trim();
388
+ return priorityId || undefined;
389
+ }
390
+ /**
391
+ * Normalizes plan estimated hours (supports numeric strings from forms/storage).
392
+ */
393
+ function resolvePlanEstimatedHours(plan) {
394
+ const raw = plan.estimatedHours;
395
+ if (isNumber(raw) && raw >= 0) {
396
+ return raw;
397
+ }
398
+ if (isString(raw)) {
399
+ const parsed = Number(raw);
400
+ if (!Number.isNaN(parsed) && parsed >= 0) {
401
+ return parsed;
402
+ }
403
+ }
404
+ return undefined;
405
+ }
406
+ const EMPLOYEE_ENTITY = 'HumanCapitalManagement.Employee';
407
+ /**
408
+ * Maintenance plan `assignedToId` stores Employee id; work order `assignedToId` expects Person id.
409
+ */
410
+ async function resolvePlanAssignedToForWorkOrder(backend, plan) {
411
+ const employeeId = plan.assignedToId?.trim();
412
+ if (!employeeId) {
413
+ return {};
414
+ }
415
+ const employee = (await backend.getOne(EMPLOYEE_ENTITY, employeeId).catch(() => null));
416
+ const personId = employee?.personId?.trim() || employee?.person?.id?.trim();
417
+ if (!personId) {
418
+ return {};
419
+ }
420
+ const fullName = employee?.person?.fullName?.trim() || employee?.person?.displayName?.trim();
421
+ return {
422
+ assignedToId: personId,
423
+ assignedTo: fullName ? { id: personId, fullName } : { id: personId },
424
+ };
425
+ }
426
+ /**
427
+ * Resolves work-order assignment, priority, and estimated hours from a maintenance plan.
428
+ */
429
+ async function resolvePlanFieldsForWorkOrder(backend, plan) {
430
+ const assignment = await resolvePlanAssignedToForWorkOrder(backend, plan);
431
+ const priorityId = resolvePlanPriorityId(plan);
432
+ const estimatedHours = resolvePlanEstimatedHours(plan);
433
+ return {
434
+ ...assignment,
435
+ ...(priorityId ? { priorityId } : {}),
436
+ ...(estimatedHours !== undefined ? { estimatedHours } : {}),
437
+ };
438
+ }
439
+ function buildWorkOrderPayloadFromFailureRegister(failureRegister, template, workOrderNo) {
440
+ const title = normalizeMultiLanguageString(template.title, template.code ?? 'Template');
441
+ return {
442
+ workOrderNo,
443
+ assetId: failureRegister.assetId,
444
+ maintenanceTypeId: template.maintenanceTypeId,
445
+ maintenanceTemplateId: template.id,
446
+ failureRegisterId: failureRegister.id,
447
+ priorityId: failureRegister.priorityId,
448
+ title,
449
+ description: failureRegister.description,
450
+ needPermission: !!template.needPermission,
451
+ needShutdown: !!template.needShutdown,
452
+ statusId: AXMWorkOrderStatus.Planned,
453
+ sourceType: AXMWorkOrderSourceType.FailureRegister,
454
+ isArchived: false,
455
+ isDeleted: false,
456
+ };
457
+ }
458
+ function buildWorkOrderPayloadFromPlan(plan, workOrderNo, options) {
459
+ const title = normalizeMultiLanguageString(plan.title, plan.code ?? 'Work order');
460
+ const occurrence = options?.occurrence ??
461
+ resolveWorkOrderOccurrences(plan.schedule, {
462
+ referenceDate: options?.referenceDate,
463
+ estimatedHours: resolvePlanEstimatedHours(plan),
464
+ })[0];
465
+ const fields = options?.workOrderFields ?? {};
466
+ const priorityId = fields.priorityId ?? resolvePlanPriorityId(plan);
467
+ const estimatedHours = fields.estimatedHours ?? resolvePlanEstimatedHours(plan);
468
+ return {
469
+ workOrderNo,
470
+ assetId: plan.assetId,
471
+ maintenanceTypeId: plan.maintenanceTypeId,
472
+ maintenanceTemplateId: plan.maintenanceTemplateId,
473
+ maintenancePlanId: plan.id,
474
+ title,
475
+ description: plan.description,
476
+ scheduledStart: occurrence?.scheduledStart,
477
+ ...(options?.includeScheduledEnd && occurrence?.scheduledEnd
478
+ ? { scheduledEnd: occurrence.scheduledEnd }
479
+ : {}),
480
+ ...(fields.assignedToId
481
+ ? {
482
+ assignedToId: fields.assignedToId,
483
+ ...(fields.assignedTo ? { assignedTo: fields.assignedTo } : {}),
484
+ }
485
+ : {}),
486
+ ...(priorityId ? { priorityId } : {}),
487
+ ...(estimatedHours !== undefined ? { estimatedHours } : {}),
488
+ needPermission: !!plan.needPermission,
489
+ needShutdown: !!plan.needShutdown,
490
+ ...(options?.autoGeneratedWorkOrder ? { autoGeneratedWorkOrder: true } : {}),
491
+ statusId: AXMWorkOrderStatus.Planned,
492
+ sourceType: options?.sourceType ?? AXMWorkOrderSourceType.MaintenancePlan,
493
+ isArchived: false,
494
+ isDeleted: false,
495
+ };
496
+ }
497
+ /**
498
+ * Builds one work-order payload per schedule occurrence (count varies by end condition).
499
+ */
500
+ function buildWorkOrderPayloadsFromPlan(plan, options) {
501
+ const referenceDate = options?.referenceDate ?? new Date();
502
+ const estimatedHours = resolvePlanEstimatedHours(plan);
503
+ const occurrences = resolveWorkOrderOccurrences(plan.schedule, {
504
+ referenceDate,
505
+ estimatedHours,
506
+ });
507
+ const selectedOccurrences = options?.autoGeneratedWorkOrder ? occurrences.slice(0, 1) : occurrences;
508
+ return selectedOccurrences.map((occurrence) => buildWorkOrderPayloadFromPlan(plan, '', {
509
+ autoGeneratedWorkOrder: options?.autoGeneratedWorkOrder,
510
+ referenceDate,
511
+ occurrence,
512
+ sourceType: options?.sourceType,
513
+ workOrderFields: options?.workOrderFields,
514
+ includeScheduledEnd: options?.includeScheduledEnd,
515
+ }));
516
+ }
517
+ /**
518
+ * Inserts all work orders implied by the plan schedule (peek identifier per row).
519
+ */
520
+ async function insertWorkOrdersFromPlan(entityStorage, identifierService, sessionService, workOrderEntityName, plan, options) {
521
+ const resolvedPlan = normalizePlanRelationIds(plan);
522
+ const workOrderFields = options?.backend ? await resolvePlanFieldsForWorkOrder(options.backend, resolvedPlan) : {};
523
+ const payloads = buildWorkOrderPayloadsFromPlan(resolvedPlan, {
524
+ autoGeneratedWorkOrder: options?.autoGeneratedWorkOrder,
525
+ referenceDate: options?.referenceDate,
526
+ sourceType: options?.sourceType,
527
+ workOrderFields,
528
+ includeScheduledEnd: false,
529
+ });
530
+ let createdCount = 0;
531
+ for (const payload of payloads) {
532
+ const workOrderNo = await allocateIdentifierCode(identifierService, sessionService, WORK_ORDER_NO_RULE_ID);
533
+ await entityStorage.insertOne(workOrderEntityName, { ...payload, workOrderNo });
534
+ createdCount += 1;
535
+ }
536
+ return createdCount;
537
+ }
538
+ function canCreateWorkOrderFromFailureRegister(failureRegister, template) {
539
+ return !!(failureRegister.assetId && template.id && template.maintenanceTypeId);
540
+ }
541
+ function canCreateWorkOrderFromPlan(plan) {
542
+ const normalized = normalizePlanRelationIds(plan);
543
+ return !!(normalized.assetId &&
544
+ normalized.maintenanceTypeId &&
545
+ normalized.maintenanceTemplateId);
546
+ }
547
+ function isMaintenanceTemplateLike(row) {
548
+ if (!row || typeof row !== 'object') {
549
+ return false;
550
+ }
551
+ const candidate = row;
552
+ return typeof candidate.id === 'string' && typeof candidate.maintenanceTypeId === 'string';
553
+ }
554
+ async function queryAutoGenerateTemplatesForAssetType(backend, templateEntityName, assetTypeId) {
555
+ const result = await backend
556
+ .query(templateEntityName, {
557
+ skip: 0,
558
+ take: 200,
559
+ filter: {
560
+ logic: 'and',
561
+ filters: [
562
+ { field: 'assetTypeId', operator: { type: 'equal' }, value: assetTypeId },
563
+ { field: 'autoGeneratePlan', operator: { type: 'equal' }, value: true },
564
+ ],
565
+ },
566
+ })
567
+ .catch(() => ({ total: 0, items: [] }));
568
+ const items = result.items ?? [];
569
+ return items.filter(isMaintenanceTemplateLike);
570
+ }
571
+ const ASSET_ENTITY$2 = 'AssetManagement.Asset';
572
+ const ASSET_TYPE_ENTITY$1 = 'AssetManagement.AssetType';
573
+ function isWorkflowEnabledOnTemplate(template) {
574
+ const config = template.workflowConfig;
575
+ if (!config?.workflowDefinitionId?.trim() || !config?.workflowName?.trim()) {
576
+ return false;
577
+ }
578
+ return config.enabled !== false;
579
+ }
580
+ /**
581
+ * Resolves asset → asset type maintenance types → maintenance templates with an enabled workflow.
582
+ */
583
+ async function queryWorkflowTemplatesForAsset(backend, templateEntityName, assetId) {
584
+ const trimmedAssetId = assetId?.trim();
585
+ if (!trimmedAssetId) {
586
+ return [];
587
+ }
588
+ const asset = (await backend.getOne(ASSET_ENTITY$2, trimmedAssetId).catch(() => null));
589
+ const assetTypeId = asset?.assetTypeId?.trim();
590
+ if (!asset || !assetTypeId) {
591
+ return [];
592
+ }
593
+ const assetType = (await backend.getOne(ASSET_TYPE_ENTITY$1, assetTypeId).catch(() => null));
594
+ const maintenanceTypeIds = (assetType?.maintenanceTypeIds ?? []).filter((id) => isString(id) && id.trim());
595
+ if (maintenanceTypeIds.length === 0) {
596
+ return [];
597
+ }
598
+ const result = await backend
599
+ .query(templateEntityName, {
600
+ skip: 0,
601
+ take: 500,
602
+ filter: {
603
+ logic: 'and',
604
+ filters: [
605
+ { field: 'assetTypeId', operator: { type: 'equal' }, value: assetTypeId },
606
+ { field: 'maintenanceTypeId', operator: { type: 'in' }, value: maintenanceTypeIds },
607
+ ],
608
+ },
609
+ })
610
+ .catch(() => ({ total: 0, items: [] }));
611
+ const rawItems = result.items ?? [];
612
+ const items = rawItems.filter(isMaintenanceTemplateLike);
613
+ return items.filter((template) => isWorkflowEnabledOnTemplate(template));
614
+ }
615
+ async function hasWorkOrderForPlan(backend, workOrderEntityName, planId) {
616
+ const result = await backend
617
+ .query(workOrderEntityName, {
618
+ skip: 0,
619
+ take: 1,
620
+ filter: {
621
+ field: 'maintenancePlanId',
622
+ operator: { type: 'equal' },
623
+ value: planId,
624
+ },
625
+ })
626
+ .catch(() => ({ total: 0, items: [] }));
627
+ return (result.total ?? 0) > 0 || (result.items?.length ?? 0) > 0;
628
+ }
629
+ async function countWorkOrdersForMaintenancePlan(backend, workOrderEntityName, planId) {
630
+ const result = await backend
631
+ .query(workOrderEntityName, {
632
+ skip: 0,
633
+ take: 1,
634
+ filter: {
635
+ field: 'maintenancePlanId',
636
+ operator: { type: 'equal' },
637
+ value: planId,
638
+ },
639
+ })
640
+ .catch(() => ({ total: 0 }));
641
+ return result.total ?? 0;
642
+ }
643
+ async function hasWorkOrderForPlanScheduledStart(backend, workOrderEntityName, planId, scheduledStart) {
644
+ const result = await backend
645
+ .query(workOrderEntityName, {
646
+ skip: 0,
647
+ take: 1,
648
+ filter: {
649
+ logic: 'and',
650
+ filters: [
651
+ { field: 'maintenancePlanId', operator: { type: 'equal' }, value: planId },
652
+ { field: 'scheduledStart', operator: { type: 'equal' }, value: scheduledStart },
653
+ ],
654
+ },
655
+ })
656
+ .catch(() => ({ total: 0, items: [] }));
657
+ return (result.total ?? 0) > 0 || (result.items?.length ?? 0) > 0;
658
+ }
659
+ /**
660
+ * Resolves the next scheduled work-order occurrence after a signed-off work order.
661
+ * For `endCondition.type === 'never'`, returns the next interval from the signed-off scheduled start.
662
+ */
663
+ function resolveNextWorkOrderOccurrenceAfterSignedOff(plan, signedOffWorkOrder, referenceDate = new Date()) {
664
+ const schedule = plan.schedule;
665
+ if (!schedule) {
666
+ return null;
667
+ }
668
+ const startType = get(schedule, 'startCondition.type');
669
+ if (startType === 'onDemand') {
670
+ return null;
671
+ }
672
+ const anchor = toDate(signedOffWorkOrder.scheduledStart) ?? resolveScheduleAnchorDate(schedule, referenceDate);
673
+ if (!anchor) {
674
+ return null;
675
+ }
676
+ const mode = inferScheduleMode(schedule);
677
+ const interval = resolveScheduleInterval(schedule);
678
+ const nextStart = addScheduleInterval(anchor, mode, interval, 1);
679
+ const endType = defaultTo(get(schedule, 'endCondition.type'), 'never');
680
+ if (endType === 'byDate') {
681
+ const endDate = toScheduleEndBoundary(get(schedule, 'endCondition.endDate'));
682
+ if (endDate && nextStart.getTime() > endDate.getTime()) {
683
+ return null;
684
+ }
685
+ }
686
+ const estimatedHours = resolvePlanEstimatedHours(plan);
687
+ const scheduledEnd = resolveOccurrenceScheduledEnd(nextStart, estimatedHours);
688
+ return {
689
+ scheduledStart: toIsoString(nextStart),
690
+ ...(scheduledEnd ? { scheduledEnd } : {}),
691
+ };
692
+ }
693
+ //#endregion
694
+
695
+ //#region ---- Imports ----
696
+ //#endregion
697
+ //#region ---- Constants ----
698
+ const ASSET_ENTITY$1 = 'AssetManagement.Asset';
699
+ async function askMaintenanceOfferChoice(dialogService, translateService, templateCount, assetTitle) {
700
+ const title = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.title');
701
+ const content = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.content', { params: { count: templateCount, assetTitle } });
702
+ const plansOnlyLabel = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.actions.plans-only');
703
+ const plansAndWorkOrdersLabel = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.actions.plans-and-work-orders');
704
+ const cancelLabel = await translateService.translateAsync('@general:actions.cancel.title');
705
+ return new Promise((resolve) => {
706
+ let settled = false;
707
+ const finish = (value) => {
708
+ if (settled) {
709
+ return;
710
+ }
711
+ settled = true;
712
+ resolve(value);
713
+ };
714
+ const dialog = dialogService.open({
715
+ title,
716
+ content,
717
+ type: 'primary',
718
+ orientation: 'horizontal',
719
+ closeButton: false,
720
+ buttons: [
721
+ {
722
+ text: cancelLabel,
723
+ color: 'default',
724
+ autofocus: true,
725
+ onClick: () => {
726
+ dialog.close();
727
+ finish(null);
728
+ },
729
+ },
730
+ {
731
+ text: plansOnlyLabel,
732
+ color: 'default',
733
+ onClick: () => {
734
+ dialog.close();
735
+ finish({ createPlans: true, createWorkOrders: false });
736
+ },
737
+ },
738
+ {
739
+ text: plansAndWorkOrdersLabel,
740
+ color: 'primary',
741
+ onClick: () => {
742
+ dialog.close();
743
+ finish({ createPlans: true, createWorkOrders: true });
744
+ },
745
+ },
746
+ ],
747
+ });
748
+ });
749
+ }
750
+ //#endregion
751
+ //#region ---- Middleware ----
752
+ /**
753
+ * After creating an Asset, offers to create maintenance plans (and optionally work orders)
754
+ * for maintenance templates on the asset type with `autoGeneratePlan = true`.
755
+ */
756
+ const assetCreateMaintenanceOfferMiddleware = {
757
+ target: {
758
+ ops: ['create'],
759
+ order: 88,
760
+ },
761
+ execute: async (ctx, next) => {
762
+ const dialogService = inject(AXDialogService, { optional: true });
763
+ const toastService = inject(AXToastService, { optional: true });
764
+ const translateService = inject(AXTranslationService, { optional: true });
765
+ const backend = ctx.entities;
766
+ const entityStorage = inject(AXPEntityStorageService, { optional: true });
767
+ const identifierService = inject(AXP_IDENTIFIER_SERVICE, { optional: true });
768
+ const sessionService = inject(AXPSessionService, { optional: true });
769
+ if (ctx.entityName !== ASSET_ENTITY$1) {
770
+ await next();
771
+ return;
772
+ }
773
+ await next();
774
+ const createdId = typeof ctx.result === 'string' ? ctx.result : undefined;
775
+ if (!createdId ||
776
+ !dialogService ||
777
+ !toastService ||
778
+ !translateService ||
779
+ !entityStorage ||
780
+ !identifierService ||
781
+ !sessionService) {
782
+ return;
783
+ }
784
+ const asset = (await backend.getOne(ASSET_ENTITY$1, createdId).catch(() => null));
785
+ if (!asset?.assetTypeId) {
786
+ return;
787
+ }
788
+ const templateEntity = `${RootConfig.module.name}.${RootConfig.entities.maintenanceTemplate.name}`;
789
+ const planEntity = `${RootConfig.module.name}.${RootConfig.entities.maintenancePlan.name}`;
790
+ const workOrderEntity = `${RootConfig.module.name}.${RootConfig.entities.workOrder.name}`;
791
+ const templates = await queryAutoGenerateTemplatesForAssetType(backend, templateEntity, asset.assetTypeId);
792
+ if (templates.length === 0) {
793
+ return;
794
+ }
795
+ const assetTitle = resolveDisplayLabel(asset.title, asset.code ?? createdId);
796
+ const choice = await askMaintenanceOfferChoice(dialogService, translateService, templates.length, assetTitle);
797
+ if (!choice?.createPlans) {
798
+ return;
799
+ }
800
+ const createdPlans = [];
801
+ for (const template of templates) {
802
+ if (!template.maintenanceTypeId) {
803
+ const loaded = (await backend
804
+ .getOne(templateEntity, template.id)
805
+ .catch(() => null));
806
+ if (!loaded?.maintenanceTypeId) {
807
+ continue;
808
+ }
809
+ Object.assign(template, loaded);
810
+ }
811
+ try {
812
+ // Validation runs before identifier middleware; allocate (commit) a distinct code per plan.
813
+ const planCode = await allocateIdentifierCode(identifierService, sessionService, MAINTENANCE_PLAN_CODE_RULE_ID);
814
+ const planPayload = buildMaintenancePlanPayload(asset, template, {
815
+ suppressWorkOrderPrompt: true,
816
+ code: planCode,
817
+ autoGeneratedPlan: true,
818
+ });
819
+ const planId = await entityStorage.insertOne(planEntity, planPayload);
820
+ const resolvedPlanId = typeof planId === 'string' ? planId : undefined;
821
+ if (!resolvedPlanId) {
822
+ continue;
823
+ }
824
+ const storedPlan = (await backend.getOne(planEntity, resolvedPlanId).catch(() => null));
825
+ const plan = mergeMaintenancePlanForWorkOrder({ ...planPayload, id: resolvedPlanId }, storedPlan, resolvedPlanId);
826
+ if (plan) {
827
+ createdPlans.push(plan);
828
+ }
829
+ }
830
+ catch (error) {
831
+ const errorTitle = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.errors.create-failed-title');
832
+ const errorMessage = error instanceof Error
833
+ ? error.message
834
+ : await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.errors.create-failed-content');
835
+ toastService.show({ color: 'danger', title: errorTitle, content: errorMessage });
836
+ return;
837
+ }
838
+ }
839
+ if (!choice.createWorkOrders || createdPlans.length === 0) {
840
+ const successTitle = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.success.plans-title');
841
+ const successContent = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.success.plans-content', { params: { count: createdPlans.length } });
842
+ toastService.show({ color: 'success', title: successTitle, content: successContent });
843
+ return;
844
+ }
845
+ let workOrderCount = 0;
846
+ const referenceDate = new Date();
847
+ for (const plan of createdPlans) {
848
+ if (!canCreateWorkOrderFromPlan(plan)) {
849
+ continue;
850
+ }
851
+ workOrderCount += await insertWorkOrdersFromPlan(entityStorage, identifierService, sessionService, workOrderEntity, plan, {
852
+ autoGeneratedWorkOrder: true,
853
+ referenceDate,
854
+ sourceType: AXMWorkOrderSourceType.CreateAsset,
855
+ backend,
856
+ });
857
+ }
858
+ const successTitle = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.success.both-title');
859
+ const successContent = await translateService.translateAsync('@asset-management:assets.entities.asset.dialogs.create-maintenance-offer.success.both-content', { params: { planCount: createdPlans.length, workOrderCount } });
860
+ toastService.show({ color: 'success', title: successTitle, content: successContent });
861
+ },
862
+ };
863
+ //#endregion
864
+
865
+ //#region ---- Imports ----
866
+ /** Asset detail route entity keys (must match AssetManagement registration). */
867
+ const ASSET_ENTITY = 'AssetManagement.Asset';
868
+ const ASSET_TYPE_ENTITY = 'AssetManagement.AssetType';
869
+ //#endregion
870
+ //#region ---- Helpers ----
871
+ function normalizeMaintenanceTypeIds(value) {
872
+ if (!Array.isArray(value)) {
873
+ return [];
874
+ }
875
+ return value.filter((id) => typeof id === 'string' && id.trim().length > 0);
876
+ }
877
+ /**
878
+ * Resolves maintenance type ids allowed for the asset (from asset type), matching work-order / maintenance-plan lookups.
879
+ */
880
+ async function resolveAssetMaintenanceTypeIds(backend, assetId) {
881
+ const asset = (await backend.getOne(ASSET_ENTITY, assetId).catch(() => null));
882
+ if (!asset) {
883
+ return [];
884
+ }
885
+ const fromAssetType = normalizeMaintenanceTypeIds(asset.assetType?.maintenanceTypeIds);
886
+ if (fromAssetType.length > 0) {
887
+ return fromAssetType;
888
+ }
889
+ if (!asset.assetTypeId) {
890
+ return [];
891
+ }
892
+ const assetType = (await backend
893
+ .getOne(ASSET_TYPE_ENTITY, asset.assetTypeId)
894
+ .catch(() => null));
895
+ return normalizeMaintenanceTypeIds(assetType?.maintenanceTypeIds);
896
+ }
897
+ //#endregion
898
+ //#region ---- Middleware ----
899
+ /**
900
+ * After creating a Failure Register, asks user to optionally create a Work Order.
901
+ * If user confirms, opens the standard entity data selector for maintenance templates.
902
+ */
903
+ const failureRegisterCreateWorkOrderMiddleware = {
904
+ target: {
905
+ ops: ['create'],
906
+ order: 90,
907
+ },
908
+ execute: async (ctx, next) => {
909
+ // IMPORTANT: resolve injected deps before any await to keep Angular injection context valid.
910
+ const dialogService = inject(AXDialogService, { optional: true });
911
+ const toastService = inject(AXToastService, { optional: true });
912
+ const entityRegistry = inject(AXPEntityDefinitionRegistryService, { optional: true });
913
+ const entityDataSelector = inject(AXPEntityDataSelectorService, { optional: true });
914
+ const backend = ctx.entities;
915
+ const entityStorage = inject(AXPEntityStorageService, { optional: true });
916
+ const identifierService = inject(AXP_IDENTIFIER_SERVICE, { optional: true });
917
+ const sessionService = inject(AXPSessionService, { optional: true });
918
+ const failureRegisterEntity = `${RootConfig.module.name}.${RootConfig.entities.failureRegister.name}`;
919
+ if (ctx.entityName !== failureRegisterEntity) {
920
+ await next();
921
+ return;
922
+ }
923
+ await next();
924
+ const createdId = typeof ctx.result === 'string' ? ctx.result : undefined;
925
+ if (!createdId) {
926
+ return;
927
+ }
928
+ // The middleware can run in non-UI execution contexts; keep it safe.
929
+ if (!dialogService ||
930
+ !toastService ||
931
+ !entityRegistry ||
932
+ !entityDataSelector ||
933
+ !entityStorage ||
934
+ !identifierService ||
935
+ !sessionService) {
936
+ return;
937
+ }
938
+ const fr = (await backend.getOne(ctx.entityName, createdId).catch(() => null));
939
+ if (!fr?.assetId) {
940
+ return;
941
+ }
942
+ const confirm = await dialogService.confirm('Create work order', 'Do you want to create work order now?', 'warning', 'horizontal', false, 'cancel');
943
+ if (confirm.result !== true) {
944
+ return;
945
+ }
946
+ const templateEntity = await entityRegistry.resolve(RootConfig.module.name, RootConfig.entities.maintenanceTemplate.name);
947
+ if (!templateEntity) {
948
+ toastService.show({
949
+ color: 'danger',
950
+ title: 'Template error',
951
+ content: 'Maintenance template entity is not available.',
952
+ });
953
+ return;
954
+ }
955
+ const maintenanceTypeIds = await resolveAssetMaintenanceTypeIds(backend, fr.assetId);
956
+ if (!maintenanceTypeIds.length) {
957
+ toastService.show({
958
+ color: 'warning',
959
+ title: 'No maintenance types',
960
+ content: 'The selected asset has no maintenance types configured on its asset type.',
961
+ });
962
+ return;
963
+ }
964
+ const selectorTitle = typeof templateEntity.title === 'string' ? templateEntity.title : RootConfig.entities.maintenanceTemplate.title;
965
+ const templateFilters = {
966
+ field: 'maintenanceTypeId',
967
+ operator: { type: 'in' },
968
+ value: maintenanceTypeIds,
969
+ };
970
+ const templateEntityName = `${RootConfig.module.name}.${RootConfig.entities.maintenanceTemplate.name}`;
971
+ const workOrderEntityName = `${RootConfig.module.name}.${RootConfig.entities.workOrder.name}`;
972
+ const selectorResult = await entityDataSelector.open({
973
+ entity: templateEntity,
974
+ title: selectorTitle,
975
+ allowMultiple: false,
976
+ allowCreate: 'none',
977
+ columns: [
978
+ 'code',
979
+ 'title',
980
+ 'maintenanceTypeId',
981
+ 'needPermission',
982
+ 'needShutdown',
983
+ 'estimatedHours',
984
+ 'hasSchedule',
985
+ 'schedule',
986
+ 'autoGeneratePlan',
987
+ ],
988
+ filters: templateFilters,
989
+ });
990
+ if (!selectorResult?.items?.length) {
991
+ return;
992
+ }
993
+ const selectedTemplate = selectorResult.items[0];
994
+ const template = await resolveMaintenanceTemplate(backend, templateEntityName, selectedTemplate);
995
+ if (!template) {
996
+ toastService.show({
997
+ color: 'danger',
998
+ title: 'Template error',
999
+ content: 'Selected template does not have maintenance type.',
1000
+ });
1001
+ return;
1002
+ }
1003
+ if (!canCreateWorkOrderFromFailureRegister(fr, template)) {
1004
+ toastService.show({
1005
+ color: 'warning',
1006
+ title: 'Missing data',
1007
+ content: 'Asset, maintenance type, and maintenance template are required to create a work order.',
1008
+ });
1009
+ return;
1010
+ }
1011
+ const workOrderNo = await allocateIdentifierCode(identifierService, sessionService, WORK_ORDER_NO_RULE_ID);
1012
+ const result = await entityStorage.insertOne(workOrderEntityName, buildWorkOrderPayloadFromFailureRegister(fr, template, workOrderNo));
1013
+ const workOrderId = typeof result === 'string' ? result : undefined;
1014
+ if (!workOrderId) {
1015
+ toastService.show({
1016
+ color: 'danger',
1017
+ title: 'Work order error',
1018
+ content: 'Work order creation failed.',
1019
+ });
1020
+ return;
1021
+ }
1022
+ toastService.show({
1023
+ color: 'success',
1024
+ title: 'Work order created',
1025
+ content: 'Work order was created successfully.',
1026
+ });
1027
+ },
1028
+ };
1029
+ //#endregion
1030
+
1031
+ //#region ---- Imports ----
1032
+ //#endregion
1033
+ //#region ---- Constants ----
1034
+ /** Per-create ctx.locals flag so duplicate middleware entries schedule only one prompt. */
1035
+ const WORK_ORDER_PROMPT_SCHEDULED_KEY = 'maintenancePlan.workOrderPromptScheduled';
1036
+ //#endregion
1037
+ //#region ---- Prompt runner ----
1038
+ /**
1039
+ * Asks whether to create work order(s) immediately after plan create completes.
1040
+ * Runs inline after `next()` so the dialog appears before navigation away from the create form.
1041
+ */
1042
+ async function runMaintenancePlanWorkOrderPrompt(deps) {
1043
+ const { createdId, planEntity, createPayload, dialogService, backend, entityStorage, identifierService, sessionService, toastService, } = deps;
1044
+ const storedPlan = (await backend.getOne(planEntity, createdId).catch(() => null));
1045
+ const plan = mergeMaintenancePlanForWorkOrder(createPayload, storedPlan, createdId);
1046
+ if (!plan) {
1047
+ return;
1048
+ }
1049
+ const plannedWorkOrderCount = countWorkOrdersToCreateFromSchedule(plan.schedule);
1050
+ const confirmMessage = plannedWorkOrderCount === 1
1051
+ ? 'Do you want to create 1 work order now based on the plan schedule?'
1052
+ : `Do you want to create ${plannedWorkOrderCount} work orders now based on the plan schedule?`;
1053
+ const confirm = await dialogService.confirm('Create work order', confirmMessage, 'warning', 'horizontal', false, 'cancel');
1054
+ if (confirm.result !== true) {
1055
+ return;
1056
+ }
1057
+ if (!canCreateWorkOrderFromPlan(plan)) {
1058
+ await dialogService.alert('Missing plan data', 'Asset, maintenance type, and maintenance template are required to create a work order.', 'warning');
1059
+ return;
1060
+ }
1061
+ const workOrderEntity = `${RootConfig.module.name}.${RootConfig.entities.workOrder.name}`;
1062
+ if (await hasWorkOrderForPlan(backend, workOrderEntity, plan.id)) {
1063
+ await dialogService.alert('Work order exists', 'A work order already exists for this maintenance plan.', 'warning');
1064
+ return;
1065
+ }
1066
+ try {
1067
+ const workOrderCount = await insertWorkOrdersFromPlan(entityStorage, identifierService, sessionService, workOrderEntity, plan, { backend });
1068
+ if (workOrderCount === 0) {
1069
+ await dialogService.alert('Work order error', 'Work order creation failed.', 'danger');
1070
+ return;
1071
+ }
1072
+ const successMessage = workOrderCount === 1
1073
+ ? 'Work order was created successfully.'
1074
+ : `${workOrderCount} work orders were created successfully.`;
1075
+ toastService.show({
1076
+ color: 'success',
1077
+ title: 'Work order created',
1078
+ content: successMessage,
1079
+ });
1080
+ }
1081
+ catch (error) {
1082
+ const message = error instanceof Error ? error.message : 'Work order creation failed.';
1083
+ await dialogService.alert('Work order error', message, 'danger');
1084
+ }
1085
+ }
1086
+ //#endregion
1087
+ //#region ---- Middleware ----
1088
+ /**
1089
+ * After creating a Maintenance Plan, asks whether to create a Work Order immediately.
1090
+ * If confirmed, creates Work Order using the plan's already selected template.
1091
+ */
1092
+ const maintenancePlanCreateWorkOrderMiddleware = {
1093
+ target: {
1094
+ ops: ['create'],
1095
+ order: 91,
1096
+ },
1097
+ execute: async (ctx, next) => {
1098
+ const dialogService = inject(AXDialogService, { optional: true });
1099
+ const toastService = inject(AXToastService, { optional: true });
1100
+ const backend = ctx.entities;
1101
+ const entityStorage = inject(AXPEntityStorageService, { optional: true });
1102
+ const identifierService = inject(AXP_IDENTIFIER_SERVICE, { optional: true });
1103
+ const sessionService = inject(AXPSessionService, { optional: true });
1104
+ const maintenancePlanEntity = `${RootConfig.module.name}.${RootConfig.entities.maintenancePlan.name}`;
1105
+ if (ctx.entityName !== maintenancePlanEntity) {
1106
+ await next();
1107
+ return;
1108
+ }
1109
+ const suppressPrompt = ctx.data &&
1110
+ typeof ctx.data === 'object' &&
1111
+ ctx.data[SUPPRESS_WORK_ORDER_PROMPT_FIELD] === true;
1112
+ const createPayload = ctx.data && typeof ctx.data === 'object' ? ctx.data : undefined;
1113
+ await next();
1114
+ const createdId = typeof ctx.result === 'string' ? ctx.result : undefined;
1115
+ if (!createdId ||
1116
+ !dialogService ||
1117
+ !toastService ||
1118
+ !entityStorage ||
1119
+ !identifierService ||
1120
+ !sessionService ||
1121
+ suppressPrompt) {
1122
+ return;
1123
+ }
1124
+ if (ctx.locals.get(WORK_ORDER_PROMPT_SCHEDULED_KEY)) {
1125
+ return;
1126
+ }
1127
+ ctx.locals.set(WORK_ORDER_PROMPT_SCHEDULED_KEY, true);
1128
+ await runMaintenancePlanWorkOrderPrompt({
1129
+ createdId,
1130
+ planEntity: ctx.entityName,
1131
+ createPayload,
1132
+ dialogService,
1133
+ backend,
1134
+ entityStorage,
1135
+ identifierService,
1136
+ sessionService,
1137
+ toastService,
1138
+ });
1139
+ },
1140
+ };
1141
+ //#endregion
1142
+
1143
+ //#region ---- Constants ----
1144
+ /** Answer keys pre-filled from asset.code (readonly in viewer). */
1145
+ const WORK_ORDER_CHECKLIST_ASSET_CODE_KEYS = [
1146
+ 'mm_f920_asset_no',
1147
+ 'mm_prestart_plant_item',
1148
+ ];
1149
+ /** Answer keys pre-filled from asset.serialNumber (readonly in viewer). */
1150
+ const WORK_ORDER_CHECKLIST_ASSET_SERIAL_KEYS = [
1151
+ 'mm_f920_registration_number',
1152
+ 'mm_prestart_serial_number',
1153
+ ];
1154
+ /** All asset-driven prefill keys across maintenance checklists. */
1155
+ const WORK_ORDER_CHECKLIST_ASSET_PREFILL_KEYS = [
1156
+ ...WORK_ORDER_CHECKLIST_ASSET_CODE_KEYS,
1157
+ ...WORK_ORDER_CHECKLIST_ASSET_SERIAL_KEYS,
1158
+ ];
1159
+ //#endregion
1160
+ //#region ---- Helpers ----
1161
+ /**
1162
+ * Builds checklist answer prefill from asset identifiers for maintenance questionnaires.
1163
+ */
1164
+ function buildWorkOrderChecklistAssetPrefillAnswers(asset) {
1165
+ const code = typeof asset.code === 'string' ? asset.code.trim() : '';
1166
+ const serialNumber = typeof asset.serialNumber === 'string' ? asset.serialNumber.trim() : '';
1167
+ const answers = {};
1168
+ if (code) {
1169
+ for (const key of WORK_ORDER_CHECKLIST_ASSET_CODE_KEYS) {
1170
+ answers[key] = code;
1171
+ }
1172
+ }
1173
+ if (serialNumber) {
1174
+ for (const key of WORK_ORDER_CHECKLIST_ASSET_SERIAL_KEYS) {
1175
+ answers[key] = serialNumber;
1176
+ }
1177
+ }
1178
+ return answers;
1179
+ }
1180
+ //#endregion
1181
+
1182
+ //#region ---- Imports ----
1183
+ //#endregion
1184
+ //#region ---- Types ----
1185
+ const WORK_ORDER_SUBJECT_TYPE$1 = `${RootConfig.module.name}.${RootConfig.entities.workOrder.name}`;
1186
+ //#endregion
1187
+ //#region ---- Middleware ----
1188
+ /**
1189
+ * Pre-fills PD-F920 asset header answers when a work-order checklist is opened from the task board.
1190
+ */
1191
+ const workOrderChecklistFillMiddleware = async (context, next) => {
1192
+ const entityService = inject(AXPEntityService);
1193
+ const input = context.input;
1194
+ const caseId = resolveText$1(get(input, 'caseId'));
1195
+ if (!caseId) {
1196
+ return next(context);
1197
+ }
1198
+ const assessmentCase = await entityService
1199
+ .withEntity('AssessmentManagement', 'AssessmentCase')
1200
+ .data()
1201
+ .byKey(caseId);
1202
+ const subjectType = resolveText$1(get(assessmentCase, 'subjectRef.type'));
1203
+ const workOrderId = resolveText$1(get(assessmentCase, 'subjectRef.id'));
1204
+ if (subjectType !== WORK_ORDER_SUBJECT_TYPE$1 || !workOrderId) {
1205
+ return next(context);
1206
+ }
1207
+ const workOrder = await entityService
1208
+ .withEntity(RootConfig.module.name, RootConfig.entities.workOrder.name)
1209
+ .data()
1210
+ .byKey(workOrderId);
1211
+ const assetId = resolveText$1(get(workOrder, 'assetId'));
1212
+ if (!assetId) {
1213
+ return next(context);
1214
+ }
1215
+ const asset = (await entityService.withEntity('AssetManagement', 'Asset').data().byKey(assetId));
1216
+ const prefillAnswers = buildWorkOrderChecklistAssetPrefillAnswers({
1217
+ code: asset?.code ?? null,
1218
+ serialNumber: asset?.serialNumber ?? null,
1219
+ });
1220
+ if (isEmpty(prefillAnswers)) {
1221
+ return next(context);
1222
+ }
1223
+ const sessionId = resolveText$1(get(input, 'sessionId'));
1224
+ if (sessionId) {
1225
+ const session = await entityService.withEntity('AssessmentManagement', 'AssessmentSession').data().byKey(sessionId);
1226
+ const existingAnswers = defaultTo(get(session, 'answers'), {});
1227
+ const { merged, changed } = mergeMissingAnswers(existingAnswers, prefillAnswers);
1228
+ if (changed) {
1229
+ await entityService
1230
+ .withEntity('AssessmentManagement', 'AssessmentSession')
1231
+ .data()
1232
+ .update(sessionId, { answers: merged });
1233
+ }
1234
+ }
1235
+ return next({
1236
+ ...context,
1237
+ input: {
1238
+ ...input,
1239
+ prefillAnswers: {
1240
+ ...prefillAnswers,
1241
+ ...defaultTo(get(input, 'prefillAnswers'), {}),
1242
+ },
1243
+ readonlyAnswerKeys: [
1244
+ ...WORK_ORDER_CHECKLIST_ASSET_PREFILL_KEYS,
1245
+ ...defaultTo(get(input, 'readonlyAnswerKeys'), []),
1246
+ ],
1247
+ },
1248
+ });
1249
+ };
1250
+ //#endregion
1251
+ //#region ---- Helpers ----
1252
+ function resolveText$1(value) {
1253
+ if (!isString(value)) {
1254
+ return '';
1255
+ }
1256
+ return value.trim();
1257
+ }
1258
+ function mergeMissingAnswers(existing, prefill) {
1259
+ const merged = { ...existing };
1260
+ let changed = false;
1261
+ for (const [key, value] of Object.entries(prefill)) {
1262
+ if (isEmpty(merged[key]) && !isEmpty(value)) {
1263
+ merged[key] = value;
1264
+ changed = true;
1265
+ }
1266
+ }
1267
+ return { merged, changed };
1268
+ }
1269
+ //#endregion
1270
+
1271
+ //#region ---- Imports ----
1272
+ //#endregion
1273
+ //#region ---- Types ----
1274
+ const WORK_ORDER_SUBJECT_TYPE = `${RootConfig.module.name}.${RootConfig.entities.workOrder.name}`;
1275
+ //#endregion
1276
+ //#region ---- Middleware ----
1277
+ /**
1278
+ * After a work-order checklist is submitted, ensures WorkReport draft, assessment reference,
1279
+ * and work-order in-progress status are persisted even when the workflow backend chain does not run.
1280
+ */
1281
+ const workOrderChecklistPostSubmitMiddleware = async (context, next) => {
1282
+ const entityService = inject(AXPEntityService);
1283
+ const commandService = inject(AXPCommandService);
1284
+ const sessionService = inject(AXPSessionService);
1285
+ const result = await next(context);
1286
+ try {
1287
+ await applyWorkOrderChecklistPostSubmitEffects(context.input, result, {
1288
+ entityService,
1289
+ commandService,
1290
+ sessionService,
1291
+ });
1292
+ }
1293
+ catch (error) {
1294
+ AXPDebugService.instance?.error('maintenance-management', 'work-order-checklist-post-submit', 'Post-submit middleware failed; assessment fill result preserved', () => ({
1295
+ caseId: get(context.input, 'caseId'),
1296
+ sessionId: get(context.input, 'sessionId'),
1297
+ success: result?.success,
1298
+ outcome: get(result, 'metadata.outcome'),
1299
+ error: error instanceof Error ? error.message : String(error),
1300
+ }));
1301
+ }
1302
+ return result;
1303
+ };
1304
+ //#endregion
1305
+ //#region ---- Post-submit effects ----
1306
+ async function applyWorkOrderChecklistPostSubmitEffects(input, result, services) {
1307
+ if (!result?.success) {
1308
+ return;
1309
+ }
1310
+ const caseId = resolveText(get(input, 'caseId'));
1311
+ if (!caseId) {
1312
+ return;
1313
+ }
1314
+ const submitted = await isWorkOrderChecklistSubmitted(input, result, caseId, services.entityService);
1315
+ if (!submitted) {
1316
+ return;
1317
+ }
1318
+ const { entityService, commandService, sessionService } = services;
1319
+ const assessmentCase = await entityService
1320
+ .withEntity('AssessmentManagement', 'AssessmentCase')
1321
+ .data()
1322
+ .byKey(caseId);
1323
+ const subjectType = resolveText(get(assessmentCase, 'subjectRef.type'));
1324
+ const workOrderId = resolveText(get(assessmentCase, 'subjectRef.id'));
1325
+ if (subjectType !== WORK_ORDER_SUBJECT_TYPE || !workOrderId) {
1326
+ return;
1327
+ }
1328
+ const workOrder = (await entityService
1329
+ .withEntity(RootConfig.module.name, RootConfig.entities.workOrder.name)
1330
+ .data()
1331
+ .byKey(workOrderId));
1332
+ if (!workOrder?.id) {
1333
+ return;
1334
+ }
1335
+ const performedById = await resolveEmployeeIdByPersonId(entityService, resolveText(workOrder.assignedToId));
1336
+ const completedById = resolveText(sessionService.user?.id);
1337
+ const activityKeys = AXMMaintenanceManagementCommandKeys.WorkflowActivity;
1338
+ const draftResult = await commandService.execute(activityKeys.CreateOrGetWorkReportDraft, {
1339
+ workOrderId,
1340
+ performedById: performedById || null,
1341
+ });
1342
+ const workReportId = resolveText(get(draftResult, 'data.workReportId'));
1343
+ await commandService.execute(activityKeys.RecordWorkReportAssessment, {
1344
+ workOrderId,
1345
+ workReportId: workReportId || null,
1346
+ performedById: performedById || null,
1347
+ assessmentCaseId: caseId,
1348
+ completedById: completedById || null,
1349
+ });
1350
+ const shouldSetInProgress = workOrder.statusId === AXMWorkOrderStatus.Planned ||
1351
+ workOrder.statusId === AXMWorkOrderStatus.Scheduled ||
1352
+ workOrder.statusId === AXMWorkOrderStatus.Assigned;
1353
+ if (shouldSetInProgress) {
1354
+ await commandService.execute(activityKeys.UpdateWorkOrderInProgress, { workOrderId });
1355
+ }
1356
+ }
1357
+ async function isWorkOrderChecklistSubmitted(input, result, caseId, entityService) {
1358
+ const outcome = resolveText(get(result, 'metadata.outcome')).toLowerCase();
1359
+ if (outcome === 'submitted') {
1360
+ return true;
1361
+ }
1362
+ const sessionId = resolveText(get(input, 'sessionId'));
1363
+ if (sessionId) {
1364
+ const session = await entityService
1365
+ .withEntity('AssessmentManagement', 'AssessmentSession')
1366
+ .data()
1367
+ .byKey(sessionId);
1368
+ if (resolveText(get(session, 'statusId')).toLowerCase() === 'submitted') {
1369
+ return true;
1370
+ }
1371
+ }
1372
+ const page = await entityService
1373
+ .withEntity('AssessmentManagement', 'AssessmentSession')
1374
+ .data()
1375
+ .query({
1376
+ skip: 0,
1377
+ take: 1,
1378
+ sort: [{ field: 'lastSavedAt', direction: 'desc' }],
1379
+ filter: {
1380
+ logic: 'and',
1381
+ filters: [{ field: 'caseId', operator: { type: 'equal' }, value: caseId }],
1382
+ },
1383
+ });
1384
+ const latest = defaultTo(get(page, 'items[0]'), null);
1385
+ return resolveText(latest?.statusId).toLowerCase() === 'submitted';
1386
+ }
1387
+ async function resolveEmployeeIdByPersonId(entityService, personId) {
1388
+ if (!personId) {
1389
+ return '';
1390
+ }
1391
+ const page = await entityService
1392
+ .withEntity('HumanCapitalManagement', 'Employee')
1393
+ .data()
1394
+ .query({
1395
+ skip: 0,
1396
+ take: 1,
1397
+ filter: {
1398
+ logic: 'and',
1399
+ filters: [{ field: 'personId', operator: { type: 'equal' }, value: personId }],
1400
+ },
1401
+ });
1402
+ const employee = defaultTo(get(page, 'items[0]'), null);
1403
+ return resolveText(employee?.id);
1404
+ }
1405
+ function resolveText(value) {
1406
+ if (!isString(value)) {
1407
+ return '';
1408
+ }
1409
+ return value.trim();
1410
+ }
1411
+ //#endregion
1412
+
1413
+ //#region ---- Imports ----
1414
+ //#endregion
1415
+ //#region ---- Middleware ----
1416
+ const workOrderEntityName = `${RootConfig.module.name}.${RootConfig.entities.workOrder.name}`;
1417
+ /**
1418
+ * Applies create defaults for work orders: `sourceType` (manual when unset) and `requestedById` (current user).
1419
+ */
1420
+ const workOrderSourceTypeMiddleware = {
1421
+ target: {
1422
+ ops: ['create'],
1423
+ order: 10,
1424
+ },
1425
+ execute: async (ctx, next) => {
1426
+ if (ctx.entityName !== workOrderEntityName || !ctx.data || typeof ctx.data !== 'object') {
1427
+ await next();
1428
+ return;
1429
+ }
1430
+ const data = ctx.data;
1431
+ if (isNil(data['sourceType']) || data['sourceType'] === '') {
1432
+ data['sourceType'] = AXMWorkOrderSourceType.Manual;
1433
+ }
1434
+ const sessionService = inject(AXPSessionService, { optional: true });
1435
+ const currentUserId = sessionService?.user?.id;
1436
+ if (!isEmpty(currentUserId)) {
1437
+ data['requestedById'] = currentUserId;
1438
+ }
1439
+ await next();
1440
+ },
1441
+ };
1442
+ //#endregion
1443
+
1444
+ //#region ---- Middleware Exports ----
1445
+ //#endregion
1446
+
1447
+ //#endregion
1448
+ //#region ---- Constants ----
1449
+ const QUESTIONNAIRE = 'AssessmentManagement.Questionnaire';
1450
+ const QUESTION_BANK_ITEM = 'AssessmentManagement.QuestionBankItem';
1451
+ const WORKFLOW_DEFINITION = 'WorkflowManagement.WorkflowDefinition';
1452
+ const MM_CATALOG_TARGETS = [QUESTIONNAIRE, QUESTION_BANK_ITEM, WORKFLOW_DEFINITION];
1453
+ //#endregion
1454
+ //#region ---- Provider ----
1455
+ class AXMMaintenanceManagementCatalogScopeDefinitionProvider {
1456
+ async items() {
1457
+ return [
1458
+ {
1459
+ name: MM_CATALOG_SCOPE_MN,
1460
+ title: '@maintenance-management:catalog-scopes.mn.title',
1461
+ description: '@maintenance-management:catalog-scopes.mn.description',
1462
+ targets: [...MM_CATALOG_TARGETS],
1463
+ icon: 'fa-light fa-screwdriver-wrench',
1464
+ cssClass: 'warning-surface',
1465
+ order: 20,
1466
+ },
1467
+ ];
1468
+ }
1469
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementCatalogScopeDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1470
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementCatalogScopeDefinitionProvider }); }
1471
+ }
1472
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementCatalogScopeDefinitionProvider, decorators: [{
1473
+ type: Injectable
1474
+ }] });
1475
+
1476
+ //#region ---- Imports ----
1477
+ //#endregion
1478
+ //#region ---- Helpers ----
1479
+ function resolveAssetId(value) {
1480
+ if (!isString(value)) {
1481
+ return '';
1482
+ }
1483
+ return value.trim();
1484
+ }
1485
+ //#endregion
1486
+ /**
1487
+ * Expression-evaluator scope for work-order "Create" dropdown items (workflow-enabled maintenance templates).
1488
+ */
1489
+ class AXMMaintenanceManagementWorkOrderExpressionEvaluatorScopeProvider {
1490
+ constructor() {
1491
+ //#region ---- Services & Dependencies ----
1492
+ this.entityService = inject(AXPEntityService);
1493
+ this.translation = inject(AXTranslationService);
1494
+ //#endregion
1495
+ }
1496
+ //#endregion
1497
+ //#region ---- AXPExpressionEvaluatorScopeProvider ----
1498
+ async provide(context) {
1499
+ context.addScope(RootConfig.module.name, {
1500
+ /**
1501
+ * Loads maintenance templates with workflows for the asset behind the current list context.
1502
+ * Resolves asset → assetType.maintenanceTypeIds → templates (assetType + maintenanceType + workflow).
1503
+ */
1504
+ WorkOrderCreateActions: async (assetIdRaw) => {
1505
+ const assetId = resolveAssetId(assetIdRaw);
1506
+ if (!assetId) {
1507
+ return [];
1508
+ }
1509
+ try {
1510
+ const locale = this.translation.getActiveLang();
1511
+ const backend = this.createStorageBackend();
1512
+ const assetContext = await this.loadAssetMaintenanceContext(backend, assetId);
1513
+ if (!assetContext) {
1514
+ return [];
1515
+ }
1516
+ const templateEntityName = `${RootConfig.module.name}.${RootConfig.entities.maintenanceTemplate.name}`;
1517
+ const templates = await queryWorkflowTemplatesForAsset(backend, templateEntityName, assetId);
1518
+ const sorted = [...templates].sort((a, b) => {
1519
+ const ta = resolveDisplayLabel(a.title, a.code ?? a.id, locale);
1520
+ const tb = resolveDisplayLabel(b.title, b.code ?? b.id, locale);
1521
+ return ta.localeCompare(tb, locale, { sensitivity: 'base' });
1522
+ });
1523
+ const { asset, assetTypeId, maintenanceTypeIds } = assetContext;
1524
+ return sorted.map((template) => ({
1525
+ name: `create-work-order-${template.id}`,
1526
+ title: resolveDisplayLabel(template.title, template.code ?? template.id, locale),
1527
+ icon: 'fa-light fa-clipboard-list',
1528
+ color: 'default',
1529
+ command: {
1530
+ name: 'Entity:Create',
1531
+ options: {
1532
+ process: {
1533
+ redirect: false,
1534
+ canCreateNewOne: true,
1535
+ data: {
1536
+ assetId: asset.id,
1537
+ asset: {
1538
+ id: asset.id,
1539
+ title: asset.title,
1540
+ assetTypeId,
1541
+ assetType: { maintenanceTypeIds },
1542
+ },
1543
+ maintenanceTypeId: template.maintenanceTypeId,
1544
+ maintenanceTemplateId: template.id,
1545
+ maintenanceTemplate: {
1546
+ id: template.id,
1547
+ title: template.title,
1548
+ metadataIds: template.metadataIds,
1549
+ workflowConfig: template.workflowConfig,
1550
+ },
1551
+ needShutdown: template.needShutdown ?? false,
1552
+ needPermission: template.needPermission ?? false,
1553
+ estimatedHours: typeof template.estimatedMinutes === 'number' && template.estimatedMinutes > 0
1554
+ ? Math.round((template.estimatedMinutes / 60) * 100) / 100
1555
+ : undefined,
1556
+ sourceType: AXMWorkOrderSourceType.Manual,
1557
+ autoGeneratedWorkOrder: false,
1558
+ },
1559
+ },
1560
+ },
1561
+ },
1562
+ priority: 'primary',
1563
+ type: 'info',
1564
+ scope: AXPEntityCommandScope.TypeLevel,
1565
+ }));
1566
+ }
1567
+ catch (error) {
1568
+ console.error(`${RootConfig.module.name}.WorkOrderCreateActions failed:`, error instanceof Error ? error.message : error);
1569
+ return [];
1570
+ }
1571
+ },
1572
+ });
1573
+ }
1574
+ //#endregion
1575
+ //#region ---- Helpers ----
1576
+ createStorageBackend() {
1577
+ return {
1578
+ getOne: async (entityName, id) => {
1579
+ const [module, entity] = entityName.split('.');
1580
+ return this.entityService.withEntity(module, entity).data().byKey(id);
1581
+ },
1582
+ insertOne: async () => null,
1583
+ query: async (entityName, request) => {
1584
+ const [module, entity] = entityName.split('.');
1585
+ return this.entityService.withEntity(module, entity).data().query(request);
1586
+ },
1587
+ };
1588
+ }
1589
+ async loadAssetMaintenanceContext(backend, assetId) {
1590
+ const asset = (await backend.getOne('AssetManagement.Asset', assetId));
1591
+ const assetTypeId = asset?.assetTypeId?.trim();
1592
+ if (!asset?.id || !assetTypeId) {
1593
+ return null;
1594
+ }
1595
+ const assetType = (await backend.getOne('AssetManagement.AssetType', assetTypeId));
1596
+ const maintenanceTypeIds = (assetType?.maintenanceTypeIds ?? []).filter((id) => isString(id) && id.trim());
1597
+ if (maintenanceTypeIds.length === 0) {
1598
+ return null;
1599
+ }
1600
+ return {
1601
+ asset: { id: asset.id, title: asset.title, assetTypeId },
1602
+ assetTypeId,
1603
+ maintenanceTypeIds,
1604
+ };
1605
+ }
1606
+ }
1607
+
1608
+ //#region ---- Imports ----
1609
+ //#endregion
1610
+ //#region ---- Widget config ----
1611
+ const AXMWorkOrderWorkflowColumnWidget = {
1612
+ name: 'work-order-workflow-column',
1613
+ title: 'Work Order Workflow Column',
1614
+ description: 'List column for selecting a maintenance template workflow and starting the flow per row.',
1615
+ type: 'view',
1616
+ categories: [],
1617
+ groups: [AXPWidgetGroupEnum.EntityWidget],
1618
+ icon: 'fa-light fa-diagram-project',
1619
+ properties: [],
1620
+ components: {
1621
+ column: {
1622
+ component: () => import('./acorex-platform-module-maintenance-management-client-work-order-workflow-column.component-Dth3Z9fW.mjs').then((c) => c.AXMWorkOrderWorkflowColumnComponent),
1623
+ },
1624
+ },
1625
+ };
1626
+ //#endregion
1627
+
1628
+ //#region ---- Imports ----
1629
+ //#endregion
1630
+ //#region ---- Widget config ----
1631
+ const AXMWorkOrderWorkReportColumnWidget = {
1632
+ name: 'work-order-work-report-column',
1633
+ title: 'Work Order Work Report Column',
1634
+ description: 'List column for viewing the work report linked to a work order.',
1635
+ type: 'view',
1636
+ categories: [],
1637
+ groups: [AXPWidgetGroupEnum.EntityWidget],
1638
+ icon: 'fa-light fa-file-lines',
1639
+ properties: [],
1640
+ components: {
1641
+ column: {
1642
+ component: () => import('./acorex-platform-module-maintenance-management-client-work-order-work-report-column.component-Bf1WZWIS.mjs').then((c) => c.AXMWorkOrderWorkReportColumnComponent),
1643
+ },
1644
+ },
1645
+ };
1646
+ //#endregion
1647
+
1648
+ //#endregion
1649
+ //#region ---- Provider ----
1650
+ class AXMWorkOrderWorkflowColumnWidgetProvider {
1651
+ getWidgets() {
1652
+ return [AXMWorkOrderWorkflowColumnWidget, AXMWorkOrderWorkReportColumnWidget];
1653
+ }
1654
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkOrderWorkflowColumnWidgetProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1655
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkOrderWorkflowColumnWidgetProvider }); }
1656
+ }
1657
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkOrderWorkflowColumnWidgetProvider, decorators: [{
1658
+ type: Injectable
1659
+ }] });
1660
+
1661
+ //#region ---- Imports ----
1662
+ //#endregion
1663
+ //#region ---- Widget config ----
1664
+ const AXMWorkReportChecklistResultsWidget = {
1665
+ name: 'work-report-checklist-results',
1666
+ title: 'Work Report Checklist Results',
1667
+ description: 'Read-only checklist assessment references with view-response actions.',
1668
+ type: 'view',
1669
+ categories: [],
1670
+ groups: [AXPWidgetGroupEnum.EntityWidget],
1671
+ icon: 'fa-light fa-list-check',
1672
+ properties: [],
1673
+ components: {
1674
+ view: {
1675
+ component: () => import('./acorex-platform-module-maintenance-management-client-work-report-checklist-results-view.component-BSFW0Yt-.mjs').then((c) => c.AXMWorkReportChecklistResultsViewComponent),
1676
+ },
1677
+ edit: {
1678
+ component: () => import('./acorex-platform-module-maintenance-management-client-work-report-checklist-results-view.component-BSFW0Yt-.mjs').then((c) => c.AXMWorkReportChecklistResultsViewComponent),
1679
+ },
1680
+ },
1681
+ };
1682
+ //#endregion
1683
+
1684
+ //#endregion
1685
+ //#region ---- Provider ----
1686
+ class AXMWorkReportWidgetProvider {
1687
+ getWidgets() {
1688
+ return [AXMWorkReportChecklistResultsWidget];
1689
+ }
1690
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkReportWidgetProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1691
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkReportWidgetProvider }); }
1692
+ }
1693
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkReportWidgetProvider, decorators: [{
1694
+ type: Injectable
1695
+ }] });
1696
+
1697
+ //#region ---- Imports ----
1698
+ //#endregion
1699
+ //#region ---- Module ----
1700
+ class AXMMaintenanceManagementModule {
1701
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1702
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementModule }); }
1703
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementModule, providers: [
1704
+ // Module Manifest Provider
1705
+ {
1706
+ provide: AXP_MODULE_MANIFEST_PROVIDER,
1707
+ useValue: MaintenanceManagementManifest,
1708
+ multi: true,
1709
+ },
1710
+ {
1711
+ provide: AXP_CATALOG_SCOPE_DEFINITION_PROVIDER,
1712
+ useClass: AXMMaintenanceManagementCatalogScopeDefinitionProvider,
1713
+ multi: true,
1714
+ },
1715
+ {
1716
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
1717
+ useClass: AXMMaintenanceManagementWorkOrderExpressionEvaluatorScopeProvider,
1718
+ multi: true,
1719
+ },
1720
+ {
1721
+ provide: AXP_WIDGET_DEFINITION_PROVIDER,
1722
+ useClass: AXMWorkReportWidgetProvider,
1723
+ multi: true,
1724
+ },
1725
+ {
1726
+ provide: AXP_WIDGET_DEFINITION_PROVIDER,
1727
+ useClass: AXMWorkOrderWorkflowColumnWidgetProvider,
1728
+ multi: true,
1729
+ },
1730
+ // Provider references (now using tokens)
1731
+ provideLazyProvider(AXP_PERMISSION_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return permissionDefinition_provider; }).then((m) => m.AXMMaintenanceManagementPermissionDefinitionProvider)),
1732
+ provideLazyProvider(AXP_MENU_PROVIDER, () => Promise.resolve().then(function () { return menu_provider; }).then((m) => m.AXMMaintenanceManagementMenuProvider)),
1733
+ provideLazyProvider(AXP_SEARCH_PROVIDER, () => Promise.resolve().then(function () { return searchCommand_provider; }).then((m) => m.AXMMaintenanceManagementSearchCommandProvider)),
1734
+ provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-maintenance-management-client-failure-register-status.provider-CLBaQy_e.mjs').then((m) => m.AXMMaintenanceManagementFailureRegisterStatusProvider)),
1735
+ provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-maintenance-management-client-work-order-status.provider-DvBk5kAW.mjs').then((m) => m.AXMMaintenanceManagementWorkOrderStatusProvider)),
1736
+ provideCommandMiddleware([
1737
+ {
1738
+ target: 'AssessmentManagement.AssessmentCase:Fill',
1739
+ middleware: workOrderChecklistPostSubmitMiddleware,
1740
+ },
1741
+ {
1742
+ target: 'AssessmentManagement.AssessmentCase:Fill',
1743
+ middleware: workOrderChecklistFillMiddleware,
1744
+ },
1745
+ ]),
1746
+ provideCommandSetups([
1747
+ {
1748
+ key: 'Entity:List',
1749
+ command: () => import('./acorex-platform-module-maintenance-management-client-work-order-list-command-Bh_6PS5w.mjs').then((c) => c.WorkOrderListCommand),
1750
+ },
1751
+ {
1752
+ key: AXMMaintenanceManagementCommandKeys.WorkOrder.StartFlow,
1753
+ command: () => import('./acorex-platform-module-maintenance-management-client-start-work-order-flow.command-B06a962Y.mjs').then((c) => c.StartWorkOrderFlowCommand),
1754
+ },
1755
+ {
1756
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.ResolveWorkOrder,
1757
+ command: () => import('./acorex-platform-module-maintenance-management-client-resolve-work-order.activity-q5WM7Sv5.mjs').then((c) => c.ResolveWorkOrderActivity),
1758
+ },
1759
+ {
1760
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.ResolvePersonUserId,
1761
+ command: () => import('./acorex-platform-module-maintenance-management-client-resolve-person-user-id.activity-nwXAJHkd.mjs').then((c) => c.ResolvePersonUserIdActivity),
1762
+ },
1763
+ {
1764
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.CreateOrGetWorkReportDraft,
1765
+ command: () => import('./acorex-platform-module-maintenance-management-client-create-or-get-work-report-draft.activity-xxvOfIxf.mjs').then((c) => c.CreateOrGetWorkReportDraftActivity),
1766
+ },
1767
+ {
1768
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.UpdateWorkOrderInProgress,
1769
+ command: () => import('./acorex-platform-module-maintenance-management-client-update-work-order-in-progress.activity-CzkCCl1L.mjs').then((c) => c.UpdateWorkOrderInProgressActivity),
1770
+ },
1771
+ {
1772
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.ValidateWorkOrderCompletion,
1773
+ command: () => import('./acorex-platform-module-maintenance-management-client-validate-work-order-completion.activity-RA2zaQHH.mjs').then((c) => c.ValidateWorkOrderCompletionActivity),
1774
+ },
1775
+ {
1776
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.UpdateWorkReportOnCompletion,
1777
+ command: () => import('./acorex-platform-module-maintenance-management-client-update-work-report-on-completion.activity-_B0SUFtQ.mjs').then((c) => c.UpdateWorkReportOnCompletionActivity),
1778
+ },
1779
+ {
1780
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.RecordWorkReportAssessment,
1781
+ command: () => import('./acorex-platform-module-maintenance-management-client-record-work-report-assessment.activity-CxRfaf0G.mjs').then((c) => c.RecordWorkReportAssessmentActivity),
1782
+ },
1783
+ {
1784
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.UpdateWorkOrderCompleted,
1785
+ command: () => import('./acorex-platform-module-maintenance-management-client-update-work-order-completed.activity-Di4R6LQl.mjs').then((c) => c.UpdateWorkOrderCompletedActivity),
1786
+ },
1787
+ {
1788
+ key: AXMMaintenanceManagementCommandKeys.WorkReport.FillCompletion,
1789
+ command: () => import('./acorex-platform-module-maintenance-management-client-fill-work-report-completion.command-Capowl1e.mjs').then((c) => c.FillWorkReportCompletionCommand),
1790
+ },
1791
+ {
1792
+ key: AXMMaintenanceManagementCommandKeys.WorkReport.OpenFromWorkOrder,
1793
+ command: () => import('./acorex-platform-module-maintenance-management-client-open-work-report-from-work-order.command-B0O4fWPt.mjs').then((c) => c.OpenWorkReportFromWorkOrderCommand),
1794
+ },
1795
+ ]),
1796
+ {
1797
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1798
+ useValue: assetCreateMaintenanceOfferMiddleware,
1799
+ multi: true,
1800
+ },
1801
+ {
1802
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1803
+ useValue: failureRegisterCreateWorkOrderMiddleware,
1804
+ multi: true,
1805
+ },
1806
+ {
1807
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1808
+ useValue: maintenancePlanCreateWorkOrderMiddleware,
1809
+ multi: true,
1810
+ },
1811
+ {
1812
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1813
+ useValue: workOrderSourceTypeMiddleware,
1814
+ multi: true,
1815
+ },
1816
+ ] }); }
1817
+ }
1818
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementModule, decorators: [{
1819
+ type: NgModule,
1820
+ args: [{
1821
+ imports: [],
1822
+ providers: [
1823
+ // Module Manifest Provider
1824
+ {
1825
+ provide: AXP_MODULE_MANIFEST_PROVIDER,
1826
+ useValue: MaintenanceManagementManifest,
1827
+ multi: true,
1828
+ },
1829
+ {
1830
+ provide: AXP_CATALOG_SCOPE_DEFINITION_PROVIDER,
1831
+ useClass: AXMMaintenanceManagementCatalogScopeDefinitionProvider,
1832
+ multi: true,
1833
+ },
1834
+ {
1835
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
1836
+ useClass: AXMMaintenanceManagementWorkOrderExpressionEvaluatorScopeProvider,
1837
+ multi: true,
1838
+ },
1839
+ {
1840
+ provide: AXP_WIDGET_DEFINITION_PROVIDER,
1841
+ useClass: AXMWorkReportWidgetProvider,
1842
+ multi: true,
1843
+ },
1844
+ {
1845
+ provide: AXP_WIDGET_DEFINITION_PROVIDER,
1846
+ useClass: AXMWorkOrderWorkflowColumnWidgetProvider,
1847
+ multi: true,
1848
+ },
1849
+ // Provider references (now using tokens)
1850
+ provideLazyProvider(AXP_PERMISSION_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return permissionDefinition_provider; }).then((m) => m.AXMMaintenanceManagementPermissionDefinitionProvider)),
1851
+ provideLazyProvider(AXP_MENU_PROVIDER, () => Promise.resolve().then(function () { return menu_provider; }).then((m) => m.AXMMaintenanceManagementMenuProvider)),
1852
+ provideLazyProvider(AXP_SEARCH_PROVIDER, () => Promise.resolve().then(function () { return searchCommand_provider; }).then((m) => m.AXMMaintenanceManagementSearchCommandProvider)),
1853
+ provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-maintenance-management-client-failure-register-status.provider-CLBaQy_e.mjs').then((m) => m.AXMMaintenanceManagementFailureRegisterStatusProvider)),
1854
+ provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-maintenance-management-client-work-order-status.provider-DvBk5kAW.mjs').then((m) => m.AXMMaintenanceManagementWorkOrderStatusProvider)),
1855
+ provideCommandMiddleware([
1856
+ {
1857
+ target: 'AssessmentManagement.AssessmentCase:Fill',
1858
+ middleware: workOrderChecklistPostSubmitMiddleware,
1859
+ },
1860
+ {
1861
+ target: 'AssessmentManagement.AssessmentCase:Fill',
1862
+ middleware: workOrderChecklistFillMiddleware,
1863
+ },
1864
+ ]),
1865
+ provideCommandSetups([
1866
+ {
1867
+ key: 'Entity:List',
1868
+ command: () => import('./acorex-platform-module-maintenance-management-client-work-order-list-command-Bh_6PS5w.mjs').then((c) => c.WorkOrderListCommand),
1869
+ },
1870
+ {
1871
+ key: AXMMaintenanceManagementCommandKeys.WorkOrder.StartFlow,
1872
+ command: () => import('./acorex-platform-module-maintenance-management-client-start-work-order-flow.command-B06a962Y.mjs').then((c) => c.StartWorkOrderFlowCommand),
1873
+ },
1874
+ {
1875
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.ResolveWorkOrder,
1876
+ command: () => import('./acorex-platform-module-maintenance-management-client-resolve-work-order.activity-q5WM7Sv5.mjs').then((c) => c.ResolveWorkOrderActivity),
1877
+ },
1878
+ {
1879
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.ResolvePersonUserId,
1880
+ command: () => import('./acorex-platform-module-maintenance-management-client-resolve-person-user-id.activity-nwXAJHkd.mjs').then((c) => c.ResolvePersonUserIdActivity),
1881
+ },
1882
+ {
1883
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.CreateOrGetWorkReportDraft,
1884
+ command: () => import('./acorex-platform-module-maintenance-management-client-create-or-get-work-report-draft.activity-xxvOfIxf.mjs').then((c) => c.CreateOrGetWorkReportDraftActivity),
1885
+ },
1886
+ {
1887
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.UpdateWorkOrderInProgress,
1888
+ command: () => import('./acorex-platform-module-maintenance-management-client-update-work-order-in-progress.activity-CzkCCl1L.mjs').then((c) => c.UpdateWorkOrderInProgressActivity),
1889
+ },
1890
+ {
1891
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.ValidateWorkOrderCompletion,
1892
+ command: () => import('./acorex-platform-module-maintenance-management-client-validate-work-order-completion.activity-RA2zaQHH.mjs').then((c) => c.ValidateWorkOrderCompletionActivity),
1893
+ },
1894
+ {
1895
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.UpdateWorkReportOnCompletion,
1896
+ command: () => import('./acorex-platform-module-maintenance-management-client-update-work-report-on-completion.activity-_B0SUFtQ.mjs').then((c) => c.UpdateWorkReportOnCompletionActivity),
1897
+ },
1898
+ {
1899
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.RecordWorkReportAssessment,
1900
+ command: () => import('./acorex-platform-module-maintenance-management-client-record-work-report-assessment.activity-CxRfaf0G.mjs').then((c) => c.RecordWorkReportAssessmentActivity),
1901
+ },
1902
+ {
1903
+ key: AXMMaintenanceManagementCommandKeys.WorkflowActivity.UpdateWorkOrderCompleted,
1904
+ command: () => import('./acorex-platform-module-maintenance-management-client-update-work-order-completed.activity-Di4R6LQl.mjs').then((c) => c.UpdateWorkOrderCompletedActivity),
1905
+ },
1906
+ {
1907
+ key: AXMMaintenanceManagementCommandKeys.WorkReport.FillCompletion,
1908
+ command: () => import('./acorex-platform-module-maintenance-management-client-fill-work-report-completion.command-Capowl1e.mjs').then((c) => c.FillWorkReportCompletionCommand),
1909
+ },
1910
+ {
1911
+ key: AXMMaintenanceManagementCommandKeys.WorkReport.OpenFromWorkOrder,
1912
+ command: () => import('./acorex-platform-module-maintenance-management-client-open-work-report-from-work-order.command-B0O4fWPt.mjs').then((c) => c.OpenWorkReportFromWorkOrderCommand),
1913
+ },
1914
+ ]),
1915
+ {
1916
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1917
+ useValue: assetCreateMaintenanceOfferMiddleware,
1918
+ multi: true,
1919
+ },
1920
+ {
1921
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1922
+ useValue: failureRegisterCreateWorkOrderMiddleware,
1923
+ multi: true,
1924
+ },
1925
+ {
1926
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1927
+ useValue: maintenancePlanCreateWorkOrderMiddleware,
1928
+ multi: true,
1929
+ },
1930
+ {
1931
+ provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
1932
+ useValue: workOrderSourceTypeMiddleware,
1933
+ multi: true,
1934
+ },
1935
+ ],
1936
+ }]
1937
+ }] });
1938
+
1939
+ //#region ---- Imports ----
1940
+ //#endregion
1941
+ //#region ---- Menu Provider ----
1942
+ const PLAN_EQUIPMENT_MENU_KEY = 'Configuration:Menu:PlantEquipment';
1943
+ // const PLAN_EQUIPMENT_ASSET_MAINTENANCE_DIVIDER_KEY = `${PLAN_EQUIPMENT_MENU_KEY}:divider-assets-maintenance`;
1944
+ /**
1945
+ * Maintenance Management Menu Provider.
1946
+ * Provides menu items for the Maintenance Management module with permission and feature checks.
1947
+ */
1948
+ class AXMMaintenanceManagementMenuProvider {
1949
+ constructor() {
1950
+ this.entityService = inject(AXPEntityService);
1951
+ }
1952
+ async provide(context) {
1953
+ const module = RootConfig.module;
1954
+ const keys = AXPAssetsMaintenancePermissionKeys;
1955
+ // const mainMaintenanceSectionGroup = context.find(
1956
+ // AXMMaintenanceManagementMenuKeys.MainPlanEquipmentMaintenanceSectionGroup,
1957
+ // );
1958
+ // if (!mainMaintenanceSectionGroup.exists) {
1959
+ // context.find(AXPCommonMenuKeys.PlantEquipment).addItems([
1960
+ // {
1961
+ // name: AXMMaintenanceManagementMenuKeys.MainPlanEquipmentMaintenanceSectionGroup,
1962
+ // priority: 11,
1963
+ // text: '@general:menus.maintenance.title',
1964
+ // type: 'group',
1965
+ // },
1966
+ // ]);
1967
+ // }
1968
+ context.find(AXPCommonMenuKeys.PlantEquipment).addItems([
1969
+ {
1970
+ name: AXMMaintenanceManagementMenuKeys.FailureRegisters,
1971
+ text: RootConfig.entities.failureRegister.titlePlural,
1972
+ icon: RootConfig.entities.failureRegister.icon,
1973
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureRegister.name),
1974
+ priority: 12,
1975
+ policy: {
1976
+ features: [module.name],
1977
+ permissions: [keys.MaintainMaintenance],
1978
+ },
1979
+ },
1980
+ ]);
1981
+ const planEquipmentMenu = context.find(PLAN_EQUIPMENT_MENU_KEY);
1982
+ if (!planEquipmentMenu.exists) {
1983
+ context.find(AXPCommonMenuKeys.Configuration).addItems([
1984
+ {
1985
+ name: PLAN_EQUIPMENT_MENU_KEY,
1986
+ priority: 9000,
1987
+ text: '@general:menus.plan-equipment.title',
1988
+ icon: module.icon,
1989
+ },
1990
+ ]);
1991
+ }
1992
+ // const maintenanceSectionGroup = context.find(AXMMaintenanceManagementMenuKeys.PlanEquipmentMaintenanceSectionGroup);
1993
+ // if (!maintenanceSectionGroup.exists) {
1994
+ // context.find(PLAN_EQUIPMENT_MENU_KEY).addItems([
1995
+ // {
1996
+ // name: AXMMaintenanceManagementMenuKeys.PlanEquipmentMaintenanceSectionGroup,
1997
+ // priority: 11,
1998
+ // text: '@general:menus.maintenance.title',
1999
+ // type: 'group',
2000
+ // },
2001
+ // ]);
2002
+ // }
2003
+ context.find(PLAN_EQUIPMENT_MENU_KEY).addItems([
2004
+ {
2005
+ name: AXMMaintenanceManagementMenuKeys.MaintenanceTypes,
2006
+ text: RootConfig.entities.maintenanceType.titlePlural,
2007
+ icon: RootConfig.entities.maintenanceType.icon,
2008
+ path: this.entityService.createPath(module.name, RootConfig.entities.maintenanceType.name),
2009
+ priority: 12,
2010
+ policy: {
2011
+ features: [module.name],
2012
+ permissions: [keys.MaintainMaintenance],
2013
+ },
2014
+ },
2015
+ {
2016
+ name: AXMMaintenanceManagementMenuKeys.ActivityTypes,
2017
+ text: RootConfig.entities.activityType.titlePlural,
2018
+ icon: RootConfig.entities.activityType.icon,
2019
+ path: this.entityService.createPath(module.name, RootConfig.entities.activityType.name),
2020
+ priority: 13,
2021
+ policy: {
2022
+ features: [module.name],
2023
+ permissions: [keys.MaintainMaintenance],
2024
+ },
2025
+ },
2026
+ {
2027
+ name: AXMMaintenanceManagementMenuKeys.Failures,
2028
+ text: '@maintenance-management:module.menus.failures.title',
2029
+ type: 'group',
2030
+ priority: 14,
2031
+ policy: {
2032
+ features: [module.name],
2033
+ permissions: [keys.MaintainMaintenance],
2034
+ },
2035
+ },
2036
+ {
2037
+ name: AXMMaintenanceManagementMenuKeys.FailureCauses,
2038
+ text: RootConfig.entities.failureCause.titlePlural,
2039
+ icon: RootConfig.entities.failureCause.icon,
2040
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureCause.name),
2041
+ priority: 15,
2042
+ policy: {
2043
+ features: [module.name],
2044
+ permissions: [keys.MaintainMaintenance],
2045
+ },
2046
+ },
2047
+ {
2048
+ name: AXMMaintenanceManagementMenuKeys.FailureMechanisms,
2049
+ text: RootConfig.entities.failureMechanism.titlePlural,
2050
+ icon: RootConfig.entities.failureMechanism.icon,
2051
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureMechanism.name),
2052
+ priority: 16,
2053
+ policy: {
2054
+ features: [module.name],
2055
+ permissions: [keys.MaintainMaintenance],
2056
+ },
2057
+ },
2058
+ {
2059
+ name: AXMMaintenanceManagementMenuKeys.FailureDetections,
2060
+ text: RootConfig.entities.failureDetection.titlePlural,
2061
+ icon: RootConfig.entities.failureDetection.icon,
2062
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureDetection.name),
2063
+ priority: 17,
2064
+ policy: {
2065
+ features: [module.name],
2066
+ permissions: [keys.MaintainMaintenance],
2067
+ },
2068
+ },
2069
+ {
2070
+ name: AXMMaintenanceManagementMenuKeys.FailureEffects,
2071
+ text: RootConfig.entities.failureEffect.titlePlural,
2072
+ icon: RootConfig.entities.failureEffect.icon,
2073
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureEffect.name),
2074
+ priority: 18,
2075
+ policy: {
2076
+ features: [module.name],
2077
+ permissions: [keys.MaintainMaintenance],
2078
+ },
2079
+ },
2080
+ {
2081
+ name: AXMMaintenanceManagementMenuKeys.FailureSeverities,
2082
+ text: RootConfig.entities.failureSeverity.titlePlural,
2083
+ icon: RootConfig.entities.failureSeverity.icon,
2084
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureSeverity.name),
2085
+ priority: 19,
2086
+ policy: {
2087
+ features: [module.name],
2088
+ permissions: [keys.MaintainMaintenance],
2089
+ },
2090
+ },
2091
+ {
2092
+ name: AXMMaintenanceManagementMenuKeys.FailureTypes,
2093
+ text: RootConfig.entities.failureType.titlePlural,
2094
+ icon: RootConfig.entities.failureType.icon,
2095
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureType.name),
2096
+ priority: 20,
2097
+ policy: {
2098
+ features: [module.name],
2099
+ permissions: [keys.MaintainMaintenance],
2100
+ },
2101
+ },
2102
+ {
2103
+ name: AXMMaintenanceManagementMenuKeys.FailureModes,
2104
+ text: RootConfig.entities.failureMode.titlePlural,
2105
+ icon: RootConfig.entities.failureMode.icon,
2106
+ path: this.entityService.createPath(module.name, RootConfig.entities.failureMode.name),
2107
+ priority: 21,
2108
+ policy: {
2109
+ features: [module.name],
2110
+ permissions: [keys.MaintainMaintenance],
2111
+ },
2112
+ },
2113
+ // {
2114
+ // name: AXMMaintenanceManagementMenuKeys.MaintenanceTemplateActivityTypes,
2115
+ // text: RootConfig.entities.maintenanceTemplateActivityType.titlePlural,
2116
+ // icon: RootConfig.entities.maintenanceTemplateActivityType.icon,
2117
+ // path: this.entityService.createPath(module.name, RootConfig.entities.maintenanceTemplateActivityType.name),
2118
+ // priority: 4,
2119
+ // policy: {
2120
+ // features: [module.name],
2121
+ // permissions: [keys.MaintenanceTemplateActivityType.View],
2122
+ // },
2123
+ // },
2124
+ // {
2125
+ // name: AXMMaintenanceManagementMenuKeys.MaintenanceTemplateResources,
2126
+ // text: RootConfig.entities.maintenanceTemplateResource.titlePlural,
2127
+ // icon: RootConfig.entities.maintenanceTemplateResource.icon,
2128
+ // path: this.entityService.createPath(module.name, RootConfig.entities.maintenanceTemplateResource.name),
2129
+ // priority: 5,
2130
+ // policy: {
2131
+ // features: [module.name],
2132
+ // permissions: [keys.MaintenanceTemplateResource.View],
2133
+ // },
2134
+ // },
2135
+ // {
2136
+ // name: AXMMaintenanceManagementMenuKeys.MaintenanceTemplateFailureModes,
2137
+ // text: RootConfig.entities.maintenanceTemplateFailureMode.titlePlural,
2138
+ // icon: RootConfig.entities.maintenanceTemplateFailureMode.icon,
2139
+ // path: this.entityService.createPath(module.name, RootConfig.entities.maintenanceTemplateFailureMode.name),
2140
+ // priority: 6,
2141
+ // policy: {
2142
+ // features: [module.name],
2143
+ // permissions: [keys.MaintenanceTemplateFailureMode.View],
2144
+ // },
2145
+ // },
2146
+ ]);
2147
+ }
2148
+ }
2149
+ //#endregion
2150
+
2151
+ var menu_provider = /*#__PURE__*/Object.freeze({
2152
+ __proto__: null,
2153
+ AXMMaintenanceManagementMenuProvider: AXMMaintenanceManagementMenuProvider
2154
+ });
2155
+
2156
+ //#endregion
2157
+ //#region ----- Permission Definition Provider -----
2158
+ /**
2159
+ * Registers maintenance capabilities into the shared Assets & Maintenance group.
2160
+ */
2161
+ class AXMMaintenanceManagementPermissionDefinitionProvider {
2162
+ async define(context) {
2163
+ const keys = AXPAssetsMaintenancePermissionKeys;
2164
+ const groups = AXPCommonPermissionGroupKeys;
2165
+ const P = '@common:assets-maintenance.permissions';
2166
+ const G = '@common:permission-groups';
2167
+ context.addGroup(groups.AssetsMaintenance.Root, `${G}.assets-maintenance.title`, `${G}.assets-maintenance.description`, { order: 70 });
2168
+ context
2169
+ .addGroup(groups.AssetsMaintenance.Maintenance, `${G}.assets-maintenance-maintenance.title`, `${G}.assets-maintenance-maintenance.description`, { parent: groups.AssetsMaintenance.Root, order: 20 })
2170
+ .addPermission(keys.MaintainMaintenance, `${P}.maintain-maintenance.title`, `${P}.maintain-maintenance.description`)
2171
+ .endPermission()
2172
+ .endGroup();
2173
+ }
2174
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementPermissionDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2175
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementPermissionDefinitionProvider }); }
2176
+ }
2177
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMaintenanceManagementPermissionDefinitionProvider, decorators: [{
2178
+ type: Injectable
2179
+ }] });
2180
+
2181
+ var permissionDefinition_provider = /*#__PURE__*/Object.freeze({
2182
+ __proto__: null,
2183
+ AXMMaintenanceManagementPermissionDefinitionProvider: AXMMaintenanceManagementPermissionDefinitionProvider
2184
+ });
2185
+
2186
+ //#region ---- Imports ----
2187
+ //#endregion
2188
+ //#region ---- Search Command Provider ----
2189
+ class AXMMaintenanceManagementSearchCommandProvider extends AXPSearchCommandProvider {
2190
+ constructor() {
2191
+ super(...arguments);
2192
+ this.commands = [
2193
+ {
2194
+ id: 'create-maintenance-type',
2195
+ group: 'command',
2196
+ title: RootConfig.entities.maintenanceType.title,
2197
+ icon: RootConfig.entities.maintenanceType.icon,
2198
+ description: RootConfig.entities.maintenanceType.titlePlural,
2199
+ command: {
2200
+ name: 'Entity:Create',
2201
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.maintenanceType.name}`, {
2202
+ name: RootConfig.entities.maintenanceType.name,
2203
+ module: RootConfig.module.name,
2204
+ title: RootConfig.entities.maintenanceType.title,
2205
+ }),
2206
+ },
2207
+ },
2208
+ {
2209
+ id: 'create-maintenance-template',
2210
+ group: 'command',
2211
+ title: RootConfig.entities.maintenanceTemplate.title,
2212
+ icon: RootConfig.entities.maintenanceTemplate.icon,
2213
+ description: RootConfig.entities.maintenanceTemplate.titlePlural,
2214
+ command: {
2215
+ name: 'Entity:Create',
2216
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.maintenanceTemplate.name}`, {
2217
+ name: RootConfig.entities.maintenanceTemplate.name,
2218
+ module: RootConfig.module.name,
2219
+ title: RootConfig.entities.maintenanceTemplate.title,
2220
+ }),
2221
+ },
2222
+ },
2223
+ {
2224
+ id: 'create-maintenance-plan',
2225
+ group: 'command',
2226
+ title: RootConfig.entities.maintenancePlan.title,
2227
+ icon: RootConfig.entities.maintenancePlan.icon,
2228
+ description: RootConfig.entities.maintenancePlan.titlePlural,
2229
+ command: {
2230
+ name: 'Entity:Create',
2231
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.maintenancePlan.name}`, {
2232
+ name: RootConfig.entities.maintenancePlan.name,
2233
+ module: RootConfig.module.name,
2234
+ title: RootConfig.entities.maintenancePlan.title,
2235
+ }),
2236
+ },
2237
+ },
2238
+ {
2239
+ id: 'create-work-report',
2240
+ group: 'command',
2241
+ title: RootConfig.entities.workReport.title,
2242
+ icon: RootConfig.entities.workReport.icon,
2243
+ description: RootConfig.entities.workReport.titlePlural,
2244
+ command: {
2245
+ name: 'Entity:Create',
2246
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.workReport.name}`, {
2247
+ name: RootConfig.entities.workReport.name,
2248
+ module: RootConfig.module.name,
2249
+ title: RootConfig.entities.workReport.title,
2250
+ }),
2251
+ },
2252
+ },
2253
+ {
2254
+ id: 'create-activity-type-resource',
2255
+ group: 'command',
2256
+ title: RootConfig.entities.activityTypeResource.title,
2257
+ icon: RootConfig.entities.activityTypeResource.icon,
2258
+ description: RootConfig.entities.activityTypeResource.titlePlural,
2259
+ command: {
2260
+ name: 'Entity:Create',
2261
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.activityTypeResource.name}`, {
2262
+ name: RootConfig.entities.activityTypeResource.name,
2263
+ module: RootConfig.module.name,
2264
+ title: RootConfig.entities.activityTypeResource.title,
2265
+ }),
2266
+ },
2267
+ },
2268
+ {
2269
+ id: 'create-failure-mode',
2270
+ group: 'command',
2271
+ title: RootConfig.entities.failureMode.title,
2272
+ icon: RootConfig.entities.failureMode.icon,
2273
+ description: RootConfig.entities.failureMode.titlePlural,
2274
+ command: {
2275
+ name: 'Entity:Create',
2276
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.failureMode.name}`, {
2277
+ name: RootConfig.entities.failureMode.name,
2278
+ module: RootConfig.module.name,
2279
+ title: RootConfig.entities.failureMode.title,
2280
+ }),
2281
+ },
2282
+ },
2283
+ {
2284
+ id: 'create-failure-cause',
2285
+ group: 'command',
2286
+ title: RootConfig.entities.failureCause.title,
2287
+ icon: RootConfig.entities.failureCause.icon,
2288
+ description: RootConfig.entities.failureCause.titlePlural,
2289
+ command: {
2290
+ name: 'Entity:Create',
2291
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.failureCause.name}`, { name: RootConfig.entities.failureCause.name, module: RootConfig.module.name, title: RootConfig.entities.failureCause.title }),
2292
+ },
2293
+ },
2294
+ {
2295
+ id: 'create-failure-mechanism',
2296
+ group: 'command',
2297
+ title: RootConfig.entities.failureMechanism.title,
2298
+ icon: RootConfig.entities.failureMechanism.icon,
2299
+ description: RootConfig.entities.failureMechanism.titlePlural,
2300
+ command: {
2301
+ name: 'Entity:Create',
2302
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.failureMechanism.name}`, {
2303
+ name: RootConfig.entities.failureMechanism.name,
2304
+ module: RootConfig.module.name,
2305
+ title: RootConfig.entities.failureMechanism.title,
2306
+ }),
2307
+ },
2308
+ },
2309
+ {
2310
+ id: 'create-failure-detection',
2311
+ group: 'command',
2312
+ title: RootConfig.entities.failureDetection.title,
2313
+ icon: RootConfig.entities.failureDetection.icon,
2314
+ description: RootConfig.entities.failureDetection.titlePlural,
2315
+ command: {
2316
+ name: 'Entity:Create',
2317
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.failureDetection.name}`, {
2318
+ name: RootConfig.entities.failureDetection.name,
2319
+ module: RootConfig.module.name,
2320
+ title: RootConfig.entities.failureDetection.title,
2321
+ }),
2322
+ },
2323
+ },
2324
+ {
2325
+ id: 'create-failure-type',
2326
+ group: 'command',
2327
+ title: RootConfig.entities.failureType.title,
2328
+ icon: RootConfig.entities.failureType.icon,
2329
+ description: RootConfig.entities.failureType.titlePlural,
2330
+ command: {
2331
+ name: 'Entity:Create',
2332
+ options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.failureType.name}`, {
2333
+ name: RootConfig.entities.failureType.name,
2334
+ module: RootConfig.module.name,
2335
+ title: RootConfig.entities.failureType.title,
2336
+ }),
2337
+ },
2338
+ },
2339
+ ];
2340
+ }
2341
+ }
2342
+ //#endregion
2343
+
2344
+ var searchCommand_provider = /*#__PURE__*/Object.freeze({
2345
+ __proto__: null,
2346
+ AXMMaintenanceManagementSearchCommandProvider: AXMMaintenanceManagementSearchCommandProvider
2347
+ });
2348
+
2349
+ //#region ---- Imports ----
2350
+ //#endregion
2351
+ //#region ---- Expression helpers ----
2352
+ const WFM_EXPR_ASSIGNED_USER = 'context.eval("variables.assignedUserId")';
2353
+ const WFM_EXPR_WORK_ORDER_ID = 'context.eval("inputs.workOrderId")';
2354
+ const WFM_EXPR_ASSET_ID = 'context.eval("inputs.assetId")';
2355
+ const WFM_EXPR_MAINTENANCE_TYPE_ID = 'context.eval("inputs.maintenanceTypeId")';
2356
+ const wfmExpr = (expression) => `{{ ${expression} }}`;
2357
+ const workOrderTaskContext = {
2358
+ workOrderId: wfmExpr(WFM_EXPR_WORK_ORDER_ID),
2359
+ workOrderNo: '{{ inputs.workOrderNo }}',
2360
+ assetId: wfmExpr(WFM_EXPR_ASSET_ID),
2361
+ assetDisplayName: '{{ inputs.assetDisplayName }}',
2362
+ maintenanceTypeId: '{{ inputs.maintenanceTypeId }}',
2363
+ maintenanceTypeName: '{{ inputs.maintenanceTypeName }}',
2364
+ maintenancePlanId: '{{ inputs.maintenancePlanId }}',
2365
+ failureRegisterId: '{{ inputs.failureRegisterId }}',
2366
+ sourceType: '{{ inputs.sourceType }}',
2367
+ dueDate: '{{ inputs.dueDate }}',
2368
+ entityType: 'MaintenanceManagement.WorkOrder',
2369
+ };
2370
+ const startWorkAction = {
2371
+ name: 'start-work',
2372
+ title: 'Start work',
2373
+ icon: 'fa-light fa-play',
2374
+ color: 'primary',
2375
+ command: { name: 'start-work' },
2376
+ };
2377
+ const completeWorkAction = {
2378
+ name: 'complete-work',
2379
+ title: 'Complete work',
2380
+ icon: 'fa-light fa-check',
2381
+ color: 'success',
2382
+ command: { name: 'complete-work' },
2383
+ };
2384
+ //#endregion
2385
+ /**
2386
+ * Executes an existing work order: assignee task board → start work → in progress → complete work → completed.
2387
+ * Approval/sign-off is intentionally excluded (separate workflow).
2388
+ */
2389
+ function createWorkOrderExecutionWorkflowDefinition(config) {
2390
+ const { name, title, description, startTaskTitle, inProgressTaskTitle } = config;
2391
+ const activityKeys = AXMMaintenanceManagementCommandKeys.WorkflowActivity;
2392
+ const assetActivityKey = AXMAssetManagementCommandKeys.WorkflowActivity.RecalculateOperationalStatus;
2393
+ return {
2394
+ schemaVersion: 'acorex-platform-workflow/v1',
2395
+ name,
2396
+ title,
2397
+ description,
2398
+ variables: [
2399
+ {
2400
+ name: 'assignedUserId',
2401
+ title: 'Assigned user',
2402
+ dataType: 'string',
2403
+ interface: { type: 'text-editor', options: {} },
2404
+ },
2405
+ {
2406
+ name: 'assignedPersonId',
2407
+ title: 'Assigned person',
2408
+ dataType: 'string',
2409
+ interface: { type: 'text-editor', options: {} },
2410
+ },
2411
+ {
2412
+ name: 'assetStatusTarget',
2413
+ title: 'Asset status target',
2414
+ dataType: 'string',
2415
+ interface: { type: 'text-editor', options: {} },
2416
+ },
2417
+ {
2418
+ name: 'workStartedAt',
2419
+ title: 'Work started at',
2420
+ dataType: 'string',
2421
+ interface: { type: 'text-editor', options: {} },
2422
+ },
2423
+ {
2424
+ name: 'workCompletedAt',
2425
+ title: 'Work completed at',
2426
+ dataType: 'string',
2427
+ interface: { type: 'text-editor', options: {} },
2428
+ },
2429
+ ],
2430
+ inputs: [
2431
+ {
2432
+ name: 'workOrderId',
2433
+ title: 'Work order ID',
2434
+ dataType: 'string',
2435
+ interface: { type: 'text-editor', options: {} },
2436
+ },
2437
+ {
2438
+ name: 'workOrderNo',
2439
+ title: 'Work order number',
2440
+ dataType: 'string',
2441
+ interface: { type: 'text-editor', options: {} },
2442
+ },
2443
+ {
2444
+ name: 'assetId',
2445
+ title: 'Asset ID',
2446
+ dataType: 'string',
2447
+ interface: { type: 'text-editor', options: {} },
2448
+ },
2449
+ {
2450
+ name: 'assetDisplayName',
2451
+ title: 'Asset display name',
2452
+ dataType: 'string',
2453
+ interface: { type: 'text-editor', options: {} },
2454
+ },
2455
+ {
2456
+ name: 'assignedToId',
2457
+ title: 'Assigned person ID',
2458
+ dataType: 'string',
2459
+ interface: { type: 'text-editor', options: {} },
2460
+ },
2461
+ {
2462
+ name: 'assignedToDisplayName',
2463
+ title: 'Assigned person display name',
2464
+ dataType: 'string',
2465
+ interface: { type: 'text-editor', options: {} },
2466
+ },
2467
+ {
2468
+ name: 'maintenanceTypeId',
2469
+ title: 'Maintenance type ID',
2470
+ dataType: 'string',
2471
+ interface: { type: 'text-editor', options: {} },
2472
+ },
2473
+ {
2474
+ name: 'maintenanceTypeName',
2475
+ title: 'Maintenance type name',
2476
+ dataType: 'string',
2477
+ interface: { type: 'text-editor', options: {} },
2478
+ },
2479
+ {
2480
+ name: 'maintenancePlanId',
2481
+ title: 'Maintenance plan ID',
2482
+ dataType: 'string',
2483
+ interface: { type: 'text-editor', options: {} },
2484
+ },
2485
+ {
2486
+ name: 'failureRegisterId',
2487
+ title: 'Failure register ID',
2488
+ dataType: 'string',
2489
+ interface: { type: 'text-editor', options: {} },
2490
+ },
2491
+ {
2492
+ name: 'sourceType',
2493
+ title: 'Source type',
2494
+ dataType: 'string',
2495
+ interface: { type: 'text-editor', options: {} },
2496
+ },
2497
+ {
2498
+ name: 'dueDate',
2499
+ title: 'Due date',
2500
+ dataType: 'string',
2501
+ interface: { type: 'text-editor', options: {} },
2502
+ },
2503
+ ],
2504
+ outputs: [],
2505
+ extensions: {},
2506
+ graph: {
2507
+ startActivityId: 'resolveWorkOrder',
2508
+ activities: [
2509
+ {
2510
+ id: 'resolveWorkOrder',
2511
+ name: activityKeys.ResolveWorkOrder,
2512
+ title: 'Resolve work order',
2513
+ inputs: {
2514
+ workOrderId: '{{ inputs.workOrderId }}',
2515
+ assignedToId: '{{ inputs.assignedToId }}',
2516
+ },
2517
+ outputToVariables: {
2518
+ assignedPersonId: 'assignedToId',
2519
+ },
2520
+ },
2521
+ {
2522
+ id: 'resolveAssignedUser',
2523
+ name: activityKeys.ResolvePersonUserId,
2524
+ title: 'Resolve assigned user',
2525
+ inputs: {
2526
+ personId: '{{ variables.assignedPersonId || inputs.assignedToId }}',
2527
+ },
2528
+ outputToVariables: { assignedUserId: 'userId' },
2529
+ },
2530
+ {
2531
+ id: 'showAssignedUserRequiredToast',
2532
+ name: 'workflow-activity:show-toast',
2533
+ title: 'Assigned user required',
2534
+ inputs: {
2535
+ message: 'Assigned user is required before starting work order execution.',
2536
+ type: 'warning',
2537
+ },
2538
+ },
2539
+ {
2540
+ id: 'createWorkOrderTask',
2541
+ name: 'workflow-activity:human-task',
2542
+ title: startTaskTitle,
2543
+ inputs: {
2544
+ title: 'Work order: {{ inputs.workOrderNo }}',
2545
+ description: 'Start the assigned maintenance work when you are ready.',
2546
+ assignedUserIds: wfmExpr(WFM_EXPR_ASSIGNED_USER),
2547
+ dueDate: '{{ inputs.dueDate }}',
2548
+ context: workOrderTaskContext,
2549
+ actions: { suffix: [startWorkAction] },
2550
+ },
2551
+ },
2552
+ {
2553
+ id: 'updateWorkOrderInProgress',
2554
+ name: activityKeys.UpdateWorkOrderInProgress,
2555
+ title: 'Work order — in progress',
2556
+ inputs: {
2557
+ workOrderId: wfmExpr(WFM_EXPR_WORK_ORDER_ID),
2558
+ },
2559
+ outputToVariables: { workStartedAt: 'startedAt' },
2560
+ },
2561
+ {
2562
+ id: 'recalculateAssetStatusOnStart',
2563
+ name: assetActivityKey,
2564
+ title: 'Recalculate asset status (work started)',
2565
+ inputs: {
2566
+ assetId: wfmExpr(WFM_EXPR_ASSET_ID),
2567
+ trigger: 'work-started',
2568
+ workOrderId: wfmExpr(WFM_EXPR_WORK_ORDER_ID),
2569
+ maintenanceTypeId: wfmExpr(WFM_EXPR_MAINTENANCE_TYPE_ID),
2570
+ },
2571
+ outputToVariables: { assetStatusTarget: 'statusId' },
2572
+ },
2573
+ {
2574
+ id: 'workInProgressTask',
2575
+ name: 'workflow-activity:human-task',
2576
+ title: inProgressTaskTitle,
2577
+ inputs: {
2578
+ title: 'Work order: {{ inputs.workOrderNo }}',
2579
+ description: 'Perform the maintenance work, then mark it complete.',
2580
+ assignedUserIds: wfmExpr(WFM_EXPR_ASSIGNED_USER),
2581
+ dueDate: '{{ inputs.dueDate }}',
2582
+ context: workOrderTaskContext,
2583
+ actions: { suffix: [completeWorkAction] },
2584
+ },
2585
+ },
2586
+ {
2587
+ id: 'showWorkCompletionValidationFailedToast',
2588
+ name: 'workflow-activity:show-toast',
2589
+ title: 'Work completion validation failed',
2590
+ inputs: {
2591
+ message: 'Work order cannot be completed yet. Ensure work is in progress and requirements are met.',
2592
+ type: 'warning',
2593
+ },
2594
+ },
2595
+ {
2596
+ id: 'validateWorkCompletion',
2597
+ name: activityKeys.ValidateWorkOrderCompletion,
2598
+ title: 'Validate work completion',
2599
+ inputs: {
2600
+ workOrderId: wfmExpr(WFM_EXPR_WORK_ORDER_ID),
2601
+ },
2602
+ },
2603
+ {
2604
+ id: 'updateWorkOrderCompleted',
2605
+ name: activityKeys.UpdateWorkOrderCompleted,
2606
+ title: 'Work order — completed',
2607
+ inputs: {
2608
+ workOrderId: wfmExpr(WFM_EXPR_WORK_ORDER_ID),
2609
+ },
2610
+ outputToVariables: { workCompletedAt: 'completedAt' },
2611
+ },
2612
+ {
2613
+ id: 'recalculateAssetStatusOnComplete',
2614
+ name: assetActivityKey,
2615
+ title: 'Recalculate asset status (work completed)',
2616
+ inputs: {
2617
+ assetId: wfmExpr(WFM_EXPR_ASSET_ID),
2618
+ trigger: 'work-completed',
2619
+ workOrderId: wfmExpr(WFM_EXPR_WORK_ORDER_ID),
2620
+ maintenanceTypeId: wfmExpr(WFM_EXPR_MAINTENANCE_TYPE_ID),
2621
+ },
2622
+ },
2623
+ ],
2624
+ connections: [
2625
+ { source: { activtyName: 'resolveWorkOrder', port: 'Done' }, target: { activtyName: 'resolveAssignedUser' } },
2626
+ {
2627
+ source: { activtyName: 'resolveWorkOrder', port: 'Blocked' },
2628
+ target: { activtyName: 'showAssignedUserRequiredToast' },
2629
+ },
2630
+ {
2631
+ source: { activtyName: 'resolveWorkOrder', port: 'NotFound' },
2632
+ target: { activtyName: 'showAssignedUserRequiredToast' },
2633
+ },
2634
+ {
2635
+ source: { activtyName: 'resolveAssignedUser', port: 'Done' },
2636
+ target: { activtyName: 'createWorkOrderTask' },
2637
+ },
2638
+ {
2639
+ source: { activtyName: 'createWorkOrderTask', port: 'start-work' },
2640
+ target: { activtyName: 'updateWorkOrderInProgress' },
2641
+ },
2642
+ {
2643
+ source: { activtyName: 'updateWorkOrderInProgress', port: 'Done' },
2644
+ target: { activtyName: 'recalculateAssetStatusOnStart' },
2645
+ },
2646
+ {
2647
+ source: { activtyName: 'recalculateAssetStatusOnStart', port: 'Done' },
2648
+ target: { activtyName: 'workInProgressTask' },
2649
+ },
2650
+ {
2651
+ source: { activtyName: 'workInProgressTask', port: 'complete-work' },
2652
+ target: { activtyName: 'validateWorkCompletion' },
2653
+ },
2654
+ {
2655
+ source: { activtyName: 'validateWorkCompletion', port: 'Done' },
2656
+ target: { activtyName: 'updateWorkOrderCompleted' },
2657
+ },
2658
+ {
2659
+ source: { activtyName: 'validateWorkCompletion', port: 'Failed' },
2660
+ target: { activtyName: 'showWorkCompletionValidationFailedToast' },
2661
+ },
2662
+ {
2663
+ source: { activtyName: 'showWorkCompletionValidationFailedToast', port: 'Done' },
2664
+ target: { activtyName: 'workInProgressTask' },
2665
+ },
2666
+ {
2667
+ source: { activtyName: 'updateWorkOrderCompleted', port: 'Done' },
2668
+ target: { activtyName: 'recalculateAssetStatusOnComplete' },
2669
+ },
2670
+ ],
2671
+ },
2672
+ };
2673
+ }
2674
+ const workOrderExecutionWorkflowName = 'work-order-execution';
2675
+ //#endregion
2676
+
2677
+ //#region ---- Imports ----
2678
+ //#endregion
2679
+ //#region ---- Constants ----
2680
+ const M = createMultiLanguageString;
2681
+ //#endregion
2682
+ //#region ---- Definition export ----
2683
+ /** Published workflow graph for seeding `WorkflowManagement.WorkflowDefinition`. */
2684
+ const workOrderExecutionWorkflowDefinition = createWorkOrderExecutionWorkflowDefinition({
2685
+ name: workOrderExecutionWorkflowName,
2686
+ title: M('Work order execution', 'اجرای دستور کار'),
2687
+ description: M('Assignee task board, start work, asset status recalculation, complete work. Approval is a separate workflow.', 'کارتابل مسئول، شروع کار، محاسبه وضعیت دارایی، تکمیل کار. تأیید در گردش کار جداگانه انجام می‌شود.'),
2688
+ startTaskTitle: 'Start work — work order',
2689
+ inProgressTaskTitle: 'Complete work — work order',
2690
+ });
2691
+ //#endregion
2692
+
2693
+ /**
2694
+ * Generated bundle index. Do not edit.
2695
+ */
2696
+
2697
+ export { AXM_WORK_ORDER_WORKFLOW_DEBUG_NAMESPACE as A, AXMMaintenanceManagementMenuProvider as a, AXMMaintenanceManagementModule as b, AXMMaintenanceManagementPermissionDefinitionProvider as c, AXMMaintenanceManagementSearchCommandProvider as d, createWorkOrderExecutionWorkflowDefinition as e, workOrderExecutionWorkflowName as f, queryWorkflowTemplatesForAsset as q, resolveDisplayLabel as r, workOrderExecutionWorkflowDefinition as w };
2698
+ //# sourceMappingURL=acorex-platform-module-maintenance-management-client-acorex-platform-module-maintenance-management-client-BiQlJxPX.mjs.map