@rytass/bpm-core-nestjs-module 0.5.1 → 0.7.0
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.
- package/CHANGELOG.md +52 -0
- package/README.md +2 -0
- package/package.json +10 -3
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/bpm/bpm-root.module.d.ts +18 -0
- package/src/lib/bpm/bpm-root.module.js +8 -0
- package/src/lib/bpm/bpm-root.module.js.map +1 -1
- package/src/lib/calendar/business-calendar.provider.d.ts +11 -0
- package/src/lib/calendar/business-calendar.provider.js +20 -0
- package/src/lib/calendar/business-calendar.provider.js.map +1 -0
- package/src/lib/calendar/business-calendar.token.d.ts +38 -0
- package/src/lib/calendar/business-calendar.token.js +5 -0
- package/src/lib/calendar/business-calendar.token.js.map +1 -0
- package/src/lib/calendar/calendar.module.d.ts +18 -0
- package/src/lib/calendar/calendar.module.js +32 -0
- package/src/lib/calendar/calendar.module.js.map +1 -0
- package/src/lib/calendar/index.d.ts +5 -0
- package/src/lib/calendar/index.js +9 -0
- package/src/lib/calendar/index.js.map +1 -0
- package/src/lib/calendar/sla-schedule.service.d.ts +33 -0
- package/src/lib/calendar/sla-schedule.service.js +94 -0
- package/src/lib/calendar/sla-schedule.service.js.map +1 -0
- package/src/lib/calendar/weekday-business-calendar.d.ts +15 -0
- package/src/lib/calendar/weekday-business-calendar.js +28 -0
- package/src/lib/calendar/weekday-business-calendar.js.map +1 -0
- package/src/lib/common/iso-duration.d.ts +11 -0
- package/src/lib/common/iso-duration.js +13 -4
- package/src/lib/common/iso-duration.js.map +1 -1
- package/src/lib/notification/notification-options.d.ts +10 -0
- package/src/lib/notification/notification-options.js +19 -0
- package/src/lib/notification/notification-options.js.map +1 -1
- package/src/lib/notification/notification.enums.d.ts +13 -0
- package/src/lib/notification/notification.enums.js +14 -1
- package/src/lib/notification/notification.enums.js.map +1 -1
- package/src/lib/notification/notification.service.d.ts +8 -0
- package/src/lib/notification/notification.service.js +19 -1
- package/src/lib/notification/notification.service.js.map +1 -1
- package/src/lib/template/workflow-definition.validator.js +75 -1
- package/src/lib/template/workflow-definition.validator.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.service.d.ts +21 -3
- package/src/lib/workflow-engine/workflow-engine.service.js +115 -41
- package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.tokens.d.ts +2 -1
- package/src/lib/workflow-engine/workflow-engine.tokens.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## 0.7.0 (2026-08-10)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **bpm-core:** lint the new SLA and return-behaviour node fields ([f10c0bb](https://github.com/Rytass/BPMCore/commit/f10c0bb))
|
|
6
|
+
- **bpm-core:** enforce required return comments ([6cb288f](https://github.com/Rytass/BPMCore/commit/6cb288f))
|
|
7
|
+
- **bpm-core:** resolve task SLA due dates through a host business calendar ([3cb9d4d](https://github.com/Rytass/BPMCore/commit/3cb9d4d))
|
|
8
|
+
|
|
9
|
+
### 🩹 Fixes
|
|
10
|
+
|
|
11
|
+
- **bpm-core:** stop SLA escalation from walking the whole management chain ([f7e4669](https://github.com/Rytass/BPMCore/commit/f7e4669))
|
|
12
|
+
|
|
13
|
+
### ❤️ Thank You
|
|
14
|
+
|
|
15
|
+
- Chia Yu Pai @fantasywind
|
|
16
|
+
- Claude Opus 5 (1M context)
|
|
17
|
+
|
|
1
18
|
# Changelog
|
|
2
19
|
|
|
3
20
|
All notable changes to `@rytass/bpm-core-nestjs-module` are documented in this
|
|
@@ -9,6 +26,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
26
|
Releases are managed by [`nx release`](https://nx.dev/recipes/nx-release) with
|
|
10
27
|
Conventional Commits — see `nx.json` for the release config.
|
|
11
28
|
|
|
29
|
+
## 0.6.0 — 2026-08-04
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- **Opt-in org-unit depth filtering for manager resolution.** The
|
|
34
|
+
`ORG_MANAGER` and `ORG_UNIT_MANAGER` approver resolvers now accept an
|
|
35
|
+
optional `preferClosestOrgUnit: boolean` flag. When enabled, the engine
|
|
36
|
+
keeps only the deepest org-unit-level manager rules on the winning
|
|
37
|
+
priority tier — ancestor catch-all rules (e.g. a company-wide fallback)
|
|
38
|
+
no longer join the approver list. Sibling org units at the same depth
|
|
39
|
+
are still preserved so multi-manager steps continue to work. Depth is
|
|
40
|
+
derived from the org unit `path` ltree (segment count).
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **Manager resolution priority now respected.**
|
|
45
|
+
`resolveManagerResolutionCandidates` previously returned every active
|
|
46
|
+
resolution regardless of priority. Now it keeps only the top-priority
|
|
47
|
+
tier (matching `OrganizationService.resolveManagerMemberId` which
|
|
48
|
+
already picks `active[0]`), so a low-priority company-wide catch-all
|
|
49
|
+
rule no longer appends its manager to every member's approver list.
|
|
50
|
+
- **Top-level `managerMemberId` fallback restored when `customFields` is
|
|
51
|
+
an empty object.** `readManagerMemberIdFromInitiatorSnapshot` previously
|
|
52
|
+
short-circuited to `undefined` as soon as `customFields` was any object
|
|
53
|
+
(including `{}`), preventing the top-level `managerMemberId` fallback
|
|
54
|
+
from ever executing. Now it only takes the `customFields` branch when
|
|
55
|
+
`customFields.managerMemberId` is actually present.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- Peer dependency `@rytass/bpm-core-shared` now requires ^0.6.0.
|
|
60
|
+
- `readOrgUnitAndAncestorIds` refactored to `readOrgUnitAndAncestors`
|
|
61
|
+
(returns full `OrgUnitEntity[]` instead of just IDs) so callers can
|
|
62
|
+
compute depth maps without duplicate DB queries.
|
|
63
|
+
|
|
12
64
|
## 0.5.1 — 2026-07-06
|
|
13
65
|
|
|
14
66
|
### Fixed
|
package/README.md
CHANGED
|
@@ -811,6 +811,7 @@ BPMRootModule.forRootAsync({
|
|
|
811
811
|
| `memberResolverProvider` | required | Provider for `BPM_MEMBER_RESOLVER`. |
|
|
812
812
|
| `attachmentStorageProvider` | local `.storage/attachments` | Host-provided `@rytass/storages` adapter. |
|
|
813
813
|
| `workflowServiceTaskDispatcherProvider` | built-in `fetch` dispatcher | Host provider for executable workflow `WEBHOOK` service tasks. |
|
|
814
|
+
| `businessCalendarProvider` | Monday–Friday calendar | Host provider for `BPM_BUSINESS_CALENDAR`, used by `BUSINESS_DAY` SLAs. BPMCore ships no holiday data. |
|
|
814
815
|
| `attachmentRoutePrefix` | `/attachments` | Drives both the BPM signed URL path and the Nest controller mount path for `AttachmentController`. Must be set at module wiring time (see "Attachment Storage" below). |
|
|
815
816
|
| `attachmentStorageProviderId` | `local` | Value stored on attachment metadata for the active adapter. |
|
|
816
817
|
| `attachmentPublicBaseUrl` | `http://localhost:17603` | Public base URL for signed attachment URLs. |
|
|
@@ -835,6 +836,7 @@ BPMRootModule.forRootAsync({
|
|
|
835
836
|
| `notificationDeliveryRetryBaseDelayMs` | `60000` | Base retry delay multiplied by attempt count. |
|
|
836
837
|
| `notificationSlaSchedulerEnabled` | `false` | Runs automatic SLA scan loop in this process. |
|
|
837
838
|
| `notificationSlaScanIntervalMs` | `60000` | SLA scheduler interval. |
|
|
839
|
+
| `notificationSlaBusinessCalendarTimeZone` | `UTC` | IANA zone for the built-in weekday calendar. Ignored when `businessCalendarProvider` is set. |
|
|
838
840
|
| `notificationSlaTimeoutRemindEnabled` | `true` | Enables SLA timeout `REMIND`. |
|
|
839
841
|
| `notificationSlaTimeoutAutoApproveEnabled` | `false` | Enables SLA timeout `AUTO_APPROVE`. |
|
|
840
842
|
| `notificationSlaTimeoutEscalateEnabled` | `false` | Enables SLA timeout `ESCALATE`. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rytass/bpm-core-nestjs-module",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Embeddable NestJS BPM approval workflow module: workflow engine, approval templates, forms, organization/member contracts, attachments, signatures, notifications, delegation, and TypeORM migrations.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bpm",
|
|
@@ -42,6 +42,9 @@
|
|
|
42
42
|
"bpm-auth": [
|
|
43
43
|
"./src/lib/bpm-auth/index.d.ts"
|
|
44
44
|
],
|
|
45
|
+
"calendar": [
|
|
46
|
+
"./src/lib/calendar/index.d.ts"
|
|
47
|
+
],
|
|
45
48
|
"condition": [
|
|
46
49
|
"./src/lib/condition/index.d.ts"
|
|
47
50
|
],
|
|
@@ -91,6 +94,10 @@
|
|
|
91
94
|
"types": "./src/lib/bpm-auth/index.d.ts",
|
|
92
95
|
"default": "./src/lib/bpm-auth/index.js"
|
|
93
96
|
},
|
|
97
|
+
"./calendar": {
|
|
98
|
+
"types": "./src/lib/calendar/index.d.ts",
|
|
99
|
+
"default": "./src/lib/calendar/index.js"
|
|
100
|
+
},
|
|
94
101
|
"./database": {
|
|
95
102
|
"types": "./src/lib/database/index.d.ts",
|
|
96
103
|
"default": "./src/lib/database/index.js"
|
|
@@ -141,8 +148,8 @@
|
|
|
141
148
|
"@nestjs/core": "^11.0.0",
|
|
142
149
|
"@nestjs/graphql": "^13.4.0",
|
|
143
150
|
"@nestjs/typeorm": "^11.0.1",
|
|
144
|
-
"@rytass/bpm-core-shared": "^0.
|
|
145
|
-
"@rytass/secret-adapter-vault-nestjs": "^0.4.5 || ^0.5.0",
|
|
151
|
+
"@rytass/bpm-core-shared": "^0.7.0",
|
|
152
|
+
"@rytass/secret-adapter-vault-nestjs": "^0.4.5 || ^0.5.0 || ^0.6.0",
|
|
146
153
|
"express": "^4.0.0 || ^5.0.0",
|
|
147
154
|
"graphql": "^16.0.0",
|
|
148
155
|
"reflect-metadata": "^0.1.13 || ^0.2.0",
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
tslib_1.__exportStar(require("./lib/attachment"), exports);
|
|
5
5
|
tslib_1.__exportStar(require("./lib/bpm"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./lib/bpm-auth"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./lib/calendar"), exports);
|
|
7
8
|
tslib_1.__exportStar(require("./lib/common"), exports);
|
|
8
9
|
tslib_1.__exportStar(require("./lib/condition"), exports);
|
|
9
10
|
tslib_1.__exportStar(require("./lib/database"), exports);
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/bpm-core/src/index.ts"],"names":[],"mappings":";;;AAAA,2DAAiC;AACjC,oDAA0B;AAC1B,yDAA+B;AAC/B,uDAA6B;AAC7B,0DAAgC;AAChC,yDAA+B;AAC/B,2DAAiC;AACjC,qDAA2B;AAC3B,yDAA+B;AAC/B,6DAAmC;AACnC,6DAAmC;AACnC,0DAAgC;AAChC,yDAA+B;AAC/B,gEAAsC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/bpm-core/src/index.ts"],"names":[],"mappings":";;;AAAA,2DAAiC;AACjC,oDAA0B;AAC1B,yDAA+B;AAC/B,yDAA+B;AAC/B,uDAA6B;AAC7B,0DAAgC;AAChC,yDAA+B;AAC/B,2DAAiC;AACjC,qDAA2B;AAC3B,yDAA+B;AAC/B,6DAAmC;AACnC,6DAAmC;AACnC,0DAAgC;AAChC,yDAA+B;AAC/B,gEAAsC"}
|
|
@@ -3,6 +3,7 @@ import { ModuleMetadata } from '@nestjs/common/interfaces';
|
|
|
3
3
|
import { BPMRootAttachmentOptions } from '../attachment/attachment-options';
|
|
4
4
|
import { AttachmentStorage } from '../attachment/attachment-storage.token';
|
|
5
5
|
import { BPMAuthModuleOptions } from '../bpm-auth/bpm-auth.options';
|
|
6
|
+
import { BPMBusinessCalendar } from '../calendar/business-calendar.token';
|
|
6
7
|
import { BPMRootIdentityOptions } from '../identity/identity-options';
|
|
7
8
|
import { BPMMemberResolver } from '../identity/member-resolver.interface';
|
|
8
9
|
import { BPMRootNotificationOptions } from '../notification/notification-options';
|
|
@@ -27,6 +28,16 @@ export interface BPMRootModuleOptions extends Pick<ModuleMetadata, 'imports'>, B
|
|
|
27
28
|
* operations that require authentication will not receive a host session.
|
|
28
29
|
*/
|
|
29
30
|
readonly authContextFactory?: BPMAuthModuleOptions['contextFactory'];
|
|
31
|
+
/**
|
|
32
|
+
* Host-provided business calendar used by workflow nodes whose SLA opts into
|
|
33
|
+
* `BUSINESS_DAY`.
|
|
34
|
+
*
|
|
35
|
+
* BPMCore ships no national holiday data. When omitted, BPM falls back to a
|
|
36
|
+
* Monday–Friday calendar (see `notificationSlaBusinessCalendarTimeZone`);
|
|
37
|
+
* hosts that need national holidays or make-up working days register their
|
|
38
|
+
* own `BPM_BUSINESS_CALENDAR` provider here.
|
|
39
|
+
*/
|
|
40
|
+
readonly businessCalendarProvider?: Provider<BPMBusinessCalendar>;
|
|
30
41
|
/**
|
|
31
42
|
* Host-provided member resolver provider.
|
|
32
43
|
*
|
|
@@ -72,6 +83,13 @@ export interface BPMRootModuleAsyncOptions extends Pick<ModuleMetadata, 'imports
|
|
|
72
83
|
* use a Nest provider with `useFactory` / `inject` here.
|
|
73
84
|
*/
|
|
74
85
|
readonly attachmentStorageProvider?: Provider<AttachmentStorage>;
|
|
86
|
+
/**
|
|
87
|
+
* Host-provided business calendar for `BUSINESS_DAY` SLAs.
|
|
88
|
+
*
|
|
89
|
+
* This provider is static at module wiring time. If secrets or a repository
|
|
90
|
+
* are required, use a Nest provider with `useFactory` / `inject` here.
|
|
91
|
+
*/
|
|
92
|
+
readonly businessCalendarProvider?: Provider<BPMBusinessCalendar>;
|
|
75
93
|
/**
|
|
76
94
|
* Providers injected into `useFactory`.
|
|
77
95
|
*
|
|
@@ -6,6 +6,7 @@ const tslib_1 = require("tslib");
|
|
|
6
6
|
const common_1 = require("@nestjs/common");
|
|
7
7
|
const attachment_module_1 = require("../attachment/attachment.module");
|
|
8
8
|
const bpm_auth_module_1 = require("../bpm-auth/bpm-auth.module");
|
|
9
|
+
const calendar_module_1 = require("../calendar/calendar.module");
|
|
9
10
|
const delegation_module_1 = require("../delegation/delegation.module");
|
|
10
11
|
const form_module_1 = require("../form/form.module");
|
|
11
12
|
const identity_module_1 = require("../identity/identity.module");
|
|
@@ -82,6 +83,7 @@ let BPMRootModule = BPMRootModule_1 = class BPMRootModule {
|
|
|
82
83
|
return {
|
|
83
84
|
exports: [
|
|
84
85
|
notification_options_module_1.NotificationOptionsModule,
|
|
86
|
+
calendar_module_1.CalendarModule,
|
|
85
87
|
bpm_auth_module_1.BPMAuthModule,
|
|
86
88
|
identity_module_1.IdentityModule,
|
|
87
89
|
organization_module_1.OrganizationModule,
|
|
@@ -99,6 +101,9 @@ let BPMRootModule = BPMRootModule_1 = class BPMRootModule {
|
|
|
99
101
|
inject: options.inject,
|
|
100
102
|
useFactory: options.useFactory,
|
|
101
103
|
}),
|
|
104
|
+
calendar_module_1.CalendarModule.forRoot({
|
|
105
|
+
businessCalendarProvider: options.businessCalendarProvider,
|
|
106
|
+
}),
|
|
102
107
|
bpm_auth_module_1.BPMAuthModule.forRootAsync(authOptions),
|
|
103
108
|
identity_module_1.IdentityModule.forRootAsync({
|
|
104
109
|
imports: options.imports,
|
|
@@ -139,6 +144,9 @@ exports.BPMRootModule = BPMRootModule = BPMRootModule_1 = tslib_1.__decorate([
|
|
|
139
144
|
function createBPMFeatureModules(options) {
|
|
140
145
|
return [
|
|
141
146
|
notification_options_module_1.NotificationOptionsModule.forRoot(options),
|
|
147
|
+
calendar_module_1.CalendarModule.forRoot({
|
|
148
|
+
businessCalendarProvider: options.businessCalendarProvider,
|
|
149
|
+
}),
|
|
142
150
|
bpm_auth_module_1.BPMAuthModule.forRoot(createBPMAuthModuleOptions(options)),
|
|
143
151
|
identity_module_1.IdentityModule.forRoot({
|
|
144
152
|
...options,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bpm-root.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/bpm/bpm-root.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAMwB;AAGxB,uEAAmE;AAEnE,iEAA4D;
|
|
1
|
+
{"version":3,"file":"bpm-root.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/bpm/bpm-root.module.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Provider } from '@nestjs/common';
|
|
2
|
+
import { BPMBusinessCalendar } from './business-calendar.token';
|
|
3
|
+
/**
|
|
4
|
+
* Default {@link BPMBusinessCalendar} used when the host registers none.
|
|
5
|
+
*
|
|
6
|
+
* Treats Monday–Friday as working days in the time zone configured through
|
|
7
|
+
* `notificationSlaBusinessCalendarTimeZone`, and knows about no holidays. Hosts
|
|
8
|
+
* that need national holidays or make-up working days replace this provider via
|
|
9
|
+
* `BPMRootModule`'s `businessCalendarProvider`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const defaultBusinessCalendarProvider: Provider<BPMBusinessCalendar>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultBusinessCalendarProvider = void 0;
|
|
4
|
+
const notification_options_1 = require("../notification/notification-options");
|
|
5
|
+
const business_calendar_token_1 = require("./business-calendar.token");
|
|
6
|
+
const weekday_business_calendar_1 = require("./weekday-business-calendar");
|
|
7
|
+
/**
|
|
8
|
+
* Default {@link BPMBusinessCalendar} used when the host registers none.
|
|
9
|
+
*
|
|
10
|
+
* Treats Monday–Friday as working days in the time zone configured through
|
|
11
|
+
* `notificationSlaBusinessCalendarTimeZone`, and knows about no holidays. Hosts
|
|
12
|
+
* that need national holidays or make-up working days replace this provider via
|
|
13
|
+
* `BPMRootModule`'s `businessCalendarProvider`.
|
|
14
|
+
*/
|
|
15
|
+
exports.defaultBusinessCalendarProvider = {
|
|
16
|
+
inject: [notification_options_1.BPM_NOTIFICATION_OPTIONS],
|
|
17
|
+
provide: business_calendar_token_1.BPM_BUSINESS_CALENDAR,
|
|
18
|
+
useFactory: (options) => new weekday_business_calendar_1.BPMWeekdayBusinessCalendar(options.slaBusinessCalendarTimeZone),
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=business-calendar.provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"business-calendar.provider.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/business-calendar.provider.ts"],"names":[],"mappings":";;;AACA,+EAG8C;AAC9C,uEAGmC;AACnC,2EAAyE;AAEzE;;;;;;;GAOG;AACU,QAAA,+BAA+B,GAAkC;IAC5E,MAAM,EAAE,CAAC,+CAAwB,CAAC;IAClC,OAAO,EAAE,+CAAqB;IAC9B,UAAU,EAAE,CACV,OAAuC,EAClB,EAAE,CACvB,IAAI,sDAA0B,CAAC,OAAO,CAAC,2BAA2B,CAAC;CACtE,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { InjectionToken } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Host-provided business calendar used to resolve `BUSINESS_DAY` SLA due
|
|
4
|
+
* dates.
|
|
5
|
+
*
|
|
6
|
+
* BPMCore deliberately ships **no** national holiday data. A host that needs
|
|
7
|
+
* real working-day semantics (national holidays, make-up working Saturdays,
|
|
8
|
+
* company shutdown days) implements this contract against its own calendar
|
|
9
|
+
* source and registers it through `BPMRootModule`'s `businessCalendarProvider`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* BPMRootModule.forRoot({
|
|
14
|
+
* businessCalendarProvider: {
|
|
15
|
+
* provide: BPM_BUSINESS_CALENDAR,
|
|
16
|
+
* useClass: TaiwanBusinessCalendar,
|
|
17
|
+
* },
|
|
18
|
+
* // ...
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export interface BPMBusinessCalendar {
|
|
23
|
+
/**
|
|
24
|
+
* IANA time zone the calendar's dates are expressed in, for example
|
|
25
|
+
* `Asia/Taipei`. BPM converts each instant to a local date in this zone
|
|
26
|
+
* before asking {@link BPMBusinessCalendar.isBusinessDay}, so day boundaries
|
|
27
|
+
* follow the host's calendar rather than the server's locale or UTC.
|
|
28
|
+
*/
|
|
29
|
+
readonly timeZone: string;
|
|
30
|
+
/**
|
|
31
|
+
* Answers whether `localDate` is a working day.
|
|
32
|
+
*
|
|
33
|
+
* @param localDate Calendar date in `YYYY-MM-DD` form, already expressed in
|
|
34
|
+
* {@link BPMBusinessCalendar.timeZone}.
|
|
35
|
+
*/
|
|
36
|
+
isBusinessDay(localDate: string): boolean | Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
export declare const BPM_BUSINESS_CALENDAR: InjectionToken<BPMBusinessCalendar>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"business-calendar.token.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/business-calendar.token.ts"],"names":[],"mappings":";;;AAwCa,QAAA,qBAAqB,GAChC,MAAM,CAAC,uBAAuB,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DynamicModule, Provider } from '@nestjs/common';
|
|
2
|
+
import { BPMBusinessCalendar } from './business-calendar.token';
|
|
3
|
+
export interface CalendarModuleOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Host-provided business calendar. When omitted, BPM falls back to a
|
|
6
|
+
* Monday–Friday calendar with no holiday knowledge.
|
|
7
|
+
*/
|
|
8
|
+
readonly businessCalendarProvider?: Provider<BPMBusinessCalendar>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Supplies SLA scheduling to every BPM module.
|
|
12
|
+
*
|
|
13
|
+
* Global because the workflow engine computes due dates while creating tasks
|
|
14
|
+
* and hosts should not have to thread the calendar through each feature module.
|
|
15
|
+
*/
|
|
16
|
+
export declare class CalendarModule {
|
|
17
|
+
static forRoot(options?: CalendarModuleOptions): DynamicModule;
|
|
18
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var CalendarModule_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.CalendarModule = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const business_calendar_provider_1 = require("./business-calendar.provider");
|
|
8
|
+
const sla_schedule_service_1 = require("./sla-schedule.service");
|
|
9
|
+
/**
|
|
10
|
+
* Supplies SLA scheduling to every BPM module.
|
|
11
|
+
*
|
|
12
|
+
* Global because the workflow engine computes due dates while creating tasks
|
|
13
|
+
* and hosts should not have to thread the calendar through each feature module.
|
|
14
|
+
*/
|
|
15
|
+
let CalendarModule = CalendarModule_1 = class CalendarModule {
|
|
16
|
+
static forRoot(options = {}) {
|
|
17
|
+
return {
|
|
18
|
+
exports: [sla_schedule_service_1.BPMSlaScheduleService],
|
|
19
|
+
module: CalendarModule_1,
|
|
20
|
+
providers: [
|
|
21
|
+
options.businessCalendarProvider ?? business_calendar_provider_1.defaultBusinessCalendarProvider,
|
|
22
|
+
sla_schedule_service_1.BPMSlaScheduleService,
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.CalendarModule = CalendarModule;
|
|
28
|
+
exports.CalendarModule = CalendarModule = CalendarModule_1 = tslib_1.__decorate([
|
|
29
|
+
(0, common_1.Global)(),
|
|
30
|
+
(0, common_1.Module)({})
|
|
31
|
+
], CalendarModule);
|
|
32
|
+
//# sourceMappingURL=calendar.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/calendar.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAAyE;AAEzE,6EAA+E;AAC/E,iEAA+D;AAU/D;;;;;GAKG;AAGI,IAAM,cAAc,sBAApB,MAAM,cAAc;IACzB,MAAM,CAAC,OAAO,CAAC,UAAiC,EAAE;QAChD,OAAO;YACL,OAAO,EAAE,CAAC,4CAAqB,CAAC;YAChC,MAAM,EAAE,gBAAc;YACtB,SAAS,EAAE;gBACT,OAAO,CAAC,wBAAwB,IAAI,4DAA+B;gBACnE,4CAAqB;aACtB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAXY,wCAAc;yBAAd,cAAc;IAF1B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,cAAc,CAW1B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./business-calendar.provider"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./business-calendar.token"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./calendar.module"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./sla-schedule.service"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./weekday-business-calendar"), exports);
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/index.ts"],"names":[],"mappings":";;;AAAA,uEAA6C;AAC7C,oEAA0C;AAC1C,4DAAkC;AAClC,iEAAuC;AACvC,sEAA4C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { UserTaskNode } from '@rytass/bpm-core-shared/workflow';
|
|
2
|
+
import { BPMBusinessCalendar } from './business-calendar.token';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves task SLA due dates, honouring {@link SlaConfig.calendar}.
|
|
5
|
+
*
|
|
6
|
+
* `CALENDAR` (the default) adds the ISO duration as elapsed wall time —
|
|
7
|
+
* identical to BPM's pre-0.7.0 behaviour. `BUSINESS_DAY` advances the duration's
|
|
8
|
+
* day component across business days only, asking the host-provided
|
|
9
|
+
* {@link BPMBusinessCalendar} about each candidate date; any sub-day component
|
|
10
|
+
* is then added as plain elapsed time on top of the resolved business day.
|
|
11
|
+
*/
|
|
12
|
+
export declare class BPMSlaScheduleService {
|
|
13
|
+
private readonly businessCalendar;
|
|
14
|
+
private readonly logger;
|
|
15
|
+
private readonly dateFormatter;
|
|
16
|
+
constructor(businessCalendar: BPMBusinessCalendar);
|
|
17
|
+
resolveTaskSlaDueAt({ node, now, }: {
|
|
18
|
+
readonly node: UserTaskNode;
|
|
19
|
+
readonly now: Date;
|
|
20
|
+
}): Promise<Date | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Walks forward one calendar day at a time from `now`, consuming one unit of
|
|
23
|
+
* `businessDays` for each date the host calendar reports as a working day,
|
|
24
|
+
* and returns how many calendar days were stepped.
|
|
25
|
+
*
|
|
26
|
+
* The starting date is never counted: an SLA of "1 business day" always lands
|
|
27
|
+
* on the *next* working day, whether the task was raised on a Monday or on a
|
|
28
|
+
* Saturday.
|
|
29
|
+
*/
|
|
30
|
+
private countCalendarDaysForBusinessDays;
|
|
31
|
+
/** Formats an instant as a `YYYY-MM-DD` date in the calendar's time zone. */
|
|
32
|
+
private readLocalDate;
|
|
33
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var BPMSlaScheduleService_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.BPMSlaScheduleService = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const iso_duration_1 = require("../common/iso-duration");
|
|
8
|
+
const business_calendar_token_1 = require("./business-calendar.token");
|
|
9
|
+
/**
|
|
10
|
+
* Upper bound on how far the business-day search may walk before giving up.
|
|
11
|
+
*
|
|
12
|
+
* A host calendar that reports every date as a non-business day would
|
|
13
|
+
* otherwise loop forever (and, when the calendar is database-backed, issue one
|
|
14
|
+
* query per step). The allowance is generous enough for weekends plus a long
|
|
15
|
+
* holiday season, and capped so a misconfigured calendar degrades quickly.
|
|
16
|
+
*/
|
|
17
|
+
const MAX_BUSINESS_DAY_SCAN_STEPS = 400;
|
|
18
|
+
function readBusinessDayScanLimit(days) {
|
|
19
|
+
return Math.min(days * 7 + 60, MAX_BUSINESS_DAY_SCAN_STEPS);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolves task SLA due dates, honouring {@link SlaConfig.calendar}.
|
|
23
|
+
*
|
|
24
|
+
* `CALENDAR` (the default) adds the ISO duration as elapsed wall time —
|
|
25
|
+
* identical to BPM's pre-0.7.0 behaviour. `BUSINESS_DAY` advances the duration's
|
|
26
|
+
* day component across business days only, asking the host-provided
|
|
27
|
+
* {@link BPMBusinessCalendar} about each candidate date; any sub-day component
|
|
28
|
+
* is then added as plain elapsed time on top of the resolved business day.
|
|
29
|
+
*/
|
|
30
|
+
let BPMSlaScheduleService = BPMSlaScheduleService_1 = class BPMSlaScheduleService {
|
|
31
|
+
constructor(businessCalendar) {
|
|
32
|
+
this.businessCalendar = businessCalendar;
|
|
33
|
+
this.logger = new common_1.Logger(BPMSlaScheduleService_1.name);
|
|
34
|
+
this.dateFormatter = new Intl.DateTimeFormat('en-CA', {
|
|
35
|
+
day: '2-digit',
|
|
36
|
+
month: '2-digit',
|
|
37
|
+
timeZone: businessCalendar.timeZone,
|
|
38
|
+
year: 'numeric',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async resolveTaskSlaDueAt({ node, now, }) {
|
|
42
|
+
const sla = node.data.sla;
|
|
43
|
+
if (!sla?.duration) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const parts = (0, iso_duration_1.parseIsoDurationParts)(sla.duration);
|
|
47
|
+
if (!parts) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
if (sla.calendar !== 'BUSINESS_DAY' || parts.days === 0) {
|
|
51
|
+
return new Date(now.getTime() + parts.days * iso_duration_1.MS_PER_DAY + parts.timeMs);
|
|
52
|
+
}
|
|
53
|
+
const advancedDays = await this.countCalendarDaysForBusinessDays(now, parts.days, node.id);
|
|
54
|
+
return new Date(now.getTime() + advancedDays * iso_duration_1.MS_PER_DAY + parts.timeMs);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Walks forward one calendar day at a time from `now`, consuming one unit of
|
|
58
|
+
* `businessDays` for each date the host calendar reports as a working day,
|
|
59
|
+
* and returns how many calendar days were stepped.
|
|
60
|
+
*
|
|
61
|
+
* The starting date is never counted: an SLA of "1 business day" always lands
|
|
62
|
+
* on the *next* working day, whether the task was raised on a Monday or on a
|
|
63
|
+
* Saturday.
|
|
64
|
+
*/
|
|
65
|
+
async countCalendarDaysForBusinessDays(now, businessDays, nodeId) {
|
|
66
|
+
const scanLimit = readBusinessDayScanLimit(businessDays);
|
|
67
|
+
let remainingBusinessDays = businessDays;
|
|
68
|
+
let steps = 0;
|
|
69
|
+
while (remainingBusinessDays > 0 && steps < scanLimit) {
|
|
70
|
+
steps += 1;
|
|
71
|
+
const candidate = new Date(now.getTime() + steps * iso_duration_1.MS_PER_DAY);
|
|
72
|
+
if (await this.businessCalendar.isBusinessDay(this.readLocalDate(candidate))) {
|
|
73
|
+
remainingBusinessDays -= 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (remainingBusinessDays > 0) {
|
|
77
|
+
this.logger.warn(`Business calendar reported no working day within ${scanLimit} days for node ${nodeId}; falling back to calendar time.`);
|
|
78
|
+
return businessDays;
|
|
79
|
+
}
|
|
80
|
+
return steps;
|
|
81
|
+
}
|
|
82
|
+
/** Formats an instant as a `YYYY-MM-DD` date in the calendar's time zone. */
|
|
83
|
+
readLocalDate(value) {
|
|
84
|
+
// `en-CA` renders ISO-ordered dates, so no part reassembly is needed.
|
|
85
|
+
return this.dateFormatter.format(value);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
exports.BPMSlaScheduleService = BPMSlaScheduleService;
|
|
89
|
+
exports.BPMSlaScheduleService = BPMSlaScheduleService = BPMSlaScheduleService_1 = tslib_1.__decorate([
|
|
90
|
+
(0, common_1.Injectable)(),
|
|
91
|
+
tslib_1.__param(0, (0, common_1.Inject)(business_calendar_token_1.BPM_BUSINESS_CALENDAR)),
|
|
92
|
+
tslib_1.__metadata("design:paramtypes", [Object])
|
|
93
|
+
], BPMSlaScheduleService);
|
|
94
|
+
//# sourceMappingURL=sla-schedule.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sla-schedule.service.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/sla-schedule.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BPMBusinessCalendar } from './business-calendar.token';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in fallback calendar: Monday through Friday are working days, weekends
|
|
4
|
+
* are not, and no holiday is known.
|
|
5
|
+
*
|
|
6
|
+
* This is what a host gets when it opts a node into `BUSINESS_DAY` without
|
|
7
|
+
* registering a calendar. It is intentionally naive — a host that cares about
|
|
8
|
+
* national holidays or make-up working days must supply its own
|
|
9
|
+
* {@link BPMBusinessCalendar}.
|
|
10
|
+
*/
|
|
11
|
+
export declare class BPMWeekdayBusinessCalendar implements BPMBusinessCalendar {
|
|
12
|
+
readonly timeZone: string;
|
|
13
|
+
constructor(timeZone?: string);
|
|
14
|
+
isBusinessDay(localDate: string): boolean;
|
|
15
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BPMWeekdayBusinessCalendar = void 0;
|
|
4
|
+
const SATURDAY = 6;
|
|
5
|
+
const SUNDAY = 0;
|
|
6
|
+
/**
|
|
7
|
+
* Built-in fallback calendar: Monday through Friday are working days, weekends
|
|
8
|
+
* are not, and no holiday is known.
|
|
9
|
+
*
|
|
10
|
+
* This is what a host gets when it opts a node into `BUSINESS_DAY` without
|
|
11
|
+
* registering a calendar. It is intentionally naive — a host that cares about
|
|
12
|
+
* national holidays or make-up working days must supply its own
|
|
13
|
+
* {@link BPMBusinessCalendar}.
|
|
14
|
+
*/
|
|
15
|
+
class BPMWeekdayBusinessCalendar {
|
|
16
|
+
constructor(timeZone = 'UTC') {
|
|
17
|
+
this.timeZone = timeZone;
|
|
18
|
+
}
|
|
19
|
+
isBusinessDay(localDate) {
|
|
20
|
+
// `localDate` is already expressed in this calendar's zone, so reading it
|
|
21
|
+
// back as a UTC instant yields the correct weekday without re-applying an
|
|
22
|
+
// offset.
|
|
23
|
+
const weekday = new Date(`${localDate}T00:00:00.000Z`).getUTCDay();
|
|
24
|
+
return weekday !== SATURDAY && weekday !== SUNDAY;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.BPMWeekdayBusinessCalendar = BPMWeekdayBusinessCalendar;
|
|
28
|
+
//# sourceMappingURL=weekday-business-calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weekday-business-calendar.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/weekday-business-calendar.ts"],"names":[],"mappings":";;;AAEA,MAAM,QAAQ,GAAG,CAAC,CAAC;AACnB,MAAM,MAAM,GAAG,CAAC,CAAC;AAEjB;;;;;;;;GAQG;AACH,MAAa,0BAA0B;IAGrC,YAAY,QAAQ,GAAG,KAAK;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,aAAa,CAAC,SAAiB;QAC7B,0EAA0E;QAC1E,0EAA0E;QAC1E,UAAU;QACV,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,SAAS,gBAAgB,CAAC,CAAC,SAAS,EAAE,CAAC;QAEnE,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,MAAM,CAAC;IACpD,CAAC;CACF;AAfD,gEAeC"}
|
|
@@ -1 +1,12 @@
|
|
|
1
|
+
export declare const MS_PER_DAY: number;
|
|
2
|
+
/**
|
|
3
|
+
* The day component and the sub-day (time) component of an ISO duration, kept
|
|
4
|
+
* apart because business-day SLA scheduling advances them differently: `days`
|
|
5
|
+
* skips non-business dates, `timeMs` is added as plain elapsed time.
|
|
6
|
+
*/
|
|
7
|
+
export interface IsoDurationParts {
|
|
8
|
+
readonly days: number;
|
|
9
|
+
readonly timeMs: number;
|
|
10
|
+
}
|
|
1
11
|
export declare function parseIsoDurationToMilliseconds(value: string): number | null;
|
|
12
|
+
export declare function parseIsoDurationParts(value: string): IsoDurationParts | null;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MS_PER_DAY = void 0;
|
|
3
4
|
exports.parseIsoDurationToMilliseconds = parseIsoDurationToMilliseconds;
|
|
5
|
+
exports.parseIsoDurationParts = parseIsoDurationParts;
|
|
4
6
|
const ISO_DURATION_PATTERN = /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/u;
|
|
5
7
|
const MS_PER_SECOND = 1000;
|
|
6
8
|
const SECONDS_PER_MINUTE = 60;
|
|
7
9
|
const MINUTES_PER_HOUR = 60;
|
|
8
10
|
const HOURS_PER_DAY = 24;
|
|
11
|
+
exports.MS_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MS_PER_SECOND;
|
|
9
12
|
function parseIsoDurationToMilliseconds(value) {
|
|
13
|
+
const parts = parseIsoDurationParts(value);
|
|
14
|
+
return parts ? parts.days * exports.MS_PER_DAY + parts.timeMs : null;
|
|
15
|
+
}
|
|
16
|
+
function parseIsoDurationParts(value) {
|
|
10
17
|
const match = ISO_DURATION_PATTERN.exec(value.trim());
|
|
11
18
|
if (!match) {
|
|
12
19
|
return null;
|
|
@@ -15,11 +22,13 @@ function parseIsoDurationToMilliseconds(value) {
|
|
|
15
22
|
const hours = readDurationUnit(match[2]);
|
|
16
23
|
const minutes = readDurationUnit(match[3]);
|
|
17
24
|
const seconds = readDurationUnit(match[4]);
|
|
18
|
-
const
|
|
25
|
+
const timeSeconds = seconds +
|
|
19
26
|
minutes * SECONDS_PER_MINUTE +
|
|
20
|
-
hours * MINUTES_PER_HOUR * SECONDS_PER_MINUTE
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
hours * MINUTES_PER_HOUR * SECONDS_PER_MINUTE;
|
|
28
|
+
if (days === 0 && timeSeconds === 0) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return { days, timeMs: timeSeconds * MS_PER_SECOND };
|
|
23
32
|
}
|
|
24
33
|
function readDurationUnit(value) {
|
|
25
34
|
return value ? Number(value) : 0;
|