From 65aaae9d905b54ecba7cc8e4730140df6a9be386 Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 29 Mar 2026 16:21:57 +0700 Subject: [PATCH] 690329:1621 Fixing superadmin by GPT-5.3 #01 --- ...119442391-1908b04cd11e739233ee8977de00dc57 | Bin 71011 -> 71038 bytes ...ceservice_3ffc2ea46146fb9da9dc418f81d1e3c8 | 881 ++++++++++++++++++ ...rvice_3ffc2ea46146fb9da9dc418f81d1e3c8.map | 1 + ...rvicespec_5d371618e36feb86f1397eae2e3f99cc | 361 +++++++ ...espec_5d371618e36feb86f1397eae2e3f99cc.map | 1 + ...rvicespec_a4210bd9791ec5e98d400126ff42cb7e | 361 +++++++ ...espec_a4210bd9791ec5e98d400126ff42cb7e.map | 1 + ...ceservice_ae8ff3a33dc0eeda2f50bf4243e0051a | 881 ++++++++++++++++++ ...rvice_ae8ff3a33dc0eeda2f50bf4243e0051a.map | 1 + ...tagentity_cd09324200fd1ed927db2d852f565a3c | 65 ++ ...ntity_cd09324200fd1ed927db2d852f565a3c.map | 1 + ...rvicespec_efb009e94d43e8a69ddadbd2e8e37b03 | 361 +++++++ ...espec_efb009e94d43e8a69ddadbd2e8e37b03.map | 1 + ...cac696b99-da39a3ee5e6b4b0d3255bfef95601890 | 2 +- .../circulation/circulation.service.ts | 41 +- .../circulation/dto/create-circulation.dto.ts | 3 + .../correspondence.service.spec.ts | 92 ++ .../correspondence/correspondence.service.ts | 28 +- backend/src/modules/rfa/dto/create-rfa.dto.ts | 8 + backend/src/modules/rfa/rfa.service.ts | 22 + .../transmittal/dto/create-transmittal.dto.ts | 8 + .../transmittal/transmittal.service.ts | 40 +- 22 files changed, 3145 insertions(+), 15 deletions(-) create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8 create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8.map create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc.map create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e.map create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a.map create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c.map create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03 create mode 100644 backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03.map diff --git a/backend/src/.jest-cache/haste-map-60cab15b743c6776f41d29bcac696b99-0ca4a1d6e3dfec1d63b61b0119442391-1908b04cd11e739233ee8977de00dc57 b/backend/src/.jest-cache/haste-map-60cab15b743c6776f41d29bcac696b99-0ca4a1d6e3dfec1d63b61b0119442391-1908b04cd11e739233ee8977de00dc57 index c1b757eed127229f8c78a46d9755aad154fdbeb0..75295316a61870ba7f7c5a17c05338d7bb34d5be 100644 GIT binary patch delta 1511 zcmYk5dr(wm7{+<`!0sM)5%vNs7ZDZ^aPk5ajtI0kjw4MOnTe9Z0zm;{jAWDHh$&9! zRD(X&!I5ObRFt@W;DQhrQAvdar9q6iiEiScA`vz^&@M39`R6Rq?n#6|&tw#9b6CEow+Q1NHOL(2nTxLzv9?7M#9sBwBi8&%ww4RN_ASG+ZA?isE(`<<9U<~^I9`cj*y2u zv)!N;v4HhmgwRL@Mx!Kf+hBvHXbF3J<9Z%#i+K2r$dMZ_XN~%L656H2W3h2YL8D%V z_SjDHgU5)P<;J&2M=oY}1pU1qT<@fx%|S0FIkz?%2P5gWXaSyE5vN`nWg_}M~f58FNI?Z2hil*K?~9B?TYVwc4M;m1wzzPmQ~_O z7_EpyU-<@%|CEiw(mN&`q;M&3!R|5v0Tp%ZQstY3-ccS=m1$@_--a#cQyB~~gxBjF z@M~2xYN{OYUfs5t^`Ghl*i{w5x4I5DFAc)~N*37VJ*W=SfUn(x*4p{dUx-D1508%8 z4CMK1&|fRV(1oq0nkxpIb|A5K5B{jr!&sj~{^-PC_Gl19(Y!DMA>qQaL0yhSmDL3go)-9oNn}h`=v@&ex-wG4Jxkq zVB+d_w)dB}h$UR>6tRMKxd@u}R8(DeMS2I%I&Q2rJ3YF*5ZbB4uA4U4>}i7=x87lz z&LokEXrB3XrEnB%_87KXku#ZaEn!K$wj4?tcsLDdA&XMMz2AmC7^pH`BDUYyPw+Cv;_`#{5&z&b_S%S?lc!rK_RaEqQ;x&8mmqUASFTq$&xxf9d{L*v zx=NnuA1O(0xAyv>S-WXJaYG@yzq(5e@ISEpGS}horEoGEd%~CodXh zNgl`&-SETLDhyaLkFv}m&QCZzPo1EyFX1 zBd~YsLA+x=NP7zhHD^sR7o5>3@pzH~TQ^v<+PPN18g~u;c1wk?hlcxHM-Xpw_a-EH zZie1#KKeaFq4AuHe2)bF-fI~_;d>GbbX(w2pu}_USZ>$(3OJGX2Wk&Lz~=l+G_{Ca zSAtFSJh3~k)DB5y*kWPkmr_BKy4twi` zfSd`zR^xYNUtK>nTps>s6?adFl_9x7#I150a~7_IDv%Uv=a?1K5jm7~?-+$!gbU$H z-M|R6iCQiUtrW2RT^)SRX?bbL9WqfAIWo{u2HkBpG{0}pE$@1(*gfhx70+}RFt*c< zWwV!yq(^Mm@M$7&DBaoT(i>Xhx@7cQU01~s|ZT-!=m`n$gCQP``g^Ob$gr~lLHll zKes32rVNv^EgeJuFYf(jxXn_zsaVeynHGZd6Oo!9?Aa&di&-+_Z+{IVzPw*Ak_7r8FT&s8Dy@O0Bi|3Rax62j39>{2*}kaF}k ze2z(&TXYGBj?BiXW2Z6gNG!^ph`7i}yrwvU5LEgbJXVXSHdy2CiTP+LJ^k8GhO8tJ zLC0$mu}DOXuL=>z9at)Pn@q!AjsCKfU1bV{p^kXj#p$N1t8REy^Ck18dI1G>ksN=;Pk{Wg8!GBW_NxDY zXbM&|yupFjrU<6&16Wr(gk?0$FiWTqOYi*!r!EaX?@%CUmIKN=ts!*!V_wH{{L(KX zvrA>d>`~ff%W<8)0!_q6Eza<0v_a7)YNS?Lv*u2Xz@e3T!n_t8i_O;wQ`-_y;VYT~ z-mGYyNQi85LGRs2E@<;73LLzm_pSt}YZkbG#HKsbcesH1EtufLNfKk0_^!22v)N7lU)C~fSYNQxKx$KE6sp_t6 z`glm(<#yQL63kwGPDBCl?sG&*{}RmTpNXJ;CupDUg?1no$Dc0c^#h5b6l_6Bxc6@_ z_P(-ICC3i$=ibqnU<^R(D_iz?wUwkR0=Y;ABBNO?QlXq|GtScu!zzJlWZZspGD$`S zIZIU*rlUtema3u+!!%2EW}4DrGZdzvXVQHo6`DmRg()e=kReh4Nt3K7O=_^DctgGw zt(6%p?5KyNRkq}A*k?nZ3DST)B}yF*lrHFku_9Y5y>uWuX`2HrkaRW_Eq$sXr~d#B CVrSC; diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8 b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8 new file mode 100644 index 0000000..b0a9528 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8 @@ -0,0 +1,881 @@ +e94ae16f5f5a03b7666b58118bd53cd7 +"use strict"; +// File: src/modules/correspondence/correspondence.service.ts +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + 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; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var CorrespondenceService_1; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CorrespondenceService = void 0; +const common_1 = require("@nestjs/common"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +// Entities +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const tag_entity_1 = require("../master/entities/tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +// Services +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +let CorrespondenceService = CorrespondenceService_1 = class CorrespondenceService { + async hasSystemManageAllPermission(userId) { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + constructor(correspondenceRepo, revisionRepo, typeRepo, statusRepo, referenceRepo, tagRepo, numberingService, jsonSchemaService, workflowEngine, userService, dataSource, searchService, fileStorageService, uuidResolver, notificationService) { + this.correspondenceRepo = correspondenceRepo; + this.revisionRepo = revisionRepo; + this.typeRepo = typeRepo; + this.statusRepo = statusRepo; + this.referenceRepo = referenceRepo; + this.tagRepo = tagRepo; + this.numberingService = numberingService; + this.jsonSchemaService = jsonSchemaService; + this.workflowEngine = workflowEngine; + this.userService = userService; + this.dataSource = dataSource; + this.searchService = searchService; + this.fileStorageService = fileStorageService; + this.uuidResolver = uuidResolver; + this.notificationService = notificationService; + this.logger = new common_1.Logger(CorrespondenceService_1.name); + } + /** + * Business Rule Validation: EC-CORR-003 - Correspondence to Self + * Prevent external correspondence to same organization + */ + async validateCorrespondenceRecipients(createDto, user) { + // Get user's organization + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + if (!userOrgId) { + if (createDto.originatorId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (canManageAll) { + userOrgId = await this.uuidResolver.resolveOrganizationId(createDto.originatorId); + } + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + } + // For impersonation, use the specified originator + const originatorOrgId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : userOrgId; + // Check if it's internal communication + if (createDto.isInternal) { + // Internal communications should use Circulation instead + throw new common_1.BadRequestException('Internal communications should use Circulation Sheet instead of Correspondence'); + } + // Validate recipients + if (!createDto.recipients || createDto.recipients.length === 0) { + throw new common_1.BadRequestException('At least one recipient (TO or CC) is required'); + } + const toRecipients = createDto.recipients.filter((r) => r.type === 'TO'); + const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC'); + if (toRecipients.length === 0 && ccRecipients.length === 0) { + throw new common_1.BadRequestException('At least one TO or CC recipient is required'); + } + // Check for same organization correspondence + for (const recipient of createDto.recipients) { + const recipientOrgId = await this.uuidResolver.resolveOrganizationId(recipient.organizationId); + if (recipientOrgId === originatorOrgId) { + throw new common_1.BadRequestException('Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'); + } + } + } + async create(createDto, user) { + // Business Rule Validation: EC-CORR-003 - Correspondence to Self + await this.validateCorrespondenceRecipients(createDto, user); + // ADR-019: Resolve UUID references to internal INT IDs + const resolvedProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const resolvedOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const resolvedRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + const statusDraft = await this.statusRepo.findOne({ + where: { statusCode: 'DRAFT' }, + }); + if (!statusDraft) { + throw new common_1.InternalServerErrorException('Status DRAFT not found in Master Data'); + } + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + // Impersonation Logic + if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (!canManageAll) { + throw new common_1.ForbiddenException('You do not have permission to create documents on behalf of other organizations.'); + } + userOrgId = resolvedOriginatorId; + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + if (createDto.details) { + try { + await this.jsonSchemaService.validate(type.typeCode, createDto.details); + } + catch (error) { + this.logger.warn(`Schema validation warning for ${type.typeCode}: ${error.message}`); + } + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // [Fix #6] Fetch real ORG Code from Organization entity + const originatorOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: userOrgId }, + }); + const orgCode = originatorOrg?.organizationCode ?? 'UNK'; + // [v1.5.1] Extract recipient organization from recipients array (Primary TO) + const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + const docNumber = await this.numberingService.generateNextNumber({ + projectId: resolvedProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, // [v1.5.1] Pass recipient for document number format + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + const correspondence = queryRunner.manager.create(correspondence_entity_1.Correspondence, { + correspondenceNumber: docNumber.number, + correspondenceTypeId: createDto.typeId, + disciplineId: createDto.disciplineId, + projectId: resolvedProjectId, + originatorId: userOrgId, + isInternal: createDto.isInternal || false, + createdBy: user.user_id, + }); + const savedCorr = await queryRunner.manager.save(correspondence); + const revision = queryRunner.manager.create(correspondence_revision_entity_1.CorrespondenceRevision, { + correspondenceId: savedCorr.id, + revisionNumber: 0, + revisionLabel: 'A', + isCurrent: true, + statusId: statusDraft.id, + subject: createDto.subject, + body: createDto.body, + remarks: createDto.remarks, + dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined, + documentDate: createDto.documentDate + ? new Date(createDto.documentDate) + : undefined, + issuedDate: createDto.issuedDate + ? new Date(createDto.issuedDate) + : undefined, + receivedDate: createDto.receivedDate + ? new Date(createDto.receivedDate) + : undefined, + description: createDto.description, + details: createDto.details, + createdBy: user.user_id, + schemaVersion: 1, + }); + await queryRunner.manager.save(revision); + // Save Recipients (using resolved INT IDs) + if (resolvedRecipients && resolvedRecipients.length > 0) { + const recipients = resolvedRecipients.map((r) => queryRunner.manager.create(correspondence_recipient_entity_1.CorrespondenceRecipient, { + correspondenceId: savedCorr.id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await queryRunner.manager.save(recipients); + } + // Commit attachments from Temp → Permanent (Two-Phase Storage) + if (createDto.attachmentTempIds?.length) { + const issueDate = createDto.issuedDate + ? new Date(createDto.issuedDate) + : createDto.documentDate + ? new Date(createDto.documentDate) + : undefined; + await this.fileStorageService.commit(createDto.attachmentTempIds, { + issueDate, + documentType: 'Correspondence', + }); + } + await queryRunner.commitTransaction(); + // Start Workflow Instance (non-blocking) + try { + const workflowCode = `CORRESPONDENCE_${type.typeCode}`; + await this.workflowEngine.createInstance(workflowCode, 'correspondence', savedCorr.id.toString(), { + projectId: resolvedProjectId, + originatorId: userOrgId, + disciplineId: createDto.disciplineId, + initiatorId: user.user_id, + }); + } + catch (error) { + this.logger.warn(`Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${error.message}`); + } + // Fire-and-forget search indexing (non-blocking, void intentional) + void this.searchService.indexDocument({ + id: savedCorr.id, + publicId: savedCorr.publicId, + type: 'correspondence', + docNumber: docNumber.number, + title: createDto.subject, + description: createDto.description, + status: 'DRAFT', + projectId: resolvedProjectId, + createdAt: new Date(), + }); + return { + ...savedCorr, + currentRevision: revision, + }; + } + catch (err) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to create correspondence: ${err.message}`); + throw err; + } + finally { + await queryRunner.release(); + } + } + async findAll(searchDto = {}) { + const { search, typeId, projectId, statusId, status, page = 1, limit = 10, } = searchDto; + const skip = (page - 1) * limit; + // Change: Query from Revision Repo + const query = this.revisionRepo + .createQueryBuilder('rev') + .leftJoinAndSelect('rev.correspondence', 'corr') + .leftJoinAndSelect('corr.type', 'type') + .leftJoinAndSelect('corr.project', 'project') + .leftJoinAndSelect('corr.originator', 'org') + .leftJoinAndSelect('rev.status', 'status'); + // Filter by Revision Status + const revStatus = searchDto.revisionStatus || 'CURRENT'; + if (revStatus === 'CURRENT') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: true }); + } + else if (revStatus === 'OLD') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: false }); + } + // If 'ALL', no filter needed on isCurrent + if (projectId) { + query.andWhere('corr.projectId = :projectId', { projectId }); + } + if (typeId) { + query.andWhere('corr.correspondenceTypeId = :typeId', { typeId }); + } + if (statusId) { + query.andWhere('rev.statusId = :statusId', { statusId }); + } + if (status) { + query.andWhere('status.statusCode = :status', { status }); + } + if (search) { + query.andWhere('(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)', { search: `%${search}%` }); + } + // Default Sort: Latest Created + query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit); + const [items, total] = await query.getManyAndCount(); + return { + data: items, + meta: { + total, + page, + limit, + totalPages: Math.ceil(total / limit), + }, + }; + } + async findOne(id) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with ID ${id} not found`); + } + return correspondence; + } + async findOneByUuid(publicId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { publicId }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with UUID ${publicId} not found`); + } + return correspondence; + } + async addReference(id, dto) { + const source = await this.correspondenceRepo.findOne({ where: { id } }); + // ADR-019: Resolve target publicId → internal INT id + const target = await this.correspondenceRepo.findOne({ + where: { publicId: dto.targetUuid }, + }); + if (!source || !target) { + throw new common_1.NotFoundException('Source or Target correspondence not found'); + } + if (source.id === target.id) { + throw new common_1.BadRequestException('Cannot reference self'); + } + const exists = await this.referenceRepo.findOne({ + where: { + sourceId: id, + targetId: target.id, + }, + }); + if (exists) { + return exists; + } + const ref = this.referenceRepo.create({ + sourceId: id, + targetId: target.id, + }); + return this.referenceRepo.save(ref); + } + async removeReference(id, targetId) { + const result = await this.referenceRepo.delete({ + sourceId: id, + targetId: targetId, + }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Reference not found'); + } + } + async getTags(id) { + const rows = await this.tagRepo.find({ + where: { correspondenceId: id }, + relations: ['tag'], + }); + return rows.map((r) => r.tag).filter(Boolean); + } + async addTag(id, tagId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence ${id} not found`); + } + const tag = await this.dataSource.manager.findOne(tag_entity_1.Tag, { + where: { id: tagId }, + }); + if (!tag) { + throw new common_1.NotFoundException(`Tag ${tagId} not found`); + } + const exists = await this.tagRepo.findOne({ + where: { correspondenceId: id, tagId }, + }); + if (exists) + return exists; + const row = this.tagRepo.create({ correspondenceId: id, tagId }); + return this.tagRepo.save(row); + } + async removeTag(id, tagId) { + const result = await this.tagRepo.delete({ correspondenceId: id, tagId }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Tag assignment not found'); + } + } + async getReferences(id) { + const outgoing = await this.referenceRepo.find({ + where: { sourceId: id }, + relations: ['target', 'target.type'], + }); + const incoming = await this.referenceRepo.find({ + where: { targetId: id }, + relations: ['source', 'source.type'], + }); + return { outgoing, incoming }; + } + async update(id, updateDto, user) { + // 1. Find Current Revision + const revision = await this.revisionRepo.findOne({ + where: { + correspondenceId: id, + isCurrent: true, + }, + relations: ['correspondence'], + }); + if (!revision) { + throw new common_1.NotFoundException(`Current revision for correspondence ${id} not found`); + } + // 2. Check Permission + if (revision.statusId) { + const status = await this.statusRepo.findOne({ + where: { id: revision.statusId }, + }); + if (status && status.statusCode !== 'DRAFT') { + throw new common_1.BadRequestException('Only DRAFT documents can be updated'); + } + } + // ADR-019: Resolve UUID references in update DTO + const updResolvedProjectId = updateDto.projectId + ? await this.uuidResolver.resolveProjectId(updateDto.projectId) + : undefined; + const updResolvedOriginatorId = updateDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId) + : undefined; + const updResolvedRecipients = updateDto.recipients + ? await Promise.all(updateDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + // 3. Update Correspondence Entity if needed + const correspondenceUpdate = {}; + if (updateDto.disciplineId) + correspondenceUpdate.disciplineId = updateDto.disciplineId; + if (updResolvedProjectId) + correspondenceUpdate.projectId = updResolvedProjectId; + if (updResolvedOriginatorId) + correspondenceUpdate.originatorId = updResolvedOriginatorId; + if (Object.keys(correspondenceUpdate).length > 0) { + await this.correspondenceRepo.update(id, correspondenceUpdate); + } + // 4. Update Revision Entity + const revisionUpdate = {}; + if (updateDto.subject) + revisionUpdate.subject = updateDto.subject; + if (updateDto.body) + revisionUpdate.body = updateDto.body; + if (updateDto.remarks) + revisionUpdate.remarks = updateDto.remarks; + // Format Date correctly if string + if (updateDto.dueDate) + revisionUpdate.dueDate = new Date(updateDto.dueDate); + if (updateDto.documentDate) + revisionUpdate.documentDate = new Date(updateDto.documentDate); + if (updateDto.issuedDate) + revisionUpdate.issuedDate = new Date(updateDto.issuedDate); + if (updateDto.receivedDate) + revisionUpdate.receivedDate = new Date(updateDto.receivedDate); + if (updateDto.description) + revisionUpdate.description = updateDto.description; + if (updateDto.details) + revisionUpdate.details = updateDto.details; + if (Object.keys(revisionUpdate).length > 0) { + await this.revisionRepo.update(revision.id, revisionUpdate); + } + // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage) + if (updateDto.attachmentTempIds?.length) { + const issueDate = updateDto.issuedDate + ? new Date(updateDto.issuedDate) + : updateDto.documentDate + ? new Date(updateDto.documentDate) + : revision.issuedDate || revision.documentDate || undefined; + await this.fileStorageService.commit(updateDto.attachmentTempIds, { + issueDate: issueDate ? new Date(issueDate) : undefined, + documentType: 'Correspondence', + }); + } + // 5. Update Recipients if provided + if (updResolvedRecipients) { + const recipientRepo = this.dataSource.getRepository(correspondence_recipient_entity_1.CorrespondenceRecipient); + await recipientRepo.delete({ correspondenceId: id }); + const newRecipients = updResolvedRecipients.map((r) => recipientRepo.create({ + correspondenceId: id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await recipientRepo.save(newRecipients); + } + // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project) + // AND it is a DRAFT. + // Fetch fresh data for context and comparison + const currentCorr = await this.correspondenceRepo.findOne({ + where: { id }, + relations: ['type', 'recipients', 'recipients.recipientOrganization'], + }); + if (currentCorr) { + const currentToRecipient = currentCorr.recipients?.find((r) => r.recipientType === 'TO'); + const currentRecipientId = currentToRecipient?.recipientOrganizationId; + // Check for ACTUAL value changes + const isProjectChanged = updResolvedProjectId !== undefined && + updResolvedProjectId !== currentCorr.projectId; + const isOriginatorChanged = updResolvedOriginatorId !== undefined && + updResolvedOriginatorId !== currentCorr.originatorId; + const isDisciplineChanged = updateDto.disciplineId !== undefined && + updateDto.disciplineId !== currentCorr.disciplineId; + const isTypeChanged = updateDto.typeId !== undefined && + updateDto.typeId !== currentCorr.correspondenceTypeId; + let isRecipientChanged = false; + let newRecipientId; + if (updResolvedRecipients) { + const newToRecipient = updResolvedRecipients.find((r) => r.type === 'TO'); + newRecipientId = newToRecipient?.organizationId; + if (newRecipientId !== currentRecipientId) { + isRecipientChanged = true; + } + } + if (isProjectChanged || + isDisciplineChanged || + isTypeChanged || + isRecipientChanged || + isOriginatorChanged) { + const targetRecipientId = isRecipientChanged + ? newRecipientId + : currentRecipientId; + // Resolve Recipient Code for the NEW context + let recipientCode = ''; + if (targetRecipientId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: targetRecipientId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + // [Fix #6] Fetch real ORG Code from originator organization + const originatorOrgForUpdate = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { + id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + }, + }); + const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK'; + // Prepare Contexts + const oldCtx = { + projectId: currentCorr.projectId, + originatorOrganizationId: currentCorr.originatorId ?? 0, + typeId: currentCorr.correspondenceTypeId, + disciplineId: currentCorr.disciplineId, + recipientOrganizationId: currentRecipientId, + year: new Date().getFullYear(), + }; + const newCtx = { + projectId: updResolvedProjectId ?? currentCorr.projectId, + originatorOrganizationId: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId, + disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId, + recipientOrganizationId: targetRecipientId, + year: new Date().getFullYear(), + userId: user.user_id, // Pass User ID for Audit + customTokens: { + TYPE_CODE: currentCorr.type?.typeCode || '', + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }; + // If Type Changed, need NEW Type Code + if (isTypeChanged) { + const newType = await this.typeRepo.findOne({ + where: { id: newCtx.typeId }, + }); + if (newType) + newCtx.customTokens.TYPE_CODE = newType.typeCode; + } + const newDocNumber = await this.numberingService.updateNumberForDraft(currentCorr.correspondenceNumber, oldCtx, newCtx); + await this.correspondenceRepo.update(id, { + correspondenceNumber: newDocNumber, + }); + } + } + const updated = await this.findOne(id); + // Re-index updated document in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: updated.id, + publicId: updated.publicId, + type: 'correspondence', + docNumber: updated.correspondenceNumber, + title: updateDto.subject ?? updated.revisions?.[0]?.subject, + description: updateDto.description ?? updated.revisions?.[0]?.description, + status: 'DRAFT', + projectId: updated.projectId, + createdAt: updated.createdAt, + }); + return updated; + } + async previewDocumentNumber(createDto, user) { + // ADR-019: Resolve UUID references + const previewProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const previewOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const previewRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) + userOrgId = fullUser.primaryOrganizationId; + } + if (previewOriginatorId && previewOriginatorId !== userOrgId) { + // Allow impersonation for preview + userOrgId = previewOriginatorId; + } + // Extract recipient from recipients array + const toRecipient = previewRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + return this.numberingService.previewNumber({ + projectId: previewProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + } + /** + * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation + * Cancel correspondence and handle related circulations + */ + async cancel(publicId, reason, user) { + const correspondence = await this.findOneByUuid(publicId); + // Check if user has permission to cancel (Org Admin or Superadmin only) + const permissions = await this.userService.getUserPermissions(user.user_id); + const canCancel = permissions.includes('correspondence.cancel') || + permissions.includes('system.manage_all'); + if (!canCancel) { + throw new common_1.ForbiddenException('Only administrators can cancel correspondences'); + } + // Check if there are any active circulations + const circulationRepo = this.dataSource.getRepository('Circulation'); + const activeCirculations = await circulationRepo.find({ + where: { + correspondenceId: correspondence.id, + status: 'OPEN', + }, + }); + const warningMessage = activeCirculations.length > 0 + ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.` + : ''; + // Get the current revision to update status + const currentRevision = await this.revisionRepo.findOne({ + where: { + correspondenceId: correspondence.id, + isCurrent: true, + }, + }); + if (!currentRevision) { + throw new common_1.NotFoundException('Current revision not found'); + } + // Get cancelled status + const cancelledStatus = await this.statusRepo.findOne({ + where: { statusCode: 'CANCELLED' }, + }); + if (!cancelledStatus) { + throw new common_1.InternalServerErrorException('CANCELLED status not found'); + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // Update correspondence revision status to CANCELLED + await queryRunner.manager.update(correspondence_revision_entity_1.CorrespondenceRevision, currentRevision.id, { + statusId: cancelledStatus.id, + remarks: `Cancelled: ${reason}`, + }); + // Force close all active circulations + if (activeCirculations.length > 0) { + await queryRunner.manager.update('Circulation', { + correspondenceId: correspondence.id, + status: 'OPEN', + }, { + status: 'FORCE_CLOSED', + closedAt: new Date(), + closedBy: user.user_id, + closeReason: `Correspondence cancelled: ${reason}`, + }); + } + await queryRunner.commitTransaction(); + // Re-index cancelled status in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: correspondence.id, + publicId: correspondence.publicId, + type: 'correspondence', + docNumber: correspondence.correspondenceNumber, + title: currentRevision.subject, + status: 'CANCELLED', + projectId: correspondence.projectId, + createdAt: correspondence.createdAt, + }); + // Notify originator's doc-control user about cancellation (fire-and-forget) + if (correspondence.originatorId) { + void this.userService + .findDocControlIdByOrg(correspondence.originatorId) + .then((targetUserId) => { + if (targetUserId) { + void this.notificationService.send({ + userId: targetUserId, + title: 'Correspondence Cancelled', + message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`, + type: 'EMAIL', + entityType: 'correspondence', + entityId: correspondence.id, + link: `/correspondences/${correspondence.publicId}`, + }); + } + }) + .catch((err) => this.logger.warn(`Cancel notification failed: ${err.message}`)); + } + return { + success: true, + message: warningMessage || 'Correspondence cancelled successfully', + activeCirculationsCount: activeCirculations.length, + }; + } + catch (error) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to cancel correspondence: ${error.message}`); + throw error; + } + finally { + await queryRunner.release(); + } + } + async bulkCancel(publicIds, reason, user) { + const succeeded = []; + const failed = []; + for (const publicId of publicIds) { + try { + await this.cancel(publicId, reason, user); + succeeded.push(publicId); + } + catch { + failed.push(publicId); + } + } + return { succeeded, failed }; + } + async exportCsv(searchDto) { + const { data } = await this.findAll(searchDto); + const header = [ + 'Document No.', + 'Rev', + 'Subject', + 'Type', + 'Status', + 'Project', + 'From', + 'Due Date', + 'Created At', + ]; + const rows = data.map((rev) => { + const corr = rev.correspondence ?? rev; + return [ + this.escapeCsv(corr.correspondenceNumber ?? ''), + this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)), + this.escapeCsv(rev.subject ?? ''), + this.escapeCsv(corr.type?.typeCode ?? ''), + this.escapeCsv(rev.status?.statusCode ?? ''), + this.escapeCsv(corr.project?.projectCode ?? ''), + this.escapeCsv(corr.originator?.organizationCode ?? ''), + rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '', + new Date(rev.createdAt).toISOString().split('T')[0], + ].join(','); + }); + return [header.join(','), ...rows].join('\n'); + } + escapeCsv(value) { + if (value.includes(',') || value.includes('"') || value.includes('\n')) { + return `"${value.replace(/"/g, '""')}"`; + } + return value; + } +}; +exports.CorrespondenceService = CorrespondenceService; +exports.CorrespondenceService = CorrespondenceService = CorrespondenceService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(correspondence_entity_1.Correspondence)), + __param(1, (0, typeorm_1.InjectRepository)(correspondence_revision_entity_1.CorrespondenceRevision)), + __param(2, (0, typeorm_1.InjectRepository)(correspondence_type_entity_1.CorrespondenceType)), + __param(3, (0, typeorm_1.InjectRepository)(correspondence_status_entity_1.CorrespondenceStatus)), + __param(4, (0, typeorm_1.InjectRepository)(correspondence_reference_entity_1.CorrespondenceReference)), + __param(5, (0, typeorm_1.InjectRepository)(correspondence_tag_entity_1.CorrespondenceTag)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object, typeof (_f = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _f : Object, typeof (_g = typeof document_numbering_service_1.DocumentNumberingService !== "undefined" && document_numbering_service_1.DocumentNumberingService) === "function" ? _g : Object, typeof (_h = typeof json_schema_service_1.JsonSchemaService !== "undefined" && json_schema_service_1.JsonSchemaService) === "function" ? _h : Object, typeof (_j = typeof workflow_engine_service_1.WorkflowEngineService !== "undefined" && workflow_engine_service_1.WorkflowEngineService) === "function" ? _j : Object, typeof (_k = typeof user_service_1.UserService !== "undefined" && user_service_1.UserService) === "function" ? _k : Object, typeof (_l = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _l : Object, typeof (_m = typeof search_service_1.SearchService !== "undefined" && search_service_1.SearchService) === "function" ? _m : Object, typeof (_o = typeof file_storage_service_1.FileStorageService !== "undefined" && file_storage_service_1.FileStorageService) === "function" ? _o : Object, typeof (_p = typeof uuid_resolver_service_1.UuidResolverService !== "undefined" && uuid_resolver_service_1.UuidResolverService) === "function" ? _p : Object, typeof (_q = typeof notification_service_1.NotificationService !== "undefined" && notification_service_1.NotificationService) === "function" ? _q : Object]) +], CorrespondenceService); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2UudHMiLCJtYXBwaW5ncyI6IjtBQUFBLDZEQUE2RDs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFN0QsMkNBT3dCO0FBQ3hCLDZDQUFtRDtBQUNuRCxxQ0FBaUQ7QUFFakQsV0FBVztBQUNYLDRFQUFrRTtBQUNsRSw4RkFBbUY7QUFDbkYsc0ZBQTJFO0FBQzNFLDBGQUErRTtBQUMvRSxnR0FBcUY7QUFDckYsZ0dBQXFGO0FBQ3JGLG9GQUF5RTtBQUN6RSw4REFBb0Q7QUFFcEQsc0ZBQTRFO0FBUTVFLFdBQVc7QUFDWCwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBVXBFLElBQU0scUJBQXFCLDZCQUEzQixNQUFNLHFCQUFxQjtJQUd4QixLQUFLLENBQUMsNEJBQTRCLENBQUMsTUFBYztRQUN2RCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEUsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVELFlBRUUsa0JBQXNELEVBRXRELFlBQXdELEVBRXhELFFBQWdELEVBRWhELFVBQW9ELEVBRXBELGFBQTBELEVBRTFELE9BQThDLEVBQ3RDLGdCQUEwQyxFQUMxQyxpQkFBb0MsRUFDcEMsY0FBcUMsRUFDckMsV0FBd0IsRUFDeEIsVUFBc0IsRUFDdEIsYUFBNEIsRUFDNUIsa0JBQXNDLEVBQ3RDLFlBQWlDLEVBQ2pDLG1CQUF3QztRQW5CeEMsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUE0QjtRQUU5QyxpQkFBWSxHQUFaLFlBQVksQ0FBb0M7UUFFaEQsYUFBUSxHQUFSLFFBQVEsQ0FBZ0M7UUFFeEMs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QkFBVSxvREFFZCxvQkFBVSxvQkFBVixvQkFBVSxvREFFUixvQkFBVSxvQkFBVixvQkFBVSxvREFFUCxvQkFBVSxvQkFBVixvQkFBVSxvREFFaEIsb0JBQVUsb0JBQVYsb0JBQVUsb0RBQ0QscURBQXdCLG9CQUF4QixxREFBd0Isb0RBQ3ZCLHVDQUFpQixvQkFBakIsdUNBQWlCLG9EQUNwQiwrQ0FBcUIsb0JBQXJCLCtDQUFxQixvREFDeEIsMEJBQVcsb0JBQVgsMEJBQVcsb0RBQ1osb0JBQVUsb0JBQVYsb0JBQVUsb0RBQ1AsOEJBQWEsb0JBQWIsOEJBQWEsb0RBQ1IseUNBQWtCLG9CQUFsQix5Q0FBa0Isb0RBQ3hCLDJDQUFtQixvQkFBbkIsMkNBQW1CLG9EQUNaLDBDQUFtQixvQkFBbkIsMENBQW1CO0dBN0J2QyxxQkFBcUIsQ0FxaUNqQyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJFOlxcbnAtZG1zXFxsY2JwM1xcYmFja2VuZFxcc3JjXFxtb2R1bGVzXFxjb3JyZXNwb25kZW5jZVxcY29ycmVzcG9uZGVuY2Uuc2VydmljZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBGaWxlOiBzcmMvbW9kdWxlcy9jb3JyZXNwb25kZW5jZS9jb3JyZXNwb25kZW5jZS5zZXJ2aWNlLnRzXHJcblxyXG5pbXBvcnQge1xyXG4gIEluamVjdGFibGUsXHJcbiAgTm90Rm91bmRFeGNlcHRpb24sXHJcbiAgQmFkUmVxdWVzdEV4Y2VwdGlvbixcclxuICBJbnRlcm5hbFNlcnZlckVycm9yRXhjZXB0aW9uLFxyXG4gIEZvcmJpZGRlbkV4Y2VwdGlvbixcclxuICBMb2dnZXIsXHJcbn0gZnJvbSAnQG5lc3Rqcy9jb21tb24nO1xyXG5pbXBvcnQgeyBJbmplY3RSZXBvc2l0b3J5IH0gZnJvbSAnQG5lc3Rqcy90eXBlb3JtJztcclxuaW1wb3J0IHsgUmVwb3NpdG9yeSwgRGF0YVNvdXJjZSB9IGZyb20gJ3R5cGVvcm0nO1xyXG5cclxuLy8gRW50aXRpZXNcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2UgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmV2aXNpb24gfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJldmlzaW9uLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVHlwZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtdHlwZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVN0YXR1cyB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2Utc3RhdHVzLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZWZlcmVuY2UuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VSZWNpcGllbnQgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJlY2lwaWVudC5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVRhZyB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtdGFnLmVudGl0eSc7XHJcbmltcG9ydCB7IFRhZyB9IGZyb20gJy4uL21hc3Rlci9lbnRpdGllcy90YWcuZW50aXR5JztcclxuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL3VzZXIvZW50aXRpZXMvdXNlci5lbnRpdHknO1xyXG5pbXBvcnQgeyBPcmdhbml6YXRpb24gfSBmcm9tICcuLi9vcmdhbml6YXRpb24vZW50aXRpZXMvb3JnYW5pemF0aW9uLmVudGl0eSc7XHJcblxyXG4vLyBEVE9zXHJcbmltcG9ydCB7IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vY3JlYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vdXBkYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IEFkZFJlZmVyZW5jZUR0byB9IGZyb20gJy4vZHRvL2FkZC1yZWZlcmVuY2UuZHRvJztcclxuaW1wb3J0IHsgU2VhcmNoQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by9zZWFyY2gtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuXHJcbi8vIFNlcnZpY2VzXHJcbmltcG9ydCB7IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSB9IGZyb20gJy4uL2RvY3VtZW50LW51bWJlcmluZy9zZXJ2aWNlcy9kb2N1bWVudC1udW1iZXJpbmcuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vanNvbi1zY2hlbWEvanNvbi1zY2hlbWEuc2VydmljZSc7XHJcbmltcG9ydCB7IFdvcmtmbG93RW5naW5lU2VydmljZSB9IGZyb20gJy4uL3dvcmtmbG93LWVuZ2luZS93b3JrZmxvdy1lbmdpbmUuc2VydmljZSc7XHJcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci91c2VyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vc2VhcmNoL3NlYXJjaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL2ZpbGUtc3RvcmFnZS9maWxlLXN0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IFV1aWRSZXNvbHZlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvdXVpZC1yZXNvbHZlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uc2VydmljZSc7XHJcblxyXG4vKipcclxuICogQ29ycmVzcG9uZGVuY2VTZXJ2aWNlIC0gRG9jdW1lbnQgbWFuYWdlbWVudCAoQ1JVRClcclxuICovXHJcbmludGVyZmFjZSBSZXNvbHZlZFJlY2lwaWVudCB7XHJcbiAgb3JnYW5pemF0aW9uSWQ6IG51bWJlcjtcclxuICB0eXBlOiAnVE8nIHwgJ0NDJztcclxufVxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBDb3JyZXNwb25kZW5jZVNlcnZpY2Uge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IExvZ2dlcihDb3JyZXNwb25kZW5jZVNlcnZpY2UubmFtZSk7XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgaGFzU3lzdGVtTWFuYWdlQWxsUGVybWlzc2lvbih1c2VySWQ6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyh1c2VySWQpO1xyXG4gICAgcmV0dXJuIHBlcm1pc3Npb25zLmluY2x1ZGVzKCdzeXN0ZW0ubWFuYWdlX2FsbCcpO1xyXG4gIH1cclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZSlcclxuICAgIHByaXZhdGUgY29ycmVzcG9uZGVuY2VSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlUmV2aXNpb24pXHJcbiAgICBwcml2YXRlIHJldmlzaW9uUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVJldmlzaW9uPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgIHByaXZhdGUgdHlwZVJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgcHJpdmF0ZSBzdGF0dXNSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlKVxyXG4gICAgcHJpdmF0ZSByZWZlcmVuY2VSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlVGFnKVxyXG4gICAgcHJpdmF0ZSB0YWdSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVGFnPixcclxuICAgIHByaXZhdGUgbnVtYmVyaW5nU2VydmljZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBqc29uU2NoZW1hU2VydmljZTogSnNvblNjaGVtYVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHdvcmtmbG93RW5naW5lOiBXb3JrZmxvd0VuZ2luZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHVzZXJTZXJ2aWNlOiBVc2VyU2VydmljZSxcclxuICAgIHByaXZhdGUgZGF0YVNvdXJjZTogRGF0YVNvdXJjZSxcclxuICAgIHByaXZhdGUgc2VhcmNoU2VydmljZTogU2VhcmNoU2VydmljZSxcclxuICAgIHByaXZhdGUgZmlsZVN0b3JhZ2VTZXJ2aWNlOiBGaWxlU3RvcmFnZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHV1aWRSZXNvbHZlcjogVXVpZFJlc29sdmVyU2VydmljZSxcclxuICAgIHByaXZhdGUgbm90aWZpY2F0aW9uU2VydmljZTogTm90aWZpY2F0aW9uU2VydmljZVxyXG4gICkge31cclxuXHJcbiAgLyoqXHJcbiAgICogQnVzaW5lc3MgUnVsZSBWYWxpZGF0aW9uOiBFQy1DT1JSLTAwMyAtIENvcnJlc3BvbmRlbmNlIHRvIFNlbGZcclxuICAgKiBQcmV2ZW50IGV4dGVybmFsIGNvcnJlc3BvbmRlbmNlIHRvIHNhbWUgb3JnYW5pemF0aW9uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhc3luYyB2YWxpZGF0ZUNvcnJlc3BvbmRlbmNlUmVjaXBpZW50cyhcclxuICAgIGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8sXHJcbiAgICB1c2VyOiBVc2VyXHJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAvLyBHZXQgdXNlcidzIG9yZ2FuaXphdGlvblxyXG4gICAgbGV0IHVzZXJPcmdJZCA9IHVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgY29uc3QgZnVsbFVzZXIgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmZpbmRPbmUodXNlci51c2VyX2lkKTtcclxuICAgICAgaWYgKGZ1bGxVc2VyKSB7XHJcbiAgICAgICAgdXNlck9yZ0lkID0gZnVsbFVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgaWYgKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpIHtcclxuICAgICAgICBjb25zdCBjYW5NYW5hZ2VBbGwgPSBhd2FpdCB0aGlzLmhhc1N5c3RlbU1hbmFnZUFsbFBlcm1pc3Npb24oXHJcbiAgICAgICAgICB1c2VyLnVzZXJfaWRcclxuICAgICAgICApO1xyXG4gICAgICAgIGlmIChjYW5NYW5hZ2VBbGwpIHtcclxuICAgICAgICAgIHVzZXJPcmdJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICAgICAgY3JlYXRlRHRvLm9yaWdpbmF0b3JJZFxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgICAnVXNlciBtdXN0IGJlbG9uZyB0byBhbiBvcmdhbml6YXRpb24gdG8gY3JlYXRlIGRvY3VtZW50cydcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9yIGltcGVyc29uYXRpb24sIHVzZSB0aGUgc3BlY2lmaWVkIG9yaWdpbmF0b3JcclxuICAgIGNvbnN0IG9yaWdpbmF0b3JPcmdJZCA9IGNyZWF0ZUR0by5vcmlnaW5hdG9ySWRcclxuICAgICAgPyBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoY3JlYXRlRHRvLm9yaWdpbmF0b3JJZClcclxuICAgICAgOiB1c2VyT3JnSWQ7XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgaXQncyBpbnRlcm5hbCBjb21tdW5pY2F0aW9uXHJcbiAgICBpZiAoY3JlYXRlRHRvLmlzSW50ZXJuYWwpIHtcclxuICAgICAgLy8gSW50ZXJuYWwgY29tbXVuaWNhdGlvbnMgc2hvdWxkIHVzZSBDaXJjdWxhdGlvbiBpbnN0ZWFkXHJcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICdJbnRlcm5hbCBjb21tdW5pY2F0aW9ucyBzaG91bGQgdXNlIENpcmN1bGF0aW9uIFNoZWV0IGluc3RlYWQgb2YgQ29ycmVzcG9uZGVuY2UnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVmFsaWRhdGUgcmVjaXBpZW50c1xyXG4gICAgaWYgKCFjcmVhdGVEdG8ucmVjaXBpZW50cyB8fCBjcmVhdGVEdG8ucmVjaXBpZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgJ0F0IGxlYXN0IG9uZSByZWNpcGllbnQgKFRPIG9yIENDKSBpcyByZXF1aXJlZCdcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB0b1JlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50cy5maWx0ZXIoKHIpID0+IHIudHlwZSA9PT0gJ1RPJyk7XHJcbiAgICBjb25zdCBjY1JlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50cy5maWx0ZXIoKHIpID0+IHIudHlwZSA9PT0gJ0NDJyk7XHJcblxyXG4gICAgaWYgKHRvUmVjaXBpZW50cy5sZW5ndGggPT09IDAgJiYgY2NSZWNpcGllbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcclxuICAgICAgICAnQXQgbGVhc3Qgb25lIFRPIG9yIENDIHJlY2lwaWVudCBpcyByZXF1aXJlZCdcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDaGVjayBmb3Igc2FtZSBvcmdhbml6YXRpb24gY29ycmVzcG9uZGVuY2VcclxuICAgIGZvciAoY29uc3QgcmVjaXBpZW50IG9mIGNyZWF0ZUR0by5yZWNpcGllbnRzKSB7XHJcbiAgICAgIGNvbnN0IHJlY2lwaWVudE9yZ0lkID0gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKFxyXG4gICAgICAgIHJlY2lwaWVudC5vcmdhbml6YXRpb25JZFxyXG4gICAgICApO1xyXG5cclxuICAgICAgaWYgKHJlY2lwaWVudE9yZ0lkID09PSBvcmlnaW5hdG9yT3JnSWQpIHtcclxuICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcclxuICAgICAgICAgICdDYW5ub3Qgc2VuZCBjb3JyZXNwb25kZW5jZSB0byB5b3VyIG93biBvcmdhbml6YXRpb24uIFVzZSBDaXJjdWxhdGlvbiBTaGVldCBmb3IgaW50ZXJuYWwgY29tbXVuaWNhdGlvbi4nXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgY3JlYXRlKGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8sIHVzZXI6IFVzZXIpIHtcclxuICAgIC8vIEJ1c2luZXNzIFJ1bGUgVmFsaWRhdGlvbjogRUMtQ09SUi0wMDMgLSBDb3JyZXNwb25kZW5jZSB0byBTZWxmXHJcbiAgICBhd2FpdCB0aGlzLnZhbGlkYXRlQ29ycmVzcG9uZGVuY2VSZWNpcGllbnRzKGNyZWF0ZUR0bywgdXNlcik7XHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIFVVSUQgcmVmZXJlbmNlcyB0byBpbnRlcm5hbCBJTlQgSURzXHJcbiAgICBjb25zdCByZXNvbHZlZFByb2plY3RJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQoXHJcbiAgICAgIGNyZWF0ZUR0by5wcm9qZWN0SWRcclxuICAgICk7XHJcbiAgICBjb25zdCByZXNvbHZlZE9yaWdpbmF0b3JJZCA9IGNyZWF0ZUR0by5vcmlnaW5hdG9ySWRcclxuICAgICAgPyBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoY3JlYXRlRHRvLm9yaWdpbmF0b3JJZClcclxuICAgICAgOiB1bmRlZmluZWQ7XHJcbiAgICBjb25zdCByZXNvbHZlZFJlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50c1xyXG4gICAgICA/IGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgY3JlYXRlRHRvLnJlY2lwaWVudHMubWFwKFxyXG4gICAgICAgICAgICBhc3luYyAocik6IFByb21pc2U8UmVzb2x2ZWRSZWNpcGllbnQ+ID0+ICh7XHJcbiAgICAgICAgICAgICAgb3JnYW5pemF0aW9uSWQ6IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICAgICAgICAgIHIub3JnYW5pemF0aW9uSWRcclxuICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgICAgIHR5cGU6IHIudHlwZSxcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgIClcclxuICAgICAgICApXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgdHlwZSA9IGF3YWl0IHRoaXMudHlwZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGlkOiBjcmVhdGVEdG8udHlwZUlkIH0sXHJcbiAgICB9KTtcclxuICAgIGlmICghdHlwZSkgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdEb2N1bWVudCBUeXBlIG5vdCBmb3VuZCcpO1xyXG5cclxuICAgIGNvbnN0IHN0YXR1c0RyYWZ0ID0gYXdhaXQgdGhpcy5zdGF0dXNSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBzdGF0dXNDb2RlOiAnRFJBRlQnIH0sXHJcbiAgICB9KTtcclxuICAgIGlmICghc3RhdHVzRHJhZnQpIHtcclxuICAgICAgdGhyb3cgbmV3IEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24oXHJcbiAgICAgICAgJ1N0YXR1cyBEUkFGVCBub3QgZm91bmQgaW4gTWFzdGVyIERhdGEnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHVzZXJPcmdJZCA9IHVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG5cclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIGNvbnN0IGZ1bGxVc2VyID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5maW5kT25lKHVzZXIudXNlcl9pZCk7XHJcbiAgICAgIGlmIChmdWxsVXNlcikge1xyXG4gICAgICAgIHVzZXJPcmdJZCA9IGZ1bGxVc2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIEltcGVyc29uYXRpb24gTG9naWNcclxuICAgIGlmIChyZXNvbHZlZE9yaWdpbmF0b3JJZCAmJiByZXNvbHZlZE9yaWdpbmF0b3JJZCAhPT0gdXNlck9yZ0lkKSB7XHJcbiAgICAgIGNvbnN0IGNhbk1hbmFnZUFsbCA9IGF3YWl0IHRoaXMuaGFzU3lzdGVtTWFuYWdlQWxsUGVybWlzc2lvbihcclxuICAgICAgICB1c2VyLnVzZXJfaWRcclxuICAgICAgKTtcclxuICAgICAgaWYgKCFjYW5NYW5hZ2VBbGwpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRm9yYmlkZGVuRXhjZXB0aW9uKFxyXG4gICAgICAgICAgJ1lvdSBkbyBub3QgaGF2ZSBwZXJtaXNzaW9uIHRvIGNyZWF0ZSBkb2N1bWVudHMgb24gYmVoYWxmIG9mIG90aGVyIG9yZ2FuaXphdGlvbnMuJ1xyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgICAgdXNlck9yZ0lkID0gcmVzb2x2ZWRPcmlnaW5hdG9ySWQ7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgJ1VzZXIgbXVzdCBiZWxvbmcgdG8gYW4gb3JnYW5pemF0aW9uIHRvIGNyZWF0ZSBkb2N1bWVudHMnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNyZWF0ZUR0by5kZXRhaWxzKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5qc29uU2NoZW1hU2VydmljZS52YWxpZGF0ZSh0eXBlLnR5cGVDb2RlLCBjcmVhdGVEdG8uZGV0YWlscyk7XHJcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XHJcbiAgICAgICAgdGhpcy5sb2dnZXIud2FybihcclxuICAgICAgICAgIGBTY2hlbWEgdmFsaWRhdGlvbiB3YXJuaW5nIGZvciAke3R5cGUudHlwZUNvZGV9OiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0gdGhpcy5kYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyKCk7XHJcbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5jb25uZWN0KCk7XHJcbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5zdGFydFRyYW5zYWN0aW9uKCk7XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgLy8gW0ZpeCAjNl0gRmV0Y2ggcmVhbCBPUkcgQ29kZSBmcm9tIE9yZ2FuaXphdGlvbiBlbnRpdHlcclxuICAgICAgY29uc3Qgb3JpZ2luYXRvck9yZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoXHJcbiAgICAgICAgT3JnYW5pemF0aW9uLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHdoZXJlOiB7IGlkOiB1c2VyT3JnSWQgfSxcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IG9yZ0NvZGUgPSBvcmlnaW5hdG9yT3JnPy5vcmdhbml6YXRpb25Db2RlID8/ICdVTksnO1xyXG5cclxuICAgICAgLy8gW3YxLjUuMV0gRXh0cmFjdCByZWNpcGllbnQgb3JnYW5pemF0aW9uIGZyb20gcmVjaXBpZW50cyBhcnJheSAoUHJpbWFyeSBUTylcclxuICAgICAgY29uc3QgdG9SZWNpcGllbnQgPSByZXNvbHZlZFJlY2lwaWVudHM/LmZpbmQoKHIpID0+IHIudHlwZSA9PT0gJ1RPJyk7XHJcbiAgICAgIGNvbnN0IHJlY2lwaWVudE9yZ2FuaXphdGlvbklkID0gdG9SZWNpcGllbnQ/Lm9yZ2FuaXphdGlvbklkO1xyXG5cclxuICAgICAgbGV0IHJlY2lwaWVudENvZGUgPSAnJztcclxuICAgICAgaWYgKHJlY2lwaWVudE9yZ2FuaXphdGlvbklkKSB7XHJcbiAgICAgICAgY29uc3QgcmVjT3JnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShPcmdhbml6YXRpb24sIHtcclxuICAgICAgICAgIHdoZXJlOiB7IGlkOiByZWNpcGllbnRPcmdhbml6YXRpb25JZCB9LFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmIChyZWNPcmcpIHJlY2lwaWVudENvZGUgPSByZWNPcmcub3JnYW5pemF0aW9uQ29kZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgZG9jTnVtYmVyID0gYXdhaXQgdGhpcy5udW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlcih7XHJcbiAgICAgICAgcHJvamVjdElkOiByZXNvbHZlZFByb2plY3RJZCxcclxuICAgICAgICBvcmlnaW5hdG9yT3JnYW5pemF0aW9uSWQ6IHVzZXJPcmdJZCxcclxuICAgICAgICB0eXBlSWQ6IGNyZWF0ZUR0by50eXBlSWQsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiBjcmVhdGVEdG8uZGlzY2lwbGluZUlkLFxyXG4gICAgICAgIHN1YlR5cGVJZDogY3JlYXRlRHRvLnN1YlR5cGVJZCxcclxuICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZCwgLy8gW3YxLjUuMV0gUGFzcyByZWNpcGllbnQgZm9yIGRvY3VtZW50IG51bWJlciBmb3JtYXRcclxuICAgICAgICB5ZWFyOiBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCksXHJcbiAgICAgICAgY3VzdG9tVG9rZW5zOiB7XHJcbiAgICAgICAgICBUWVBFX0NPREU6IHR5cGUudHlwZUNvZGUsXHJcbiAgICAgICAgICBPUkdfQ09ERTogb3JnQ29kZSxcclxuICAgICAgICAgIFJFQ0lQSUVOVF9DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgICAgUkVDX0NPREU6IHJlY2lwaWVudENvZGUsXHJcbiAgICAgICAgfSxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKENvcnJlc3BvbmRlbmNlLCB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6IGRvY051bWJlci5udW1iZXIsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IGNyZWF0ZUR0by50eXBlSWQsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiBjcmVhdGVEdG8uZGlzY2lwbGluZUlkLFxyXG4gICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiB1c2VyT3JnSWQsXHJcbiAgICAgICAgaXNJbnRlcm5hbDogY3JlYXRlRHRvLmlzSW50ZXJuYWwgfHwgZmFsc2UsXHJcbiAgICAgICAgY3JlYXRlZEJ5OiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgIH0pO1xyXG4gICAgICBjb25zdCBzYXZlZENvcnIgPSBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnNhdmUoY29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgcmV2aXNpb24gPSBxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZShDb3JyZXNwb25kZW5jZVJldmlzaW9uLCB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogc2F2ZWRDb3JyLmlkLFxyXG4gICAgICAgIHJldmlzaW9uTnVtYmVyOiAwLFxyXG4gICAgICAgIHJldmlzaW9uTGFiZWw6ICdBJyxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IHN0YXR1c0RyYWZ0LmlkLFxyXG4gICAgICAgIHN1YmplY3Q6IGNyZWF0ZUR0by5zdWJqZWN0LFxyXG4gICAgICAgIGJvZHk6IGNyZWF0ZUR0by5ib2R5LFxyXG4gICAgICAgIHJlbWFya3M6IGNyZWF0ZUR0by5yZW1hcmtzLFxyXG4gICAgICAgIGR1ZURhdGU6IGNyZWF0ZUR0by5kdWVEYXRlID8gbmV3IERhdGUoY3JlYXRlRHRvLmR1ZURhdGUpIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIGRvY3VtZW50RGF0ZTogY3JlYXRlRHRvLmRvY3VtZW50RGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICAgICAgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgaXNzdWVkRGF0ZTogY3JlYXRlRHRvLmlzc3VlZERhdGVcclxuICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcclxuICAgICAgICByZWNlaXZlZERhdGU6IGNyZWF0ZUR0by5yZWNlaXZlZERhdGVcclxuICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLnJlY2VpdmVkRGF0ZSlcclxuICAgICAgICAgIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIGRlc2NyaXB0aW9uOiBjcmVhdGVEdG8uZGVzY3JpcHRpb24sXHJcbiAgICAgICAgZGV0YWlsczogY3JlYXRlRHRvLmRldGFpbHMsXHJcbiAgICAgICAgY3JlYXRlZEJ5OiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgICAgc2NoZW1hVmVyc2lvbjogMSxcclxuICAgICAgfSk7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIuc2F2ZShyZXZpc2lvbik7XHJcblxyXG4gICAgICAvLyBTYXZlIFJlY2lwaWVudHMgKHVzaW5nIHJlc29sdmVkIElOVCBJRHMpXHJcbiAgICAgIGlmIChyZXNvbHZlZFJlY2lwaWVudHMgJiYgcmVzb2x2ZWRSZWNpcGllbnRzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBjb25zdCByZWNpcGllbnRzID0gcmVzb2x2ZWRSZWNpcGllbnRzLm1hcCgocikgPT5cclxuICAgICAgICAgIHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKENvcnJlc3BvbmRlbmNlUmVjaXBpZW50LCB7XHJcbiAgICAgICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IHNhdmVkQ29yci5pZCxcclxuICAgICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IHIub3JnYW5pemF0aW9uSWQsXHJcbiAgICAgICAgICAgIHJlY2lwaWVudFR5cGU6IHIudHlwZSxcclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgICAgICBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnNhdmUocmVjaXBpZW50cyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIENvbW1pdCBhdHRhY2htZW50cyBmcm9tIFRlbXAg4oaSIFBlcm1hbmVudCAoVHdvLVBoYXNlIFN0b3JhZ2UpXHJcbiAgICAgIGlmIChjcmVhdGVEdG8uYXR0YWNobWVudFRlbXBJZHM/Lmxlbmd0aCkge1xyXG4gICAgICAgIGNvbnN0IGlzc3VlRGF0ZSA9IGNyZWF0ZUR0by5pc3N1ZWREYXRlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKGNyZWF0ZUR0by5pc3N1ZWREYXRlKVxyXG4gICAgICAgICAgOiBjcmVhdGVEdG8uZG9jdW1lbnREYXRlXHJcbiAgICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLmRvY3VtZW50RGF0ZSlcclxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XHJcblxyXG4gICAgICAgIGF3YWl0IHRoaXMuZmlsZVN0b3JhZ2VTZXJ2aWNlLmNvbW1pdChjcmVhdGVEdG8uYXR0YWNobWVudFRlbXBJZHMsIHtcclxuICAgICAgICAgIGlzc3VlRGF0ZSxcclxuICAgICAgICAgIGRvY3VtZW50VHlwZTogJ0NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIuY29tbWl0VHJhbnNhY3Rpb24oKTtcclxuXHJcbiAgICAgIC8vIFN0YXJ0IFdvcmtmbG93IEluc3RhbmNlIChub24tYmxvY2tpbmcpXHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3Qgd29ya2Zsb3dDb2RlID0gYENPUlJFU1BPTkRFTkNFXyR7dHlwZS50eXBlQ29kZX1gO1xyXG4gICAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dFbmdpbmUuY3JlYXRlSW5zdGFuY2UoXHJcbiAgICAgICAgICB3b3JrZmxvd0NvZGUsXHJcbiAgICAgICAgICAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgICAgc2F2ZWRDb3JyLmlkLnRvU3RyaW5nKCksXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgICAgIG9yaWdpbmF0b3JJZDogdXNlck9yZ0lkLFxyXG4gICAgICAgICAgICBkaXNjaXBsaW5lSWQ6IGNyZWF0ZUR0by5kaXNjaXBsaW5lSWQsXHJcbiAgICAgICAgICAgIGluaXRpYXRvcklkOiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgICAgICB9IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+XHJcbiAgICAgICAgKTtcclxuICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcclxuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFxyXG4gICAgICAgICAgYFdvcmtmbG93IG5vdCBzdGFydGVkIGZvciAke2RvY051bWJlci5udW1iZXJ9IChDb2RlOiBDT1JSRVNQT05ERU5DRV8ke3R5cGUudHlwZUNvZGV9KTogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIEZpcmUtYW5kLWZvcmdldCBzZWFyY2ggaW5kZXhpbmcgKG5vbi1ibG9ja2luZywgdm9pZCBpbnRlbnRpb25hbClcclxuICAgICAgdm9pZCB0aGlzLnNlYXJjaFNlcnZpY2UuaW5kZXhEb2N1bWVudCh7XHJcbiAgICAgICAgaWQ6IHNhdmVkQ29yci5pZCxcclxuICAgICAgICBwdWJsaWNJZDogc2F2ZWRDb3JyLnB1YmxpY0lkLFxyXG4gICAgICAgIHR5cGU6ICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgICAgZG9jTnVtYmVyOiBkb2NOdW1iZXIubnVtYmVyLFxyXG4gICAgICAgIHRpdGxlOiBjcmVhdGVEdG8uc3ViamVjdCxcclxuICAgICAgICBkZXNjcmlwdGlvbjogY3JlYXRlRHRvLmRlc2NyaXB0aW9uLFxyXG4gICAgICAgIHN0YXR1czogJ0RSQUZUJyxcclxuICAgICAgICBwcm9qZWN0SWQ6IHJlc29sdmVkUHJvamVjdElkLFxyXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKSxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIC4uLnNhdmVkQ29ycixcclxuICAgICAgICBjdXJyZW50UmV2aXNpb246IHJldmlzaW9uLFxyXG4gICAgICB9O1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcclxuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXHJcbiAgICAgICAgYEZhaWxlZCB0byBjcmVhdGUgY29ycmVzcG9uZGVuY2U6ICR7KGVyciBhcyBFcnJvcikubWVzc2FnZX1gXHJcbiAgICAgICk7XHJcbiAgICAgIHRocm93IGVycjtcclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJlbGVhc2UoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGZpbmRBbGwoc2VhcmNoRHRvOiBTZWFyY2hDb3JyZXNwb25kZW5jZUR0byA9IHt9KSB7XHJcbiAgICBjb25zdCB7XHJcbiAgICAgIHNlYXJjaCxcclxuICAgICAgdHlwZUlkLFxyXG4gICAgICBwcm9qZWN0SWQsXHJcbiAgICAgIHN0YXR1c0lkLFxyXG4gICAgICBzdGF0dXMsXHJcbiAgICAgIHBhZ2UgPSAxLFxyXG4gICAgICBsaW1pdCA9IDEwLFxyXG4gICAgfSA9IHNlYXJjaER0bztcclxuICAgIGNvbnN0IHNraXAgPSAocGFnZSAtIDEpICogbGltaXQ7XHJcblxyXG4gICAgLy8gQ2hhbmdlOiBRdWVyeSBmcm9tIFJldmlzaW9uIFJlcG9cclxuICAgIGNvbnN0IHF1ZXJ5ID0gdGhpcy5yZXZpc2lvblJlcG9cclxuICAgICAgLmNyZWF0ZVF1ZXJ5QnVpbGRlcigncmV2JylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdyZXYuY29ycmVzcG9uZGVuY2UnLCAnY29ycicpXHJcbiAgICAgIC5sZWZ0Sm9pbkFuZFNlbGVjdCgnY29yci50eXBlJywgJ3R5cGUnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ2NvcnIucHJvamVjdCcsICdwcm9qZWN0JylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdjb3JyLm9yaWdpbmF0b3InLCAnb3JnJylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdyZXYuc3RhdHVzJywgJ3N0YXR1cycpO1xyXG5cclxuICAgIC8vIEZpbHRlciBieSBSZXZpc2lvbiBTdGF0dXNcclxuICAgIGNvbnN0IHJldlN0YXR1cyA9IHNlYXJjaER0by5yZXZpc2lvblN0YXR1cyB8fCAnQ1VSUkVOVCc7XHJcblxyXG4gICAgaWYgKHJldlN0YXR1cyA9PT0gJ0NVUlJFTlQnKSB7XHJcbiAgICAgIHF1ZXJ5LndoZXJlKCdyZXYuaXNDdXJyZW50ID0gOmlzQ3VycmVudCcsIHsgaXNDdXJyZW50OiB0cnVlIH0pO1xyXG4gICAgfSBlbHNlIGlmIChyZXZTdGF0dXMgPT09ICdPTEQnKSB7XHJcbiAgICAgIHF1ZXJ5LndoZXJlKCdyZXYuaXNDdXJyZW50ID0gOmlzQ3VycmVudCcsIHsgaXNDdXJyZW50OiBmYWxzZSB9KTtcclxuICAgIH1cclxuICAgIC8vIElmICdBTEwnLCBubyBmaWx0ZXIgbmVlZGVkIG9uIGlzQ3VycmVudFxyXG5cclxuICAgIGlmIChwcm9qZWN0SWQpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ2NvcnIucHJvamVjdElkID0gOnByb2plY3RJZCcsIHsgcHJvamVjdElkIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlSWQpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ2NvcnIuY29ycmVzcG9uZGVuY2VUeXBlSWQgPSA6dHlwZUlkJywgeyB0eXBlSWQgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHN0YXR1c0lkKSB7XHJcbiAgICAgIHF1ZXJ5LmFuZFdoZXJlKCdyZXYuc3RhdHVzSWQgPSA6c3RhdHVzSWQnLCB7IHN0YXR1c0lkIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChzdGF0dXMpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ3N0YXR1cy5zdGF0dXNDb2RlID0gOnN0YXR1cycsIHsgc3RhdHVzIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChzZWFyY2gpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoXHJcbiAgICAgICAgJyhjb3JyLmNvcnJlc3BvbmRlbmNlTnVtYmVyIExJS0UgOnNlYXJjaCBPUiByZXYuc3ViamVjdCBMSUtFIDpzZWFyY2gpJyxcclxuICAgICAgICB7IHNlYXJjaDogYCUke3NlYXJjaH0lYCB9XHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRGVmYXVsdCBTb3J0OiBMYXRlc3QgQ3JlYXRlZFxyXG4gICAgcXVlcnkub3JkZXJCeSgncmV2LmNyZWF0ZWRBdCcsICdERVNDJykuc2tpcChza2lwKS50YWtlKGxpbWl0KTtcclxuXHJcbiAgICBjb25zdCBbaXRlbXMsIHRvdGFsXSA9IGF3YWl0IHF1ZXJ5LmdldE1hbnlBbmRDb3VudCgpO1xyXG5cclxuICAgIHJldHVybiB7XHJcbiAgICAgIGRhdGE6IGl0ZW1zLFxyXG4gICAgICBtZXRhOiB7XHJcbiAgICAgICAgdG90YWwsXHJcbiAgICAgICAgcGFnZSxcclxuICAgICAgICBsaW1pdCxcclxuICAgICAgICB0b3RhbFBhZ2VzOiBNYXRoLmNlaWwodG90YWwgLyBsaW1pdCksXHJcbiAgICAgIH0sXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZmluZE9uZShpZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFtcclxuICAgICAgICAncmV2aXNpb25zJyxcclxuICAgICAgICAncmV2aXNpb25zLnN0YXR1cycsXHJcbiAgICAgICAgJ3R5cGUnLFxyXG4gICAgICAgICdwcm9qZWN0JyxcclxuICAgICAgICAnb3JpZ2luYXRvcicsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMnLFxyXG4gICAgICAgICdyZWNpcGllbnRzLnJlY2lwaWVudE9yZ2FuaXphdGlvbicsIC8vIFt2MS41LjFdIEZpeGVkIHJlbGF0aW9uIG5hbWVcclxuICAgICAgXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghY29ycmVzcG9uZGVuY2UpIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKGBDb3JyZXNwb25kZW5jZSB3aXRoIElEICR7aWR9IG5vdCBmb3VuZGApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGNvcnJlc3BvbmRlbmNlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZmluZE9uZUJ5VXVpZChwdWJsaWNJZDogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBwdWJsaWNJZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFtcclxuICAgICAgICAncmV2aXNpb25zJyxcclxuICAgICAgICAncmV2aXNpb25zLnN0YXR1cycsXHJcbiAgICAgICAgJ3R5cGUnLFxyXG4gICAgICAgICdwcm9qZWN0JyxcclxuICAgICAgICAnb3JpZ2luYXRvcicsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMnLFxyXG4gICAgICAgICdyZWNpcGllbnRzLnJlY2lwaWVudE9yZ2FuaXphdGlvbicsXHJcbiAgICAgIF0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIWNvcnJlc3BvbmRlbmNlKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihcclxuICAgICAgICBgQ29ycmVzcG9uZGVuY2Ugd2l0aCBVVUlEICR7cHVibGljSWR9IG5vdCBmb3VuZGBcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIHJldHVybiBjb3JyZXNwb25kZW5jZTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGFkZFJlZmVyZW5jZShpZDogbnVtYmVyLCBkdG86IEFkZFJlZmVyZW5jZUR0bykge1xyXG4gICAgY29uc3Qgc291cmNlID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7IHdoZXJlOiB7IGlkIH0gfSk7XHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIHRhcmdldCBwdWJsaWNJZCDihpIgaW50ZXJuYWwgSU5UIGlkXHJcbiAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgcHVibGljSWQ6IGR0by50YXJnZXRVdWlkIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIXNvdXJjZSB8fCAhdGFyZ2V0KSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignU291cmNlIG9yIFRhcmdldCBjb3JyZXNwb25kZW5jZSBub3QgZm91bmQnKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoc291cmNlLmlkID09PSB0YXJnZXQuaWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oJ0Nhbm5vdCByZWZlcmVuY2Ugc2VsZicpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGV4aXN0cyA9IGF3YWl0IHRoaXMucmVmZXJlbmNlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHtcclxuICAgICAgICBzb3VyY2VJZDogaWQsXHJcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldC5pZCxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChleGlzdHMpIHtcclxuICAgICAgcmV0dXJuIGV4aXN0cztcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCByZWYgPSB0aGlzLnJlZmVyZW5jZVJlcG8uY3JlYXRlKHtcclxuICAgICAgc291cmNlSWQ6IGlkLFxyXG4gICAgICB0YXJnZXRJZDogdGFyZ2V0LmlkLFxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMucmVmZXJlbmNlUmVwby5zYXZlKHJlZik7XHJcbiAgfVxyXG5cclxuICBhc3luYyByZW1vdmVSZWZlcmVuY2UoaWQ6IG51bWJlciwgdGFyZ2V0SWQ6IG51bWJlcikge1xyXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmRlbGV0ZSh7XHJcbiAgICAgIHNvdXJjZUlkOiBpZCxcclxuICAgICAgdGFyZ2V0SWQ6IHRhcmdldElkLFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKHJlc3VsdC5hZmZlY3RlZCA9PT0gMCkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ1JlZmVyZW5jZSBub3QgZm91bmQnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGdldFRhZ3MoaWQ6IG51bWJlcikge1xyXG4gICAgY29uc3Qgcm93cyA9IGF3YWl0IHRoaXMudGFnUmVwby5maW5kKHtcclxuICAgICAgd2hlcmU6IHsgY29ycmVzcG9uZGVuY2VJZDogaWQgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ3RhZyddLFxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gcm93cy5tYXAoKHIpID0+IHIudGFnKS5maWx0ZXIoQm9vbGVhbik7XHJcbiAgfVxyXG5cclxuICBhc3luYyBhZGRUYWcoaWQ6IG51bWJlciwgdGFnSWQ6IG51bWJlcikge1xyXG4gICAgY29uc3QgY29ycmVzcG9uZGVuY2UgPSBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgaWQgfSxcclxuICAgIH0pO1xyXG4gICAgaWYgKCFjb3JyZXNwb25kZW5jZSkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oYENvcnJlc3BvbmRlbmNlICR7aWR9IG5vdCBmb3VuZGApO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHRhZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoVGFnLCB7XHJcbiAgICAgIHdoZXJlOiB7IGlkOiB0YWdJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXRhZykge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oYFRhZyAke3RhZ0lkfSBub3QgZm91bmRgKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBleGlzdHMgPSBhd2FpdCB0aGlzLnRhZ1JlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGNvcnJlc3BvbmRlbmNlSWQ6IGlkLCB0YWdJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoZXhpc3RzKSByZXR1cm4gZXhpc3RzO1xyXG5cclxuICAgIGNvbnN0IHJvdyA9IHRoaXMudGFnUmVwby5jcmVhdGUoeyBjb3JyZXNwb25kZW5jZUlkOiBpZCwgdGFnSWQgfSk7XHJcbiAgICByZXR1cm4gdGhpcy50YWdSZXBvLnNhdmUocm93KTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHJlbW92ZVRhZyhpZDogbnVtYmVyLCB0YWdJZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnRhZ1JlcG8uZGVsZXRlKHsgY29ycmVzcG9uZGVuY2VJZDogaWQsIHRhZ0lkIH0pO1xyXG4gICAgaWYgKHJlc3VsdC5hZmZlY3RlZCA9PT0gMCkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ1RhZyBhc3NpZ25tZW50IG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgZ2V0UmVmZXJlbmNlcyhpZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBvdXRnb2luZyA9IGF3YWl0IHRoaXMucmVmZXJlbmNlUmVwby5maW5kKHtcclxuICAgICAgd2hlcmU6IHsgc291cmNlSWQ6IGlkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogWyd0YXJnZXQnLCAndGFyZ2V0LnR5cGUnXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IGluY29taW5nID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmZpbmQoe1xyXG4gICAgICB3aGVyZTogeyB0YXJnZXRJZDogaWQgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ3NvdXJjZScsICdzb3VyY2UudHlwZSddLFxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHsgb3V0Z29pbmcsIGluY29taW5nIH07XHJcbiAgfVxyXG5cclxuICBhc3luYyB1cGRhdGUoaWQ6IG51bWJlciwgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0bywgdXNlcjogVXNlcikge1xyXG4gICAgLy8gMS4gRmluZCBDdXJyZW50IFJldmlzaW9uXHJcbiAgICBjb25zdCByZXZpc2lvbiA9IGF3YWl0IHRoaXMucmV2aXNpb25SZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZToge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGlkLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ2NvcnJlc3BvbmRlbmNlJ10sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIXJldmlzaW9uKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihcclxuICAgICAgICBgQ3VycmVudCByZXZpc2lvbiBmb3IgY29ycmVzcG9uZGVuY2UgJHtpZH0gbm90IGZvdW5kYFxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDIuIENoZWNrIFBlcm1pc3Npb25cclxuICAgIGlmIChyZXZpc2lvbi5zdGF0dXNJZCkge1xyXG4gICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCB0aGlzLnN0YXR1c1JlcG8uZmluZE9uZSh7XHJcbiAgICAgICAgd2hlcmU6IHsgaWQ6IHJldmlzaW9uLnN0YXR1c0lkIH0sXHJcbiAgICAgIH0pO1xyXG4gICAgICBpZiAoc3RhdHVzICYmIHN0YXR1cy5zdGF0dXNDb2RlICE9PSAnRFJBRlQnKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oJ09ubHkgRFJBRlQgZG9jdW1lbnRzIGNhbiBiZSB1cGRhdGVkJyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIFVVSUQgcmVmZXJlbmNlcyBpbiB1cGRhdGUgRFRPXHJcbiAgICBjb25zdCB1cGRSZXNvbHZlZFByb2plY3RJZCA9IHVwZGF0ZUR0by5wcm9qZWN0SWRcclxuICAgICAgPyBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkKHVwZGF0ZUR0by5wcm9qZWN0SWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgdXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQgPSB1cGRhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKHVwZGF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgdXBkUmVzb2x2ZWRSZWNpcGllbnRzID0gdXBkYXRlRHRvLnJlY2lwaWVudHNcclxuICAgICAgPyBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgIHVwZGF0ZUR0by5yZWNpcGllbnRzLm1hcChcclxuICAgICAgICAgICAgYXN5bmMgKHIpOiBQcm9taXNlPFJlc29sdmVkUmVjaXBpZW50PiA9PiAoe1xyXG4gICAgICAgICAgICAgIG9yZ2FuaXphdGlvbklkOiBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgICAgICByLm9yZ2FuaXphdGlvbklkXHJcbiAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICB0eXBlOiByLnR5cGUsXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICAvLyAzLiBVcGRhdGUgQ29ycmVzcG9uZGVuY2UgRW50aXR5IGlmIG5lZWRlZFxyXG4gICAgY29uc3QgY29ycmVzcG9uZGVuY2VVcGRhdGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XHJcbiAgICBpZiAodXBkYXRlRHRvLmRpc2NpcGxpbmVJZClcclxuICAgICAgY29ycmVzcG9uZGVuY2VVcGRhdGUuZGlzY2lwbGluZUlkID0gdXBkYXRlRHRvLmRpc2NpcGxpbmVJZDtcclxuICAgIGlmICh1cGRSZXNvbHZlZFByb2plY3RJZClcclxuICAgICAgY29ycmVzcG9uZGVuY2VVcGRhdGUucHJvamVjdElkID0gdXBkUmVzb2x2ZWRQcm9qZWN0SWQ7XHJcbiAgICBpZiAodXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQpXHJcbiAgICAgIGNvcnJlc3BvbmRlbmNlVXBkYXRlLm9yaWdpbmF0b3JJZCA9IHVwZFJlc29sdmVkT3JpZ2luYXRvcklkO1xyXG5cclxuICAgIGlmIChPYmplY3Qua2V5cyhjb3JyZXNwb25kZW5jZVVwZGF0ZSkubGVuZ3RoID4gMCkge1xyXG4gICAgICBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby51cGRhdGUoaWQsIGNvcnJlc3BvbmRlbmNlVXBkYXRlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA0LiBVcGRhdGUgUmV2aXNpb24gRW50aXR5XHJcbiAgICBjb25zdCByZXZpc2lvblVwZGF0ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcclxuICAgIGlmICh1cGRhdGVEdG8uc3ViamVjdCkgcmV2aXNpb25VcGRhdGUuc3ViamVjdCA9IHVwZGF0ZUR0by5zdWJqZWN0O1xyXG4gICAgaWYgKHVwZGF0ZUR0by5ib2R5KSByZXZpc2lvblVwZGF0ZS5ib2R5ID0gdXBkYXRlRHRvLmJvZHk7XHJcbiAgICBpZiAodXBkYXRlRHRvLnJlbWFya3MpIHJldmlzaW9uVXBkYXRlLnJlbWFya3MgPSB1cGRhdGVEdG8ucmVtYXJrcztcclxuICAgIC8vIEZvcm1hdCBEYXRlIGNvcnJlY3RseSBpZiBzdHJpbmdcclxuICAgIGlmICh1cGRhdGVEdG8uZHVlRGF0ZSkgcmV2aXNpb25VcGRhdGUuZHVlRGF0ZSA9IG5ldyBEYXRlKHVwZGF0ZUR0by5kdWVEYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICByZXZpc2lvblVwZGF0ZS5kb2N1bWVudERhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8uZG9jdW1lbnREYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8uaXNzdWVkRGF0ZSlcclxuICAgICAgcmV2aXNpb25VcGRhdGUuaXNzdWVkRGF0ZSA9IG5ldyBEYXRlKHVwZGF0ZUR0by5pc3N1ZWREYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8ucmVjZWl2ZWREYXRlKVxyXG4gICAgICByZXZpc2lvblVwZGF0ZS5yZWNlaXZlZERhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8ucmVjZWl2ZWREYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8uZGVzY3JpcHRpb24pXHJcbiAgICAgIHJldmlzaW9uVXBkYXRlLmRlc2NyaXB0aW9uID0gdXBkYXRlRHRvLmRlc2NyaXB0aW9uO1xyXG4gICAgaWYgKHVwZGF0ZUR0by5kZXRhaWxzKSByZXZpc2lvblVwZGF0ZS5kZXRhaWxzID0gdXBkYXRlRHRvLmRldGFpbHM7XHJcblxyXG4gICAgaWYgKE9iamVjdC5rZXlzKHJldmlzaW9uVXBkYXRlKS5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGF3YWl0IHRoaXMucmV2aXNpb25SZXBvLnVwZGF0ZShyZXZpc2lvbi5pZCwgcmV2aXNpb25VcGRhdGUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDQuNSBDb21taXQgbmV3IGF0dGFjaG1lbnRzIGZyb20gVGVtcCDihpIgUGVybWFuZW50IChUd28tUGhhc2UgU3RvcmFnZSlcclxuICAgIGlmICh1cGRhdGVEdG8uYXR0YWNobWVudFRlbXBJZHM/Lmxlbmd0aCkge1xyXG4gICAgICBjb25zdCBpc3N1ZURhdGUgPSB1cGRhdGVEdG8uaXNzdWVkRGF0ZVxyXG4gICAgICAgID8gbmV3IERhdGUodXBkYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgICAgOiB1cGRhdGVEdG8uZG9jdW1lbnREYXRlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKHVwZGF0ZUR0by5kb2N1bWVudERhdGUpXHJcbiAgICAgICAgICA6IHJldmlzaW9uLmlzc3VlZERhdGUgfHwgcmV2aXNpb24uZG9jdW1lbnREYXRlIHx8IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgIGF3YWl0IHRoaXMuZmlsZVN0b3JhZ2VTZXJ2aWNlLmNvbW1pdCh1cGRhdGVEdG8uYXR0YWNobWVudFRlbXBJZHMsIHtcclxuICAgICAgICBpc3N1ZURhdGU6IGlzc3VlRGF0ZSA/IG5ldyBEYXRlKGlzc3VlRGF0ZSkgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgZG9jdW1lbnRUeXBlOiAnQ29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA1LiBVcGRhdGUgUmVjaXBpZW50cyBpZiBwcm92aWRlZFxyXG4gICAgaWYgKHVwZFJlc29sdmVkUmVjaXBpZW50cykge1xyXG4gICAgICBjb25zdCByZWNpcGllbnRSZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VSZWNpcGllbnRcclxuICAgICAgKTtcclxuICAgICAgYXdhaXQgcmVjaXBpZW50UmVwby5kZWxldGUoeyBjb3JyZXNwb25kZW5jZUlkOiBpZCB9KTtcclxuXHJcbiAgICAgIGNvbnN0IG5ld1JlY2lwaWVudHMgPSB1cGRSZXNvbHZlZFJlY2lwaWVudHMubWFwKChyKSA9PlxyXG4gICAgICAgIHJlY2lwaWVudFJlcG8uY3JlYXRlKHtcclxuICAgICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGlkLFxyXG4gICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IHIub3JnYW5pemF0aW9uSWQsXHJcbiAgICAgICAgICByZWNpcGllbnRUeXBlOiByLnR5cGUsXHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICAgICAgYXdhaXQgcmVjaXBpZW50UmVwby5zYXZlKG5ld1JlY2lwaWVudHMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDYuIFJlZ2VuZXJhdGUgRG9jdW1lbnQgTnVtYmVyIGlmIHN0cnVjdHVyYWwgZmllbGRzIGNoYW5nZWQgKFJlY2lwaWVudCwgRGlzY2lwbGluZSwgVHlwZSwgUHJvamVjdClcclxuICAgIC8vIEFORCBpdCBpcyBhIERSQUZULlxyXG5cclxuICAgIC8vIEZldGNoIGZyZXNoIGRhdGEgZm9yIGNvbnRleHQgYW5kIGNvbXBhcmlzb25cclxuICAgIGNvbnN0IGN1cnJlbnRDb3JyID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGlkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogWyd0eXBlJywgJ3JlY2lwaWVudHMnLCAncmVjaXBpZW50cy5yZWNpcGllbnRPcmdhbml6YXRpb24nXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChjdXJyZW50Q29ycikge1xyXG4gICAgICBjb25zdCBjdXJyZW50VG9SZWNpcGllbnQgPSBjdXJyZW50Q29yci5yZWNpcGllbnRzPy5maW5kKFxyXG4gICAgICAgIChyKSA9PiByLnJlY2lwaWVudFR5cGUgPT09ICdUTydcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgY3VycmVudFJlY2lwaWVudElkID0gY3VycmVudFRvUmVjaXBpZW50Py5yZWNpcGllbnRPcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICAgIC8vIENoZWNrIGZvciBBQ1RVQUwgdmFsdWUgY2hhbmdlc1xyXG4gICAgICBjb25zdCBpc1Byb2plY3RDaGFuZ2VkID1cclxuICAgICAgICB1cGRSZXNvbHZlZFByb2plY3RJZCAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgICAgdXBkUmVzb2x2ZWRQcm9qZWN0SWQgIT09IGN1cnJlbnRDb3JyLnByb2plY3RJZDtcclxuICAgICAgY29uc3QgaXNPcmlnaW5hdG9yQ2hhbmdlZCA9XHJcbiAgICAgICAgdXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZFJlc29sdmVkT3JpZ2luYXRvcklkICE9PSBjdXJyZW50Q29yci5vcmlnaW5hdG9ySWQ7XHJcbiAgICAgIGNvbnN0IGlzRGlzY2lwbGluZUNoYW5nZWQgPVxyXG4gICAgICAgIHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQgIT09IGN1cnJlbnRDb3JyLmRpc2NpcGxpbmVJZDtcclxuICAgICAgY29uc3QgaXNUeXBlQ2hhbmdlZCA9XHJcbiAgICAgICAgdXBkYXRlRHRvLnR5cGVJZCAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgICAgdXBkYXRlRHRvLnR5cGVJZCAhPT0gY3VycmVudENvcnIuY29ycmVzcG9uZGVuY2VUeXBlSWQ7XHJcblxyXG4gICAgICBsZXQgaXNSZWNpcGllbnRDaGFuZ2VkID0gZmFsc2U7XHJcbiAgICAgIGxldCBuZXdSZWNpcGllbnRJZDogbnVtYmVyIHwgdW5kZWZpbmVkO1xyXG5cclxuICAgICAgaWYgKHVwZFJlc29sdmVkUmVjaXBpZW50cykge1xyXG4gICAgICAgIGNvbnN0IG5ld1RvUmVjaXBpZW50ID0gdXBkUmVzb2x2ZWRSZWNpcGllbnRzLmZpbmQoXHJcbiAgICAgICAgICAocikgPT4gci50eXBlID09PSAnVE8nXHJcbiAgICAgICAgKTtcclxuICAgICAgICBuZXdSZWNpcGllbnRJZCA9IG5ld1RvUmVjaXBpZW50Py5vcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICAgICAgaWYgKG5ld1JlY2lwaWVudElkICE9PSBjdXJyZW50UmVjaXBpZW50SWQpIHtcclxuICAgICAgICAgIGlzUmVjaXBpZW50Q2hhbmdlZCA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgaXNQcm9qZWN0Q2hhbmdlZCB8fFxyXG4gICAgICAgIGlzRGlzY2lwbGluZUNoYW5nZWQgfHxcclxuICAgICAgICBpc1R5cGVDaGFuZ2VkIHx8XHJcbiAgICAgICAgaXNSZWNpcGllbnRDaGFuZ2VkIHx8XHJcbiAgICAgICAgaXNPcmlnaW5hdG9yQ2hhbmdlZFxyXG4gICAgICApIHtcclxuICAgICAgICBjb25zdCB0YXJnZXRSZWNpcGllbnRJZCA9IGlzUmVjaXBpZW50Q2hhbmdlZFxyXG4gICAgICAgICAgPyBuZXdSZWNpcGllbnRJZFxyXG4gICAgICAgICAgOiBjdXJyZW50UmVjaXBpZW50SWQ7XHJcblxyXG4gICAgICAgIC8vIFJlc29sdmUgUmVjaXBpZW50IENvZGUgZm9yIHRoZSBORVcgY29udGV4dFxyXG4gICAgICAgIGxldCByZWNpcGllbnRDb2RlID0gJyc7XHJcbiAgICAgICAgaWYgKHRhcmdldFJlY2lwaWVudElkKSB7XHJcbiAgICAgICAgICBjb25zdCByZWNPcmcgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UubWFuYWdlci5maW5kT25lKE9yZ2FuaXphdGlvbiwge1xyXG4gICAgICAgICAgICB3aGVyZTogeyBpZDogdGFyZ2V0UmVjaXBpZW50SWQgfSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgaWYgKHJlY09yZykgcmVjaXBpZW50Q29kZSA9IHJlY09yZy5vcmdhbml6YXRpb25Db2RlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gW0ZpeCAjNl0gRmV0Y2ggcmVhbCBPUkcgQ29kZSBmcm9tIG9yaWdpbmF0b3Igb3JnYW5pemF0aW9uXHJcbiAgICAgICAgY29uc3Qgb3JpZ2luYXRvck9yZ0ZvclVwZGF0ZSA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoXHJcbiAgICAgICAgICBPcmdhbml6YXRpb24sXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgICAgICAgaWQ6IHVwZFJlc29sdmVkT3JpZ2luYXRvcklkID8/IGN1cnJlbnRDb3JyLm9yaWdpbmF0b3JJZCA/PyAwLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICAgICAgY29uc3Qgb3JnQ29kZSA9IG9yaWdpbmF0b3JPcmdGb3JVcGRhdGU/Lm9yZ2FuaXphdGlvbkNvZGUgPz8gJ1VOSyc7XHJcblxyXG4gICAgICAgIC8vIFByZXBhcmUgQ29udGV4dHNcclxuICAgICAgICBjb25zdCBvbGRDdHggPSB7XHJcbiAgICAgICAgICBwcm9qZWN0SWQ6IGN1cnJlbnRDb3JyLnByb2plY3RJZCxcclxuICAgICAgICAgIG9yaWdpbmF0b3JPcmdhbml6YXRpb25JZDogY3VycmVudENvcnIub3JpZ2luYXRvcklkID8/IDAsXHJcbiAgICAgICAgICB0eXBlSWQ6IGN1cnJlbnRDb3JyLmNvcnJlc3BvbmRlbmNlVHlwZUlkLFxyXG4gICAgICAgICAgZGlzY2lwbGluZUlkOiBjdXJyZW50Q29yci5kaXNjaXBsaW5lSWQsXHJcbiAgICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZDogY3VycmVudFJlY2lwaWVudElkLFxyXG4gICAgICAgICAgeWVhcjogbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld0N0eCA9IHtcclxuICAgICAgICAgIHByb2plY3RJZDogdXBkUmVzb2x2ZWRQcm9qZWN0SWQgPz8gY3VycmVudENvcnIucHJvamVjdElkLFxyXG4gICAgICAgICAgb3JpZ2luYXRvck9yZ2FuaXphdGlvbklkOlxyXG4gICAgICAgICAgICB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZCA/PyBjdXJyZW50Q29yci5vcmlnaW5hdG9ySWQgPz8gMCxcclxuICAgICAgICAgIHR5cGVJZDogdXBkYXRlRHRvLnR5cGVJZCA/PyBjdXJyZW50Q29yci5jb3JyZXNwb25kZW5jZVR5cGVJZCxcclxuICAgICAgICAgIGRpc2NpcGxpbmVJZDogdXBkYXRlRHRvLmRpc2NpcGxpbmVJZCA/PyBjdXJyZW50Q29yci5kaXNjaXBsaW5lSWQsXHJcbiAgICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZDogdGFyZ2V0UmVjaXBpZW50SWQsXHJcbiAgICAgICAgICB5ZWFyOiBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCksXHJcbiAgICAgICAgICB1c2VySWQ6IHVzZXIudXNlcl9pZCwgLy8gUGFzcyBVc2VyIElEIGZvciBBdWRpdFxyXG4gICAgICAgICAgY3VzdG9tVG9rZW5zOiB7XHJcbiAgICAgICAgICAgIFRZUEVfQ09ERTogY3VycmVudENvcnIudHlwZT8udHlwZUNvZGUgfHwgJycsXHJcbiAgICAgICAgICAgIE9SR19DT0RFOiBvcmdDb2RlLFxyXG4gICAgICAgICAgICBSRUNJUElFTlRfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgICAgICAgUkVDX0NPREU6IHJlY2lwaWVudENvZGUsXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIElmIFR5cGUgQ2hhbmdlZCwgbmVlZCBORVcgVHlwZSBDb2RlXHJcbiAgICAgICAgaWYgKGlzVHlwZUNoYW5nZWQpIHtcclxuICAgICAgICAgIGNvbnN0IG5ld1R5cGUgPSBhd2FpdCB0aGlzLnR5cGVSZXBvLmZpbmRPbmUoe1xyXG4gICAgICAgICAgICB3aGVyZTogeyBpZDogbmV3Q3R4LnR5cGVJZCB9LFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICBpZiAobmV3VHlwZSkgbmV3Q3R4LmN1c3RvbVRva2Vucy5UWVBFX0NPREUgPSBuZXdUeXBlLnR5cGVDb2RlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgbmV3RG9jTnVtYmVyID0gYXdhaXQgdGhpcy5udW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0KFxyXG4gICAgICAgICAgY3VycmVudENvcnIuY29ycmVzcG9uZGVuY2VOdW1iZXIsXHJcbiAgICAgICAgICBvbGRDdHgsXHJcbiAgICAgICAgICBuZXdDdHhcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby51cGRhdGUoaWQsIHtcclxuICAgICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiBuZXdEb2NOdW1iZXIsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB1cGRhdGVkID0gYXdhaXQgdGhpcy5maW5kT25lKGlkKTtcclxuXHJcbiAgICAvLyBSZS1pbmRleCB1cGRhdGVkIGRvY3VtZW50IGluIEVsYXN0aWNzZWFyY2ggKGZpcmUtYW5kLWZvcmdldClcclxuICAgIHZvaWQgdGhpcy5zZWFyY2hTZXJ2aWNlLmluZGV4RG9jdW1lbnQoe1xyXG4gICAgICBpZDogdXBkYXRlZC5pZCxcclxuICAgICAgcHVibGljSWQ6IHVwZGF0ZWQucHVibGljSWQsXHJcbiAgICAgIHR5cGU6ICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgIGRvY051bWJlcjogdXBkYXRlZC5jb3JyZXNwb25kZW5jZU51bWJlcixcclxuICAgICAgdGl0bGU6IHVwZGF0ZUR0by5zdWJqZWN0ID8/IHVwZGF0ZWQucmV2aXNpb25zPy5bMF0/LnN1YmplY3QsXHJcbiAgICAgIGRlc2NyaXB0aW9uOiB1cGRhdGVEdG8uZGVzY3JpcHRpb24gPz8gdXBkYXRlZC5yZXZpc2lvbnM/LlswXT8uZGVzY3JpcHRpb24sXHJcbiAgICAgIHN0YXR1czogJ0RSQUZUJyxcclxuICAgICAgcHJvamVjdElkOiB1cGRhdGVkLnByb2plY3RJZCxcclxuICAgICAgY3JlYXRlZEF0OiB1cGRhdGVkLmNyZWF0ZWRBdCxcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiB1cGRhdGVkO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgcHJldmlld0RvY3VtZW50TnVtYmVyKGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8sIHVzZXI6IFVzZXIpIHtcclxuICAgIC8vIEFEUi0wMTk6IFJlc29sdmUgVVVJRCByZWZlcmVuY2VzXHJcbiAgICBjb25zdCBwcmV2aWV3UHJvamVjdElkID0gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZChcclxuICAgICAgY3JlYXRlRHRvLnByb2plY3RJZFxyXG4gICAgKTtcclxuICAgIGNvbnN0IHByZXZpZXdPcmlnaW5hdG9ySWQgPSBjcmVhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgcHJldmlld1JlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50c1xyXG4gICAgICA/IGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgY3JlYXRlRHRvLnJlY2lwaWVudHMubWFwKFxyXG4gICAgICAgICAgICBhc3luYyAocik6IFByb21pc2U8UmVzb2x2ZWRSZWNpcGllbnQ+ID0+ICh7XHJcbiAgICAgICAgICAgICAgb3JnYW5pemF0aW9uSWQ6IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICAgICAgICAgIHIub3JnYW5pemF0aW9uSWRcclxuICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgICAgIHR5cGU6IHIudHlwZSxcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgIClcclxuICAgICAgICApXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG5cclxuICAgIGNvbnN0IHR5cGUgPSBhd2FpdCB0aGlzLnR5cGVSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZDogY3JlYXRlRHRvLnR5cGVJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXR5cGUpIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignRG9jdW1lbnQgVHlwZSBub3QgZm91bmQnKTtcclxuXHJcbiAgICBsZXQgdXNlck9yZ0lkID0gdXNlci5wcmltYXJ5T3JnYW5pemF0aW9uSWQ7XHJcbiAgICBpZiAoIXVzZXJPcmdJZCkge1xyXG4gICAgICBjb25zdCBmdWxsVXNlciA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZmluZE9uZSh1c2VyLnVzZXJfaWQpO1xyXG4gICAgICBpZiAoZnVsbFVzZXIpIHVzZXJPcmdJZCA9IGZ1bGxVc2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocHJldmlld09yaWdpbmF0b3JJZCAmJiBwcmV2aWV3T3JpZ2luYXRvcklkICE9PSB1c2VyT3JnSWQpIHtcclxuICAgICAgLy8gQWxsb3cgaW1wZXJzb25hdGlvbiBmb3IgcHJldmlld1xyXG4gICAgICB1c2VyT3JnSWQgPSBwcmV2aWV3T3JpZ2luYXRvcklkO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEV4dHJhY3QgcmVjaXBpZW50IGZyb20gcmVjaXBpZW50cyBhcnJheVxyXG4gICAgY29uc3QgdG9SZWNpcGllbnQgPSBwcmV2aWV3UmVjaXBpZW50cz8uZmluZCgocikgPT4gci50eXBlID09PSAnVE8nKTtcclxuICAgIGNvbnN0IHJlY2lwaWVudE9yZ2FuaXphdGlvbklkID0gdG9SZWNpcGllbnQ/Lm9yZ2FuaXphdGlvbklkO1xyXG5cclxuICAgIGxldCByZWNpcGllbnRDb2RlID0gJyc7XHJcbiAgICBpZiAocmVjaXBpZW50T3JnYW5pemF0aW9uSWQpIHtcclxuICAgICAgY29uc3QgcmVjT3JnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShPcmdhbml6YXRpb24sIHtcclxuICAgICAgICB3aGVyZTogeyBpZDogcmVjaXBpZW50T3JnYW5pemF0aW9uSWQgfSxcclxuICAgICAgfSk7XHJcbiAgICAgIGlmIChyZWNPcmcpIHJlY2lwaWVudENvZGUgPSByZWNPcmcub3JnYW5pemF0aW9uQ29kZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpcy5udW1iZXJpbmdTZXJ2aWNlLnByZXZpZXdOdW1iZXIoe1xyXG4gICAgICBwcm9qZWN0SWQ6IHByZXZpZXdQcm9qZWN0SWQsXHJcbiAgICAgIG9yaWdpbmF0b3JPcmdhbml6YXRpb25JZDogdXNlck9yZ0lkISxcclxuICAgICAgdHlwZUlkOiBjcmVhdGVEdG8udHlwZUlkLFxyXG4gICAgICBkaXNjaXBsaW5lSWQ6IGNyZWF0ZUR0by5kaXNjaXBsaW5lSWQsXHJcbiAgICAgIHN1YlR5cGVJZDogY3JlYXRlRHRvLnN1YlR5cGVJZCxcclxuICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQsXHJcbiAgICAgIHllYXI6IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKSxcclxuICAgICAgY3VzdG9tVG9rZW5zOiB7XHJcbiAgICAgICAgVFlQRV9DT0RFOiB0eXBlLnR5cGVDb2RlLFxyXG4gICAgICAgIFJFQ0lQSUVOVF9DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgIFJFQ19DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBCdXNpbmVzcyBSdWxlIEltcGxlbWVudGF0aW9uOiBFQy1DT1JSLTAwMSAtIENhbmNlbCBDb3JyZXNwb25kZW5jZSB3aXRoIERvd25zdHJlYW0gQ2lyY3VsYXRpb25cclxuICAgKiBDYW5jZWwgY29ycmVzcG9uZGVuY2UgYW5kIGhhbmRsZSByZWxhdGVkIGNpcmN1bGF0aW9uc1xyXG4gICAqL1xyXG4gIGFzeW5jIGNhbmNlbChwdWJsaWNJZDogc3RyaW5nLCByZWFzb246IHN0cmluZywgdXNlcjogVXNlcikge1xyXG4gICAgY29uc3QgY29ycmVzcG9uZGVuY2UgPSBhd2FpdCB0aGlzLmZpbmRPbmVCeVV1aWQocHVibGljSWQpO1xyXG5cclxuICAgIC8vIENoZWNrIGlmIHVzZXIgaGFzIHBlcm1pc3Npb24gdG8gY2FuY2VsIChPcmcgQWRtaW4gb3IgU3VwZXJhZG1pbiBvbmx5KVxyXG4gICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyh1c2VyLnVzZXJfaWQpO1xyXG4gICAgY29uc3QgY2FuQ2FuY2VsID1cclxuICAgICAgcGVybWlzc2lvbnMuaW5jbHVkZXMoJ2NvcnJlc3BvbmRlbmNlLmNhbmNlbCcpIHx8XHJcbiAgICAgIHBlcm1pc3Npb25zLmluY2x1ZGVzKCdzeXN0ZW0ubWFuYWdlX2FsbCcpO1xyXG5cclxuICAgIGlmICghY2FuQ2FuY2VsKSB7XHJcbiAgICAgIHRocm93IG5ldyBGb3JiaWRkZW5FeGNlcHRpb24oXHJcbiAgICAgICAgJ09ubHkgYWRtaW5pc3RyYXRvcnMgY2FuIGNhbmNlbCBjb3JyZXNwb25kZW5jZXMnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBhY3RpdmUgY2lyY3VsYXRpb25zXHJcbiAgICBjb25zdCBjaXJjdWxhdGlvblJlcG8gPSB0aGlzLmRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeSgnQ2lyY3VsYXRpb24nKTtcclxuICAgIGNvbnN0IGFjdGl2ZUNpcmN1bGF0aW9ucyA9IGF3YWl0IGNpcmN1bGF0aW9uUmVwby5maW5kKHtcclxuICAgICAgd2hlcmU6IHtcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiBjb3JyZXNwb25kZW5jZS5pZCxcclxuICAgICAgICBzdGF0dXM6ICdPUEVOJyxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHdhcm5pbmdNZXNzYWdlID1cclxuICAgICAgYWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aCA+IDBcclxuICAgICAgICA/IGBUaGVyZSBhcmUgJHthY3RpdmVDaXJjdWxhdGlvbnMubGVuZ3RofSBhY3RpdmUgY2lyY3VsYXRpb24ocykgZm9yIHRoaXMgY29ycmVzcG9uZGVuY2UuIENhbmNlbGluZyB3aWxsIGZvcmNlIGNsb3NlIGFsbCByZWxhdGVkIGNpcmN1bGF0aW9ucy5gXHJcbiAgICAgICAgOiAnJztcclxuXHJcbiAgICAvLyBHZXQgdGhlIGN1cnJlbnQgcmV2aXNpb24gdG8gdXBkYXRlIHN0YXR1c1xyXG4gICAgY29uc3QgY3VycmVudFJldmlzaW9uID0gYXdhaXQgdGhpcy5yZXZpc2lvblJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKCFjdXJyZW50UmV2aXNpb24pIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdDdXJyZW50IHJldmlzaW9uIG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEdldCBjYW5jZWxsZWQgc3RhdHVzXHJcbiAgICBjb25zdCBjYW5jZWxsZWRTdGF0dXMgPSBhd2FpdCB0aGlzLnN0YXR1c1JlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IHN0YXR1c0NvZGU6ICdDQU5DRUxMRUQnIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIWNhbmNlbGxlZFN0YXR1cykge1xyXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxTZXJ2ZXJFcnJvckV4Y2VwdGlvbignQ0FOQ0VMTEVEIHN0YXR1cyBub3QgZm91bmQnKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHRoaXMuZGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lcigpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuY29ubmVjdCgpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuc3RhcnRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIFVwZGF0ZSBjb3JyZXNwb25kZW5jZSByZXZpc2lvbiBzdGF0dXMgdG8gQ0FOQ0VMTEVEXHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIudXBkYXRlKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgY3VycmVudFJldmlzaW9uLmlkLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHN0YXR1c0lkOiBjYW5jZWxsZWRTdGF0dXMuaWQsXHJcbiAgICAgICAgICByZW1hcmtzOiBgQ2FuY2VsbGVkOiAke3JlYXNvbn1gLFxyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuXHJcbiAgICAgIC8vIEZvcmNlIGNsb3NlIGFsbCBhY3RpdmUgY2lyY3VsYXRpb25zXHJcbiAgICAgIGlmIChhY3RpdmVDaXJjdWxhdGlvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIudXBkYXRlKFxyXG4gICAgICAgICAgJ0NpcmN1bGF0aW9uJyxcclxuICAgICAgICAgIHtcclxuICAgICAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgICAgIHN0YXR1czogJ09QRU4nLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICAgIHtcclxuICAgICAgICAgICAgc3RhdHVzOiAnRk9SQ0VfQ0xPU0VEJyxcclxuICAgICAgICAgICAgY2xvc2VkQXQ6IG5ldyBEYXRlKCksXHJcbiAgICAgICAgICAgIGNsb3NlZEJ5OiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgICAgICAgIGNsb3NlUmVhc29uOiBgQ29ycmVzcG9uZGVuY2UgY2FuY2VsbGVkOiAke3JlYXNvbn1gLFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLmNvbW1pdFRyYW5zYWN0aW9uKCk7XHJcblxyXG4gICAgICAvLyBSZS1pbmRleCBjYW5jZWxsZWQgc3RhdHVzIGluIEVsYXN0aWNzZWFyY2ggKGZpcmUtYW5kLWZvcmdldClcclxuICAgICAgdm9pZCB0aGlzLnNlYXJjaFNlcnZpY2UuaW5kZXhEb2N1bWVudCh7XHJcbiAgICAgICAgaWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgIHB1YmxpY0lkOiBjb3JyZXNwb25kZW5jZS5wdWJsaWNJZCxcclxuICAgICAgICB0eXBlOiAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgIGRvY051bWJlcjogY29ycmVzcG9uZGVuY2UuY29ycmVzcG9uZGVuY2VOdW1iZXIsXHJcbiAgICAgICAgdGl0bGU6IGN1cnJlbnRSZXZpc2lvbi5zdWJqZWN0LFxyXG4gICAgICAgIHN0YXR1czogJ0NBTkNFTExFRCcsXHJcbiAgICAgICAgcHJvamVjdElkOiBjb3JyZXNwb25kZW5jZS5wcm9qZWN0SWQsXHJcbiAgICAgICAgY3JlYXRlZEF0OiBjb3JyZXNwb25kZW5jZS5jcmVhdGVkQXQsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gTm90aWZ5IG9yaWdpbmF0b3IncyBkb2MtY29udHJvbCB1c2VyIGFib3V0IGNhbmNlbGxhdGlvbiAoZmlyZS1hbmQtZm9yZ2V0KVxyXG4gICAgICBpZiAoY29ycmVzcG9uZGVuY2Uub3JpZ2luYXRvcklkKSB7XHJcbiAgICAgICAgdm9pZCB0aGlzLnVzZXJTZXJ2aWNlXHJcbiAgICAgICAgICAuZmluZERvY0NvbnRyb2xJZEJ5T3JnKGNvcnJlc3BvbmRlbmNlLm9yaWdpbmF0b3JJZClcclxuICAgICAgICAgIC50aGVuKCh0YXJnZXRVc2VySWQpID0+IHtcclxuICAgICAgICAgICAgaWYgKHRhcmdldFVzZXJJZCkge1xyXG4gICAgICAgICAgICAgIHZvaWQgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLnNlbmQoe1xyXG4gICAgICAgICAgICAgICAgdXNlcklkOiB0YXJnZXRVc2VySWQsXHJcbiAgICAgICAgICAgICAgICB0aXRsZTogJ0NvcnJlc3BvbmRlbmNlIENhbmNlbGxlZCcsXHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBgJHtjb3JyZXNwb25kZW5jZS5jb3JyZXNwb25kZW5jZU51bWJlcn0g4oCUICR7Y3VycmVudFJldmlzaW9uLnN1YmplY3R9IGhhcyBiZWVuIGNhbmNlbGxlZC4gUmVhc29uOiAke3JlYXNvbn1gLFxyXG4gICAgICAgICAgICAgICAgdHlwZTogJ0VNQUlMJyxcclxuICAgICAgICAgICAgICAgIGVudGl0eVR5cGU6ICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgICAgICAgICAgICBlbnRpdHlJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgICAgICAgICBsaW5rOiBgL2NvcnJlc3BvbmRlbmNlcy8ke2NvcnJlc3BvbmRlbmNlLnB1YmxpY0lkfWAsXHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgICAuY2F0Y2goKGVycjogRXJyb3IpID0+XHJcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oYENhbmNlbCBub3RpZmljYXRpb24gZmFpbGVkOiAke2Vyci5tZXNzYWdlfWApXHJcbiAgICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIHN1Y2Nlc3M6IHRydWUsXHJcbiAgICAgICAgbWVzc2FnZTogd2FybmluZ01lc3NhZ2UgfHwgJ0NvcnJlc3BvbmRlbmNlIGNhbmNlbGxlZCBzdWNjZXNzZnVsbHknLFxyXG4gICAgICAgIGFjdGl2ZUNpcmN1bGF0aW9uc0NvdW50OiBhY3RpdmVDaXJjdWxhdGlvbnMubGVuZ3RoLFxyXG4gICAgICB9O1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucm9sbGJhY2tUcmFuc2FjdGlvbigpO1xyXG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcclxuICAgICAgICBgRmFpbGVkIHRvIGNhbmNlbCBjb3JyZXNwb25kZW5jZTogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YFxyXG4gICAgICApO1xyXG4gICAgICB0aHJvdyBlcnJvcjtcclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJlbGVhc2UoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGJ1bGtDYW5jZWwoXHJcbiAgICBwdWJsaWNJZHM6IHN0cmluZ1tdLFxyXG4gICAgcmVhc29uOiBzdHJpbmcsXHJcbiAgICB1c2VyOiBVc2VyXHJcbiAgKTogUHJvbWlzZTx7IHN1Y2NlZWRlZDogc3RyaW5nW107IGZhaWxlZDogc3RyaW5nW10gfT4ge1xyXG4gICAgY29uc3Qgc3VjY2VlZGVkOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgY29uc3QgZmFpbGVkOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIGZvciAoY29uc3QgcHVibGljSWQgb2YgcHVibGljSWRzKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5jYW5jZWwocHVibGljSWQsIHJlYXNvbiwgdXNlcik7XHJcbiAgICAgICAgc3VjY2VlZGVkLnB1c2gocHVibGljSWQpO1xyXG4gICAgICB9IGNhdGNoIHtcclxuICAgICAgICBmYWlsZWQucHVzaChwdWJsaWNJZCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4geyBzdWNjZWVkZWQsIGZhaWxlZCB9O1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZXhwb3J0Q3N2KHNlYXJjaER0bzogU2VhcmNoQ29ycmVzcG9uZGVuY2VEdG8pOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgY29uc3QgeyBkYXRhIH0gPSBhd2FpdCB0aGlzLmZpbmRBbGwoc2VhcmNoRHRvKTtcclxuXHJcbiAgICBjb25zdCBoZWFkZXIgPSBbXHJcbiAgICAgICdEb2N1bWVudCBOby4nLFxyXG4gICAgICAnUmV2JyxcclxuICAgICAgJ1N1YmplY3QnLFxyXG4gICAgICAnVHlwZScsXHJcbiAgICAgICdTdGF0dXMnLFxyXG4gICAgICAnUHJvamVjdCcsXHJcbiAgICAgICdGcm9tJyxcclxuICAgICAgJ0R1ZSBEYXRlJyxcclxuICAgICAgJ0NyZWF0ZWQgQXQnLFxyXG4gICAgXTtcclxuICAgIGNvbnN0IHJvd3MgPSBkYXRhLm1hcCgocmV2KSA9PiB7XHJcbiAgICAgIGNvbnN0IGNvcnIgPSByZXYuY29ycmVzcG9uZGVuY2UgPz8gKHJldiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuICAgICAgcmV0dXJuIFtcclxuICAgICAgICB0aGlzLmVzY2FwZUNzdihjb3JyLmNvcnJlc3BvbmRlbmNlTnVtYmVyID8/ICcnKSxcclxuICAgICAgICB0aGlzLmVzY2FwZUNzdihyZXYucmV2aXNpb25MYWJlbCA/PyBTdHJpbmcocmV2LnJldmlzaW9uTnVtYmVyID8/IDApKSxcclxuICAgICAgICB0aGlzLmVzY2FwZUNzdihyZXYuc3ViamVjdCA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci50eXBlPy50eXBlQ29kZSA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YocmV2LnN0YXR1cz8uc3RhdHVzQ29kZSA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci5wcm9qZWN0Py5wcm9qZWN0Q29kZSA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci5vcmlnaW5hdG9yPy5vcmdhbml6YXRpb25Db2RlID8/ICcnKSxcclxuICAgICAgICByZXYuZHVlRGF0ZSA/IG5ldyBEYXRlKHJldi5kdWVEYXRlKS50b0lTT1N0cmluZygpLnNwbGl0KCdUJylbMF0gOiAnJyxcclxuICAgICAgICBuZXcgRGF0ZShyZXYuY3JlYXRlZEF0KS50b0lTT1N0cmluZygpLnNwbGl0KCdUJylbMF0sXHJcbiAgICAgIF0uam9pbignLCcpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIFtoZWFkZXIuam9pbignLCcpLCAuLi5yb3dzXS5qb2luKCdcXG4nKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZXNjYXBlQ3N2KHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKHZhbHVlLmluY2x1ZGVzKCcsJykgfHwgdmFsdWUuaW5jbHVkZXMoJ1wiJykgfHwgdmFsdWUuaW5jbHVkZXMoJ1xcbicpKSB7XHJcbiAgICAgIHJldHVybiBgXCIke3ZhbHVlLnJlcGxhY2UoL1wiL2csICdcIlwiJyl9XCJgO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHZhbHVlO1xyXG4gIH1cclxufVxyXG4iXSwidmVyc2lvbiI6M30= \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8.map new file mode 100644 index 0000000..e8b9c4c --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/3f/correspondenceservice_3ffc2ea46146fb9da9dc418f81d1e3c8.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts"],"sourcesContent":["// File: src/modules/correspondence/correspondence.service.ts\r\n\r\nimport {\r\n Injectable,\r\n NotFoundException,\r\n BadRequestException,\r\n InternalServerErrorException,\r\n ForbiddenException,\r\n Logger,\r\n} from '@nestjs/common';\r\nimport { InjectRepository } from '@nestjs/typeorm';\r\nimport { Repository, DataSource } from 'typeorm';\r\n\r\n// Entities\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Tag } from '../master/entities/tag.entity';\r\nimport { User } from '../user/entities/user.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\n\r\n// DTOs\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { AddReferenceDto } from './dto/add-reference.dto';\r\nimport { SearchCorrespondenceDto } from './dto/search-correspondence.dto';\r\n\r\n// Services\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\n\r\n/**\r\n * CorrespondenceService - Document management (CRUD)\r\n */\r\ninterface ResolvedRecipient {\r\n organizationId: number;\r\n type: 'TO' | 'CC';\r\n}\r\n@Injectable()\r\nexport class CorrespondenceService {\r\n private readonly logger = new Logger(CorrespondenceService.name);\r\n\r\n private async hasSystemManageAllPermission(userId: number): Promise {\r\n const permissions = await this.userService.getUserPermissions(userId);\r\n return permissions.includes('system.manage_all');\r\n }\r\n\r\n constructor(\r\n @InjectRepository(Correspondence)\r\n private correspondenceRepo: Repository,\r\n @InjectRepository(CorrespondenceRevision)\r\n private revisionRepo: Repository,\r\n @InjectRepository(CorrespondenceType)\r\n private typeRepo: Repository,\r\n @InjectRepository(CorrespondenceStatus)\r\n private statusRepo: Repository,\r\n @InjectRepository(CorrespondenceReference)\r\n private referenceRepo: Repository,\r\n @InjectRepository(CorrespondenceTag)\r\n private tagRepo: Repository,\r\n private numberingService: DocumentNumberingService,\r\n private jsonSchemaService: JsonSchemaService,\r\n private workflowEngine: WorkflowEngineService,\r\n private userService: UserService,\r\n private dataSource: DataSource,\r\n private searchService: SearchService,\r\n private fileStorageService: FileStorageService,\r\n private uuidResolver: UuidResolverService,\r\n private notificationService: NotificationService\r\n ) {}\r\n\r\n /**\r\n * Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n * Prevent external correspondence to same organization\r\n */\r\n private async validateCorrespondenceRecipients(\r\n createDto: CreateCorrespondenceDto,\r\n user: User\r\n ): Promise {\r\n // Get user's organization\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n if (createDto.originatorId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (canManageAll) {\r\n userOrgId = await this.uuidResolver.resolveOrganizationId(\r\n createDto.originatorId\r\n );\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n }\r\n\r\n // For impersonation, use the specified originator\r\n const originatorOrgId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : userOrgId;\r\n\r\n // Check if it's internal communication\r\n if (createDto.isInternal) {\r\n // Internal communications should use Circulation instead\r\n throw new BadRequestException(\r\n 'Internal communications should use Circulation Sheet instead of Correspondence'\r\n );\r\n }\r\n\r\n // Validate recipients\r\n if (!createDto.recipients || createDto.recipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one recipient (TO or CC) is required'\r\n );\r\n }\r\n\r\n const toRecipients = createDto.recipients.filter((r) => r.type === 'TO');\r\n const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC');\r\n\r\n if (toRecipients.length === 0 && ccRecipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one TO or CC recipient is required'\r\n );\r\n }\r\n\r\n // Check for same organization correspondence\r\n for (const recipient of createDto.recipients) {\r\n const recipientOrgId = await this.uuidResolver.resolveOrganizationId(\r\n recipient.organizationId\r\n );\r\n\r\n if (recipientOrgId === originatorOrgId) {\r\n throw new BadRequestException(\r\n 'Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'\r\n );\r\n }\r\n }\r\n }\r\n\r\n async create(createDto: CreateCorrespondenceDto, user: User) {\r\n // Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n await this.validateCorrespondenceRecipients(createDto, user);\r\n // ADR-019: Resolve UUID references to internal INT IDs\r\n const resolvedProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const resolvedOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const resolvedRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n const statusDraft = await this.statusRepo.findOne({\r\n where: { statusCode: 'DRAFT' },\r\n });\r\n if (!statusDraft) {\r\n throw new InternalServerErrorException(\r\n 'Status DRAFT not found in Master Data'\r\n );\r\n }\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n // Impersonation Logic\r\n if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (!canManageAll) {\r\n throw new ForbiddenException(\r\n 'You do not have permission to create documents on behalf of other organizations.'\r\n );\r\n }\r\n userOrgId = resolvedOriginatorId;\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n\r\n if (createDto.details) {\r\n try {\r\n await this.jsonSchemaService.validate(type.typeCode, createDto.details);\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Schema validation warning for ${type.typeCode}: ${(error as Error).message}`\r\n );\r\n }\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // [Fix #6] Fetch real ORG Code from Organization entity\r\n const originatorOrg = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: { id: userOrgId },\r\n }\r\n );\r\n const orgCode = originatorOrg?.organizationCode ?? 'UNK';\r\n\r\n // [v1.5.1] Extract recipient organization from recipients array (Primary TO)\r\n const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n const docNumber = await this.numberingService.generateNextNumber({\r\n projectId: resolvedProjectId,\r\n originatorOrganizationId: userOrgId,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId, // [v1.5.1] Pass recipient for document number format\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n\r\n const correspondence = queryRunner.manager.create(Correspondence, {\r\n correspondenceNumber: docNumber.number,\r\n correspondenceTypeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n isInternal: createDto.isInternal || false,\r\n createdBy: user.user_id,\r\n });\r\n const savedCorr = await queryRunner.manager.save(correspondence);\r\n\r\n const revision = queryRunner.manager.create(CorrespondenceRevision, {\r\n correspondenceId: savedCorr.id,\r\n revisionNumber: 0,\r\n revisionLabel: 'A',\r\n isCurrent: true,\r\n statusId: statusDraft.id,\r\n subject: createDto.subject,\r\n body: createDto.body,\r\n remarks: createDto.remarks,\r\n dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined,\r\n documentDate: createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined,\r\n issuedDate: createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : undefined,\r\n receivedDate: createDto.receivedDate\r\n ? new Date(createDto.receivedDate)\r\n : undefined,\r\n description: createDto.description,\r\n details: createDto.details,\r\n createdBy: user.user_id,\r\n schemaVersion: 1,\r\n });\r\n await queryRunner.manager.save(revision);\r\n\r\n // Save Recipients (using resolved INT IDs)\r\n if (resolvedRecipients && resolvedRecipients.length > 0) {\r\n const recipients = resolvedRecipients.map((r) =>\r\n queryRunner.manager.create(CorrespondenceRecipient, {\r\n correspondenceId: savedCorr.id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await queryRunner.manager.save(recipients);\r\n }\r\n\r\n // Commit attachments from Temp → Permanent (Two-Phase Storage)\r\n if (createDto.attachmentTempIds?.length) {\r\n const issueDate = createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined;\r\n\r\n await this.fileStorageService.commit(createDto.attachmentTempIds, {\r\n issueDate,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Start Workflow Instance (non-blocking)\r\n try {\r\n const workflowCode = `CORRESPONDENCE_${type.typeCode}`;\r\n await this.workflowEngine.createInstance(\r\n workflowCode,\r\n 'correspondence',\r\n savedCorr.id.toString(),\r\n {\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n disciplineId: createDto.disciplineId,\r\n initiatorId: user.user_id,\r\n } as Record\r\n );\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${(error as Error).message}`\r\n );\r\n }\r\n\r\n // Fire-and-forget search indexing (non-blocking, void intentional)\r\n void this.searchService.indexDocument({\r\n id: savedCorr.id,\r\n publicId: savedCorr.publicId,\r\n type: 'correspondence',\r\n docNumber: docNumber.number,\r\n title: createDto.subject,\r\n description: createDto.description,\r\n status: 'DRAFT',\r\n projectId: resolvedProjectId,\r\n createdAt: new Date(),\r\n });\r\n\r\n return {\r\n ...savedCorr,\r\n currentRevision: revision,\r\n };\r\n } catch (err) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to create correspondence: ${(err as Error).message}`\r\n );\r\n throw err;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async findAll(searchDto: SearchCorrespondenceDto = {}) {\r\n const {\r\n search,\r\n typeId,\r\n projectId,\r\n statusId,\r\n status,\r\n page = 1,\r\n limit = 10,\r\n } = searchDto;\r\n const skip = (page - 1) * limit;\r\n\r\n // Change: Query from Revision Repo\r\n const query = this.revisionRepo\r\n .createQueryBuilder('rev')\r\n .leftJoinAndSelect('rev.correspondence', 'corr')\r\n .leftJoinAndSelect('corr.type', 'type')\r\n .leftJoinAndSelect('corr.project', 'project')\r\n .leftJoinAndSelect('corr.originator', 'org')\r\n .leftJoinAndSelect('rev.status', 'status');\r\n\r\n // Filter by Revision Status\r\n const revStatus = searchDto.revisionStatus || 'CURRENT';\r\n\r\n if (revStatus === 'CURRENT') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: true });\r\n } else if (revStatus === 'OLD') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: false });\r\n }\r\n // If 'ALL', no filter needed on isCurrent\r\n\r\n if (projectId) {\r\n query.andWhere('corr.projectId = :projectId', { projectId });\r\n }\r\n\r\n if (typeId) {\r\n query.andWhere('corr.correspondenceTypeId = :typeId', { typeId });\r\n }\r\n\r\n if (statusId) {\r\n query.andWhere('rev.statusId = :statusId', { statusId });\r\n }\r\n\r\n if (status) {\r\n query.andWhere('status.statusCode = :status', { status });\r\n }\r\n\r\n if (search) {\r\n query.andWhere(\r\n '(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)',\r\n { search: `%${search}%` }\r\n );\r\n }\r\n\r\n // Default Sort: Latest Created\r\n query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit);\r\n\r\n const [items, total] = await query.getManyAndCount();\r\n\r\n return {\r\n data: items,\r\n meta: {\r\n total,\r\n page,\r\n limit,\r\n totalPages: Math.ceil(total / limit),\r\n },\r\n };\r\n }\r\n\r\n async findOne(id: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence with ID ${id} not found`);\r\n }\r\n return correspondence;\r\n }\r\n\r\n async findOneByUuid(publicId: string) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { publicId },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization',\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(\r\n `Correspondence with UUID ${publicId} not found`\r\n );\r\n }\r\n return correspondence;\r\n }\r\n\r\n async addReference(id: number, dto: AddReferenceDto) {\r\n const source = await this.correspondenceRepo.findOne({ where: { id } });\r\n // ADR-019: Resolve target publicId → internal INT id\r\n const target = await this.correspondenceRepo.findOne({\r\n where: { publicId: dto.targetUuid },\r\n });\r\n\r\n if (!source || !target) {\r\n throw new NotFoundException('Source or Target correspondence not found');\r\n }\r\n\r\n if (source.id === target.id) {\r\n throw new BadRequestException('Cannot reference self');\r\n }\r\n\r\n const exists = await this.referenceRepo.findOne({\r\n where: {\r\n sourceId: id,\r\n targetId: target.id,\r\n },\r\n });\r\n\r\n if (exists) {\r\n return exists;\r\n }\r\n\r\n const ref = this.referenceRepo.create({\r\n sourceId: id,\r\n targetId: target.id,\r\n });\r\n\r\n return this.referenceRepo.save(ref);\r\n }\r\n\r\n async removeReference(id: number, targetId: number) {\r\n const result = await this.referenceRepo.delete({\r\n sourceId: id,\r\n targetId: targetId,\r\n });\r\n\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Reference not found');\r\n }\r\n }\r\n\r\n async getTags(id: number) {\r\n const rows = await this.tagRepo.find({\r\n where: { correspondenceId: id },\r\n relations: ['tag'],\r\n });\r\n return rows.map((r) => r.tag).filter(Boolean);\r\n }\r\n\r\n async addTag(id: number, tagId: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n });\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence ${id} not found`);\r\n }\r\n\r\n const tag = await this.dataSource.manager.findOne(Tag, {\r\n where: { id: tagId },\r\n });\r\n if (!tag) {\r\n throw new NotFoundException(`Tag ${tagId} not found`);\r\n }\r\n\r\n const exists = await this.tagRepo.findOne({\r\n where: { correspondenceId: id, tagId },\r\n });\r\n if (exists) return exists;\r\n\r\n const row = this.tagRepo.create({ correspondenceId: id, tagId });\r\n return this.tagRepo.save(row);\r\n }\r\n\r\n async removeTag(id: number, tagId: number) {\r\n const result = await this.tagRepo.delete({ correspondenceId: id, tagId });\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Tag assignment not found');\r\n }\r\n }\r\n\r\n async getReferences(id: number) {\r\n const outgoing = await this.referenceRepo.find({\r\n where: { sourceId: id },\r\n relations: ['target', 'target.type'],\r\n });\r\n\r\n const incoming = await this.referenceRepo.find({\r\n where: { targetId: id },\r\n relations: ['source', 'source.type'],\r\n });\r\n\r\n return { outgoing, incoming };\r\n }\r\n\r\n async update(id: number, updateDto: UpdateCorrespondenceDto, user: User) {\r\n // 1. Find Current Revision\r\n const revision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: id,\r\n isCurrent: true,\r\n },\r\n relations: ['correspondence'],\r\n });\r\n\r\n if (!revision) {\r\n throw new NotFoundException(\r\n `Current revision for correspondence ${id} not found`\r\n );\r\n }\r\n\r\n // 2. Check Permission\r\n if (revision.statusId) {\r\n const status = await this.statusRepo.findOne({\r\n where: { id: revision.statusId },\r\n });\r\n if (status && status.statusCode !== 'DRAFT') {\r\n throw new BadRequestException('Only DRAFT documents can be updated');\r\n }\r\n }\r\n\r\n // ADR-019: Resolve UUID references in update DTO\r\n const updResolvedProjectId = updateDto.projectId\r\n ? await this.uuidResolver.resolveProjectId(updateDto.projectId)\r\n : undefined;\r\n const updResolvedOriginatorId = updateDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId)\r\n : undefined;\r\n const updResolvedRecipients = updateDto.recipients\r\n ? await Promise.all(\r\n updateDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n // 3. Update Correspondence Entity if needed\r\n const correspondenceUpdate: Record = {};\r\n if (updateDto.disciplineId)\r\n correspondenceUpdate.disciplineId = updateDto.disciplineId;\r\n if (updResolvedProjectId)\r\n correspondenceUpdate.projectId = updResolvedProjectId;\r\n if (updResolvedOriginatorId)\r\n correspondenceUpdate.originatorId = updResolvedOriginatorId;\r\n\r\n if (Object.keys(correspondenceUpdate).length > 0) {\r\n await this.correspondenceRepo.update(id, correspondenceUpdate);\r\n }\r\n\r\n // 4. Update Revision Entity\r\n const revisionUpdate: Record = {};\r\n if (updateDto.subject) revisionUpdate.subject = updateDto.subject;\r\n if (updateDto.body) revisionUpdate.body = updateDto.body;\r\n if (updateDto.remarks) revisionUpdate.remarks = updateDto.remarks;\r\n // Format Date correctly if string\r\n if (updateDto.dueDate) revisionUpdate.dueDate = new Date(updateDto.dueDate);\r\n if (updateDto.documentDate)\r\n revisionUpdate.documentDate = new Date(updateDto.documentDate);\r\n if (updateDto.issuedDate)\r\n revisionUpdate.issuedDate = new Date(updateDto.issuedDate);\r\n if (updateDto.receivedDate)\r\n revisionUpdate.receivedDate = new Date(updateDto.receivedDate);\r\n if (updateDto.description)\r\n revisionUpdate.description = updateDto.description;\r\n if (updateDto.details) revisionUpdate.details = updateDto.details;\r\n\r\n if (Object.keys(revisionUpdate).length > 0) {\r\n await this.revisionRepo.update(revision.id, revisionUpdate);\r\n }\r\n\r\n // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage)\r\n if (updateDto.attachmentTempIds?.length) {\r\n const issueDate = updateDto.issuedDate\r\n ? new Date(updateDto.issuedDate)\r\n : updateDto.documentDate\r\n ? new Date(updateDto.documentDate)\r\n : revision.issuedDate || revision.documentDate || undefined;\r\n\r\n await this.fileStorageService.commit(updateDto.attachmentTempIds, {\r\n issueDate: issueDate ? new Date(issueDate) : undefined,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n // 5. Update Recipients if provided\r\n if (updResolvedRecipients) {\r\n const recipientRepo = this.dataSource.getRepository(\r\n CorrespondenceRecipient\r\n );\r\n await recipientRepo.delete({ correspondenceId: id });\r\n\r\n const newRecipients = updResolvedRecipients.map((r) =>\r\n recipientRepo.create({\r\n correspondenceId: id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await recipientRepo.save(newRecipients);\r\n }\r\n\r\n // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project)\r\n // AND it is a DRAFT.\r\n\r\n // Fetch fresh data for context and comparison\r\n const currentCorr = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: ['type', 'recipients', 'recipients.recipientOrganization'],\r\n });\r\n\r\n if (currentCorr) {\r\n const currentToRecipient = currentCorr.recipients?.find(\r\n (r) => r.recipientType === 'TO'\r\n );\r\n const currentRecipientId = currentToRecipient?.recipientOrganizationId;\r\n\r\n // Check for ACTUAL value changes\r\n const isProjectChanged =\r\n updResolvedProjectId !== undefined &&\r\n updResolvedProjectId !== currentCorr.projectId;\r\n const isOriginatorChanged =\r\n updResolvedOriginatorId !== undefined &&\r\n updResolvedOriginatorId !== currentCorr.originatorId;\r\n const isDisciplineChanged =\r\n updateDto.disciplineId !== undefined &&\r\n updateDto.disciplineId !== currentCorr.disciplineId;\r\n const isTypeChanged =\r\n updateDto.typeId !== undefined &&\r\n updateDto.typeId !== currentCorr.correspondenceTypeId;\r\n\r\n let isRecipientChanged = false;\r\n let newRecipientId: number | undefined;\r\n\r\n if (updResolvedRecipients) {\r\n const newToRecipient = updResolvedRecipients.find(\r\n (r) => r.type === 'TO'\r\n );\r\n newRecipientId = newToRecipient?.organizationId;\r\n\r\n if (newRecipientId !== currentRecipientId) {\r\n isRecipientChanged = true;\r\n }\r\n }\r\n\r\n if (\r\n isProjectChanged ||\r\n isDisciplineChanged ||\r\n isTypeChanged ||\r\n isRecipientChanged ||\r\n isOriginatorChanged\r\n ) {\r\n const targetRecipientId = isRecipientChanged\r\n ? newRecipientId\r\n : currentRecipientId;\r\n\r\n // Resolve Recipient Code for the NEW context\r\n let recipientCode = '';\r\n if (targetRecipientId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: targetRecipientId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n // [Fix #6] Fetch real ORG Code from originator organization\r\n const originatorOrgForUpdate = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: {\r\n id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n },\r\n }\r\n );\r\n const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK';\r\n\r\n // Prepare Contexts\r\n const oldCtx = {\r\n projectId: currentCorr.projectId,\r\n originatorOrganizationId: currentCorr.originatorId ?? 0,\r\n typeId: currentCorr.correspondenceTypeId,\r\n disciplineId: currentCorr.disciplineId,\r\n recipientOrganizationId: currentRecipientId,\r\n year: new Date().getFullYear(),\r\n };\r\n\r\n const newCtx = {\r\n projectId: updResolvedProjectId ?? currentCorr.projectId,\r\n originatorOrganizationId:\r\n updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId,\r\n disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId,\r\n recipientOrganizationId: targetRecipientId,\r\n year: new Date().getFullYear(),\r\n userId: user.user_id, // Pass User ID for Audit\r\n customTokens: {\r\n TYPE_CODE: currentCorr.type?.typeCode || '',\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n };\r\n\r\n // If Type Changed, need NEW Type Code\r\n if (isTypeChanged) {\r\n const newType = await this.typeRepo.findOne({\r\n where: { id: newCtx.typeId },\r\n });\r\n if (newType) newCtx.customTokens.TYPE_CODE = newType.typeCode;\r\n }\r\n\r\n const newDocNumber = await this.numberingService.updateNumberForDraft(\r\n currentCorr.correspondenceNumber,\r\n oldCtx,\r\n newCtx\r\n );\r\n\r\n await this.correspondenceRepo.update(id, {\r\n correspondenceNumber: newDocNumber,\r\n });\r\n }\r\n }\r\n\r\n const updated = await this.findOne(id);\r\n\r\n // Re-index updated document in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: updated.id,\r\n publicId: updated.publicId,\r\n type: 'correspondence',\r\n docNumber: updated.correspondenceNumber,\r\n title: updateDto.subject ?? updated.revisions?.[0]?.subject,\r\n description: updateDto.description ?? updated.revisions?.[0]?.description,\r\n status: 'DRAFT',\r\n projectId: updated.projectId,\r\n createdAt: updated.createdAt,\r\n });\r\n\r\n return updated;\r\n }\r\n\r\n async previewDocumentNumber(createDto: CreateCorrespondenceDto, user: User) {\r\n // ADR-019: Resolve UUID references\r\n const previewProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const previewOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const previewRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n\r\n if (previewOriginatorId && previewOriginatorId !== userOrgId) {\r\n // Allow impersonation for preview\r\n userOrgId = previewOriginatorId;\r\n }\r\n\r\n // Extract recipient from recipients array\r\n const toRecipient = previewRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n return this.numberingService.previewNumber({\r\n projectId: previewProjectId,\r\n originatorOrganizationId: userOrgId!,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId,\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation\r\n * Cancel correspondence and handle related circulations\r\n */\r\n async cancel(publicId: string, reason: string, user: User) {\r\n const correspondence = await this.findOneByUuid(publicId);\r\n\r\n // Check if user has permission to cancel (Org Admin or Superadmin only)\r\n const permissions = await this.userService.getUserPermissions(user.user_id);\r\n const canCancel =\r\n permissions.includes('correspondence.cancel') ||\r\n permissions.includes('system.manage_all');\r\n\r\n if (!canCancel) {\r\n throw new ForbiddenException(\r\n 'Only administrators can cancel correspondences'\r\n );\r\n }\r\n\r\n // Check if there are any active circulations\r\n const circulationRepo = this.dataSource.getRepository('Circulation');\r\n const activeCirculations = await circulationRepo.find({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n });\r\n\r\n const warningMessage =\r\n activeCirculations.length > 0\r\n ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.`\r\n : '';\r\n\r\n // Get the current revision to update status\r\n const currentRevision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n isCurrent: true,\r\n },\r\n });\r\n\r\n if (!currentRevision) {\r\n throw new NotFoundException('Current revision not found');\r\n }\r\n\r\n // Get cancelled status\r\n const cancelledStatus = await this.statusRepo.findOne({\r\n where: { statusCode: 'CANCELLED' },\r\n });\r\n\r\n if (!cancelledStatus) {\r\n throw new InternalServerErrorException('CANCELLED status not found');\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // Update correspondence revision status to CANCELLED\r\n await queryRunner.manager.update(\r\n CorrespondenceRevision,\r\n currentRevision.id,\r\n {\r\n statusId: cancelledStatus.id,\r\n remarks: `Cancelled: ${reason}`,\r\n }\r\n );\r\n\r\n // Force close all active circulations\r\n if (activeCirculations.length > 0) {\r\n await queryRunner.manager.update(\r\n 'Circulation',\r\n {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n {\r\n status: 'FORCE_CLOSED',\r\n closedAt: new Date(),\r\n closedBy: user.user_id,\r\n closeReason: `Correspondence cancelled: ${reason}`,\r\n }\r\n );\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Re-index cancelled status in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: correspondence.id,\r\n publicId: correspondence.publicId,\r\n type: 'correspondence',\r\n docNumber: correspondence.correspondenceNumber,\r\n title: currentRevision.subject,\r\n status: 'CANCELLED',\r\n projectId: correspondence.projectId,\r\n createdAt: correspondence.createdAt,\r\n });\r\n\r\n // Notify originator's doc-control user about cancellation (fire-and-forget)\r\n if (correspondence.originatorId) {\r\n void this.userService\r\n .findDocControlIdByOrg(correspondence.originatorId)\r\n .then((targetUserId) => {\r\n if (targetUserId) {\r\n void this.notificationService.send({\r\n userId: targetUserId,\r\n title: 'Correspondence Cancelled',\r\n message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`,\r\n type: 'EMAIL',\r\n entityType: 'correspondence',\r\n entityId: correspondence.id,\r\n link: `/correspondences/${correspondence.publicId}`,\r\n });\r\n }\r\n })\r\n .catch((err: Error) =>\r\n this.logger.warn(`Cancel notification failed: ${err.message}`)\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n message: warningMessage || 'Correspondence cancelled successfully',\r\n activeCirculationsCount: activeCirculations.length,\r\n };\r\n } catch (error) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to cancel correspondence: ${(error as Error).message}`\r\n );\r\n throw error;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async bulkCancel(\r\n publicIds: string[],\r\n reason: string,\r\n user: User\r\n ): Promise<{ succeeded: string[]; failed: string[] }> {\r\n const succeeded: string[] = [];\r\n const failed: string[] = [];\r\n\r\n for (const publicId of publicIds) {\r\n try {\r\n await this.cancel(publicId, reason, user);\r\n succeeded.push(publicId);\r\n } catch {\r\n failed.push(publicId);\r\n }\r\n }\r\n\r\n return { succeeded, failed };\r\n }\r\n\r\n async exportCsv(searchDto: SearchCorrespondenceDto): Promise {\r\n const { data } = await this.findAll(searchDto);\r\n\r\n const header = [\r\n 'Document No.',\r\n 'Rev',\r\n 'Subject',\r\n 'Type',\r\n 'Status',\r\n 'Project',\r\n 'From',\r\n 'Due Date',\r\n 'Created At',\r\n ];\r\n const rows = data.map((rev) => {\r\n const corr = rev.correspondence ?? (rev as unknown as Correspondence);\r\n return [\r\n this.escapeCsv(corr.correspondenceNumber ?? ''),\r\n this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)),\r\n this.escapeCsv(rev.subject ?? ''),\r\n this.escapeCsv(corr.type?.typeCode ?? ''),\r\n this.escapeCsv(rev.status?.statusCode ?? ''),\r\n this.escapeCsv(corr.project?.projectCode ?? ''),\r\n this.escapeCsv(corr.originator?.organizationCode ?? ''),\r\n rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '',\r\n new Date(rev.createdAt).toISOString().split('T')[0],\r\n ].join(',');\r\n });\r\n\r\n return [header.join(','), ...rows].join('\\n');\r\n }\r\n\r\n private escapeCsv(value: string): string {\r\n if (value.includes(',') || value.includes('\"') || value.includes('\\n')) {\r\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n return value;\r\n }\r\n}\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc new file mode 100644 index 0000000..ebf80fd --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc @@ -0,0 +1,361 @@ +1782bd7fccf5b430f003b42fc04687dc +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testing_1 = require("@nestjs/testing"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +const correspondence_service_1 = require("./correspondence.service"); +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +describe('CorrespondenceService', () => { + let service; + let numberingService; + let correspondenceRepo; + let revisionRepo; + let testingModule; + let _dataSource; + const createMockRepository = () => ({ + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + softDelete: jest.fn(), + createQueryBuilder: jest.fn(() => ({ + leftJoinAndSelect: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + andWhere: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockReturnThis(), + take: jest.fn().mockReturnThis(), + getOne: jest.fn().mockResolvedValue(null), + getMany: jest.fn().mockResolvedValue([]), + getManyAndCount: jest.fn().mockResolvedValue([[], 0]), + })), + }); + const mockDataSource = { + createQueryRunner: jest.fn(() => ({ + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn(), + save: jest.fn(), + findOne: jest.fn(), + }, + })), + getRepository: jest.fn(() => createMockRepository()), + manager: { + findOne: jest.fn(), + }, + }; + beforeEach(async () => { + testingModule = await testing_1.Test.createTestingModule({ + providers: [ + correspondence_service_1.CorrespondenceService, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_reference_entity_1.CorrespondenceReference), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_tag_entity_1.CorrespondenceTag), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(organization_entity_1.Organization), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_recipient_entity_1.CorrespondenceRecipient), + useValue: createMockRepository(), + }, + { + provide: document_numbering_service_1.DocumentNumberingService, + useValue: { + generateNextNumber: jest.fn(), + updateNumberForDraft: jest.fn(), + previewNextNumber: jest.fn(), + }, + }, + { + provide: json_schema_service_1.JsonSchemaService, + useValue: { validate: jest.fn() }, + }, + { + provide: workflow_engine_service_1.WorkflowEngineService, + useValue: { createInstance: jest.fn() }, + }, + { + provide: user_service_1.UserService, + useValue: { + findOne: jest.fn(), + getUserPermissions: jest.fn().mockResolvedValue([]), + }, + }, + { + provide: typeorm_2.DataSource, + useValue: mockDataSource, + }, + { + provide: search_service_1.SearchService, + useValue: { indexDocument: jest.fn() }, + }, + { + provide: file_storage_service_1.FileStorageService, + useValue: { commit: jest.fn().mockResolvedValue([]) }, + }, + { + provide: uuid_resolver_service_1.UuidResolverService, + useValue: { + resolveProjectId: jest.fn().mockResolvedValue(1), + resolveOrganizationId: jest.fn().mockResolvedValue(1), + }, + }, + { + provide: notification_service_1.NotificationService, + useValue: { send: jest.fn().mockResolvedValue(undefined) }, + }, + ], + }).compile(); + service = testingModule.get(correspondence_service_1.CorrespondenceService); + numberingService = testingModule.get(document_numbering_service_1.DocumentNumberingService); + correspondenceRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence)); + revisionRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision)); + _dataSource = testingModule.get(typeorm_2.DataSource); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('update', () => { + it('should NOT regenerate number if critical fields unchanged', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 1, + disciplineId: 3, + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).not.toHaveBeenCalled(); + }); + it('should regenerate number if Project ID changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 2, + }; + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(2); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Document Type changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + typeId: 999, + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + typeRepo.findOne.mockResolvedValue({ + id: 999, + typeCode: 'NEW-TYPE', + }); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Recipient Organization changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + // Access DataSource manager for mocking + mockDataSource.manager.findOne.mockResolvedValue({ + id: 88, + organizationCode: 'NEW-ORG', + }); + const updateDto = { + recipients: [{ type: 'TO', organizationId: 88 }], + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + }); + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const userService = testingModule.get(user_service_1.UserService); + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + userService.findOne.mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + userService.getUserPermissions.mockResolvedValue([ + 'system.manage_all', + ]); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockImplementation(async (value) => { + if (value === 'originator-uuid') + return 10; + if (value === 'recipient-uuid') + return 20; + return 0; + }); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_entity_1.Correspondence, expect.objectContaining({ originatorId: 10 })); + }); + }); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFzRDtBQUN0RCw2Q0FBcUQ7QUFDckQscUNBQWlEO0FBQ2pELHFFQUFpRTtBQUNqRSw0RUFBa0U7QUFDbEUsOEZBQW1GO0FBQ25GLHNGQUEyRTtBQUMzRSwwRkFBK0U7QUFDL0UsZ0dBQXFGO0FBQ3JGLG9GQUF5RTtBQUN6RSxzRkFBNEU7QUFDNUUsZ0dBQXFGO0FBQ3JGLDBHQUFxRztBQUNyRyw0RUFBdUU7QUFDdkUsd0ZBQW1GO0FBQ25GLHVEQUFtRDtBQUNuRCw2REFBeUQ7QUFDekQseUZBQW9GO0FBQ3BGLHVGQUFrRjtBQUNsRiwrRUFBMkU7QUFLM0UsUUFBUSxDQUFDLHVCQUF1QixFQUFFLEdBQUcsRUFBRTtJQUNyQyxJQUFJLE9BQThCLENBQUM7SUFDbkMsSUFBSSxnQkFBMEMsQ0FBQztJQUMvQyxJQUFJLGtCQUE4QyxDQUFDO0lBQ25ELElBQUksWUFBZ0QsQ0FBQztJQUNyRCxJQUFJLGFBQTRCLENBQUM7SUFDakMsSUFBSSxXQUF1QixDQUFDO0lBRTVCLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNsQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNmLE9BQU8sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2xCLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2YsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDakIsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDakIsVUFBVSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDckIsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ2pD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LENBQUMsRUFBRSxFQUFFO2dCQUM1QixtQkFBbUIsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO2dCQUM5QixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDbEIsT0FBTyxFQUFFO29CQUNQLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxDQUNiLENBQUMsT0FBZ0IsRUFBRSxPQUFnQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQ2hFO29CQUNELElBQUksRUFBRSxJQUFJO3lCQUNQLEVBQUUsRUFBRTt5QkFDSixxQkFBcUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxDQUFDO3lCQUN6RCxxQkFBcUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQzt5QkFDbkMscUJBQXFCLENBQUMsRUFBRSxDQUFDO29CQUM1QixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtpQkFDbkI7YUFDRixDQUFDO1lBRUQsY0FBYyxDQUFDLGlCQUErQixDQUFDLGVBQWUsQ0FDN0QsV0FBVyxDQUNaLENBQUM7WUFFRixNQUFNLE9BQU8sQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBRTFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLG9CQUFvQixDQUNyRCxzQ0FBYyxFQUNkLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUM5QyxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIkU6XFxucC1kbXNcXGxjYnAzXFxiYWNrZW5kXFxzcmNcXG1vZHVsZXNcXGNvcnJlc3BvbmRlbmNlXFxjb3JyZXNwb25kZW5jZS5zZXJ2aWNlLnNwZWMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVGVzdCwgVGVzdGluZ01vZHVsZSB9IGZyb20gJ0BuZXN0anMvdGVzdGluZyc7XHJcbmltcG9ydCB7IGdldFJlcG9zaXRvcnlUb2tlbiB9IGZyb20gJ0BuZXN0anMvdHlwZW9ybSc7XHJcbmltcG9ydCB7IERhdGFTb3VyY2UsIFJlcG9zaXRvcnkgfSBmcm9tICd0eXBlb3JtJztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VTZXJ2aWNlIH0gZnJvbSAnLi9jb3JyZXNwb25kZW5jZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2UgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmV2aXNpb24gfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJldmlzaW9uLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVHlwZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtdHlwZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVN0YXR1cyB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2Utc3RhdHVzLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZWZlcmVuY2UuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VUYWcgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXRhZy5lbnRpdHknO1xyXG5pbXBvcnQgeyBPcmdhbml6YXRpb24gfSBmcm9tICcuLi9vcmdhbml6YXRpb24vZW50aXRpZXMvb3JnYW5pemF0aW9uLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmVjaXBpZW50IH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZWNpcGllbnQuZW50aXR5JztcclxuaW1wb3J0IHsgRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlIH0gZnJvbSAnLi4vZG9jdW1lbnQtbnVtYmVyaW5nL3NlcnZpY2VzL2RvY3VtZW50LW51bWJlcmluZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSnNvblNjaGVtYVNlcnZpY2UgfSBmcm9tICcuLi9qc29uLXNjaGVtYS9qc29uLXNjaGVtYS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgV29ya2Zsb3dFbmdpbmVTZXJ2aWNlIH0gZnJvbSAnLi4vd29ya2Zsb3ctZW5naW5lL3dvcmtmbG93LWVuZ2luZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXNlclNlcnZpY2UgfSBmcm9tICcuLi91c2VyL3VzZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IFNlYXJjaFNlcnZpY2UgfSBmcm9tICcuLi9zZWFyY2gvc2VhcmNoLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGaWxlU3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vZmlsZS1zdG9yYWdlL2ZpbGUtc3RvcmFnZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXVpZFJlc29sdmVyU2VydmljZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9zZXJ2aWNlcy91dWlkLXJlc29sdmVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBOb3RpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vbm90aWZpY2F0aW9uL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by91cGRhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by9jcmVhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL3VzZXIvZW50aXRpZXMvdXNlci5lbnRpdHknO1xyXG5cclxuZGVzY3JpYmUoJ0NvcnJlc3BvbmRlbmNlU2VydmljZScsICgpID0+IHtcclxuICBsZXQgc2VydmljZTogQ29ycmVzcG9uZGVuY2VTZXJ2aWNlO1xyXG4gIGxldCBudW1iZXJpbmdTZXJ2aWNlOiBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2U7XHJcbiAgbGV0IGNvcnJlc3BvbmRlbmNlUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZT47XHJcbiAgbGV0IHJldmlzaW9uUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVJldmlzaW9uPjtcclxuICBsZXQgdGVzdGluZ01vZHVsZTogVGVzdGluZ01vZHVsZTtcclxuICBsZXQgX2RhdGFTb3VyY2U6IERhdGFTb3VyY2U7XHJcblxyXG4gIGNvbnN0IGNyZWF0ZU1vY2tSZXBvc2l0b3J5ID0gKCkgPT4gKHtcclxuICAgIGZpbmQ6IGplc3QuZm4oKSxcclxuICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgIGNyZWF0ZTogamVzdC5mbigpLFxyXG4gICAgc2F2ZTogamVzdC5mbigpLFxyXG4gICAgdXBkYXRlOiBqZXN0LmZuKCksXHJcbiAgICBkZWxldGU6IGplc3QuZm4oKSxcclxuICAgIHNvZnREZWxldGU6IGplc3QuZm4oKSxcclxuICAgIGNyZWF0ZVF1ZXJ5QnVpbGRlcjogamVzdC5mbigoKSA9PiAoe1xyXG4gICAgICBsZWZ0Sm9pbkFuZFNlbGVjdDogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHdoZXJlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgYW5kV2hlcmU6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICBvcmRlckJ5OiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgc2tpcDogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHRha2U6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICBnZXRPbmU6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShudWxsKSxcclxuICAgICAgZ2V0TWFueTogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtdKSxcclxuICAgICAgZ2V0TWFueUFuZENvdW50OiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoW1tdLCAwXSksXHJcbiAgICB9KSksXHJcbiAgfSk7XHJcblxyXG4gIGNvbnN0IG1vY2tEYXRhU291cmNlID0ge1xyXG4gICAgY3JlYXRlUXVlcnlSdW5uZXI6IGplc3QuZm4oKCkgPT4gKHtcclxuICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgY3JlYXRlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgc2F2ZTogamVzdC5mbigpLFxyXG4gICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgfSxcclxuICAgIH0pKSxcclxuICAgIGdldFJlcG9zaXRvcnk6IGplc3QuZm4oKCkgPT4gY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSksXHJcbiAgICBtYW5hZ2VyOiB7XHJcbiAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgIH0sXHJcbiAgfTtcclxuXHJcbiAgYmVmb3JlRWFjaChhc3luYyAoKSA9PiB7XHJcbiAgICB0ZXN0aW5nTW9kdWxlID0gYXdhaXQgVGVzdC5jcmVhdGVUZXN0aW5nTW9kdWxlKHtcclxuICAgICAgcHJvdmlkZXJzOiBbXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VTZXJ2aWNlLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZSksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVJldmlzaW9uKSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cyksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVRhZyksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihPcmdhbml6YXRpb24pLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZWNpcGllbnQpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZToge1xyXG4gICAgICAgICAgICBnZW5lcmF0ZU5leHROdW1iZXI6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgdXBkYXRlTnVtYmVyRm9yRHJhZnQ6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgcHJldmlld05leHROdW1iZXI6IGplc3QuZm4oKSxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBKc29uU2NoZW1hU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IHZhbGlkYXRlOiBqZXN0LmZuKCkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFdvcmtmbG93RW5naW5lU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IGNyZWF0ZUluc3RhbmNlOiBqZXN0LmZuKCkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFVzZXJTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHtcclxuICAgICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgICAgICBnZXRVc2VyUGVybWlzc2lvbnM6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogRGF0YVNvdXJjZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBtb2NrRGF0YVNvdXJjZSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFNlYXJjaFNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBpbmRleERvY3VtZW50OiBqZXN0LmZuKCkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IEZpbGVTdG9yYWdlU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IGNvbW1pdDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtdKSB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogVXVpZFJlc29sdmVyU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7XHJcbiAgICAgICAgICAgIHJlc29sdmVQcm9qZWN0SWQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZSgxKSxcclxuICAgICAgICAgICAgcmVzb2x2ZU9yZ2FuaXphdGlvbklkOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoMSksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogTm90aWZpY2F0aW9uU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IHNlbmQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZSh1bmRlZmluZWQpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgXSxcclxuICAgIH0pLmNvbXBpbGUoKTtcclxuXHJcbiAgICBzZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8Q29ycmVzcG9uZGVuY2VTZXJ2aWNlPihDb3JyZXNwb25kZW5jZVNlcnZpY2UpO1xyXG4gICAgbnVtYmVyaW5nU2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PERvY3VtZW50TnVtYmVyaW5nU2VydmljZT4oXHJcbiAgICAgIERvY3VtZW50TnVtYmVyaW5nU2VydmljZVxyXG4gICAgKTtcclxuICAgIGNvcnJlc3BvbmRlbmNlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2U+PihcclxuICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlKVxyXG4gICAgKTtcclxuICAgIHJldmlzaW9uUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj4+KFxyXG4gICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZXZpc2lvbilcclxuICAgICk7XHJcbiAgICBfZGF0YVNvdXJjZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PERhdGFTb3VyY2U+KERhdGFTb3VyY2UpO1xyXG4gIH0pO1xyXG5cclxuICBpdCgnc2hvdWxkIGJlIGRlZmluZWQnLCAoKSA9PiB7XHJcbiAgICBleHBlY3Qoc2VydmljZSkudG9CZURlZmluZWQoKTtcclxuICB9KTtcclxuXHJcbiAgZGVzY3JpYmUoJ3VwZGF0ZScsICgpID0+IHtcclxuICAgIGl0KCdzaG91bGQgTk9UIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIGNyaXRpY2FsIGZpZWxkcyB1bmNoYW5nZWQnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIFByb2plY3QgSUQgY2hhbmdlcycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6IDIsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWdlbmVyYXRlIG51bWJlciBpZiBEb2N1bWVudCBUeXBlIGNoYW5nZXMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgdHlwZUlkOiA5OTksXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB0eXBlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgICAgKTtcclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDk5OSxcclxuICAgICAgICB0eXBlQ29kZTogJ05FVy1UWVBFJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVnZW5lcmF0ZSBudW1iZXIgaWYgUmVjaXBpZW50IE9yZ2FuaXphdGlvbiBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICAvLyBBY2Nlc3MgRGF0YVNvdXJjZSBtYW5hZ2VyIGZvciBtb2NraW5nXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDg4LFxyXG4gICAgICAgIG9yZ2FuaXphdGlvbkNvZGU6ICdORVctT1JHJyxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIE9yZ2FuaXphdGlvbik7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHR5cGU6ICdUTycsIG9yZ2FuaXphdGlvbklkOiA4OCB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcblxyXG4gIGRlc2NyaWJlKCdjcmVhdGUnLCAoKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIGFsbG93IHN5c3RlbS5tYW5hZ2VfYWxsIHVzZXIgd2l0aG91dCBwcmltYXJ5T3JnYW5pemF0aW9uSWQgd2hlbiBvcmlnaW5hdG9ySWQgaXMgcHJvdmlkZWQnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiBudWxsLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuXHJcbiAgICAgIGNvbnN0IGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAncHJvamVjdC11dWlkJyxcclxuICAgICAgICB0eXBlSWQ6IDEsXHJcbiAgICAgICAgc3ViamVjdDogJ1Rlc3QgU3ViamVjdCcsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAnb3JpZ2luYXRvci11dWlkJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHVzZXJTZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8VXNlclNlcnZpY2U+KFVzZXJTZXJ2aWNlKTtcclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHVzZXJTZXJ2aWNlLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgdXNlcl9pZDogMSxcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IG51bGwsXHJcbiAgICAgIH0pO1xyXG4gICAgICAodXNlclNlcnZpY2UuZ2V0VXNlclBlcm1pc3Npb25zIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoW1xyXG4gICAgICAgICdzeXN0ZW0ubWFuYWdlX2FsbCcsXHJcbiAgICAgIF0pO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrSW1wbGVtZW50YXRpb24oXHJcbiAgICAgICAgYXN5bmMgKHZhbHVlOiBudW1iZXIgfCBzdHJpbmcpID0+IHtcclxuICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ29yaWdpbmF0b3ItdXVpZCcpIHJldHVybiAxMDtcclxuICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ3JlY2lwaWVudC11dWlkJykgcmV0dXJuIDIwO1xyXG4gICAgICAgICAgcmV0dXJuIDA7XHJcbiAgICAgICAgfVxyXG4gICAgICApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdMVFInLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZSxcclxuICAgICAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IG9yaWdpbmF0b3JJZDogMTAgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG59KTtcclxuIl0sInZlcnNpb24iOjN9 \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc.map new file mode 100644 index 0000000..9c91d8b --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/5d/correspondenceservicespec_5d371618e36feb86f1397eae2e3f99cc.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\r\nimport { getRepositoryToken } from '@nestjs/typeorm';\r\nimport { DataSource, Repository } from 'typeorm';\r\nimport { CorrespondenceService } from './correspondence.service';\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { User } from '../user/entities/user.entity';\r\n\r\ndescribe('CorrespondenceService', () => {\r\n let service: CorrespondenceService;\r\n let numberingService: DocumentNumberingService;\r\n let correspondenceRepo: Repository;\r\n let revisionRepo: Repository;\r\n let testingModule: TestingModule;\r\n let _dataSource: DataSource;\r\n\r\n const createMockRepository = () => ({\r\n find: jest.fn(),\r\n findOne: jest.fn(),\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n update: jest.fn(),\r\n delete: jest.fn(),\r\n softDelete: jest.fn(),\r\n createQueryBuilder: jest.fn(() => ({\r\n leftJoinAndSelect: jest.fn().mockReturnThis(),\r\n where: jest.fn().mockReturnThis(),\r\n andWhere: jest.fn().mockReturnThis(),\r\n orderBy: jest.fn().mockReturnThis(),\r\n skip: jest.fn().mockReturnThis(),\r\n take: jest.fn().mockReturnThis(),\r\n getOne: jest.fn().mockResolvedValue(null),\r\n getMany: jest.fn().mockResolvedValue([]),\r\n getManyAndCount: jest.fn().mockResolvedValue([[], 0]),\r\n })),\r\n });\r\n\r\n const mockDataSource = {\r\n createQueryRunner: jest.fn(() => ({\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n findOne: jest.fn(),\r\n },\r\n })),\r\n getRepository: jest.fn(() => createMockRepository()),\r\n manager: {\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n beforeEach(async () => {\r\n testingModule = await Test.createTestingModule({\r\n providers: [\r\n CorrespondenceService,\r\n {\r\n provide: getRepositoryToken(Correspondence),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRevision),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceType),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceStatus),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceReference),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceTag),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(Organization),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRecipient),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: DocumentNumberingService,\r\n useValue: {\r\n generateNextNumber: jest.fn(),\r\n updateNumberForDraft: jest.fn(),\r\n previewNextNumber: jest.fn(),\r\n },\r\n },\r\n {\r\n provide: JsonSchemaService,\r\n useValue: { validate: jest.fn() },\r\n },\r\n {\r\n provide: WorkflowEngineService,\r\n useValue: { createInstance: jest.fn() },\r\n },\r\n {\r\n provide: UserService,\r\n useValue: {\r\n findOne: jest.fn(),\r\n getUserPermissions: jest.fn().mockResolvedValue([]),\r\n },\r\n },\r\n {\r\n provide: DataSource,\r\n useValue: mockDataSource,\r\n },\r\n {\r\n provide: SearchService,\r\n useValue: { indexDocument: jest.fn() },\r\n },\r\n {\r\n provide: FileStorageService,\r\n useValue: { commit: jest.fn().mockResolvedValue([]) },\r\n },\r\n {\r\n provide: UuidResolverService,\r\n useValue: {\r\n resolveProjectId: jest.fn().mockResolvedValue(1),\r\n resolveOrganizationId: jest.fn().mockResolvedValue(1),\r\n },\r\n },\r\n {\r\n provide: NotificationService,\r\n useValue: { send: jest.fn().mockResolvedValue(undefined) },\r\n },\r\n ],\r\n }).compile();\r\n\r\n service = testingModule.get(CorrespondenceService);\r\n numberingService = testingModule.get(\r\n DocumentNumberingService\r\n );\r\n correspondenceRepo = testingModule.get>(\r\n getRepositoryToken(Correspondence)\r\n );\r\n revisionRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceRevision)\r\n );\r\n _dataSource = testingModule.get(DataSource);\r\n });\r\n\r\n it('should be defined', () => {\r\n expect(service).toBeDefined();\r\n });\r\n\r\n describe('update', () => {\r\n it('should NOT regenerate number if critical fields unchanged', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 1,\r\n disciplineId: 3,\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).not.toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Project ID changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 2,\r\n };\r\n\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(2);\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Document Type changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n typeId: 999,\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 999,\r\n typeCode: 'NEW-TYPE',\r\n });\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Recipient Organization changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n // Access DataSource manager for mocking\r\n mockDataSource.manager.findOne.mockResolvedValue({\r\n id: 88,\r\n organizationCode: 'NEW-ORG',\r\n } as unknown as Organization);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n recipients: [{ type: 'TO', organizationId: 88 }],\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n });\r\n\r\n describe('create', () => {\r\n it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n originatorId: 'originator-uuid',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const userService = testingModule.get(UserService);\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (userService.findOne as jest.Mock).mockResolvedValue({\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n });\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'system.manage_all',\r\n ]);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(\r\n async (value: number | string) => {\r\n if (value === 'originator-uuid') return 10;\r\n if (value === 'recipient-uuid') return 20;\r\n return 0;\r\n }\r\n );\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LTR',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n Correspondence,\r\n expect.objectContaining({ originatorId: 10 })\r\n );\r\n });\r\n });\r\n});\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e new file mode 100644 index 0000000..ebf80fd --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e @@ -0,0 +1,361 @@ +1782bd7fccf5b430f003b42fc04687dc +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testing_1 = require("@nestjs/testing"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +const correspondence_service_1 = require("./correspondence.service"); +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +describe('CorrespondenceService', () => { + let service; + let numberingService; + let correspondenceRepo; + let revisionRepo; + let testingModule; + let _dataSource; + const createMockRepository = () => ({ + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + softDelete: jest.fn(), + createQueryBuilder: jest.fn(() => ({ + leftJoinAndSelect: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + andWhere: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockReturnThis(), + take: jest.fn().mockReturnThis(), + getOne: jest.fn().mockResolvedValue(null), + getMany: jest.fn().mockResolvedValue([]), + getManyAndCount: jest.fn().mockResolvedValue([[], 0]), + })), + }); + const mockDataSource = { + createQueryRunner: jest.fn(() => ({ + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn(), + save: jest.fn(), + findOne: jest.fn(), + }, + })), + getRepository: jest.fn(() => createMockRepository()), + manager: { + findOne: jest.fn(), + }, + }; + beforeEach(async () => { + testingModule = await testing_1.Test.createTestingModule({ + providers: [ + correspondence_service_1.CorrespondenceService, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_reference_entity_1.CorrespondenceReference), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_tag_entity_1.CorrespondenceTag), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(organization_entity_1.Organization), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_recipient_entity_1.CorrespondenceRecipient), + useValue: createMockRepository(), + }, + { + provide: document_numbering_service_1.DocumentNumberingService, + useValue: { + generateNextNumber: jest.fn(), + updateNumberForDraft: jest.fn(), + previewNextNumber: jest.fn(), + }, + }, + { + provide: json_schema_service_1.JsonSchemaService, + useValue: { validate: jest.fn() }, + }, + { + provide: workflow_engine_service_1.WorkflowEngineService, + useValue: { createInstance: jest.fn() }, + }, + { + provide: user_service_1.UserService, + useValue: { + findOne: jest.fn(), + getUserPermissions: jest.fn().mockResolvedValue([]), + }, + }, + { + provide: typeorm_2.DataSource, + useValue: mockDataSource, + }, + { + provide: search_service_1.SearchService, + useValue: { indexDocument: jest.fn() }, + }, + { + provide: file_storage_service_1.FileStorageService, + useValue: { commit: jest.fn().mockResolvedValue([]) }, + }, + { + provide: uuid_resolver_service_1.UuidResolverService, + useValue: { + resolveProjectId: jest.fn().mockResolvedValue(1), + resolveOrganizationId: jest.fn().mockResolvedValue(1), + }, + }, + { + provide: notification_service_1.NotificationService, + useValue: { send: jest.fn().mockResolvedValue(undefined) }, + }, + ], + }).compile(); + service = testingModule.get(correspondence_service_1.CorrespondenceService); + numberingService = testingModule.get(document_numbering_service_1.DocumentNumberingService); + correspondenceRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence)); + revisionRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision)); + _dataSource = testingModule.get(typeorm_2.DataSource); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('update', () => { + it('should NOT regenerate number if critical fields unchanged', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 1, + disciplineId: 3, + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).not.toHaveBeenCalled(); + }); + it('should regenerate number if Project ID changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 2, + }; + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(2); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Document Type changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + typeId: 999, + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + typeRepo.findOne.mockResolvedValue({ + id: 999, + typeCode: 'NEW-TYPE', + }); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Recipient Organization changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + // Access DataSource manager for mocking + mockDataSource.manager.findOne.mockResolvedValue({ + id: 88, + organizationCode: 'NEW-ORG', + }); + const updateDto = { + recipients: [{ type: 'TO', organizationId: 88 }], + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + }); + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const userService = testingModule.get(user_service_1.UserService); + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + userService.findOne.mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + userService.getUserPermissions.mockResolvedValue([ + 'system.manage_all', + ]); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockImplementation(async (value) => { + if (value === 'originator-uuid') + return 10; + if (value === 'recipient-uuid') + return 20; + return 0; + }); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_entity_1.Correspondence, expect.objectContaining({ originatorId: 10 })); + }); + }); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFzRDtBQUN0RCw2Q0FBcUQ7QUFDckQscUNBQWlEO0FBQ2pELHFFQUFpRTtBQUNqRSw0RUFBa0U7QUFDbEUsOEZBQW1GO0FBQ25GLHNGQUEyRTtBQUMzRSwwRkFBK0U7QUFDL0UsZ0dBQXFGO0FBQ3JGLG9GQUF5RTtBQUN6RSxzRkFBNEU7QUFDNUUsZ0dBQXFGO0FBQ3JGLDBHQUFxRztBQUNyRyw0RUFBdUU7QUFDdkUsd0ZBQW1GO0FBQ25GLHVEQUFtRDtBQUNuRCw2REFBeUQ7QUFDekQseUZBQW9GO0FBQ3BGLHVGQUFrRjtBQUNsRiwrRUFBMkU7QUFLM0UsUUFBUSxDQUFDLHVCQUF1QixFQUFFLEdBQUcsRUFBRTtJQUNyQyxJQUFJLE9BQThCLENBQUM7SUFDbkMsSUFBSSxnQkFBMEMsQ0FBQztJQUMvQyxJQUFJLGtCQUE4QyxDQUFDO0lBQ25ELElBQUksWUFBZ0QsQ0FBQztJQUNyRCxJQUFJLGFBQTRCLENBQUM7SUFDakMsSUFBSSxXQUF1QixDQUFDO0lBRTVCLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNsQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNmLE9BQU8sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2xCLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2YsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDakIsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDakIsVUFBVSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDckIsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ2pD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LENBQUMsRUFBRSxFQUFFO2dCQUM1QixtQkFBbUIsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO2dCQUM5QixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDbEIsT0FBTyxFQUFFO29CQUNQLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxDQUNiLENBQUMsT0FBZ0IsRUFBRSxPQUFnQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQ2hFO29CQUNELElBQUksRUFBRSxJQUFJO3lCQUNQLEVBQUUsRUFBRTt5QkFDSixxQkFBcUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxDQUFDO3lCQUN6RCxxQkFBcUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQzt5QkFDbkMscUJBQXFCLENBQUMsRUFBRSxDQUFDO29CQUM1QixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtpQkFDbkI7YUFDRixDQUFDO1lBRUQsY0FBYyxDQUFDLGlCQUErQixDQUFDLGVBQWUsQ0FDN0QsV0FBVyxDQUNaLENBQUM7WUFFRixNQUFNLE9BQU8sQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBRTFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLG9CQUFvQixDQUNyRCxzQ0FBYyxFQUNkLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUM5QyxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIkU6XFxucC1kbXNcXGxjYnAzXFxiYWNrZW5kXFxzcmNcXG1vZHVsZXNcXGNvcnJlc3BvbmRlbmNlXFxjb3JyZXNwb25kZW5jZS5zZXJ2aWNlLnNwZWMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVGVzdCwgVGVzdGluZ01vZHVsZSB9IGZyb20gJ0BuZXN0anMvdGVzdGluZyc7XHJcbmltcG9ydCB7IGdldFJlcG9zaXRvcnlUb2tlbiB9IGZyb20gJ0BuZXN0anMvdHlwZW9ybSc7XHJcbmltcG9ydCB7IERhdGFTb3VyY2UsIFJlcG9zaXRvcnkgfSBmcm9tICd0eXBlb3JtJztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VTZXJ2aWNlIH0gZnJvbSAnLi9jb3JyZXNwb25kZW5jZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2UgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmV2aXNpb24gfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJldmlzaW9uLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVHlwZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtdHlwZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVN0YXR1cyB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2Utc3RhdHVzLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZWZlcmVuY2UuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VUYWcgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXRhZy5lbnRpdHknO1xyXG5pbXBvcnQgeyBPcmdhbml6YXRpb24gfSBmcm9tICcuLi9vcmdhbml6YXRpb24vZW50aXRpZXMvb3JnYW5pemF0aW9uLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmVjaXBpZW50IH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZWNpcGllbnQuZW50aXR5JztcclxuaW1wb3J0IHsgRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlIH0gZnJvbSAnLi4vZG9jdW1lbnQtbnVtYmVyaW5nL3NlcnZpY2VzL2RvY3VtZW50LW51bWJlcmluZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSnNvblNjaGVtYVNlcnZpY2UgfSBmcm9tICcuLi9qc29uLXNjaGVtYS9qc29uLXNjaGVtYS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgV29ya2Zsb3dFbmdpbmVTZXJ2aWNlIH0gZnJvbSAnLi4vd29ya2Zsb3ctZW5naW5lL3dvcmtmbG93LWVuZ2luZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXNlclNlcnZpY2UgfSBmcm9tICcuLi91c2VyL3VzZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IFNlYXJjaFNlcnZpY2UgfSBmcm9tICcuLi9zZWFyY2gvc2VhcmNoLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGaWxlU3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vZmlsZS1zdG9yYWdlL2ZpbGUtc3RvcmFnZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXVpZFJlc29sdmVyU2VydmljZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9zZXJ2aWNlcy91dWlkLXJlc29sdmVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBOb3RpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vbm90aWZpY2F0aW9uL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by91cGRhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by9jcmVhdGUtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL3VzZXIvZW50aXRpZXMvdXNlci5lbnRpdHknO1xyXG5cclxuZGVzY3JpYmUoJ0NvcnJlc3BvbmRlbmNlU2VydmljZScsICgpID0+IHtcclxuICBsZXQgc2VydmljZTogQ29ycmVzcG9uZGVuY2VTZXJ2aWNlO1xyXG4gIGxldCBudW1iZXJpbmdTZXJ2aWNlOiBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2U7XHJcbiAgbGV0IGNvcnJlc3BvbmRlbmNlUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZT47XHJcbiAgbGV0IHJldmlzaW9uUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVJldmlzaW9uPjtcclxuICBsZXQgdGVzdGluZ01vZHVsZTogVGVzdGluZ01vZHVsZTtcclxuICBsZXQgX2RhdGFTb3VyY2U6IERhdGFTb3VyY2U7XHJcblxyXG4gIGNvbnN0IGNyZWF0ZU1vY2tSZXBvc2l0b3J5ID0gKCkgPT4gKHtcclxuICAgIGZpbmQ6IGplc3QuZm4oKSxcclxuICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgIGNyZWF0ZTogamVzdC5mbigpLFxyXG4gICAgc2F2ZTogamVzdC5mbigpLFxyXG4gICAgdXBkYXRlOiBqZXN0LmZuKCksXHJcbiAgICBkZWxldGU6IGplc3QuZm4oKSxcclxuICAgIHNvZnREZWxldGU6IGplc3QuZm4oKSxcclxuICAgIGNyZWF0ZVF1ZXJ5QnVpbGRlcjogamVzdC5mbigoKSA9PiAoe1xyXG4gICAgICBsZWZ0Sm9pbkFuZFNlbGVjdDogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHdoZXJlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgYW5kV2hlcmU6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICBvcmRlckJ5OiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgc2tpcDogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHRha2U6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICBnZXRPbmU6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShudWxsKSxcclxuICAgICAgZ2V0TWFueTogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtdKSxcclxuICAgICAgZ2V0TWFueUFuZENvdW50OiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoW1tdLCAwXSksXHJcbiAgICB9KSksXHJcbiAgfSk7XHJcblxyXG4gIGNvbnN0IG1vY2tEYXRhU291cmNlID0ge1xyXG4gICAgY3JlYXRlUXVlcnlSdW5uZXI6IGplc3QuZm4oKCkgPT4gKHtcclxuICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIGNvbW1pdFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICBtYW5hZ2VyOiB7XHJcbiAgICAgICAgY3JlYXRlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgc2F2ZTogamVzdC5mbigpLFxyXG4gICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgfSxcclxuICAgIH0pKSxcclxuICAgIGdldFJlcG9zaXRvcnk6IGplc3QuZm4oKCkgPT4gY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSksXHJcbiAgICBtYW5hZ2VyOiB7XHJcbiAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgIH0sXHJcbiAgfTtcclxuXHJcbiAgYmVmb3JlRWFjaChhc3luYyAoKSA9PiB7XHJcbiAgICB0ZXN0aW5nTW9kdWxlID0gYXdhaXQgVGVzdC5jcmVhdGVUZXN0aW5nTW9kdWxlKHtcclxuICAgICAgcHJvdmlkZXJzOiBbXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VTZXJ2aWNlLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZSksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVJldmlzaW9uKSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cyksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVRhZyksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihPcmdhbml6YXRpb24pLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZWNpcGllbnQpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZToge1xyXG4gICAgICAgICAgICBnZW5lcmF0ZU5leHROdW1iZXI6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgdXBkYXRlTnVtYmVyRm9yRHJhZnQ6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgcHJldmlld05leHROdW1iZXI6IGplc3QuZm4oKSxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBKc29uU2NoZW1hU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IHZhbGlkYXRlOiBqZXN0LmZuKCkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFdvcmtmbG93RW5naW5lU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IGNyZWF0ZUluc3RhbmNlOiBqZXN0LmZuKCkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFVzZXJTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHtcclxuICAgICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgICAgICBnZXRVc2VyUGVybWlzc2lvbnM6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogRGF0YVNvdXJjZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBtb2NrRGF0YVNvdXJjZSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFNlYXJjaFNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBpbmRleERvY3VtZW50OiBqZXN0LmZuKCkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IEZpbGVTdG9yYWdlU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IGNvbW1pdDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtdKSB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogVXVpZFJlc29sdmVyU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7XHJcbiAgICAgICAgICAgIHJlc29sdmVQcm9qZWN0SWQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZSgxKSxcclxuICAgICAgICAgICAgcmVzb2x2ZU9yZ2FuaXphdGlvbklkOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoMSksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogTm90aWZpY2F0aW9uU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7IHNlbmQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZSh1bmRlZmluZWQpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgXSxcclxuICAgIH0pLmNvbXBpbGUoKTtcclxuXHJcbiAgICBzZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8Q29ycmVzcG9uZGVuY2VTZXJ2aWNlPihDb3JyZXNwb25kZW5jZVNlcnZpY2UpO1xyXG4gICAgbnVtYmVyaW5nU2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PERvY3VtZW50TnVtYmVyaW5nU2VydmljZT4oXHJcbiAgICAgIERvY3VtZW50TnVtYmVyaW5nU2VydmljZVxyXG4gICAgKTtcclxuICAgIGNvcnJlc3BvbmRlbmNlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2U+PihcclxuICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlKVxyXG4gICAgKTtcclxuICAgIHJldmlzaW9uUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj4+KFxyXG4gICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZXZpc2lvbilcclxuICAgICk7XHJcbiAgICBfZGF0YVNvdXJjZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PERhdGFTb3VyY2U+KERhdGFTb3VyY2UpO1xyXG4gIH0pO1xyXG5cclxuICBpdCgnc2hvdWxkIGJlIGRlZmluZWQnLCAoKSA9PiB7XHJcbiAgICBleHBlY3Qoc2VydmljZSkudG9CZURlZmluZWQoKTtcclxuICB9KTtcclxuXHJcbiAgZGVzY3JpYmUoJ3VwZGF0ZScsICgpID0+IHtcclxuICAgIGl0KCdzaG91bGQgTk9UIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIGNyaXRpY2FsIGZpZWxkcyB1bmNoYW5nZWQnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIFByb2plY3QgSUQgY2hhbmdlcycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6IDIsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG4gICAgICAodXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSgyKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWdlbmVyYXRlIG51bWJlciBpZiBEb2N1bWVudCBUeXBlIGNoYW5nZXMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgdHlwZUlkOiA5OTksXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB0eXBlUmVwbyA9IHRlc3RpbmdNb2R1bGUuZ2V0PFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgICAgKTtcclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDk5OSxcclxuICAgICAgICB0eXBlQ29kZTogJ05FVy1UWVBFJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVnZW5lcmF0ZSBudW1iZXIgaWYgUmVjaXBpZW50IE9yZ2FuaXphdGlvbiBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICAvLyBBY2Nlc3MgRGF0YVNvdXJjZSBtYW5hZ2VyIGZvciBtb2NraW5nXHJcbiAgICAgIG1vY2tEYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDg4LFxyXG4gICAgICAgIG9yZ2FuaXphdGlvbkNvZGU6ICdORVctT1JHJyxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIE9yZ2FuaXphdGlvbik7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHR5cGU6ICdUTycsIG9yZ2FuaXphdGlvbklkOiA4OCB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UudXBkYXRlKDEsIHVwZGF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KFxyXG4gICAgICAgIG51bWJlcmluZ1NlcnZpY2UudXBkYXRlTnVtYmVyRm9yRHJhZnQgYXMgamVzdC5Nb2NrXHJcbiAgICAgICkudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcblxyXG4gIGRlc2NyaWJlKCdjcmVhdGUnLCAoKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIGFsbG93IHN5c3RlbS5tYW5hZ2VfYWxsIHVzZXIgd2l0aG91dCBwcmltYXJ5T3JnYW5pemF0aW9uSWQgd2hlbiBvcmlnaW5hdG9ySWQgaXMgcHJvdmlkZWQnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0ge1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiBudWxsLFxyXG4gICAgICB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuXHJcbiAgICAgIGNvbnN0IGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAncHJvamVjdC11dWlkJyxcclxuICAgICAgICB0eXBlSWQ6IDEsXHJcbiAgICAgICAgc3ViamVjdDogJ1Rlc3QgU3ViamVjdCcsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAnb3JpZ2luYXRvci11dWlkJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyBvcmdhbml6YXRpb25JZDogJ3JlY2lwaWVudC11dWlkJywgdHlwZTogJ1RPJyB9XSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHVzZXJTZXJ2aWNlID0gdGVzdGluZ01vZHVsZS5nZXQ8VXNlclNlcnZpY2U+KFVzZXJTZXJ2aWNlKTtcclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHN0YXR1c1JlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPj4oXHJcbiAgICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCB1dWlkUmVzb2x2ZXIgPVxyXG4gICAgICAgIHRlc3RpbmdNb2R1bGUuZ2V0PFV1aWRSZXNvbHZlclNlcnZpY2U+KFV1aWRSZXNvbHZlclNlcnZpY2UpO1xyXG5cclxuICAgICAgKHVzZXJTZXJ2aWNlLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgdXNlcl9pZDogMSxcclxuICAgICAgICBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IG51bGwsXHJcbiAgICAgIH0pO1xyXG4gICAgICAodXNlclNlcnZpY2UuZ2V0VXNlclBlcm1pc3Npb25zIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoW1xyXG4gICAgICAgICdzeXN0ZW0ubWFuYWdlX2FsbCcsXHJcbiAgICAgIF0pO1xyXG5cclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMTAwKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQgYXMgamVzdC5Nb2NrKS5tb2NrSW1wbGVtZW50YXRpb24oXHJcbiAgICAgICAgYXN5bmMgKHZhbHVlOiBudW1iZXIgfCBzdHJpbmcpID0+IHtcclxuICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ29yaWdpbmF0b3ItdXVpZCcpIHJldHVybiAxMDtcclxuICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ3JlY2lwaWVudC11dWlkJykgcmV0dXJuIDIwO1xyXG4gICAgICAgICAgcmV0dXJuIDA7XHJcbiAgICAgICAgfVxyXG4gICAgICApO1xyXG5cclxuICAgICAgKHR5cGVSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgdHlwZUNvZGU6ICdMVFInLFxyXG4gICAgICB9KTtcclxuICAgICAgKHN0YXR1c1JlcG8uZmluZE9uZSBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBzdGF0dXNDb2RlOiAnRFJBRlQnLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIChudW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcclxuICAgICAgICBudW1iZXI6ICdET0MtMDAxJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmVcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDEwLCBvcmdhbml6YXRpb25Db2RlOiAnT1JHJyB9KVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMjAsIG9yZ2FuaXphdGlvbkNvZGU6ICdSRUMnIH0pO1xyXG5cclxuICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB7XHJcbiAgICAgICAgY29ubmVjdDogamVzdC5mbigpLFxyXG4gICAgICAgIHN0YXJ0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICAgIHJvbGxiYWNrVHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByZWxlYXNlOiBqZXN0LmZuKCksXHJcbiAgICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgICAgY3JlYXRlOiBqZXN0LmZuKFxyXG4gICAgICAgICAgICAoX2VudGl0eTogdW5rbm93biwgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHBheWxvYWRcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBzYXZlOiBqZXN0XHJcbiAgICAgICAgICAgIC5mbigpXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogOTk5LCBwdWJsaWNJZDogJ2NvcnItdXVpZCcgfSlcclxuICAgICAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMDAwIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoW10pLFxyXG4gICAgICAgICAgZmluZE9uZTogamVzdC5mbigpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICAobW9ja0RhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmV0dXJuVmFsdWUoXHJcbiAgICAgICAgcXVlcnlSdW5uZXJcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGF3YWl0IHNlcnZpY2UuY3JlYXRlKGNyZWF0ZUR0bywgbW9ja1VzZXIpO1xyXG5cclxuICAgICAgZXhwZWN0KHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcclxuICAgICAgICBDb3JyZXNwb25kZW5jZSxcclxuICAgICAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IG9yaWdpbmF0b3JJZDogMTAgfSlcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG59KTtcclxuIl0sInZlcnNpb24iOjN9 \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e.map new file mode 100644 index 0000000..9c91d8b --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/a4/correspondenceservicespec_a4210bd9791ec5e98d400126ff42cb7e.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\r\nimport { getRepositoryToken } from '@nestjs/typeorm';\r\nimport { DataSource, Repository } from 'typeorm';\r\nimport { CorrespondenceService } from './correspondence.service';\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { User } from '../user/entities/user.entity';\r\n\r\ndescribe('CorrespondenceService', () => {\r\n let service: CorrespondenceService;\r\n let numberingService: DocumentNumberingService;\r\n let correspondenceRepo: Repository;\r\n let revisionRepo: Repository;\r\n let testingModule: TestingModule;\r\n let _dataSource: DataSource;\r\n\r\n const createMockRepository = () => ({\r\n find: jest.fn(),\r\n findOne: jest.fn(),\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n update: jest.fn(),\r\n delete: jest.fn(),\r\n softDelete: jest.fn(),\r\n createQueryBuilder: jest.fn(() => ({\r\n leftJoinAndSelect: jest.fn().mockReturnThis(),\r\n where: jest.fn().mockReturnThis(),\r\n andWhere: jest.fn().mockReturnThis(),\r\n orderBy: jest.fn().mockReturnThis(),\r\n skip: jest.fn().mockReturnThis(),\r\n take: jest.fn().mockReturnThis(),\r\n getOne: jest.fn().mockResolvedValue(null),\r\n getMany: jest.fn().mockResolvedValue([]),\r\n getManyAndCount: jest.fn().mockResolvedValue([[], 0]),\r\n })),\r\n });\r\n\r\n const mockDataSource = {\r\n createQueryRunner: jest.fn(() => ({\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n findOne: jest.fn(),\r\n },\r\n })),\r\n getRepository: jest.fn(() => createMockRepository()),\r\n manager: {\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n beforeEach(async () => {\r\n testingModule = await Test.createTestingModule({\r\n providers: [\r\n CorrespondenceService,\r\n {\r\n provide: getRepositoryToken(Correspondence),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRevision),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceType),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceStatus),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceReference),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceTag),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(Organization),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRecipient),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: DocumentNumberingService,\r\n useValue: {\r\n generateNextNumber: jest.fn(),\r\n updateNumberForDraft: jest.fn(),\r\n previewNextNumber: jest.fn(),\r\n },\r\n },\r\n {\r\n provide: JsonSchemaService,\r\n useValue: { validate: jest.fn() },\r\n },\r\n {\r\n provide: WorkflowEngineService,\r\n useValue: { createInstance: jest.fn() },\r\n },\r\n {\r\n provide: UserService,\r\n useValue: {\r\n findOne: jest.fn(),\r\n getUserPermissions: jest.fn().mockResolvedValue([]),\r\n },\r\n },\r\n {\r\n provide: DataSource,\r\n useValue: mockDataSource,\r\n },\r\n {\r\n provide: SearchService,\r\n useValue: { indexDocument: jest.fn() },\r\n },\r\n {\r\n provide: FileStorageService,\r\n useValue: { commit: jest.fn().mockResolvedValue([]) },\r\n },\r\n {\r\n provide: UuidResolverService,\r\n useValue: {\r\n resolveProjectId: jest.fn().mockResolvedValue(1),\r\n resolveOrganizationId: jest.fn().mockResolvedValue(1),\r\n },\r\n },\r\n {\r\n provide: NotificationService,\r\n useValue: { send: jest.fn().mockResolvedValue(undefined) },\r\n },\r\n ],\r\n }).compile();\r\n\r\n service = testingModule.get(CorrespondenceService);\r\n numberingService = testingModule.get(\r\n DocumentNumberingService\r\n );\r\n correspondenceRepo = testingModule.get>(\r\n getRepositoryToken(Correspondence)\r\n );\r\n revisionRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceRevision)\r\n );\r\n _dataSource = testingModule.get(DataSource);\r\n });\r\n\r\n it('should be defined', () => {\r\n expect(service).toBeDefined();\r\n });\r\n\r\n describe('update', () => {\r\n it('should NOT regenerate number if critical fields unchanged', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 1,\r\n disciplineId: 3,\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).not.toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Project ID changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 2,\r\n };\r\n\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(2);\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Document Type changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n typeId: 999,\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 999,\r\n typeCode: 'NEW-TYPE',\r\n });\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Recipient Organization changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n // Access DataSource manager for mocking\r\n mockDataSource.manager.findOne.mockResolvedValue({\r\n id: 88,\r\n organizationCode: 'NEW-ORG',\r\n } as unknown as Organization);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n recipients: [{ type: 'TO', organizationId: 88 }],\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n });\r\n\r\n describe('create', () => {\r\n it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n originatorId: 'originator-uuid',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const userService = testingModule.get(UserService);\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (userService.findOne as jest.Mock).mockResolvedValue({\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n });\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'system.manage_all',\r\n ]);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(\r\n async (value: number | string) => {\r\n if (value === 'originator-uuid') return 10;\r\n if (value === 'recipient-uuid') return 20;\r\n return 0;\r\n }\r\n );\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LTR',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n Correspondence,\r\n expect.objectContaining({ originatorId: 10 })\r\n );\r\n });\r\n });\r\n});\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a new file mode 100644 index 0000000..b0a9528 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a @@ -0,0 +1,881 @@ +e94ae16f5f5a03b7666b58118bd53cd7 +"use strict"; +// File: src/modules/correspondence/correspondence.service.ts +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + 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; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var CorrespondenceService_1; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CorrespondenceService = void 0; +const common_1 = require("@nestjs/common"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +// Entities +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const tag_entity_1 = require("../master/entities/tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +// Services +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +let CorrespondenceService = CorrespondenceService_1 = class CorrespondenceService { + async hasSystemManageAllPermission(userId) { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + constructor(correspondenceRepo, revisionRepo, typeRepo, statusRepo, referenceRepo, tagRepo, numberingService, jsonSchemaService, workflowEngine, userService, dataSource, searchService, fileStorageService, uuidResolver, notificationService) { + this.correspondenceRepo = correspondenceRepo; + this.revisionRepo = revisionRepo; + this.typeRepo = typeRepo; + this.statusRepo = statusRepo; + this.referenceRepo = referenceRepo; + this.tagRepo = tagRepo; + this.numberingService = numberingService; + this.jsonSchemaService = jsonSchemaService; + this.workflowEngine = workflowEngine; + this.userService = userService; + this.dataSource = dataSource; + this.searchService = searchService; + this.fileStorageService = fileStorageService; + this.uuidResolver = uuidResolver; + this.notificationService = notificationService; + this.logger = new common_1.Logger(CorrespondenceService_1.name); + } + /** + * Business Rule Validation: EC-CORR-003 - Correspondence to Self + * Prevent external correspondence to same organization + */ + async validateCorrespondenceRecipients(createDto, user) { + // Get user's organization + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + if (!userOrgId) { + if (createDto.originatorId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (canManageAll) { + userOrgId = await this.uuidResolver.resolveOrganizationId(createDto.originatorId); + } + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + } + // For impersonation, use the specified originator + const originatorOrgId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : userOrgId; + // Check if it's internal communication + if (createDto.isInternal) { + // Internal communications should use Circulation instead + throw new common_1.BadRequestException('Internal communications should use Circulation Sheet instead of Correspondence'); + } + // Validate recipients + if (!createDto.recipients || createDto.recipients.length === 0) { + throw new common_1.BadRequestException('At least one recipient (TO or CC) is required'); + } + const toRecipients = createDto.recipients.filter((r) => r.type === 'TO'); + const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC'); + if (toRecipients.length === 0 && ccRecipients.length === 0) { + throw new common_1.BadRequestException('At least one TO or CC recipient is required'); + } + // Check for same organization correspondence + for (const recipient of createDto.recipients) { + const recipientOrgId = await this.uuidResolver.resolveOrganizationId(recipient.organizationId); + if (recipientOrgId === originatorOrgId) { + throw new common_1.BadRequestException('Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'); + } + } + } + async create(createDto, user) { + // Business Rule Validation: EC-CORR-003 - Correspondence to Self + await this.validateCorrespondenceRecipients(createDto, user); + // ADR-019: Resolve UUID references to internal INT IDs + const resolvedProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const resolvedOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const resolvedRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + const statusDraft = await this.statusRepo.findOne({ + where: { statusCode: 'DRAFT' }, + }); + if (!statusDraft) { + throw new common_1.InternalServerErrorException('Status DRAFT not found in Master Data'); + } + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + // Impersonation Logic + if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { + const canManageAll = await this.hasSystemManageAllPermission(user.user_id); + if (!canManageAll) { + throw new common_1.ForbiddenException('You do not have permission to create documents on behalf of other organizations.'); + } + userOrgId = resolvedOriginatorId; + } + if (!userOrgId) { + throw new common_1.BadRequestException('User must belong to an organization to create documents'); + } + if (createDto.details) { + try { + await this.jsonSchemaService.validate(type.typeCode, createDto.details); + } + catch (error) { + this.logger.warn(`Schema validation warning for ${type.typeCode}: ${error.message}`); + } + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // [Fix #6] Fetch real ORG Code from Organization entity + const originatorOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: userOrgId }, + }); + const orgCode = originatorOrg?.organizationCode ?? 'UNK'; + // [v1.5.1] Extract recipient organization from recipients array (Primary TO) + const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + const docNumber = await this.numberingService.generateNextNumber({ + projectId: resolvedProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, // [v1.5.1] Pass recipient for document number format + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + const correspondence = queryRunner.manager.create(correspondence_entity_1.Correspondence, { + correspondenceNumber: docNumber.number, + correspondenceTypeId: createDto.typeId, + disciplineId: createDto.disciplineId, + projectId: resolvedProjectId, + originatorId: userOrgId, + isInternal: createDto.isInternal || false, + createdBy: user.user_id, + }); + const savedCorr = await queryRunner.manager.save(correspondence); + const revision = queryRunner.manager.create(correspondence_revision_entity_1.CorrespondenceRevision, { + correspondenceId: savedCorr.id, + revisionNumber: 0, + revisionLabel: 'A', + isCurrent: true, + statusId: statusDraft.id, + subject: createDto.subject, + body: createDto.body, + remarks: createDto.remarks, + dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined, + documentDate: createDto.documentDate + ? new Date(createDto.documentDate) + : undefined, + issuedDate: createDto.issuedDate + ? new Date(createDto.issuedDate) + : undefined, + receivedDate: createDto.receivedDate + ? new Date(createDto.receivedDate) + : undefined, + description: createDto.description, + details: createDto.details, + createdBy: user.user_id, + schemaVersion: 1, + }); + await queryRunner.manager.save(revision); + // Save Recipients (using resolved INT IDs) + if (resolvedRecipients && resolvedRecipients.length > 0) { + const recipients = resolvedRecipients.map((r) => queryRunner.manager.create(correspondence_recipient_entity_1.CorrespondenceRecipient, { + correspondenceId: savedCorr.id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await queryRunner.manager.save(recipients); + } + // Commit attachments from Temp → Permanent (Two-Phase Storage) + if (createDto.attachmentTempIds?.length) { + const issueDate = createDto.issuedDate + ? new Date(createDto.issuedDate) + : createDto.documentDate + ? new Date(createDto.documentDate) + : undefined; + await this.fileStorageService.commit(createDto.attachmentTempIds, { + issueDate, + documentType: 'Correspondence', + }); + } + await queryRunner.commitTransaction(); + // Start Workflow Instance (non-blocking) + try { + const workflowCode = `CORRESPONDENCE_${type.typeCode}`; + await this.workflowEngine.createInstance(workflowCode, 'correspondence', savedCorr.id.toString(), { + projectId: resolvedProjectId, + originatorId: userOrgId, + disciplineId: createDto.disciplineId, + initiatorId: user.user_id, + }); + } + catch (error) { + this.logger.warn(`Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${error.message}`); + } + // Fire-and-forget search indexing (non-blocking, void intentional) + void this.searchService.indexDocument({ + id: savedCorr.id, + publicId: savedCorr.publicId, + type: 'correspondence', + docNumber: docNumber.number, + title: createDto.subject, + description: createDto.description, + status: 'DRAFT', + projectId: resolvedProjectId, + createdAt: new Date(), + }); + return { + ...savedCorr, + currentRevision: revision, + }; + } + catch (err) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to create correspondence: ${err.message}`); + throw err; + } + finally { + await queryRunner.release(); + } + } + async findAll(searchDto = {}) { + const { search, typeId, projectId, statusId, status, page = 1, limit = 10, } = searchDto; + const skip = (page - 1) * limit; + // Change: Query from Revision Repo + const query = this.revisionRepo + .createQueryBuilder('rev') + .leftJoinAndSelect('rev.correspondence', 'corr') + .leftJoinAndSelect('corr.type', 'type') + .leftJoinAndSelect('corr.project', 'project') + .leftJoinAndSelect('corr.originator', 'org') + .leftJoinAndSelect('rev.status', 'status'); + // Filter by Revision Status + const revStatus = searchDto.revisionStatus || 'CURRENT'; + if (revStatus === 'CURRENT') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: true }); + } + else if (revStatus === 'OLD') { + query.where('rev.isCurrent = :isCurrent', { isCurrent: false }); + } + // If 'ALL', no filter needed on isCurrent + if (projectId) { + query.andWhere('corr.projectId = :projectId', { projectId }); + } + if (typeId) { + query.andWhere('corr.correspondenceTypeId = :typeId', { typeId }); + } + if (statusId) { + query.andWhere('rev.statusId = :statusId', { statusId }); + } + if (status) { + query.andWhere('status.statusCode = :status', { status }); + } + if (search) { + query.andWhere('(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)', { search: `%${search}%` }); + } + // Default Sort: Latest Created + query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit); + const [items, total] = await query.getManyAndCount(); + return { + data: items, + meta: { + total, + page, + limit, + totalPages: Math.ceil(total / limit), + }, + }; + } + async findOne(id) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with ID ${id} not found`); + } + return correspondence; + } + async findOneByUuid(publicId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { publicId }, + relations: [ + 'revisions', + 'revisions.status', + 'type', + 'project', + 'originator', + 'recipients', + 'recipients.recipientOrganization', + ], + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence with UUID ${publicId} not found`); + } + return correspondence; + } + async addReference(id, dto) { + const source = await this.correspondenceRepo.findOne({ where: { id } }); + // ADR-019: Resolve target publicId → internal INT id + const target = await this.correspondenceRepo.findOne({ + where: { publicId: dto.targetUuid }, + }); + if (!source || !target) { + throw new common_1.NotFoundException('Source or Target correspondence not found'); + } + if (source.id === target.id) { + throw new common_1.BadRequestException('Cannot reference self'); + } + const exists = await this.referenceRepo.findOne({ + where: { + sourceId: id, + targetId: target.id, + }, + }); + if (exists) { + return exists; + } + const ref = this.referenceRepo.create({ + sourceId: id, + targetId: target.id, + }); + return this.referenceRepo.save(ref); + } + async removeReference(id, targetId) { + const result = await this.referenceRepo.delete({ + sourceId: id, + targetId: targetId, + }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Reference not found'); + } + } + async getTags(id) { + const rows = await this.tagRepo.find({ + where: { correspondenceId: id }, + relations: ['tag'], + }); + return rows.map((r) => r.tag).filter(Boolean); + } + async addTag(id, tagId) { + const correspondence = await this.correspondenceRepo.findOne({ + where: { id }, + }); + if (!correspondence) { + throw new common_1.NotFoundException(`Correspondence ${id} not found`); + } + const tag = await this.dataSource.manager.findOne(tag_entity_1.Tag, { + where: { id: tagId }, + }); + if (!tag) { + throw new common_1.NotFoundException(`Tag ${tagId} not found`); + } + const exists = await this.tagRepo.findOne({ + where: { correspondenceId: id, tagId }, + }); + if (exists) + return exists; + const row = this.tagRepo.create({ correspondenceId: id, tagId }); + return this.tagRepo.save(row); + } + async removeTag(id, tagId) { + const result = await this.tagRepo.delete({ correspondenceId: id, tagId }); + if (result.affected === 0) { + throw new common_1.NotFoundException('Tag assignment not found'); + } + } + async getReferences(id) { + const outgoing = await this.referenceRepo.find({ + where: { sourceId: id }, + relations: ['target', 'target.type'], + }); + const incoming = await this.referenceRepo.find({ + where: { targetId: id }, + relations: ['source', 'source.type'], + }); + return { outgoing, incoming }; + } + async update(id, updateDto, user) { + // 1. Find Current Revision + const revision = await this.revisionRepo.findOne({ + where: { + correspondenceId: id, + isCurrent: true, + }, + relations: ['correspondence'], + }); + if (!revision) { + throw new common_1.NotFoundException(`Current revision for correspondence ${id} not found`); + } + // 2. Check Permission + if (revision.statusId) { + const status = await this.statusRepo.findOne({ + where: { id: revision.statusId }, + }); + if (status && status.statusCode !== 'DRAFT') { + throw new common_1.BadRequestException('Only DRAFT documents can be updated'); + } + } + // ADR-019: Resolve UUID references in update DTO + const updResolvedProjectId = updateDto.projectId + ? await this.uuidResolver.resolveProjectId(updateDto.projectId) + : undefined; + const updResolvedOriginatorId = updateDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId) + : undefined; + const updResolvedRecipients = updateDto.recipients + ? await Promise.all(updateDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + // 3. Update Correspondence Entity if needed + const correspondenceUpdate = {}; + if (updateDto.disciplineId) + correspondenceUpdate.disciplineId = updateDto.disciplineId; + if (updResolvedProjectId) + correspondenceUpdate.projectId = updResolvedProjectId; + if (updResolvedOriginatorId) + correspondenceUpdate.originatorId = updResolvedOriginatorId; + if (Object.keys(correspondenceUpdate).length > 0) { + await this.correspondenceRepo.update(id, correspondenceUpdate); + } + // 4. Update Revision Entity + const revisionUpdate = {}; + if (updateDto.subject) + revisionUpdate.subject = updateDto.subject; + if (updateDto.body) + revisionUpdate.body = updateDto.body; + if (updateDto.remarks) + revisionUpdate.remarks = updateDto.remarks; + // Format Date correctly if string + if (updateDto.dueDate) + revisionUpdate.dueDate = new Date(updateDto.dueDate); + if (updateDto.documentDate) + revisionUpdate.documentDate = new Date(updateDto.documentDate); + if (updateDto.issuedDate) + revisionUpdate.issuedDate = new Date(updateDto.issuedDate); + if (updateDto.receivedDate) + revisionUpdate.receivedDate = new Date(updateDto.receivedDate); + if (updateDto.description) + revisionUpdate.description = updateDto.description; + if (updateDto.details) + revisionUpdate.details = updateDto.details; + if (Object.keys(revisionUpdate).length > 0) { + await this.revisionRepo.update(revision.id, revisionUpdate); + } + // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage) + if (updateDto.attachmentTempIds?.length) { + const issueDate = updateDto.issuedDate + ? new Date(updateDto.issuedDate) + : updateDto.documentDate + ? new Date(updateDto.documentDate) + : revision.issuedDate || revision.documentDate || undefined; + await this.fileStorageService.commit(updateDto.attachmentTempIds, { + issueDate: issueDate ? new Date(issueDate) : undefined, + documentType: 'Correspondence', + }); + } + // 5. Update Recipients if provided + if (updResolvedRecipients) { + const recipientRepo = this.dataSource.getRepository(correspondence_recipient_entity_1.CorrespondenceRecipient); + await recipientRepo.delete({ correspondenceId: id }); + const newRecipients = updResolvedRecipients.map((r) => recipientRepo.create({ + correspondenceId: id, + recipientOrganizationId: r.organizationId, + recipientType: r.type, + })); + await recipientRepo.save(newRecipients); + } + // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project) + // AND it is a DRAFT. + // Fetch fresh data for context and comparison + const currentCorr = await this.correspondenceRepo.findOne({ + where: { id }, + relations: ['type', 'recipients', 'recipients.recipientOrganization'], + }); + if (currentCorr) { + const currentToRecipient = currentCorr.recipients?.find((r) => r.recipientType === 'TO'); + const currentRecipientId = currentToRecipient?.recipientOrganizationId; + // Check for ACTUAL value changes + const isProjectChanged = updResolvedProjectId !== undefined && + updResolvedProjectId !== currentCorr.projectId; + const isOriginatorChanged = updResolvedOriginatorId !== undefined && + updResolvedOriginatorId !== currentCorr.originatorId; + const isDisciplineChanged = updateDto.disciplineId !== undefined && + updateDto.disciplineId !== currentCorr.disciplineId; + const isTypeChanged = updateDto.typeId !== undefined && + updateDto.typeId !== currentCorr.correspondenceTypeId; + let isRecipientChanged = false; + let newRecipientId; + if (updResolvedRecipients) { + const newToRecipient = updResolvedRecipients.find((r) => r.type === 'TO'); + newRecipientId = newToRecipient?.organizationId; + if (newRecipientId !== currentRecipientId) { + isRecipientChanged = true; + } + } + if (isProjectChanged || + isDisciplineChanged || + isTypeChanged || + isRecipientChanged || + isOriginatorChanged) { + const targetRecipientId = isRecipientChanged + ? newRecipientId + : currentRecipientId; + // Resolve Recipient Code for the NEW context + let recipientCode = ''; + if (targetRecipientId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: targetRecipientId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + // [Fix #6] Fetch real ORG Code from originator organization + const originatorOrgForUpdate = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { + id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + }, + }); + const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK'; + // Prepare Contexts + const oldCtx = { + projectId: currentCorr.projectId, + originatorOrganizationId: currentCorr.originatorId ?? 0, + typeId: currentCorr.correspondenceTypeId, + disciplineId: currentCorr.disciplineId, + recipientOrganizationId: currentRecipientId, + year: new Date().getFullYear(), + }; + const newCtx = { + projectId: updResolvedProjectId ?? currentCorr.projectId, + originatorOrganizationId: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0, + typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId, + disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId, + recipientOrganizationId: targetRecipientId, + year: new Date().getFullYear(), + userId: user.user_id, // Pass User ID for Audit + customTokens: { + TYPE_CODE: currentCorr.type?.typeCode || '', + ORG_CODE: orgCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }; + // If Type Changed, need NEW Type Code + if (isTypeChanged) { + const newType = await this.typeRepo.findOne({ + where: { id: newCtx.typeId }, + }); + if (newType) + newCtx.customTokens.TYPE_CODE = newType.typeCode; + } + const newDocNumber = await this.numberingService.updateNumberForDraft(currentCorr.correspondenceNumber, oldCtx, newCtx); + await this.correspondenceRepo.update(id, { + correspondenceNumber: newDocNumber, + }); + } + } + const updated = await this.findOne(id); + // Re-index updated document in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: updated.id, + publicId: updated.publicId, + type: 'correspondence', + docNumber: updated.correspondenceNumber, + title: updateDto.subject ?? updated.revisions?.[0]?.subject, + description: updateDto.description ?? updated.revisions?.[0]?.description, + status: 'DRAFT', + projectId: updated.projectId, + createdAt: updated.createdAt, + }); + return updated; + } + async previewDocumentNumber(createDto, user) { + // ADR-019: Resolve UUID references + const previewProjectId = await this.uuidResolver.resolveProjectId(createDto.projectId); + const previewOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + const previewRecipients = createDto.recipients + ? await Promise.all(createDto.recipients.map(async (r) => ({ + organizationId: await this.uuidResolver.resolveOrganizationId(r.organizationId), + type: r.type, + }))) + : undefined; + const type = await this.typeRepo.findOne({ + where: { id: createDto.typeId }, + }); + if (!type) + throw new common_1.NotFoundException('Document Type not found'); + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) + userOrgId = fullUser.primaryOrganizationId; + } + if (previewOriginatorId && previewOriginatorId !== userOrgId) { + // Allow impersonation for preview + userOrgId = previewOriginatorId; + } + // Extract recipient from recipients array + const toRecipient = previewRecipients?.find((r) => r.type === 'TO'); + const recipientOrganizationId = toRecipient?.organizationId; + let recipientCode = ''; + if (recipientOrganizationId) { + const recOrg = await this.dataSource.manager.findOne(organization_entity_1.Organization, { + where: { id: recipientOrganizationId }, + }); + if (recOrg) + recipientCode = recOrg.organizationCode; + } + return this.numberingService.previewNumber({ + projectId: previewProjectId, + originatorOrganizationId: userOrgId, + typeId: createDto.typeId, + disciplineId: createDto.disciplineId, + subTypeId: createDto.subTypeId, + recipientOrganizationId, + year: new Date().getFullYear(), + customTokens: { + TYPE_CODE: type.typeCode, + RECIPIENT_CODE: recipientCode, + REC_CODE: recipientCode, + }, + }); + } + /** + * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation + * Cancel correspondence and handle related circulations + */ + async cancel(publicId, reason, user) { + const correspondence = await this.findOneByUuid(publicId); + // Check if user has permission to cancel (Org Admin or Superadmin only) + const permissions = await this.userService.getUserPermissions(user.user_id); + const canCancel = permissions.includes('correspondence.cancel') || + permissions.includes('system.manage_all'); + if (!canCancel) { + throw new common_1.ForbiddenException('Only administrators can cancel correspondences'); + } + // Check if there are any active circulations + const circulationRepo = this.dataSource.getRepository('Circulation'); + const activeCirculations = await circulationRepo.find({ + where: { + correspondenceId: correspondence.id, + status: 'OPEN', + }, + }); + const warningMessage = activeCirculations.length > 0 + ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.` + : ''; + // Get the current revision to update status + const currentRevision = await this.revisionRepo.findOne({ + where: { + correspondenceId: correspondence.id, + isCurrent: true, + }, + }); + if (!currentRevision) { + throw new common_1.NotFoundException('Current revision not found'); + } + // Get cancelled status + const cancelledStatus = await this.statusRepo.findOne({ + where: { statusCode: 'CANCELLED' }, + }); + if (!cancelledStatus) { + throw new common_1.InternalServerErrorException('CANCELLED status not found'); + } + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + try { + // Update correspondence revision status to CANCELLED + await queryRunner.manager.update(correspondence_revision_entity_1.CorrespondenceRevision, currentRevision.id, { + statusId: cancelledStatus.id, + remarks: `Cancelled: ${reason}`, + }); + // Force close all active circulations + if (activeCirculations.length > 0) { + await queryRunner.manager.update('Circulation', { + correspondenceId: correspondence.id, + status: 'OPEN', + }, { + status: 'FORCE_CLOSED', + closedAt: new Date(), + closedBy: user.user_id, + closeReason: `Correspondence cancelled: ${reason}`, + }); + } + await queryRunner.commitTransaction(); + // Re-index cancelled status in Elasticsearch (fire-and-forget) + void this.searchService.indexDocument({ + id: correspondence.id, + publicId: correspondence.publicId, + type: 'correspondence', + docNumber: correspondence.correspondenceNumber, + title: currentRevision.subject, + status: 'CANCELLED', + projectId: correspondence.projectId, + createdAt: correspondence.createdAt, + }); + // Notify originator's doc-control user about cancellation (fire-and-forget) + if (correspondence.originatorId) { + void this.userService + .findDocControlIdByOrg(correspondence.originatorId) + .then((targetUserId) => { + if (targetUserId) { + void this.notificationService.send({ + userId: targetUserId, + title: 'Correspondence Cancelled', + message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`, + type: 'EMAIL', + entityType: 'correspondence', + entityId: correspondence.id, + link: `/correspondences/${correspondence.publicId}`, + }); + } + }) + .catch((err) => this.logger.warn(`Cancel notification failed: ${err.message}`)); + } + return { + success: true, + message: warningMessage || 'Correspondence cancelled successfully', + activeCirculationsCount: activeCirculations.length, + }; + } + catch (error) { + await queryRunner.rollbackTransaction(); + this.logger.error(`Failed to cancel correspondence: ${error.message}`); + throw error; + } + finally { + await queryRunner.release(); + } + } + async bulkCancel(publicIds, reason, user) { + const succeeded = []; + const failed = []; + for (const publicId of publicIds) { + try { + await this.cancel(publicId, reason, user); + succeeded.push(publicId); + } + catch { + failed.push(publicId); + } + } + return { succeeded, failed }; + } + async exportCsv(searchDto) { + const { data } = await this.findAll(searchDto); + const header = [ + 'Document No.', + 'Rev', + 'Subject', + 'Type', + 'Status', + 'Project', + 'From', + 'Due Date', + 'Created At', + ]; + const rows = data.map((rev) => { + const corr = rev.correspondence ?? rev; + return [ + this.escapeCsv(corr.correspondenceNumber ?? ''), + this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)), + this.escapeCsv(rev.subject ?? ''), + this.escapeCsv(corr.type?.typeCode ?? ''), + this.escapeCsv(rev.status?.statusCode ?? ''), + this.escapeCsv(corr.project?.projectCode ?? ''), + this.escapeCsv(corr.originator?.organizationCode ?? ''), + rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '', + new Date(rev.createdAt).toISOString().split('T')[0], + ].join(','); + }); + return [header.join(','), ...rows].join('\n'); + } + escapeCsv(value) { + if (value.includes(',') || value.includes('"') || value.includes('\n')) { + return `"${value.replace(/"/g, '""')}"`; + } + return value; + } +}; +exports.CorrespondenceService = CorrespondenceService; +exports.CorrespondenceService = CorrespondenceService = CorrespondenceService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(correspondence_entity_1.Correspondence)), + __param(1, (0, typeorm_1.InjectRepository)(correspondence_revision_entity_1.CorrespondenceRevision)), + __param(2, (0, typeorm_1.InjectRepository)(correspondence_type_entity_1.CorrespondenceType)), + __param(3, (0, typeorm_1.InjectRepository)(correspondence_status_entity_1.CorrespondenceStatus)), + __param(4, (0, typeorm_1.InjectRepository)(correspondence_reference_entity_1.CorrespondenceReference)), + __param(5, (0, typeorm_1.InjectRepository)(correspondence_tag_entity_1.CorrespondenceTag)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object, typeof (_f = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _f : Object, typeof (_g = typeof document_numbering_service_1.DocumentNumberingService !== "undefined" && document_numbering_service_1.DocumentNumberingService) === "function" ? _g : Object, typeof (_h = typeof json_schema_service_1.JsonSchemaService !== "undefined" && json_schema_service_1.JsonSchemaService) === "function" ? _h : Object, typeof (_j = typeof workflow_engine_service_1.WorkflowEngineService !== "undefined" && workflow_engine_service_1.WorkflowEngineService) === "function" ? _j : Object, typeof (_k = typeof user_service_1.UserService !== "undefined" && user_service_1.UserService) === "function" ? _k : Object, typeof (_l = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _l : Object, typeof (_m = typeof search_service_1.SearchService !== "undefined" && search_service_1.SearchService) === "function" ? _m : Object, typeof (_o = typeof file_storage_service_1.FileStorageService !== "undefined" && file_storage_service_1.FileStorageService) === "function" ? _o : Object, typeof (_p = typeof uuid_resolver_service_1.UuidResolverService !== "undefined" && uuid_resolver_service_1.UuidResolverService) === "function" ? _p : Object, typeof (_q = typeof notification_service_1.NotificationService !== "undefined" && notification_service_1.NotificationService) === "function" ? _q : Object]) +], CorrespondenceService); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2UudHMiLCJtYXBwaW5ncyI6IjtBQUFBLDZEQUE2RDs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFN0QsMkNBT3dCO0FBQ3hCLDZDQUFtRDtBQUNuRCxxQ0FBaUQ7QUFFakQsV0FBVztBQUNYLDRFQUFrRTtBQUNsRSw4RkFBbUY7QUFDbkYsc0ZBQTJFO0FBQzNFLDBGQUErRTtBQUMvRSxnR0FBcUY7QUFDckYsZ0dBQXFGO0FBQ3JGLG9GQUF5RTtBQUN6RSw4REFBb0Q7QUFFcEQsc0ZBQTRFO0FBUTVFLFdBQVc7QUFDWCwwR0FBcUc7QUFDckcsNEVBQXVFO0FBQ3ZFLHdGQUFtRjtBQUNuRix1REFBbUQ7QUFDbkQsNkRBQXlEO0FBQ3pELHlGQUFvRjtBQUNwRix1RkFBa0Y7QUFDbEYsK0VBQTJFO0FBVXBFLElBQU0scUJBQXFCLDZCQUEzQixNQUFNLHFCQUFxQjtJQUd4QixLQUFLLENBQUMsNEJBQTRCLENBQUMsTUFBYztRQUN2RCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEUsT0FBTyxXQUFXLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVELFlBRUUsa0JBQXNELEVBRXRELFlBQXdELEVBRXhELFFBQWdELEVBRWhELFVBQW9ELEVBRXBELGFBQTBELEVBRTFELE9BQThDLEVBQ3RDLGdCQUEwQyxFQUMxQyxpQkFBb0MsRUFDcEMsY0FBcUMsRUFDckMsV0FBd0IsRUFDeEIsVUFBc0IsRUFDdEIsYUFBNEIsRUFDNUIsa0JBQXNDLEVBQ3RDLFlBQWlDLEVBQ2pDLG1CQUF3QztRQW5CeEMsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUE0QjtRQUU5QyxpQkFBWSxHQUFaLFlBQVksQ0FBb0M7UUFFaEQsYUFBUSxHQUFSLFFBQVEsQ0FBZ0M7UUFFeEMs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QkFBVSxvREFFZCxvQkFBVSxvQkFBVixvQkFBVSxvREFFUixvQkFBVSxvQkFBVixvQkFBVSxvREFFUCxvQkFBVSxvQkFBVixvQkFBVSxvREFFaEIsb0JBQVUsb0JBQVYsb0JBQVUsb0RBQ0QscURBQXdCLG9CQUF4QixxREFBd0Isb0RBQ3ZCLHVDQUFpQixvQkFBakIsdUNBQWlCLG9EQUNwQiwrQ0FBcUIsb0JBQXJCLCtDQUFxQixvREFDeEIsMEJBQVcsb0JBQVgsMEJBQVcsb0RBQ1osb0JBQVUsb0JBQVYsb0JBQVUsb0RBQ1AsOEJBQWEsb0JBQWIsOEJBQWEsb0RBQ1IseUNBQWtCLG9CQUFsQix5Q0FBa0Isb0RBQ3hCLDJDQUFtQixvQkFBbkIsMkNBQW1CLG9EQUNaLDBDQUFtQixvQkFBbkIsMENBQW1CO0dBN0J2QyxxQkFBcUIsQ0FxaUNqQyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJFOlxcbnAtZG1zXFxsY2JwM1xcYmFja2VuZFxcc3JjXFxtb2R1bGVzXFxjb3JyZXNwb25kZW5jZVxcY29ycmVzcG9uZGVuY2Uuc2VydmljZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBGaWxlOiBzcmMvbW9kdWxlcy9jb3JyZXNwb25kZW5jZS9jb3JyZXNwb25kZW5jZS5zZXJ2aWNlLnRzXHJcblxyXG5pbXBvcnQge1xyXG4gIEluamVjdGFibGUsXHJcbiAgTm90Rm91bmRFeGNlcHRpb24sXHJcbiAgQmFkUmVxdWVzdEV4Y2VwdGlvbixcclxuICBJbnRlcm5hbFNlcnZlckVycm9yRXhjZXB0aW9uLFxyXG4gIEZvcmJpZGRlbkV4Y2VwdGlvbixcclxuICBMb2dnZXIsXHJcbn0gZnJvbSAnQG5lc3Rqcy9jb21tb24nO1xyXG5pbXBvcnQgeyBJbmplY3RSZXBvc2l0b3J5IH0gZnJvbSAnQG5lc3Rqcy90eXBlb3JtJztcclxuaW1wb3J0IHsgUmVwb3NpdG9yeSwgRGF0YVNvdXJjZSB9IGZyb20gJ3R5cGVvcm0nO1xyXG5cclxuLy8gRW50aXRpZXNcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2UgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmV2aXNpb24gfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJldmlzaW9uLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVHlwZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtdHlwZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVN0YXR1cyB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2Utc3RhdHVzLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZWZlcmVuY2UuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VSZWNpcGllbnQgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXJlY2lwaWVudC5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVRhZyB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtdGFnLmVudGl0eSc7XHJcbmltcG9ydCB7IFRhZyB9IGZyb20gJy4uL21hc3Rlci9lbnRpdGllcy90YWcuZW50aXR5JztcclxuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL3VzZXIvZW50aXRpZXMvdXNlci5lbnRpdHknO1xyXG5pbXBvcnQgeyBPcmdhbml6YXRpb24gfSBmcm9tICcuLi9vcmdhbml6YXRpb24vZW50aXRpZXMvb3JnYW5pemF0aW9uLmVudGl0eSc7XHJcblxyXG4vLyBEVE9zXHJcbmltcG9ydCB7IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vY3JlYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vdXBkYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IEFkZFJlZmVyZW5jZUR0byB9IGZyb20gJy4vZHRvL2FkZC1yZWZlcmVuY2UuZHRvJztcclxuaW1wb3J0IHsgU2VhcmNoQ29ycmVzcG9uZGVuY2VEdG8gfSBmcm9tICcuL2R0by9zZWFyY2gtY29ycmVzcG9uZGVuY2UuZHRvJztcclxuXHJcbi8vIFNlcnZpY2VzXHJcbmltcG9ydCB7IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSB9IGZyb20gJy4uL2RvY3VtZW50LW51bWJlcmluZy9zZXJ2aWNlcy9kb2N1bWVudC1udW1iZXJpbmcuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vanNvbi1zY2hlbWEvanNvbi1zY2hlbWEuc2VydmljZSc7XHJcbmltcG9ydCB7IFdvcmtmbG93RW5naW5lU2VydmljZSB9IGZyb20gJy4uL3dvcmtmbG93LWVuZ2luZS93b3JrZmxvdy1lbmdpbmUuc2VydmljZSc7XHJcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci91c2VyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vc2VhcmNoL3NlYXJjaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL2ZpbGUtc3RvcmFnZS9maWxlLXN0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IFV1aWRSZXNvbHZlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvdXVpZC1yZXNvbHZlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uc2VydmljZSc7XHJcblxyXG4vKipcclxuICogQ29ycmVzcG9uZGVuY2VTZXJ2aWNlIC0gRG9jdW1lbnQgbWFuYWdlbWVudCAoQ1JVRClcclxuICovXHJcbmludGVyZmFjZSBSZXNvbHZlZFJlY2lwaWVudCB7XHJcbiAgb3JnYW5pemF0aW9uSWQ6IG51bWJlcjtcclxuICB0eXBlOiAnVE8nIHwgJ0NDJztcclxufVxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBDb3JyZXNwb25kZW5jZVNlcnZpY2Uge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IExvZ2dlcihDb3JyZXNwb25kZW5jZVNlcnZpY2UubmFtZSk7XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgaGFzU3lzdGVtTWFuYWdlQWxsUGVybWlzc2lvbih1c2VySWQ6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyh1c2VySWQpO1xyXG4gICAgcmV0dXJuIHBlcm1pc3Npb25zLmluY2x1ZGVzKCdzeXN0ZW0ubWFuYWdlX2FsbCcpO1xyXG4gIH1cclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBASW5qZWN0UmVwb3NpdG9yeShDb3JyZXNwb25kZW5jZSlcclxuICAgIHByaXZhdGUgY29ycmVzcG9uZGVuY2VSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlUmV2aXNpb24pXHJcbiAgICBwcml2YXRlIHJldmlzaW9uUmVwbzogUmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVJldmlzaW9uPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlVHlwZSlcclxuICAgIHByaXZhdGUgdHlwZVJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VUeXBlPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlU3RhdHVzKVxyXG4gICAgcHJpdmF0ZSBzdGF0dXNSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlU3RhdHVzPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlKVxyXG4gICAgcHJpdmF0ZSByZWZlcmVuY2VSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlUmVmZXJlbmNlPixcclxuICAgIEBJbmplY3RSZXBvc2l0b3J5KENvcnJlc3BvbmRlbmNlVGFnKVxyXG4gICAgcHJpdmF0ZSB0YWdSZXBvOiBSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVGFnPixcclxuICAgIHByaXZhdGUgbnVtYmVyaW5nU2VydmljZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBqc29uU2NoZW1hU2VydmljZTogSnNvblNjaGVtYVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHdvcmtmbG93RW5naW5lOiBXb3JrZmxvd0VuZ2luZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHVzZXJTZXJ2aWNlOiBVc2VyU2VydmljZSxcclxuICAgIHByaXZhdGUgZGF0YVNvdXJjZTogRGF0YVNvdXJjZSxcclxuICAgIHByaXZhdGUgc2VhcmNoU2VydmljZTogU2VhcmNoU2VydmljZSxcclxuICAgIHByaXZhdGUgZmlsZVN0b3JhZ2VTZXJ2aWNlOiBGaWxlU3RvcmFnZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHV1aWRSZXNvbHZlcjogVXVpZFJlc29sdmVyU2VydmljZSxcclxuICAgIHByaXZhdGUgbm90aWZpY2F0aW9uU2VydmljZTogTm90aWZpY2F0aW9uU2VydmljZVxyXG4gICkge31cclxuXHJcbiAgLyoqXHJcbiAgICogQnVzaW5lc3MgUnVsZSBWYWxpZGF0aW9uOiBFQy1DT1JSLTAwMyAtIENvcnJlc3BvbmRlbmNlIHRvIFNlbGZcclxuICAgKiBQcmV2ZW50IGV4dGVybmFsIGNvcnJlc3BvbmRlbmNlIHRvIHNhbWUgb3JnYW5pemF0aW9uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhc3luYyB2YWxpZGF0ZUNvcnJlc3BvbmRlbmNlUmVjaXBpZW50cyhcclxuICAgIGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8sXHJcbiAgICB1c2VyOiBVc2VyXHJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAvLyBHZXQgdXNlcidzIG9yZ2FuaXphdGlvblxyXG4gICAgbGV0IHVzZXJPcmdJZCA9IHVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgY29uc3QgZnVsbFVzZXIgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmZpbmRPbmUodXNlci51c2VyX2lkKTtcclxuICAgICAgaWYgKGZ1bGxVc2VyKSB7XHJcbiAgICAgICAgdXNlck9yZ0lkID0gZnVsbFVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgaWYgKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpIHtcclxuICAgICAgICBjb25zdCBjYW5NYW5hZ2VBbGwgPSBhd2FpdCB0aGlzLmhhc1N5c3RlbU1hbmFnZUFsbFBlcm1pc3Npb24oXHJcbiAgICAgICAgICB1c2VyLnVzZXJfaWRcclxuICAgICAgICApO1xyXG4gICAgICAgIGlmIChjYW5NYW5hZ2VBbGwpIHtcclxuICAgICAgICAgIHVzZXJPcmdJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICAgICAgY3JlYXRlRHRvLm9yaWdpbmF0b3JJZFxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgICAnVXNlciBtdXN0IGJlbG9uZyB0byBhbiBvcmdhbml6YXRpb24gdG8gY3JlYXRlIGRvY3VtZW50cydcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9yIGltcGVyc29uYXRpb24sIHVzZSB0aGUgc3BlY2lmaWVkIG9yaWdpbmF0b3JcclxuICAgIGNvbnN0IG9yaWdpbmF0b3JPcmdJZCA9IGNyZWF0ZUR0by5vcmlnaW5hdG9ySWRcclxuICAgICAgPyBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoY3JlYXRlRHRvLm9yaWdpbmF0b3JJZClcclxuICAgICAgOiB1c2VyT3JnSWQ7XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgaXQncyBpbnRlcm5hbCBjb21tdW5pY2F0aW9uXHJcbiAgICBpZiAoY3JlYXRlRHRvLmlzSW50ZXJuYWwpIHtcclxuICAgICAgLy8gSW50ZXJuYWwgY29tbXVuaWNhdGlvbnMgc2hvdWxkIHVzZSBDaXJjdWxhdGlvbiBpbnN0ZWFkXHJcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxyXG4gICAgICAgICdJbnRlcm5hbCBjb21tdW5pY2F0aW9ucyBzaG91bGQgdXNlIENpcmN1bGF0aW9uIFNoZWV0IGluc3RlYWQgb2YgQ29ycmVzcG9uZGVuY2UnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVmFsaWRhdGUgcmVjaXBpZW50c1xyXG4gICAgaWYgKCFjcmVhdGVEdG8ucmVjaXBpZW50cyB8fCBjcmVhdGVEdG8ucmVjaXBpZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgJ0F0IGxlYXN0IG9uZSByZWNpcGllbnQgKFRPIG9yIENDKSBpcyByZXF1aXJlZCdcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB0b1JlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50cy5maWx0ZXIoKHIpID0+IHIudHlwZSA9PT0gJ1RPJyk7XHJcbiAgICBjb25zdCBjY1JlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50cy5maWx0ZXIoKHIpID0+IHIudHlwZSA9PT0gJ0NDJyk7XHJcblxyXG4gICAgaWYgKHRvUmVjaXBpZW50cy5sZW5ndGggPT09IDAgJiYgY2NSZWNpcGllbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcclxuICAgICAgICAnQXQgbGVhc3Qgb25lIFRPIG9yIENDIHJlY2lwaWVudCBpcyByZXF1aXJlZCdcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDaGVjayBmb3Igc2FtZSBvcmdhbml6YXRpb24gY29ycmVzcG9uZGVuY2VcclxuICAgIGZvciAoY29uc3QgcmVjaXBpZW50IG9mIGNyZWF0ZUR0by5yZWNpcGllbnRzKSB7XHJcbiAgICAgIGNvbnN0IHJlY2lwaWVudE9yZ0lkID0gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKFxyXG4gICAgICAgIHJlY2lwaWVudC5vcmdhbml6YXRpb25JZFxyXG4gICAgICApO1xyXG5cclxuICAgICAgaWYgKHJlY2lwaWVudE9yZ0lkID09PSBvcmlnaW5hdG9yT3JnSWQpIHtcclxuICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcclxuICAgICAgICAgICdDYW5ub3Qgc2VuZCBjb3JyZXNwb25kZW5jZSB0byB5b3VyIG93biBvcmdhbml6YXRpb24uIFVzZSBDaXJjdWxhdGlvbiBTaGVldCBmb3IgaW50ZXJuYWwgY29tbXVuaWNhdGlvbi4nXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgY3JlYXRlKGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8sIHVzZXI6IFVzZXIpIHtcclxuICAgIC8vIEJ1c2luZXNzIFJ1bGUgVmFsaWRhdGlvbjogRUMtQ09SUi0wMDMgLSBDb3JyZXNwb25kZW5jZSB0byBTZWxmXHJcbiAgICBhd2FpdCB0aGlzLnZhbGlkYXRlQ29ycmVzcG9uZGVuY2VSZWNpcGllbnRzKGNyZWF0ZUR0bywgdXNlcik7XHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIFVVSUQgcmVmZXJlbmNlcyB0byBpbnRlcm5hbCBJTlQgSURzXHJcbiAgICBjb25zdCByZXNvbHZlZFByb2plY3RJZCA9IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVQcm9qZWN0SWQoXHJcbiAgICAgIGNyZWF0ZUR0by5wcm9qZWN0SWRcclxuICAgICk7XHJcbiAgICBjb25zdCByZXNvbHZlZE9yaWdpbmF0b3JJZCA9IGNyZWF0ZUR0by5vcmlnaW5hdG9ySWRcclxuICAgICAgPyBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoY3JlYXRlRHRvLm9yaWdpbmF0b3JJZClcclxuICAgICAgOiB1bmRlZmluZWQ7XHJcbiAgICBjb25zdCByZXNvbHZlZFJlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50c1xyXG4gICAgICA/IGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgY3JlYXRlRHRvLnJlY2lwaWVudHMubWFwKFxyXG4gICAgICAgICAgICBhc3luYyAocik6IFByb21pc2U8UmVzb2x2ZWRSZWNpcGllbnQ+ID0+ICh7XHJcbiAgICAgICAgICAgICAgb3JnYW5pemF0aW9uSWQ6IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICAgICAgICAgIHIub3JnYW5pemF0aW9uSWRcclxuICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgICAgIHR5cGU6IHIudHlwZSxcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgIClcclxuICAgICAgICApXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgdHlwZSA9IGF3YWl0IHRoaXMudHlwZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGlkOiBjcmVhdGVEdG8udHlwZUlkIH0sXHJcbiAgICB9KTtcclxuICAgIGlmICghdHlwZSkgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdEb2N1bWVudCBUeXBlIG5vdCBmb3VuZCcpO1xyXG5cclxuICAgIGNvbnN0IHN0YXR1c0RyYWZ0ID0gYXdhaXQgdGhpcy5zdGF0dXNSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBzdGF0dXNDb2RlOiAnRFJBRlQnIH0sXHJcbiAgICB9KTtcclxuICAgIGlmICghc3RhdHVzRHJhZnQpIHtcclxuICAgICAgdGhyb3cgbmV3IEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24oXHJcbiAgICAgICAgJ1N0YXR1cyBEUkFGVCBub3QgZm91bmQgaW4gTWFzdGVyIERhdGEnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHVzZXJPcmdJZCA9IHVzZXIucHJpbWFyeU9yZ2FuaXphdGlvbklkO1xyXG5cclxuICAgIGlmICghdXNlck9yZ0lkKSB7XHJcbiAgICAgIGNvbnN0IGZ1bGxVc2VyID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5maW5kT25lKHVzZXIudXNlcl9pZCk7XHJcbiAgICAgIGlmIChmdWxsVXNlcikge1xyXG4gICAgICAgIHVzZXJPcmdJZCA9IGZ1bGxVc2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIEltcGVyc29uYXRpb24gTG9naWNcclxuICAgIGlmIChyZXNvbHZlZE9yaWdpbmF0b3JJZCAmJiByZXNvbHZlZE9yaWdpbmF0b3JJZCAhPT0gdXNlck9yZ0lkKSB7XHJcbiAgICAgIGNvbnN0IGNhbk1hbmFnZUFsbCA9IGF3YWl0IHRoaXMuaGFzU3lzdGVtTWFuYWdlQWxsUGVybWlzc2lvbihcclxuICAgICAgICB1c2VyLnVzZXJfaWRcclxuICAgICAgKTtcclxuICAgICAgaWYgKCFjYW5NYW5hZ2VBbGwpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRm9yYmlkZGVuRXhjZXB0aW9uKFxyXG4gICAgICAgICAgJ1lvdSBkbyBub3QgaGF2ZSBwZXJtaXNzaW9uIHRvIGNyZWF0ZSBkb2N1bWVudHMgb24gYmVoYWxmIG9mIG90aGVyIG9yZ2FuaXphdGlvbnMuJ1xyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgICAgdXNlck9yZ0lkID0gcmVzb2x2ZWRPcmlnaW5hdG9ySWQ7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF1c2VyT3JnSWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXHJcbiAgICAgICAgJ1VzZXIgbXVzdCBiZWxvbmcgdG8gYW4gb3JnYW5pemF0aW9uIHRvIGNyZWF0ZSBkb2N1bWVudHMnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNyZWF0ZUR0by5kZXRhaWxzKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5qc29uU2NoZW1hU2VydmljZS52YWxpZGF0ZSh0eXBlLnR5cGVDb2RlLCBjcmVhdGVEdG8uZGV0YWlscyk7XHJcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XHJcbiAgICAgICAgdGhpcy5sb2dnZXIud2FybihcclxuICAgICAgICAgIGBTY2hlbWEgdmFsaWRhdGlvbiB3YXJuaW5nIGZvciAke3R5cGUudHlwZUNvZGV9OiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0gdGhpcy5kYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyKCk7XHJcbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5jb25uZWN0KCk7XHJcbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5zdGFydFRyYW5zYWN0aW9uKCk7XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgLy8gW0ZpeCAjNl0gRmV0Y2ggcmVhbCBPUkcgQ29kZSBmcm9tIE9yZ2FuaXphdGlvbiBlbnRpdHlcclxuICAgICAgY29uc3Qgb3JpZ2luYXRvck9yZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoXHJcbiAgICAgICAgT3JnYW5pemF0aW9uLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHdoZXJlOiB7IGlkOiB1c2VyT3JnSWQgfSxcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IG9yZ0NvZGUgPSBvcmlnaW5hdG9yT3JnPy5vcmdhbml6YXRpb25Db2RlID8/ICdVTksnO1xyXG5cclxuICAgICAgLy8gW3YxLjUuMV0gRXh0cmFjdCByZWNpcGllbnQgb3JnYW5pemF0aW9uIGZyb20gcmVjaXBpZW50cyBhcnJheSAoUHJpbWFyeSBUTylcclxuICAgICAgY29uc3QgdG9SZWNpcGllbnQgPSByZXNvbHZlZFJlY2lwaWVudHM/LmZpbmQoKHIpID0+IHIudHlwZSA9PT0gJ1RPJyk7XHJcbiAgICAgIGNvbnN0IHJlY2lwaWVudE9yZ2FuaXphdGlvbklkID0gdG9SZWNpcGllbnQ/Lm9yZ2FuaXphdGlvbklkO1xyXG5cclxuICAgICAgbGV0IHJlY2lwaWVudENvZGUgPSAnJztcclxuICAgICAgaWYgKHJlY2lwaWVudE9yZ2FuaXphdGlvbklkKSB7XHJcbiAgICAgICAgY29uc3QgcmVjT3JnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShPcmdhbml6YXRpb24sIHtcclxuICAgICAgICAgIHdoZXJlOiB7IGlkOiByZWNpcGllbnRPcmdhbml6YXRpb25JZCB9LFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmIChyZWNPcmcpIHJlY2lwaWVudENvZGUgPSByZWNPcmcub3JnYW5pemF0aW9uQ29kZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgZG9jTnVtYmVyID0gYXdhaXQgdGhpcy5udW1iZXJpbmdTZXJ2aWNlLmdlbmVyYXRlTmV4dE51bWJlcih7XHJcbiAgICAgICAgcHJvamVjdElkOiByZXNvbHZlZFByb2plY3RJZCxcclxuICAgICAgICBvcmlnaW5hdG9yT3JnYW5pemF0aW9uSWQ6IHVzZXJPcmdJZCxcclxuICAgICAgICB0eXBlSWQ6IGNyZWF0ZUR0by50eXBlSWQsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiBjcmVhdGVEdG8uZGlzY2lwbGluZUlkLFxyXG4gICAgICAgIHN1YlR5cGVJZDogY3JlYXRlRHRvLnN1YlR5cGVJZCxcclxuICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZCwgLy8gW3YxLjUuMV0gUGFzcyByZWNpcGllbnQgZm9yIGRvY3VtZW50IG51bWJlciBmb3JtYXRcclxuICAgICAgICB5ZWFyOiBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCksXHJcbiAgICAgICAgY3VzdG9tVG9rZW5zOiB7XHJcbiAgICAgICAgICBUWVBFX0NPREU6IHR5cGUudHlwZUNvZGUsXHJcbiAgICAgICAgICBPUkdfQ09ERTogb3JnQ29kZSxcclxuICAgICAgICAgIFJFQ0lQSUVOVF9DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgICAgUkVDX0NPREU6IHJlY2lwaWVudENvZGUsXHJcbiAgICAgICAgfSxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKENvcnJlc3BvbmRlbmNlLCB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6IGRvY051bWJlci5udW1iZXIsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IGNyZWF0ZUR0by50eXBlSWQsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiBjcmVhdGVEdG8uZGlzY2lwbGluZUlkLFxyXG4gICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiB1c2VyT3JnSWQsXHJcbiAgICAgICAgaXNJbnRlcm5hbDogY3JlYXRlRHRvLmlzSW50ZXJuYWwgfHwgZmFsc2UsXHJcbiAgICAgICAgY3JlYXRlZEJ5OiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgIH0pO1xyXG4gICAgICBjb25zdCBzYXZlZENvcnIgPSBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnNhdmUoY29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgcmV2aXNpb24gPSBxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZShDb3JyZXNwb25kZW5jZVJldmlzaW9uLCB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogc2F2ZWRDb3JyLmlkLFxyXG4gICAgICAgIHJldmlzaW9uTnVtYmVyOiAwLFxyXG4gICAgICAgIHJldmlzaW9uTGFiZWw6ICdBJyxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IHN0YXR1c0RyYWZ0LmlkLFxyXG4gICAgICAgIHN1YmplY3Q6IGNyZWF0ZUR0by5zdWJqZWN0LFxyXG4gICAgICAgIGJvZHk6IGNyZWF0ZUR0by5ib2R5LFxyXG4gICAgICAgIHJlbWFya3M6IGNyZWF0ZUR0by5yZW1hcmtzLFxyXG4gICAgICAgIGR1ZURhdGU6IGNyZWF0ZUR0by5kdWVEYXRlID8gbmV3IERhdGUoY3JlYXRlRHRvLmR1ZURhdGUpIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIGRvY3VtZW50RGF0ZTogY3JlYXRlRHRvLmRvY3VtZW50RGF0ZVxyXG4gICAgICAgICAgPyBuZXcgRGF0ZShjcmVhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICAgICAgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgaXNzdWVkRGF0ZTogY3JlYXRlRHRvLmlzc3VlZERhdGVcclxuICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcclxuICAgICAgICByZWNlaXZlZERhdGU6IGNyZWF0ZUR0by5yZWNlaXZlZERhdGVcclxuICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLnJlY2VpdmVkRGF0ZSlcclxuICAgICAgICAgIDogdW5kZWZpbmVkLFxyXG4gICAgICAgIGRlc2NyaXB0aW9uOiBjcmVhdGVEdG8uZGVzY3JpcHRpb24sXHJcbiAgICAgICAgZGV0YWlsczogY3JlYXRlRHRvLmRldGFpbHMsXHJcbiAgICAgICAgY3JlYXRlZEJ5OiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgICAgc2NoZW1hVmVyc2lvbjogMSxcclxuICAgICAgfSk7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIuc2F2ZShyZXZpc2lvbik7XHJcblxyXG4gICAgICAvLyBTYXZlIFJlY2lwaWVudHMgKHVzaW5nIHJlc29sdmVkIElOVCBJRHMpXHJcbiAgICAgIGlmIChyZXNvbHZlZFJlY2lwaWVudHMgJiYgcmVzb2x2ZWRSZWNpcGllbnRzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBjb25zdCByZWNpcGllbnRzID0gcmVzb2x2ZWRSZWNpcGllbnRzLm1hcCgocikgPT5cclxuICAgICAgICAgIHF1ZXJ5UnVubmVyLm1hbmFnZXIuY3JlYXRlKENvcnJlc3BvbmRlbmNlUmVjaXBpZW50LCB7XHJcbiAgICAgICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IHNhdmVkQ29yci5pZCxcclxuICAgICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IHIub3JnYW5pemF0aW9uSWQsXHJcbiAgICAgICAgICAgIHJlY2lwaWVudFR5cGU6IHIudHlwZSxcclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgICAgICBhd2FpdCBxdWVyeVJ1bm5lci5tYW5hZ2VyLnNhdmUocmVjaXBpZW50cyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIENvbW1pdCBhdHRhY2htZW50cyBmcm9tIFRlbXAg4oaSIFBlcm1hbmVudCAoVHdvLVBoYXNlIFN0b3JhZ2UpXHJcbiAgICAgIGlmIChjcmVhdGVEdG8uYXR0YWNobWVudFRlbXBJZHM/Lmxlbmd0aCkge1xyXG4gICAgICAgIGNvbnN0IGlzc3VlRGF0ZSA9IGNyZWF0ZUR0by5pc3N1ZWREYXRlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKGNyZWF0ZUR0by5pc3N1ZWREYXRlKVxyXG4gICAgICAgICAgOiBjcmVhdGVEdG8uZG9jdW1lbnREYXRlXHJcbiAgICAgICAgICAgID8gbmV3IERhdGUoY3JlYXRlRHRvLmRvY3VtZW50RGF0ZSlcclxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XHJcblxyXG4gICAgICAgIGF3YWl0IHRoaXMuZmlsZVN0b3JhZ2VTZXJ2aWNlLmNvbW1pdChjcmVhdGVEdG8uYXR0YWNobWVudFRlbXBJZHMsIHtcclxuICAgICAgICAgIGlzc3VlRGF0ZSxcclxuICAgICAgICAgIGRvY3VtZW50VHlwZTogJ0NvcnJlc3BvbmRlbmNlJyxcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIuY29tbWl0VHJhbnNhY3Rpb24oKTtcclxuXHJcbiAgICAgIC8vIFN0YXJ0IFdvcmtmbG93IEluc3RhbmNlIChub24tYmxvY2tpbmcpXHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3Qgd29ya2Zsb3dDb2RlID0gYENPUlJFU1BPTkRFTkNFXyR7dHlwZS50eXBlQ29kZX1gO1xyXG4gICAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dFbmdpbmUuY3JlYXRlSW5zdGFuY2UoXHJcbiAgICAgICAgICB3b3JrZmxvd0NvZGUsXHJcbiAgICAgICAgICAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgICAgc2F2ZWRDb3JyLmlkLnRvU3RyaW5nKCksXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHByb2plY3RJZDogcmVzb2x2ZWRQcm9qZWN0SWQsXHJcbiAgICAgICAgICAgIG9yaWdpbmF0b3JJZDogdXNlck9yZ0lkLFxyXG4gICAgICAgICAgICBkaXNjaXBsaW5lSWQ6IGNyZWF0ZUR0by5kaXNjaXBsaW5lSWQsXHJcbiAgICAgICAgICAgIGluaXRpYXRvcklkOiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgICAgICB9IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+XHJcbiAgICAgICAgKTtcclxuICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcclxuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFxyXG4gICAgICAgICAgYFdvcmtmbG93IG5vdCBzdGFydGVkIGZvciAke2RvY051bWJlci5udW1iZXJ9IChDb2RlOiBDT1JSRVNQT05ERU5DRV8ke3R5cGUudHlwZUNvZGV9KTogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIEZpcmUtYW5kLWZvcmdldCBzZWFyY2ggaW5kZXhpbmcgKG5vbi1ibG9ja2luZywgdm9pZCBpbnRlbnRpb25hbClcclxuICAgICAgdm9pZCB0aGlzLnNlYXJjaFNlcnZpY2UuaW5kZXhEb2N1bWVudCh7XHJcbiAgICAgICAgaWQ6IHNhdmVkQ29yci5pZCxcclxuICAgICAgICBwdWJsaWNJZDogc2F2ZWRDb3JyLnB1YmxpY0lkLFxyXG4gICAgICAgIHR5cGU6ICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgICAgZG9jTnVtYmVyOiBkb2NOdW1iZXIubnVtYmVyLFxyXG4gICAgICAgIHRpdGxlOiBjcmVhdGVEdG8uc3ViamVjdCxcclxuICAgICAgICBkZXNjcmlwdGlvbjogY3JlYXRlRHRvLmRlc2NyaXB0aW9uLFxyXG4gICAgICAgIHN0YXR1czogJ0RSQUZUJyxcclxuICAgICAgICBwcm9qZWN0SWQ6IHJlc29sdmVkUHJvamVjdElkLFxyXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKSxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIC4uLnNhdmVkQ29ycixcclxuICAgICAgICBjdXJyZW50UmV2aXNpb246IHJldmlzaW9uLFxyXG4gICAgICB9O1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcclxuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXHJcbiAgICAgICAgYEZhaWxlZCB0byBjcmVhdGUgY29ycmVzcG9uZGVuY2U6ICR7KGVyciBhcyBFcnJvcikubWVzc2FnZX1gXHJcbiAgICAgICk7XHJcbiAgICAgIHRocm93IGVycjtcclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJlbGVhc2UoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGZpbmRBbGwoc2VhcmNoRHRvOiBTZWFyY2hDb3JyZXNwb25kZW5jZUR0byA9IHt9KSB7XHJcbiAgICBjb25zdCB7XHJcbiAgICAgIHNlYXJjaCxcclxuICAgICAgdHlwZUlkLFxyXG4gICAgICBwcm9qZWN0SWQsXHJcbiAgICAgIHN0YXR1c0lkLFxyXG4gICAgICBzdGF0dXMsXHJcbiAgICAgIHBhZ2UgPSAxLFxyXG4gICAgICBsaW1pdCA9IDEwLFxyXG4gICAgfSA9IHNlYXJjaER0bztcclxuICAgIGNvbnN0IHNraXAgPSAocGFnZSAtIDEpICogbGltaXQ7XHJcblxyXG4gICAgLy8gQ2hhbmdlOiBRdWVyeSBmcm9tIFJldmlzaW9uIFJlcG9cclxuICAgIGNvbnN0IHF1ZXJ5ID0gdGhpcy5yZXZpc2lvblJlcG9cclxuICAgICAgLmNyZWF0ZVF1ZXJ5QnVpbGRlcigncmV2JylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdyZXYuY29ycmVzcG9uZGVuY2UnLCAnY29ycicpXHJcbiAgICAgIC5sZWZ0Sm9pbkFuZFNlbGVjdCgnY29yci50eXBlJywgJ3R5cGUnKVxyXG4gICAgICAubGVmdEpvaW5BbmRTZWxlY3QoJ2NvcnIucHJvamVjdCcsICdwcm9qZWN0JylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdjb3JyLm9yaWdpbmF0b3InLCAnb3JnJylcclxuICAgICAgLmxlZnRKb2luQW5kU2VsZWN0KCdyZXYuc3RhdHVzJywgJ3N0YXR1cycpO1xyXG5cclxuICAgIC8vIEZpbHRlciBieSBSZXZpc2lvbiBTdGF0dXNcclxuICAgIGNvbnN0IHJldlN0YXR1cyA9IHNlYXJjaER0by5yZXZpc2lvblN0YXR1cyB8fCAnQ1VSUkVOVCc7XHJcblxyXG4gICAgaWYgKHJldlN0YXR1cyA9PT0gJ0NVUlJFTlQnKSB7XHJcbiAgICAgIHF1ZXJ5LndoZXJlKCdyZXYuaXNDdXJyZW50ID0gOmlzQ3VycmVudCcsIHsgaXNDdXJyZW50OiB0cnVlIH0pO1xyXG4gICAgfSBlbHNlIGlmIChyZXZTdGF0dXMgPT09ICdPTEQnKSB7XHJcbiAgICAgIHF1ZXJ5LndoZXJlKCdyZXYuaXNDdXJyZW50ID0gOmlzQ3VycmVudCcsIHsgaXNDdXJyZW50OiBmYWxzZSB9KTtcclxuICAgIH1cclxuICAgIC8vIElmICdBTEwnLCBubyBmaWx0ZXIgbmVlZGVkIG9uIGlzQ3VycmVudFxyXG5cclxuICAgIGlmIChwcm9qZWN0SWQpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ2NvcnIucHJvamVjdElkID0gOnByb2plY3RJZCcsIHsgcHJvamVjdElkIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlSWQpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ2NvcnIuY29ycmVzcG9uZGVuY2VUeXBlSWQgPSA6dHlwZUlkJywgeyB0eXBlSWQgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHN0YXR1c0lkKSB7XHJcbiAgICAgIHF1ZXJ5LmFuZFdoZXJlKCdyZXYuc3RhdHVzSWQgPSA6c3RhdHVzSWQnLCB7IHN0YXR1c0lkIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChzdGF0dXMpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoJ3N0YXR1cy5zdGF0dXNDb2RlID0gOnN0YXR1cycsIHsgc3RhdHVzIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChzZWFyY2gpIHtcclxuICAgICAgcXVlcnkuYW5kV2hlcmUoXHJcbiAgICAgICAgJyhjb3JyLmNvcnJlc3BvbmRlbmNlTnVtYmVyIExJS0UgOnNlYXJjaCBPUiByZXYuc3ViamVjdCBMSUtFIDpzZWFyY2gpJyxcclxuICAgICAgICB7IHNlYXJjaDogYCUke3NlYXJjaH0lYCB9XHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRGVmYXVsdCBTb3J0OiBMYXRlc3QgQ3JlYXRlZFxyXG4gICAgcXVlcnkub3JkZXJCeSgncmV2LmNyZWF0ZWRBdCcsICdERVNDJykuc2tpcChza2lwKS50YWtlKGxpbWl0KTtcclxuXHJcbiAgICBjb25zdCBbaXRlbXMsIHRvdGFsXSA9IGF3YWl0IHF1ZXJ5LmdldE1hbnlBbmRDb3VudCgpO1xyXG5cclxuICAgIHJldHVybiB7XHJcbiAgICAgIGRhdGE6IGl0ZW1zLFxyXG4gICAgICBtZXRhOiB7XHJcbiAgICAgICAgdG90YWwsXHJcbiAgICAgICAgcGFnZSxcclxuICAgICAgICBsaW1pdCxcclxuICAgICAgICB0b3RhbFBhZ2VzOiBNYXRoLmNlaWwodG90YWwgLyBsaW1pdCksXHJcbiAgICAgIH0sXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZmluZE9uZShpZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFtcclxuICAgICAgICAncmV2aXNpb25zJyxcclxuICAgICAgICAncmV2aXNpb25zLnN0YXR1cycsXHJcbiAgICAgICAgJ3R5cGUnLFxyXG4gICAgICAgICdwcm9qZWN0JyxcclxuICAgICAgICAnb3JpZ2luYXRvcicsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMnLFxyXG4gICAgICAgICdyZWNpcGllbnRzLnJlY2lwaWVudE9yZ2FuaXphdGlvbicsIC8vIFt2MS41LjFdIEZpeGVkIHJlbGF0aW9uIG5hbWVcclxuICAgICAgXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICghY29ycmVzcG9uZGVuY2UpIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKGBDb3JyZXNwb25kZW5jZSB3aXRoIElEICR7aWR9IG5vdCBmb3VuZGApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGNvcnJlc3BvbmRlbmNlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZmluZE9uZUJ5VXVpZChwdWJsaWNJZDogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBjb3JyZXNwb25kZW5jZSA9IGF3YWl0IHRoaXMuY29ycmVzcG9uZGVuY2VSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBwdWJsaWNJZCB9LFxyXG4gICAgICByZWxhdGlvbnM6IFtcclxuICAgICAgICAncmV2aXNpb25zJyxcclxuICAgICAgICAncmV2aXNpb25zLnN0YXR1cycsXHJcbiAgICAgICAgJ3R5cGUnLFxyXG4gICAgICAgICdwcm9qZWN0JyxcclxuICAgICAgICAnb3JpZ2luYXRvcicsXHJcbiAgICAgICAgJ3JlY2lwaWVudHMnLFxyXG4gICAgICAgICdyZWNpcGllbnRzLnJlY2lwaWVudE9yZ2FuaXphdGlvbicsXHJcbiAgICAgIF0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIWNvcnJlc3BvbmRlbmNlKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihcclxuICAgICAgICBgQ29ycmVzcG9uZGVuY2Ugd2l0aCBVVUlEICR7cHVibGljSWR9IG5vdCBmb3VuZGBcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIHJldHVybiBjb3JyZXNwb25kZW5jZTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGFkZFJlZmVyZW5jZShpZDogbnVtYmVyLCBkdG86IEFkZFJlZmVyZW5jZUR0bykge1xyXG4gICAgY29uc3Qgc291cmNlID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7IHdoZXJlOiB7IGlkIH0gfSk7XHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIHRhcmdldCBwdWJsaWNJZCDihpIgaW50ZXJuYWwgSU5UIGlkXHJcbiAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgcHVibGljSWQ6IGR0by50YXJnZXRVdWlkIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIXNvdXJjZSB8fCAhdGFyZ2V0KSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignU291cmNlIG9yIFRhcmdldCBjb3JyZXNwb25kZW5jZSBub3QgZm91bmQnKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoc291cmNlLmlkID09PSB0YXJnZXQuaWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oJ0Nhbm5vdCByZWZlcmVuY2Ugc2VsZicpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGV4aXN0cyA9IGF3YWl0IHRoaXMucmVmZXJlbmNlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHtcclxuICAgICAgICBzb3VyY2VJZDogaWQsXHJcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldC5pZCxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChleGlzdHMpIHtcclxuICAgICAgcmV0dXJuIGV4aXN0cztcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCByZWYgPSB0aGlzLnJlZmVyZW5jZVJlcG8uY3JlYXRlKHtcclxuICAgICAgc291cmNlSWQ6IGlkLFxyXG4gICAgICB0YXJnZXRJZDogdGFyZ2V0LmlkLFxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMucmVmZXJlbmNlUmVwby5zYXZlKHJlZik7XHJcbiAgfVxyXG5cclxuICBhc3luYyByZW1vdmVSZWZlcmVuY2UoaWQ6IG51bWJlciwgdGFyZ2V0SWQ6IG51bWJlcikge1xyXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmRlbGV0ZSh7XHJcbiAgICAgIHNvdXJjZUlkOiBpZCxcclxuICAgICAgdGFyZ2V0SWQ6IHRhcmdldElkLFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKHJlc3VsdC5hZmZlY3RlZCA9PT0gMCkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ1JlZmVyZW5jZSBub3QgZm91bmQnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGdldFRhZ3MoaWQ6IG51bWJlcikge1xyXG4gICAgY29uc3Qgcm93cyA9IGF3YWl0IHRoaXMudGFnUmVwby5maW5kKHtcclxuICAgICAgd2hlcmU6IHsgY29ycmVzcG9uZGVuY2VJZDogaWQgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ3RhZyddLFxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gcm93cy5tYXAoKHIpID0+IHIudGFnKS5maWx0ZXIoQm9vbGVhbik7XHJcbiAgfVxyXG5cclxuICBhc3luYyBhZGRUYWcoaWQ6IG51bWJlciwgdGFnSWQ6IG51bWJlcikge1xyXG4gICAgY29uc3QgY29ycmVzcG9uZGVuY2UgPSBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby5maW5kT25lKHtcclxuICAgICAgd2hlcmU6IHsgaWQgfSxcclxuICAgIH0pO1xyXG4gICAgaWYgKCFjb3JyZXNwb25kZW5jZSkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oYENvcnJlc3BvbmRlbmNlICR7aWR9IG5vdCBmb3VuZGApO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHRhZyA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoVGFnLCB7XHJcbiAgICAgIHdoZXJlOiB7IGlkOiB0YWdJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXRhZykge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oYFRhZyAke3RhZ0lkfSBub3QgZm91bmRgKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBleGlzdHMgPSBhd2FpdCB0aGlzLnRhZ1JlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGNvcnJlc3BvbmRlbmNlSWQ6IGlkLCB0YWdJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoZXhpc3RzKSByZXR1cm4gZXhpc3RzO1xyXG5cclxuICAgIGNvbnN0IHJvdyA9IHRoaXMudGFnUmVwby5jcmVhdGUoeyBjb3JyZXNwb25kZW5jZUlkOiBpZCwgdGFnSWQgfSk7XHJcbiAgICByZXR1cm4gdGhpcy50YWdSZXBvLnNhdmUocm93KTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHJlbW92ZVRhZyhpZDogbnVtYmVyLCB0YWdJZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnRhZ1JlcG8uZGVsZXRlKHsgY29ycmVzcG9uZGVuY2VJZDogaWQsIHRhZ0lkIH0pO1xyXG4gICAgaWYgKHJlc3VsdC5hZmZlY3RlZCA9PT0gMCkge1xyXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ1RhZyBhc3NpZ25tZW50IG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgZ2V0UmVmZXJlbmNlcyhpZDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBvdXRnb2luZyA9IGF3YWl0IHRoaXMucmVmZXJlbmNlUmVwby5maW5kKHtcclxuICAgICAgd2hlcmU6IHsgc291cmNlSWQ6IGlkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogWyd0YXJnZXQnLCAndGFyZ2V0LnR5cGUnXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IGluY29taW5nID0gYXdhaXQgdGhpcy5yZWZlcmVuY2VSZXBvLmZpbmQoe1xyXG4gICAgICB3aGVyZTogeyB0YXJnZXRJZDogaWQgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ3NvdXJjZScsICdzb3VyY2UudHlwZSddLFxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHsgb3V0Z29pbmcsIGluY29taW5nIH07XHJcbiAgfVxyXG5cclxuICBhc3luYyB1cGRhdGUoaWQ6IG51bWJlciwgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0bywgdXNlcjogVXNlcikge1xyXG4gICAgLy8gMS4gRmluZCBDdXJyZW50IFJldmlzaW9uXHJcbiAgICBjb25zdCByZXZpc2lvbiA9IGF3YWl0IHRoaXMucmV2aXNpb25SZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZToge1xyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGlkLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgfSxcclxuICAgICAgcmVsYXRpb25zOiBbJ2NvcnJlc3BvbmRlbmNlJ10sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIXJldmlzaW9uKSB7XHJcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihcclxuICAgICAgICBgQ3VycmVudCByZXZpc2lvbiBmb3IgY29ycmVzcG9uZGVuY2UgJHtpZH0gbm90IGZvdW5kYFxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDIuIENoZWNrIFBlcm1pc3Npb25cclxuICAgIGlmIChyZXZpc2lvbi5zdGF0dXNJZCkge1xyXG4gICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCB0aGlzLnN0YXR1c1JlcG8uZmluZE9uZSh7XHJcbiAgICAgICAgd2hlcmU6IHsgaWQ6IHJldmlzaW9uLnN0YXR1c0lkIH0sXHJcbiAgICAgIH0pO1xyXG4gICAgICBpZiAoc3RhdHVzICYmIHN0YXR1cy5zdGF0dXNDb2RlICE9PSAnRFJBRlQnKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oJ09ubHkgRFJBRlQgZG9jdW1lbnRzIGNhbiBiZSB1cGRhdGVkJyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBBRFItMDE5OiBSZXNvbHZlIFVVSUQgcmVmZXJlbmNlcyBpbiB1cGRhdGUgRFRPXHJcbiAgICBjb25zdCB1cGRSZXNvbHZlZFByb2plY3RJZCA9IHVwZGF0ZUR0by5wcm9qZWN0SWRcclxuICAgICAgPyBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkKHVwZGF0ZUR0by5wcm9qZWN0SWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgdXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQgPSB1cGRhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKHVwZGF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgdXBkUmVzb2x2ZWRSZWNpcGllbnRzID0gdXBkYXRlRHRvLnJlY2lwaWVudHNcclxuICAgICAgPyBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgIHVwZGF0ZUR0by5yZWNpcGllbnRzLm1hcChcclxuICAgICAgICAgICAgYXN5bmMgKHIpOiBQcm9taXNlPFJlc29sdmVkUmVjaXBpZW50PiA9PiAoe1xyXG4gICAgICAgICAgICAgIG9yZ2FuaXphdGlvbklkOiBhd2FpdCB0aGlzLnV1aWRSZXNvbHZlci5yZXNvbHZlT3JnYW5pemF0aW9uSWQoXHJcbiAgICAgICAgICAgICAgICByLm9yZ2FuaXphdGlvbklkXHJcbiAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICB0eXBlOiByLnR5cGUsXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgKVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICAvLyAzLiBVcGRhdGUgQ29ycmVzcG9uZGVuY2UgRW50aXR5IGlmIG5lZWRlZFxyXG4gICAgY29uc3QgY29ycmVzcG9uZGVuY2VVcGRhdGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XHJcbiAgICBpZiAodXBkYXRlRHRvLmRpc2NpcGxpbmVJZClcclxuICAgICAgY29ycmVzcG9uZGVuY2VVcGRhdGUuZGlzY2lwbGluZUlkID0gdXBkYXRlRHRvLmRpc2NpcGxpbmVJZDtcclxuICAgIGlmICh1cGRSZXNvbHZlZFByb2plY3RJZClcclxuICAgICAgY29ycmVzcG9uZGVuY2VVcGRhdGUucHJvamVjdElkID0gdXBkUmVzb2x2ZWRQcm9qZWN0SWQ7XHJcbiAgICBpZiAodXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQpXHJcbiAgICAgIGNvcnJlc3BvbmRlbmNlVXBkYXRlLm9yaWdpbmF0b3JJZCA9IHVwZFJlc29sdmVkT3JpZ2luYXRvcklkO1xyXG5cclxuICAgIGlmIChPYmplY3Qua2V5cyhjb3JyZXNwb25kZW5jZVVwZGF0ZSkubGVuZ3RoID4gMCkge1xyXG4gICAgICBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby51cGRhdGUoaWQsIGNvcnJlc3BvbmRlbmNlVXBkYXRlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA0LiBVcGRhdGUgUmV2aXNpb24gRW50aXR5XHJcbiAgICBjb25zdCByZXZpc2lvblVwZGF0ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcclxuICAgIGlmICh1cGRhdGVEdG8uc3ViamVjdCkgcmV2aXNpb25VcGRhdGUuc3ViamVjdCA9IHVwZGF0ZUR0by5zdWJqZWN0O1xyXG4gICAgaWYgKHVwZGF0ZUR0by5ib2R5KSByZXZpc2lvblVwZGF0ZS5ib2R5ID0gdXBkYXRlRHRvLmJvZHk7XHJcbiAgICBpZiAodXBkYXRlRHRvLnJlbWFya3MpIHJldmlzaW9uVXBkYXRlLnJlbWFya3MgPSB1cGRhdGVEdG8ucmVtYXJrcztcclxuICAgIC8vIEZvcm1hdCBEYXRlIGNvcnJlY3RseSBpZiBzdHJpbmdcclxuICAgIGlmICh1cGRhdGVEdG8uZHVlRGF0ZSkgcmV2aXNpb25VcGRhdGUuZHVlRGF0ZSA9IG5ldyBEYXRlKHVwZGF0ZUR0by5kdWVEYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8uZG9jdW1lbnREYXRlKVxyXG4gICAgICByZXZpc2lvblVwZGF0ZS5kb2N1bWVudERhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8uZG9jdW1lbnREYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8uaXNzdWVkRGF0ZSlcclxuICAgICAgcmV2aXNpb25VcGRhdGUuaXNzdWVkRGF0ZSA9IG5ldyBEYXRlKHVwZGF0ZUR0by5pc3N1ZWREYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8ucmVjZWl2ZWREYXRlKVxyXG4gICAgICByZXZpc2lvblVwZGF0ZS5yZWNlaXZlZERhdGUgPSBuZXcgRGF0ZSh1cGRhdGVEdG8ucmVjZWl2ZWREYXRlKTtcclxuICAgIGlmICh1cGRhdGVEdG8uZGVzY3JpcHRpb24pXHJcbiAgICAgIHJldmlzaW9uVXBkYXRlLmRlc2NyaXB0aW9uID0gdXBkYXRlRHRvLmRlc2NyaXB0aW9uO1xyXG4gICAgaWYgKHVwZGF0ZUR0by5kZXRhaWxzKSByZXZpc2lvblVwZGF0ZS5kZXRhaWxzID0gdXBkYXRlRHRvLmRldGFpbHM7XHJcblxyXG4gICAgaWYgKE9iamVjdC5rZXlzKHJldmlzaW9uVXBkYXRlKS5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGF3YWl0IHRoaXMucmV2aXNpb25SZXBvLnVwZGF0ZShyZXZpc2lvbi5pZCwgcmV2aXNpb25VcGRhdGUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDQuNSBDb21taXQgbmV3IGF0dGFjaG1lbnRzIGZyb20gVGVtcCDihpIgUGVybWFuZW50IChUd28tUGhhc2UgU3RvcmFnZSlcclxuICAgIGlmICh1cGRhdGVEdG8uYXR0YWNobWVudFRlbXBJZHM/Lmxlbmd0aCkge1xyXG4gICAgICBjb25zdCBpc3N1ZURhdGUgPSB1cGRhdGVEdG8uaXNzdWVkRGF0ZVxyXG4gICAgICAgID8gbmV3IERhdGUodXBkYXRlRHRvLmlzc3VlZERhdGUpXHJcbiAgICAgICAgOiB1cGRhdGVEdG8uZG9jdW1lbnREYXRlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKHVwZGF0ZUR0by5kb2N1bWVudERhdGUpXHJcbiAgICAgICAgICA6IHJldmlzaW9uLmlzc3VlZERhdGUgfHwgcmV2aXNpb24uZG9jdW1lbnREYXRlIHx8IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgIGF3YWl0IHRoaXMuZmlsZVN0b3JhZ2VTZXJ2aWNlLmNvbW1pdCh1cGRhdGVEdG8uYXR0YWNobWVudFRlbXBJZHMsIHtcclxuICAgICAgICBpc3N1ZURhdGU6IGlzc3VlRGF0ZSA/IG5ldyBEYXRlKGlzc3VlRGF0ZSkgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgZG9jdW1lbnRUeXBlOiAnQ29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA1LiBVcGRhdGUgUmVjaXBpZW50cyBpZiBwcm92aWRlZFxyXG4gICAgaWYgKHVwZFJlc29sdmVkUmVjaXBpZW50cykge1xyXG4gICAgICBjb25zdCByZWNpcGllbnRSZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2VSZWNpcGllbnRcclxuICAgICAgKTtcclxuICAgICAgYXdhaXQgcmVjaXBpZW50UmVwby5kZWxldGUoeyBjb3JyZXNwb25kZW5jZUlkOiBpZCB9KTtcclxuXHJcbiAgICAgIGNvbnN0IG5ld1JlY2lwaWVudHMgPSB1cGRSZXNvbHZlZFJlY2lwaWVudHMubWFwKChyKSA9PlxyXG4gICAgICAgIHJlY2lwaWVudFJlcG8uY3JlYXRlKHtcclxuICAgICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IGlkLFxyXG4gICAgICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IHIub3JnYW5pemF0aW9uSWQsXHJcbiAgICAgICAgICByZWNpcGllbnRUeXBlOiByLnR5cGUsXHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICAgICAgYXdhaXQgcmVjaXBpZW50UmVwby5zYXZlKG5ld1JlY2lwaWVudHMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDYuIFJlZ2VuZXJhdGUgRG9jdW1lbnQgTnVtYmVyIGlmIHN0cnVjdHVyYWwgZmllbGRzIGNoYW5nZWQgKFJlY2lwaWVudCwgRGlzY2lwbGluZSwgVHlwZSwgUHJvamVjdClcclxuICAgIC8vIEFORCBpdCBpcyBhIERSQUZULlxyXG5cclxuICAgIC8vIEZldGNoIGZyZXNoIGRhdGEgZm9yIGNvbnRleHQgYW5kIGNvbXBhcmlzb25cclxuICAgIGNvbnN0IGN1cnJlbnRDb3JyID0gYXdhaXQgdGhpcy5jb3JyZXNwb25kZW5jZVJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IGlkIH0sXHJcbiAgICAgIHJlbGF0aW9uczogWyd0eXBlJywgJ3JlY2lwaWVudHMnLCAncmVjaXBpZW50cy5yZWNpcGllbnRPcmdhbml6YXRpb24nXSxcclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChjdXJyZW50Q29ycikge1xyXG4gICAgICBjb25zdCBjdXJyZW50VG9SZWNpcGllbnQgPSBjdXJyZW50Q29yci5yZWNpcGllbnRzPy5maW5kKFxyXG4gICAgICAgIChyKSA9PiByLnJlY2lwaWVudFR5cGUgPT09ICdUTydcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgY3VycmVudFJlY2lwaWVudElkID0gY3VycmVudFRvUmVjaXBpZW50Py5yZWNpcGllbnRPcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICAgIC8vIENoZWNrIGZvciBBQ1RVQUwgdmFsdWUgY2hhbmdlc1xyXG4gICAgICBjb25zdCBpc1Byb2plY3RDaGFuZ2VkID1cclxuICAgICAgICB1cGRSZXNvbHZlZFByb2plY3RJZCAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgICAgdXBkUmVzb2x2ZWRQcm9qZWN0SWQgIT09IGN1cnJlbnRDb3JyLnByb2plY3RJZDtcclxuICAgICAgY29uc3QgaXNPcmlnaW5hdG9yQ2hhbmdlZCA9XHJcbiAgICAgICAgdXBkUmVzb2x2ZWRPcmlnaW5hdG9ySWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZFJlc29sdmVkT3JpZ2luYXRvcklkICE9PSBjdXJyZW50Q29yci5vcmlnaW5hdG9ySWQ7XHJcbiAgICAgIGNvbnN0IGlzRGlzY2lwbGluZUNoYW5nZWQgPVxyXG4gICAgICAgIHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHVwZGF0ZUR0by5kaXNjaXBsaW5lSWQgIT09IGN1cnJlbnRDb3JyLmRpc2NpcGxpbmVJZDtcclxuICAgICAgY29uc3QgaXNUeXBlQ2hhbmdlZCA9XHJcbiAgICAgICAgdXBkYXRlRHRvLnR5cGVJZCAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgICAgdXBkYXRlRHRvLnR5cGVJZCAhPT0gY3VycmVudENvcnIuY29ycmVzcG9uZGVuY2VUeXBlSWQ7XHJcblxyXG4gICAgICBsZXQgaXNSZWNpcGllbnRDaGFuZ2VkID0gZmFsc2U7XHJcbiAgICAgIGxldCBuZXdSZWNpcGllbnRJZDogbnVtYmVyIHwgdW5kZWZpbmVkO1xyXG5cclxuICAgICAgaWYgKHVwZFJlc29sdmVkUmVjaXBpZW50cykge1xyXG4gICAgICAgIGNvbnN0IG5ld1RvUmVjaXBpZW50ID0gdXBkUmVzb2x2ZWRSZWNpcGllbnRzLmZpbmQoXHJcbiAgICAgICAgICAocikgPT4gci50eXBlID09PSAnVE8nXHJcbiAgICAgICAgKTtcclxuICAgICAgICBuZXdSZWNpcGllbnRJZCA9IG5ld1RvUmVjaXBpZW50Py5vcmdhbml6YXRpb25JZDtcclxuXHJcbiAgICAgICAgaWYgKG5ld1JlY2lwaWVudElkICE9PSBjdXJyZW50UmVjaXBpZW50SWQpIHtcclxuICAgICAgICAgIGlzUmVjaXBpZW50Q2hhbmdlZCA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgaXNQcm9qZWN0Q2hhbmdlZCB8fFxyXG4gICAgICAgIGlzRGlzY2lwbGluZUNoYW5nZWQgfHxcclxuICAgICAgICBpc1R5cGVDaGFuZ2VkIHx8XHJcbiAgICAgICAgaXNSZWNpcGllbnRDaGFuZ2VkIHx8XHJcbiAgICAgICAgaXNPcmlnaW5hdG9yQ2hhbmdlZFxyXG4gICAgICApIHtcclxuICAgICAgICBjb25zdCB0YXJnZXRSZWNpcGllbnRJZCA9IGlzUmVjaXBpZW50Q2hhbmdlZFxyXG4gICAgICAgICAgPyBuZXdSZWNpcGllbnRJZFxyXG4gICAgICAgICAgOiBjdXJyZW50UmVjaXBpZW50SWQ7XHJcblxyXG4gICAgICAgIC8vIFJlc29sdmUgUmVjaXBpZW50IENvZGUgZm9yIHRoZSBORVcgY29udGV4dFxyXG4gICAgICAgIGxldCByZWNpcGllbnRDb2RlID0gJyc7XHJcbiAgICAgICAgaWYgKHRhcmdldFJlY2lwaWVudElkKSB7XHJcbiAgICAgICAgICBjb25zdCByZWNPcmcgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UubWFuYWdlci5maW5kT25lKE9yZ2FuaXphdGlvbiwge1xyXG4gICAgICAgICAgICB3aGVyZTogeyBpZDogdGFyZ2V0UmVjaXBpZW50SWQgfSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgaWYgKHJlY09yZykgcmVjaXBpZW50Q29kZSA9IHJlY09yZy5vcmdhbml6YXRpb25Db2RlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gW0ZpeCAjNl0gRmV0Y2ggcmVhbCBPUkcgQ29kZSBmcm9tIG9yaWdpbmF0b3Igb3JnYW5pemF0aW9uXHJcbiAgICAgICAgY29uc3Qgb3JpZ2luYXRvck9yZ0ZvclVwZGF0ZSA9IGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUoXHJcbiAgICAgICAgICBPcmdhbml6YXRpb24sXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgICAgICAgaWQ6IHVwZFJlc29sdmVkT3JpZ2luYXRvcklkID8/IGN1cnJlbnRDb3JyLm9yaWdpbmF0b3JJZCA/PyAwLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICAgICAgY29uc3Qgb3JnQ29kZSA9IG9yaWdpbmF0b3JPcmdGb3JVcGRhdGU/Lm9yZ2FuaXphdGlvbkNvZGUgPz8gJ1VOSyc7XHJcblxyXG4gICAgICAgIC8vIFByZXBhcmUgQ29udGV4dHNcclxuICAgICAgICBjb25zdCBvbGRDdHggPSB7XHJcbiAgICAgICAgICBwcm9qZWN0SWQ6IGN1cnJlbnRDb3JyLnByb2plY3RJZCxcclxuICAgICAgICAgIG9yaWdpbmF0b3JPcmdhbml6YXRpb25JZDogY3VycmVudENvcnIub3JpZ2luYXRvcklkID8/IDAsXHJcbiAgICAgICAgICB0eXBlSWQ6IGN1cnJlbnRDb3JyLmNvcnJlc3BvbmRlbmNlVHlwZUlkLFxyXG4gICAgICAgICAgZGlzY2lwbGluZUlkOiBjdXJyZW50Q29yci5kaXNjaXBsaW5lSWQsXHJcbiAgICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZDogY3VycmVudFJlY2lwaWVudElkLFxyXG4gICAgICAgICAgeWVhcjogbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld0N0eCA9IHtcclxuICAgICAgICAgIHByb2plY3RJZDogdXBkUmVzb2x2ZWRQcm9qZWN0SWQgPz8gY3VycmVudENvcnIucHJvamVjdElkLFxyXG4gICAgICAgICAgb3JpZ2luYXRvck9yZ2FuaXphdGlvbklkOlxyXG4gICAgICAgICAgICB1cGRSZXNvbHZlZE9yaWdpbmF0b3JJZCA/PyBjdXJyZW50Q29yci5vcmlnaW5hdG9ySWQgPz8gMCxcclxuICAgICAgICAgIHR5cGVJZDogdXBkYXRlRHRvLnR5cGVJZCA/PyBjdXJyZW50Q29yci5jb3JyZXNwb25kZW5jZVR5cGVJZCxcclxuICAgICAgICAgIGRpc2NpcGxpbmVJZDogdXBkYXRlRHRvLmRpc2NpcGxpbmVJZCA/PyBjdXJyZW50Q29yci5kaXNjaXBsaW5lSWQsXHJcbiAgICAgICAgICByZWNpcGllbnRPcmdhbml6YXRpb25JZDogdGFyZ2V0UmVjaXBpZW50SWQsXHJcbiAgICAgICAgICB5ZWFyOiBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCksXHJcbiAgICAgICAgICB1c2VySWQ6IHVzZXIudXNlcl9pZCwgLy8gUGFzcyBVc2VyIElEIGZvciBBdWRpdFxyXG4gICAgICAgICAgY3VzdG9tVG9rZW5zOiB7XHJcbiAgICAgICAgICAgIFRZUEVfQ09ERTogY3VycmVudENvcnIudHlwZT8udHlwZUNvZGUgfHwgJycsXHJcbiAgICAgICAgICAgIE9SR19DT0RFOiBvcmdDb2RlLFxyXG4gICAgICAgICAgICBSRUNJUElFTlRfQ09ERTogcmVjaXBpZW50Q29kZSxcclxuICAgICAgICAgICAgUkVDX0NPREU6IHJlY2lwaWVudENvZGUsXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIElmIFR5cGUgQ2hhbmdlZCwgbmVlZCBORVcgVHlwZSBDb2RlXHJcbiAgICAgICAgaWYgKGlzVHlwZUNoYW5nZWQpIHtcclxuICAgICAgICAgIGNvbnN0IG5ld1R5cGUgPSBhd2FpdCB0aGlzLnR5cGVSZXBvLmZpbmRPbmUoe1xyXG4gICAgICAgICAgICB3aGVyZTogeyBpZDogbmV3Q3R4LnR5cGVJZCB9LFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICBpZiAobmV3VHlwZSkgbmV3Q3R4LmN1c3RvbVRva2Vucy5UWVBFX0NPREUgPSBuZXdUeXBlLnR5cGVDb2RlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgbmV3RG9jTnVtYmVyID0gYXdhaXQgdGhpcy5udW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0KFxyXG4gICAgICAgICAgY3VycmVudENvcnIuY29ycmVzcG9uZGVuY2VOdW1iZXIsXHJcbiAgICAgICAgICBvbGRDdHgsXHJcbiAgICAgICAgICBuZXdDdHhcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICBhd2FpdCB0aGlzLmNvcnJlc3BvbmRlbmNlUmVwby51cGRhdGUoaWQsIHtcclxuICAgICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiBuZXdEb2NOdW1iZXIsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB1cGRhdGVkID0gYXdhaXQgdGhpcy5maW5kT25lKGlkKTtcclxuXHJcbiAgICAvLyBSZS1pbmRleCB1cGRhdGVkIGRvY3VtZW50IGluIEVsYXN0aWNzZWFyY2ggKGZpcmUtYW5kLWZvcmdldClcclxuICAgIHZvaWQgdGhpcy5zZWFyY2hTZXJ2aWNlLmluZGV4RG9jdW1lbnQoe1xyXG4gICAgICBpZDogdXBkYXRlZC5pZCxcclxuICAgICAgcHVibGljSWQ6IHVwZGF0ZWQucHVibGljSWQsXHJcbiAgICAgIHR5cGU6ICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgIGRvY051bWJlcjogdXBkYXRlZC5jb3JyZXNwb25kZW5jZU51bWJlcixcclxuICAgICAgdGl0bGU6IHVwZGF0ZUR0by5zdWJqZWN0ID8/IHVwZGF0ZWQucmV2aXNpb25zPy5bMF0/LnN1YmplY3QsXHJcbiAgICAgIGRlc2NyaXB0aW9uOiB1cGRhdGVEdG8uZGVzY3JpcHRpb24gPz8gdXBkYXRlZC5yZXZpc2lvbnM/LlswXT8uZGVzY3JpcHRpb24sXHJcbiAgICAgIHN0YXR1czogJ0RSQUZUJyxcclxuICAgICAgcHJvamVjdElkOiB1cGRhdGVkLnByb2plY3RJZCxcclxuICAgICAgY3JlYXRlZEF0OiB1cGRhdGVkLmNyZWF0ZWRBdCxcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiB1cGRhdGVkO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgcHJldmlld0RvY3VtZW50TnVtYmVyKGNyZWF0ZUR0bzogQ3JlYXRlQ29ycmVzcG9uZGVuY2VEdG8sIHVzZXI6IFVzZXIpIHtcclxuICAgIC8vIEFEUi0wMTk6IFJlc29sdmUgVVVJRCByZWZlcmVuY2VzXHJcbiAgICBjb25zdCBwcmV2aWV3UHJvamVjdElkID0gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZChcclxuICAgICAgY3JlYXRlRHRvLnByb2plY3RJZFxyXG4gICAgKTtcclxuICAgIGNvbnN0IHByZXZpZXdPcmlnaW5hdG9ySWQgPSBjcmVhdGVEdG8ub3JpZ2luYXRvcklkXHJcbiAgICAgID8gYXdhaXQgdGhpcy51dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkKGNyZWF0ZUR0by5vcmlnaW5hdG9ySWQpXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG4gICAgY29uc3QgcHJldmlld1JlY2lwaWVudHMgPSBjcmVhdGVEdG8ucmVjaXBpZW50c1xyXG4gICAgICA/IGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgY3JlYXRlRHRvLnJlY2lwaWVudHMubWFwKFxyXG4gICAgICAgICAgICBhc3luYyAocik6IFByb21pc2U8UmVzb2x2ZWRSZWNpcGllbnQ+ID0+ICh7XHJcbiAgICAgICAgICAgICAgb3JnYW5pemF0aW9uSWQ6IGF3YWl0IHRoaXMudXVpZFJlc29sdmVyLnJlc29sdmVPcmdhbml6YXRpb25JZChcclxuICAgICAgICAgICAgICAgIHIub3JnYW5pemF0aW9uSWRcclxuICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgICAgIHR5cGU6IHIudHlwZSxcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgIClcclxuICAgICAgICApXHJcbiAgICAgIDogdW5kZWZpbmVkO1xyXG5cclxuICAgIGNvbnN0IHR5cGUgPSBhd2FpdCB0aGlzLnR5cGVSZXBvLmZpbmRPbmUoe1xyXG4gICAgICB3aGVyZTogeyBpZDogY3JlYXRlRHRvLnR5cGVJZCB9LFxyXG4gICAgfSk7XHJcbiAgICBpZiAoIXR5cGUpIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignRG9jdW1lbnQgVHlwZSBub3QgZm91bmQnKTtcclxuXHJcbiAgICBsZXQgdXNlck9yZ0lkID0gdXNlci5wcmltYXJ5T3JnYW5pemF0aW9uSWQ7XHJcbiAgICBpZiAoIXVzZXJPcmdJZCkge1xyXG4gICAgICBjb25zdCBmdWxsVXNlciA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZmluZE9uZSh1c2VyLnVzZXJfaWQpO1xyXG4gICAgICBpZiAoZnVsbFVzZXIpIHVzZXJPcmdJZCA9IGZ1bGxVc2VyLnByaW1hcnlPcmdhbml6YXRpb25JZDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocHJldmlld09yaWdpbmF0b3JJZCAmJiBwcmV2aWV3T3JpZ2luYXRvcklkICE9PSB1c2VyT3JnSWQpIHtcclxuICAgICAgLy8gQWxsb3cgaW1wZXJzb25hdGlvbiBmb3IgcHJldmlld1xyXG4gICAgICB1c2VyT3JnSWQgPSBwcmV2aWV3T3JpZ2luYXRvcklkO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEV4dHJhY3QgcmVjaXBpZW50IGZyb20gcmVjaXBpZW50cyBhcnJheVxyXG4gICAgY29uc3QgdG9SZWNpcGllbnQgPSBwcmV2aWV3UmVjaXBpZW50cz8uZmluZCgocikgPT4gci50eXBlID09PSAnVE8nKTtcclxuICAgIGNvbnN0IHJlY2lwaWVudE9yZ2FuaXphdGlvbklkID0gdG9SZWNpcGllbnQ/Lm9yZ2FuaXphdGlvbklkO1xyXG5cclxuICAgIGxldCByZWNpcGllbnRDb2RlID0gJyc7XHJcbiAgICBpZiAocmVjaXBpZW50T3JnYW5pemF0aW9uSWQpIHtcclxuICAgICAgY29uc3QgcmVjT3JnID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLm1hbmFnZXIuZmluZE9uZShPcmdhbml6YXRpb24sIHtcclxuICAgICAgICB3aGVyZTogeyBpZDogcmVjaXBpZW50T3JnYW5pemF0aW9uSWQgfSxcclxuICAgICAgfSk7XHJcbiAgICAgIGlmIChyZWNPcmcpIHJlY2lwaWVudENvZGUgPSByZWNPcmcub3JnYW5pemF0aW9uQ29kZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpcy5udW1iZXJpbmdTZXJ2aWNlLnByZXZpZXdOdW1iZXIoe1xyXG4gICAgICBwcm9qZWN0SWQ6IHByZXZpZXdQcm9qZWN0SWQsXHJcbiAgICAgIG9yaWdpbmF0b3JPcmdhbml6YXRpb25JZDogdXNlck9yZ0lkISxcclxuICAgICAgdHlwZUlkOiBjcmVhdGVEdG8udHlwZUlkLFxyXG4gICAgICBkaXNjaXBsaW5lSWQ6IGNyZWF0ZUR0by5kaXNjaXBsaW5lSWQsXHJcbiAgICAgIHN1YlR5cGVJZDogY3JlYXRlRHRvLnN1YlR5cGVJZCxcclxuICAgICAgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQsXHJcbiAgICAgIHllYXI6IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKSxcclxuICAgICAgY3VzdG9tVG9rZW5zOiB7XHJcbiAgICAgICAgVFlQRV9DT0RFOiB0eXBlLnR5cGVDb2RlLFxyXG4gICAgICAgIFJFQ0lQSUVOVF9DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICAgIFJFQ19DT0RFOiByZWNpcGllbnRDb2RlLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBCdXNpbmVzcyBSdWxlIEltcGxlbWVudGF0aW9uOiBFQy1DT1JSLTAwMSAtIENhbmNlbCBDb3JyZXNwb25kZW5jZSB3aXRoIERvd25zdHJlYW0gQ2lyY3VsYXRpb25cclxuICAgKiBDYW5jZWwgY29ycmVzcG9uZGVuY2UgYW5kIGhhbmRsZSByZWxhdGVkIGNpcmN1bGF0aW9uc1xyXG4gICAqL1xyXG4gIGFzeW5jIGNhbmNlbChwdWJsaWNJZDogc3RyaW5nLCByZWFzb246IHN0cmluZywgdXNlcjogVXNlcikge1xyXG4gICAgY29uc3QgY29ycmVzcG9uZGVuY2UgPSBhd2FpdCB0aGlzLmZpbmRPbmVCeVV1aWQocHVibGljSWQpO1xyXG5cclxuICAgIC8vIENoZWNrIGlmIHVzZXIgaGFzIHBlcm1pc3Npb24gdG8gY2FuY2VsIChPcmcgQWRtaW4gb3IgU3VwZXJhZG1pbiBvbmx5KVxyXG4gICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyh1c2VyLnVzZXJfaWQpO1xyXG4gICAgY29uc3QgY2FuQ2FuY2VsID1cclxuICAgICAgcGVybWlzc2lvbnMuaW5jbHVkZXMoJ2NvcnJlc3BvbmRlbmNlLmNhbmNlbCcpIHx8XHJcbiAgICAgIHBlcm1pc3Npb25zLmluY2x1ZGVzKCdzeXN0ZW0ubWFuYWdlX2FsbCcpO1xyXG5cclxuICAgIGlmICghY2FuQ2FuY2VsKSB7XHJcbiAgICAgIHRocm93IG5ldyBGb3JiaWRkZW5FeGNlcHRpb24oXHJcbiAgICAgICAgJ09ubHkgYWRtaW5pc3RyYXRvcnMgY2FuIGNhbmNlbCBjb3JyZXNwb25kZW5jZXMnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBhY3RpdmUgY2lyY3VsYXRpb25zXHJcbiAgICBjb25zdCBjaXJjdWxhdGlvblJlcG8gPSB0aGlzLmRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeSgnQ2lyY3VsYXRpb24nKTtcclxuICAgIGNvbnN0IGFjdGl2ZUNpcmN1bGF0aW9ucyA9IGF3YWl0IGNpcmN1bGF0aW9uUmVwby5maW5kKHtcclxuICAgICAgd2hlcmU6IHtcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiBjb3JyZXNwb25kZW5jZS5pZCxcclxuICAgICAgICBzdGF0dXM6ICdPUEVOJyxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHdhcm5pbmdNZXNzYWdlID1cclxuICAgICAgYWN0aXZlQ2lyY3VsYXRpb25zLmxlbmd0aCA+IDBcclxuICAgICAgICA/IGBUaGVyZSBhcmUgJHthY3RpdmVDaXJjdWxhdGlvbnMubGVuZ3RofSBhY3RpdmUgY2lyY3VsYXRpb24ocykgZm9yIHRoaXMgY29ycmVzcG9uZGVuY2UuIENhbmNlbGluZyB3aWxsIGZvcmNlIGNsb3NlIGFsbCByZWxhdGVkIGNpcmN1bGF0aW9ucy5gXHJcbiAgICAgICAgOiAnJztcclxuXHJcbiAgICAvLyBHZXQgdGhlIGN1cnJlbnQgcmV2aXNpb24gdG8gdXBkYXRlIHN0YXR1c1xyXG4gICAgY29uc3QgY3VycmVudFJldmlzaW9uID0gYXdhaXQgdGhpcy5yZXZpc2lvblJlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7XHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKCFjdXJyZW50UmV2aXNpb24pIHtcclxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdDdXJyZW50IHJldmlzaW9uIG5vdCBmb3VuZCcpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEdldCBjYW5jZWxsZWQgc3RhdHVzXHJcbiAgICBjb25zdCBjYW5jZWxsZWRTdGF0dXMgPSBhd2FpdCB0aGlzLnN0YXR1c1JlcG8uZmluZE9uZSh7XHJcbiAgICAgIHdoZXJlOiB7IHN0YXR1c0NvZGU6ICdDQU5DRUxMRUQnIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoIWNhbmNlbGxlZFN0YXR1cykge1xyXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxTZXJ2ZXJFcnJvckV4Y2VwdGlvbignQ0FOQ0VMTEVEIHN0YXR1cyBub3QgZm91bmQnKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHRoaXMuZGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lcigpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuY29ubmVjdCgpO1xyXG4gICAgYXdhaXQgcXVlcnlSdW5uZXIuc3RhcnRUcmFuc2FjdGlvbigpO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIFVwZGF0ZSBjb3JyZXNwb25kZW5jZSByZXZpc2lvbiBzdGF0dXMgdG8gQ0FOQ0VMTEVEXHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIudXBkYXRlKFxyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlUmV2aXNpb24sXHJcbiAgICAgICAgY3VycmVudFJldmlzaW9uLmlkLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHN0YXR1c0lkOiBjYW5jZWxsZWRTdGF0dXMuaWQsXHJcbiAgICAgICAgICByZW1hcmtzOiBgQ2FuY2VsbGVkOiAke3JlYXNvbn1gLFxyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuXHJcbiAgICAgIC8vIEZvcmNlIGNsb3NlIGFsbCBhY3RpdmUgY2lyY3VsYXRpb25zXHJcbiAgICAgIGlmIChhY3RpdmVDaXJjdWxhdGlvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIudXBkYXRlKFxyXG4gICAgICAgICAgJ0NpcmN1bGF0aW9uJyxcclxuICAgICAgICAgIHtcclxuICAgICAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgICAgIHN0YXR1czogJ09QRU4nLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICAgIHtcclxuICAgICAgICAgICAgc3RhdHVzOiAnRk9SQ0VfQ0xPU0VEJyxcclxuICAgICAgICAgICAgY2xvc2VkQXQ6IG5ldyBEYXRlKCksXHJcbiAgICAgICAgICAgIGNsb3NlZEJ5OiB1c2VyLnVzZXJfaWQsXHJcbiAgICAgICAgICAgIGNsb3NlUmVhc29uOiBgQ29ycmVzcG9uZGVuY2UgY2FuY2VsbGVkOiAke3JlYXNvbn1gLFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLmNvbW1pdFRyYW5zYWN0aW9uKCk7XHJcblxyXG4gICAgICAvLyBSZS1pbmRleCBjYW5jZWxsZWQgc3RhdHVzIGluIEVsYXN0aWNzZWFyY2ggKGZpcmUtYW5kLWZvcmdldClcclxuICAgICAgdm9pZCB0aGlzLnNlYXJjaFNlcnZpY2UuaW5kZXhEb2N1bWVudCh7XHJcbiAgICAgICAgaWQ6IGNvcnJlc3BvbmRlbmNlLmlkLFxyXG4gICAgICAgIHB1YmxpY0lkOiBjb3JyZXNwb25kZW5jZS5wdWJsaWNJZCxcclxuICAgICAgICB0eXBlOiAnY29ycmVzcG9uZGVuY2UnLFxyXG4gICAgICAgIGRvY051bWJlcjogY29ycmVzcG9uZGVuY2UuY29ycmVzcG9uZGVuY2VOdW1iZXIsXHJcbiAgICAgICAgdGl0bGU6IGN1cnJlbnRSZXZpc2lvbi5zdWJqZWN0LFxyXG4gICAgICAgIHN0YXR1czogJ0NBTkNFTExFRCcsXHJcbiAgICAgICAgcHJvamVjdElkOiBjb3JyZXNwb25kZW5jZS5wcm9qZWN0SWQsXHJcbiAgICAgICAgY3JlYXRlZEF0OiBjb3JyZXNwb25kZW5jZS5jcmVhdGVkQXQsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gTm90aWZ5IG9yaWdpbmF0b3IncyBkb2MtY29udHJvbCB1c2VyIGFib3V0IGNhbmNlbGxhdGlvbiAoZmlyZS1hbmQtZm9yZ2V0KVxyXG4gICAgICBpZiAoY29ycmVzcG9uZGVuY2Uub3JpZ2luYXRvcklkKSB7XHJcbiAgICAgICAgdm9pZCB0aGlzLnVzZXJTZXJ2aWNlXHJcbiAgICAgICAgICAuZmluZERvY0NvbnRyb2xJZEJ5T3JnKGNvcnJlc3BvbmRlbmNlLm9yaWdpbmF0b3JJZClcclxuICAgICAgICAgIC50aGVuKCh0YXJnZXRVc2VySWQpID0+IHtcclxuICAgICAgICAgICAgaWYgKHRhcmdldFVzZXJJZCkge1xyXG4gICAgICAgICAgICAgIHZvaWQgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLnNlbmQoe1xyXG4gICAgICAgICAgICAgICAgdXNlcklkOiB0YXJnZXRVc2VySWQsXHJcbiAgICAgICAgICAgICAgICB0aXRsZTogJ0NvcnJlc3BvbmRlbmNlIENhbmNlbGxlZCcsXHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBgJHtjb3JyZXNwb25kZW5jZS5jb3JyZXNwb25kZW5jZU51bWJlcn0g4oCUICR7Y3VycmVudFJldmlzaW9uLnN1YmplY3R9IGhhcyBiZWVuIGNhbmNlbGxlZC4gUmVhc29uOiAke3JlYXNvbn1gLFxyXG4gICAgICAgICAgICAgICAgdHlwZTogJ0VNQUlMJyxcclxuICAgICAgICAgICAgICAgIGVudGl0eVR5cGU6ICdjb3JyZXNwb25kZW5jZScsXHJcbiAgICAgICAgICAgICAgICBlbnRpdHlJZDogY29ycmVzcG9uZGVuY2UuaWQsXHJcbiAgICAgICAgICAgICAgICBsaW5rOiBgL2NvcnJlc3BvbmRlbmNlcy8ke2NvcnJlc3BvbmRlbmNlLnB1YmxpY0lkfWAsXHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgICAuY2F0Y2goKGVycjogRXJyb3IpID0+XHJcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oYENhbmNlbCBub3RpZmljYXRpb24gZmFpbGVkOiAke2Vyci5tZXNzYWdlfWApXHJcbiAgICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIHN1Y2Nlc3M6IHRydWUsXHJcbiAgICAgICAgbWVzc2FnZTogd2FybmluZ01lc3NhZ2UgfHwgJ0NvcnJlc3BvbmRlbmNlIGNhbmNlbGxlZCBzdWNjZXNzZnVsbHknLFxyXG4gICAgICAgIGFjdGl2ZUNpcmN1bGF0aW9uc0NvdW50OiBhY3RpdmVDaXJjdWxhdGlvbnMubGVuZ3RoLFxyXG4gICAgICB9O1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucm9sbGJhY2tUcmFuc2FjdGlvbigpO1xyXG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcclxuICAgICAgICBgRmFpbGVkIHRvIGNhbmNlbCBjb3JyZXNwb25kZW5jZTogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YFxyXG4gICAgICApO1xyXG4gICAgICB0aHJvdyBlcnJvcjtcclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJlbGVhc2UoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGJ1bGtDYW5jZWwoXHJcbiAgICBwdWJsaWNJZHM6IHN0cmluZ1tdLFxyXG4gICAgcmVhc29uOiBzdHJpbmcsXHJcbiAgICB1c2VyOiBVc2VyXHJcbiAgKTogUHJvbWlzZTx7IHN1Y2NlZWRlZDogc3RyaW5nW107IGZhaWxlZDogc3RyaW5nW10gfT4ge1xyXG4gICAgY29uc3Qgc3VjY2VlZGVkOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgY29uc3QgZmFpbGVkOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIGZvciAoY29uc3QgcHVibGljSWQgb2YgcHVibGljSWRzKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5jYW5jZWwocHVibGljSWQsIHJlYXNvbiwgdXNlcik7XHJcbiAgICAgICAgc3VjY2VlZGVkLnB1c2gocHVibGljSWQpO1xyXG4gICAgICB9IGNhdGNoIHtcclxuICAgICAgICBmYWlsZWQucHVzaChwdWJsaWNJZCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4geyBzdWNjZWVkZWQsIGZhaWxlZCB9O1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZXhwb3J0Q3N2KHNlYXJjaER0bzogU2VhcmNoQ29ycmVzcG9uZGVuY2VEdG8pOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgY29uc3QgeyBkYXRhIH0gPSBhd2FpdCB0aGlzLmZpbmRBbGwoc2VhcmNoRHRvKTtcclxuXHJcbiAgICBjb25zdCBoZWFkZXIgPSBbXHJcbiAgICAgICdEb2N1bWVudCBOby4nLFxyXG4gICAgICAnUmV2JyxcclxuICAgICAgJ1N1YmplY3QnLFxyXG4gICAgICAnVHlwZScsXHJcbiAgICAgICdTdGF0dXMnLFxyXG4gICAgICAnUHJvamVjdCcsXHJcbiAgICAgICdGcm9tJyxcclxuICAgICAgJ0R1ZSBEYXRlJyxcclxuICAgICAgJ0NyZWF0ZWQgQXQnLFxyXG4gICAgXTtcclxuICAgIGNvbnN0IHJvd3MgPSBkYXRhLm1hcCgocmV2KSA9PiB7XHJcbiAgICAgIGNvbnN0IGNvcnIgPSByZXYuY29ycmVzcG9uZGVuY2UgPz8gKHJldiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuICAgICAgcmV0dXJuIFtcclxuICAgICAgICB0aGlzLmVzY2FwZUNzdihjb3JyLmNvcnJlc3BvbmRlbmNlTnVtYmVyID8/ICcnKSxcclxuICAgICAgICB0aGlzLmVzY2FwZUNzdihyZXYucmV2aXNpb25MYWJlbCA/PyBTdHJpbmcocmV2LnJldmlzaW9uTnVtYmVyID8/IDApKSxcclxuICAgICAgICB0aGlzLmVzY2FwZUNzdihyZXYuc3ViamVjdCA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci50eXBlPy50eXBlQ29kZSA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YocmV2LnN0YXR1cz8uc3RhdHVzQ29kZSA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci5wcm9qZWN0Py5wcm9qZWN0Q29kZSA/PyAnJyksXHJcbiAgICAgICAgdGhpcy5lc2NhcGVDc3YoY29yci5vcmlnaW5hdG9yPy5vcmdhbml6YXRpb25Db2RlID8/ICcnKSxcclxuICAgICAgICByZXYuZHVlRGF0ZSA/IG5ldyBEYXRlKHJldi5kdWVEYXRlKS50b0lTT1N0cmluZygpLnNwbGl0KCdUJylbMF0gOiAnJyxcclxuICAgICAgICBuZXcgRGF0ZShyZXYuY3JlYXRlZEF0KS50b0lTT1N0cmluZygpLnNwbGl0KCdUJylbMF0sXHJcbiAgICAgIF0uam9pbignLCcpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIFtoZWFkZXIuam9pbignLCcpLCAuLi5yb3dzXS5qb2luKCdcXG4nKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZXNjYXBlQ3N2KHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKHZhbHVlLmluY2x1ZGVzKCcsJykgfHwgdmFsdWUuaW5jbHVkZXMoJ1wiJykgfHwgdmFsdWUuaW5jbHVkZXMoJ1xcbicpKSB7XHJcbiAgICAgIHJldHVybiBgXCIke3ZhbHVlLnJlcGxhY2UoL1wiL2csICdcIlwiJyl9XCJgO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHZhbHVlO1xyXG4gIH1cclxufVxyXG4iXSwidmVyc2lvbiI6M30= \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a.map new file mode 100644 index 0000000..e8b9c4c --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ae/correspondenceservice_ae8ff3a33dc0eeda2f50bf4243e0051a.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.ts"],"sourcesContent":["// File: src/modules/correspondence/correspondence.service.ts\r\n\r\nimport {\r\n Injectable,\r\n NotFoundException,\r\n BadRequestException,\r\n InternalServerErrorException,\r\n ForbiddenException,\r\n Logger,\r\n} from '@nestjs/common';\r\nimport { InjectRepository } from '@nestjs/typeorm';\r\nimport { Repository, DataSource } from 'typeorm';\r\n\r\n// Entities\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Tag } from '../master/entities/tag.entity';\r\nimport { User } from '../user/entities/user.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\n\r\n// DTOs\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { AddReferenceDto } from './dto/add-reference.dto';\r\nimport { SearchCorrespondenceDto } from './dto/search-correspondence.dto';\r\n\r\n// Services\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\n\r\n/**\r\n * CorrespondenceService - Document management (CRUD)\r\n */\r\ninterface ResolvedRecipient {\r\n organizationId: number;\r\n type: 'TO' | 'CC';\r\n}\r\n@Injectable()\r\nexport class CorrespondenceService {\r\n private readonly logger = new Logger(CorrespondenceService.name);\r\n\r\n private async hasSystemManageAllPermission(userId: number): Promise {\r\n const permissions = await this.userService.getUserPermissions(userId);\r\n return permissions.includes('system.manage_all');\r\n }\r\n\r\n constructor(\r\n @InjectRepository(Correspondence)\r\n private correspondenceRepo: Repository,\r\n @InjectRepository(CorrespondenceRevision)\r\n private revisionRepo: Repository,\r\n @InjectRepository(CorrespondenceType)\r\n private typeRepo: Repository,\r\n @InjectRepository(CorrespondenceStatus)\r\n private statusRepo: Repository,\r\n @InjectRepository(CorrespondenceReference)\r\n private referenceRepo: Repository,\r\n @InjectRepository(CorrespondenceTag)\r\n private tagRepo: Repository,\r\n private numberingService: DocumentNumberingService,\r\n private jsonSchemaService: JsonSchemaService,\r\n private workflowEngine: WorkflowEngineService,\r\n private userService: UserService,\r\n private dataSource: DataSource,\r\n private searchService: SearchService,\r\n private fileStorageService: FileStorageService,\r\n private uuidResolver: UuidResolverService,\r\n private notificationService: NotificationService\r\n ) {}\r\n\r\n /**\r\n * Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n * Prevent external correspondence to same organization\r\n */\r\n private async validateCorrespondenceRecipients(\r\n createDto: CreateCorrespondenceDto,\r\n user: User\r\n ): Promise {\r\n // Get user's organization\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n if (createDto.originatorId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (canManageAll) {\r\n userOrgId = await this.uuidResolver.resolveOrganizationId(\r\n createDto.originatorId\r\n );\r\n }\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n }\r\n\r\n // For impersonation, use the specified originator\r\n const originatorOrgId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : userOrgId;\r\n\r\n // Check if it's internal communication\r\n if (createDto.isInternal) {\r\n // Internal communications should use Circulation instead\r\n throw new BadRequestException(\r\n 'Internal communications should use Circulation Sheet instead of Correspondence'\r\n );\r\n }\r\n\r\n // Validate recipients\r\n if (!createDto.recipients || createDto.recipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one recipient (TO or CC) is required'\r\n );\r\n }\r\n\r\n const toRecipients = createDto.recipients.filter((r) => r.type === 'TO');\r\n const ccRecipients = createDto.recipients.filter((r) => r.type === 'CC');\r\n\r\n if (toRecipients.length === 0 && ccRecipients.length === 0) {\r\n throw new BadRequestException(\r\n 'At least one TO or CC recipient is required'\r\n );\r\n }\r\n\r\n // Check for same organization correspondence\r\n for (const recipient of createDto.recipients) {\r\n const recipientOrgId = await this.uuidResolver.resolveOrganizationId(\r\n recipient.organizationId\r\n );\r\n\r\n if (recipientOrgId === originatorOrgId) {\r\n throw new BadRequestException(\r\n 'Cannot send correspondence to your own organization. Use Circulation Sheet for internal communication.'\r\n );\r\n }\r\n }\r\n }\r\n\r\n async create(createDto: CreateCorrespondenceDto, user: User) {\r\n // Business Rule Validation: EC-CORR-003 - Correspondence to Self\r\n await this.validateCorrespondenceRecipients(createDto, user);\r\n // ADR-019: Resolve UUID references to internal INT IDs\r\n const resolvedProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const resolvedOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const resolvedRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n const statusDraft = await this.statusRepo.findOne({\r\n where: { statusCode: 'DRAFT' },\r\n });\r\n if (!statusDraft) {\r\n throw new InternalServerErrorException(\r\n 'Status DRAFT not found in Master Data'\r\n );\r\n }\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) {\r\n userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n }\r\n\r\n // Impersonation Logic\r\n if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {\r\n const canManageAll = await this.hasSystemManageAllPermission(\r\n user.user_id\r\n );\r\n if (!canManageAll) {\r\n throw new ForbiddenException(\r\n 'You do not have permission to create documents on behalf of other organizations.'\r\n );\r\n }\r\n userOrgId = resolvedOriginatorId;\r\n }\r\n\r\n if (!userOrgId) {\r\n throw new BadRequestException(\r\n 'User must belong to an organization to create documents'\r\n );\r\n }\r\n\r\n if (createDto.details) {\r\n try {\r\n await this.jsonSchemaService.validate(type.typeCode, createDto.details);\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Schema validation warning for ${type.typeCode}: ${(error as Error).message}`\r\n );\r\n }\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // [Fix #6] Fetch real ORG Code from Organization entity\r\n const originatorOrg = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: { id: userOrgId },\r\n }\r\n );\r\n const orgCode = originatorOrg?.organizationCode ?? 'UNK';\r\n\r\n // [v1.5.1] Extract recipient organization from recipients array (Primary TO)\r\n const toRecipient = resolvedRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n const docNumber = await this.numberingService.generateNextNumber({\r\n projectId: resolvedProjectId,\r\n originatorOrganizationId: userOrgId,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId, // [v1.5.1] Pass recipient for document number format\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n\r\n const correspondence = queryRunner.manager.create(Correspondence, {\r\n correspondenceNumber: docNumber.number,\r\n correspondenceTypeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n isInternal: createDto.isInternal || false,\r\n createdBy: user.user_id,\r\n });\r\n const savedCorr = await queryRunner.manager.save(correspondence);\r\n\r\n const revision = queryRunner.manager.create(CorrespondenceRevision, {\r\n correspondenceId: savedCorr.id,\r\n revisionNumber: 0,\r\n revisionLabel: 'A',\r\n isCurrent: true,\r\n statusId: statusDraft.id,\r\n subject: createDto.subject,\r\n body: createDto.body,\r\n remarks: createDto.remarks,\r\n dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined,\r\n documentDate: createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined,\r\n issuedDate: createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : undefined,\r\n receivedDate: createDto.receivedDate\r\n ? new Date(createDto.receivedDate)\r\n : undefined,\r\n description: createDto.description,\r\n details: createDto.details,\r\n createdBy: user.user_id,\r\n schemaVersion: 1,\r\n });\r\n await queryRunner.manager.save(revision);\r\n\r\n // Save Recipients (using resolved INT IDs)\r\n if (resolvedRecipients && resolvedRecipients.length > 0) {\r\n const recipients = resolvedRecipients.map((r) =>\r\n queryRunner.manager.create(CorrespondenceRecipient, {\r\n correspondenceId: savedCorr.id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await queryRunner.manager.save(recipients);\r\n }\r\n\r\n // Commit attachments from Temp → Permanent (Two-Phase Storage)\r\n if (createDto.attachmentTempIds?.length) {\r\n const issueDate = createDto.issuedDate\r\n ? new Date(createDto.issuedDate)\r\n : createDto.documentDate\r\n ? new Date(createDto.documentDate)\r\n : undefined;\r\n\r\n await this.fileStorageService.commit(createDto.attachmentTempIds, {\r\n issueDate,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Start Workflow Instance (non-blocking)\r\n try {\r\n const workflowCode = `CORRESPONDENCE_${type.typeCode}`;\r\n await this.workflowEngine.createInstance(\r\n workflowCode,\r\n 'correspondence',\r\n savedCorr.id.toString(),\r\n {\r\n projectId: resolvedProjectId,\r\n originatorId: userOrgId,\r\n disciplineId: createDto.disciplineId,\r\n initiatorId: user.user_id,\r\n } as Record\r\n );\r\n } catch (error: unknown) {\r\n this.logger.warn(\r\n `Workflow not started for ${docNumber.number} (Code: CORRESPONDENCE_${type.typeCode}): ${(error as Error).message}`\r\n );\r\n }\r\n\r\n // Fire-and-forget search indexing (non-blocking, void intentional)\r\n void this.searchService.indexDocument({\r\n id: savedCorr.id,\r\n publicId: savedCorr.publicId,\r\n type: 'correspondence',\r\n docNumber: docNumber.number,\r\n title: createDto.subject,\r\n description: createDto.description,\r\n status: 'DRAFT',\r\n projectId: resolvedProjectId,\r\n createdAt: new Date(),\r\n });\r\n\r\n return {\r\n ...savedCorr,\r\n currentRevision: revision,\r\n };\r\n } catch (err) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to create correspondence: ${(err as Error).message}`\r\n );\r\n throw err;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async findAll(searchDto: SearchCorrespondenceDto = {}) {\r\n const {\r\n search,\r\n typeId,\r\n projectId,\r\n statusId,\r\n status,\r\n page = 1,\r\n limit = 10,\r\n } = searchDto;\r\n const skip = (page - 1) * limit;\r\n\r\n // Change: Query from Revision Repo\r\n const query = this.revisionRepo\r\n .createQueryBuilder('rev')\r\n .leftJoinAndSelect('rev.correspondence', 'corr')\r\n .leftJoinAndSelect('corr.type', 'type')\r\n .leftJoinAndSelect('corr.project', 'project')\r\n .leftJoinAndSelect('corr.originator', 'org')\r\n .leftJoinAndSelect('rev.status', 'status');\r\n\r\n // Filter by Revision Status\r\n const revStatus = searchDto.revisionStatus || 'CURRENT';\r\n\r\n if (revStatus === 'CURRENT') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: true });\r\n } else if (revStatus === 'OLD') {\r\n query.where('rev.isCurrent = :isCurrent', { isCurrent: false });\r\n }\r\n // If 'ALL', no filter needed on isCurrent\r\n\r\n if (projectId) {\r\n query.andWhere('corr.projectId = :projectId', { projectId });\r\n }\r\n\r\n if (typeId) {\r\n query.andWhere('corr.correspondenceTypeId = :typeId', { typeId });\r\n }\r\n\r\n if (statusId) {\r\n query.andWhere('rev.statusId = :statusId', { statusId });\r\n }\r\n\r\n if (status) {\r\n query.andWhere('status.statusCode = :status', { status });\r\n }\r\n\r\n if (search) {\r\n query.andWhere(\r\n '(corr.correspondenceNumber LIKE :search OR rev.subject LIKE :search)',\r\n { search: `%${search}%` }\r\n );\r\n }\r\n\r\n // Default Sort: Latest Created\r\n query.orderBy('rev.createdAt', 'DESC').skip(skip).take(limit);\r\n\r\n const [items, total] = await query.getManyAndCount();\r\n\r\n return {\r\n data: items,\r\n meta: {\r\n total,\r\n page,\r\n limit,\r\n totalPages: Math.ceil(total / limit),\r\n },\r\n };\r\n }\r\n\r\n async findOne(id: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization', // [v1.5.1] Fixed relation name\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence with ID ${id} not found`);\r\n }\r\n return correspondence;\r\n }\r\n\r\n async findOneByUuid(publicId: string) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { publicId },\r\n relations: [\r\n 'revisions',\r\n 'revisions.status',\r\n 'type',\r\n 'project',\r\n 'originator',\r\n 'recipients',\r\n 'recipients.recipientOrganization',\r\n ],\r\n });\r\n\r\n if (!correspondence) {\r\n throw new NotFoundException(\r\n `Correspondence with UUID ${publicId} not found`\r\n );\r\n }\r\n return correspondence;\r\n }\r\n\r\n async addReference(id: number, dto: AddReferenceDto) {\r\n const source = await this.correspondenceRepo.findOne({ where: { id } });\r\n // ADR-019: Resolve target publicId → internal INT id\r\n const target = await this.correspondenceRepo.findOne({\r\n where: { publicId: dto.targetUuid },\r\n });\r\n\r\n if (!source || !target) {\r\n throw new NotFoundException('Source or Target correspondence not found');\r\n }\r\n\r\n if (source.id === target.id) {\r\n throw new BadRequestException('Cannot reference self');\r\n }\r\n\r\n const exists = await this.referenceRepo.findOne({\r\n where: {\r\n sourceId: id,\r\n targetId: target.id,\r\n },\r\n });\r\n\r\n if (exists) {\r\n return exists;\r\n }\r\n\r\n const ref = this.referenceRepo.create({\r\n sourceId: id,\r\n targetId: target.id,\r\n });\r\n\r\n return this.referenceRepo.save(ref);\r\n }\r\n\r\n async removeReference(id: number, targetId: number) {\r\n const result = await this.referenceRepo.delete({\r\n sourceId: id,\r\n targetId: targetId,\r\n });\r\n\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Reference not found');\r\n }\r\n }\r\n\r\n async getTags(id: number) {\r\n const rows = await this.tagRepo.find({\r\n where: { correspondenceId: id },\r\n relations: ['tag'],\r\n });\r\n return rows.map((r) => r.tag).filter(Boolean);\r\n }\r\n\r\n async addTag(id: number, tagId: number) {\r\n const correspondence = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n });\r\n if (!correspondence) {\r\n throw new NotFoundException(`Correspondence ${id} not found`);\r\n }\r\n\r\n const tag = await this.dataSource.manager.findOne(Tag, {\r\n where: { id: tagId },\r\n });\r\n if (!tag) {\r\n throw new NotFoundException(`Tag ${tagId} not found`);\r\n }\r\n\r\n const exists = await this.tagRepo.findOne({\r\n where: { correspondenceId: id, tagId },\r\n });\r\n if (exists) return exists;\r\n\r\n const row = this.tagRepo.create({ correspondenceId: id, tagId });\r\n return this.tagRepo.save(row);\r\n }\r\n\r\n async removeTag(id: number, tagId: number) {\r\n const result = await this.tagRepo.delete({ correspondenceId: id, tagId });\r\n if (result.affected === 0) {\r\n throw new NotFoundException('Tag assignment not found');\r\n }\r\n }\r\n\r\n async getReferences(id: number) {\r\n const outgoing = await this.referenceRepo.find({\r\n where: { sourceId: id },\r\n relations: ['target', 'target.type'],\r\n });\r\n\r\n const incoming = await this.referenceRepo.find({\r\n where: { targetId: id },\r\n relations: ['source', 'source.type'],\r\n });\r\n\r\n return { outgoing, incoming };\r\n }\r\n\r\n async update(id: number, updateDto: UpdateCorrespondenceDto, user: User) {\r\n // 1. Find Current Revision\r\n const revision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: id,\r\n isCurrent: true,\r\n },\r\n relations: ['correspondence'],\r\n });\r\n\r\n if (!revision) {\r\n throw new NotFoundException(\r\n `Current revision for correspondence ${id} not found`\r\n );\r\n }\r\n\r\n // 2. Check Permission\r\n if (revision.statusId) {\r\n const status = await this.statusRepo.findOne({\r\n where: { id: revision.statusId },\r\n });\r\n if (status && status.statusCode !== 'DRAFT') {\r\n throw new BadRequestException('Only DRAFT documents can be updated');\r\n }\r\n }\r\n\r\n // ADR-019: Resolve UUID references in update DTO\r\n const updResolvedProjectId = updateDto.projectId\r\n ? await this.uuidResolver.resolveProjectId(updateDto.projectId)\r\n : undefined;\r\n const updResolvedOriginatorId = updateDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(updateDto.originatorId)\r\n : undefined;\r\n const updResolvedRecipients = updateDto.recipients\r\n ? await Promise.all(\r\n updateDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n // 3. Update Correspondence Entity if needed\r\n const correspondenceUpdate: Record = {};\r\n if (updateDto.disciplineId)\r\n correspondenceUpdate.disciplineId = updateDto.disciplineId;\r\n if (updResolvedProjectId)\r\n correspondenceUpdate.projectId = updResolvedProjectId;\r\n if (updResolvedOriginatorId)\r\n correspondenceUpdate.originatorId = updResolvedOriginatorId;\r\n\r\n if (Object.keys(correspondenceUpdate).length > 0) {\r\n await this.correspondenceRepo.update(id, correspondenceUpdate);\r\n }\r\n\r\n // 4. Update Revision Entity\r\n const revisionUpdate: Record = {};\r\n if (updateDto.subject) revisionUpdate.subject = updateDto.subject;\r\n if (updateDto.body) revisionUpdate.body = updateDto.body;\r\n if (updateDto.remarks) revisionUpdate.remarks = updateDto.remarks;\r\n // Format Date correctly if string\r\n if (updateDto.dueDate) revisionUpdate.dueDate = new Date(updateDto.dueDate);\r\n if (updateDto.documentDate)\r\n revisionUpdate.documentDate = new Date(updateDto.documentDate);\r\n if (updateDto.issuedDate)\r\n revisionUpdate.issuedDate = new Date(updateDto.issuedDate);\r\n if (updateDto.receivedDate)\r\n revisionUpdate.receivedDate = new Date(updateDto.receivedDate);\r\n if (updateDto.description)\r\n revisionUpdate.description = updateDto.description;\r\n if (updateDto.details) revisionUpdate.details = updateDto.details;\r\n\r\n if (Object.keys(revisionUpdate).length > 0) {\r\n await this.revisionRepo.update(revision.id, revisionUpdate);\r\n }\r\n\r\n // 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage)\r\n if (updateDto.attachmentTempIds?.length) {\r\n const issueDate = updateDto.issuedDate\r\n ? new Date(updateDto.issuedDate)\r\n : updateDto.documentDate\r\n ? new Date(updateDto.documentDate)\r\n : revision.issuedDate || revision.documentDate || undefined;\r\n\r\n await this.fileStorageService.commit(updateDto.attachmentTempIds, {\r\n issueDate: issueDate ? new Date(issueDate) : undefined,\r\n documentType: 'Correspondence',\r\n });\r\n }\r\n\r\n // 5. Update Recipients if provided\r\n if (updResolvedRecipients) {\r\n const recipientRepo = this.dataSource.getRepository(\r\n CorrespondenceRecipient\r\n );\r\n await recipientRepo.delete({ correspondenceId: id });\r\n\r\n const newRecipients = updResolvedRecipients.map((r) =>\r\n recipientRepo.create({\r\n correspondenceId: id,\r\n recipientOrganizationId: r.organizationId,\r\n recipientType: r.type,\r\n })\r\n );\r\n await recipientRepo.save(newRecipients);\r\n }\r\n\r\n // 6. Regenerate Document Number if structural fields changed (Recipient, Discipline, Type, Project)\r\n // AND it is a DRAFT.\r\n\r\n // Fetch fresh data for context and comparison\r\n const currentCorr = await this.correspondenceRepo.findOne({\r\n where: { id },\r\n relations: ['type', 'recipients', 'recipients.recipientOrganization'],\r\n });\r\n\r\n if (currentCorr) {\r\n const currentToRecipient = currentCorr.recipients?.find(\r\n (r) => r.recipientType === 'TO'\r\n );\r\n const currentRecipientId = currentToRecipient?.recipientOrganizationId;\r\n\r\n // Check for ACTUAL value changes\r\n const isProjectChanged =\r\n updResolvedProjectId !== undefined &&\r\n updResolvedProjectId !== currentCorr.projectId;\r\n const isOriginatorChanged =\r\n updResolvedOriginatorId !== undefined &&\r\n updResolvedOriginatorId !== currentCorr.originatorId;\r\n const isDisciplineChanged =\r\n updateDto.disciplineId !== undefined &&\r\n updateDto.disciplineId !== currentCorr.disciplineId;\r\n const isTypeChanged =\r\n updateDto.typeId !== undefined &&\r\n updateDto.typeId !== currentCorr.correspondenceTypeId;\r\n\r\n let isRecipientChanged = false;\r\n let newRecipientId: number | undefined;\r\n\r\n if (updResolvedRecipients) {\r\n const newToRecipient = updResolvedRecipients.find(\r\n (r) => r.type === 'TO'\r\n );\r\n newRecipientId = newToRecipient?.organizationId;\r\n\r\n if (newRecipientId !== currentRecipientId) {\r\n isRecipientChanged = true;\r\n }\r\n }\r\n\r\n if (\r\n isProjectChanged ||\r\n isDisciplineChanged ||\r\n isTypeChanged ||\r\n isRecipientChanged ||\r\n isOriginatorChanged\r\n ) {\r\n const targetRecipientId = isRecipientChanged\r\n ? newRecipientId\r\n : currentRecipientId;\r\n\r\n // Resolve Recipient Code for the NEW context\r\n let recipientCode = '';\r\n if (targetRecipientId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: targetRecipientId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n // [Fix #6] Fetch real ORG Code from originator organization\r\n const originatorOrgForUpdate = await this.dataSource.manager.findOne(\r\n Organization,\r\n {\r\n where: {\r\n id: updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n },\r\n }\r\n );\r\n const orgCode = originatorOrgForUpdate?.organizationCode ?? 'UNK';\r\n\r\n // Prepare Contexts\r\n const oldCtx = {\r\n projectId: currentCorr.projectId,\r\n originatorOrganizationId: currentCorr.originatorId ?? 0,\r\n typeId: currentCorr.correspondenceTypeId,\r\n disciplineId: currentCorr.disciplineId,\r\n recipientOrganizationId: currentRecipientId,\r\n year: new Date().getFullYear(),\r\n };\r\n\r\n const newCtx = {\r\n projectId: updResolvedProjectId ?? currentCorr.projectId,\r\n originatorOrganizationId:\r\n updResolvedOriginatorId ?? currentCorr.originatorId ?? 0,\r\n typeId: updateDto.typeId ?? currentCorr.correspondenceTypeId,\r\n disciplineId: updateDto.disciplineId ?? currentCorr.disciplineId,\r\n recipientOrganizationId: targetRecipientId,\r\n year: new Date().getFullYear(),\r\n userId: user.user_id, // Pass User ID for Audit\r\n customTokens: {\r\n TYPE_CODE: currentCorr.type?.typeCode || '',\r\n ORG_CODE: orgCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n };\r\n\r\n // If Type Changed, need NEW Type Code\r\n if (isTypeChanged) {\r\n const newType = await this.typeRepo.findOne({\r\n where: { id: newCtx.typeId },\r\n });\r\n if (newType) newCtx.customTokens.TYPE_CODE = newType.typeCode;\r\n }\r\n\r\n const newDocNumber = await this.numberingService.updateNumberForDraft(\r\n currentCorr.correspondenceNumber,\r\n oldCtx,\r\n newCtx\r\n );\r\n\r\n await this.correspondenceRepo.update(id, {\r\n correspondenceNumber: newDocNumber,\r\n });\r\n }\r\n }\r\n\r\n const updated = await this.findOne(id);\r\n\r\n // Re-index updated document in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: updated.id,\r\n publicId: updated.publicId,\r\n type: 'correspondence',\r\n docNumber: updated.correspondenceNumber,\r\n title: updateDto.subject ?? updated.revisions?.[0]?.subject,\r\n description: updateDto.description ?? updated.revisions?.[0]?.description,\r\n status: 'DRAFT',\r\n projectId: updated.projectId,\r\n createdAt: updated.createdAt,\r\n });\r\n\r\n return updated;\r\n }\r\n\r\n async previewDocumentNumber(createDto: CreateCorrespondenceDto, user: User) {\r\n // ADR-019: Resolve UUID references\r\n const previewProjectId = await this.uuidResolver.resolveProjectId(\r\n createDto.projectId\r\n );\r\n const previewOriginatorId = createDto.originatorId\r\n ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)\r\n : undefined;\r\n const previewRecipients = createDto.recipients\r\n ? await Promise.all(\r\n createDto.recipients.map(\r\n async (r): Promise => ({\r\n organizationId: await this.uuidResolver.resolveOrganizationId(\r\n r.organizationId\r\n ),\r\n type: r.type,\r\n })\r\n )\r\n )\r\n : undefined;\r\n\r\n const type = await this.typeRepo.findOne({\r\n where: { id: createDto.typeId },\r\n });\r\n if (!type) throw new NotFoundException('Document Type not found');\r\n\r\n let userOrgId = user.primaryOrganizationId;\r\n if (!userOrgId) {\r\n const fullUser = await this.userService.findOne(user.user_id);\r\n if (fullUser) userOrgId = fullUser.primaryOrganizationId;\r\n }\r\n\r\n if (previewOriginatorId && previewOriginatorId !== userOrgId) {\r\n // Allow impersonation for preview\r\n userOrgId = previewOriginatorId;\r\n }\r\n\r\n // Extract recipient from recipients array\r\n const toRecipient = previewRecipients?.find((r) => r.type === 'TO');\r\n const recipientOrganizationId = toRecipient?.organizationId;\r\n\r\n let recipientCode = '';\r\n if (recipientOrganizationId) {\r\n const recOrg = await this.dataSource.manager.findOne(Organization, {\r\n where: { id: recipientOrganizationId },\r\n });\r\n if (recOrg) recipientCode = recOrg.organizationCode;\r\n }\r\n\r\n return this.numberingService.previewNumber({\r\n projectId: previewProjectId,\r\n originatorOrganizationId: userOrgId!,\r\n typeId: createDto.typeId,\r\n disciplineId: createDto.disciplineId,\r\n subTypeId: createDto.subTypeId,\r\n recipientOrganizationId,\r\n year: new Date().getFullYear(),\r\n customTokens: {\r\n TYPE_CODE: type.typeCode,\r\n RECIPIENT_CODE: recipientCode,\r\n REC_CODE: recipientCode,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Business Rule Implementation: EC-CORR-001 - Cancel Correspondence with Downstream Circulation\r\n * Cancel correspondence and handle related circulations\r\n */\r\n async cancel(publicId: string, reason: string, user: User) {\r\n const correspondence = await this.findOneByUuid(publicId);\r\n\r\n // Check if user has permission to cancel (Org Admin or Superadmin only)\r\n const permissions = await this.userService.getUserPermissions(user.user_id);\r\n const canCancel =\r\n permissions.includes('correspondence.cancel') ||\r\n permissions.includes('system.manage_all');\r\n\r\n if (!canCancel) {\r\n throw new ForbiddenException(\r\n 'Only administrators can cancel correspondences'\r\n );\r\n }\r\n\r\n // Check if there are any active circulations\r\n const circulationRepo = this.dataSource.getRepository('Circulation');\r\n const activeCirculations = await circulationRepo.find({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n });\r\n\r\n const warningMessage =\r\n activeCirculations.length > 0\r\n ? `There are ${activeCirculations.length} active circulation(s) for this correspondence. Canceling will force close all related circulations.`\r\n : '';\r\n\r\n // Get the current revision to update status\r\n const currentRevision = await this.revisionRepo.findOne({\r\n where: {\r\n correspondenceId: correspondence.id,\r\n isCurrent: true,\r\n },\r\n });\r\n\r\n if (!currentRevision) {\r\n throw new NotFoundException('Current revision not found');\r\n }\r\n\r\n // Get cancelled status\r\n const cancelledStatus = await this.statusRepo.findOne({\r\n where: { statusCode: 'CANCELLED' },\r\n });\r\n\r\n if (!cancelledStatus) {\r\n throw new InternalServerErrorException('CANCELLED status not found');\r\n }\r\n\r\n const queryRunner = this.dataSource.createQueryRunner();\r\n await queryRunner.connect();\r\n await queryRunner.startTransaction();\r\n\r\n try {\r\n // Update correspondence revision status to CANCELLED\r\n await queryRunner.manager.update(\r\n CorrespondenceRevision,\r\n currentRevision.id,\r\n {\r\n statusId: cancelledStatus.id,\r\n remarks: `Cancelled: ${reason}`,\r\n }\r\n );\r\n\r\n // Force close all active circulations\r\n if (activeCirculations.length > 0) {\r\n await queryRunner.manager.update(\r\n 'Circulation',\r\n {\r\n correspondenceId: correspondence.id,\r\n status: 'OPEN',\r\n },\r\n {\r\n status: 'FORCE_CLOSED',\r\n closedAt: new Date(),\r\n closedBy: user.user_id,\r\n closeReason: `Correspondence cancelled: ${reason}`,\r\n }\r\n );\r\n }\r\n\r\n await queryRunner.commitTransaction();\r\n\r\n // Re-index cancelled status in Elasticsearch (fire-and-forget)\r\n void this.searchService.indexDocument({\r\n id: correspondence.id,\r\n publicId: correspondence.publicId,\r\n type: 'correspondence',\r\n docNumber: correspondence.correspondenceNumber,\r\n title: currentRevision.subject,\r\n status: 'CANCELLED',\r\n projectId: correspondence.projectId,\r\n createdAt: correspondence.createdAt,\r\n });\r\n\r\n // Notify originator's doc-control user about cancellation (fire-and-forget)\r\n if (correspondence.originatorId) {\r\n void this.userService\r\n .findDocControlIdByOrg(correspondence.originatorId)\r\n .then((targetUserId) => {\r\n if (targetUserId) {\r\n void this.notificationService.send({\r\n userId: targetUserId,\r\n title: 'Correspondence Cancelled',\r\n message: `${correspondence.correspondenceNumber} — ${currentRevision.subject} has been cancelled. Reason: ${reason}`,\r\n type: 'EMAIL',\r\n entityType: 'correspondence',\r\n entityId: correspondence.id,\r\n link: `/correspondences/${correspondence.publicId}`,\r\n });\r\n }\r\n })\r\n .catch((err: Error) =>\r\n this.logger.warn(`Cancel notification failed: ${err.message}`)\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n message: warningMessage || 'Correspondence cancelled successfully',\r\n activeCirculationsCount: activeCirculations.length,\r\n };\r\n } catch (error) {\r\n await queryRunner.rollbackTransaction();\r\n this.logger.error(\r\n `Failed to cancel correspondence: ${(error as Error).message}`\r\n );\r\n throw error;\r\n } finally {\r\n await queryRunner.release();\r\n }\r\n }\r\n\r\n async bulkCancel(\r\n publicIds: string[],\r\n reason: string,\r\n user: User\r\n ): Promise<{ succeeded: string[]; failed: string[] }> {\r\n const succeeded: string[] = [];\r\n const failed: string[] = [];\r\n\r\n for (const publicId of publicIds) {\r\n try {\r\n await this.cancel(publicId, reason, user);\r\n succeeded.push(publicId);\r\n } catch {\r\n failed.push(publicId);\r\n }\r\n }\r\n\r\n return { succeeded, failed };\r\n }\r\n\r\n async exportCsv(searchDto: SearchCorrespondenceDto): Promise {\r\n const { data } = await this.findAll(searchDto);\r\n\r\n const header = [\r\n 'Document No.',\r\n 'Rev',\r\n 'Subject',\r\n 'Type',\r\n 'Status',\r\n 'Project',\r\n 'From',\r\n 'Due Date',\r\n 'Created At',\r\n ];\r\n const rows = data.map((rev) => {\r\n const corr = rev.correspondence ?? (rev as unknown as Correspondence);\r\n return [\r\n this.escapeCsv(corr.correspondenceNumber ?? ''),\r\n this.escapeCsv(rev.revisionLabel ?? String(rev.revisionNumber ?? 0)),\r\n this.escapeCsv(rev.subject ?? ''),\r\n this.escapeCsv(corr.type?.typeCode ?? ''),\r\n this.escapeCsv(rev.status?.statusCode ?? ''),\r\n this.escapeCsv(corr.project?.projectCode ?? ''),\r\n this.escapeCsv(corr.originator?.organizationCode ?? ''),\r\n rev.dueDate ? new Date(rev.dueDate).toISOString().split('T')[0] : '',\r\n new Date(rev.createdAt).toISOString().split('T')[0],\r\n ].join(',');\r\n });\r\n\r\n return [header.join(','), ...rows].join('\\n');\r\n }\r\n\r\n private escapeCsv(value: string): string {\r\n if (value.includes(',') || value.includes('\"') || value.includes('\\n')) {\r\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n return value;\r\n }\r\n}\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c new file mode 100644 index 0000000..cef7d9d --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c @@ -0,0 +1,65 @@ +14540db954a05918780678361189125c +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + 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; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Tag = void 0; +const typeorm_1 = require("typeorm"); +const project_entity_1 = require("../../project/entities/project.entity"); +let Tag = class Tag { +}; +exports.Tag = Tag; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)(), + __metadata("design:type", Number) +], Tag.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ name: 'project_id', type: 'int', nullable: true }), + __metadata("design:type", Object) +], Tag.prototype, "projectId", void 0); +__decorate([ + (0, typeorm_1.Column)({ name: 'tag_name', length: 100 }), + __metadata("design:type", String) +], Tag.prototype, "tagName", void 0); +__decorate([ + (0, typeorm_1.Column)({ name: 'color_code', length: 30, default: 'default' }), + __metadata("design:type", String) +], Tag.prototype, "colorCode", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text', nullable: true }), + __metadata("design:type", Object) +], Tag.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => project_entity_1.Project), + (0, typeorm_1.JoinColumn)({ name: 'project_id' }), + __metadata("design:type", typeof (_a = typeof project_entity_1.Project !== "undefined" && project_entity_1.Project) === "function" ? _a : Object) +], Tag.prototype, "project", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ name: 'created_at' }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], Tag.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ name: 'updated_at' }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], Tag.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ name: 'created_by', type: 'int', nullable: true }), + __metadata("design:type", Object) +], Tag.prototype, "createdBy", void 0); +__decorate([ + (0, typeorm_1.DeleteDateColumn)({ name: 'deleted_at' }), + __metadata("design:type", Object) +], Tag.prototype, "deletedAt", void 0); +exports.Tag = Tag = __decorate([ + (0, typeorm_1.Entity)('tags'), + (0, typeorm_1.Unique)('ux_tag_project', ['projectId', 'tagName']) +], Tag); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcbWFzdGVyXFxlbnRpdGllc1xcdGFnLmVudGl0eS50cyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBQUEscUNBVWlCO0FBQ2pCLDBFQUFnRTtBQUl6RCxJQUFNLEdBQUcsR0FBVCxNQUFNLEdBQUc7Q0FnQ2YsQ0FBQTtBQWhDWSxrQkFBRztBQUVkO0lBREMsSUFBQSxnQ0FBc0IsR0FBRTs7K0JBQ2I7QUFHWjtJQURDLElBQUEsZ0JBQU0sRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7O3NDQUNsQztBQUcxQjtJQURDLElBQUEsZ0JBQU0sRUFBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDOztvQ0FDekI7QUFHakI7SUFEQyxJQUFBLGdCQUFNLEVBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDOztzQ0FDNUM7QUFHbkI7SUFEQyxJQUFBLGdCQUFNLEVBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQzs7d0NBQ2I7QUFLNUI7SUFGQyxJQUFBLG1CQUFTLEVBQUMsR0FBRyxFQUFFLENBQUMsd0JBQU8sQ0FBQztJQUN4QixJQUFBLG9CQUFVLEVBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLENBQUM7a0RBQ3pCLHdCQUFPLG9CQUFQLHdCQUFPO29DQUFDO0FBR2xCO0lBREMsSUFBQSwwQkFBZ0IsRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztrREFDN0IsSUFBSSxvQkFBSixJQUFJO3NDQUFDO0FBR2pCO0lBREMsSUFBQSwwQkFBZ0IsRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztrREFDN0IsSUFBSSxvQkFBSixJQUFJO3NDQUFDO0FBR2pCO0lBREMsSUFBQSxnQkFBTSxFQUFDLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQzs7c0NBQ2xDO0FBRzFCO0lBREMsSUFBQSwwQkFBZ0IsRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQzs7c0NBQ2pCO2NBL0JiLEdBQUc7SUFGZixJQUFBLGdCQUFNLEVBQUMsTUFBTSxDQUFDO0lBQ2QsSUFBQSxnQkFBTSxFQUFDLGdCQUFnQixFQUFFLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0dBQ3RDLEdBQUcsQ0FnQ2YiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcbWFzdGVyXFxlbnRpdGllc1xcdGFnLmVudGl0eS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIEVudGl0eSxcclxuICBDb2x1bW4sXHJcbiAgUHJpbWFyeUdlbmVyYXRlZENvbHVtbixcclxuICBDcmVhdGVEYXRlQ29sdW1uLFxyXG4gIFVwZGF0ZURhdGVDb2x1bW4sXHJcbiAgRGVsZXRlRGF0ZUNvbHVtbixcclxuICBVbmlxdWUsXHJcbiAgTWFueVRvT25lLFxyXG4gIEpvaW5Db2x1bW4sXHJcbn0gZnJvbSAndHlwZW9ybSc7XHJcbmltcG9ydCB7IFByb2plY3QgfSBmcm9tICcuLi8uLi9wcm9qZWN0L2VudGl0aWVzL3Byb2plY3QuZW50aXR5JztcclxuXHJcbkBFbnRpdHkoJ3RhZ3MnKVxyXG5AVW5pcXVlKCd1eF90YWdfcHJvamVjdCcsIFsncHJvamVjdElkJywgJ3RhZ05hbWUnXSlcclxuZXhwb3J0IGNsYXNzIFRhZyB7XHJcbiAgQFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4oKVxyXG4gIGlkITogbnVtYmVyOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAQ29sdW1uKHsgbmFtZTogJ3Byb2plY3RfaWQnLCB0eXBlOiAnaW50JywgbnVsbGFibGU6IHRydWUgfSlcclxuICBwcm9qZWN0SWQhOiBudW1iZXIgfCBudWxsOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAQ29sdW1uKHsgbmFtZTogJ3RhZ19uYW1lJywgbGVuZ3RoOiAxMDAgfSlcclxuICB0YWdOYW1lITogc3RyaW5nOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAQ29sdW1uKHsgbmFtZTogJ2NvbG9yX2NvZGUnLCBsZW5ndGg6IDMwLCBkZWZhdWx0OiAnZGVmYXVsdCcgfSlcclxuICBjb2xvckNvZGUhOiBzdHJpbmc7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcblxyXG4gIEBDb2x1bW4oeyB0eXBlOiAndGV4dCcsIG51bGxhYmxlOiB0cnVlIH0pXHJcbiAgZGVzY3JpcHRpb24hOiBzdHJpbmcgfCBudWxsOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICAvLyBSZWxhdGlvbnNcclxuICBATWFueVRvT25lKCgpID0+IFByb2plY3QpXHJcbiAgQEpvaW5Db2x1bW4oeyBuYW1lOiAncHJvamVjdF9pZCcgfSlcclxuICBwcm9qZWN0PzogUHJvamVjdDtcclxuXHJcbiAgQENyZWF0ZURhdGVDb2x1bW4oeyBuYW1lOiAnY3JlYXRlZF9hdCcgfSlcclxuICBjcmVhdGVkQXQhOiBEYXRlOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAVXBkYXRlRGF0ZUNvbHVtbih7IG5hbWU6ICd1cGRhdGVkX2F0JyB9KVxyXG4gIHVwZGF0ZWRBdCE6IERhdGU7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcblxyXG4gIEBDb2x1bW4oeyBuYW1lOiAnY3JlYXRlZF9ieScsIHR5cGU6ICdpbnQnLCBudWxsYWJsZTogdHJ1ZSB9KVxyXG4gIGNyZWF0ZWRCeSE6IG51bWJlciB8IG51bGw7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcblxyXG4gIEBEZWxldGVEYXRlQ29sdW1uKHsgbmFtZTogJ2RlbGV0ZWRfYXQnIH0pXHJcbiAgZGVsZXRlZEF0ITogRGF0ZSB8IG51bGw7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcbn1cclxuIl0sInZlcnNpb24iOjN9 \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c.map new file mode 100644 index 0000000..401c012 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/cd/tagentity_cd09324200fd1ed927db2d852f565a3c.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\master\\entities\\tag.entity.ts","mappings":";;;;;;;;;;;;;AAAA,qCAUiB;AACjB,0EAAgE;AAIzD,IAAM,GAAG,GAAT,MAAM,GAAG;CAgCf,CAAA;AAhCY,kBAAG;AAEd;IADC,IAAA,gCAAsB,GAAE;;+BACb;AAGZ;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;sCAClC;AAG1B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;oCACzB;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;;sCAC5C;AAGnB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;wCACb;AAK5B;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,wBAAO,CAAC;IACxB,IAAA,oBAAU,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;kDACzB,wBAAO,oBAAP,wBAAO;oCAAC;AAGlB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;kDAC7B,IAAI,oBAAJ,IAAI;sCAAC;AAGjB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;kDAC7B,IAAI,oBAAJ,IAAI;sCAAC;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;sCAClC;AAG1B;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;;sCACjB;cA/Bb,GAAG;IAFf,IAAA,gBAAM,EAAC,MAAM,CAAC;IACd,IAAA,gBAAM,EAAC,gBAAgB,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;GACtC,GAAG,CAgCf","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\master\\entities\\tag.entity.ts"],"sourcesContent":["import {\r\n Entity,\r\n Column,\r\n PrimaryGeneratedColumn,\r\n CreateDateColumn,\r\n UpdateDateColumn,\r\n DeleteDateColumn,\r\n Unique,\r\n ManyToOne,\r\n JoinColumn,\r\n} from 'typeorm';\r\nimport { Project } from '../../project/entities/project.entity';\r\n\r\n@Entity('tags')\r\n@Unique('ux_tag_project', ['projectId', 'tagName'])\r\nexport class Tag {\r\n @PrimaryGeneratedColumn()\r\n id!: number; // เพิ่ม !\r\n\r\n @Column({ name: 'project_id', type: 'int', nullable: true })\r\n projectId!: number | null; // เพิ่ม !\r\n\r\n @Column({ name: 'tag_name', length: 100 })\r\n tagName!: string; // เพิ่ม !\r\n\r\n @Column({ name: 'color_code', length: 30, default: 'default' })\r\n colorCode!: string; // เพิ่ม !\r\n\r\n @Column({ type: 'text', nullable: true })\r\n description!: string | null; // เพิ่ม !\r\n\r\n // Relations\r\n @ManyToOne(() => Project)\r\n @JoinColumn({ name: 'project_id' })\r\n project?: Project;\r\n\r\n @CreateDateColumn({ name: 'created_at' })\r\n createdAt!: Date; // เพิ่ม !\r\n\r\n @UpdateDateColumn({ name: 'updated_at' })\r\n updatedAt!: Date; // เพิ่ม !\r\n\r\n @Column({ name: 'created_by', type: 'int', nullable: true })\r\n createdBy!: number | null; // เพิ่ม !\r\n\r\n @DeleteDateColumn({ name: 'deleted_at' })\r\n deletedAt!: Date | null; // เพิ่ม !\r\n}\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03 b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03 new file mode 100644 index 0000000..c665be3 --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03 @@ -0,0 +1,361 @@ +7710e092c56e7167f1b8a5efd18af77b +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const testing_1 = require("@nestjs/testing"); +const typeorm_1 = require("@nestjs/typeorm"); +const typeorm_2 = require("typeorm"); +const correspondence_service_1 = require("./correspondence.service"); +const correspondence_entity_1 = require("./entities/correspondence.entity"); +const correspondence_revision_entity_1 = require("./entities/correspondence-revision.entity"); +const correspondence_type_entity_1 = require("./entities/correspondence-type.entity"); +const correspondence_status_entity_1 = require("./entities/correspondence-status.entity"); +const correspondence_reference_entity_1 = require("./entities/correspondence-reference.entity"); +const correspondence_tag_entity_1 = require("./entities/correspondence-tag.entity"); +const organization_entity_1 = require("../organization/entities/organization.entity"); +const correspondence_recipient_entity_1 = require("./entities/correspondence-recipient.entity"); +const document_numbering_service_1 = require("../document-numbering/services/document-numbering.service"); +const json_schema_service_1 = require("../json-schema/json-schema.service"); +const workflow_engine_service_1 = require("../workflow-engine/workflow-engine.service"); +const user_service_1 = require("../user/user.service"); +const search_service_1 = require("../search/search.service"); +const file_storage_service_1 = require("../../common/file-storage/file-storage.service"); +const uuid_resolver_service_1 = require("../../common/services/uuid-resolver.service"); +const notification_service_1 = require("../notification/notification.service"); +describe('CorrespondenceService', () => { + let service; + let numberingService; + let correspondenceRepo; + let revisionRepo; + let testingModule; + let _dataSource; + const createMockRepository = () => ({ + find: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + save: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + softDelete: jest.fn(), + createQueryBuilder: jest.fn(() => ({ + leftJoinAndSelect: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + andWhere: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockReturnThis(), + take: jest.fn().mockReturnThis(), + getOne: jest.fn().mockResolvedValue(null), + getMany: jest.fn().mockResolvedValue([]), + getManyAndCount: jest.fn().mockResolvedValue([[], 0]), + })), + }); + const mockDataSource = { + createQueryRunner: jest.fn(() => ({ + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn(), + save: jest.fn(), + findOne: jest.fn(), + }, + })), + getRepository: jest.fn(() => createMockRepository()), + manager: { + findOne: jest.fn(), + }, + }; + beforeEach(async () => { + testingModule = await testing_1.Test.createTestingModule({ + providers: [ + correspondence_service_1.CorrespondenceService, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_reference_entity_1.CorrespondenceReference), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_tag_entity_1.CorrespondenceTag), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(organization_entity_1.Organization), + useValue: createMockRepository(), + }, + { + provide: (0, typeorm_1.getRepositoryToken)(correspondence_recipient_entity_1.CorrespondenceRecipient), + useValue: createMockRepository(), + }, + { + provide: document_numbering_service_1.DocumentNumberingService, + useValue: { + generateNextNumber: jest.fn(), + updateNumberForDraft: jest.fn(), + previewNextNumber: jest.fn(), + }, + }, + { + provide: json_schema_service_1.JsonSchemaService, + useValue: { validate: jest.fn() }, + }, + { + provide: workflow_engine_service_1.WorkflowEngineService, + useValue: { createInstance: jest.fn() }, + }, + { + provide: user_service_1.UserService, + useValue: { + findOne: jest.fn(), + getUserPermissions: jest.fn().mockResolvedValue([]), + }, + }, + { + provide: typeorm_2.DataSource, + useValue: mockDataSource, + }, + { + provide: search_service_1.SearchService, + useValue: { indexDocument: jest.fn() }, + }, + { + provide: file_storage_service_1.FileStorageService, + useValue: { commit: jest.fn().mockResolvedValue([]) }, + }, + { + provide: uuid_resolver_service_1.UuidResolverService, + useValue: { + resolveProjectId: jest.fn().mockResolvedValue(1), + resolveOrganizationId: jest.fn().mockResolvedValue(1), + }, + }, + { + provide: notification_service_1.NotificationService, + useValue: { send: jest.fn().mockResolvedValue(undefined) }, + }, + ], + }).compile(); + service = testingModule.get(correspondence_service_1.CorrespondenceService); + numberingService = testingModule.get(document_numbering_service_1.DocumentNumberingService); + correspondenceRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_entity_1.Correspondence)); + revisionRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_revision_entity_1.CorrespondenceRevision)); + _dataSource = testingModule.get(typeorm_2.DataSource); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('update', () => { + it('should NOT regenerate number if critical fields unchanged', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 1, + disciplineId: 3, + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).not.toHaveBeenCalled(); + }); + it('should regenerate number if Project ID changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + projectId: 2, + }; + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + uuidResolver.resolveProjectId.mockResolvedValue(2); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Document Type changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + const updateDto = { + typeId: 999, + }; + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + typeRepo.findOne.mockResolvedValue({ + id: 999, + typeCode: 'NEW-TYPE', + }); + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + it('should regenerate number if Recipient Organization changes', async () => { + const mockUser = { id: 1, primaryOrganizationId: 10 }; + const mockRevision = { + id: 100, + correspondenceId: 1, + isCurrent: true, + statusId: 5, + }; + jest + .spyOn(revisionRepo, 'findOne') + .mockResolvedValue(mockRevision); + const mockCorr = { + id: 1, + projectId: 1, + correspondenceTypeId: 2, + disciplineId: 3, + originatorId: 10, + correspondenceNumber: 'OLD-NUM', + recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }], + }; + jest + .spyOn(correspondenceRepo, 'findOne') + .mockResolvedValue(mockCorr); + // Access DataSource manager for mocking + mockDataSource.manager.findOne.mockResolvedValue({ + id: 88, + organizationCode: 'NEW-ORG', + }); + const updateDto = { + recipients: [{ type: 'TO', organizationId: 88 }], + }; + await service.update(1, updateDto, mockUser); + expect(numberingService.updateNumberForDraft).toHaveBeenCalled(); + }); + }); + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + }; + const createDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + const userService = testingModule.get(user_service_1.UserService); + const typeRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_type_entity_1.CorrespondenceType)); + const statusRepo = testingModule.get((0, typeorm_1.getRepositoryToken)(correspondence_status_entity_1.CorrespondenceStatus)); + const uuidResolver = testingModule.get(uuid_resolver_service_1.UuidResolverService); + userService.findOne.mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + userService.getUserPermissions.mockResolvedValue([ + 'system.manage_all', + ]); + uuidResolver.resolveProjectId.mockResolvedValue(100); + uuidResolver.resolveOrganizationId.mockImplementation((value) => { + if (value === 'originator-uuid') + return 10; + if (value === 'recipient-uuid') + return 20; + return 0; + }); + typeRepo.findOne.mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + statusRepo.findOne.mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + numberingService.generateNextNumber.mockResolvedValue({ + number: 'DOC-001', + }); + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn((_entity, payload) => payload), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + mockDataSource.createQueryRunner.mockReturnValue(queryRunner); + await service.create(createDto, mockUser); + expect(queryRunner.manager.create).toHaveBeenCalledWith(correspondence_entity_1.Correspondence, expect.objectContaining({ originatorId: 10 })); + }); + }); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcY29ycmVzcG9uZGVuY2VcXGNvcnJlc3BvbmRlbmNlLnNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFzRDtBQUN0RCw2Q0FBcUQ7QUFDckQscUNBQWlEO0FBQ2pELHFFQUFpRTtBQUNqRSw0RUFBa0U7QUFDbEUsOEZBQW1GO0FBQ25GLHNGQUEyRTtBQUMzRSwwRkFBK0U7QUFDL0UsZ0dBQXFGO0FBQ3JGLG9GQUF5RTtBQUN6RSxzRkFBNEU7QUFDNUUsZ0dBQXFGO0FBQ3JGLDBHQUFxRztBQUNyRyw0RUFBdUU7QUFDdkUsd0ZBQW1GO0FBQ25GLHVEQUFtRDtBQUNuRCw2REFBeUQ7QUFDekQseUZBQW9GO0FBQ3BGLHVGQUFrRjtBQUNsRiwrRUFBMkU7QUFLM0UsUUFBUSxDQUFDLHVCQUF1QixFQUFFLEdBQUcsRUFBRTtJQUNyQyxJQUFJLE9BQThCLENBQUM7SUFDbkMsSUFBSSxnQkFBMEMsQ0FBQztJQUMvQyxJQUFJLGtCQUE4QyxDQUFDO0lBQ25ELElBQUksWUFBZ0QsQ0FBQztJQUNyRCxJQUFJLGFBQTRCLENBQUM7SUFDakMsSUFBSSxXQUF1QixDQUFDO0lBRTVCLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNsQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNmLE9BQU8sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2xCLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2pCLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2YsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDakIsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDakIsVUFBVSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDckIsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ2pDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDN0MsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDakMsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDcEMsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDbkMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDaEMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDaEMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUM7WUFDekMsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7WUFDeEMsZUFBZSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUN0RCxDQUFDLENBQUM7S0FDSixDQUFDLENBQUM7SUFFSCxNQUFNLGNBQWMsR0FBRztRQUNyQixpQkFBaUIsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDaEMsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDbEIsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUMzQixpQkFBaUIsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1lBQzVCLG1CQUFtQixFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDOUIsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDbEIsT0FBTyxFQUFFO2dCQUNQLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO2dCQUNqQixJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDZixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTthQUNuQjtTQUNGLENBQUMsQ0FBQztRQUNILGFBQWEsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDcEQsT0FBTyxFQUFFO1lBQ1AsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7U0FDbkI7S0FDRixDQUFDO0lBRUYsVUFBVSxDQUFDLEtBQUssSUFBSSxFQUFFO1FBQ3BCLGFBQWEsR0FBRyxNQUFNLGNBQUksQ0FBQyxtQkFBbUIsQ0FBQztZQUM3QyxTQUFTLEVBQUU7Z0JBQ1QsOENBQXFCO2dCQUNyQjtvQkFDRSxPQUFPLEVBQUUsSUFBQSw0QkFBa0IsRUFBQyxzQ0FBYyxDQUFDO29CQUMzQyxRQUFRLEVBQUUsb0JBQW9CLEVBQUU7aUJBQ2pDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxJQUFBLDRCQUFrQixFQUFDLHVEQUFzQixDQUFDO29CQUNuRCxRQUFRLEVBQUUsb0JBQW9CLEVBQUU7aUJBQ2pDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxJQUFBLDRCQUFrQixFQUFDLCtDQUFrQixDQUFDO29CQUMvQyxRQUFRLEVBQUUsb0JBQW9CLEVBQUU7aUJBQ2pDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxJQUFBLDRCQUFrQixFQUFDLG1EQUFvQixDQUFDO29CQUNqRCxRQUFRLEVBQUUsb0JBQW9CLEVBQUU7aUJBQ2pDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxJQUFBLDRCQUFrQixFQUFDLHlEQUF1QixDQUFDO29CQUNwRCxRQUFRLEVBQUUsb0JBQW9CLEVBQUU7aUJBQ2pDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxJQUFBLDRCQUFrQixFQUFDLDZDQUFpQixDQUFDO29CQUM5QyxRQUFRLEVBQUUsb0JBQW9CLEVBQUU7aUJBQ2pDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxJQUFBLDRCQUFrQixFQUFDLGtDQUFZLENBQUM7b0JBQ3pDLFFBQVEsRUFBRSxvQkFBb0IsRUFBRTtpQkFDakM7Z0JBQ0Q7b0JBQ0UsT0FBTyxFQUFFLElBQUEsNEJBQWtCLEVBQUMseURBQXVCLENBQUM7b0JBQ3BELFFBQVEsRUFBRSxvQkFBb0IsRUFBRTtpQkFDakM7Z0JBQ0Q7b0JBQ0UsT0FBTyxFQUFFLHFEQUF3QjtvQkFDakMsUUFBUSxFQUFFO3dCQUNSLGtCQUFrQixFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7d0JBQzdCLG9CQUFvQixFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7d0JBQy9CLGlCQUFpQixFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7cUJBQzdCO2lCQUNGO2dCQUNEO29CQUNFLE9BQU8sRUFBRSx1Q0FBaUI7b0JBQzFCLFFBQVEsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUU7aUJBQ2xDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSwrQ0FBcUI7b0JBQzlCLFFBQVEsRUFBRSxFQUFFLGNBQWMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUU7aUJBQ3hDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSwwQkFBVztvQkFDcEIsUUFBUSxFQUFFO3dCQUNSLE9BQU8sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO3dCQUNsQixrQkFBa0IsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO3FCQUNwRDtpQkFDRjtnQkFDRDtvQkFDRSxPQUFPLEVBQUUsb0JBQVU7b0JBQ25CLFFBQVEsRUFBRSxjQUFjO2lCQUN6QjtnQkFDRDtvQkFDRSxPQUFPLEVBQUUsOEJBQWE7b0JBQ3RCLFFBQVEsRUFBRSxFQUFFLGFBQWEsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUU7aUJBQ3ZDO2dCQUNEO29CQUNFLE9BQU8sRUFBRSx5Q0FBa0I7b0JBQzNCLFFBQVEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDLEVBQUU7aUJBQ3REO2dCQUNEO29CQUNFLE9BQU8sRUFBRSwyQ0FBbUI7b0JBQzVCLFFBQVEsRUFBRTt3QkFDUixnQkFBZ0IsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO3dCQUNoRCxxQkFBcUIsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO3FCQUN0RDtpQkFDRjtnQkFDRDtvQkFDRSxPQUFPLEVBQUUsMENBQW1CO29CQUM1QixRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxFQUFFO2lCQUMzRDthQUNGO1NBQ0YsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRWIsT0FBTyxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQXdCLDhDQUFxQixDQUFDLENBQUM7UUFDMUUsZ0JBQWdCLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FDbEMscURBQXdCLENBQ3pCLENBQUM7UUFDRixrQkFBa0IsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUNwQyxJQUFBLDRCQUFrQixFQUFDLHNDQUFjLENBQUMsQ0FDbkMsQ0FBQztRQUNGLFlBQVksR0FBRyxhQUFhLENBQUMsR0FBRyxDQUM5QixJQUFBLDRCQUFrQixFQUFDLHVEQUFzQixDQUFDLENBQzNDLENBQUM7UUFDRixXQUFXLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FBYSxvQkFBVSxDQUFDLENBQUM7SUFDMUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxFQUFFO1FBQzNCLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNoQyxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxRQUFRLEVBQUUsR0FBRyxFQUFFO1FBQ3RCLEVBQUUsQ0FBQywyREFBMkQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUN6RSxNQUFNLFFBQVEsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUscUJBQXFCLEVBQUUsRUFBRSxFQUFxQixDQUFDO1lBQ3pFLE1BQU0sWUFBWSxHQUFHO2dCQUNuQixFQUFFLEVBQUUsR0FBRztnQkFDUCxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNuQixTQUFTLEVBQUUsSUFBSTtnQkFDZixRQUFRLEVBQUUsQ0FBQzthQUNaLENBQUM7WUFFRixJQUFJO2lCQUNELEtBQUssQ0FBQyxZQUFZLEVBQUUsU0FBUyxDQUFDO2lCQUM5QixpQkFBaUIsQ0FBQyxZQUFpRCxDQUFDLENBQUM7WUFFeEUsTUFBTSxRQUFRLEdBQUc7Z0JBQ2YsRUFBRSxFQUFFLENBQUM7Z0JBQ0wsU0FBUyxFQUFFLENBQUM7Z0JBQ1osb0JBQW9CLEVBQUUsQ0FBQztnQkFDdkIsWUFBWSxFQUFFLENBQUM7Z0JBQ2YsWUFBWSxFQUFFLEVBQUU7Z0JBQ2hCLG9CQUFvQixFQUFFLFNBQVM7Z0JBQy9CLFVBQVUsRUFBRSxDQUFDLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSx1QkFBdUIsRUFBRSxFQUFFLEVBQUUsQ0FBQzthQUNuRSxDQUFDO1lBQ0YsSUFBSTtpQkFDRCxLQUFLLENBQUMsa0JBQWtCLEVBQUUsU0FBUyxDQUFDO2lCQUNwQyxpQkFBaUIsQ0FBQyxRQUFxQyxDQUFDLENBQUM7WUFFNUQsTUFBTSxTQUFTLEdBQTRCO2dCQUN6QyxTQUFTLEVBQUUsQ0FBQztnQkFDWixZQUFZLEVBQUUsQ0FBQzthQUNoQixDQUFDO1lBRUYsTUFBTSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFFN0MsTUFBTSxDQUNKLGdCQUFnQixDQUFDLG9CQUFpQyxDQUNuRCxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQzNCLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGdEQUFnRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzlELE1BQU0sUUFBUSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxxQkFBcUIsRUFBRSxFQUFFLEVBQXFCLENBQUM7WUFDekUsTUFBTSxZQUFZLEdBQUc7Z0JBQ25CLEVBQUUsRUFBRSxHQUFHO2dCQUNQLGdCQUFnQixFQUFFLENBQUM7Z0JBQ25CLFNBQVMsRUFBRSxJQUFJO2dCQUNmLFFBQVEsRUFBRSxDQUFDO2FBQ1osQ0FBQztZQUNGLElBQUk7aUJBQ0QsS0FBSyxDQUFDLFlBQVksRUFBRSxTQUFTLENBQUM7aUJBQzlCLGlCQUFpQixDQUFDLFlBQWlELENBQUMsQ0FBQztZQUV4RSxNQUFNLFFBQVEsR0FBRztnQkFDZixFQUFFLEVBQUUsQ0FBQztnQkFDTCxTQUFTLEVBQUUsQ0FBQztnQkFDWixvQkFBb0IsRUFBRSxDQUFDO2dCQUN2QixZQUFZLEVBQUUsQ0FBQztnQkFDZixZQUFZLEVBQUUsRUFBRTtnQkFDaEIsb0JBQW9CLEVBQUUsU0FBUztnQkFDL0IsVUFBVSxFQUFFLENBQUMsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLHVCQUF1QixFQUFFLEVBQUUsRUFBRSxDQUFDO2FBQ25FLENBQUM7WUFDRixJQUFJO2lCQUNELEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxTQUFTLENBQUM7aUJBQ3BDLGlCQUFpQixDQUFDLFFBQXFDLENBQUMsQ0FBQztZQUU1RCxNQUFNLFNBQVMsR0FBNEI7Z0JBQ3pDLFNBQVMsRUFBRSxDQUFDO2FBQ2IsQ0FBQztZQUVGLE1BQU0sWUFBWSxHQUNoQixhQUFhLENBQUMsR0FBRyxDQUFzQiwyQ0FBbUIsQ0FBQyxDQUFDO1lBQzdELFlBQVksQ0FBQyxnQkFBOEIsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVsRSxNQUFNLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUU3QyxNQUFNLENBQ0osZ0JBQWdCLENBQUMsb0JBQWlDLENBQ25ELENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUN2QixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxtREFBbUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNqRSxNQUFNLFFBQVEsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUscUJBQXFCLEVBQUUsRUFBRSxFQUFxQixDQUFDO1lBQ3pFLE1BQU0sWUFBWSxHQUFHO2dCQUNuQixFQUFFLEVBQUUsR0FBRztnQkFDUCxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNuQixTQUFTLEVBQUUsSUFBSTtnQkFDZixRQUFRLEVBQUUsQ0FBQzthQUNaLENBQUM7WUFDRixJQUFJO2lCQUNELEtBQUssQ0FBQyxZQUFZLEVBQUUsU0FBUyxDQUFDO2lCQUM5QixpQkFBaUIsQ0FBQyxZQUFpRCxDQUFDLENBQUM7WUFFeEUsTUFBTSxRQUFRLEdBQUc7Z0JBQ2YsRUFBRSxFQUFFLENBQUM7Z0JBQ0wsU0FBUyxFQUFFLENBQUM7Z0JBQ1osb0JBQW9CLEVBQUUsQ0FBQztnQkFDdkIsWUFBWSxFQUFFLENBQUM7Z0JBQ2YsWUFBWSxFQUFFLEVBQUU7Z0JBQ2hCLG9CQUFvQixFQUFFLFNBQVM7Z0JBQy9CLFVBQVUsRUFBRSxDQUFDLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSx1QkFBdUIsRUFBRSxFQUFFLEVBQUUsQ0FBQzthQUNuRSxDQUFDO1lBQ0YsSUFBSTtpQkFDRCxLQUFLLENBQUMsa0JBQWtCLEVBQUUsU0FBUyxDQUFDO2lCQUNwQyxpQkFBaUIsQ0FBQyxRQUFxQyxDQUFDLENBQUM7WUFFNUQsTUFBTSxTQUFTLEdBQTRCO2dCQUN6QyxNQUFNLEVBQUUsR0FBRzthQUNaLENBQUM7WUFFRixNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUNoQyxJQUFBLDRCQUFrQixFQUFDLCtDQUFrQixDQUFDLENBQ3ZDLENBQUM7WUFDRCxRQUFRLENBQUMsT0FBcUIsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDaEQsRUFBRSxFQUFFLEdBQUc7Z0JBQ1AsUUFBUSxFQUFFLFVBQVU7YUFDckIsQ0FBQyxDQUFDO1lBRUgsTUFBTSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFFN0MsTUFBTSxDQUNKLGdCQUFnQixDQUFDLG9CQUFpQyxDQUNuRCxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdkIsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNERBQTRELEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDMUUsTUFBTSxRQUFRLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLHFCQUFxQixFQUFFLEVBQUUsRUFBcUIsQ0FBQztZQUN6RSxNQUFNLFlBQVksR0FBRztnQkFDbkIsRUFBRSxFQUFFLEdBQUc7Z0JBQ1AsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDbkIsU0FBUyxFQUFFLElBQUk7Z0JBQ2YsUUFBUSxFQUFFLENBQUM7YUFDWixDQUFDO1lBQ0YsSUFBSTtpQkFDRCxLQUFLLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQztpQkFDOUIsaUJBQWlCLENBQUMsWUFBaUQsQ0FBQyxDQUFDO1lBRXhFLE1BQU0sUUFBUSxHQUFHO2dCQUNmLEVBQUUsRUFBRSxDQUFDO2dCQUNMLFNBQVMsRUFBRSxDQUFDO2dCQUNaLG9CQUFvQixFQUFFLENBQUM7Z0JBQ3ZCLFlBQVksRUFBRSxDQUFDO2dCQUNmLFlBQVksRUFBRSxFQUFFO2dCQUNoQixvQkFBb0IsRUFBRSxTQUFTO2dCQUMvQixVQUFVLEVBQUUsQ0FBQyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsdUJBQXVCLEVBQUUsRUFBRSxFQUFFLENBQUM7YUFDbkUsQ0FBQztZQUNGLElBQUk7aUJBQ0QsS0FBSyxDQUFDLGtCQUFrQixFQUFFLFNBQVMsQ0FBQztpQkFDcEMsaUJBQWlCLENBQUMsUUFBcUMsQ0FBQyxDQUFDO1lBRTVELHdDQUF3QztZQUN4QyxjQUFjLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztnQkFDL0MsRUFBRSxFQUFFLEVBQUU7Z0JBQ04sZ0JBQWdCLEVBQUUsU0FBUzthQUNELENBQUMsQ0FBQztZQUU5QixNQUFNLFNBQVMsR0FBNEI7Z0JBQ3pDLFVBQVUsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsRUFBRSxFQUFFLENBQUM7YUFDakQsQ0FBQztZQUVGLE1BQU0sT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBRTdDLE1BQU0sQ0FDSixnQkFBZ0IsQ0FBQyxvQkFBaUMsQ0FDbkQsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtRQUN0QixFQUFFLENBQUMsaUdBQWlHLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDL0csTUFBTSxRQUFRLEdBQUc7Z0JBQ2YsT0FBTyxFQUFFLENBQUM7Z0JBQ1YscUJBQXFCLEVBQUUsSUFBSTthQUNULENBQUM7WUFFckIsTUFBTSxTQUFTLEdBQTRCO2dCQUN6QyxTQUFTLEVBQUUsY0FBYztnQkFDekIsTUFBTSxFQUFFLENBQUM7Z0JBQ1QsT0FBTyxFQUFFLGNBQWM7Z0JBQ3ZCLFlBQVksRUFBRSxpQkFBaUI7Z0JBQy9CLFVBQVUsRUFBRSxDQUFDLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQzthQUMvRCxDQUFDO1lBRUYsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FBYywwQkFBVyxDQUFDLENBQUM7WUFDaEUsTUFBTSxRQUFRLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FDaEMsSUFBQSw0QkFBa0IsRUFBQywrQ0FBa0IsQ0FBQyxDQUN2QyxDQUFDO1lBQ0YsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FDbEMsSUFBQSw0QkFBa0IsRUFBQyxtREFBb0IsQ0FBQyxDQUN6QyxDQUFDO1lBQ0YsTUFBTSxZQUFZLEdBQ2hCLGFBQWEsQ0FBQyxHQUFHLENBQXNCLDJDQUFtQixDQUFDLENBQUM7WUFFN0QsV0FBVyxDQUFDLE9BQXFCLENBQUMsaUJBQWlCLENBQUM7Z0JBQ25ELE9BQU8sRUFBRSxDQUFDO2dCQUNWLHFCQUFxQixFQUFFLElBQUk7YUFDNUIsQ0FBQyxDQUFDO1lBQ0YsV0FBVyxDQUFDLGtCQUFnQyxDQUFDLGlCQUFpQixDQUFDO2dCQUM5RCxtQkFBbUI7YUFDcEIsQ0FBQyxDQUFDO1lBRUYsWUFBWSxDQUFDLGdCQUE4QixDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25FLFlBQVksQ0FBQyxxQkFBbUMsQ0FBQyxrQkFBa0IsQ0FDbEUsQ0FBQyxLQUFzQixFQUFFLEVBQUU7Z0JBQ3pCLElBQUksS0FBSyxLQUFLLGlCQUFpQjtvQkFBRSxPQUFPLEVBQUUsQ0FBQztnQkFDM0MsSUFBSSxLQUFLLEtBQUssZ0JBQWdCO29CQUFFLE9BQU8sRUFBRSxDQUFDO2dCQUMxQyxPQUFPLENBQUMsQ0FBQztZQUNYLENBQUMsQ0FDRixDQUFDO1lBRUQsUUFBUSxDQUFDLE9BQXFCLENBQUMsaUJBQWlCLENBQUM7Z0JBQ2hELEVBQUUsRUFBRSxDQUFDO2dCQUNMLFFBQVEsRUFBRSxLQUFLO2FBQ2hCLENBQUMsQ0FBQztZQUNGLFVBQVUsQ0FBQyxPQUFxQixDQUFDLGlCQUFpQixDQUFDO2dCQUNsRCxFQUFFLEVBQUUsQ0FBQztnQkFDTCxVQUFVLEVBQUUsT0FBTzthQUNwQixDQUFDLENBQUM7WUFFRixnQkFBZ0IsQ0FBQyxrQkFBZ0MsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDbkUsTUFBTSxFQUFFLFNBQVM7YUFDbEIsQ0FBQyxDQUFDO1lBRUgsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFPO2lCQUMzQixxQkFBcUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLENBQUM7aUJBQzFELHFCQUFxQixDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBRTlELE1BQU0sV0FBVyxHQUFHO2dCQUNsQixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDbEIsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDM0IsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDNUIsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDOUIsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7Z0JBQ2xCLE9BQU8sRUFBRTtvQkFDUCxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FDYixDQUFDLE9BQWdCLEVBQUUsT0FBZ0MsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUNoRTtvQkFDRCxJQUFJLEVBQUUsSUFBSTt5QkFDUCxFQUFFLEVBQUU7eUJBQ0oscUJBQXFCLENBQUMsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsQ0FBQzt5QkFDekQscUJBQXFCLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7eUJBQ25DLHFCQUFxQixDQUFDLEVBQUUsQ0FBQztvQkFDNUIsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7aUJBQ25CO2FBQ0YsQ0FBQztZQUVELGNBQWMsQ0FBQyxpQkFBK0IsQ0FBQyxlQUFlLENBQzdELFdBQVcsQ0FDWixDQUFDO1lBRUYsTUFBTSxPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUUxQyxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxvQkFBb0IsQ0FDckQsc0NBQWMsRUFDZCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FDOUMsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJFOlxcbnAtZG1zXFxsY2JwM1xcYmFja2VuZFxcc3JjXFxtb2R1bGVzXFxjb3JyZXNwb25kZW5jZVxcY29ycmVzcG9uZGVuY2Uuc2VydmljZS5zcGVjLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRlc3QsIFRlc3RpbmdNb2R1bGUgfSBmcm9tICdAbmVzdGpzL3Rlc3RpbmcnO1xyXG5pbXBvcnQgeyBnZXRSZXBvc2l0b3J5VG9rZW4gfSBmcm9tICdAbmVzdGpzL3R5cGVvcm0nO1xyXG5pbXBvcnQgeyBEYXRhU291cmNlLCBSZXBvc2l0b3J5IH0gZnJvbSAndHlwZW9ybSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlU2VydmljZSB9IGZyb20gJy4vY29ycmVzcG9uZGVuY2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJldmlzaW9uIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS1yZXZpc2lvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVR5cGUgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXR5cGUuZW50aXR5JztcclxuaW1wb3J0IHsgQ29ycmVzcG9uZGVuY2VTdGF0dXMgfSBmcm9tICcuL2VudGl0aWVzL2NvcnJlc3BvbmRlbmNlLXN0YXR1cy5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlZmVyZW5jZSB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVmZXJlbmNlLmVudGl0eSc7XHJcbmltcG9ydCB7IENvcnJlc3BvbmRlbmNlVGFnIH0gZnJvbSAnLi9lbnRpdGllcy9jb3JyZXNwb25kZW5jZS10YWcuZW50aXR5JztcclxuaW1wb3J0IHsgT3JnYW5pemF0aW9uIH0gZnJvbSAnLi4vb3JnYW5pemF0aW9uL2VudGl0aWVzL29yZ2FuaXphdGlvbi5lbnRpdHknO1xyXG5pbXBvcnQgeyBDb3JyZXNwb25kZW5jZVJlY2lwaWVudCB9IGZyb20gJy4vZW50aXRpZXMvY29ycmVzcG9uZGVuY2UtcmVjaXBpZW50LmVudGl0eSc7XHJcbmltcG9ydCB7IERvY3VtZW50TnVtYmVyaW5nU2VydmljZSB9IGZyb20gJy4uL2RvY3VtZW50LW51bWJlcmluZy9zZXJ2aWNlcy9kb2N1bWVudC1udW1iZXJpbmcuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vanNvbi1zY2hlbWEvanNvbi1zY2hlbWEuc2VydmljZSc7XHJcbmltcG9ydCB7IFdvcmtmbG93RW5naW5lU2VydmljZSB9IGZyb20gJy4uL3dvcmtmbG93LWVuZ2luZS93b3JrZmxvdy1lbmdpbmUuc2VydmljZSc7XHJcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci91c2VyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vc2VhcmNoL3NlYXJjaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL2ZpbGUtc3RvcmFnZS9maWxlLXN0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IFV1aWRSZXNvbHZlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvdXVpZC1yZXNvbHZlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vdXBkYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvIH0gZnJvbSAnLi9kdG8vY3JlYXRlLWNvcnJlc3BvbmRlbmNlLmR0byc7XHJcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi91c2VyL2VudGl0aWVzL3VzZXIuZW50aXR5JztcclxuXHJcbmRlc2NyaWJlKCdDb3JyZXNwb25kZW5jZVNlcnZpY2UnLCAoKSA9PiB7XHJcbiAgbGV0IHNlcnZpY2U6IENvcnJlc3BvbmRlbmNlU2VydmljZTtcclxuICBsZXQgbnVtYmVyaW5nU2VydmljZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlO1xyXG4gIGxldCBjb3JyZXNwb25kZW5jZVJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2U+O1xyXG4gIGxldCByZXZpc2lvblJlcG86IFJlcG9zaXRvcnk8Q29ycmVzcG9uZGVuY2VSZXZpc2lvbj47XHJcbiAgbGV0IHRlc3RpbmdNb2R1bGU6IFRlc3RpbmdNb2R1bGU7XHJcbiAgbGV0IF9kYXRhU291cmNlOiBEYXRhU291cmNlO1xyXG5cclxuICBjb25zdCBjcmVhdGVNb2NrUmVwb3NpdG9yeSA9ICgpID0+ICh7XHJcbiAgICBmaW5kOiBqZXN0LmZuKCksXHJcbiAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGU6IGplc3QuZm4oKSxcclxuICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgIHVwZGF0ZTogamVzdC5mbigpLFxyXG4gICAgZGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBzb2Z0RGVsZXRlOiBqZXN0LmZuKCksXHJcbiAgICBjcmVhdGVRdWVyeUJ1aWxkZXI6IGplc3QuZm4oKCkgPT4gKHtcclxuICAgICAgbGVmdEpvaW5BbmRTZWxlY3Q6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB3aGVyZTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIGFuZFdoZXJlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgb3JkZXJCeTogamVzdC5mbigpLm1vY2tSZXR1cm5UaGlzKCksXHJcbiAgICAgIHNraXA6IGplc3QuZm4oKS5tb2NrUmV0dXJuVGhpcygpLFxyXG4gICAgICB0YWtlOiBqZXN0LmZuKCkubW9ja1JldHVyblRoaXMoKSxcclxuICAgICAgZ2V0T25lOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUobnVsbCksXHJcbiAgICAgIGdldE1hbnk6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSksXHJcbiAgICAgIGdldE1hbnlBbmRDb3VudDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKFtbXSwgMF0pLFxyXG4gICAgfSkpLFxyXG4gIH0pO1xyXG5cclxuICBjb25zdCBtb2NrRGF0YVNvdXJjZSA9IHtcclxuICAgIGNyZWF0ZVF1ZXJ5UnVubmVyOiBqZXN0LmZuKCgpID0+ICh7XHJcbiAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgc3RhcnRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICBjb21taXRUcmFuc2FjdGlvbjogamVzdC5mbigpLFxyXG4gICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgIHJlbGVhc2U6IGplc3QuZm4oKSxcclxuICAgICAgbWFuYWdlcjoge1xyXG4gICAgICAgIGNyZWF0ZTogamVzdC5mbigpLFxyXG4gICAgICAgIHNhdmU6IGplc3QuZm4oKSxcclxuICAgICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICAgIH0sXHJcbiAgICB9KSksXHJcbiAgICBnZXRSZXBvc2l0b3J5OiBqZXN0LmZuKCgpID0+IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCkpLFxyXG4gICAgbWFuYWdlcjoge1xyXG4gICAgICBmaW5kT25lOiBqZXN0LmZuKCksXHJcbiAgICB9LFxyXG4gIH07XHJcblxyXG4gIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xyXG4gICAgdGVzdGluZ01vZHVsZSA9IGF3YWl0IFRlc3QuY3JlYXRlVGVzdGluZ01vZHVsZSh7XHJcbiAgICAgIHByb3ZpZGVyczogW1xyXG4gICAgICAgIENvcnJlc3BvbmRlbmNlU2VydmljZSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZXZpc2lvbiksXHJcbiAgICAgICAgICB1c2VWYWx1ZTogY3JlYXRlTW9ja1JlcG9zaXRvcnkoKSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VTdGF0dXMpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VSZWZlcmVuY2UpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUYWcpLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IGNyZWF0ZU1vY2tSZXBvc2l0b3J5KCksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBnZXRSZXBvc2l0b3J5VG9rZW4oT3JnYW5pemF0aW9uKSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmVjaXBpZW50KSxcclxuICAgICAgICAgIHVzZVZhbHVlOiBjcmVhdGVNb2NrUmVwb3NpdG9yeSgpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogRG9jdW1lbnROdW1iZXJpbmdTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHtcclxuICAgICAgICAgICAgZ2VuZXJhdGVOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHVwZGF0ZU51bWJlckZvckRyYWZ0OiBqZXN0LmZuKCksXHJcbiAgICAgICAgICAgIHByZXZpZXdOZXh0TnVtYmVyOiBqZXN0LmZuKCksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogSnNvblNjaGVtYVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyB2YWxpZGF0ZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBXb3JrZmxvd0VuZ2luZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjcmVhdGVJbnN0YW5jZTogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBVc2VyU2VydmljZSxcclxuICAgICAgICAgIHVzZVZhbHVlOiB7XHJcbiAgICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICAgICAgZ2V0VXNlclBlcm1pc3Npb25zOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoW10pLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IERhdGFTb3VyY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogbW9ja0RhdGFTb3VyY2UsXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBTZWFyY2hTZXJ2aWNlLFxyXG4gICAgICAgICAgdXNlVmFsdWU6IHsgaW5kZXhEb2N1bWVudDogamVzdC5mbigpIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm92aWRlOiBGaWxlU3RvcmFnZVNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBjb21taXQ6IGplc3QuZm4oKS5tb2NrUmVzb2x2ZWRWYWx1ZShbXSkgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IFV1aWRSZXNvbHZlclNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZToge1xyXG4gICAgICAgICAgICByZXNvbHZlUHJvamVjdElkOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUoMSksXHJcbiAgICAgICAgICAgIHJlc29sdmVPcmdhbml6YXRpb25JZDogamVzdC5mbigpLm1vY2tSZXNvbHZlZFZhbHVlKDEpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHByb3ZpZGU6IE5vdGlmaWNhdGlvblNlcnZpY2UsXHJcbiAgICAgICAgICB1c2VWYWx1ZTogeyBzZW5kOiBqZXN0LmZuKCkubW9ja1Jlc29sdmVkVmFsdWUodW5kZWZpbmVkKSB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgIF0sXHJcbiAgICB9KS5jb21waWxlKCk7XHJcblxyXG4gICAgc2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PENvcnJlc3BvbmRlbmNlU2VydmljZT4oQ29ycmVzcG9uZGVuY2VTZXJ2aWNlKTtcclxuICAgIG51bWJlcmluZ1NlcnZpY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEb2N1bWVudE51bWJlcmluZ1NlcnZpY2U+KFxyXG4gICAgICBEb2N1bWVudE51bWJlcmluZ1NlcnZpY2VcclxuICAgICk7XHJcbiAgICBjb3JyZXNwb25kZW5jZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlPj4oXHJcbiAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZSlcclxuICAgICk7XHJcbiAgICByZXZpc2lvblJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlUmV2aXNpb24+PihcclxuICAgICAgZ2V0UmVwb3NpdG9yeVRva2VuKENvcnJlc3BvbmRlbmNlUmV2aXNpb24pXHJcbiAgICApO1xyXG4gICAgX2RhdGFTb3VyY2UgPSB0ZXN0aW5nTW9kdWxlLmdldDxEYXRhU291cmNlPihEYXRhU291cmNlKTtcclxuICB9KTtcclxuXHJcbiAgaXQoJ3Nob3VsZCBiZSBkZWZpbmVkJywgKCkgPT4ge1xyXG4gICAgZXhwZWN0KHNlcnZpY2UpLnRvQmVEZWZpbmVkKCk7XHJcbiAgfSk7XHJcblxyXG4gIGRlc2NyaWJlKCd1cGRhdGUnLCAoKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIE5PVCByZWdlbmVyYXRlIG51bWJlciBpZiBjcml0aWNhbCBmaWVsZHMgdW5jaGFuZ2VkJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaXQoJ3Nob3VsZCByZWdlbmVyYXRlIG51bWJlciBpZiBQcm9qZWN0IElEIGNoYW5nZXMnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vY2tVc2VyID0geyBpZDogMSwgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiAxMCB9IGFzIHVua25vd24gYXMgVXNlcjtcclxuICAgICAgY29uc3QgbW9ja1JldmlzaW9uID0ge1xyXG4gICAgICAgIGlkOiAxMDAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VJZDogMSxcclxuICAgICAgICBpc0N1cnJlbnQ6IHRydWUsXHJcbiAgICAgICAgc3RhdHVzSWQ6IDUsXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24ocmV2aXNpb25SZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tSZXZpc2lvbiBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlUmV2aXNpb24pO1xyXG5cclxuICAgICAgY29uc3QgbW9ja0NvcnIgPSB7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgcHJvamVjdElkOiAxLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlVHlwZUlkOiAyLFxyXG4gICAgICAgIGRpc2NpcGxpbmVJZDogMyxcclxuICAgICAgICBvcmlnaW5hdG9ySWQ6IDEwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlTnVtYmVyOiAnT0xELU5VTScsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgcmVjaXBpZW50VHlwZTogJ1RPJywgcmVjaXBpZW50T3JnYW5pemF0aW9uSWQ6IDk5IH1dLFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKGNvcnJlc3BvbmRlbmNlUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrQ29yciBhcyB1bmtub3duIGFzIENvcnJlc3BvbmRlbmNlKTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUR0bzogVXBkYXRlQ29ycmVzcG9uZGVuY2VEdG8gPSB7XHJcbiAgICAgICAgcHJvamVjdElkOiAyLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuICAgICAgKHV1aWRSZXNvbHZlci5yZXNvbHZlUHJvamVjdElkIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoMik7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGl0KCdzaG91bGQgcmVnZW5lcmF0ZSBudW1iZXIgaWYgRG9jdW1lbnQgVHlwZSBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHsgaWQ6IDEsIHByaW1hcnlPcmdhbml6YXRpb25JZDogMTAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcbiAgICAgIGNvbnN0IG1vY2tSZXZpc2lvbiA9IHtcclxuICAgICAgICBpZDogMTAwLFxyXG4gICAgICAgIGNvcnJlc3BvbmRlbmNlSWQ6IDEsXHJcbiAgICAgICAgaXNDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIHN0YXR1c0lkOiA1LFxyXG4gICAgICB9O1xyXG4gICAgICBqZXN0XHJcbiAgICAgICAgLnNweU9uKHJldmlzaW9uUmVwbywgJ2ZpbmRPbmUnKVxyXG4gICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUmV2aXNpb24gYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZVJldmlzaW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IG1vY2tDb3JyID0ge1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHByb2plY3RJZDogMSxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZVR5cGVJZDogMixcclxuICAgICAgICBkaXNjaXBsaW5lSWQ6IDMsXHJcbiAgICAgICAgb3JpZ2luYXRvcklkOiAxMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZU51bWJlcjogJ09MRC1OVU0nLFxyXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IHJlY2lwaWVudFR5cGU6ICdUTycsIHJlY2lwaWVudE9yZ2FuaXphdGlvbklkOiA5OSB9XSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihjb3JyZXNwb25kZW5jZVJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja0NvcnIgYXMgdW5rbm93biBhcyBDb3JyZXNwb25kZW5jZSk7XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVEdG86IFVwZGF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHR5cGVJZDogOTk5LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgY29uc3QgdHlwZVJlcG8gPSB0ZXN0aW5nTW9kdWxlLmdldDxSZXBvc2l0b3J5PENvcnJlc3BvbmRlbmNlVHlwZT4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVR5cGUpXHJcbiAgICAgICk7XHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiA5OTksXHJcbiAgICAgICAgdHlwZUNvZGU6ICdORVctVFlQRScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgYXdhaXQgc2VydmljZS51cGRhdGUoMSwgdXBkYXRlRHRvLCBtb2NrVXNlcik7XHJcblxyXG4gICAgICBleHBlY3QoXHJcbiAgICAgICAgbnVtYmVyaW5nU2VydmljZS51cGRhdGVOdW1iZXJGb3JEcmFmdCBhcyBqZXN0Lk1vY2tcclxuICAgICAgKS50b0hhdmVCZWVuQ2FsbGVkKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpdCgnc2hvdWxkIHJlZ2VuZXJhdGUgbnVtYmVyIGlmIFJlY2lwaWVudCBPcmdhbml6YXRpb24gY2hhbmdlcycsIGFzeW5jICgpID0+IHtcclxuICAgICAgY29uc3QgbW9ja1VzZXIgPSB7IGlkOiAxLCBwcmltYXJ5T3JnYW5pemF0aW9uSWQ6IDEwIH0gYXMgdW5rbm93biBhcyBVc2VyO1xyXG4gICAgICBjb25zdCBtb2NrUmV2aXNpb24gPSB7XHJcbiAgICAgICAgaWQ6IDEwMCxcclxuICAgICAgICBjb3JyZXNwb25kZW5jZUlkOiAxLFxyXG4gICAgICAgIGlzQ3VycmVudDogdHJ1ZSxcclxuICAgICAgICBzdGF0dXNJZDogNSxcclxuICAgICAgfTtcclxuICAgICAgamVzdFxyXG4gICAgICAgIC5zcHlPbihyZXZpc2lvblJlcG8sICdmaW5kT25lJylcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWUobW9ja1JldmlzaW9uIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2VSZXZpc2lvbik7XHJcblxyXG4gICAgICBjb25zdCBtb2NrQ29yciA9IHtcclxuICAgICAgICBpZDogMSxcclxuICAgICAgICBwcm9qZWN0SWQ6IDEsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VUeXBlSWQ6IDIsXHJcbiAgICAgICAgZGlzY2lwbGluZUlkOiAzLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogMTAsXHJcbiAgICAgICAgY29ycmVzcG9uZGVuY2VOdW1iZXI6ICdPTEQtTlVNJyxcclxuICAgICAgICByZWNpcGllbnRzOiBbeyByZWNpcGllbnRUeXBlOiAnVE8nLCByZWNpcGllbnRPcmdhbml6YXRpb25JZDogOTkgfV0sXHJcbiAgICAgIH07XHJcbiAgICAgIGplc3RcclxuICAgICAgICAuc3B5T24oY29ycmVzcG9uZGVuY2VSZXBvLCAnZmluZE9uZScpXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKG1vY2tDb3JyIGFzIHVua25vd24gYXMgQ29ycmVzcG9uZGVuY2UpO1xyXG5cclxuICAgICAgLy8gQWNjZXNzIERhdGFTb3VyY2UgbWFuYWdlciBmb3IgbW9ja2luZ1xyXG4gICAgICBtb2NrRGF0YVNvdXJjZS5tYW5hZ2VyLmZpbmRPbmUubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiA4OCxcclxuICAgICAgICBvcmdhbml6YXRpb25Db2RlOiAnTkVXLU9SRycsXHJcbiAgICAgIH0gYXMgdW5rbm93biBhcyBPcmdhbml6YXRpb24pO1xyXG5cclxuICAgICAgY29uc3QgdXBkYXRlRHRvOiBVcGRhdGVDb3JyZXNwb25kZW5jZUR0byA9IHtcclxuICAgICAgICByZWNpcGllbnRzOiBbeyB0eXBlOiAnVE8nLCBvcmdhbml6YXRpb25JZDogODggfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLnVwZGF0ZSgxLCB1cGRhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChcclxuICAgICAgICBudW1iZXJpbmdTZXJ2aWNlLnVwZGF0ZU51bWJlckZvckRyYWZ0IGFzIGplc3QuTW9ja1xyXG4gICAgICApLnRvSGF2ZUJlZW5DYWxsZWQoKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG5cclxuICBkZXNjcmliZSgnY3JlYXRlJywgKCkgPT4ge1xyXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyBzeXN0ZW0ubWFuYWdlX2FsbCB1c2VyIHdpdGhvdXQgcHJpbWFyeU9yZ2FuaXphdGlvbklkIHdoZW4gb3JpZ2luYXRvcklkIGlzIHByb3ZpZGVkJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBtb2NrVXNlciA9IHtcclxuICAgICAgICB1c2VyX2lkOiAxLFxyXG4gICAgICAgIHByaW1hcnlPcmdhbml6YXRpb25JZDogbnVsbCxcclxuICAgICAgfSBhcyB1bmtub3duIGFzIFVzZXI7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVEdG86IENyZWF0ZUNvcnJlc3BvbmRlbmNlRHRvID0ge1xyXG4gICAgICAgIHByb2plY3RJZDogJ3Byb2plY3QtdXVpZCcsXHJcbiAgICAgICAgdHlwZUlkOiAxLFxyXG4gICAgICAgIHN1YmplY3Q6ICdUZXN0IFN1YmplY3QnLFxyXG4gICAgICAgIG9yaWdpbmF0b3JJZDogJ29yaWdpbmF0b3ItdXVpZCcsXHJcbiAgICAgICAgcmVjaXBpZW50czogW3sgb3JnYW5pemF0aW9uSWQ6ICdyZWNpcGllbnQtdXVpZCcsIHR5cGU6ICdUTycgfV0sXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCB1c2VyU2VydmljZSA9IHRlc3RpbmdNb2R1bGUuZ2V0PFVzZXJTZXJ2aWNlPihVc2VyU2VydmljZSk7XHJcbiAgICAgIGNvbnN0IHR5cGVSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVR5cGU+PihcclxuICAgICAgICBnZXRSZXBvc2l0b3J5VG9rZW4oQ29ycmVzcG9uZGVuY2VUeXBlKVxyXG4gICAgICApO1xyXG4gICAgICBjb25zdCBzdGF0dXNSZXBvID0gdGVzdGluZ01vZHVsZS5nZXQ8UmVwb3NpdG9yeTxDb3JyZXNwb25kZW5jZVN0YXR1cz4+KFxyXG4gICAgICAgIGdldFJlcG9zaXRvcnlUb2tlbihDb3JyZXNwb25kZW5jZVN0YXR1cylcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgdXVpZFJlc29sdmVyID1cclxuICAgICAgICB0ZXN0aW5nTW9kdWxlLmdldDxVdWlkUmVzb2x2ZXJTZXJ2aWNlPihVdWlkUmVzb2x2ZXJTZXJ2aWNlKTtcclxuXHJcbiAgICAgICh1c2VyU2VydmljZS5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIHVzZXJfaWQ6IDEsXHJcbiAgICAgICAgcHJpbWFyeU9yZ2FuaXphdGlvbklkOiBudWxsLFxyXG4gICAgICB9KTtcclxuICAgICAgKHVzZXJTZXJ2aWNlLmdldFVzZXJQZXJtaXNzaW9ucyBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKFtcclxuICAgICAgICAnc3lzdGVtLm1hbmFnZV9hbGwnLFxyXG4gICAgICBdKTtcclxuXHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZVByb2plY3RJZCBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKDEwMCk7XHJcbiAgICAgICh1dWlkUmVzb2x2ZXIucmVzb2x2ZU9yZ2FuaXphdGlvbklkIGFzIGplc3QuTW9jaykubW9ja0ltcGxlbWVudGF0aW9uKFxyXG4gICAgICAgICh2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICBpZiAodmFsdWUgPT09ICdvcmlnaW5hdG9yLXV1aWQnKSByZXR1cm4gMTA7XHJcbiAgICAgICAgICBpZiAodmFsdWUgPT09ICdyZWNpcGllbnQtdXVpZCcpIHJldHVybiAyMDtcclxuICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuXHJcbiAgICAgICh0eXBlUmVwby5maW5kT25lIGFzIGplc3QuTW9jaykubW9ja1Jlc29sdmVkVmFsdWUoe1xyXG4gICAgICAgIGlkOiAxLFxyXG4gICAgICAgIHR5cGVDb2RlOiAnTFRSJyxcclxuICAgICAgfSk7XHJcbiAgICAgIChzdGF0dXNSZXBvLmZpbmRPbmUgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgaWQ6IDEsXHJcbiAgICAgICAgc3RhdHVzQ29kZTogJ0RSQUZUJyxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAobnVtYmVyaW5nU2VydmljZS5nZW5lcmF0ZU5leHROdW1iZXIgYXMgamVzdC5Nb2NrKS5tb2NrUmVzb2x2ZWRWYWx1ZSh7XHJcbiAgICAgICAgbnVtYmVyOiAnRE9DLTAwMScsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgbW9ja0RhdGFTb3VyY2UubWFuYWdlci5maW5kT25lXHJcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7IGlkOiAxMCwgb3JnYW5pemF0aW9uQ29kZTogJ09SRycgfSlcclxuICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDIwLCBvcmdhbml6YXRpb25Db2RlOiAnUkVDJyB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHF1ZXJ5UnVubmVyID0ge1xyXG4gICAgICAgIGNvbm5lY3Q6IGplc3QuZm4oKSxcclxuICAgICAgICBzdGFydFRyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgY29tbWl0VHJhbnNhY3Rpb246IGplc3QuZm4oKSxcclxuICAgICAgICByb2xsYmFja1RyYW5zYWN0aW9uOiBqZXN0LmZuKCksXHJcbiAgICAgICAgcmVsZWFzZTogamVzdC5mbigpLFxyXG4gICAgICAgIG1hbmFnZXI6IHtcclxuICAgICAgICAgIGNyZWF0ZTogamVzdC5mbihcclxuICAgICAgICAgICAgKF9lbnRpdHk6IHVua25vd24sIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBwYXlsb2FkXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgc2F2ZTogamVzdFxyXG4gICAgICAgICAgICAuZm4oKVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKHsgaWQ6IDk5OSwgcHVibGljSWQ6ICdjb3JyLXV1aWQnIH0pXHJcbiAgICAgICAgICAgIC5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2UoeyBpZDogMTAwMCB9KVxyXG4gICAgICAgICAgICAubW9ja1Jlc29sdmVkVmFsdWVPbmNlKFtdKSxcclxuICAgICAgICAgIGZpbmRPbmU6IGplc3QuZm4oKSxcclxuICAgICAgICB9LFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgKG1vY2tEYXRhU291cmNlLmNyZWF0ZVF1ZXJ5UnVubmVyIGFzIGplc3QuTW9jaykubW9ja1JldHVyblZhbHVlKFxyXG4gICAgICAgIHF1ZXJ5UnVubmVyXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBhd2FpdCBzZXJ2aWNlLmNyZWF0ZShjcmVhdGVEdG8sIG1vY2tVc2VyKTtcclxuXHJcbiAgICAgIGV4cGVjdChxdWVyeVJ1bm5lci5tYW5hZ2VyLmNyZWF0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXHJcbiAgICAgICAgQ29ycmVzcG9uZGVuY2UsXHJcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyBvcmlnaW5hdG9ySWQ6IDEwIH0pXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuICB9KTtcclxufSk7XHJcbiJdLCJ2ZXJzaW9uIjozfQ== \ No newline at end of file diff --git a/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03.map b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03.map new file mode 100644 index 0000000..9dc5eda --- /dev/null +++ b/backend/src/.jest-cache/jest-transform-cache-60cab15b743c6776f41d29bcac696b99-12533232bd0f05f65688e7a7764bf3fb/ef/correspondenceservicespec_efb009e94d43e8a69ddadbd2e8e37b03.map @@ -0,0 +1 @@ +{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts","mappings":"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","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\r\nimport { getRepositoryToken } from '@nestjs/typeorm';\r\nimport { DataSource, Repository } from 'typeorm';\r\nimport { CorrespondenceService } from './correspondence.service';\r\nimport { Correspondence } from './entities/correspondence.entity';\r\nimport { CorrespondenceRevision } from './entities/correspondence-revision.entity';\r\nimport { CorrespondenceType } from './entities/correspondence-type.entity';\r\nimport { CorrespondenceStatus } from './entities/correspondence-status.entity';\r\nimport { CorrespondenceReference } from './entities/correspondence-reference.entity';\r\nimport { CorrespondenceTag } from './entities/correspondence-tag.entity';\r\nimport { Organization } from '../organization/entities/organization.entity';\r\nimport { CorrespondenceRecipient } from './entities/correspondence-recipient.entity';\r\nimport { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';\r\nimport { JsonSchemaService } from '../json-schema/json-schema.service';\r\nimport { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';\r\nimport { UserService } from '../user/user.service';\r\nimport { SearchService } from '../search/search.service';\r\nimport { FileStorageService } from '../../common/file-storage/file-storage.service';\r\nimport { UuidResolverService } from '../../common/services/uuid-resolver.service';\r\nimport { NotificationService } from '../notification/notification.service';\r\nimport { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';\r\nimport { CreateCorrespondenceDto } from './dto/create-correspondence.dto';\r\nimport { User } from '../user/entities/user.entity';\r\n\r\ndescribe('CorrespondenceService', () => {\r\n let service: CorrespondenceService;\r\n let numberingService: DocumentNumberingService;\r\n let correspondenceRepo: Repository;\r\n let revisionRepo: Repository;\r\n let testingModule: TestingModule;\r\n let _dataSource: DataSource;\r\n\r\n const createMockRepository = () => ({\r\n find: jest.fn(),\r\n findOne: jest.fn(),\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n update: jest.fn(),\r\n delete: jest.fn(),\r\n softDelete: jest.fn(),\r\n createQueryBuilder: jest.fn(() => ({\r\n leftJoinAndSelect: jest.fn().mockReturnThis(),\r\n where: jest.fn().mockReturnThis(),\r\n andWhere: jest.fn().mockReturnThis(),\r\n orderBy: jest.fn().mockReturnThis(),\r\n skip: jest.fn().mockReturnThis(),\r\n take: jest.fn().mockReturnThis(),\r\n getOne: jest.fn().mockResolvedValue(null),\r\n getMany: jest.fn().mockResolvedValue([]),\r\n getManyAndCount: jest.fn().mockResolvedValue([[], 0]),\r\n })),\r\n });\r\n\r\n const mockDataSource = {\r\n createQueryRunner: jest.fn(() => ({\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(),\r\n save: jest.fn(),\r\n findOne: jest.fn(),\r\n },\r\n })),\r\n getRepository: jest.fn(() => createMockRepository()),\r\n manager: {\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n beforeEach(async () => {\r\n testingModule = await Test.createTestingModule({\r\n providers: [\r\n CorrespondenceService,\r\n {\r\n provide: getRepositoryToken(Correspondence),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRevision),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceType),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceStatus),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceReference),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceTag),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(Organization),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: getRepositoryToken(CorrespondenceRecipient),\r\n useValue: createMockRepository(),\r\n },\r\n {\r\n provide: DocumentNumberingService,\r\n useValue: {\r\n generateNextNumber: jest.fn(),\r\n updateNumberForDraft: jest.fn(),\r\n previewNextNumber: jest.fn(),\r\n },\r\n },\r\n {\r\n provide: JsonSchemaService,\r\n useValue: { validate: jest.fn() },\r\n },\r\n {\r\n provide: WorkflowEngineService,\r\n useValue: { createInstance: jest.fn() },\r\n },\r\n {\r\n provide: UserService,\r\n useValue: {\r\n findOne: jest.fn(),\r\n getUserPermissions: jest.fn().mockResolvedValue([]),\r\n },\r\n },\r\n {\r\n provide: DataSource,\r\n useValue: mockDataSource,\r\n },\r\n {\r\n provide: SearchService,\r\n useValue: { indexDocument: jest.fn() },\r\n },\r\n {\r\n provide: FileStorageService,\r\n useValue: { commit: jest.fn().mockResolvedValue([]) },\r\n },\r\n {\r\n provide: UuidResolverService,\r\n useValue: {\r\n resolveProjectId: jest.fn().mockResolvedValue(1),\r\n resolveOrganizationId: jest.fn().mockResolvedValue(1),\r\n },\r\n },\r\n {\r\n provide: NotificationService,\r\n useValue: { send: jest.fn().mockResolvedValue(undefined) },\r\n },\r\n ],\r\n }).compile();\r\n\r\n service = testingModule.get(CorrespondenceService);\r\n numberingService = testingModule.get(\r\n DocumentNumberingService\r\n );\r\n correspondenceRepo = testingModule.get>(\r\n getRepositoryToken(Correspondence)\r\n );\r\n revisionRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceRevision)\r\n );\r\n _dataSource = testingModule.get(DataSource);\r\n });\r\n\r\n it('should be defined', () => {\r\n expect(service).toBeDefined();\r\n });\r\n\r\n describe('update', () => {\r\n it('should NOT regenerate number if critical fields unchanged', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 1,\r\n disciplineId: 3,\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).not.toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Project ID changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n projectId: 2,\r\n };\r\n\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(2);\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Document Type changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n typeId: 999,\r\n };\r\n\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 999,\r\n typeCode: 'NEW-TYPE',\r\n });\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n\r\n it('should regenerate number if Recipient Organization changes', async () => {\r\n const mockUser = { id: 1, primaryOrganizationId: 10 } as unknown as User;\r\n const mockRevision = {\r\n id: 100,\r\n correspondenceId: 1,\r\n isCurrent: true,\r\n statusId: 5,\r\n };\r\n jest\r\n .spyOn(revisionRepo, 'findOne')\r\n .mockResolvedValue(mockRevision as unknown as CorrespondenceRevision);\r\n\r\n const mockCorr = {\r\n id: 1,\r\n projectId: 1,\r\n correspondenceTypeId: 2,\r\n disciplineId: 3,\r\n originatorId: 10,\r\n correspondenceNumber: 'OLD-NUM',\r\n recipients: [{ recipientType: 'TO', recipientOrganizationId: 99 }],\r\n };\r\n jest\r\n .spyOn(correspondenceRepo, 'findOne')\r\n .mockResolvedValue(mockCorr as unknown as Correspondence);\r\n\r\n // Access DataSource manager for mocking\r\n mockDataSource.manager.findOne.mockResolvedValue({\r\n id: 88,\r\n organizationCode: 'NEW-ORG',\r\n } as unknown as Organization);\r\n\r\n const updateDto: UpdateCorrespondenceDto = {\r\n recipients: [{ type: 'TO', organizationId: 88 }],\r\n };\r\n\r\n await service.update(1, updateDto, mockUser);\r\n\r\n expect(\r\n numberingService.updateNumberForDraft as jest.Mock\r\n ).toHaveBeenCalled();\r\n });\r\n });\r\n\r\n describe('create', () => {\r\n it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {\r\n const mockUser = {\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n } as unknown as User;\r\n\r\n const createDto: CreateCorrespondenceDto = {\r\n projectId: 'project-uuid',\r\n typeId: 1,\r\n subject: 'Test Subject',\r\n originatorId: 'originator-uuid',\r\n recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],\r\n };\r\n\r\n const userService = testingModule.get(UserService);\r\n const typeRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceType)\r\n );\r\n const statusRepo = testingModule.get>(\r\n getRepositoryToken(CorrespondenceStatus)\r\n );\r\n const uuidResolver =\r\n testingModule.get(UuidResolverService);\r\n\r\n (userService.findOne as jest.Mock).mockResolvedValue({\r\n user_id: 1,\r\n primaryOrganizationId: null,\r\n });\r\n (userService.getUserPermissions as jest.Mock).mockResolvedValue([\r\n 'system.manage_all',\r\n ]);\r\n\r\n (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);\r\n (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(\r\n (value: number | string) => {\r\n if (value === 'originator-uuid') return 10;\r\n if (value === 'recipient-uuid') return 20;\r\n return 0;\r\n }\r\n );\r\n\r\n (typeRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n typeCode: 'LTR',\r\n });\r\n (statusRepo.findOne as jest.Mock).mockResolvedValue({\r\n id: 1,\r\n statusCode: 'DRAFT',\r\n });\r\n\r\n (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({\r\n number: 'DOC-001',\r\n });\r\n\r\n mockDataSource.manager.findOne\r\n .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })\r\n .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });\r\n\r\n const queryRunner = {\r\n connect: jest.fn(),\r\n startTransaction: jest.fn(),\r\n commitTransaction: jest.fn(),\r\n rollbackTransaction: jest.fn(),\r\n release: jest.fn(),\r\n manager: {\r\n create: jest.fn(\r\n (_entity: unknown, payload: Record) => payload\r\n ),\r\n save: jest\r\n .fn()\r\n .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })\r\n .mockResolvedValueOnce({ id: 1000 })\r\n .mockResolvedValueOnce([]),\r\n findOne: jest.fn(),\r\n },\r\n };\r\n\r\n (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(\r\n queryRunner\r\n );\r\n\r\n await service.create(createDto, mockUser);\r\n\r\n expect(queryRunner.manager.create).toHaveBeenCalledWith(\r\n Correspondence,\r\n expect.objectContaining({ originatorId: 10 })\r\n );\r\n });\r\n });\r\n});\r\n"],"version":3} \ No newline at end of file diff --git a/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 b/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 index ce07ee0..7284c83 100644 --- a/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 +++ b/backend/src/.jest-cache/perf-cache-60cab15b743c6776f41d29bcac696b99-da39a3ee5e6b4b0d3255bfef95601890 @@ -1 +1 @@ -{"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\due-date-reminder.service.spec.ts":[1,1723],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts":[1,11114],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.service.spec.ts":[1,1538],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\document-numbering.service.spec.ts":[1,2037],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\casl\\ability.factory.spec.ts":[1,1294],"E:\\np-dms\\lcbp3\\backend\\src\\common\\services\\uuid-resolver.service.spec.ts":[1,5491],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\workflow-engine.service.spec.ts":[1,5639],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\dsl\\parser.service.spec.ts":[1,5818],"E:\\np-dms\\lcbp3\\backend\\src\\common\\pipes\\parse-uuid.pipe.spec.ts":[1,355],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\user\\user.service.spec.ts":[1,1270],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.service.spec.ts":[1,1187],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.controller.spec.ts":[1,12100],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.service.spec.ts":[1,1296],"E:\\np-dms\\lcbp3\\backend\\src\\common\\entities\\uuid-base.entity.spec.ts":[1,430],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.service.spec.ts":[1,1109],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.controller.spec.ts":[1,2191],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\services\\manual-override.service.spec.ts":[1,5256],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.controller.spec.ts":[1,1827],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.controller.spec.ts":[1,6380],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.controller.spec.ts":[1,1482],"E:\\np-dms\\lcbp3\\backend\\src\\app.controller.spec.ts":[1,587],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\json-schema\\json-schema.controller.spec.ts":[1,5062]} \ No newline at end of file +{"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\due-date-reminder.service.spec.ts":[1,1723],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts":[1,7901],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.service.spec.ts":[1,1538],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\document-numbering.service.spec.ts":[1,2037],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\casl\\ability.factory.spec.ts":[1,1294],"E:\\np-dms\\lcbp3\\backend\\src\\common\\services\\uuid-resolver.service.spec.ts":[1,5491],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\workflow-engine.service.spec.ts":[1,5639],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\dsl\\parser.service.spec.ts":[1,5818],"E:\\np-dms\\lcbp3\\backend\\src\\common\\pipes\\parse-uuid.pipe.spec.ts":[1,355],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\user\\user.service.spec.ts":[1,1270],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.service.spec.ts":[1,1187],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.controller.spec.ts":[1,8495],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.service.spec.ts":[1,1296],"E:\\np-dms\\lcbp3\\backend\\src\\common\\entities\\uuid-base.entity.spec.ts":[1,430],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.service.spec.ts":[1,1109],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.controller.spec.ts":[1,2191],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\services\\manual-override.service.spec.ts":[1,5256],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.controller.spec.ts":[1,1827],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.controller.spec.ts":[1,6380],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.controller.spec.ts":[1,1482],"E:\\np-dms\\lcbp3\\backend\\src\\app.controller.spec.ts":[1,587],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\json-schema\\json-schema.controller.spec.ts":[1,5062]} \ No newline at end of file diff --git a/backend/src/modules/circulation/circulation.service.ts b/backend/src/modules/circulation/circulation.service.ts index 7c67035..c935045 100644 --- a/backend/src/modules/circulation/circulation.service.ts +++ b/backend/src/modules/circulation/circulation.service.ts @@ -15,9 +15,15 @@ import { UpdateCirculationRoutingDto } from './dto/update-circulation-routing.dt import { SearchCirculationDto } from './dto/search-circulation.dto'; import { DocumentNumberingService } from '../document-numbering/services/document-numbering.service'; import { UuidResolverService } from '../../common/services/uuid-resolver.service'; +import { UserService } from '../user/user.service'; @Injectable() export class CirculationService { + private async hasSystemManageAllPermission(userId: number): Promise { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + constructor( @InjectRepository(Circulation) private circulationRepo: Repository, @@ -25,11 +31,36 @@ export class CirculationService { private routingRepo: Repository, private numberingService: DocumentNumberingService, private dataSource: DataSource, - private uuidResolver: UuidResolverService + private uuidResolver: UuidResolverService, + private userService: UserService ) {} async create(createDto: CreateCirculationDto, user: User) { - if (!user.primaryOrganizationId) { + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + + const resolvedOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + + if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { + const canManageAll = await this.hasSystemManageAllPermission( + user.user_id + ); + if (!canManageAll) { + throw new ForbiddenException( + 'You do not have permission to create documents on behalf of other organizations.' + ); + } + userOrgId = resolvedOriginatorId; + } + + if (!userOrgId) { throw new BadRequestException('User must belong to an organization'); } @@ -52,7 +83,7 @@ export class CirculationService { // Generate No. using DocumentNumberingService (Type 900 - Circulation) const result = await this.numberingService.generateNextNumber({ projectId: resolvedProjectId, - originatorOrganizationId: user.primaryOrganizationId, + originatorOrganizationId: userOrgId, typeId: 900, // Fixed Type ID for Circulation year: new Date().getFullYear(), customTokens: { @@ -62,7 +93,7 @@ export class CirculationService { }); const circulation = queryRunner.manager.create(Circulation, { - organizationId: user.primaryOrganizationId, + organizationId: userOrgId, correspondenceId: resolvedCorrId, circulationNo: result.number, subject: createDto.subject, @@ -76,7 +107,7 @@ export class CirculationService { queryRunner.manager.create(CirculationRouting, { circulationId: savedCirculation.id, stepNumber: index + 1, - organizationId: user.primaryOrganizationId, + organizationId: userOrgId, assignedTo: assigneeId, status: 'PENDING', }) diff --git a/backend/src/modules/circulation/dto/create-circulation.dto.ts b/backend/src/modules/circulation/dto/create-circulation.dto.ts index 4bd31ff..18ae8ae 100644 --- a/backend/src/modules/circulation/dto/create-circulation.dto.ts +++ b/backend/src/modules/circulation/dto/create-circulation.dto.ts @@ -13,6 +13,9 @@ export class CreateCirculationDto { @IsOptional() projectId?: number | string; // Project ID or UUID for Numbering + @IsOptional() + originatorId?: number | string; // ระบุองค์กรเจ้าของเอกสาร (ต้องใช้ร่วมกับสิทธิ system.manage_all) + @IsString() @IsNotEmpty() subject!: string; // หัวข้อเรื่อง (Subject) diff --git a/backend/src/modules/correspondence/correspondence.service.spec.ts b/backend/src/modules/correspondence/correspondence.service.spec.ts index 3ee1b0d..2f3d9b7 100644 --- a/backend/src/modules/correspondence/correspondence.service.spec.ts +++ b/backend/src/modules/correspondence/correspondence.service.spec.ts @@ -19,6 +19,7 @@ import { FileStorageService } from '../../common/file-storage/file-storage.servi import { UuidResolverService } from '../../common/services/uuid-resolver.service'; import { NotificationService } from '../notification/notification.service'; import { UpdateCorrespondenceDto } from './dto/update-correspondence.dto'; +import { CreateCorrespondenceDto } from './dto/create-correspondence.dto'; import { User } from '../user/entities/user.entity'; describe('CorrespondenceService', () => { @@ -336,4 +337,95 @@ describe('CorrespondenceService', () => { ).toHaveBeenCalled(); }); }); + + describe('create', () => { + it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => { + const mockUser = { + user_id: 1, + primaryOrganizationId: null, + } as unknown as User; + + const createDto: CreateCorrespondenceDto = { + projectId: 'project-uuid', + typeId: 1, + subject: 'Test Subject', + originatorId: 'originator-uuid', + recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }], + }; + + const userService = testingModule.get(UserService); + const typeRepo = testingModule.get>( + getRepositoryToken(CorrespondenceType) + ); + const statusRepo = testingModule.get>( + getRepositoryToken(CorrespondenceStatus) + ); + const uuidResolver = + testingModule.get(UuidResolverService); + + (userService.findOne as jest.Mock).mockResolvedValue({ + user_id: 1, + primaryOrganizationId: null, + }); + (userService.getUserPermissions as jest.Mock).mockResolvedValue([ + 'system.manage_all', + ]); + + (uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100); + (uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation( + (value: number | string) => { + if (value === 'originator-uuid') return 10; + if (value === 'recipient-uuid') return 20; + return 0; + } + ); + + (typeRepo.findOne as jest.Mock).mockResolvedValue({ + id: 1, + typeCode: 'LTR', + }); + (statusRepo.findOne as jest.Mock).mockResolvedValue({ + id: 1, + statusCode: 'DRAFT', + }); + + (numberingService.generateNextNumber as jest.Mock).mockResolvedValue({ + number: 'DOC-001', + }); + + mockDataSource.manager.findOne + .mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' }) + .mockResolvedValueOnce({ id: 20, organizationCode: 'REC' }); + + const queryRunner = { + connect: jest.fn(), + startTransaction: jest.fn(), + commitTransaction: jest.fn(), + rollbackTransaction: jest.fn(), + release: jest.fn(), + manager: { + create: jest.fn( + (_entity: unknown, payload: Record) => payload + ), + save: jest + .fn() + .mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' }) + .mockResolvedValueOnce({ id: 1000 }) + .mockResolvedValueOnce([]), + findOne: jest.fn(), + }, + }; + + (mockDataSource.createQueryRunner as jest.Mock).mockReturnValue( + queryRunner + ); + + await service.create(createDto, mockUser); + + expect(queryRunner.manager.create).toHaveBeenCalledWith( + Correspondence, + expect.objectContaining({ originatorId: 10 }) + ); + }); + }); }); diff --git a/backend/src/modules/correspondence/correspondence.service.ts b/backend/src/modules/correspondence/correspondence.service.ts index 56f2bdd..7955c25 100644 --- a/backend/src/modules/correspondence/correspondence.service.ts +++ b/backend/src/modules/correspondence/correspondence.service.ts @@ -50,6 +50,11 @@ interface ResolvedRecipient { export class CorrespondenceService { private readonly logger = new Logger(CorrespondenceService.name); + private async hasSystemManageAllPermission(userId: number): Promise { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + constructor( @InjectRepository(Correspondence) private correspondenceRepo: Repository, @@ -92,9 +97,22 @@ export class CorrespondenceService { } if (!userOrgId) { - throw new BadRequestException( - 'User must belong to an organization to create documents' - ); + if (createDto.originatorId) { + const canManageAll = await this.hasSystemManageAllPermission( + user.user_id + ); + if (canManageAll) { + userOrgId = await this.uuidResolver.resolveOrganizationId( + createDto.originatorId + ); + } + } + + if (!userOrgId) { + throw new BadRequestException( + 'User must belong to an organization to create documents' + ); + } } // For impersonation, use the specified originator @@ -187,10 +205,10 @@ export class CorrespondenceService { // Impersonation Logic if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { - const permissions = await this.userService.getUserPermissions( + const canManageAll = await this.hasSystemManageAllPermission( user.user_id ); - if (!permissions.includes('system.manage_all')) { + if (!canManageAll) { throw new ForbiddenException( 'You do not have permission to create documents on behalf of other organizations.' ); diff --git a/backend/src/modules/rfa/dto/create-rfa.dto.ts b/backend/src/modules/rfa/dto/create-rfa.dto.ts index df08ac0..6c6cda1 100644 --- a/backend/src/modules/rfa/dto/create-rfa.dto.ts +++ b/backend/src/modules/rfa/dto/create-rfa.dto.ts @@ -25,6 +25,14 @@ export class CreateRfaDto { @IsNotEmpty() toOrganizationId!: number | string; + @ApiProperty({ + description: + 'Originator Organization ID or UUID (for users with system.manage_all)', + required: false, + }) + @IsOptional() + originatorId?: number | string; + @ApiProperty({ description: 'ID ของประเภท RFA', example: 1 }) @IsInt() @IsNotEmpty() diff --git a/backend/src/modules/rfa/rfa.service.ts b/backend/src/modules/rfa/rfa.service.ts index 329a4b6..d8599cb 100644 --- a/backend/src/modules/rfa/rfa.service.ts +++ b/backend/src/modules/rfa/rfa.service.ts @@ -63,6 +63,11 @@ import { UuidResolverService } from '../../common/services/uuid-resolver.service export class RfaService { private readonly logger = new Logger(RfaService.name); + private async hasSystemManageAllPermission(userId: number): Promise { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + constructor( @InjectRepository(Rfa) private rfaRepo: Repository, @@ -226,12 +231,29 @@ export class RfaService { ); } + const resolvedOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + // Determine User Organization let userOrgId = user.primaryOrganizationId; if (!userOrgId) { const fullUser = await this.userService.findOne(user.user_id); if (fullUser) userOrgId = fullUser.primaryOrganizationId; } + + if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { + const canManageAll = await this.hasSystemManageAllPermission( + user.user_id + ); + if (!canManageAll) { + throw new ForbiddenException( + 'You do not have permission to create documents on behalf of other organizations.' + ); + } + userOrgId = resolvedOriginatorId; + } + if (!userOrgId) { throw new BadRequestException('User must belong to an organization'); } diff --git a/backend/src/modules/transmittal/dto/create-transmittal.dto.ts b/backend/src/modules/transmittal/dto/create-transmittal.dto.ts index 5ff4686..f0e691c 100644 --- a/backend/src/modules/transmittal/dto/create-transmittal.dto.ts +++ b/backend/src/modules/transmittal/dto/create-transmittal.dto.ts @@ -54,6 +54,14 @@ export class CreateTransmittalDto { @IsNotEmpty() recipientOrganizationId!: number | string; + @ApiProperty({ + description: + 'ผู้ส่ง Organization ID หรือ UUID (สำหรับผู้ใช้ที่มีสิทธิ system.manage_all)', + required: false, + }) + @IsOptional() + originatorId?: number | string; + @ApiProperty({ description: 'Correspondence ID หรือ UUID (ADR-019)', required: false, diff --git a/backend/src/modules/transmittal/transmittal.service.ts b/backend/src/modules/transmittal/transmittal.service.ts index f7ada83..e558ba2 100644 --- a/backend/src/modules/transmittal/transmittal.service.ts +++ b/backend/src/modules/transmittal/transmittal.service.ts @@ -4,6 +4,7 @@ import { NotFoundException, InternalServerErrorException, BadRequestException, + ForbiddenException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, DataSource } from 'typeorm'; @@ -22,11 +23,17 @@ import { CorrespondenceType } from '../correspondence/entities/correspondence-ty import { CorrespondenceStatus } from '../correspondence/entities/correspondence-status.entity'; import { UuidResolverService } from '../../common/services/uuid-resolver.service'; import { CorrespondenceRecipient } from '../correspondence/entities/correspondence-recipient.entity'; +import { UserService } from '../user/user.service'; @Injectable() export class TransmittalService { private readonly logger = new Logger(TransmittalService.name); + private async hasSystemManageAllPermission(userId: number): Promise { + const permissions = await this.userService.getUserPermissions(userId); + return permissions.includes('system.manage_all'); + } + constructor( @InjectRepository(Transmittal) private transmittalRepo: Repository, @@ -38,7 +45,8 @@ export class TransmittalService { private statusRepo: Repository, private numberingService: DocumentNumberingService, private dataSource: DataSource, - private uuidResolver: UuidResolverService + private uuidResolver: UuidResolverService, + private userService: UserService ) {} async create( @@ -61,7 +69,31 @@ export class TransmittalService { await queryRunner.connect(); await queryRunner.startTransaction(); - if (!user.primaryOrganizationId) { + let userOrgId = user.primaryOrganizationId; + if (!userOrgId) { + const fullUser = await this.userService.findOne(user.user_id); + if (fullUser) { + userOrgId = fullUser.primaryOrganizationId; + } + } + + const resolvedOriginatorId = createDto.originatorId + ? await this.uuidResolver.resolveOrganizationId(createDto.originatorId) + : undefined; + + if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) { + const canManageAll = await this.hasSystemManageAllPermission( + user.user_id + ); + if (!canManageAll) { + throw new ForbiddenException( + 'You do not have permission to create documents on behalf of other organizations.' + ); + } + userOrgId = resolvedOriginatorId; + } + + if (!userOrgId) { throw new BadRequestException( 'User must belong to an organization to create a transmittal' ); @@ -76,7 +108,7 @@ export class TransmittalService { // 2. Generate Number const docNumber = await this.numberingService.generateNextNumber({ projectId: internalProjectId, - originatorOrganizationId: user.primaryOrganizationId, + originatorOrganizationId: userOrgId, typeId: type.id, year: new Date().getFullYear(), customTokens: { @@ -90,7 +122,7 @@ export class TransmittalService { correspondenceNumber: docNumber.number, correspondenceTypeId: type.id, projectId: internalProjectId, - originatorId: user.primaryOrganizationId, + originatorId: userOrgId, isInternal: false, createdBy: user.user_id, });