@tstdl/base 0.92.142 → 0.92.144
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/ai-file.service.js +1 -1
- package/ai/ai.service.js +3 -3
- package/ai/types.d.ts +1 -1
- package/api/client/client.d.ts +1 -1
- package/api/client/client.js +10 -4
- package/api/server/middlewares/content-type.middleware.js +8 -7
- package/api/types.js +1 -1
- package/authentication/client/authentication.service.js +3 -3
- package/authentication/server/authentication-ancillary.service.d.ts +11 -1
- package/authentication/server/authentication-ancillary.service.js +1 -1
- package/authentication/server/authentication-secret-requirements.validator.js +1 -1
- package/authentication/server/authentication.api-controller.js +22 -10
- package/authentication/server/authentication.service.d.ts +11 -5
- package/authentication/server/authentication.service.js +97 -49
- package/authentication/server/drizzle.config.js +2 -2
- package/authentication/server/module.js +1 -1
- package/cancellation/token.d.ts +2 -2
- package/cancellation/token.js +4 -4
- package/cookie/cookie.js +2 -2
- package/document-management/api/document-management.api.d.ts +122 -24
- package/document-management/api/document-management.api.js +17 -0
- package/document-management/{server/services → authorization}/document-management-authorization.service.d.ts +7 -7
- package/document-management/authorization/document-management-authorization.service.js +2 -0
- package/document-management/authorization/index.d.ts +2 -0
- package/document-management/authorization/index.js +2 -0
- package/document-management/authorization/policies.d.ts +38 -0
- package/document-management/authorization/policies.js +2 -0
- package/document-management/index.d.ts +1 -0
- package/document-management/index.js +1 -0
- package/document-management/models/document-assignment-scope.model.d.ts +1 -0
- package/document-management/models/document-assignment-scope.model.js +10 -3
- package/document-management/models/document-assignment-task.model.d.ts +1 -0
- package/document-management/models/document-assignment-task.model.js +8 -2
- package/document-management/models/document-category.model.d.ts +1 -0
- package/document-management/models/document-category.model.js +7 -1
- package/document-management/models/document-collection-assignment.model.d.ts +1 -0
- package/document-management/models/document-collection-assignment.model.js +12 -4
- package/document-management/models/document-collection.model.d.ts +2 -0
- package/document-management/models/document-collection.model.js +8 -2
- package/document-management/models/document-management-table.d.ts +3 -1
- package/document-management/models/document-management-table.js +2 -2
- package/document-management/models/document-property-value.model.d.ts +1 -0
- package/document-management/models/document-property-value.model.js +9 -3
- package/document-management/models/document-property.model.d.ts +1 -0
- package/document-management/models/document-property.model.js +8 -2
- package/document-management/models/document-request-collection-assignment.model.d.ts +1 -0
- package/document-management/models/document-request-collection-assignment.model.js +12 -4
- package/document-management/models/document-request-template.d.ts +1 -0
- package/document-management/models/document-request-template.js +6 -1
- package/document-management/models/document-request.model.d.ts +1 -0
- package/document-management/models/document-request.model.js +10 -1
- package/document-management/models/document-requests-template.d.ts +1 -0
- package/document-management/models/document-requests-template.js +7 -3
- package/document-management/models/document-tag-assignment.model.d.ts +8 -0
- package/document-management/models/document-tag-assignment.model.js +40 -0
- package/document-management/models/document-tag.model.d.ts +6 -0
- package/document-management/models/{document-request-submission.model.js → document-tag.model.js} +14 -18
- package/document-management/models/document-type-property.model.d.ts +1 -0
- package/document-management/models/document-type-property.model.js +7 -2
- package/document-management/models/document-type-validation.model.d.ts +1 -0
- package/document-management/models/document-type-validation.model.js +8 -2
- package/document-management/models/document-type.model.d.ts +1 -0
- package/document-management/models/document-type.model.js +7 -2
- package/document-management/models/document-validation-definition.model.d.ts +1 -0
- package/document-management/models/document-validation-definition.model.js +7 -2
- package/document-management/models/document-validation-execution-related-document.model.d.ts +1 -0
- package/document-management/models/document-validation-execution-related-document.model.js +10 -3
- package/document-management/models/document-validation-execution.model.d.ts +1 -0
- package/document-management/models/document-validation-execution.model.js +9 -3
- package/document-management/models/document-workflow.model.d.ts +4 -1
- package/document-management/models/document-workflow.model.js +16 -4
- package/document-management/models/document.model.d.ts +2 -2
- package/document-management/models/document.model.js +9 -8
- package/document-management/models/index.d.ts +2 -1
- package/document-management/models/index.js +2 -1
- package/document-management/server/api/document-management.api.d.ts +4 -1
- package/document-management/server/api/document-management.api.js +113 -22
- package/document-management/server/configure.d.ts +2 -2
- package/document-management/server/configure.js +7 -7
- package/document-management/server/drizzle/0000_parallel_mantis.sql +359 -0
- package/document-management/server/drizzle/meta/0000_snapshot.json +784 -260
- package/document-management/server/drizzle/meta/_journal.json +2 -2
- package/document-management/server/module.d.ts +2 -2
- package/document-management/server/module.js +2 -2
- package/document-management/server/schemas.d.ts +6 -5
- package/document-management/server/schemas.js +12 -11
- package/document-management/server/services/document-category-type.service.d.ts +19 -10
- package/document-management/server/services/document-category-type.service.js +34 -27
- package/document-management/server/services/document-collection.service.d.ts +13 -6
- package/document-management/server/services/document-collection.service.js +36 -12
- package/document-management/server/services/document-file.service.d.ts +8 -7
- package/document-management/server/services/document-file.service.js +28 -33
- package/document-management/server/services/document-management-ai.service.d.ts +5 -4
- package/document-management/server/services/document-management-ai.service.js +51 -28
- package/document-management/server/services/document-management-ancillary.service.d.ts +3 -21
- package/document-management/server/services/document-management-ancillary.service.js +0 -24
- package/document-management/server/services/document-management-observation.service.d.ts +15 -0
- package/document-management/server/services/document-management-observation.service.js +160 -0
- package/document-management/server/services/document-management.service.d.ts +6 -5
- package/document-management/server/services/document-management.service.js +112 -86
- package/document-management/server/services/document-property.service.d.ts +15 -7
- package/document-management/server/services/document-property.service.js +52 -20
- package/document-management/server/services/document-request.service.d.ts +13 -24
- package/document-management/server/services/document-request.service.js +39 -62
- package/document-management/server/services/document-tag.service.d.ts +10 -0
- package/document-management/server/services/document-tag.service.js +59 -0
- package/document-management/server/services/document-validation.service.d.ts +8 -8
- package/document-management/server/services/document-validation.service.js +41 -40
- package/document-management/server/services/document-workflow.service.d.ts +6 -5
- package/document-management/server/services/document-workflow.service.js +54 -43
- package/document-management/server/services/document.service.d.ts +12 -11
- package/document-management/server/services/document.service.js +66 -40
- package/document-management/server/services/index.d.ts +2 -1
- package/document-management/server/services/index.js +2 -1
- package/document-management/server/services/singleton.js +2 -2
- package/document-management/server/validators/ai-validation-executor.js +4 -4
- package/document-management/service-models/document-collection-metadata.service-model.d.ts +14 -0
- package/document-management/service-models/document-collection-metadata.service-model.js +1 -0
- package/document-management/service-models/document-folders.view-model.d.ts +1 -7
- package/document-management/service-models/document-folders.view-model.js +3 -15
- package/document-management/service-models/document-management.view-model.d.ts +20 -6
- package/document-management/service-models/document-management.view-model.js +62 -8
- package/document-management/service-models/document.service-model.d.ts +14 -11
- package/document-management/service-models/document.service-model.js +11 -2
- package/document-management/service-models/enriched/enriched-document-assignment.view.d.ts +1 -1
- package/document-management/service-models/enriched/enriched-document-assignment.view.js +0 -2
- package/document-management/service-models/enriched/enriched-document-category.view.d.ts +11 -1
- package/document-management/service-models/enriched/enriched-document-category.view.js +44 -1
- package/document-management/service-models/enriched/enriched-document-collection.view.d.ts +4 -2
- package/document-management/service-models/enriched/enriched-document-collection.view.js +13 -3
- package/document-management/service-models/enriched/enriched-document-management-data.view.d.ts +2 -0
- package/document-management/service-models/enriched/enriched-document-management-data.view.js +4 -2
- package/document-management/service-models/enriched/enriched-document-request.view.d.ts +1 -0
- package/document-management/service-models/enriched/enriched-document-request.view.js +2 -0
- package/document-management/service-models/enriched/enriched-document-type.view.d.ts +9 -1
- package/document-management/service-models/enriched/enriched-document-type.view.js +28 -1
- package/document-management/service-models/enriched/enriched-document.view.d.ts +7 -6
- package/document-management/service-models/enriched/enriched-document.view.js +29 -6
- package/document-management/service-models/{normalized-requests-template-data.model.d.ts → enriched/enriched-requests-template-data.model.d.ts} +6 -6
- package/document-management/service-models/{normalized-requests-template-data.model.js → enriched/enriched-requests-template-data.model.js} +1 -1
- package/document-management/service-models/enriched/index.d.ts +1 -0
- package/document-management/service-models/enriched/index.js +1 -0
- package/document-management/service-models/index.d.ts +2 -2
- package/document-management/service-models/index.js +2 -2
- package/examples/document-management/categories-and-types.d.ts +33 -31
- package/examples/document-management/categories-and-types.js +33 -0
- package/examples/document-management/main.d.ts +5 -4
- package/examples/document-management/main.js +13 -7
- package/function/log.js +2 -2
- package/http/server/node/module.d.ts +4 -1
- package/http/server/node/module.js +10 -1
- package/http/server/node/node-http-server.d.ts +3 -6
- package/http/server/node/node-http-server.js +68 -67
- package/injector/inject.js +6 -6
- package/injector/injector.js +3 -3
- package/jsx/is-component-class.js +1 -1
- package/key-value-store/key-value.store.d.ts +38 -7
- package/key-value-store/key-value.store.js +2 -1
- package/key-value-store/mongo/mongo-key-value.store.d.ts +1 -0
- package/key-value-store/mongo/mongo-key-value.store.js +14 -5
- package/key-value-store/postgres/drizzle/0000_shocking_slipstream.sql +12 -0
- package/key-value-store/postgres/drizzle/meta/0000_snapshot.json +97 -0
- package/key-value-store/postgres/drizzle/meta/_journal.json +13 -0
- package/key-value-store/postgres/drizzle.config.d.ts +2 -0
- package/key-value-store/postgres/drizzle.config.js +11 -0
- package/key-value-store/postgres/index.d.ts +2 -0
- package/key-value-store/postgres/index.js +2 -0
- package/key-value-store/postgres/key-value-store.service.d.ts +17 -0
- package/key-value-store/postgres/key-value-store.service.js +65 -0
- package/key-value-store/postgres/models/index.d.ts +2 -0
- package/key-value-store/postgres/models/index.js +2 -0
- package/key-value-store/postgres/models/key-value.model.d.ts +7 -0
- package/key-value-store/postgres/models/key-value.model.js +35 -0
- package/key-value-store/postgres/models/schemas.d.ts +3 -0
- package/key-value-store/postgres/models/schemas.js +4 -0
- package/key-value-store/postgres/module.d.ts +6 -0
- package/key-value-store/postgres/module.js +23 -0
- package/lock/web/web-lock.d.ts +0 -1
- package/lock/web/web-lock.js +6 -13
- package/orm/data-types/timestamp.js +1 -1
- package/orm/decorators.d.ts +37 -29
- package/orm/decorators.js +44 -24
- package/orm/entity.d.ts +1 -0
- package/orm/query.d.ts +10 -2
- package/orm/repository.types.d.ts +2 -1
- package/orm/schemas/json.d.ts +12 -6
- package/orm/schemas/json.js +12 -5
- package/orm/server/database.js +5 -2
- package/orm/server/drizzle/schema-converter.js +40 -11
- package/orm/server/query-converter.d.ts +2 -1
- package/orm/server/query-converter.js +57 -34
- package/orm/server/repository.d.ts +26 -43
- package/orm/server/repository.js +106 -39
- package/orm/server/transaction.d.ts +2 -1
- package/orm/server/transaction.js +3 -0
- package/orm/server/transactional.d.ts +5 -1
- package/orm/server/transactional.js +34 -4
- package/package.json +14 -11
- package/process/spawn.js +0 -1
- package/promise/deferred-promise.d.ts +4 -3
- package/promise/deferred-promise.js +13 -5
- package/queue/postgres/queue.js +8 -8
- package/reflection/utils.js +3 -3
- package/schema/decorators/class.js +0 -1
- package/schema/decorators/schema.js +1 -1
- package/schema/schemas/boolean.d.ts +1 -1
- package/schema/schemas/boolean.js +2 -2
- package/schema/schemas/number.js +3 -3
- package/schema/schemas/object.js +5 -6
- package/sse/server-sent-events-source.js +4 -1
- package/utils/compression.js +9 -9
- package/utils/date-time.d.ts +1 -0
- package/utils/date-time.js +18 -4
- package/utils/equals.d.ts +7 -0
- package/utils/equals.js +17 -2
- package/utils/function/memoize.js +10 -2
- package/utils/jwt.js +3 -3
- package/utils/object/property-name.d.ts +2 -2
- package/utils/timing.d.ts +2 -2
- package/utils/timing.js +12 -12
- package/document-management/models/document-request-submission.model.d.ts +0 -7
- package/document-management/server/drizzle/0000_moaning_luckman.sql +0 -305
- 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
|
-
#
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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(
|
|
101
|
+
async assignDocument(document, requestId) {
|
|
97
102
|
await this.transaction(async (tx) => {
|
|
98
|
-
const request = await this.#documentRequestRepository.withTransaction(tx).
|
|
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).
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
85
|
-
const workflow = await this.#documentWorkflowService.repository.
|
|
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.
|
|
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,
|
|
102
|
-
this.#documentManagementService.loadManyByQuery({ id: { $in: documentCollectionIds } }),
|
|
103
|
-
this.#documentCategoryService.
|
|
104
|
-
this.#
|
|
105
|
-
this.#
|
|
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.
|
|
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.
|
|
121
|
-
this.#documentWorkflowService.repository.
|
|
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
|
-
|
|
12
|
-
|
|
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 =
|
|
34
|
-
#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)
|
|
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
|
|
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
|
-
.
|
|
61
|
-
.
|
|
62
|
-
.
|
|
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
|
|
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.
|
|
69
|
-
throw new BadRequestError('Current workflow is not
|
|
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
|
-
//
|
|
105
|
-
await this.
|
|
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
|
|
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
|
|
126
|
-
|
|
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(
|
|
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(
|
|
146
|
+
await this.#documentCollectionService.assignDocument(document, suitableCollectionIds);
|
|
136
147
|
})
|
|
137
148
|
.with('request', async () => {
|
|
138
|
-
const suitableRequestId = await this.#documentManagementAiService.findSuitableRequestForDocument(
|
|
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(
|
|
154
|
+
await this.#documentRequestService.assignDocument(document, suitableRequestId);
|
|
144
155
|
})
|
|
145
156
|
.exhaustive();
|
|
146
157
|
}
|