@rytass/bpm-core-nestjs-module 0.1.10 → 0.3.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.
Files changed (90) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/README.md +43 -0
  3. package/package.json +3 -2
  4. package/src/lib/database/migration-runner.js +2 -0
  5. package/src/lib/database/migration-runner.js.map +1 -1
  6. package/src/lib/database/reconcile-legacy-migrations.d.ts +13 -0
  7. package/src/lib/database/reconcile-legacy-migrations.js +70 -0
  8. package/src/lib/database/reconcile-legacy-migrations.js.map +1 -0
  9. package/src/lib/form/dto/form-definition.input.d.ts +5 -0
  10. package/src/lib/form/dto/form-definition.input.js +24 -1
  11. package/src/lib/form/dto/form-definition.input.js.map +1 -1
  12. package/src/lib/form/form.mutations.d.ts +2 -2
  13. package/src/lib/form/form.mutations.js +6 -5
  14. package/src/lib/form/form.mutations.js.map +1 -1
  15. package/src/lib/form/form.service.d.ts +20 -6
  16. package/src/lib/form/form.service.js +129 -80
  17. package/src/lib/form/form.service.js.map +1 -1
  18. package/src/lib/migrations/0000000014000-notification-resolution.d.ts +6 -0
  19. package/src/lib/migrations/0000000014000-notification-resolution.js +30 -0
  20. package/src/lib/migrations/0000000014000-notification-resolution.js.map +1 -0
  21. package/src/lib/migrations/0000000015000-backfill-stale-notification-resolution.d.ts +15 -0
  22. package/src/lib/migrations/0000000015000-backfill-stale-notification-resolution.js +37 -0
  23. package/src/lib/migrations/0000000015000-backfill-stale-notification-resolution.js.map +1 -0
  24. package/src/lib/migrations/0000000016000-archive-parallel-form-drafts.d.ts +15 -0
  25. package/src/lib/migrations/0000000016000-archive-parallel-form-drafts.js +34 -0
  26. package/src/lib/migrations/0000000016000-archive-parallel-form-drafts.js.map +1 -0
  27. package/src/lib/migrations/0000000017000-adhoc-directives.d.ts +6 -0
  28. package/src/lib/migrations/0000000017000-adhoc-directives.js +53 -0
  29. package/src/lib/migrations/0000000017000-adhoc-directives.js.map +1 -0
  30. package/src/lib/migrations/index.d.ts +4 -0
  31. package/src/lib/migrations/index.js +12 -0
  32. package/src/lib/migrations/index.js.map +1 -1
  33. package/src/lib/notification/notification.entity.d.ts +9 -1
  34. package/src/lib/notification/notification.entity.js +27 -0
  35. package/src/lib/notification/notification.entity.js.map +1 -1
  36. package/src/lib/notification/notification.enums.d.ts +14 -0
  37. package/src/lib/notification/notification.enums.js +19 -1
  38. package/src/lib/notification/notification.enums.js.map +1 -1
  39. package/src/lib/notification/notification.service.d.ts +40 -0
  40. package/src/lib/notification/notification.service.js +92 -0
  41. package/src/lib/notification/notification.service.js.map +1 -1
  42. package/src/lib/template/compose-approval-template.object.d.ts +11 -0
  43. package/src/lib/template/compose-approval-template.object.js +36 -0
  44. package/src/lib/template/compose-approval-template.object.js.map +1 -0
  45. package/src/lib/template/compose-template.mutations.d.ts +8 -0
  46. package/src/lib/template/compose-template.mutations.js +32 -0
  47. package/src/lib/template/compose-template.mutations.js.map +1 -0
  48. package/src/lib/template/dto/compose-approval-template.input.d.ts +17 -0
  49. package/src/lib/template/dto/compose-approval-template.input.js +99 -0
  50. package/src/lib/template/dto/compose-approval-template.input.js.map +1 -0
  51. package/src/lib/template/index.d.ts +2 -0
  52. package/src/lib/template/index.js +2 -0
  53. package/src/lib/template/index.js.map +1 -1
  54. package/src/lib/template/template.module.js +9 -1
  55. package/src/lib/template/template.module.js.map +1 -1
  56. package/src/lib/template/template.service.d.ts +25 -6
  57. package/src/lib/template/template.service.js +216 -83
  58. package/src/lib/template/template.service.js.map +1 -1
  59. package/src/lib/workflow-engine/adhoc-directive.entity.d.ts +31 -0
  60. package/src/lib/workflow-engine/adhoc-directive.entity.js +105 -0
  61. package/src/lib/workflow-engine/adhoc-directive.entity.js.map +1 -0
  62. package/src/lib/workflow-engine/adhoc.enums.d.ts +21 -0
  63. package/src/lib/workflow-engine/adhoc.enums.js +42 -0
  64. package/src/lib/workflow-engine/adhoc.enums.js.map +1 -0
  65. package/src/lib/workflow-engine/dto/adhoc-notification.input.d.ts +6 -0
  66. package/src/lib/workflow-engine/dto/adhoc-notification.input.js +28 -0
  67. package/src/lib/workflow-engine/dto/adhoc-notification.input.js.map +1 -0
  68. package/src/lib/workflow-engine/dto/adhoc-target.input.d.ts +16 -0
  69. package/src/lib/workflow-engine/dto/adhoc-target.input.js +61 -0
  70. package/src/lib/workflow-engine/dto/adhoc-target.input.js.map +1 -0
  71. package/src/lib/workflow-engine/index.d.ts +4 -0
  72. package/src/lib/workflow-engine/index.js +4 -0
  73. package/src/lib/workflow-engine/index.js.map +1 -1
  74. package/src/lib/workflow-engine/task.entity.d.ts +5 -0
  75. package/src/lib/workflow-engine/task.entity.js +21 -0
  76. package/src/lib/workflow-engine/task.entity.js.map +1 -1
  77. package/src/lib/workflow-engine/workflow-engine.enums.d.ts +3 -0
  78. package/src/lib/workflow-engine/workflow-engine.enums.js +3 -0
  79. package/src/lib/workflow-engine/workflow-engine.enums.js.map +1 -1
  80. package/src/lib/workflow-engine/workflow-engine.module.js +2 -0
  81. package/src/lib/workflow-engine/workflow-engine.module.js.map +1 -1
  82. package/src/lib/workflow-engine/workflow-engine.mutations.d.ts +10 -0
  83. package/src/lib/workflow-engine/workflow-engine.mutations.js +112 -0
  84. package/src/lib/workflow-engine/workflow-engine.mutations.js.map +1 -1
  85. package/src/lib/workflow-engine/workflow-engine.queries.d.ts +2 -0
  86. package/src/lib/workflow-engine/workflow-engine.queries.js +12 -0
  87. package/src/lib/workflow-engine/workflow-engine.queries.js.map +1 -1
  88. package/src/lib/workflow-engine/workflow-engine.service.d.ts +44 -1
  89. package/src/lib/workflow-engine/workflow-engine.service.js +817 -41
  90. package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose-approval-template.input.js","sourceRoot":"","sources":["../../../../../../../libs/bpm-core/src/lib/template/dto/compose-approval-template.input.ts"],"names":[],"mappings":";;;;AAAA,6CAAuD;AACvD,qDAA0E;AAGnE,IAAM,oCAAoC,GAA1C,MAAM,oCAAoC;CA2EhD,CAAA;AA3EY,oFAAoC;AAK/C;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,YAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACnC,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAM,GAAE;;8EACwB;AAKjC;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,YAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACnC,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAM,GAAE;;wEACkB;AAK3B;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,0BAAQ,GAAE;;sEACO;AAKlB;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;6EACqB;AAKhC;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;wEACgB;AAK3B;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;0EACkB;AAK7B;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,0BAAQ,GAAE;;0EACW;AAKtB;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;iFACyB;AAKpC;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;sEACc;AAKzB;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,YAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACnC,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAM,GAAE;;wEACkB;AAI3B;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,0BAAQ,GAAE;;oFACqB;AAKhC;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;gFACwB;AAKnC;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;oFAC4B;AAKvC;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;6EACqB;AAKhC;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,2BAAS,GAAE;;qEACM;+CA1EP,oCAAoC;IADhD,IAAA,mBAAS,GAAE;GACC,oCAAoC,CA2EhD"}
