@devizovaburza/mdm-sdk 1.2.9 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/v1/index.d.mts +104 -14
- package/dist/v1/index.d.ts +104 -14
- package/dist/v1/index.mjs +495 -338
- package/package.json +7 -6
package/dist/v1/index.mjs
CHANGED
|
@@ -194,6 +194,19 @@ const ID_DOC_STATUS = [
|
|
|
194
194
|
"REVOKED"
|
|
195
195
|
];
|
|
196
196
|
const CUSTOMER_STATUS = ["NEW", "ACTIVE", "CLOSED", "BLOCKED"];
|
|
197
|
+
const BLOCK_REASON = [
|
|
198
|
+
"MISSING_OWNERSHIP_STRUCTURE",
|
|
199
|
+
"REMOVED_FROM_REGISTRY",
|
|
200
|
+
"INSOLVENCY",
|
|
201
|
+
"EXECUTION",
|
|
202
|
+
"INACTIVE_FROM_START",
|
|
203
|
+
"INACTIVE_OVER_2_YEARS",
|
|
204
|
+
"COMPANY_SOLD",
|
|
205
|
+
"UNINTERESTING",
|
|
206
|
+
"OUTDATED_ID_DOCUMENTS",
|
|
207
|
+
"OTHER",
|
|
208
|
+
"BLOCKED_BY_CLIENT"
|
|
209
|
+
];
|
|
197
210
|
const PARTY_TYPE = [
|
|
198
211
|
"INDIVIDUAL",
|
|
199
212
|
"SELF_EMPLOYED",
|
|
@@ -310,6 +323,38 @@ const RISK_BUSINESS_AREA = [
|
|
|
310
323
|
"VIRTUAL_ASSET_SERVICES"
|
|
311
324
|
];
|
|
312
325
|
|
|
326
|
+
function logAuditEvent(context, input) {
|
|
327
|
+
const identity = context.get("identity");
|
|
328
|
+
const sourceIp = context.req.header("CF-Connecting-IP");
|
|
329
|
+
const correlationId = input.correlationId ?? context.get("correlationId");
|
|
330
|
+
if (!correlationId) {
|
|
331
|
+
throw new Error(
|
|
332
|
+
"logAuditEvent: missing correlationId \u2014 auditLog() middleware must be mounted before handlers that call logAuditEvent"
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
context.executionCtx.waitUntil(
|
|
336
|
+
context.env.ACTIVITY_SERVICE.logAuditEvent({
|
|
337
|
+
logType: "event",
|
|
338
|
+
service: "gateway",
|
|
339
|
+
eventType: input.eventType,
|
|
340
|
+
correlationId,
|
|
341
|
+
actorUserId: input.actorUserId ?? identity?.user?.id,
|
|
342
|
+
actorEmail: input.actorEmail ?? identity?.user?.email ?? "not-authorized@system.internal",
|
|
343
|
+
actorOrganizationId: input.actorOrganizationId ?? identity?.user?.organizationId,
|
|
344
|
+
targetType: input.targetType,
|
|
345
|
+
targetId: input.targetId,
|
|
346
|
+
outcome: input.outcome,
|
|
347
|
+
description: input.description,
|
|
348
|
+
severity: input.severity ?? "low",
|
|
349
|
+
details: input.details,
|
|
350
|
+
userAgent: context.req.header("User-Agent"),
|
|
351
|
+
...sourceIp && { sourceIp }
|
|
352
|
+
}).catch((error) => {
|
|
353
|
+
console.error(`Failed to log audit event "${input.eventType}":`, error);
|
|
354
|
+
})
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
313
358
|
z.object({
|
|
314
359
|
message: z.string(),
|
|
315
360
|
data: z.null(),
|
|
@@ -350,7 +395,10 @@ const partySchema$1 = z.object({
|
|
|
350
395
|
id: z.uuid(),
|
|
351
396
|
internalId: z.string().optional(),
|
|
352
397
|
note: z.string().optional(),
|
|
353
|
-
countryCode: z.enum(COUNTRY_CODES).optional()
|
|
398
|
+
countryCode: z.enum(COUNTRY_CODES).optional(),
|
|
399
|
+
customerStatus: z.enum(CUSTOMER_STATUS).optional(),
|
|
400
|
+
blockReason: z.enum(BLOCK_REASON).nullable().optional(),
|
|
401
|
+
blockReasonNote: z.string().trim().min(1).nullable().optional()
|
|
354
402
|
});
|
|
355
403
|
const idDocumentInputSchema$1 = z.object({
|
|
356
404
|
idDocType: z.enum(ID_DOC_TYPE),
|
|
@@ -583,6 +631,21 @@ const createPartyInputSchema = z.object({
|
|
|
583
631
|
recipients: z.array(bankAccountInputSchema),
|
|
584
632
|
products: productsInputSchema$1.optional(),
|
|
585
633
|
traderIds: z.array(z.uuid()).optional()
|
|
634
|
+
}).refine(
|
|
635
|
+
(b) => b.party.customerStatus !== "BLOCKED" || !!b.party.blockReason,
|
|
636
|
+
{
|
|
637
|
+
message: "blockReason is required when customerStatus is BLOCKED",
|
|
638
|
+
path: ["party", "blockReason"]
|
|
639
|
+
}
|
|
640
|
+
).refine(
|
|
641
|
+
(b) => b.party.customerStatus === "BLOCKED" || !b.party.blockReason && !b.party.blockReasonNote,
|
|
642
|
+
{
|
|
643
|
+
message: "blockReason and blockReasonNote must be null when customerStatus is not BLOCKED",
|
|
644
|
+
path: ["party", "blockReason"]
|
|
645
|
+
}
|
|
646
|
+
).refine((b) => b.party.blockReason !== "OTHER" || !!b.party.blockReasonNote, {
|
|
647
|
+
message: "blockReasonNote is required when blockReason is OTHER",
|
|
648
|
+
path: ["party", "blockReasonNote"]
|
|
586
649
|
});
|
|
587
650
|
const partyCreateOutputSchema = z.object({
|
|
588
651
|
customerStatus: z.enum(CUSTOMER_STATUS),
|
|
@@ -627,101 +690,211 @@ const createPartyRoute = createRoute({
|
|
|
627
690
|
...errorResponse("Party", "Creation")
|
|
628
691
|
}
|
|
629
692
|
});
|
|
630
|
-
new OpenAPIHono().openapi(
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
)
|
|
637
|
-
|
|
638
|
-
|
|
693
|
+
new OpenAPIHono().openapi(createPartyRoute, async (context) => {
|
|
694
|
+
const { owners, legalRepresentatives, ...partyInput } = context.req.valid("json");
|
|
695
|
+
const disponentsWithDocs = (partyInput.disponents ?? []).filter(
|
|
696
|
+
(d) => d.partyType === "INDIVIDUAL" && !!d.data.identityDocuments?.length
|
|
697
|
+
);
|
|
698
|
+
const disponentsForBatch = (partyInput.disponents ?? []).filter(
|
|
699
|
+
(d) => !(d.partyType === "INDIVIDUAL" && !!d.data.identityDocuments?.length)
|
|
700
|
+
);
|
|
701
|
+
const { data: partyData, error } = await context.env.MASTER_DATA_MANAGEMENT_SERVICE.createParty({
|
|
702
|
+
...partyInput,
|
|
703
|
+
disponents: disponentsForBatch,
|
|
704
|
+
party: { ...partyInput.party, isRoot: true }
|
|
705
|
+
});
|
|
706
|
+
if (!partyData || error) {
|
|
707
|
+
logAuditEvent(context, {
|
|
708
|
+
eventType: "party.created",
|
|
709
|
+
targetType: "party",
|
|
710
|
+
outcome: "failure",
|
|
711
|
+
severity: "medium",
|
|
712
|
+
description: "Failed to create party",
|
|
713
|
+
details: { partyType: partyInput.party.partyType }
|
|
714
|
+
});
|
|
715
|
+
return context.json(
|
|
716
|
+
{
|
|
717
|
+
message: "Could not create a party"
|
|
718
|
+
},
|
|
719
|
+
500
|
|
639
720
|
);
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
721
|
+
}
|
|
722
|
+
const mdm = context.env.MASTER_DATA_MANAGEMENT_SERVICE;
|
|
723
|
+
const docService = context.env.DOCUMENT_SERVICE;
|
|
724
|
+
if (partyInput.organizationData?.registerUri) {
|
|
725
|
+
await docService.acknowledgeDocument({
|
|
726
|
+
storageUrl: partyInput.organizationData.registerUri,
|
|
727
|
+
entityId: partyData.id
|
|
644
728
|
});
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
message: "Could not create a party"
|
|
649
|
-
},
|
|
650
|
-
500
|
|
651
|
-
);
|
|
652
|
-
}
|
|
653
|
-
const mdm = context.env.MASTER_DATA_MANAGEMENT_SERVICE;
|
|
654
|
-
const docService = context.env.DOCUMENT_SERVICE;
|
|
655
|
-
if (partyInput.organizationData?.registerUri) {
|
|
729
|
+
}
|
|
730
|
+
for (const ba of partyInput.bankAccounts ?? []) {
|
|
731
|
+
if (ba.statementUri) {
|
|
656
732
|
await docService.acknowledgeDocument({
|
|
657
|
-
storageUrl:
|
|
733
|
+
storageUrl: ba.statementUri,
|
|
658
734
|
entityId: partyData.id
|
|
659
735
|
});
|
|
660
736
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
737
|
+
}
|
|
738
|
+
for (const [i, doc] of (partyInput.personalData?.identityDocuments ?? []).entries()) {
|
|
739
|
+
const idDocId = partyData.personalIdDocIds?.[i] ?? partyData.id;
|
|
740
|
+
if (doc.frontImageUri) {
|
|
741
|
+
await docService.acknowledgeDocument({
|
|
742
|
+
storageUrl: doc.frontImageUri,
|
|
743
|
+
entityId: idDocId
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
if (doc.backImageUri) {
|
|
747
|
+
await docService.acknowledgeDocument({
|
|
748
|
+
storageUrl: doc.backImageUri,
|
|
749
|
+
entityId: idDocId
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
for (const disponent of disponentsWithDocs) {
|
|
754
|
+
const { identityDocuments, ...individualData } = disponent.data;
|
|
755
|
+
const { data: disponentParty, error: disponentError } = await mdm.createParty({
|
|
756
|
+
party: {
|
|
757
|
+
partyType: "INDIVIDUAL",
|
|
758
|
+
language: partyInput.party.language,
|
|
759
|
+
customerStatus: "NEW"
|
|
760
|
+
},
|
|
761
|
+
personalData: individualData,
|
|
762
|
+
organizationData: null,
|
|
763
|
+
bankAccounts: null,
|
|
764
|
+
recipients: null,
|
|
765
|
+
disponents: null,
|
|
766
|
+
addresses: [],
|
|
767
|
+
aml: null
|
|
768
|
+
});
|
|
769
|
+
if (!disponentParty || disponentError) {
|
|
770
|
+
return context.json({ message: "Could not create disponent party" }, 500);
|
|
771
|
+
}
|
|
772
|
+
const { error: linkDisponentError } = await mdm.linkPartyToParty({
|
|
773
|
+
fromPartyId: disponentParty.id,
|
|
774
|
+
toPartyId: partyData.id,
|
|
775
|
+
relationshipType: "AUTHORIZED_SIGNATORY"
|
|
776
|
+
});
|
|
777
|
+
if (linkDisponentError) {
|
|
778
|
+
return context.json({ message: "Could not link disponent to party" }, 500);
|
|
668
779
|
}
|
|
669
|
-
for (const
|
|
670
|
-
const
|
|
780
|
+
for (const doc of identityDocuments ?? []) {
|
|
781
|
+
const { data: createdIdDoc, error: idDocError } = await mdm.createIdDocument({
|
|
782
|
+
partyId: disponentParty.id,
|
|
783
|
+
idDocument: {
|
|
784
|
+
partyId: disponentParty.id,
|
|
785
|
+
idDocType: doc.idDocType,
|
|
786
|
+
idDocNumber: doc.idDocNumber,
|
|
787
|
+
idDocHolderName: `${individualData.name} ${individualData.surname}`,
|
|
788
|
+
issueDate: doc.issueDate,
|
|
789
|
+
expirationDate: doc.expirationDate,
|
|
790
|
+
issuer: doc.issuer,
|
|
791
|
+
frontImageUri: doc.frontImageUri,
|
|
792
|
+
backImageUri: doc.backImageUri
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
if (!createdIdDoc || idDocError) {
|
|
796
|
+
return context.json(
|
|
797
|
+
{ message: "Could not create disponent identity document" },
|
|
798
|
+
500
|
|
799
|
+
);
|
|
800
|
+
}
|
|
671
801
|
if (doc.frontImageUri) {
|
|
672
802
|
await docService.acknowledgeDocument({
|
|
673
803
|
storageUrl: doc.frontImageUri,
|
|
674
|
-
entityId:
|
|
804
|
+
entityId: createdIdDoc.id
|
|
675
805
|
});
|
|
676
806
|
}
|
|
677
807
|
if (doc.backImageUri) {
|
|
678
808
|
await docService.acknowledgeDocument({
|
|
679
809
|
storageUrl: doc.backImageUri,
|
|
680
|
-
entityId:
|
|
810
|
+
entityId: createdIdDoc.id
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (owners?.length) {
|
|
816
|
+
for (const owner of owners) {
|
|
817
|
+
const { address, sharePercentage, shareEstablishedAt, ...individual } = owner;
|
|
818
|
+
const { data: ownerParty, error: ownerError } = await mdm.createParty({
|
|
819
|
+
party: {
|
|
820
|
+
partyType: "INDIVIDUAL",
|
|
821
|
+
language: partyInput.party.language,
|
|
822
|
+
customerStatus: "NEW"
|
|
823
|
+
},
|
|
824
|
+
personalData: { ...individual, email: individual.email ?? "" },
|
|
825
|
+
organizationData: null,
|
|
826
|
+
bankAccounts: null,
|
|
827
|
+
recipients: null,
|
|
828
|
+
disponents: null,
|
|
829
|
+
addresses: [
|
|
830
|
+
{
|
|
831
|
+
...address,
|
|
832
|
+
district: address.district ?? "",
|
|
833
|
+
region: address.region ?? ""
|
|
834
|
+
}
|
|
835
|
+
],
|
|
836
|
+
aml: null
|
|
837
|
+
});
|
|
838
|
+
if (ownerParty && !ownerError) {
|
|
839
|
+
await mdm.linkPartyToParty({
|
|
840
|
+
fromPartyId: ownerParty.id,
|
|
841
|
+
toPartyId: partyData.id,
|
|
842
|
+
relationshipType: "UBO",
|
|
843
|
+
sharePercentage,
|
|
844
|
+
fromDate: new Date(shareEstablishedAt)
|
|
681
845
|
});
|
|
682
846
|
}
|
|
683
847
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
848
|
+
}
|
|
849
|
+
if (legalRepresentatives?.length) {
|
|
850
|
+
for (const rep of legalRepresentatives) {
|
|
851
|
+
const { address, identityDocuments, dateOfEstablishment, ...individual } = rep;
|
|
852
|
+
const { data: repParty, error: repError } = await mdm.createParty({
|
|
687
853
|
party: {
|
|
688
854
|
partyType: "INDIVIDUAL",
|
|
689
855
|
language: partyInput.party.language,
|
|
690
856
|
customerStatus: "NEW"
|
|
691
857
|
},
|
|
692
|
-
personalData:
|
|
858
|
+
personalData: individual,
|
|
693
859
|
organizationData: null,
|
|
694
860
|
bankAccounts: null,
|
|
695
861
|
recipients: null,
|
|
696
862
|
disponents: null,
|
|
697
|
-
addresses: [
|
|
863
|
+
addresses: [
|
|
864
|
+
{
|
|
865
|
+
...address,
|
|
866
|
+
district: address.district ?? "",
|
|
867
|
+
region: address.region ?? ""
|
|
868
|
+
}
|
|
869
|
+
],
|
|
698
870
|
aml: null
|
|
699
871
|
});
|
|
700
|
-
if (!
|
|
872
|
+
if (!repParty || repError) {
|
|
701
873
|
return context.json(
|
|
702
|
-
{ message: "Could not create
|
|
874
|
+
{ message: "Could not create legal representative party" },
|
|
703
875
|
500
|
|
704
876
|
);
|
|
705
877
|
}
|
|
706
|
-
const { error:
|
|
707
|
-
fromPartyId:
|
|
878
|
+
const { error: linkRepError } = await mdm.linkPartyToParty({
|
|
879
|
+
fromPartyId: repParty.id,
|
|
708
880
|
toPartyId: partyData.id,
|
|
709
|
-
relationshipType: "
|
|
881
|
+
relationshipType: "BOARD_MEMBER",
|
|
882
|
+
fromDate: new Date(dateOfEstablishment)
|
|
710
883
|
});
|
|
711
|
-
if (
|
|
884
|
+
if (linkRepError) {
|
|
712
885
|
return context.json(
|
|
713
|
-
{ message: "Could not link
|
|
886
|
+
{ message: "Could not link legal representative to party" },
|
|
714
887
|
500
|
|
715
888
|
);
|
|
716
889
|
}
|
|
717
890
|
for (const doc of identityDocuments ?? []) {
|
|
718
891
|
const { data: createdIdDoc, error: idDocError } = await mdm.createIdDocument({
|
|
719
|
-
partyId:
|
|
892
|
+
partyId: repParty.id,
|
|
720
893
|
idDocument: {
|
|
721
|
-
partyId:
|
|
894
|
+
partyId: repParty.id,
|
|
722
895
|
idDocType: doc.idDocType,
|
|
723
896
|
idDocNumber: doc.idDocNumber,
|
|
724
|
-
idDocHolderName: `${
|
|
897
|
+
idDocHolderName: `${individual.name} ${individual.surname}`,
|
|
725
898
|
issueDate: doc.issueDate,
|
|
726
899
|
expirationDate: doc.expirationDate,
|
|
727
900
|
issuer: doc.issuer,
|
|
@@ -731,7 +904,9 @@ new OpenAPIHono().openapi(
|
|
|
731
904
|
});
|
|
732
905
|
if (!createdIdDoc || idDocError) {
|
|
733
906
|
return context.json(
|
|
734
|
-
{
|
|
907
|
+
{
|
|
908
|
+
message: "Could not create legal representative identity document"
|
|
909
|
+
},
|
|
735
910
|
500
|
|
736
911
|
);
|
|
737
912
|
}
|
|
@@ -749,133 +924,30 @@ new OpenAPIHono().openapi(
|
|
|
749
924
|
}
|
|
750
925
|
}
|
|
751
926
|
}
|
|
752
|
-
if (owners?.length) {
|
|
753
|
-
for (const owner of owners) {
|
|
754
|
-
const { address, sharePercentage, shareEstablishedAt, ...individual } = owner;
|
|
755
|
-
const { data: ownerParty, error: ownerError } = await mdm.createParty({
|
|
756
|
-
party: {
|
|
757
|
-
partyType: "INDIVIDUAL",
|
|
758
|
-
language: partyInput.party.language,
|
|
759
|
-
customerStatus: "NEW"
|
|
760
|
-
},
|
|
761
|
-
personalData: { ...individual, email: individual.email ?? "" },
|
|
762
|
-
organizationData: null,
|
|
763
|
-
bankAccounts: null,
|
|
764
|
-
recipients: null,
|
|
765
|
-
disponents: null,
|
|
766
|
-
addresses: [
|
|
767
|
-
{
|
|
768
|
-
...address,
|
|
769
|
-
district: address.district ?? "",
|
|
770
|
-
region: address.region ?? ""
|
|
771
|
-
}
|
|
772
|
-
],
|
|
773
|
-
aml: null
|
|
774
|
-
});
|
|
775
|
-
if (ownerParty && !ownerError) {
|
|
776
|
-
await mdm.linkPartyToParty({
|
|
777
|
-
fromPartyId: ownerParty.id,
|
|
778
|
-
toPartyId: partyData.id,
|
|
779
|
-
relationshipType: "UBO",
|
|
780
|
-
sharePercentage,
|
|
781
|
-
fromDate: new Date(shareEstablishedAt)
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
if (legalRepresentatives?.length) {
|
|
787
|
-
for (const rep of legalRepresentatives) {
|
|
788
|
-
const {
|
|
789
|
-
address,
|
|
790
|
-
identityDocuments,
|
|
791
|
-
dateOfEstablishment,
|
|
792
|
-
...individual
|
|
793
|
-
} = rep;
|
|
794
|
-
const { data: repParty, error: repError } = await mdm.createParty({
|
|
795
|
-
party: {
|
|
796
|
-
partyType: "INDIVIDUAL",
|
|
797
|
-
language: partyInput.party.language,
|
|
798
|
-
customerStatus: "NEW"
|
|
799
|
-
},
|
|
800
|
-
personalData: individual,
|
|
801
|
-
organizationData: null,
|
|
802
|
-
bankAccounts: null,
|
|
803
|
-
recipients: null,
|
|
804
|
-
disponents: null,
|
|
805
|
-
addresses: [
|
|
806
|
-
{
|
|
807
|
-
...address,
|
|
808
|
-
district: address.district ?? "",
|
|
809
|
-
region: address.region ?? ""
|
|
810
|
-
}
|
|
811
|
-
],
|
|
812
|
-
aml: null
|
|
813
|
-
});
|
|
814
|
-
if (!repParty || repError) {
|
|
815
|
-
return context.json(
|
|
816
|
-
{ message: "Could not create legal representative party" },
|
|
817
|
-
500
|
|
818
|
-
);
|
|
819
|
-
}
|
|
820
|
-
const { error: linkRepError } = await mdm.linkPartyToParty({
|
|
821
|
-
fromPartyId: repParty.id,
|
|
822
|
-
toPartyId: partyData.id,
|
|
823
|
-
relationshipType: "BOARD_MEMBER",
|
|
824
|
-
fromDate: new Date(dateOfEstablishment)
|
|
825
|
-
});
|
|
826
|
-
if (linkRepError) {
|
|
827
|
-
return context.json(
|
|
828
|
-
{ message: "Could not link legal representative to party" },
|
|
829
|
-
500
|
|
830
|
-
);
|
|
831
|
-
}
|
|
832
|
-
for (const doc of identityDocuments ?? []) {
|
|
833
|
-
const { data: createdIdDoc, error: idDocError } = await mdm.createIdDocument({
|
|
834
|
-
partyId: repParty.id,
|
|
835
|
-
idDocument: {
|
|
836
|
-
partyId: repParty.id,
|
|
837
|
-
idDocType: doc.idDocType,
|
|
838
|
-
idDocNumber: doc.idDocNumber,
|
|
839
|
-
idDocHolderName: `${individual.name} ${individual.surname}`,
|
|
840
|
-
issueDate: doc.issueDate,
|
|
841
|
-
expirationDate: doc.expirationDate,
|
|
842
|
-
issuer: doc.issuer,
|
|
843
|
-
frontImageUri: doc.frontImageUri,
|
|
844
|
-
backImageUri: doc.backImageUri
|
|
845
|
-
}
|
|
846
|
-
});
|
|
847
|
-
if (!createdIdDoc || idDocError) {
|
|
848
|
-
return context.json(
|
|
849
|
-
{
|
|
850
|
-
message: "Could not create legal representative identity document"
|
|
851
|
-
},
|
|
852
|
-
500
|
|
853
|
-
);
|
|
854
|
-
}
|
|
855
|
-
if (doc.frontImageUri) {
|
|
856
|
-
await docService.acknowledgeDocument({
|
|
857
|
-
storageUrl: doc.frontImageUri,
|
|
858
|
-
entityId: createdIdDoc.id
|
|
859
|
-
});
|
|
860
|
-
}
|
|
861
|
-
if (doc.backImageUri) {
|
|
862
|
-
await docService.acknowledgeDocument({
|
|
863
|
-
storageUrl: doc.backImageUri,
|
|
864
|
-
entityId: createdIdDoc.id
|
|
865
|
-
});
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
return context.json(
|
|
871
|
-
{
|
|
872
|
-
message: "party created",
|
|
873
|
-
party: partyData
|
|
874
|
-
},
|
|
875
|
-
200
|
|
876
|
-
);
|
|
877
927
|
}
|
|
878
|
-
|
|
928
|
+
logAuditEvent(context, {
|
|
929
|
+
eventType: "party.created",
|
|
930
|
+
targetType: "party",
|
|
931
|
+
targetId: partyData.id,
|
|
932
|
+
outcome: "success",
|
|
933
|
+
severity: "medium",
|
|
934
|
+
description: `Party ${partyData.id} created`,
|
|
935
|
+
details: {
|
|
936
|
+
partyType: partyInput.party.partyType,
|
|
937
|
+
disponentCount: partyInput.disponents?.length ?? 0,
|
|
938
|
+
bankAccountCount: partyInput.bankAccounts?.length ?? 0,
|
|
939
|
+
ownerCount: owners?.length ?? 0,
|
|
940
|
+
legalRepresentativeCount: legalRepresentatives?.length ?? 0
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
return context.json(
|
|
944
|
+
{
|
|
945
|
+
message: "party created",
|
|
946
|
+
party: partyData
|
|
947
|
+
},
|
|
948
|
+
200
|
|
949
|
+
);
|
|
950
|
+
});
|
|
879
951
|
|
|
880
952
|
const partySchema = z.object({
|
|
881
953
|
partyType: z.enum(PARTY_TYPE),
|
|
@@ -883,7 +955,10 @@ const partySchema = z.object({
|
|
|
883
955
|
id: z.uuid(),
|
|
884
956
|
internalId: z.string().optional(),
|
|
885
957
|
note: z.string().optional(),
|
|
886
|
-
countryCode: z.enum(COUNTRY_CODES).optional()
|
|
958
|
+
countryCode: z.enum(COUNTRY_CODES).optional(),
|
|
959
|
+
customerStatus: z.enum(CUSTOMER_STATUS).optional(),
|
|
960
|
+
blockReason: z.enum(BLOCK_REASON).nullable().optional(),
|
|
961
|
+
blockReasonNote: z.string().trim().min(1).nullable().optional()
|
|
887
962
|
});
|
|
888
963
|
const idDocumentInputSchema = z.object({
|
|
889
964
|
id: z.uuid().optional(),
|
|
@@ -1091,7 +1166,7 @@ const ownerSyncSchema = z.object({
|
|
|
1091
1166
|
name: z.string(),
|
|
1092
1167
|
surname: z.string(),
|
|
1093
1168
|
titleAfter: z.string().optional(),
|
|
1094
|
-
email: z.email("E-mail je povinn\xFD"),
|
|
1169
|
+
email: z.email("E-mail je povinn\xFD").optional(),
|
|
1095
1170
|
birthDate: z.string(),
|
|
1096
1171
|
birthPlace: z.string().optional(),
|
|
1097
1172
|
personalId: z.string(),
|
|
@@ -1134,6 +1209,21 @@ const partyUpdateInputSchema = z.object({
|
|
|
1134
1209
|
aml: updateAmlInputSchema.optional(),
|
|
1135
1210
|
products: productsInputSchema.optional(),
|
|
1136
1211
|
traderIds: z.array(z.uuid()).optional()
|
|
1212
|
+
}).refine(
|
|
1213
|
+
(b) => b.party.customerStatus !== "BLOCKED" || !!b.party.blockReason,
|
|
1214
|
+
{
|
|
1215
|
+
message: "blockReason is required when customerStatus is BLOCKED",
|
|
1216
|
+
path: ["party", "blockReason"]
|
|
1217
|
+
}
|
|
1218
|
+
).refine(
|
|
1219
|
+
(b) => b.party.customerStatus === "BLOCKED" || b.party.customerStatus === void 0 || !b.party.blockReason && !b.party.blockReasonNote,
|
|
1220
|
+
{
|
|
1221
|
+
message: "blockReason and blockReasonNote must be null when customerStatus is not BLOCKED",
|
|
1222
|
+
path: ["party", "blockReason"]
|
|
1223
|
+
}
|
|
1224
|
+
).refine((b) => b.party.blockReason !== "OTHER" || !!b.party.blockReasonNote, {
|
|
1225
|
+
message: "blockReasonNote is required when blockReason is OTHER",
|
|
1226
|
+
path: ["party", "blockReasonNote"]
|
|
1137
1227
|
});
|
|
1138
1228
|
const updatePartyOuputSchema = z.object({
|
|
1139
1229
|
id: z.uuid(),
|
|
@@ -1181,48 +1271,75 @@ const updatePartyRoute = createRoute({
|
|
|
1181
1271
|
...errorResponse("Party", "Update")
|
|
1182
1272
|
}
|
|
1183
1273
|
});
|
|
1184
|
-
new OpenAPIHono().openapi(
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1274
|
+
new OpenAPIHono().openapi(updatePartyRoute, async (context) => {
|
|
1275
|
+
const party = context.req.valid("json");
|
|
1276
|
+
const { partyId } = context.req.valid("param");
|
|
1277
|
+
const { data: updatedParty, error: partyError } = await context.env.MASTER_DATA_MANAGEMENT_SERVICE.updateParty({
|
|
1278
|
+
partyId,
|
|
1279
|
+
party: party.party,
|
|
1280
|
+
personalData: party.personalData ?? void 0,
|
|
1281
|
+
organizationData: party.organizationData ?? void 0,
|
|
1282
|
+
bankAccounts: party.bankAccounts ?? void 0,
|
|
1283
|
+
disponents: party.disponents ?? void 0,
|
|
1284
|
+
addresses: party.addresses ?? void 0,
|
|
1285
|
+
recipients: party.recipients ?? void 0,
|
|
1286
|
+
aml: party.aml ?? void 0,
|
|
1287
|
+
products: party.products ?? void 0,
|
|
1288
|
+
traderIds: party.traderIds ?? void 0,
|
|
1289
|
+
legalRepresentatives: party.legalRepresentatives ?? void 0,
|
|
1290
|
+
owners: party.owners ?? void 0
|
|
1291
|
+
});
|
|
1292
|
+
if (!updatedParty || partyError) {
|
|
1293
|
+
logAuditEvent(context, {
|
|
1294
|
+
eventType: "party.updated",
|
|
1295
|
+
targetType: "party",
|
|
1296
|
+
targetId: partyId,
|
|
1297
|
+
outcome: "failure",
|
|
1298
|
+
severity: "medium",
|
|
1299
|
+
description: `Failed to update party ${partyId}`,
|
|
1300
|
+
details: { partyType: party.party.partyType }
|
|
1203
1301
|
});
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1302
|
+
return context.json({ message: "Could not update a Party" }, 404);
|
|
1303
|
+
}
|
|
1304
|
+
const docService = context.env.DOCUMENT_SERVICE;
|
|
1305
|
+
if (party.organizationData?.registerUri) {
|
|
1306
|
+
await docService.acknowledgeDocument({
|
|
1307
|
+
storageUrl: party.organizationData.registerUri,
|
|
1308
|
+
entityId: partyId
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
for (const ba of party.bankAccounts ?? []) {
|
|
1312
|
+
if (ba.statementUri) {
|
|
1209
1313
|
await docService.acknowledgeDocument({
|
|
1210
|
-
storageUrl:
|
|
1314
|
+
storageUrl: ba.statementUri,
|
|
1211
1315
|
entityId: partyId
|
|
1212
1316
|
});
|
|
1213
1317
|
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1318
|
+
}
|
|
1319
|
+
if (party.personalData?.identityDocuments?.length) {
|
|
1320
|
+
let newDocIdx = 0;
|
|
1321
|
+
for (const doc of party.personalData.identityDocuments) {
|
|
1322
|
+
const idDocEntityId = doc.id ? doc.id : updatedParty.newPersonalIdDocIds?.[newDocIdx++] ?? partyId;
|
|
1323
|
+
if (doc.frontImageUri) {
|
|
1216
1324
|
await docService.acknowledgeDocument({
|
|
1217
|
-
storageUrl:
|
|
1218
|
-
entityId:
|
|
1325
|
+
storageUrl: doc.frontImageUri,
|
|
1326
|
+
entityId: idDocEntityId
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
if (doc.backImageUri) {
|
|
1330
|
+
await docService.acknowledgeDocument({
|
|
1331
|
+
storageUrl: doc.backImageUri,
|
|
1332
|
+
entityId: idDocEntityId
|
|
1219
1333
|
});
|
|
1220
1334
|
}
|
|
1221
1335
|
}
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1336
|
+
}
|
|
1337
|
+
if (party.legalRepresentatives?.length) {
|
|
1338
|
+
let newBmDocIdx = 0;
|
|
1339
|
+
for (const rep of party.legalRepresentatives) {
|
|
1340
|
+
if (rep.id) continue;
|
|
1341
|
+
for (const doc of rep.identityDocuments ?? []) {
|
|
1342
|
+
const idDocEntityId = updatedParty.newBoardMemberIdDocIds?.[newBmDocIdx++] ?? partyId;
|
|
1226
1343
|
if (doc.frontImageUri) {
|
|
1227
1344
|
await docService.acknowledgeDocument({
|
|
1228
1345
|
storageUrl: doc.frontImageUri,
|
|
@@ -1237,54 +1354,45 @@ new OpenAPIHono().openapi(
|
|
|
1237
1354
|
}
|
|
1238
1355
|
}
|
|
1239
1356
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
for (const
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
entityId: idDocEntityId
|
|
1250
|
-
});
|
|
1251
|
-
}
|
|
1252
|
-
if (doc.backImageUri) {
|
|
1253
|
-
await docService.acknowledgeDocument({
|
|
1254
|
-
storageUrl: doc.backImageUri,
|
|
1255
|
-
entityId: idDocEntityId
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1357
|
+
for (const rep of party.legalRepresentatives) {
|
|
1358
|
+
if (!rep.id) continue;
|
|
1359
|
+
for (const doc of rep.identityDocuments ?? []) {
|
|
1360
|
+
const idDocEntityId = doc.id ? doc.id : updatedParty.newBoardMemberIdDocIds?.[newBmDocIdx++] ?? partyId;
|
|
1361
|
+
if (doc.frontImageUri) {
|
|
1362
|
+
await docService.acknowledgeDocument({
|
|
1363
|
+
storageUrl: doc.frontImageUri,
|
|
1364
|
+
entityId: idDocEntityId
|
|
1365
|
+
});
|
|
1258
1366
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
if (doc.frontImageUri) {
|
|
1265
|
-
await docService.acknowledgeDocument({
|
|
1266
|
-
storageUrl: doc.frontImageUri,
|
|
1267
|
-
entityId: idDocEntityId
|
|
1268
|
-
});
|
|
1269
|
-
}
|
|
1270
|
-
if (doc.backImageUri) {
|
|
1271
|
-
await docService.acknowledgeDocument({
|
|
1272
|
-
storageUrl: doc.backImageUri,
|
|
1273
|
-
entityId: idDocEntityId
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1367
|
+
if (doc.backImageUri) {
|
|
1368
|
+
await docService.acknowledgeDocument({
|
|
1369
|
+
storageUrl: doc.backImageUri,
|
|
1370
|
+
entityId: idDocEntityId
|
|
1371
|
+
});
|
|
1276
1372
|
}
|
|
1277
1373
|
}
|
|
1278
1374
|
}
|
|
1279
|
-
return context.json(
|
|
1280
|
-
{
|
|
1281
|
-
message: "Party updated successfully",
|
|
1282
|
-
party: updatedParty
|
|
1283
|
-
},
|
|
1284
|
-
200
|
|
1285
|
-
);
|
|
1286
1375
|
}
|
|
1287
|
-
|
|
1376
|
+
logAuditEvent(context, {
|
|
1377
|
+
eventType: "party.updated",
|
|
1378
|
+
targetType: "party",
|
|
1379
|
+
targetId: partyId,
|
|
1380
|
+
outcome: "success",
|
|
1381
|
+
severity: "medium",
|
|
1382
|
+
description: `Party ${partyId} updated`,
|
|
1383
|
+
details: {
|
|
1384
|
+
partyType: party.party.partyType,
|
|
1385
|
+
customerStatus: updatedParty.customerStatus
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
return context.json(
|
|
1389
|
+
{
|
|
1390
|
+
message: "Party updated successfully",
|
|
1391
|
+
party: updatedParty
|
|
1392
|
+
},
|
|
1393
|
+
200
|
|
1394
|
+
);
|
|
1395
|
+
});
|
|
1288
1396
|
|
|
1289
1397
|
const DOCUMENT_SIDE = ["front", "back"];
|
|
1290
1398
|
const paramsSchema$2 = z.object({
|
|
@@ -1388,64 +1496,91 @@ const createDocumentRoute = createRoute({
|
|
|
1388
1496
|
}
|
|
1389
1497
|
}
|
|
1390
1498
|
});
|
|
1391
|
-
new OpenAPIHono().openapi(
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1499
|
+
new OpenAPIHono().openapi(createDocumentRoute, async (context) => {
|
|
1500
|
+
const rawBody = await context.req.parseBody();
|
|
1501
|
+
const { partyId } = context.req.valid("param");
|
|
1502
|
+
const idDocumentRaw = rawBody.idDocument;
|
|
1503
|
+
const documentSide = rawBody.documentSide;
|
|
1504
|
+
const file = rawBody.file;
|
|
1505
|
+
if (typeof idDocumentRaw !== "string" || !DOCUMENT_SIDE.includes(documentSide) || !(file instanceof File)) {
|
|
1506
|
+
return context.json({ message: "Invalid multipart payload" }, 400);
|
|
1507
|
+
}
|
|
1508
|
+
const idDocumentJson = JSON.parse(JSON.parse(idDocumentRaw));
|
|
1509
|
+
const idDocumentResult = idDocumentCreateInputSchema.safeParse(idDocumentJson);
|
|
1510
|
+
if (!idDocumentResult.success) {
|
|
1511
|
+
console.error(idDocumentResult.error);
|
|
1512
|
+
return context.json({ message: "Could not parse IdDocument" }, 400);
|
|
1513
|
+
}
|
|
1514
|
+
const {
|
|
1515
|
+
data: createdIdDocument,
|
|
1516
|
+
error: createError,
|
|
1517
|
+
message
|
|
1518
|
+
} = await context.env.MASTER_DATA_MANAGEMENT_SERVICE.createIdDocument({
|
|
1519
|
+
idDocument: idDocumentResult.data,
|
|
1520
|
+
partyId
|
|
1521
|
+
});
|
|
1522
|
+
if (!createdIdDocument || createError) {
|
|
1523
|
+
console.error(message);
|
|
1524
|
+
logAuditEvent(context, {
|
|
1525
|
+
eventType: "id-document.created",
|
|
1526
|
+
targetType: "id-document",
|
|
1527
|
+
outcome: "failure",
|
|
1528
|
+
severity: "medium",
|
|
1529
|
+
description: `Failed to create ID document for party ${partyId}`,
|
|
1530
|
+
details: { partyId, idDocType: idDocumentResult.data.idDocType }
|
|
1415
1531
|
});
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1532
|
+
return context.json({ message: "Could not create IdDocument" }, 500);
|
|
1533
|
+
}
|
|
1534
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
1535
|
+
const { data: uploadResult, error: uploadError } = await context.env.DOCUMENT_SERVICE.uploadDocument({
|
|
1536
|
+
entityType: "client",
|
|
1537
|
+
entityId: createdIdDocument.id,
|
|
1538
|
+
type: "kyc",
|
|
1539
|
+
metadata: {},
|
|
1540
|
+
file: {
|
|
1541
|
+
bytes,
|
|
1542
|
+
type: file.type,
|
|
1543
|
+
name: file.name,
|
|
1544
|
+
size: file.size
|
|
1419
1545
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
size: file.size
|
|
1431
|
-
}
|
|
1546
|
+
});
|
|
1547
|
+
if (!uploadResult || uploadError) {
|
|
1548
|
+
logAuditEvent(context, {
|
|
1549
|
+
eventType: "id-document.created",
|
|
1550
|
+
targetType: "id-document",
|
|
1551
|
+
targetId: createdIdDocument.id,
|
|
1552
|
+
outcome: "error",
|
|
1553
|
+
severity: "medium",
|
|
1554
|
+
description: `ID document ${createdIdDocument.id} created but file upload failed`,
|
|
1555
|
+
details: { partyId, documentSide }
|
|
1432
1556
|
});
|
|
1433
|
-
|
|
1434
|
-
return context.json({ message: "File upload failed" }, 500);
|
|
1435
|
-
}
|
|
1436
|
-
return context.json(
|
|
1437
|
-
{
|
|
1438
|
-
message: "IdDocument created successfully",
|
|
1439
|
-
idDocument: {
|
|
1440
|
-
...createdIdDocument,
|
|
1441
|
-
frontImageUri: documentSide === "front" ? uploadResult.storageUrl : createdIdDocument.frontImageUri,
|
|
1442
|
-
backImageUri: documentSide === "back" ? uploadResult.storageUrl : createdIdDocument.backImageUri
|
|
1443
|
-
}
|
|
1444
|
-
},
|
|
1445
|
-
200
|
|
1446
|
-
);
|
|
1557
|
+
return context.json({ message: "File upload failed" }, 500);
|
|
1447
1558
|
}
|
|
1448
|
-
|
|
1559
|
+
logAuditEvent(context, {
|
|
1560
|
+
eventType: "id-document.created",
|
|
1561
|
+
targetType: "id-document",
|
|
1562
|
+
targetId: createdIdDocument.id,
|
|
1563
|
+
outcome: "success",
|
|
1564
|
+
severity: "medium",
|
|
1565
|
+
description: `ID document ${createdIdDocument.id} created for party ${partyId}`,
|
|
1566
|
+
details: {
|
|
1567
|
+
partyId,
|
|
1568
|
+
idDocType: createdIdDocument.idDocType,
|
|
1569
|
+
documentSide
|
|
1570
|
+
}
|
|
1571
|
+
});
|
|
1572
|
+
return context.json(
|
|
1573
|
+
{
|
|
1574
|
+
message: "IdDocument created successfully",
|
|
1575
|
+
idDocument: {
|
|
1576
|
+
...createdIdDocument,
|
|
1577
|
+
frontImageUri: documentSide === "front" ? uploadResult.storageUrl : createdIdDocument.frontImageUri,
|
|
1578
|
+
backImageUri: documentSide === "back" ? uploadResult.storageUrl : createdIdDocument.backImageUri
|
|
1579
|
+
}
|
|
1580
|
+
},
|
|
1581
|
+
200
|
|
1582
|
+
);
|
|
1583
|
+
});
|
|
1449
1584
|
|
|
1450
1585
|
const partyBaseOutputSchema = z.object({
|
|
1451
1586
|
customerStatus: z.enum(CUSTOMER_STATUS),
|
|
@@ -1960,35 +2095,57 @@ const updateIdDocumentRoute = createRoute({
|
|
|
1960
2095
|
}
|
|
1961
2096
|
}
|
|
1962
2097
|
});
|
|
1963
|
-
new OpenAPIHono().openapi(
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
id
|
|
1976
|
-
};
|
|
1977
|
-
const { data: updatedIdDocument, error: updateError } = await context.env.MASTER_DATA_MANAGEMENT_SERVICE.updateIdDocument({
|
|
1978
|
-
idDocument: fullIdDocument
|
|
2098
|
+
new OpenAPIHono().openapi(updateIdDocumentRoute, async (context) => {
|
|
2099
|
+
const { id } = context.req.valid("param");
|
|
2100
|
+
const patch = context.req.valid("json");
|
|
2101
|
+
const { data: existingDocument, error: fetchError } = await context.env.MASTER_DATA_MANAGEMENT_SERVICE.getIdDocument({ id });
|
|
2102
|
+
if (!existingDocument || fetchError) {
|
|
2103
|
+
logAuditEvent(context, {
|
|
2104
|
+
eventType: "id-document.updated",
|
|
2105
|
+
targetType: "id-document",
|
|
2106
|
+
targetId: id,
|
|
2107
|
+
outcome: "failure",
|
|
2108
|
+
severity: "medium",
|
|
2109
|
+
description: `Failed to update ID document ${id}: not found`
|
|
1979
2110
|
});
|
|
1980
|
-
|
|
1981
|
-
return context.json({ message: "Could not update ID document" }, 500);
|
|
1982
|
-
}
|
|
1983
|
-
return context.json(
|
|
1984
|
-
{
|
|
1985
|
-
message: "ID document updated successfully",
|
|
1986
|
-
idDocument: updatedIdDocument
|
|
1987
|
-
},
|
|
1988
|
-
200
|
|
1989
|
-
);
|
|
2111
|
+
return context.json({ message: "ID document not found" }, 404);
|
|
1990
2112
|
}
|
|
1991
|
-
|
|
2113
|
+
const fullIdDocument = {
|
|
2114
|
+
...existingDocument,
|
|
2115
|
+
...patch,
|
|
2116
|
+
id
|
|
2117
|
+
};
|
|
2118
|
+
const { data: updatedIdDocument, error: updateError } = await context.env.MASTER_DATA_MANAGEMENT_SERVICE.updateIdDocument({
|
|
2119
|
+
idDocument: fullIdDocument
|
|
2120
|
+
});
|
|
2121
|
+
if (!updatedIdDocument || updateError) {
|
|
2122
|
+
logAuditEvent(context, {
|
|
2123
|
+
eventType: "id-document.updated",
|
|
2124
|
+
targetType: "id-document",
|
|
2125
|
+
targetId: id,
|
|
2126
|
+
outcome: "failure",
|
|
2127
|
+
severity: "medium",
|
|
2128
|
+
description: `Failed to update ID document ${id}`
|
|
2129
|
+
});
|
|
2130
|
+
return context.json({ message: "Could not update ID document" }, 500);
|
|
2131
|
+
}
|
|
2132
|
+
logAuditEvent(context, {
|
|
2133
|
+
eventType: "id-document.updated",
|
|
2134
|
+
targetType: "id-document",
|
|
2135
|
+
targetId: id,
|
|
2136
|
+
outcome: "success",
|
|
2137
|
+
severity: "medium",
|
|
2138
|
+
description: `ID document ${id} updated`,
|
|
2139
|
+
details: { partyId: updatedIdDocument.partyId }
|
|
2140
|
+
});
|
|
2141
|
+
return context.json(
|
|
2142
|
+
{
|
|
2143
|
+
message: "ID document updated successfully",
|
|
2144
|
+
idDocument: updatedIdDocument
|
|
2145
|
+
},
|
|
2146
|
+
200
|
|
2147
|
+
);
|
|
2148
|
+
});
|
|
1992
2149
|
|
|
1993
2150
|
const messageResponseSchema = z.object({
|
|
1994
2151
|
message: z.string()
|