@voyantjs/customer-portal 0.26.0 → 0.26.1
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/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/routes-public.d.ts +352 -74
- package/dist/routes-public.d.ts.map +1 -1
- package/dist/routes-public.js +40 -1
- package/dist/service-public.d.ts +80 -0
- package/dist/service-public.d.ts.map +1 -1
- package/dist/service-public.js +218 -34
- package/dist/validation-public.d.ts +73 -45
- package/dist/validation-public.d.ts.map +1 -1
- package/dist/validation-public.js +48 -20
- package/package.json +10 -10
package/dist/service-public.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ interface CustomerPortalServiceOptions {
|
|
|
5
5
|
kms?: KmsProvider | null;
|
|
6
6
|
resolveDocumentDownloadUrl?: (storageKey: string) => Promise<string | null> | string | null;
|
|
7
7
|
}
|
|
8
|
+
type WireDocumentType = "passport" | "id_card" | "visa" | "drivers_license" | "other";
|
|
8
9
|
export declare const publicCustomerPortalService: {
|
|
9
10
|
contactExists(db: PostgresJsDatabase, email: string): Promise<CustomerPortalContactExistsResult>;
|
|
10
11
|
phoneContactExists(db: PostgresJsDatabase, phone: string): Promise<CustomerPortalPhoneContactExistsResult>;
|
|
@@ -52,6 +53,85 @@ export declare const publicCustomerPortalService: {
|
|
|
52
53
|
address1: string | null;
|
|
53
54
|
postal: string | null;
|
|
54
55
|
} | null>;
|
|
56
|
+
listMyDocuments(db: PostgresJsDatabase, userId: string, options?: CustomerPortalServiceOptions): Promise<{
|
|
57
|
+
id: string;
|
|
58
|
+
type: WireDocumentType;
|
|
59
|
+
number: string | null;
|
|
60
|
+
issuingAuthority: string | null;
|
|
61
|
+
issuingCountry: string | null;
|
|
62
|
+
issueDate: string | null;
|
|
63
|
+
expiryDate: string | null;
|
|
64
|
+
attachmentId: string | null;
|
|
65
|
+
isPrimary: boolean;
|
|
66
|
+
notes: string | null;
|
|
67
|
+
createdAt: string;
|
|
68
|
+
updatedAt: string;
|
|
69
|
+
}[]>;
|
|
70
|
+
createMyDocument(db: PostgresJsDatabase, userId: string, input: {
|
|
71
|
+
type: WireDocumentType;
|
|
72
|
+
number?: string | null;
|
|
73
|
+
issuingAuthority?: string | null;
|
|
74
|
+
issuingCountry?: string | null;
|
|
75
|
+
issueDate?: string | null;
|
|
76
|
+
expiryDate?: string | null;
|
|
77
|
+
attachmentId?: string | null;
|
|
78
|
+
isPrimary?: boolean;
|
|
79
|
+
notes?: string | null;
|
|
80
|
+
}, options?: CustomerPortalServiceOptions): Promise<{
|
|
81
|
+
id: string;
|
|
82
|
+
type: WireDocumentType;
|
|
83
|
+
number: string | null;
|
|
84
|
+
issuingAuthority: string | null;
|
|
85
|
+
issuingCountry: string | null;
|
|
86
|
+
issueDate: string | null;
|
|
87
|
+
expiryDate: string | null;
|
|
88
|
+
attachmentId: string | null;
|
|
89
|
+
isPrimary: boolean;
|
|
90
|
+
notes: string | null;
|
|
91
|
+
createdAt: string;
|
|
92
|
+
updatedAt: string;
|
|
93
|
+
} | null>;
|
|
94
|
+
updateMyDocument(db: PostgresJsDatabase, userId: string, documentId: string, input: {
|
|
95
|
+
type?: WireDocumentType;
|
|
96
|
+
number?: string | null;
|
|
97
|
+
issuingAuthority?: string | null;
|
|
98
|
+
issuingCountry?: string | null;
|
|
99
|
+
issueDate?: string | null;
|
|
100
|
+
expiryDate?: string | null;
|
|
101
|
+
attachmentId?: string | null;
|
|
102
|
+
isPrimary?: boolean;
|
|
103
|
+
notes?: string | null;
|
|
104
|
+
}, options?: CustomerPortalServiceOptions): Promise<{
|
|
105
|
+
id: string;
|
|
106
|
+
type: WireDocumentType;
|
|
107
|
+
number: string | null;
|
|
108
|
+
issuingAuthority: string | null;
|
|
109
|
+
issuingCountry: string | null;
|
|
110
|
+
issueDate: string | null;
|
|
111
|
+
expiryDate: string | null;
|
|
112
|
+
attachmentId: string | null;
|
|
113
|
+
isPrimary: boolean;
|
|
114
|
+
notes: string | null;
|
|
115
|
+
createdAt: string;
|
|
116
|
+
updatedAt: string;
|
|
117
|
+
} | null>;
|
|
118
|
+
deleteMyDocument(db: PostgresJsDatabase, userId: string, documentId: string): Promise<{
|
|
119
|
+
id: string;
|
|
120
|
+
} | null>;
|
|
121
|
+
setPrimaryMyDocument(db: PostgresJsDatabase, userId: string, documentId: string, options?: CustomerPortalServiceOptions): Promise<{
|
|
122
|
+
id: string;
|
|
123
|
+
type: WireDocumentType;
|
|
124
|
+
number: string | null;
|
|
125
|
+
issuingAuthority: string | null;
|
|
126
|
+
issuingCountry: string | null;
|
|
127
|
+
issueDate: string | null;
|
|
128
|
+
expiryDate: string | null;
|
|
129
|
+
attachmentId: string | null;
|
|
130
|
+
isPrimary: boolean;
|
|
131
|
+
notes: string | null;
|
|
132
|
+
createdAt: string;
|
|
133
|
+
updatedAt: string;
|
|
134
|
+
} | null>;
|
|
55
135
|
};
|
|
56
136
|
export {};
|
|
57
137
|
//# sourceMappingURL=service-public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"AAwBA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,kCAAkC,EAGlC,2BAA2B,EAK3B,4BAA4B,EAE5B,uBAAuB,EACvB,iCAAiC,EACjC,sCAAsC,EACtC,qBAAqB,EACrB,yCAAyC,EACzC,0CAA0C,EAE1C,kCAAkC,EAClC,gCAAgC,EACjC,MAAM,wBAAwB,CAAA;AAQ/B,UAAU,4BAA4B;IACpC,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,0BAA0B,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA;CAC5F;AAsGD,KAAK,gBAAgB,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,iBAAiB,GAAG,OAAO,CAAA;AAgwCrF,eAAO,MAAM,2BAA2B;sBAEhC,kBAAkB,SACf,MAAM,GACZ,OAAO,CAAC,iCAAiC,CAAC;2BAuBvC,kBAAkB,SACf,MAAM,GACZ,OAAO,CAAC,sCAAsC,CAAC;mBAa7B,kBAAkB,UAAU,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;8BAKzF,kBAAkB,UACd,MAAM,YACJ,4BAA4B,GACrC,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;sBAwDlC,kBAAkB,UACd,MAAM,SACP,gCAAgC,GACtC,OAAO,CACR;QAAE,OAAO,EAAE,qBAAqB,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,WAAW,GAAG,0BAA0B,CAAA;KAAE,CACzF;iCAKK,kBAAkB,UACd,MAAM,SACP,gCAAgC,YAC7B,4BAA4B,GACrC,OAAO,CACR;QAAE,OAAO,EAAE,qBAAqB,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,WAAW,GAAG,0BAA0B,CAAA;KAAE,CACzF;kBAwLK,kBAAkB,UACd,MAAM,SACP,4BAA4B,GAClC,OAAO,CACN,6BAA6B,GAC7B;QAAE,KAAK,EAAE,WAAW,GAAG,2BAA2B,GAAG,yBAAyB,CAAA;KAAE,CACnF;uBA0JwB,kBAAkB,UAAU,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC;2CAiB1F,kBAAkB,UACd,MAAM,SACP,yCAAyC,GAC/C,OAAO,CAAC,0CAA0C,GAAG,IAAI,CAAC;8CA2HvD,kBAAkB,UACd,MAAM,SACP,yCAAyC,GAC/C,OAAO,CAAC,0CAA0C,GAAG,IAAI,CAAC;wBAKvD,kBAAkB,UACd,MAAM,SACP,kCAAkC,GACxC,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;wBA2BpC,kBAAkB,UACd,MAAM,eACD,MAAM,SACZ,kCAAkC,GACxC,OAAO,CAAC,uBAAuB,GAAG,IAAI,GAAG,WAAW,CAAC;wBA2ClD,kBAAkB,UACd,MAAM,eACD,MAAM,GAClB,OAAO,CAAC,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;qBAyB3C,kBAAkB,UACd,MAAM,GACb,OAAO,CAAC,4BAA4B,EAAE,GAAG,IAAI,CAAC;mBAmG3C,kBAAkB,UACd,MAAM,aACH,MAAM,YACR,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC;6BA2BxC,kBAAkB,UACd,MAAM,aACH,MAAM,YACR,4BAA4B;;;;;;;;;;iCAMJ,kBAAkB,UAAU,MAAM,aAAa,MAAM;;;;;;;;;;;wBAiClF,kBAAkB,UACd,MAAM,YACJ,4BAA4B;;;;;;;;;;;;;;yBAMlC,kBAAkB,UACd,MAAM,SACP;QACL,IAAI,EAAE,gBAAgB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAChC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC5B,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACtB,YACS,4BAA4B;;;;;;;;;;;;;;yBA2BlC,kBAAkB,UACd,MAAM,cACF,MAAM,SACX;QACL,IAAI,CAAC,EAAE,gBAAgB,CAAA;QACvB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAChC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC5B,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACtB,YACS,4BAA4B;;;;;;;;;;;;;;yBA0Bb,kBAAkB,UAAU,MAAM,cAAc,MAAM;;;6BAW3E,kBAAkB,UACd,MAAM,cACF,MAAM,YACR,4BAA4B;;;;;;;;;;;;;;CAWzC,CAAA"}
|
package/dist/service-public.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { bookingDocuments, bookingFulfillments, bookingItems, bookingItemTravelers, bookingSessionStates, bookingStaffAssignments, bookings, bookingTravelers, } from "@voyantjs/bookings/schema";
|
|
2
|
-
import { crmService, people } from "@voyantjs/crm";
|
|
3
|
-
import { authUser,
|
|
2
|
+
import { crmService, people, personDocumentNumberPlaintextSchema, personPiiBlobPlaintextSchema, } from "@voyantjs/crm";
|
|
3
|
+
import { authUser, userProfilesTable } from "@voyantjs/db/schema/iam";
|
|
4
4
|
import { invoiceRenditions, invoices, payments } from "@voyantjs/finance/schema";
|
|
5
5
|
import { identityContactPoints } from "@voyantjs/identity/schema";
|
|
6
6
|
import { identityService } from "@voyantjs/identity/service";
|
|
@@ -82,11 +82,11 @@ function deriveMiddleName(fullName, firstName, lastName) {
|
|
|
82
82
|
}
|
|
83
83
|
return working.length > 0 ? working : null;
|
|
84
84
|
}
|
|
85
|
-
function
|
|
86
|
-
return type === "
|
|
85
|
+
function toCrmDocumentType(type) {
|
|
86
|
+
return type === "drivers_license" ? "driver_license" : type;
|
|
87
87
|
}
|
|
88
|
-
function
|
|
89
|
-
return type === "
|
|
88
|
+
function toWireDocumentType(type) {
|
|
89
|
+
return type === "driver_license" ? "drivers_license" : type;
|
|
90
90
|
}
|
|
91
91
|
function getMetadataRecord(value) {
|
|
92
92
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -517,7 +517,6 @@ async function getAuthProfileRow(db, userId) {
|
|
|
517
517
|
locale: userProfilesTable.locale,
|
|
518
518
|
timezone: userProfilesTable.timezone,
|
|
519
519
|
seatingPreference: userProfilesTable.seatingPreference,
|
|
520
|
-
documentsEncrypted: userProfilesTable.documentsEncrypted,
|
|
521
520
|
marketingConsent: userProfilesTable.marketingConsent,
|
|
522
521
|
marketingConsentAt: userProfilesTable.marketingConsentAt,
|
|
523
522
|
marketingConsentSource: userProfilesTable.marketingConsentSource,
|
|
@@ -530,20 +529,102 @@ async function getAuthProfileRow(db, userId) {
|
|
|
530
529
|
.limit(1);
|
|
531
530
|
return row ?? null;
|
|
532
531
|
}
|
|
533
|
-
async function
|
|
534
|
-
if (!
|
|
532
|
+
async function decryptProfileBlob(envelope, options) {
|
|
533
|
+
if (!envelope || !options?.kms) {
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
const decrypted = await decryptOptionalJsonEnvelope(options.kms, peopleKeyRef, envelope, personPiiBlobPlaintextSchema);
|
|
537
|
+
return decrypted?.text ?? null;
|
|
538
|
+
}
|
|
539
|
+
async function encryptProfileBlob(value, options) {
|
|
540
|
+
if (!options?.kms) {
|
|
541
|
+
return undefined;
|
|
542
|
+
}
|
|
543
|
+
if (value === null) {
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
return encryptOptionalJsonEnvelope(options.kms, peopleKeyRef, { text: value });
|
|
547
|
+
}
|
|
548
|
+
async function decryptDocumentNumber(envelope, options) {
|
|
549
|
+
if (!envelope || !options?.kms) {
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
const decrypted = await decryptOptionalJsonEnvelope(options.kms, peopleKeyRef, envelope, personDocumentNumberPlaintextSchema);
|
|
553
|
+
return decrypted?.number ?? null;
|
|
554
|
+
}
|
|
555
|
+
async function encryptDocumentNumber(value, options) {
|
|
556
|
+
if (!options?.kms) {
|
|
557
|
+
return undefined;
|
|
558
|
+
}
|
|
559
|
+
if (value == null) {
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
return encryptOptionalJsonEnvelope(options.kms, peopleKeyRef, { number: value });
|
|
563
|
+
}
|
|
564
|
+
async function projectPersonDocumentToWire(row, options) {
|
|
565
|
+
return {
|
|
566
|
+
id: row.id,
|
|
567
|
+
type: toWireDocumentType(row.type),
|
|
568
|
+
number: await decryptDocumentNumber(row.numberEncrypted, options),
|
|
569
|
+
issuingAuthority: row.issuingAuthority ?? null,
|
|
570
|
+
issuingCountry: row.issuingCountry ?? null,
|
|
571
|
+
issueDate: row.issueDate ?? null,
|
|
572
|
+
expiryDate: row.expiryDate ?? null,
|
|
573
|
+
attachmentId: row.attachmentId ?? null,
|
|
574
|
+
isPrimary: row.isPrimary,
|
|
575
|
+
notes: row.notes ?? null,
|
|
576
|
+
createdAt: row.createdAt instanceof Date ? row.createdAt.toISOString() : String(row.createdAt),
|
|
577
|
+
updatedAt: row.updatedAt instanceof Date ? row.updatedAt.toISOString() : String(row.updatedAt),
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
async function getLinkedPersonPiiRow(db, userId) {
|
|
581
|
+
const [row] = await db
|
|
582
|
+
.select({
|
|
583
|
+
id: people.id,
|
|
584
|
+
accessibilityEncrypted: people.accessibilityEncrypted,
|
|
585
|
+
dietaryEncrypted: people.dietaryEncrypted,
|
|
586
|
+
loyaltyEncrypted: people.loyaltyEncrypted,
|
|
587
|
+
insuranceEncrypted: people.insuranceEncrypted,
|
|
588
|
+
})
|
|
589
|
+
.from(people)
|
|
590
|
+
.where(and(eq(people.source, linkedCustomerSource), eq(people.sourceRef, userId)))
|
|
591
|
+
.limit(1);
|
|
592
|
+
return row ?? null;
|
|
593
|
+
}
|
|
594
|
+
async function getLinkedPersonDocuments(db, userId, options) {
|
|
595
|
+
const linked = await resolveLinkedCustomerRecordId(db, userId);
|
|
596
|
+
if (!linked) {
|
|
535
597
|
return [];
|
|
536
598
|
}
|
|
537
|
-
const
|
|
538
|
-
return
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
599
|
+
const rows = await crmService.listPersonDocuments(db, linked);
|
|
600
|
+
return Promise.all(rows.map((row) => projectPersonDocumentToWire(row, options)));
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Resolves the `crm.people` row linked to this auth user, creating
|
|
604
|
+
* it on first PII write if missing. The seed values mirror what the
|
|
605
|
+
* bootstrap path already produces — first/last name from the auth
|
|
606
|
+
* profile, source/sourceRef pinned to `auth.user`/`userId` so future
|
|
607
|
+
* reads find the same row.
|
|
608
|
+
*/
|
|
609
|
+
async function ensureLinkedPerson(db, userId, authProfile) {
|
|
610
|
+
const existing = await resolveLinkedCustomerRecordId(db, userId);
|
|
611
|
+
if (existing)
|
|
612
|
+
return existing;
|
|
613
|
+
const fallbackFirst = authProfile.firstName ?? authProfile.name.split(" ")[0]?.trim() ?? "Customer";
|
|
614
|
+
const fallbackLast = authProfile.lastName ?? (authProfile.name.split(" ").slice(1).join(" ").trim() || "");
|
|
615
|
+
const created = await crmService.createPerson(db, {
|
|
616
|
+
firstName: fallbackFirst,
|
|
617
|
+
lastName: fallbackLast,
|
|
618
|
+
tags: [],
|
|
619
|
+
status: "active",
|
|
620
|
+
source: linkedCustomerSource,
|
|
621
|
+
sourceRef: userId,
|
|
622
|
+
website: null,
|
|
623
|
+
});
|
|
624
|
+
if (!created) {
|
|
625
|
+
throw new Error("Failed to create linked customer record");
|
|
626
|
+
}
|
|
627
|
+
return created.id;
|
|
547
628
|
}
|
|
548
629
|
async function resolveLinkedCustomerRecordId(db, userId) {
|
|
549
630
|
const [row] = await db
|
|
@@ -962,7 +1043,13 @@ export const publicCustomerPortalService = {
|
|
|
962
1043
|
if (!authProfile) {
|
|
963
1044
|
return null;
|
|
964
1045
|
}
|
|
965
|
-
const
|
|
1046
|
+
const linkedPerson = await getLinkedPersonPiiRow(db, userId);
|
|
1047
|
+
const [accessibility, dietary, loyalty, insurance] = await Promise.all([
|
|
1048
|
+
decryptProfileBlob(linkedPerson?.accessibilityEncrypted, options),
|
|
1049
|
+
decryptProfileBlob(linkedPerson?.dietaryEncrypted, options),
|
|
1050
|
+
decryptProfileBlob(linkedPerson?.loyaltyEncrypted, options),
|
|
1051
|
+
decryptProfileBlob(linkedPerson?.insuranceEncrypted, options),
|
|
1052
|
+
]);
|
|
966
1053
|
const billingAddress = customerRecord?.billingAddress ?? null;
|
|
967
1054
|
return {
|
|
968
1055
|
userId: authProfile.id,
|
|
@@ -986,7 +1073,10 @@ export const publicCustomerPortalService = {
|
|
|
986
1073
|
addressLine2: billingAddress.line2,
|
|
987
1074
|
}
|
|
988
1075
|
: null,
|
|
989
|
-
|
|
1076
|
+
accessibility,
|
|
1077
|
+
dietary,
|
|
1078
|
+
loyalty,
|
|
1079
|
+
insurance,
|
|
990
1080
|
marketingConsent: authProfile.marketingConsent ?? false,
|
|
991
1081
|
marketingConsentAt: normalizeDateTime(authProfile.marketingConsentAt),
|
|
992
1082
|
marketingConsentSource: authProfile.marketingConsentSource ?? null,
|
|
@@ -1035,24 +1125,12 @@ export const publicCustomerPortalService = {
|
|
|
1035
1125
|
},
|
|
1036
1126
|
}
|
|
1037
1127
|
: undefined;
|
|
1038
|
-
const documentsEncrypted = input.documents !== undefined && options?.kms
|
|
1039
|
-
? await encryptOptionalJsonEnvelope(options.kms, peopleKeyRef, input.documents.map((document) => ({
|
|
1040
|
-
type: toStoredProfileDocumentType(document.type),
|
|
1041
|
-
number: document.number,
|
|
1042
|
-
issuingAuthority: document.issuingAuthority ?? undefined,
|
|
1043
|
-
issuingCountry: document.issuingCountry,
|
|
1044
|
-
nationality: document.nationality ?? undefined,
|
|
1045
|
-
expiryDate: document.expiryDate,
|
|
1046
|
-
issueDate: document.issueDate ?? undefined,
|
|
1047
|
-
})))
|
|
1048
|
-
: undefined;
|
|
1049
1128
|
await db
|
|
1050
1129
|
.insert(userProfilesTable)
|
|
1051
1130
|
.values({
|
|
1052
1131
|
id: userId,
|
|
1053
1132
|
firstName: nextFirstName,
|
|
1054
1133
|
lastName: nextLastName,
|
|
1055
|
-
...(documentsEncrypted !== undefined ? { documentsEncrypted } : {}),
|
|
1056
1134
|
avatarUrl: input.avatarUrl ?? authProfile.avatarUrl ?? authProfile.image ?? null,
|
|
1057
1135
|
locale: input.locale ?? authProfile.locale ?? "en",
|
|
1058
1136
|
timezone: input.timezone !== undefined ? input.timezone : (authProfile.timezone ?? null),
|
|
@@ -1074,7 +1152,6 @@ export const publicCustomerPortalService = {
|
|
|
1074
1152
|
set: {
|
|
1075
1153
|
firstName: nextFirstName,
|
|
1076
1154
|
lastName: nextLastName,
|
|
1077
|
-
...(documentsEncrypted !== undefined ? { documentsEncrypted } : {}),
|
|
1078
1155
|
avatarUrl: input.avatarUrl ?? authProfile.avatarUrl ?? authProfile.image ?? null,
|
|
1079
1156
|
locale: input.locale ?? authProfile.locale ?? "en",
|
|
1080
1157
|
timezone: input.timezone !== undefined ? input.timezone : (authProfile.timezone ?? null),
|
|
@@ -1093,6 +1170,34 @@ export const publicCustomerPortalService = {
|
|
|
1093
1170
|
updatedAt: new Date(),
|
|
1094
1171
|
},
|
|
1095
1172
|
});
|
|
1173
|
+
const piiUpdates = {};
|
|
1174
|
+
if (input.accessibility !== undefined) {
|
|
1175
|
+
const enc = await encryptProfileBlob(input.accessibility, options);
|
|
1176
|
+
if (enc !== undefined)
|
|
1177
|
+
piiUpdates.accessibilityEncrypted = enc;
|
|
1178
|
+
}
|
|
1179
|
+
if (input.dietary !== undefined) {
|
|
1180
|
+
const enc = await encryptProfileBlob(input.dietary, options);
|
|
1181
|
+
if (enc !== undefined)
|
|
1182
|
+
piiUpdates.dietaryEncrypted = enc;
|
|
1183
|
+
}
|
|
1184
|
+
if (input.loyalty !== undefined) {
|
|
1185
|
+
const enc = await encryptProfileBlob(input.loyalty, options);
|
|
1186
|
+
if (enc !== undefined)
|
|
1187
|
+
piiUpdates.loyaltyEncrypted = enc;
|
|
1188
|
+
}
|
|
1189
|
+
if (input.insurance !== undefined) {
|
|
1190
|
+
const enc = await encryptProfileBlob(input.insurance, options);
|
|
1191
|
+
if (enc !== undefined)
|
|
1192
|
+
piiUpdates.insuranceEncrypted = enc;
|
|
1193
|
+
}
|
|
1194
|
+
if (Object.keys(piiUpdates).length > 0) {
|
|
1195
|
+
const personId = await ensureLinkedPerson(db, userId, authProfile);
|
|
1196
|
+
await db
|
|
1197
|
+
.update(people)
|
|
1198
|
+
.set({ ...piiUpdates, updatedAt: new Date() })
|
|
1199
|
+
.where(eq(people.id, personId));
|
|
1200
|
+
}
|
|
1096
1201
|
await db
|
|
1097
1202
|
.update(authUser)
|
|
1098
1203
|
.set({
|
|
@@ -1585,4 +1690,83 @@ export const publicCustomerPortalService = {
|
|
|
1585
1690
|
}
|
|
1586
1691
|
return getBookingBillingContact(db, bookingId, customerRecord);
|
|
1587
1692
|
},
|
|
1693
|
+
// ── Identity documents ────────────────────────────────────────────────
|
|
1694
|
+
// CRUD over `crm.person_documents` scoped to the auth user's linked
|
|
1695
|
+
// person. Auto-creates the linked person row on first write so
|
|
1696
|
+
// phone-only / metadata-light customers can save documents without
|
|
1697
|
+
// a separate bootstrap step.
|
|
1698
|
+
async listMyDocuments(db, userId, options) {
|
|
1699
|
+
return getLinkedPersonDocuments(db, userId, options);
|
|
1700
|
+
},
|
|
1701
|
+
async createMyDocument(db, userId, input, options) {
|
|
1702
|
+
const authProfile = await getAuthProfileRow(db, userId);
|
|
1703
|
+
if (!authProfile)
|
|
1704
|
+
return null;
|
|
1705
|
+
const personId = await ensureLinkedPerson(db, userId, authProfile);
|
|
1706
|
+
const numberEncrypted = await encryptDocumentNumber(input.number ?? null, options);
|
|
1707
|
+
const payload = {
|
|
1708
|
+
type: toCrmDocumentType(input.type),
|
|
1709
|
+
issuingAuthority: input.issuingAuthority ?? null,
|
|
1710
|
+
issuingCountry: input.issuingCountry ?? null,
|
|
1711
|
+
issueDate: input.issueDate ?? null,
|
|
1712
|
+
expiryDate: input.expiryDate ?? null,
|
|
1713
|
+
attachmentId: input.attachmentId ?? null,
|
|
1714
|
+
isPrimary: input.isPrimary ?? false,
|
|
1715
|
+
notes: input.notes ?? null,
|
|
1716
|
+
};
|
|
1717
|
+
if (numberEncrypted !== undefined) {
|
|
1718
|
+
payload.numberEncrypted = numberEncrypted;
|
|
1719
|
+
}
|
|
1720
|
+
const row = await crmService.createPersonDocument(db, personId, payload);
|
|
1721
|
+
return row ? projectPersonDocumentToWire(row, options) : null;
|
|
1722
|
+
},
|
|
1723
|
+
async updateMyDocument(db, userId, documentId, input, options) {
|
|
1724
|
+
const linkedPersonId = await resolveLinkedCustomerRecordId(db, userId);
|
|
1725
|
+
if (!linkedPersonId)
|
|
1726
|
+
return null;
|
|
1727
|
+
const existing = await crmService.getPersonDocument(db, documentId);
|
|
1728
|
+
if (!existing || existing.personId !== linkedPersonId)
|
|
1729
|
+
return null;
|
|
1730
|
+
const numberEncrypted = input.number !== undefined ? await encryptDocumentNumber(input.number, options) : undefined;
|
|
1731
|
+
const update = {};
|
|
1732
|
+
if (input.type !== undefined)
|
|
1733
|
+
update.type = toCrmDocumentType(input.type);
|
|
1734
|
+
if (input.issuingAuthority !== undefined)
|
|
1735
|
+
update.issuingAuthority = input.issuingAuthority;
|
|
1736
|
+
if (input.issuingCountry !== undefined)
|
|
1737
|
+
update.issuingCountry = input.issuingCountry;
|
|
1738
|
+
if (input.issueDate !== undefined)
|
|
1739
|
+
update.issueDate = input.issueDate;
|
|
1740
|
+
if (input.expiryDate !== undefined)
|
|
1741
|
+
update.expiryDate = input.expiryDate;
|
|
1742
|
+
if (input.attachmentId !== undefined)
|
|
1743
|
+
update.attachmentId = input.attachmentId;
|
|
1744
|
+
if (input.isPrimary !== undefined)
|
|
1745
|
+
update.isPrimary = input.isPrimary;
|
|
1746
|
+
if (input.notes !== undefined)
|
|
1747
|
+
update.notes = input.notes;
|
|
1748
|
+
if (numberEncrypted !== undefined)
|
|
1749
|
+
update.numberEncrypted = numberEncrypted;
|
|
1750
|
+
const row = await crmService.updatePersonDocument(db, documentId, update);
|
|
1751
|
+
return row ? projectPersonDocumentToWire(row, options) : null;
|
|
1752
|
+
},
|
|
1753
|
+
async deleteMyDocument(db, userId, documentId) {
|
|
1754
|
+
const linkedPersonId = await resolveLinkedCustomerRecordId(db, userId);
|
|
1755
|
+
if (!linkedPersonId)
|
|
1756
|
+
return null;
|
|
1757
|
+
const existing = await crmService.getPersonDocument(db, documentId);
|
|
1758
|
+
if (!existing || existing.personId !== linkedPersonId)
|
|
1759
|
+
return null;
|
|
1760
|
+
return crmService.deletePersonDocument(db, documentId);
|
|
1761
|
+
},
|
|
1762
|
+
async setPrimaryMyDocument(db, userId, documentId, options) {
|
|
1763
|
+
const linkedPersonId = await resolveLinkedCustomerRecordId(db, userId);
|
|
1764
|
+
if (!linkedPersonId)
|
|
1765
|
+
return null;
|
|
1766
|
+
const existing = await crmService.getPersonDocument(db, documentId);
|
|
1767
|
+
if (!existing || existing.personId !== linkedPersonId)
|
|
1768
|
+
return null;
|
|
1769
|
+
const row = await crmService.setPrimaryPersonDocument(db, documentId);
|
|
1770
|
+
return row ? projectPersonDocumentToWire(row, options) : null;
|
|
1771
|
+
},
|
|
1588
1772
|
};
|
|
@@ -133,21 +133,10 @@ export declare const customerPortalProfileSchema: z.ZodObject<{
|
|
|
133
133
|
addressLine1: z.ZodNullable<z.ZodString>;
|
|
134
134
|
addressLine2: z.ZodNullable<z.ZodString>;
|
|
135
135
|
}, z.core.$strip>>;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
drivers_license: "drivers_license";
|
|
141
|
-
other: "other";
|
|
142
|
-
id_card: "id_card";
|
|
143
|
-
}>;
|
|
144
|
-
number: z.ZodString;
|
|
145
|
-
issuingAuthority: z.ZodNullable<z.ZodString>;
|
|
146
|
-
issuingCountry: z.ZodString;
|
|
147
|
-
nationality: z.ZodNullable<z.ZodString>;
|
|
148
|
-
expiryDate: z.ZodString;
|
|
149
|
-
issueDate: z.ZodNullable<z.ZodString>;
|
|
150
|
-
}, z.core.$strip>>;
|
|
136
|
+
accessibility: z.ZodNullable<z.ZodString>;
|
|
137
|
+
dietary: z.ZodNullable<z.ZodString>;
|
|
138
|
+
loyalty: z.ZodNullable<z.ZodString>;
|
|
139
|
+
insurance: z.ZodNullable<z.ZodString>;
|
|
151
140
|
marketingConsent: z.ZodBoolean;
|
|
152
141
|
marketingConsentAt: z.ZodNullable<z.ZodString>;
|
|
153
142
|
marketingConsentSource: z.ZodNullable<z.ZodString>;
|
|
@@ -235,21 +224,10 @@ export declare const updateCustomerPortalProfileSchema: z.ZodObject<{
|
|
|
235
224
|
addressLine1: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
236
225
|
addressLine2: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
237
226
|
}, z.core.$strip>>;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
drivers_license: "drivers_license";
|
|
243
|
-
other: "other";
|
|
244
|
-
id_card: "id_card";
|
|
245
|
-
}>;
|
|
246
|
-
number: z.ZodString;
|
|
247
|
-
issuingAuthority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
248
|
-
issuingCountry: z.ZodString;
|
|
249
|
-
nationality: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
250
|
-
expiryDate: z.ZodString;
|
|
251
|
-
issueDate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
252
|
-
}, z.core.$strip>>>;
|
|
227
|
+
accessibility: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
228
|
+
dietary: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
229
|
+
loyalty: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
230
|
+
insurance: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
253
231
|
marketingConsent: z.ZodOptional<z.ZodBoolean>;
|
|
254
232
|
marketingConsentSource: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
255
233
|
notificationDefaults: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
@@ -281,6 +259,64 @@ export declare const updateCustomerPortalProfileSchema: z.ZodObject<{
|
|
|
281
259
|
}, z.core.$strip>>;
|
|
282
260
|
}, z.core.$strip>>;
|
|
283
261
|
}, z.core.$strip>;
|
|
262
|
+
/**
|
|
263
|
+
* Per-document shape exposed by `/me/documents`. Plaintext on the
|
|
264
|
+
* wire — server encrypts/decrypts `number` against the people KMS key.
|
|
265
|
+
*/
|
|
266
|
+
export declare const customerPortalProfileDocumentSchema: z.ZodObject<{
|
|
267
|
+
id: z.ZodString;
|
|
268
|
+
type: z.ZodEnum<{
|
|
269
|
+
passport: "passport";
|
|
270
|
+
visa: "visa";
|
|
271
|
+
drivers_license: "drivers_license";
|
|
272
|
+
other: "other";
|
|
273
|
+
id_card: "id_card";
|
|
274
|
+
}>;
|
|
275
|
+
number: z.ZodNullable<z.ZodString>;
|
|
276
|
+
issuingAuthority: z.ZodNullable<z.ZodString>;
|
|
277
|
+
issuingCountry: z.ZodNullable<z.ZodString>;
|
|
278
|
+
issueDate: z.ZodNullable<z.ZodString>;
|
|
279
|
+
expiryDate: z.ZodNullable<z.ZodString>;
|
|
280
|
+
attachmentId: z.ZodNullable<z.ZodString>;
|
|
281
|
+
isPrimary: z.ZodBoolean;
|
|
282
|
+
notes: z.ZodNullable<z.ZodString>;
|
|
283
|
+
createdAt: z.ZodString;
|
|
284
|
+
updatedAt: z.ZodString;
|
|
285
|
+
}, z.core.$strip>;
|
|
286
|
+
export declare const createCustomerPortalProfileDocumentSchema: z.ZodObject<{
|
|
287
|
+
type: z.ZodEnum<{
|
|
288
|
+
passport: "passport";
|
|
289
|
+
visa: "visa";
|
|
290
|
+
drivers_license: "drivers_license";
|
|
291
|
+
other: "other";
|
|
292
|
+
id_card: "id_card";
|
|
293
|
+
}>;
|
|
294
|
+
number: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
295
|
+
issuingAuthority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
296
|
+
issuingCountry: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
297
|
+
issueDate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
298
|
+
expiryDate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
299
|
+
attachmentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
300
|
+
isPrimary: z.ZodOptional<z.ZodBoolean>;
|
|
301
|
+
notes: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
302
|
+
}, z.core.$strip>;
|
|
303
|
+
export declare const updateCustomerPortalProfileDocumentSchema: z.ZodObject<{
|
|
304
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
305
|
+
passport: "passport";
|
|
306
|
+
visa: "visa";
|
|
307
|
+
drivers_license: "drivers_license";
|
|
308
|
+
other: "other";
|
|
309
|
+
id_card: "id_card";
|
|
310
|
+
}>>;
|
|
311
|
+
number: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
312
|
+
issuingAuthority: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
313
|
+
issuingCountry: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
314
|
+
issueDate: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
315
|
+
expiryDate: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
316
|
+
attachmentId: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
317
|
+
isPrimary: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
318
|
+
notes: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
319
|
+
}, z.core.$strip>;
|
|
284
320
|
export declare const customerPortalContactExistsQuerySchema: z.ZodObject<{
|
|
285
321
|
email: z.ZodString;
|
|
286
322
|
}, z.core.$strip>;
|
|
@@ -364,21 +400,10 @@ export declare const bootstrapCustomerPortalResultSchema: z.ZodObject<{
|
|
|
364
400
|
addressLine1: z.ZodNullable<z.ZodString>;
|
|
365
401
|
addressLine2: z.ZodNullable<z.ZodString>;
|
|
366
402
|
}, z.core.$strip>>;
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
drivers_license: "drivers_license";
|
|
372
|
-
other: "other";
|
|
373
|
-
id_card: "id_card";
|
|
374
|
-
}>;
|
|
375
|
-
number: z.ZodString;
|
|
376
|
-
issuingAuthority: z.ZodNullable<z.ZodString>;
|
|
377
|
-
issuingCountry: z.ZodString;
|
|
378
|
-
nationality: z.ZodNullable<z.ZodString>;
|
|
379
|
-
expiryDate: z.ZodString;
|
|
380
|
-
issueDate: z.ZodNullable<z.ZodString>;
|
|
381
|
-
}, z.core.$strip>>;
|
|
403
|
+
accessibility: z.ZodNullable<z.ZodString>;
|
|
404
|
+
dietary: z.ZodNullable<z.ZodString>;
|
|
405
|
+
loyalty: z.ZodNullable<z.ZodString>;
|
|
406
|
+
insurance: z.ZodNullable<z.ZodString>;
|
|
382
407
|
marketingConsent: z.ZodBoolean;
|
|
383
408
|
marketingConsentAt: z.ZodNullable<z.ZodString>;
|
|
384
409
|
marketingConsentSource: z.ZodNullable<z.ZodString>;
|
|
@@ -1235,6 +1260,9 @@ export declare const customerPortalBookingDetailSchema: z.ZodObject<{
|
|
|
1235
1260
|
}, z.core.$strip>;
|
|
1236
1261
|
export type CustomerPortalProfile = z.infer<typeof customerPortalProfileSchema>;
|
|
1237
1262
|
export type UpdateCustomerPortalProfileInput = z.infer<typeof updateCustomerPortalProfileSchema>;
|
|
1263
|
+
export type CustomerPortalProfileDocument = z.infer<typeof customerPortalProfileDocumentSchema>;
|
|
1264
|
+
export type CreateCustomerPortalProfileDocumentInput = z.infer<typeof createCustomerPortalProfileDocumentSchema>;
|
|
1265
|
+
export type UpdateCustomerPortalProfileDocumentInput = z.infer<typeof updateCustomerPortalProfileDocumentSchema>;
|
|
1238
1266
|
export type CustomerPortalContactExistsQuery = z.infer<typeof customerPortalContactExistsQuerySchema>;
|
|
1239
1267
|
export type CustomerPortalContactExistsResult = z.infer<typeof customerPortalContactExistsResultSchema>;
|
|
1240
1268
|
export type CustomerPortalPhoneContactExistsQuery = z.infer<typeof customerPortalPhoneContactExistsQuerySchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-public.d.ts","sourceRoot":"","sources":["../src/validation-public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAgJvB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;iBAWtC,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;iBAc1C,CAAA;AAEJ,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYrC,CAAA;AAEF,eAAO,MAAM,sCAAsC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGjD,CAAA;AAEF,eAAO,MAAM,2BAA2B
|
|
1
|
+
{"version":3,"file":"validation-public.d.ts","sourceRoot":"","sources":["../src/validation-public.ts"],"names":[],"mappings":"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"}
|