@tstdl/base 0.92.142 → 0.92.143

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 (223) hide show
  1. package/ai/ai-file.service.js +1 -1
  2. package/ai/ai.service.js +3 -3
  3. package/ai/types.d.ts +1 -1
  4. package/api/client/client.d.ts +1 -1
  5. package/api/client/client.js +10 -4
  6. package/api/server/middlewares/content-type.middleware.js +8 -7
  7. package/api/types.js +1 -1
  8. package/authentication/client/authentication.service.js +3 -3
  9. package/authentication/server/authentication-ancillary.service.d.ts +11 -1
  10. package/authentication/server/authentication-ancillary.service.js +1 -1
  11. package/authentication/server/authentication-secret-requirements.validator.js +1 -1
  12. package/authentication/server/authentication.api-controller.js +22 -10
  13. package/authentication/server/authentication.service.d.ts +11 -5
  14. package/authentication/server/authentication.service.js +97 -49
  15. package/authentication/server/drizzle.config.js +2 -2
  16. package/authentication/server/module.js +1 -1
  17. package/cancellation/token.d.ts +2 -2
  18. package/cancellation/token.js +4 -4
  19. package/cookie/cookie.js +2 -2
  20. package/document-management/api/document-management.api.d.ts +122 -24
  21. package/document-management/api/document-management.api.js +17 -0
  22. package/document-management/{server/services → authorization}/document-management-authorization.service.d.ts +7 -7
  23. package/document-management/authorization/document-management-authorization.service.js +2 -0
  24. package/document-management/authorization/index.d.ts +2 -0
  25. package/document-management/authorization/index.js +2 -0
  26. package/document-management/authorization/policies.d.ts +38 -0
  27. package/document-management/authorization/policies.js +2 -0
  28. package/document-management/index.d.ts +1 -0
  29. package/document-management/index.js +1 -0
  30. package/document-management/models/document-assignment-scope.model.d.ts +1 -0
  31. package/document-management/models/document-assignment-scope.model.js +10 -3
  32. package/document-management/models/document-assignment-task.model.d.ts +1 -0
  33. package/document-management/models/document-assignment-task.model.js +8 -2
  34. package/document-management/models/document-category.model.d.ts +1 -0
  35. package/document-management/models/document-category.model.js +7 -1
  36. package/document-management/models/document-collection-assignment.model.d.ts +1 -0
  37. package/document-management/models/document-collection-assignment.model.js +12 -4
  38. package/document-management/models/document-collection.model.d.ts +2 -0
  39. package/document-management/models/document-collection.model.js +8 -2
  40. package/document-management/models/document-management-table.d.ts +3 -1
  41. package/document-management/models/document-management-table.js +2 -2
  42. package/document-management/models/document-property-value.model.d.ts +1 -0
  43. package/document-management/models/document-property-value.model.js +9 -3
  44. package/document-management/models/document-property.model.d.ts +1 -0
  45. package/document-management/models/document-property.model.js +8 -2
  46. package/document-management/models/document-request-collection-assignment.model.d.ts +1 -0
  47. package/document-management/models/document-request-collection-assignment.model.js +12 -4
  48. package/document-management/models/document-request-template.d.ts +1 -0
  49. package/document-management/models/document-request-template.js +6 -1
  50. package/document-management/models/document-request.model.d.ts +1 -0
  51. package/document-management/models/document-request.model.js +10 -1
  52. package/document-management/models/document-requests-template.d.ts +1 -0
  53. package/document-management/models/document-requests-template.js +7 -3
  54. package/document-management/models/document-tag-assignment.model.d.ts +8 -0
  55. package/document-management/models/document-tag-assignment.model.js +40 -0
  56. package/document-management/models/document-tag.model.d.ts +6 -0
  57. package/document-management/models/{document-request-submission.model.js → document-tag.model.js} +14 -18
  58. package/document-management/models/document-type-property.model.d.ts +1 -0
  59. package/document-management/models/document-type-property.model.js +7 -2
  60. package/document-management/models/document-type-validation.model.d.ts +1 -0
  61. package/document-management/models/document-type-validation.model.js +8 -2
  62. package/document-management/models/document-type.model.d.ts +1 -0
  63. package/document-management/models/document-type.model.js +7 -2
  64. package/document-management/models/document-validation-definition.model.d.ts +1 -0
  65. package/document-management/models/document-validation-definition.model.js +7 -2
  66. package/document-management/models/document-validation-execution-related-document.model.d.ts +1 -0
  67. package/document-management/models/document-validation-execution-related-document.model.js +10 -3
  68. package/document-management/models/document-validation-execution.model.d.ts +1 -0
  69. package/document-management/models/document-validation-execution.model.js +9 -3
  70. package/document-management/models/document-workflow.model.d.ts +4 -1
  71. package/document-management/models/document-workflow.model.js +16 -4
  72. package/document-management/models/document.model.d.ts +2 -2
  73. package/document-management/models/document.model.js +9 -8
  74. package/document-management/models/index.d.ts +2 -1
  75. package/document-management/models/index.js +2 -1
  76. package/document-management/server/api/document-management.api.d.ts +4 -1
  77. package/document-management/server/api/document-management.api.js +113 -22
  78. package/document-management/server/configure.d.ts +2 -2
  79. package/document-management/server/configure.js +7 -7
  80. package/document-management/server/drizzle/0000_parallel_mantis.sql +359 -0
  81. package/document-management/server/drizzle/meta/0000_snapshot.json +784 -260
  82. package/document-management/server/drizzle/meta/_journal.json +2 -2
  83. package/document-management/server/module.d.ts +2 -2
  84. package/document-management/server/module.js +2 -2
  85. package/document-management/server/schemas.d.ts +6 -5
  86. package/document-management/server/schemas.js +12 -11
  87. package/document-management/server/services/document-category-type.service.d.ts +19 -10
  88. package/document-management/server/services/document-category-type.service.js +34 -27
  89. package/document-management/server/services/document-collection.service.d.ts +13 -6
  90. package/document-management/server/services/document-collection.service.js +36 -12
  91. package/document-management/server/services/document-file.service.d.ts +8 -7
  92. package/document-management/server/services/document-file.service.js +28 -33
  93. package/document-management/server/services/document-management-ai.service.d.ts +5 -4
  94. package/document-management/server/services/document-management-ai.service.js +51 -28
  95. package/document-management/server/services/document-management-ancillary.service.d.ts +3 -21
  96. package/document-management/server/services/document-management-ancillary.service.js +0 -24
  97. package/document-management/server/services/document-management-observation.service.d.ts +15 -0
  98. package/document-management/server/services/document-management-observation.service.js +160 -0
  99. package/document-management/server/services/document-management.service.d.ts +6 -5
  100. package/document-management/server/services/document-management.service.js +112 -86
  101. package/document-management/server/services/document-property.service.d.ts +15 -7
  102. package/document-management/server/services/document-property.service.js +52 -20
  103. package/document-management/server/services/document-request.service.d.ts +13 -24
  104. package/document-management/server/services/document-request.service.js +39 -62
  105. package/document-management/server/services/document-tag.service.d.ts +10 -0
  106. package/document-management/server/services/document-tag.service.js +59 -0
  107. package/document-management/server/services/document-validation.service.d.ts +8 -8
  108. package/document-management/server/services/document-validation.service.js +41 -40
  109. package/document-management/server/services/document-workflow.service.d.ts +6 -5
  110. package/document-management/server/services/document-workflow.service.js +54 -43
  111. package/document-management/server/services/document.service.d.ts +12 -11
  112. package/document-management/server/services/document.service.js +64 -40
  113. package/document-management/server/services/index.d.ts +2 -1
  114. package/document-management/server/services/index.js +2 -1
  115. package/document-management/server/services/singleton.js +2 -2
  116. package/document-management/server/validators/ai-validation-executor.js +4 -4
  117. package/document-management/service-models/document-collection-metadata.service-model.d.ts +14 -0
  118. package/document-management/service-models/document-collection-metadata.service-model.js +1 -0
  119. package/document-management/service-models/document-folders.view-model.d.ts +1 -7
  120. package/document-management/service-models/document-folders.view-model.js +3 -15
  121. package/document-management/service-models/document-management.view-model.d.ts +20 -6
  122. package/document-management/service-models/document-management.view-model.js +62 -8
  123. package/document-management/service-models/document.service-model.d.ts +14 -11
  124. package/document-management/service-models/document.service-model.js +11 -2
  125. package/document-management/service-models/enriched/enriched-document-assignment.view.d.ts +1 -1
  126. package/document-management/service-models/enriched/enriched-document-assignment.view.js +0 -2
  127. package/document-management/service-models/enriched/enriched-document-category.view.d.ts +11 -1
  128. package/document-management/service-models/enriched/enriched-document-category.view.js +44 -1
  129. package/document-management/service-models/enriched/enriched-document-collection.view.d.ts +4 -2
  130. package/document-management/service-models/enriched/enriched-document-collection.view.js +13 -3
  131. package/document-management/service-models/enriched/enriched-document-management-data.view.d.ts +2 -0
  132. package/document-management/service-models/enriched/enriched-document-management-data.view.js +4 -2
  133. package/document-management/service-models/enriched/enriched-document-request.view.d.ts +1 -0
  134. package/document-management/service-models/enriched/enriched-document-request.view.js +2 -0
  135. package/document-management/service-models/enriched/enriched-document-type.view.d.ts +9 -1
  136. package/document-management/service-models/enriched/enriched-document-type.view.js +28 -1
  137. package/document-management/service-models/enriched/enriched-document.view.d.ts +7 -6
  138. package/document-management/service-models/enriched/enriched-document.view.js +29 -6
  139. package/document-management/service-models/{normalized-requests-template-data.model.d.ts → enriched/enriched-requests-template-data.model.d.ts} +6 -6
  140. package/document-management/service-models/{normalized-requests-template-data.model.js → enriched/enriched-requests-template-data.model.js} +1 -1
  141. package/document-management/service-models/enriched/index.d.ts +1 -0
  142. package/document-management/service-models/enriched/index.js +1 -0
  143. package/document-management/service-models/index.d.ts +2 -2
  144. package/document-management/service-models/index.js +2 -2
  145. package/examples/document-management/categories-and-types.d.ts +33 -31
  146. package/examples/document-management/categories-and-types.js +33 -0
  147. package/examples/document-management/main.d.ts +5 -4
  148. package/examples/document-management/main.js +13 -7
  149. package/function/log.js +2 -2
  150. package/http/server/node/module.d.ts +4 -1
  151. package/http/server/node/module.js +10 -1
  152. package/http/server/node/node-http-server.d.ts +3 -6
  153. package/http/server/node/node-http-server.js +68 -67
  154. package/injector/inject.js +6 -6
  155. package/injector/injector.js +3 -3
  156. package/jsx/is-component-class.js +1 -1
  157. package/key-value-store/key-value.store.d.ts +38 -7
  158. package/key-value-store/key-value.store.js +2 -1
  159. package/key-value-store/mongo/mongo-key-value.store.d.ts +1 -0
  160. package/key-value-store/mongo/mongo-key-value.store.js +14 -5
  161. package/key-value-store/postgres/drizzle/0000_shocking_slipstream.sql +12 -0
  162. package/key-value-store/postgres/drizzle/meta/0000_snapshot.json +97 -0
  163. package/key-value-store/postgres/drizzle/meta/_journal.json +13 -0
  164. package/key-value-store/postgres/drizzle.config.d.ts +2 -0
  165. package/key-value-store/postgres/drizzle.config.js +11 -0
  166. package/key-value-store/postgres/index.d.ts +2 -0
  167. package/key-value-store/postgres/index.js +2 -0
  168. package/key-value-store/postgres/key-value-store.service.d.ts +17 -0
  169. package/key-value-store/postgres/key-value-store.service.js +65 -0
  170. package/key-value-store/postgres/models/index.d.ts +2 -0
  171. package/key-value-store/postgres/models/index.js +2 -0
  172. package/key-value-store/postgres/models/key-value.model.d.ts +7 -0
  173. package/key-value-store/postgres/models/key-value.model.js +35 -0
  174. package/key-value-store/postgres/models/schemas.d.ts +3 -0
  175. package/key-value-store/postgres/models/schemas.js +4 -0
  176. package/key-value-store/postgres/module.d.ts +6 -0
  177. package/key-value-store/postgres/module.js +23 -0
  178. package/lock/web/web-lock.d.ts +0 -1
  179. package/lock/web/web-lock.js +6 -13
  180. package/orm/data-types/timestamp.js +1 -1
  181. package/orm/decorators.d.ts +37 -29
  182. package/orm/decorators.js +44 -24
  183. package/orm/entity.d.ts +1 -0
  184. package/orm/query.d.ts +10 -2
  185. package/orm/repository.types.d.ts +2 -1
  186. package/orm/schemas/json.d.ts +12 -6
  187. package/orm/schemas/json.js +12 -5
  188. package/orm/server/database.js +5 -2
  189. package/orm/server/drizzle/schema-converter.js +40 -11
  190. package/orm/server/query-converter.d.ts +2 -1
  191. package/orm/server/query-converter.js +57 -34
  192. package/orm/server/repository.d.ts +26 -43
  193. package/orm/server/repository.js +106 -39
  194. package/orm/server/transaction.d.ts +2 -1
  195. package/orm/server/transaction.js +3 -0
  196. package/orm/server/transactional.d.ts +5 -1
  197. package/orm/server/transactional.js +34 -4
  198. package/package.json +14 -11
  199. package/process/spawn.js +0 -1
  200. package/promise/deferred-promise.d.ts +4 -3
  201. package/promise/deferred-promise.js +13 -5
  202. package/queue/postgres/queue.js +8 -8
  203. package/reflection/utils.js +3 -3
  204. package/schema/decorators/class.js +0 -1
  205. package/schema/decorators/schema.js +1 -1
  206. package/schema/schemas/boolean.d.ts +1 -1
  207. package/schema/schemas/boolean.js +2 -2
  208. package/schema/schemas/number.js +3 -3
  209. package/schema/schemas/object.js +5 -6
  210. package/sse/server-sent-events-source.js +4 -1
  211. package/utils/compression.js +9 -9
  212. package/utils/date-time.d.ts +1 -0
  213. package/utils/date-time.js +18 -4
  214. package/utils/equals.d.ts +7 -0
  215. package/utils/equals.js +17 -2
  216. package/utils/function/memoize.js +10 -2
  217. package/utils/jwt.js +3 -3
  218. package/utils/object/property-name.d.ts +2 -2
  219. package/utils/timing.d.ts +2 -2
  220. package/utils/timing.js +12 -12
  221. package/document-management/models/document-request-submission.model.d.ts +0 -7
  222. package/document-management/server/drizzle/0000_moaning_luckman.sql +0 -305
  223. package/document-management/server/services/document-management-authorization.service.js +0 -28