@@ -1,7 +1,9 @@
1
1
  export * from './approval-template-category.entity';
2
2
  export * from './approval-template-version.entity';
3
3
  export * from './approval-template.entity';
4
+ export * from './compose-approval-template.object';
4
5
  export * from './dto/approval-template.input';
6
+ export * from './dto/compose-approval-template.input';
5
7
  export * from './template.enums';
6
8
  export * from './template.module';
7
9
  export * from './template.service';
@@ -4,7 +4,9 @@ const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./approval-template-category.entity"), exports);
5
5
  tslib_1.__exportStar(require("./approval-template-version.entity"), exports);
6
6
  tslib_1.__exportStar(require("./approval-template.entity"), exports);
7
+ tslib_1.__exportStar(require("./compose-approval-template.object"), exports);
7
8
  tslib_1.__exportStar(require("./dto/approval-template.input"), exports);
9
+ tslib_1.__exportStar(require("./dto/compose-approval-template.input"), exports);
8
10
  tslib_1.__exportStar(require("./template.enums"), exports);
9
11
  tslib_1.__exportStar(require("./template.module"), exports);
10
12
  tslib_1.__exportStar(require("./template.service"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/index.ts"],"names":[],"mappings":";;;AAAA,8EAAoD;AACpD,6EAAmD;AACnD,qEAA2C;AAC3C,wEAA8C;AAC9C,2DAAiC;AACjC,4DAAkC;AAClC,6DAAmC;AACnC,0EAAgD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/index.ts"],"names":[],"mappings":";;;AAAA,8EAAoD;AACpD,6EAAmD;AACnD,qEAA2C;AAC3C,6EAAmD;AACnD,wEAA8C;AAC9C,gFAAsD;AACtD,2DAAiC;AACjC,4DAAkC;AAClC,6DAAmC;AACnC,0EAAgD"}
@@ -6,9 +6,11 @@ const common_1 = require("@nestjs/common");
6
6
  const typeorm_1 = require("@nestjs/typeorm");
7
7
  const condition_module_1 = require("../condition/condition.module");
8
8
  const form_definition_version_entity_1 = require("../form/form-definition-version.entity");
9
+ const form_module_1 = require("../form/form.module");
9
10
  const approval_template_category_entity_1 = require("./approval-template-category.entity");
10
11
  const approval_template_entity_1 = require("./approval-template.entity");
11
12
  const approval_template_version_entity_1 = require("./approval-template-version.entity");
13
+ const compose_template_mutations_1 = require("./compose-template.mutations");
12
14
  const template_mutations_1 = require("./template.mutations");
13
15
  const template_queries_1 = require("./template.queries");
14
16
  const template_service_1 = require("./template.service");
@@ -19,6 +21,7 @@ exports.TemplateModule = TemplateModule = tslib_1.__decorate([
19
21
  (0, common_1.Module)({
20
22
  imports: [
21
23
  condition_module_1.ConditionModule,
24
+ form_module_1.FormModule,
22
25
  typeorm_1.TypeOrmModule.forFeature([
23
26
  approval_template_category_entity_1.ApprovalTemplateCategoryEntity,
24
27
  approval_template_entity_1.ApprovalTemplateEntity,
@@ -26,7 +29,12 @@ exports.TemplateModule = TemplateModule = tslib_1.__decorate([
26
29
  form_definition_version_entity_1.FormDefinitionVersionEntity,
27
30
  ]),
28
31
  ],
29
- providers: [template_mutations_1.TemplateMutations, template_queries_1.TemplateQueries, template_service_1.TemplateService],
32
+ providers: [
33
+ compose_template_mutations_1.ComposeTemplateMutations,
34
+ template_mutations_1.TemplateMutations,
35
+ template_queries_1.TemplateQueries,
36
+ template_service_1.TemplateService,
37
+ ],
30
38
  exports: [template_service_1.TemplateService],
31
39
  })
32
40
  ], TemplateModule);
@@ -1 +1 @@
1
- {"version":3,"file":"template.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/template.module.ts"],"names":[],"mappings":";;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,oEAAgE;AAChE,2FAAqF;AACrF,2FAAqF;AACrF,yEAAoE;AACpE,yFAAmF;AACnF,6DAAyD;AACzD,yDAAqD;AACrD,yDAAqD;AAe9C,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IAb1B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,kCAAe;YACf,uBAAa,CAAC,UAAU,CAAC;gBACvB,kEAA8B;gBAC9B,iDAAsB;gBACtB,gEAA6B;gBAC7B,4DAA2B;aAC5B,CAAC;SACH;QACD,SAAS,EAAE,CAAC,sCAAiB,EAAE,kCAAe,EAAE,kCAAe,CAAC;QAChE,OAAO,EAAE,CAAC,kCAAe,CAAC;KAC3B,CAAC;GACW,cAAc,CAAG"}
1
+ {"version":3,"file":"template.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/template.module.ts"],"names":[],"mappings":";;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,oEAAgE;AAChE,2FAAqF;AACrF,qDAAiD;AACjD,2FAAqF;AACrF,yEAAoE;AACpE,yFAAmF;AACnF,6EAAwE;AACxE,6DAAyD;AACzD,yDAAqD;AACrD,yDAAqD;AAqB9C,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IAnB1B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,kCAAe;YACf,wBAAU;YACV,uBAAa,CAAC,UAAU,CAAC;gBACvB,kEAA8B;gBAC9B,iDAAsB;gBACtB,gEAA6B;gBAC7B,4DAA2B;aAC5B,CAAC;SACH;QACD,SAAS,EAAE;YACT,qDAAwB;YACxB,sCAAiB;YACjB,kCAAe;YACf,kCAAe;SAChB;QACD,OAAO,EAAE,CAAC,kCAAe,CAAC;KAC3B,CAAC;GACW,cAAc,CAAG"}
@@ -1,6 +1,9 @@
1
- import { Repository } from 'typeorm';
1
+ import { EntityManager, Repository } from 'typeorm';
2
2
  import { ConditionService } from '../condition/condition.service';
3
3
  import { FormDefinitionVersionEntity } from '../form/form-definition-version.entity';
4
+ import { FormService } from '../form/form.service';
5
+ import { ComposeApprovalTemplateWithFormInput } from './dto/compose-approval-template.input';
6
+ import { ComposeApprovalTemplateWithFormObject } from './compose-approval-template.object';
4
7
  import { ApprovalTemplateCategoryEntity } from './approval-template-category.entity';
5
8
  import { ApprovalTemplateEntity } from './approval-template.entity';
6
9
  import { ApprovalTemplateVersionEntity } from './approval-template-version.entity';
@@ -25,8 +28,19 @@ export declare class TemplateService {
25
28
  private readonly templateVersionRepository;
26
29
  private readonly formDefinitionVersionRepository;
27
30
  private readonly conditionService;
28
- constructor(templateRepository: Repository<ApprovalTemplateEntity>, templateCategoryRepository: Repository<ApprovalTemplateCategoryEntity>, templateVersionRepository: Repository<ApprovalTemplateVersionEntity>, formDefinitionVersionRepository: Repository<FormDefinitionVersionEntity>, conditionService: ConditionService);
29
- createApprovalTemplate(input: CreateApprovalTemplateInput): Promise<ApprovalTemplateEntity>;
31
+ private readonly formService;
32
+ constructor(templateRepository: Repository<ApprovalTemplateEntity>, templateCategoryRepository: Repository<ApprovalTemplateCategoryEntity>, templateVersionRepository: Repository<ApprovalTemplateVersionEntity>, formDefinitionVersionRepository: Repository<FormDefinitionVersionEntity>, conditionService: ConditionService, formService: FormService);
33
+ createApprovalTemplate(input: CreateApprovalTemplateInput, manager?: EntityManager): Promise<ApprovalTemplateEntity>;
34
+ private createApprovalTemplateWithManager;
35
+ /**
36
+ * Atomically build (and optionally publish) a form definition together with
37
+ * the approval template that binds it. The whole flow runs in a single DB
38
+ * transaction so a partial failure rolls back both sides.
39
+ */
40
+ composeApprovalTemplateWithForm(input: ComposeApprovalTemplateWithFormInput, currentMemberId: string | null): Promise<ComposeApprovalTemplateWithFormObject>;
41
+ private resolveComposedFormVersion;
42
+ private resolveComposedTemplateDraftVersion;
43
+ private findDraftTemplateVersion;
30
44
  updateApprovalTemplate(input: UpdateApprovalTemplateInput): Promise<ApprovalTemplateEntity>;
31
45
  listApprovalTemplates(options?: ListApprovalTemplatesOptions): Promise<readonly ApprovalTemplateEntity[]>;
32
46
  countApprovalTemplates({ categoryId, searchText, status, }?: {
@@ -47,13 +61,18 @@ export declare class TemplateService {
47
61
  deleteApprovalTemplateCategory(id: string): Promise<ApprovalTemplateCategoryEntity>;
48
62
  listApprovalTemplateVersions(templateId: string): Promise<readonly ApprovalTemplateVersionEntity[]>;
49
63
  getApprovalTemplateVersion(id: string): Promise<ApprovalTemplateVersionEntity>;
50
- updateApprovalTemplateDraft(input: UpdateApprovalTemplateDraftInput): Promise<ApprovalTemplateVersionEntity>;
51
- forkApprovalTemplate(templateId: string): Promise<ApprovalTemplateVersionEntity>;
52
- publishApprovalTemplateVersion(versionId: string, publishedByMemberId?: string): Promise<ApprovalTemplateVersionEntity>;
64
+ updateApprovalTemplateDraft(input: UpdateApprovalTemplateDraftInput, manager?: EntityManager): Promise<ApprovalTemplateVersionEntity>;
65
+ forkApprovalTemplate(templateId: string, manager?: EntityManager): Promise<ApprovalTemplateVersionEntity>;
66
+ publishApprovalTemplateVersion(versionId: string, publishedByMemberId?: string, manager?: EntityManager): Promise<ApprovalTemplateVersionEntity>;
67
+ private publishApprovalTemplateVersionWithManager;
53
68
  rollbackApprovalTemplateVersion(versionId: string): Promise<ApprovalTemplateVersionEntity>;
54
69
  private validatePublishableVersion;
55
70
  private validateOptionalFormDefinitionVersion;
56
71
  private validateOptionalTemplateCategory;
72
+ private templates;
73
+ private templateVersions;
74
+ private templateCategories;
75
+ private formVersions;
57
76
  private getTemplateOrThrow;
58
77
  private getTemplateCategoryOrThrow;
59
78
  private setApprovalTemplateCategoryActive;
@@ -6,49 +6,155 @@ const common_1 = require("@nestjs/common");
6
6
  const typeorm_1 = require("@nestjs/typeorm");
7
7
  const typeorm_2 = require("typeorm");
8
8
  const condition_service_1 = require("../condition/condition.service");
9
+ const form_definition_entity_1 = require("../form/form-definition.entity");
9
10
  const form_definition_version_entity_1 = require("../form/form-definition-version.entity");
10
11
  const form_enums_1 = require("../form/form.enums");
12
+ const form_service_1 = require("../form/form.service");
11
13
  const approval_template_category_entity_1 = require("./approval-template-category.entity");
12
14
  const approval_template_entity_1 = require("./approval-template.entity");
13
15
  const approval_template_version_entity_1 = require("./approval-template-version.entity");
14
16
  const template_enums_1 = require("./template.enums");
15
17
  const workflow_definition_validator_1 = require("./workflow-definition.validator");
16
18
  let TemplateService = class TemplateService {
17
- constructor(templateRepository, templateCategoryRepository, templateVersionRepository, formDefinitionVersionRepository, conditionService) {
19
+ constructor(templateRepository, templateCategoryRepository, templateVersionRepository, formDefinitionVersionRepository, conditionService, formService) {
18
20
  this.templateRepository = templateRepository;
19
21
  this.templateCategoryRepository = templateCategoryRepository;
20
22
  this.templateVersionRepository = templateVersionRepository;
21
23
  this.formDefinitionVersionRepository = formDefinitionVersionRepository;
22
24
  this.conditionService = conditionService;
23
- }
24
- async createApprovalTemplate(input) {
25
- await this.validateOptionalFormDefinitionVersion(input.formDefinitionVersionId);
26
- const category = await this.validateOptionalTemplateCategory(input.categoryId);
25
+ this.formService = formService;
26
+ }
27
+ async createApprovalTemplate(input, manager) {
28
+ const run = (txManager) => this.createApprovalTemplateWithManager(txManager, input);
29
+ return manager
30
+ ? run(manager)
31
+ : this.templateRepository.manager.transaction(run);
32
+ }
33
+ async createApprovalTemplateWithManager(manager, input) {
34
+ await this.validateOptionalFormDefinitionVersion(input.formDefinitionVersionId, manager);
35
+ const category = await this.validateOptionalTemplateCategory(input.categoryId, manager);
36
+ const templateRepository = manager.getRepository(approval_template_entity_1.ApprovalTemplateEntity);
37
+ const versionRepository = manager.getRepository(approval_template_version_entity_1.ApprovalTemplateVersionEntity);
38
+ const template = await templateRepository.save(templateRepository.create({
39
+ category: input.category ?? category?.name ?? null,
40
+ categoryId: category?.id ?? null,
41
+ createdByMemberId: input.createdByMemberId,
42
+ currentVersionId: null,
43
+ description: input.description,
44
+ name: input.name,
45
+ }));
46
+ await versionRepository.save(versionRepository.create({
47
+ archivedAt: null,
48
+ formDefinitionVersionId: input.formDefinitionVersionId,
49
+ initiatorPolicyCel: null,
50
+ notificationConfig: null,
51
+ publishedAt: null,
52
+ publishedByMemberId: null,
53
+ slaDefaults: null,
54
+ status: template_enums_1.ApprovalTemplateVersionStatusEnum.DRAFT,
55
+ templateId: template.id,
56
+ version: 1,
57
+ workflowDefinition: workflow_definition_validator_1.EMPTY_WORKFLOW_DEFINITION,
58
+ }));
59
+ return template;
60
+ }
61
+ /**
62
+ * Atomically build (and optionally publish) a form definition together with
63
+ * the approval template that binds it. The whole flow runs in a single DB
64
+ * transaction so a partial failure rolls back both sides.
65
+ */
66
+ async composeApprovalTemplateWithForm(input, currentMemberId) {
27
67
  return this.templateRepository.manager.transaction(async (manager) => {
28
- const templateRepository = manager.getRepository(approval_template_entity_1.ApprovalTemplateEntity);
29
- const versionRepository = manager.getRepository(approval_template_version_entity_1.ApprovalTemplateVersionEntity);
30
- const template = await templateRepository.save(templateRepository.create({
31
- category: input.category ?? category?.name ?? null,
32
- categoryId: category?.id ?? null,
33
- createdByMemberId: input.createdByMemberId,
34
- currentVersionId: null,
35
- description: input.description,
36
- name: input.name,
37
- }));
38
- await versionRepository.save(versionRepository.create({
39
- archivedAt: null,
40
- formDefinitionVersionId: input.formDefinitionVersionId,
41
- initiatorPolicyCel: null,
42
- notificationConfig: null,
43
- publishedAt: null,
44
- publishedByMemberId: null,
45
- slaDefaults: null,
68
+ const formDefinitionVersion = await this.resolveComposedFormVersion(manager, input, currentMemberId);
69
+ const templateDraftVersion = await this.resolveComposedTemplateDraftVersion(manager, input, currentMemberId);
70
+ let templateVersion = await this.updateApprovalTemplateDraft({
71
+ formDefinitionVersionId: formDefinitionVersion.id,
72
+ initiatorPolicyCel: input.initiatorPolicyCel,
73
+ notificationConfigJson: input.notificationConfigJson,
74
+ slaDefaultsJson: input.slaDefaultsJson,
75
+ versionId: templateDraftVersion.id,
76
+ workflowDefinitionJson: input.workflowDefinitionJson,
77
+ }, manager);
78
+ if (input.publish) {
79
+ templateVersion = await this.publishApprovalTemplateVersion(templateDraftVersion.id, currentMemberId ?? undefined, manager);
80
+ }
81
+ const formDefinition = await manager
82
+ .getRepository(form_definition_entity_1.FormDefinitionEntity)
83
+ .findOneByOrFail({ id: formDefinitionVersion.formDefinitionId });
84
+ const template = await manager
85
+ .getRepository(approval_template_entity_1.ApprovalTemplateEntity)
86
+ .findOneByOrFail({ id: templateVersion.templateId });
87
+ return {
88
+ formDefinition,
89
+ formDefinitionVersion,
90
+ published: input.publish,
91
+ template,
92
+ templateVersion,
93
+ };
94
+ });
95
+ }
96
+ async resolveComposedFormVersion(manager, input, currentMemberId) {
97
+ if (!input.formDefinitionId) {
98
+ const definition = await this.formService.createFormDefinition({
99
+ createdByMemberId: currentMemberId,
100
+ description: input.formDescription,
101
+ name: input.formName,
102
+ schemaJson: input.schemaJson,
103
+ uiSchemaJson: input.uiSchemaJson,
104
+ }, manager);
105
+ const draft = await this.formService.findDraftVersion(definition.id, manager);
106
+ if (!draft) {
107
+ throw new common_1.NotFoundException(`Form definition ${definition.id} draft version was not created`);
108
+ }
109
+ return input.publish
110
+ ? this.formService.publishFormDefinitionVersion(draft.id, currentMemberId ?? undefined, manager)
111
+ : draft;
112
+ }
113
+ const existingDraft = await this.formService.findDraftVersion(input.formDefinitionId, manager);
114
+ if (existingDraft) {
115
+ const updated = await this.formService.updateFormDefinitionDraft({
116
+ schemaJson: input.schemaJson ?? '',
117
+ uiSchemaJson: input.uiSchemaJson ?? '',
118
+ versionId: existingDraft.id,
119
+ }, manager);
120
+ return input.publish
121
+ ? this.formService.publishFormDefinitionVersion(updated.id, currentMemberId ?? undefined, manager)
122
+ : updated;
123
+ }
124
+ // Published definitions no longer keep a parallel draft: edits publish a
125
+ // new version immediately (content-identical saves reuse the current
126
+ // version) so the template draft can bind a published form version.
127
+ return this.formService.publishFormDefinitionContent({
128
+ formDefinitionId: input.formDefinitionId,
129
+ schemaJson: input.schemaJson,
130
+ uiSchemaJson: input.uiSchemaJson,
131
+ }, currentMemberId ?? undefined, manager);
132
+ }
133
+ async resolveComposedTemplateDraftVersion(manager, input, currentMemberId) {
134
+ if (!input.templateId) {
135
+ const template = await this.createApprovalTemplate({
136
+ category: input.category,
137
+ categoryId: input.categoryId,
138
+ createdByMemberId: currentMemberId,
139
+ description: input.templateDescription,
140
+ formDefinitionVersionId: null,
141
+ name: input.templateName,
142
+ }, manager);
143
+ const draft = await this.findDraftTemplateVersion(template.id, manager);
144
+ if (!draft) {
145
+ throw new common_1.NotFoundException(`Approval template ${template.id} draft version was not created`);
146
+ }
147
+ return draft;
148
+ }
149
+ return ((await this.findDraftTemplateVersion(input.templateId, manager)) ??
150
+ (await this.forkApprovalTemplate(input.templateId, manager)));
151
+ }
152
+ async findDraftTemplateVersion(templateId, manager) {
153
+ return this.templateVersions(manager).findOne({
154
+ where: {
46
155
  status: template_enums_1.ApprovalTemplateVersionStatusEnum.DRAFT,
47
- templateId: template.id,
48
- version: 1,
49
- workflowDefinition: workflow_definition_validator_1.EMPTY_WORKFLOW_DEFINITION,
50
- }));
51
- return template;
156
+ templateId,
157
+ },
52
158
  });
53
159
  }
54
160
  async updateApprovalTemplate(input) {
@@ -169,25 +275,27 @@ let TemplateService = class TemplateService {
169
275
  async getApprovalTemplateVersion(id) {
170
276
  return this.getTemplateVersionOrThrow(id);
171
277
  }
172
- async updateApprovalTemplateDraft(input) {
173
- const existing = await this.getTemplateVersionOrThrow(input.versionId);
278
+ async updateApprovalTemplateDraft(input, manager) {
279
+ const versionRepository = this.templateVersions(manager);
280
+ const existing = await this.getTemplateVersionOrThrow(input.versionId, manager);
174
281
  if (existing.status !== template_enums_1.ApprovalTemplateVersionStatusEnum.DRAFT) {
175
282
  throw new common_1.ConflictException('Only draft approval template versions can be updated');
176
283
  }
177
- await this.validateOptionalFormDefinitionVersion(input.formDefinitionVersionId);
284
+ await this.validateOptionalFormDefinitionVersion(input.formDefinitionVersionId, manager);
178
285
  const workflowDefinition = this.parseWorkflowDefinitionOrThrow(input.workflowDefinitionJson);
179
- const next = this.templateVersionRepository.merge(existing, {
286
+ const next = versionRepository.merge(existing, {
180
287
  formDefinitionVersionId: input.formDefinitionVersionId,
181
288
  initiatorPolicyCel: input.initiatorPolicyCel,
182
289
  notificationConfig: parseOptionalJsonObject(input.notificationConfigJson),
183
290
  slaDefaults: parseOptionalJsonObject(input.slaDefaultsJson),
184
291
  workflowDefinition,
185
292
  });
186
- return this.templateVersionRepository.save(next);
293
+ return versionRepository.save(next);
187
294
  }
188
- async forkApprovalTemplate(templateId) {
189
- const template = await this.getTemplateOrThrow(templateId);
190
- const existingDraft = await this.templateVersionRepository.findOne({
295
+ async forkApprovalTemplate(templateId, manager) {
296
+ const versionRepository = this.templateVersions(manager);
297
+ const template = await this.getTemplateOrThrow(templateId, manager);
298
+ const existingDraft = await versionRepository.findOne({
191
299
  where: {
192
300
  status: template_enums_1.ApprovalTemplateVersionStatusEnum.DRAFT,
193
301
  templateId: template.id,
@@ -197,10 +305,10 @@ let TemplateService = class TemplateService {
197
305
  throw new common_1.ConflictException('A draft approval template version already exists');
198
306
  }
199
307
  const source = template.currentVersionId
200
- ? await this.getTemplateVersionOrThrow(template.currentVersionId)
308
+ ? await this.getTemplateVersionOrThrow(template.currentVersionId, manager)
201
309
  : null;
202
- const nextVersion = await this.readNextVersionNumber(template.id);
203
- return this.templateVersionRepository.save(this.templateVersionRepository.create({
310
+ const nextVersion = await this.readNextVersionNumber(template.id, manager);
311
+ return versionRepository.save(versionRepository.create({
204
312
  archivedAt: null,
205
313
  formDefinitionVersionId: source?.formDefinitionVersionId ?? null,
206
314
  initiatorPolicyCel: source?.initiatorPolicyCel ?? null,
@@ -214,39 +322,43 @@ let TemplateService = class TemplateService {
214
322
  workflowDefinition: source?.workflowDefinition ?? workflow_definition_validator_1.EMPTY_WORKFLOW_DEFINITION,
215
323
  }));
216
324
  }
217
- async publishApprovalTemplateVersion(versionId, publishedByMemberId) {
218
- const version = await this.getTemplateVersionOrThrow(versionId);
325
+ async publishApprovalTemplateVersion(versionId, publishedByMemberId, manager) {
326
+ const version = await this.getTemplateVersionOrThrow(versionId, manager);
219
327
  if (version.status !== template_enums_1.ApprovalTemplateVersionStatusEnum.DRAFT) {
220
328
  throw new common_1.ConflictException('Only draft approval template versions can be published');
221
329
  }
222
- await this.validatePublishableVersion(version);
223
- return this.templateRepository.manager.transaction(async (manager) => {
224
- const templateRepository = manager.getRepository(approval_template_entity_1.ApprovalTemplateEntity);
225
- const versionRepository = manager.getRepository(approval_template_version_entity_1.ApprovalTemplateVersionEntity);
226
- const template = await templateRepository.findOne({
227
- where: { deletedAt: (0, typeorm_2.IsNull)(), id: version.templateId },
228
- });
229
- if (!template) {
230
- throw new common_1.NotFoundException(`Approval template ${version.templateId} was not found`);
231
- }
232
- if (template.currentVersionId) {
233
- await versionRepository.update({ id: template.currentVersionId }, {
234
- archivedAt: new Date(),
235
- status: template_enums_1.ApprovalTemplateVersionStatusEnum.ARCHIVED,
236
- });
237
- }
238
- const published = versionRepository.merge(version, {
239
- archivedAt: null,
240
- publishedAt: new Date(),
241
- publishedByMemberId: publishedByMemberId ?? null,
242
- status: template_enums_1.ApprovalTemplateVersionStatusEnum.PUBLISHED,
330
+ await this.validatePublishableVersion(version, manager);
331
+ const run = (txManager) => this.publishApprovalTemplateVersionWithManager(txManager, version, publishedByMemberId);
332
+ return manager
333
+ ? run(manager)
334
+ : this.templateRepository.manager.transaction(run);
335
+ }
336
+ async publishApprovalTemplateVersionWithManager(manager, version, publishedByMemberId) {
337
+ const templateRepository = manager.getRepository(approval_template_entity_1.ApprovalTemplateEntity);
338
+ const versionRepository = manager.getRepository(approval_template_version_entity_1.ApprovalTemplateVersionEntity);
339
+ const template = await templateRepository.findOne({
340
+ where: { deletedAt: (0, typeorm_2.IsNull)(), id: version.templateId },
341
+ });
342
+ if (!template) {
343
+ throw new common_1.NotFoundException(`Approval template ${version.templateId} was not found`);
344
+ }
345
+ if (template.currentVersionId) {
346
+ await versionRepository.update({ id: template.currentVersionId }, {
347
+ archivedAt: new Date(),
348
+ status: template_enums_1.ApprovalTemplateVersionStatusEnum.ARCHIVED,
243
349
  });
244
- const saved = await versionRepository.save(published);
245
- await templateRepository.save(templateRepository.merge(template, {
246
- currentVersionId: saved.id,
247
- }));
248
- return saved;
350
+ }
351
+ const published = versionRepository.merge(version, {
352
+ archivedAt: null,
353
+ publishedAt: new Date(),
354
+ publishedByMemberId: publishedByMemberId ?? null,
355
+ status: template_enums_1.ApprovalTemplateVersionStatusEnum.PUBLISHED,
249
356
  });
357
+ const saved = await versionRepository.save(published);
358
+ await templateRepository.save(templateRepository.merge(template, {
359
+ currentVersionId: saved.id,
360
+ }));
361
+ return saved;
250
362
  }
251
363
  async rollbackApprovalTemplateVersion(versionId) {
252
364
  const target = await this.getTemplateVersionOrThrow(versionId);
@@ -280,11 +392,11 @@ let TemplateService = class TemplateService {
280
392
  return saved;
281
393
  });
282
394
  }
283
- async validatePublishableVersion(version) {
395
+ async validatePublishableVersion(version, manager) {
284
396
  if (!version.formDefinitionVersionId) {
285
397
  throw new common_1.BadRequestException('Approval template version must bind a form definition version before publishing');
286
398
  }
287
- const formVersion = await this.formDefinitionVersionRepository.findOne({
399
+ const formVersion = await this.formVersions(manager).findOne({
288
400
  where: { id: version.formDefinitionVersionId },
289
401
  });
290
402
  if (!formVersion) {
@@ -309,25 +421,45 @@ let TemplateService = class TemplateService {
309
421
  throw new common_1.BadRequestException(errors.join('; '));
310
422
  }
311
423
  }
312
- async validateOptionalFormDefinitionVersion(formDefinitionVersionId) {
424
+ async validateOptionalFormDefinitionVersion(formDefinitionVersionId, manager) {
313
425
  if (!formDefinitionVersionId) {
314
426
  return;
315
427
  }
316
- const formVersion = await this.formDefinitionVersionRepository.findOne({
428
+ const formVersion = await this.formVersions(manager).findOne({
317
429
  where: { id: formDefinitionVersionId },
318
430
  });
319
431
  if (!formVersion) {
320
432
  throw new common_1.NotFoundException(`Form definition version ${formDefinitionVersionId} was not found`);
321
433
  }
322
434
  }
323
- async validateOptionalTemplateCategory(categoryId) {
435
+ async validateOptionalTemplateCategory(categoryId, manager) {
324
436
  if (!categoryId) {
325
437
  return null;
326
438
  }
327
- return this.getTemplateCategoryOrThrow(categoryId);
328
- }
329
- async getTemplateOrThrow(id) {
330
- const entity = await this.templateRepository.findOne({
439
+ return this.getTemplateCategoryOrThrow(categoryId, manager);
440
+ }
441
+ templates(manager) {
442
+ return manager
443
+ ? manager.getRepository(approval_template_entity_1.ApprovalTemplateEntity)
444
+ : this.templateRepository;
445
+ }
446
+ templateVersions(manager) {
447
+ return manager
448
+ ? manager.getRepository(approval_template_version_entity_1.ApprovalTemplateVersionEntity)
449
+ : this.templateVersionRepository;
450
+ }
451
+ templateCategories(manager) {
452
+ return manager
453
+ ? manager.getRepository(approval_template_category_entity_1.ApprovalTemplateCategoryEntity)
454
+ : this.templateCategoryRepository;
455
+ }
456
+ formVersions(manager) {
457
+ return manager
458
+ ? manager.getRepository(form_definition_version_entity_1.FormDefinitionVersionEntity)
459
+ : this.formDefinitionVersionRepository;
460
+ }
461
+ async getTemplateOrThrow(id, manager) {
462
+ const entity = await this.templates(manager).findOne({
331
463
  relations: { categoryDetail: true },
332
464
  where: { deletedAt: (0, typeorm_2.IsNull)(), id },
333
465
  });
@@ -336,8 +468,8 @@ let TemplateService = class TemplateService {
336
468
  }
337
469
  return entity;
338
470
  }
339
- async getTemplateCategoryOrThrow(id) {
340
- const entity = await this.templateCategoryRepository.findOne({
471
+ async getTemplateCategoryOrThrow(id, manager) {
472
+ const entity = await this.templateCategories(manager).findOne({
341
473
  where: { id },
342
474
  });
343
475
  if (!entity) {
@@ -351,8 +483,8 @@ let TemplateService = class TemplateService {
351
483
  isActive,
352
484
  }));
353
485
  }
354
- async getTemplateVersionOrThrow(id) {
355
- const entity = await this.templateVersionRepository.findOne({
486
+ async getTemplateVersionOrThrow(id, manager) {
487
+ const entity = await this.templateVersions(manager).findOne({
356
488
  where: { id },
357
489
  });
358
490
  if (!entity) {
@@ -360,8 +492,8 @@ let TemplateService = class TemplateService {
360
492
  }
361
493
  return entity;
362
494
  }
363
- async readNextVersionNumber(templateId) {
364
- const row = await this.templateVersionRepository
495
+ async readNextVersionNumber(templateId, manager) {
496
+ const row = await this.templateVersions(manager)
365
497
  .createQueryBuilder('version')
366
498
  .select('MAX(version.version)', 'maxVersion')
367
499
  .where('version.template_id = :templateId', { templateId })
@@ -391,7 +523,8 @@ exports.TemplateService = TemplateService = tslib_1.__decorate([
391
523
  typeorm_2.Repository,
392
524
  typeorm_2.Repository,
393
525
  typeorm_2.Repository,
394
- condition_service_1.ConditionService])
526
+ condition_service_1.ConditionService,
527
+ form_service_1.FormService])
395
528
  ], TemplateService);
396
529
  function parseOptionalJsonObject(value) {
397
530
  if (!value) {