@@ -4,25 +4,27 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { count, isNotNull as dbIsNotNull, isNull as dbIsNull, eq, inArray, sql } from 'drizzle-orm';
7
+ import { and, count, isNotNull as dbIsNotNull, isNull as dbIsNull, eq, inArray, sql } from 'drizzle-orm';
8
8
  import { BadRequestError } from '../../../errors/index.js';
9
+ import { inject } from '../../../injector/inject.js';
9
10
  import { Transactional, injectRepository } from '../../../orm/server/index.js';
10
11
  import { toArray } from '../../../utils/array/index.js';
11
12
  import { assertDefinedPass, isNotNull } from '../../../utils/type-guards.js';
12
13
  import { DocumentApproval, DocumentCollectionAssignment, DocumentRequest, DocumentRequestCollectionAssignment, DocumentRequestState, DocumentRequestTemplate, DocumentRequestsTemplate } from '../../models/index.js';
13
14
  import { document, documentRequest, documentRequestCollectionAssignment } from '../schemas.js';
15
+ import { DocumentManagementObservationService } from './document-management-observation.service.js';
14
16
  import { DocumentManagementSingleton } from './singleton.js';
15
17
  let DocumentRequestService = class DocumentRequestService extends Transactional {
16
18
  #documentRequestCollectionAssignmentRepository = injectRepository(DocumentRequestCollectionAssignment);
17
19
  #documentRequestRepository = injectRepository(DocumentRequest);
18
20
  #documentRequestTemplateRepository = injectRepository(DocumentRequestTemplate);
19
21
  #documentRequestsTemplateRepository = injectRepository(DocumentRequestsTemplate);
20
- #documentCollectionAssignmentRepository = injectRepository(DocumentCollectionAssignment);
21
- async getRequestStats(collectionIds) {
22
+ #observationService = inject(DocumentManagementObservationService);
23
+ async getRequestStats(tenantId, collectionIds) {
22
24
  const relevantRequests = this.session.$with('relevant_requests').as(this.session.selectDistinct({ id: documentRequest.id })
23
25
  .from(documentRequest)
24
26
  .innerJoin(documentRequestCollectionAssignment, eq(documentRequestCollectionAssignment.requestId, documentRequest.id))
25
- .where(inArray(documentRequestCollectionAssignment.collectionId, toArray(collectionIds))));
27
+ .where(and(eq(documentRequest.tenantId, tenantId), eq(documentRequestCollectionAssignment.tenantId, tenantId), inArray(documentRequestCollectionAssignment.collectionId, toArray(collectionIds)))));
26
28
  const [result] = await this.session.with(relevantRequests)
27
29
  .select({
28
30
  total: count(sql `${documentRequest.id})`),
@@ -37,98 +39,73 @@ let DocumentRequestService = class DocumentRequestService extends Transactional
37
39
  .where(inArray(documentRequest.id, this.session.select({ id: relevantRequests.id }).from(relevantRequests)));
38
40
  return assertDefinedPass(result);
39
41
  }
40
- async createRequestsTemplate(parameters) {
41
- return this.#documentRequestsTemplateRepository.insert(parameters);
42
+ async createRequestsTemplate(tenantId, parameters) {
43
+ return await this.#documentRequestsTemplateRepository.insert({ ...parameters, tenantId });
42
44
  }
43
- async updateRequestsTemplate(id, parameters) {
44
- return this.#documentRequestsTemplateRepository.update(id, parameters);
45
+ async updateRequestsTemplate(tenantId, id, parameters) {
46
+ return await this.#documentRequestsTemplateRepository.updateByQuery({ tenantId, id }, parameters);
45
47
  }
46
- async applyRequestsTemplate(id, collectionIds) {
47
- const requestTemplates = await this.#documentRequestTemplateRepository.loadManyByQuery({ requestsTemplateId: id });
48
+ async applyRequestsTemplate(tenantId, id, collectionIds) {
49
+ const requestTemplates = await this.#documentRequestTemplateRepository.loadManyByQuery({ tenantId: { $or: [null, tenantId] }, requestsTemplateId: id });
48
50
  await this.transaction(async (tx) => {
49
51
  for (const { typeId, comment } of requestTemplates) {
50
- await this.withTransaction(tx).createRequest(typeId, collectionIds, comment);
52
+ await this.withTransaction(tx).createRequest(tenantId, typeId, collectionIds, comment);
51
53
  }
52
54
  });
53
55
  }
54
- async deleteRequestsTemplate(id) {
55
- return this.#documentRequestsTemplateRepository.delete(id);
56
+ async deleteRequestsTemplate(tenantId, id) {
57
+ return await this.#documentRequestsTemplateRepository.deleteByQuery({ tenantId, id });
56
58
  }
57
- async createRequestTemplate(requestsTemplateId, typeId, comment) {
58
- return this.#documentRequestTemplateRepository.insert({ requestsTemplateId, typeId, comment });
59
+ async createRequestTemplate(tenantId, requestsTemplateId, typeId, comment) {
60
+ return await this.#documentRequestTemplateRepository.insert({ tenantId, requestsTemplateId, typeId, comment });
59
61
  }
60
- async updateRequestTemplate(id, parameters) {
61
- return this.#documentRequestTemplateRepository.update(id, parameters);
62
+ async updateRequestTemplate(tenantId, id, parameters) {
63
+ return await this.#documentRequestTemplateRepository.updateByQuery({ tenantId, id }, parameters);
62
64
  }
63
- async deleteRequestTemplate(id) {
64
- return this.#documentRequestTemplateRepository.delete(id);
65
+ async deleteRequestTemplate(tenantId, id) {
66
+ return await this.#documentRequestTemplateRepository.deleteByQuery({ tenantId, id });
65
67
  }
66
- async createRequest(typeId, collectionIds, comment) {
68
+ async createRequest(tenantId, typeId, collectionIds, comment) {
67
69
  if (collectionIds.length == 0) {
68
70
  throw new BadRequestError('No target collectionId specified.');
69
71
  }
70
- return this.transaction(async (tx) => {
71
- const request = await this.#documentRequestRepository.withTransaction(tx).insert({ typeId, documentId: null, comment, state: DocumentRequestState.Open });
72
- const newDocumentRequestCollectionAssignments = collectionIds.map((collectionId) => ({ requestId: request.id, collectionId }));
72
+ return await this.transaction(async (tx) => {
73
+ const request = await this.#documentRequestRepository.withTransaction(tx).insert({ tenantId, typeId, documentId: null, comment, state: DocumentRequestState.Open });
74
+ const newDocumentRequestCollectionAssignments = collectionIds.map((collectionId) => ({ tenantId, requestId: request.id, collectionId }));
73
75
  await this.#documentRequestCollectionAssignmentRepository.withTransaction(tx).insertMany(newDocumentRequestCollectionAssignments);
76
+ this.#observationService.collectionChange(collectionIds, tx);
74
77
  return request;
75
78
  });
76
79
  }
77
- async updateRequest(id, update) {
80
+ async updateRequest(tenantId, id, update) {
78
81
  await this.transaction(async (tx) => {
79
- const request = await this.#documentRequestRepository.withTransaction(tx).load(id);
82
+ const request = await this.#documentRequestRepository.withTransaction(tx).loadByQuery({ tenantId, id });
80
83
  if (isNotNull(request.documentId)) {
81
84
  throw new BadRequestError('Cannot update document requests which have an assigned document.');
82
85
  }
83
- await this.#documentRequestRepository.withTransaction(tx).update(id, update);
86
+ await this.#documentRequestRepository.withTransaction(tx).updateByQuery({ tenantId, id }, update);
87
+ this.#observationService.requestChange(id, tx);
84
88
  });
85
89
  }
86
- async deleteRequest(id) {
90
+ async deleteRequest(tenantId, id) {
87
91
  await this.transaction(async (tx) => {
88
- const request = await this.#documentRequestRepository.withTransaction(tx).load(id);
92
+ const request = await this.#documentRequestRepository.withTransaction(tx).loadByQuery({ tenantId, id });
89
93
  if (isNotNull(request.documentId)) {
90
94
  throw new BadRequestError('Cannot delete requests which have an assigned document.');
91
95
  }
92
- await this.#documentRequestCollectionAssignmentRepository.withTransaction(tx).deleteManyByQuery({ requestId: id });
93
- await this.#documentRequestRepository.withTransaction(tx).delete(id);
96
+ await this.#documentRequestCollectionAssignmentRepository.withTransaction(tx).deleteManyByQuery({ tenantId, requestId: id });
97
+ await this.#documentRequestRepository.withTransaction(tx).deleteByQuery({ tenantId, id });
98
+ this.#observationService.requestChange(id, tx);
94
99
  });
95
100
  }
96
- async assignDocument(requestId, documentId) {
101
+ async assignDocument(document, requestId) {
97
102
  await this.transaction(async (tx) => {
98
- const request = await this.#documentRequestRepository.withTransaction(tx).load(requestId);
103
+ const request = await this.#documentRequestRepository.withTransaction(tx).loadByQuery({ tenantId: document.tenantId, id: requestId });
99
104
  if (isNotNull(request.documentId)) {
100
105
  throw new BadRequestError('Document request already has a document assigned.');
101
106
  }
102
- await this.#documentRequestRepository.withTransaction(tx).update(requestId, { documentId });
103
- });
104
- }
105
- /**
106
- * Fulfills a document request.
107
- * Marks the request as fulfilled and creates associations between the document
108
- * and the target collections defined in the request.
109
- *
110
- * @param requestId The ID of the DocumentRequest to fulfill.
111
- * @param documentId The ID of the Document fulfilling the request.
112
- * @param userId The ID of the user performing the action (for audit purposes).
113
- * @throws NotFoundError if the DocumentRequest with the given ID does not exist.
114
- */
115
- async fulfillRequest(requestId, documentId) {
116
- await this.transaction(async (tx) => {
117
- const request = await this.#documentRequestRepository.withTransaction(tx).load(requestId);
118
- if (request.state == DocumentRequestState.Fulfilled) {
119
- throw new BadRequestError('Document request is already fulfilled.');
120
- }
121
- const targetCollectionIds = await this.#documentRequestCollectionAssignmentRepository.withTransaction(tx).loadManyByQuery({ requestId });
122
- if (targetCollectionIds.length == 0) {
123
- throw new Error('No document request collection for document request found.');
124
- }
125
- const links = targetCollectionIds.map((target) => ({
126
- collectionId: target.collectionId,
127
- documentId,
128
- archiveTimestamp: null,
129
- }));
130
- await this.#documentCollectionAssignmentRepository.withTransaction(tx).insertMany(links);
131
- await this.#documentRequestRepository.withTransaction(tx).update(requestId, { state: DocumentRequestState.Fulfilled });
107
+ await this.#documentRequestRepository.withTransaction(tx).updateByQuery({ tenantId: document.tenantId, id: requestId }, { documentId: document.id });
108
+ this.#observationService.requestChange(requestId, tx);
132
109
  });
133
110
  }
134
111
  };
@@ -0,0 +1,10 @@
1
+ import { Transactional } from '../../../orm/server/index.js';
2
+ import { DocumentTag, DocumentTagAssignment, type Document } from '../../models/index.js';
3
+ export declare class DocumentTagService extends Transactional {
4
+ readonly tagRepository: import("../../../orm/server/index.js").EntityRepository<DocumentTag>;
5
+ readonly tagAssignmentRepository: import("../../../orm/server/index.js").EntityRepository<DocumentTagAssignment>;
6
+ loadTags(tenantId: string | null): Promise<DocumentTag[]>;
7
+ loadOrCreate(tenantId: string, labels: string[]): Promise<DocumentTag[]>;
8
+ loadDocumentTags(tenantId: string, documentId: string): Promise<DocumentTag[]>;
9
+ assignTags(document: Document, labels: string[]): Promise<void>;
10
+ }
@@ -0,0 +1,59 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { getEntityIds } from '../../../orm/index.js';
8
+ import { injectRepository, Transactional } from '../../../orm/server/index.js';
9
+ import { and, eq } from 'drizzle-orm';
10
+ import { DocumentTag, DocumentTagAssignment } from '../../models/index.js';
11
+ import { documentTag, documentTagAssignment } from '../schemas.js';
12
+ import { DocumentManagementSingleton } from './singleton.js';
13
+ let DocumentTagService = class DocumentTagService extends Transactional {
14
+ tagRepository = injectRepository(DocumentTag);
15
+ tagAssignmentRepository = injectRepository(DocumentTagAssignment);
16
+ async loadTags(tenantId) {
17
+ return await this.tagRepository.loadManyByQuery({ tenantId: { $or: [null, tenantId] } }, { order: { label: 'asc' } });
18
+ }
19
+ async loadOrCreate(tenantId, labels) {
20
+ if (labels.length === 0) {
21
+ return [];
22
+ }
23
+ return await this.tagRepository.transaction(async (tx) => {
24
+ const existingTags = await this.tagRepository.withTransaction(tx).loadManyByQuery({
25
+ tenantId: { $or: [null, tenantId] },
26
+ label: { $in: labels },
27
+ });
28
+ const newLabels = labels.filter((label) => !existingTags.some((tag) => tag.label == label));
29
+ const newTags = newLabels.map((label) => ({
30
+ tenantId,
31
+ label,
32
+ }));
33
+ const insertedTags = await this.tagRepository.withTransaction(tx).insertMany(newTags);
34
+ return [...existingTags, ...insertedTags];
35
+ });
36
+ }
37
+ async loadDocumentTags(tenantId, documentId) {
38
+ const result = await this.tagAssignmentRepository.session
39
+ .select({ tag: documentTag })
40
+ .from(documentTagAssignment)
41
+ .innerJoin(documentTag, eq(documentTag.id, documentTagAssignment.tagId))
42
+ .where(and(eq(documentTagAssignment.tenantId, tenantId), eq(documentTagAssignment.documentId, documentId)));
43
+ const tags = result.map((row) => row.tag);
44
+ return await this.tagRepository.mapManyToEntity(tags);
45
+ }
46
+ async assignTags(document, labels) {
47
+ await this.tagAssignmentRepository.transaction(async (tx) => {
48
+ const tags = await this.withTransaction(tx).loadOrCreate(document.tenantId, labels);
49
+ const tagIds = getEntityIds(tags);
50
+ const newAssignments = tagIds.map((tagId) => ({ tenantId: document.tenantId, documentId: document.id, tagId }));
51
+ await this.tagAssignmentRepository.withTransaction(tx).insertManyIfNotExists(['documentId', 'tagId'], newAssignments);
52
+ await this.tagAssignmentRepository.withTransaction(tx).hardDeleteManyByQuery({ tenantId: document.tenantId, documentId: document.id, tagId: { $nin: tagIds } });
53
+ });
54
+ }
55
+ };
56
+ DocumentTagService = __decorate([
57
+ DocumentManagementSingleton()
58
+ ], DocumentTagService);
59
+ export { DocumentTagService };
@@ -8,13 +8,13 @@ export declare class DocumentValidationService {
8
8
  #private;
9
9
  [afterResolve](_: unknown, { cancellationSignal }: AfterResolveContext<any>): void;
10
10
  processQueue(cancellationSignal: CancellationSignal): void;
11
- startValidationWorkflow(documentId: string): Promise<void>;
12
- setExecutionRunning(executionId: string): Promise<void>;
13
- setExecutionCompleted(executionId: string, status: DocumentValidationResultStatus, message: string | null): Promise<void>;
14
- setExecutionError(executionId: string, reason: string | null): Promise<void>;
15
- loadRelatedDocument(executionId: string, documentId: string): Promise<DocumentValidationExecutorContextDocumentData>;
16
- loadDocumentData(documentId: string): Promise<DocumentValidationExecutorContextDocumentData>;
17
- protected loadDocumentValidationExecutorContext(executionId: string): Promise<DocumentValidationExecutorContext>;
18
- processValidationExecution(executionId: string): Promise<void>;
11
+ startValidationWorkflow(tenantId: string, documentId: string): Promise<void>;
12
+ setExecutionRunning(tenantId: string, executionId: string): Promise<void>;
13
+ setExecutionCompleted(tenantId: string, executionId: string, status: DocumentValidationResultStatus, message: string | null): Promise<void>;
14
+ setExecutionError(tenantId: string, executionId: string, reason: string | null): Promise<void>;
15
+ loadRelatedDocument(tenantId: string, executionId: string, documentId: string): Promise<DocumentValidationExecutorContextDocumentData>;
16
+ loadDocumentData(tenantId: string, documentId: string): Promise<DocumentValidationExecutorContextDocumentData>;
17
+ protected loadDocumentValidationExecutorContext(tenantId: string, executionId: string): Promise<DocumentValidationExecutorContext>;
18
+ processValidationExecution(tenantId: string, executionId: string): Promise<void>;
19
19
  }
20
20
  export declare function registerDocumentValidationExecutor(...executors: Type<DocumentValidationExecutor>[]): void;
@@ -47,19 +47,20 @@ let DocumentValidationService = DocumentValidationService_1 = class DocumentVali
47
47
  processQueue(cancellationSignal) {
48
48
  this.#queue.process({ concurrency: 5, cancellationSignal }, async (job) => {
49
49
  this.#logger.verbose(`Processing validation execution "${job.data.executionId}"`);
50
- await this.processValidationExecution(job.data.executionId);
50
+ await this.processValidationExecution(job.data.tenantId, job.data.executionId);
51
51
  }, this.#logger);
52
52
  }
53
- async startValidationWorkflow(documentId) {
54
- const document = await this.#documentService.load(documentId);
53
+ async startValidationWorkflow(tenantId, documentId) {
54
+ const document = await this.#documentService.loadByQuery({ tenantId, id: documentId });
55
55
  if (isNull(document.typeId)) {
56
56
  throw new BadRequestError('Document has no type');
57
57
  }
58
- const workflow = await this.#documentWorkflowService.initiateWorkflow(documentId, DocumentWorkflowStep.Validation);
59
- const typeValidations = await this.#documentTypeValidationService.loadManyByQuery({ typeId: document.typeId });
58
+ const workflow = await this.#documentWorkflowService.initiateWorkflow(document.tenantId, documentId, DocumentWorkflowStep.Validation);
59
+ const typeValidations = await this.#documentTypeValidationService.loadManyByQuery({ tenantId: { $or: [null, tenantId] }, typeId: document.typeId });
60
60
  for (const typeValidation of typeValidations) {
61
- const validationDefinition = await this.#validationDefinitionService.load(typeValidation.validationId);
61
+ const validationDefinition = await this.#validationDefinitionService.loadByQuery({ tenantId: { $or: [null, tenantId] }, id: typeValidation.validationId });
62
62
  const execution = await this.#validationExecutionService.insert({
63
+ tenantId: document.tenantId,
63
64
  definitionId: validationDefinition.id,
64
65
  workflowId: workflow.id,
65
66
  state: DocumentValidationExecutionState.Pending,
@@ -68,42 +69,42 @@ let DocumentValidationService = DocumentValidationService_1 = class DocumentVali
68
69
  startedAt: null,
69
70
  completedAt: null,
70
71
  });
71
- await this.#queue.enqueue({ executionId: execution.id });
72
+ await this.#queue.enqueue({ tenantId, executionId: execution.id });
72
73
  }
73
74
  }
74
- async setExecutionRunning(executionId) {
75
- await this.#validationExecutionService.update(executionId, { state: DocumentValidationExecutionState.Running, resultStatus: null, resultMessage: null, startedAt: currentTimestamp(), completedAt: null });
75
+ async setExecutionRunning(tenantId, executionId) {
76
+ await this.#validationExecutionService.updateByQuery({ tenantId, executionId }, { state: DocumentValidationExecutionState.Running, resultStatus: null, resultMessage: null, startedAt: currentTimestamp(), completedAt: null });
76
77
  }
77
- async setExecutionCompleted(executionId, status, message) {
78
- await this.#validationExecutionService.update(executionId, { state: DocumentValidationExecutionState.Completed, resultStatus: status, resultMessage: message, completedAt: currentTimestamp() });
78
+ async setExecutionCompleted(tenantId, executionId, status, message) {
79
+ await this.#validationExecutionService.updateByQuery({ tenantId, executionId }, { state: DocumentValidationExecutionState.Completed, resultStatus: status, resultMessage: message, completedAt: currentTimestamp() });
79
80
  }
80
- async setExecutionError(executionId, reason) {
81
- await this.#validationExecutionService.update(executionId, { state: DocumentValidationExecutionState.Error, resultStatus: DocumentValidationResultStatus.Failed, resultMessage: reason, completedAt: currentTimestamp() });
81
+ async setExecutionError(tenantId, executionId, reason) {
82
+ await this.#validationExecutionService.updateByQuery({ tenantId, executionId }, { state: DocumentValidationExecutionState.Error, resultStatus: DocumentValidationResultStatus.Failed, resultMessage: reason, completedAt: currentTimestamp() });
82
83
  }
83
- async loadRelatedDocument(executionId, documentId) {
84
- const execution = await this.#validationExecutionService.load(executionId);
85
- const workflow = await this.#documentWorkflowService.repository.load(execution.workflowId);
86
- const documentData = await this.loadDocumentData(documentId);
87
- await this.#validationExecutionRelatedDocumentService.upsert(['executionId', 'documentId'], { executionId, documentId: workflow.documentId });
84
+ async loadRelatedDocument(tenantId, executionId, documentId) {
85
+ const execution = await this.#validationExecutionService.loadByQuery({ tenantId, id: executionId });
86
+ const workflow = await this.#documentWorkflowService.repository.loadByQuery({ tenantId, id: execution.workflowId });
87
+ const documentData = await this.loadDocumentData(tenantId, documentId);
88
+ await this.#validationExecutionRelatedDocumentService.upsert(['executionId', 'documentId'], { tenantId, executionId, documentId: workflow.documentId });
88
89
  return documentData;
89
90
  }
90
- async loadDocumentData(documentId) {
91
- const document = await this.#documentService.load(documentId);
91
+ async loadDocumentData(tenantId, documentId) {
92
+ const document = await this.#documentService.loadByQuery({ tenantId, id: documentId });
92
93
  if (isNull(document.typeId)) {
93
94
  throw new Error('Document has no type');
94
95
  }
95
- const [documentCollections, documentTypeProperties] = await Promise.all([
96
- this.#documentCollectionAssignmentRepository.loadManyByQuery({ documentId: document.id }),
97
- this.#documentTypePropertyService.loadManyByQuery({ typeId: document.typeId }),
96
+ const [documentCollections, documentTypeProperties, type] = await Promise.all([
97
+ this.#documentCollectionAssignmentRepository.loadManyByQuery({ tenantId, documentId: document.id }),
98
+ this.#documentTypePropertyService.loadManyByQuery({ tenantId: { $or: [null, tenantId] }, typeId: document.typeId }),
99
+ this.#documentTypeService.loadByQuery({ tenantId: { $or: [null, tenantId] }, id: document.typeId }),
98
100
  ]);
99
101
  const documentCollectionIds = getEntityIds(documentCollections);
100
102
  const documentPropertyIds = getEntityIds(documentTypeProperties);
101
- const [collections, category, type, properties, propertyValues] = await Promise.all([
102
- this.#documentManagementService.loadManyByQuery({ id: { $in: documentCollectionIds } }),
103
- this.#documentCategoryService.load(document.typeId),
104
- this.#documentTypeService.load(document.typeId),
105
- this.#documentPropertyService.loadManyByQuery({ id: { $in: documentPropertyIds } }),
106
- this.#documentPropertyValueService.loadManyByQuery({ documentId: document.id }),
103
+ const [collections, category, properties, propertyValues] = await Promise.all([
104
+ this.#documentManagementService.loadManyByQuery({ tenantId, id: { $in: documentCollectionIds } }),
105
+ this.#documentCategoryService.loadByQuery({ tenantId: { $or: [null, tenantId] }, id: type.categoryId }),
106
+ this.#documentPropertyService.loadManyByQuery({ tenantId: { $or: [null, tenantId] }, id: { $in: documentPropertyIds } }),
107
+ this.#documentPropertyValueService.loadManyByQuery({ tenantId, documentId: document.id }),
107
108
  ]);
108
109
  return {
109
110
  document,
@@ -114,34 +115,34 @@ let DocumentValidationService = DocumentValidationService_1 = class DocumentVali
114
115
  propertyValues,
115
116
  };
116
117
  }
117
- async loadDocumentValidationExecutorContext(executionId) {
118
- const execution = await this.#validationExecutionService.load(executionId);
118
+ async loadDocumentValidationExecutorContext(tenantId, executionId) {
119
+ const execution = await this.#validationExecutionService.loadByQuery({ tenantId, id: executionId });
119
120
  const [definition, workflow] = await Promise.all([
120
- this.#validationDefinitionService.load(execution.definitionId),
121
- this.#documentWorkflowService.repository.load(execution.workflowId),
121
+ this.#validationDefinitionService.loadByQuery({ tenantId, id: execution.definitionId }),
122
+ this.#documentWorkflowService.repository.loadByQuery({ tenantId, id: execution.workflowId }),
122
123
  ]);
123
- const documentData = await this.loadDocumentData(workflow.documentId);
124
+ const documentData = await this.loadDocumentData(tenantId, workflow.documentId);
124
125
  return {
125
126
  execution,
126
127
  definition,
127
128
  ...documentData,
128
129
  };
129
130
  }
130
- async processValidationExecution(executionId) {
131
- const context = await this.loadDocumentValidationExecutorContext(executionId);
131
+ async processValidationExecution(tenantId, executionId) {
132
+ const context = await this.loadDocumentValidationExecutorContext(tenantId, executionId);
132
133
  const executor = this.#executorMap.get(context.definition.identifier);
133
134
  if (isUndefined(executor)) {
134
- await this.setExecutionError(executionId, `Invalid validation identifier`);
135
+ await this.setExecutionError(tenantId, executionId, `Invalid validation identifier`);
135
136
  return;
136
137
  }
137
138
  try {
138
- await this.setExecutionRunning(executionId);
139
+ await this.setExecutionRunning(tenantId, executionId);
139
140
  const result = await executor.execute(context);
140
- await this.setExecutionCompleted(executionId, result.status, result.message ?? null);
141
+ await this.setExecutionCompleted(tenantId, executionId, result.status, result.message ?? null);
141
142
  }
142
143
  catch (error) {
143
144
  this.#logger.error(error);
144
- await this.setExecutionError(executionId, 'Internal error');
145
+ await this.setExecutionError(tenantId, executionId, 'Internal error');
145
146
  }
146
147
  }
147
148
  };
@@ -2,16 +2,17 @@ import { DocumentWorkflow, DocumentWorkflowStep } from '../../../document-manage
2
2
  import type { AfterResolveContext } from '../../../injector/index.js';
3
3
  import { afterResolve } from '../../../injector/interfaces.js';
4
4
  import { Transactional } from '../../../orm/server/transactional.js';
5
+ import type { OneOrMany } from '../../../types.js';
5
6
  export declare class DocumentWorkflowService extends Transactional {
6
7
  #private;
7
8
  private readonly documentService;
8
9
  readonly repository: import("../../../orm/server/repository.js").EntityRepository<DocumentWorkflow>;
9
10
  [afterResolve](_: unknown, { cancellationSignal }: AfterResolveContext<any>): void;
10
- loadLatestWorkflow(documentId: string): Promise<DocumentWorkflow>;
11
- tryLoadLatestWorkflow(documentId: string): Promise<DocumentWorkflow | undefined>;
12
- loadLatestWorkflows(documentIds: string[]): Promise<DocumentWorkflow[]>;
13
- proceedWorkflow(documentId: string, userId: string): Promise<void>;
14
- initiateWorkflow(documentId: string, step: DocumentWorkflowStep): Promise<DocumentWorkflow>;
11
+ loadLatestWorkflow(tenantId: string, documentId: string): Promise<DocumentWorkflow>;
12
+ loadLatestWorkflows(tenantId: string, documentIds: string[]): Promise<DocumentWorkflow[]>;
13
+ loadWorkflows(tenantId: string, documentId: OneOrMany<string>): Promise<DocumentWorkflow[]>;
14
+ proceedWorkflow(tenantId: string, documentId: string, userId: string): Promise<void>;
15
+ initiateWorkflow(tenantId: string, documentId: string, step: DocumentWorkflowStep): Promise<DocumentWorkflow>;
15
16
  private setWorkflowState;
16
17
  private processWorkflowJob;
17
18
  private processClassificationWorkflow;
@@ -17,76 +17,79 @@ import { inject } from '../../../injector/inject.js';
17
17
  import { afterResolve } from '../../../injector/interfaces.js';
18
18
  import { Logger } from '../../../logger/index.js';
19
19
  import { injectRepository } from '../../../orm/server/repository.js';
20
- import { Transactional } from '../../../orm/server/transactional.js';
20
+ import { injectTransactional, Transactional } from '../../../orm/server/transactional.js';
21
21
  import { Queue } from '../../../queue/queue.js';
22
+ import { toArray } from '../../../utils/array/array.js';
23
+ import { currentTimestamp } from '../../../utils/date-time.js';
22
24
  import { _throw } from '../../../utils/throw.js';
23
25
  import { isNotNull, isNull } from '../../../utils/type-guards.js';
24
- import { desc, inArray } from 'drizzle-orm';
26
+ import { and, desc, eq, inArray } from 'drizzle-orm';
25
27
  import { documentWorkflow } from '../schemas.js';
26
28
  import { DocumentCollectionService } from './document-collection.service.js';
27
29
  import { DocumentManagementAiService } from './document-management-ai.service.js';
30
+ import { DocumentManagementObservationService } from './document-management-observation.service.js';
28
31
  import { DocumentRequestService } from './document-request.service.js';
29
32
  import { DocumentService } from './document.service.js';
30
33
  import { DocumentManagementSingleton } from './singleton.js';
31
34
  let DocumentWorkflowService = DocumentWorkflowService_1 = class DocumentWorkflowService extends Transactional {
32
35
  #documentManagementAiService = inject(DocumentManagementAiService);
33
- #documentCollectionService = inject(DocumentCollectionService);
34
- #documentRequestService = inject(DocumentRequestService);
36
+ #documentCollectionService = injectTransactional(DocumentCollectionService);
37
+ #documentRequestService = injectTransactional(DocumentRequestService);
35
38
  #documentAssignmentTaskRepository = injectRepository(DocumentAssignmentTask);
36
39
  #documentAssignmentScopeRepository = injectRepository(DocumentAssignmentScope);
40
+ #observationService = inject(DocumentManagementObservationService);
37
41
  #queue = inject((Queue), { name: 'DocumentWorkflow', processTimeout: 5 * 60 * 1000, maxTries: 3 });
38
42
  #logger = inject(Logger, DocumentWorkflowService_1.name);
39
43
  documentService = inject(DocumentService, undefined, { forwardRef: true });
40
- repository = injectRepository(DocumentWorkflow).withSession(this.session);
44
+ repository = injectRepository(DocumentWorkflow);
41
45
  [afterResolve](_, { cancellationSignal }) {
42
46
  if (this.isInTransaction) {
43
47
  return;
44
48
  }
45
49
  this.#queue.process({ concurrency: 5, cancellationSignal }, async (job) => await this.processWorkflowJob(job), this.#logger);
46
50
  }
47
- async loadLatestWorkflow(documentId) {
48
- return await this.repository.loadByQuery({ documentId }, { order: { 'metadata.createTimestamp': 'desc' } });
51
+ async loadLatestWorkflow(tenantId, documentId) {
52
+ return await this.repository.loadByQuery({ tenantId, documentId }, { order: { 'metadata.createTimestamp': 'desc' } });
49
53
  }
50
- async tryLoadLatestWorkflow(documentId) {
51
- return await this.repository.tryLoadByQuery({ documentId }, { order: { 'metadata.createTimestamp': 'desc' } });
52
- }
53
- async loadLatestWorkflows(documentIds) {
54
- const orderedDocumentWorkflows = this.repository.session.$with('orderedDocumentWorkflows').as((qb) => qb
55
- .select()
56
- .from(documentWorkflow)
57
- .where(inArray(documentWorkflow.documentId, documentIds))
58
- .orderBy(desc(documentWorkflow.createTimestamp)));
54
+ async loadLatestWorkflows(tenantId, documentIds) {
59
55
  const latestWorkflows = await this.repository.session
60
- .with(orderedDocumentWorkflows)
61
- .selectDistinctOn([orderedDocumentWorkflows.documentId])
62
- .from(orderedDocumentWorkflows);
56
+ .selectDistinctOn([documentWorkflow.documentId])
57
+ .from(documentWorkflow)
58
+ .where(and(eq(documentWorkflow.tenantId, tenantId), inArray(documentWorkflow.documentId, documentIds)))
59
+ .orderBy(documentWorkflow.documentId, desc(documentWorkflow.createTimestamp));
63
60
  return await this.repository.mapManyToEntity(latestWorkflows);
64
61
  }
65
- async proceedWorkflow(documentId, userId) {
62
+ async loadWorkflows(tenantId, documentId) {
63
+ return await this.repository.loadManyByQuery({ tenantId, documentId: { $in: toArray(documentId) } }, { order: { 'documentId': 'asc', 'metadata.createTimestamp': 'desc' } });
64
+ }
65
+ async proceedWorkflow(tenantId, documentId, userId) {
66
66
  await this.transaction(async (tx) => {
67
- const workflow = await this.withTransaction(tx).loadLatestWorkflow(documentId);
68
- if (workflow.state != DocumentWorkflowState.Completed) {
69
- throw new BadRequestError('Current workflow is not completed');
67
+ const workflow = await this.withTransaction(tx).loadLatestWorkflow(tenantId, documentId);
68
+ if (workflow.state != DocumentWorkflowState.Review) {
69
+ throw new BadRequestError('Current workflow is not in review state.');
70
70
  }
71
71
  if (isNotNull(workflow.completeUserId)) {
72
- throw new BadRequestError('Latest workflow is already completed');
72
+ throw new BadRequestError('Latest workflow is already completed.');
73
73
  }
74
- await this.repository.withTransaction(tx).update(workflow.id, { completeUserId: userId });
74
+ await this.repository.withTransaction(tx).update(workflow.id, { state: DocumentWorkflowState.Completed, completeUserId: userId });
75
75
  await match(workflow.step)
76
76
  .with(DocumentWorkflowStep.Classification, () => _throw(new BadRequestError('Proceeding from classification occurs automatically.')))
77
- .with(DocumentWorkflowStep.Extraction, async () => await this.withTransaction(tx).initiateWorkflow(documentId, DocumentWorkflowStep.Assignment))
78
- .with(DocumentWorkflowStep.Assignment, async () => await this.withTransaction(tx).initiateWorkflow(documentId, DocumentWorkflowStep.Validation))
77
+ .with(DocumentWorkflowStep.Extraction, async () => await this.withTransaction(tx).initiateWorkflow(tenantId, documentId, DocumentWorkflowStep.Assignment))
78
+ .with(DocumentWorkflowStep.Assignment, async () => await this.withTransaction(tx).initiateWorkflow(tenantId, documentId, DocumentWorkflowStep.Validation))
79
79
  .with(DocumentWorkflowStep.Validation, () => { })
80
80
  .exhaustive();
81
+ this.#observationService.documentChange(workflow.id, tx);
81
82
  });
82
83
  }
83
- async initiateWorkflow(documentId, step) {
84
- const workflow = await this.repository.insert({ documentId, step, state: 'pending', failReason: null, completeUserId: null });
84
+ async initiateWorkflow(tenantId, documentId, step) {
85
+ const workflow = await this.repository.insert({ tenantId, documentId, step, state: 'pending', failReason: null, completeTimestamp: null, completeUserId: null });
85
86
  await this.#queue.enqueue({ workflowId: workflow.id });
87
+ this.#observationService.documentChange(workflow.id, this.session);
86
88
  return workflow;
87
89
  }
88
90
  async setWorkflowState(id, state, failReason = null) {
89
- await this.repository.update(id, { state, failReason });
91
+ await this.repository.update(id, { state, completeTimestamp: (state == DocumentWorkflowState.Completed) ? currentTimestamp() : undefined, failReason });
92
+ this.#observationService.workflowChange(id, this.session);
90
93
  }
91
94
  async processWorkflowJob(job) {
92
95
  const workflow = await this.repository.load(job.data.workflowId);
@@ -99,48 +102,56 @@ let DocumentWorkflowService = DocumentWorkflowService_1 = class DocumentWorkflow
99
102
  .with(DocumentWorkflowStep.Assignment, async () => await this.processAssignmentWorkflow(workflow))
100
103
  .with(DocumentWorkflowStep.Validation, async () => await this.processValidationWorkflow(workflow))
101
104
  .exhaustive();
102
- await this.setWorkflowState(workflow.id, DocumentWorkflowState.Completed);
103
105
  if (workflow.step == DocumentWorkflowStep.Classification) {
104
- // automatically start extraction after classification
105
- await this.initiateWorkflow(workflow.documentId, DocumentWorkflowStep.Extraction);
106
+ // no need for after classification review. Automatically start extraction.
107
+ await this.setWorkflowState(workflow.id, DocumentWorkflowState.Completed);
108
+ await this.initiateWorkflow(workflow.tenantId, workflow.documentId, DocumentWorkflowStep.Extraction);
109
+ }
110
+ else {
111
+ await this.setWorkflowState(workflow.id, DocumentWorkflowState.Review);
106
112
  }
107
113
  }
108
114
  catch (error) {
109
- const isLastTry = job.tries == this.#queue.maxTries;
115
+ const isLastTry = job.tries >= this.#queue.maxTries;
110
116
  if (isLastTry) {
111
117
  await this.repository.update(workflow.id, { state: DocumentWorkflowState.Error });
118
+ this.#observationService.documentChange(workflow.id, this.session);
112
119
  }
113
120
  throw error;
114
121
  }
115
122
  }
116
123
  async processClassificationWorkflow(workflow) {
117
- const typeId = await this.#documentManagementAiService.classifyDocumentType(workflow.documentId);
124
+ const typeId = await this.#documentManagementAiService.classifyDocumentType(workflow.tenantId, workflow.documentId);
118
125
  await this.documentService.repository.update(workflow.documentId, { typeId, approval: DocumentApproval.Pending });
126
+ this.#observationService.documentChange(workflow.documentId, this.session);
119
127
  }
120
128
  async processExtractionWorkflow(workflow) {
121
- const extraction = await this.#documentManagementAiService.extractDocumentInformation(workflow.documentId);
122
- await this.documentService.update(workflow.documentId, extraction);
129
+ const extraction = await this.#documentManagementAiService.extractDocumentInformation(workflow.tenantId, workflow.documentId);
130
+ await this.documentService.update(workflow.tenantId, workflow.documentId, extraction);
123
131
  }
124
132
  async processAssignmentWorkflow(workflow) {
125
- const assignmentTask = await this.#documentAssignmentTaskRepository.loadByQuery({ documentId: workflow.documentId });
126
- const assignmentScopes = await this.#documentAssignmentScopeRepository.loadManyByQuery({ taskId: assignmentTask.id });
133
+ const [document, assignmentTask] = await Promise.all([
134
+ this.documentService.repository.loadByQuery({ tenantId: workflow.tenantId, id: workflow.documentId }),
135
+ this.#documentAssignmentTaskRepository.loadByQuery({ tenantId: workflow.tenantId, documentId: workflow.documentId }),
136
+ ]);
137
+ const assignmentScopes = await this.#documentAssignmentScopeRepository.loadManyByQuery({ tenantId: workflow.tenantId, taskId: assignmentTask.id });
127
138
  const collectionIds = assignmentScopes.map((scope) => scope.collectionId);
128
139
  await match(assignmentTask.target)
129
140
  .with('collection', async () => {
130
- const suitableCollectionIds = await this.#documentManagementAiService.findSuitableCollectionsForDocument(workflow.documentId, collectionIds);
141
+ const suitableCollectionIds = await this.#documentManagementAiService.findSuitableCollectionsForDocument(document, collectionIds);
131
142
  if (suitableCollectionIds.length == 0) {
132
143
  await this.setWorkflowState(workflow.id, DocumentWorkflowState.Failed, DocumentWorkflowFailReason.NoSuitableCollection);
133
144
  return;
134
145
  }
135
- await this.#documentCollectionService.assignDocument(workflow.documentId, suitableCollectionIds);
146
+ await this.#documentCollectionService.assignDocument(document, suitableCollectionIds);
136
147
  })
137
148
  .with('request', async () => {
138
- const suitableRequestId = await this.#documentManagementAiService.findSuitableRequestForDocument(workflow.documentId, collectionIds);
149
+ const suitableRequestId = await this.#documentManagementAiService.findSuitableRequestForDocument(document, collectionIds);
139
150
  if (isNull(suitableRequestId)) {
140
151
  await this.setWorkflowState(workflow.id, DocumentWorkflowState.Failed, DocumentWorkflowFailReason.NoSuitableRequest);
141
152
  return;
142
153
  }
143
- await this.#documentRequestService.assignDocument(suitableRequestId, workflow.documentId);
154
+ await this.#documentRequestService.assignDocument(document, suitableRequestId);
144
155
  })
145
156
  .exhaustive();
146
157
  }