@bizmap/sdk 0.0.92 → 0.0.94
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/main.d.ts +134 -238
- package/dist/main.js +230 -178
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -21,15 +21,19 @@ var healthcareProviderRoles = companyUserRoles.extract([
|
|
|
21
21
|
]);
|
|
22
22
|
var appointmentDistAlgs = z.enum(["RR", "LOR"]);
|
|
23
23
|
var companyServiceSelectors = z.enum(["scheduler", "doctor"]);
|
|
24
|
-
var
|
|
24
|
+
var industries = z.enum([
|
|
25
|
+
"healthcare"
|
|
26
|
+
// "Pharmaceutical",
|
|
27
|
+
]);
|
|
25
28
|
var companyUserStatus = z.enum(["inviteSent", "active", "inactive"]);
|
|
26
29
|
|
|
27
30
|
// src/enums/Global.ts
|
|
31
|
+
import { currencies } from "@wavy/util";
|
|
28
32
|
import * as z2 from "zod";
|
|
29
33
|
var tiers = z2.enum(["basic", "pro", "premium", "gold"]);
|
|
30
34
|
var paymentMethods = z2.enum(["cash", "card", "insurance"]);
|
|
31
35
|
var genders = z2.enum(["male", "female"]);
|
|
32
|
-
var
|
|
36
|
+
var acceptedCurrencies = currencies.extract(["JMD"]);
|
|
33
37
|
|
|
34
38
|
// src/enums/Medical.ts
|
|
35
39
|
import * as z3 from "zod";
|
|
@@ -47,17 +51,16 @@ var serviceProviders = z4.enum([
|
|
|
47
51
|
"scheduler",
|
|
48
52
|
"doctor",
|
|
49
53
|
"physAsst",
|
|
50
|
-
"
|
|
54
|
+
"debtCollector"
|
|
51
55
|
]);
|
|
52
56
|
|
|
53
57
|
// src/schemas/company/CompanyDetails.ts
|
|
54
|
-
import * as
|
|
58
|
+
import * as z17 from "zod";
|
|
55
59
|
|
|
56
60
|
// src/schemas/company/components/Billing.ts
|
|
57
61
|
import * as z8 from "zod";
|
|
58
62
|
|
|
59
63
|
// src/schemas/utils/billing.ts
|
|
60
|
-
import { currencies } from "@wavy/util";
|
|
61
64
|
import * as z6 from "zod";
|
|
62
65
|
|
|
63
66
|
// src/schemas/utils/core.ts
|
|
@@ -95,13 +98,25 @@ var Reason = z5.object({
|
|
|
95
98
|
lastModified: Timestamp
|
|
96
99
|
});
|
|
97
100
|
var Version = z5.int().min(1);
|
|
101
|
+
var AlphaNumeric = z5.string().trim().superRefine((data, ctx) => {
|
|
102
|
+
const invalidCharIdx = data.search(/[^a-z0-9]/i);
|
|
103
|
+
if (invalidCharIdx > -1) {
|
|
104
|
+
const char = `"'`.includes(data[invalidCharIdx]) ? `(${data[invalidCharIdx]})` : `"${data[invalidCharIdx]}"`;
|
|
105
|
+
ctx.addIssue(`${char} is not an alpha-numeric character.`);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
98
108
|
|
|
99
109
|
// src/schemas/utils/billing.ts
|
|
100
110
|
var PriceAdjustment = z6.object({
|
|
101
|
-
description: z6.string().trim().min(3, "A description must have atleast (3) characters.").max(25, "A description can't have more that (25) characters.").
|
|
111
|
+
description: z6.string().trim().min(3, "A description must have atleast (3) characters.").max(25, "A description can't have more that (25) characters.").superRefine((data, ctx) => {
|
|
112
|
+
const invalidCharIdx = data.search(/[^a-zA-Z0-9-\.:\(\)]/);
|
|
113
|
+
if (invalidCharIdx > -1) {
|
|
114
|
+
ctx.addIssue("");
|
|
115
|
+
}
|
|
116
|
+
}),
|
|
102
117
|
fixedAmount: z6.object({
|
|
103
118
|
value: z6.number().min(0).max(1e6, "The max fixed amount is $1,000,000.00"),
|
|
104
|
-
currency:
|
|
119
|
+
currency: acceptedCurrencies
|
|
105
120
|
}),
|
|
106
121
|
percentage: z6.number().min(0).max(1e3, "The max percentage is 1,000%"),
|
|
107
122
|
isOptional: z6.boolean(),
|
|
@@ -112,7 +127,7 @@ var PriceTag = z6.object({
|
|
|
112
127
|
/**The name of the item that's being priced */
|
|
113
128
|
item: z6.string().trim().min(3, "The price item must be atleast (3) characters long.").max(50, "The price item can't be more than (50) characters long."),
|
|
114
129
|
cost: z6.number().min(1, "The minimum allowed cost is $1.00").max(1e9, "The max allowed cost is $1,000,000,000.00."),
|
|
115
|
-
currency:
|
|
130
|
+
currency: acceptedCurrencies,
|
|
116
131
|
...TimeLog.shape
|
|
117
132
|
});
|
|
118
133
|
var Receipts = z6.array(
|
|
@@ -220,7 +235,7 @@ var CompanyIdentity = z9.object({
|
|
|
220
235
|
}),
|
|
221
236
|
address: Address.optional(),
|
|
222
237
|
logo: z9.string().nullish(),
|
|
223
|
-
|
|
238
|
+
industry: industries.readonly(),
|
|
224
239
|
contact: z9.object({
|
|
225
240
|
email: z9.email().max(25),
|
|
226
241
|
phoneNumber: PhoneNumber.optional(),
|
|
@@ -260,7 +275,6 @@ var MutableCompanyIdentity = CompanyIdentity.pick({
|
|
|
260
275
|
import * as z11 from "zod";
|
|
261
276
|
|
|
262
277
|
// src/schemas/Global.ts
|
|
263
|
-
import { currencies as currencies2 } from "@wavy/util";
|
|
264
278
|
import * as z10 from "zod";
|
|
265
279
|
|
|
266
280
|
// src/constants.ts
|
|
@@ -355,10 +369,20 @@ var Notification = z10.object({
|
|
|
355
369
|
});
|
|
356
370
|
var CreditCurrency = z10.object({
|
|
357
371
|
uid: z10.uuidv4(),
|
|
358
|
-
cost: z10.object({ value: z10.number().min(0), currency:
|
|
372
|
+
cost: z10.object({ value: z10.number().min(0), currency: acceptedCurrencies }),
|
|
359
373
|
value: z10.int().min(0),
|
|
360
374
|
...TimeLog.shape
|
|
361
375
|
});
|
|
376
|
+
var PaymentDetails = z10.object({
|
|
377
|
+
// Used to track the payments recorded by each paymentCollector
|
|
378
|
+
uid: z10.uuidv4(),
|
|
379
|
+
method: paymentMethods,
|
|
380
|
+
currency: acceptedCurrencies,
|
|
381
|
+
amount: z10.number().min(1),
|
|
382
|
+
// Rate chart id (used to identify the rate chart used to convert the amount )
|
|
383
|
+
// rcid: z.uuidv4(),
|
|
384
|
+
...TimeLog.shape
|
|
385
|
+
});
|
|
362
386
|
|
|
363
387
|
// src/schemas/company/components/Notifications.ts
|
|
364
388
|
var CompanyNotifications = z11.array(Notification).refine(
|
|
@@ -395,13 +419,104 @@ var MutableCompanyPreferences = CompanyPreferences.omit({
|
|
|
395
419
|
});
|
|
396
420
|
|
|
397
421
|
// src/schemas/company/components/Staff.ts
|
|
398
|
-
import * as
|
|
422
|
+
import * as z16 from "zod";
|
|
399
423
|
|
|
400
424
|
// src/schemas/company/components/User.ts
|
|
401
|
-
import * as
|
|
425
|
+
import * as z15 from "zod";
|
|
402
426
|
|
|
403
427
|
// src/functions/helper-functions.ts
|
|
404
428
|
import { camelCaseToLetter, upperFirst as upperFirst2 } from "@wavy/fn";
|
|
429
|
+
|
|
430
|
+
// src/schemas/profiles/Client.ts
|
|
431
|
+
import * as z14 from "zod";
|
|
432
|
+
|
|
433
|
+
// src/schemas/profiles/User.ts
|
|
434
|
+
import { UserModel } from "@wavy/util";
|
|
435
|
+
import * as z13 from "zod";
|
|
436
|
+
var UserDetails = z13.object({
|
|
437
|
+
...UserModel.shape,
|
|
438
|
+
_id: z13.uuidv4(),
|
|
439
|
+
name: z13.string().transform((data) => {
|
|
440
|
+
const [firstName = "", lastName = ""] = data.split(" ");
|
|
441
|
+
return (firstName + " " + lastName).trim();
|
|
442
|
+
}).superRefine((data, ctx) => {
|
|
443
|
+
data.split(" ").forEach((name, idx) => {
|
|
444
|
+
const nty = idx === 0 ? "First" : "Last";
|
|
445
|
+
if (idx === 0 && name.length < 2) {
|
|
446
|
+
ctx.addIssue(`${nty} name must have at least (2) characters.`);
|
|
447
|
+
}
|
|
448
|
+
if (name.length > MAX_NAME_LENGTH) {
|
|
449
|
+
ctx.addIssue(`${nty} name can't have more than (${MAX_NAME_LENGTH}) characters.`);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}),
|
|
453
|
+
email: UserModel.shape.email,
|
|
454
|
+
publicKey: z13.string().nullable(),
|
|
455
|
+
notifications: z13.array(Notification),
|
|
456
|
+
version: Version,
|
|
457
|
+
companyUids: z13.array(CompanyState.shape._id).min(1).optional(),
|
|
458
|
+
resumeToken: z13.uuidv4().optional(),
|
|
459
|
+
...TimeLog.shape
|
|
460
|
+
}).omit({ uid: true });
|
|
461
|
+
|
|
462
|
+
// src/schemas/profiles/Client.ts
|
|
463
|
+
import { Address as Address2 } from "@wavy/util";
|
|
464
|
+
var Name = z14.string().trim().min(2).max(MAX_NAME_LENGTH).transform((d) => d.replace(/-+/g, "-").replace(/'+/g, "'")).superRefine((data, ctx) => {
|
|
465
|
+
const invalidCharIdx = data.search(/[^a-z'-]/i);
|
|
466
|
+
if (invalidCharIdx >= 0) {
|
|
467
|
+
const char = data[invalidCharIdx].includes('"') ? `(${data[invalidCharIdx]})` : `"${data[invalidCharIdx]}"`;
|
|
468
|
+
ctx.addIssue(`${char} is not an allowed character.`);
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
var ClientIdentity = UserDetails.pick({
|
|
472
|
+
_id: true,
|
|
473
|
+
createdAt: true,
|
|
474
|
+
lastModified: true,
|
|
475
|
+
phoneNumber: true,
|
|
476
|
+
version: true,
|
|
477
|
+
photoUrl: true
|
|
478
|
+
}).safeExtend(
|
|
479
|
+
z14.object({
|
|
480
|
+
firstName: Name,
|
|
481
|
+
middleName: Name,
|
|
482
|
+
lastName: Name,
|
|
483
|
+
email: UserDetails.shape.email.optional(),
|
|
484
|
+
dob: Timestamp,
|
|
485
|
+
sex: genders,
|
|
486
|
+
isGlobal: z14.boolean(),
|
|
487
|
+
origin: CompanyIdentity.shape._id,
|
|
488
|
+
// aka. National id
|
|
489
|
+
nid: z14.object({
|
|
490
|
+
trn: Trn,
|
|
491
|
+
nin: AlphaNumeric.toLowerCase().min(5).max(20),
|
|
492
|
+
passportNo: AlphaNumeric.toLowerCase().min(5).max(15)
|
|
493
|
+
}).partial().optional(),
|
|
494
|
+
// Don't hash the attributes, they can be used to help accurately identify a client by whoever is searching for
|
|
495
|
+
// the client
|
|
496
|
+
attributes: z14.object({
|
|
497
|
+
motherMaidenName: Name,
|
|
498
|
+
fatherMiddleName: Name,
|
|
499
|
+
motherMiddleName: Name,
|
|
500
|
+
oldestSiblingMiddleName: Name,
|
|
501
|
+
firstSchoolName: z14.string().trim().min(3).max(60)
|
|
502
|
+
// nickname: z.string().trim().min(1).max(40),
|
|
503
|
+
}).partial().refine(
|
|
504
|
+
(data) => Object.keys(data).length > 0,
|
|
505
|
+
"At least (1) attribute must be defined."
|
|
506
|
+
),
|
|
507
|
+
address: Address2.optional(),
|
|
508
|
+
linkedTo: UserDetails.shape._id.optional()
|
|
509
|
+
}).shape
|
|
510
|
+
);
|
|
511
|
+
var ClientForm = ClientIdentity.pick({
|
|
512
|
+
firstName: true,
|
|
513
|
+
middleName: true,
|
|
514
|
+
lastName: true,
|
|
515
|
+
dob: true,
|
|
516
|
+
sex: true
|
|
517
|
+
}).required();
|
|
518
|
+
|
|
519
|
+
// src/functions/helper-functions.ts
|
|
405
520
|
var findConflictingPartners = (...partners) => {
|
|
406
521
|
let hasSingleDoctor = false;
|
|
407
522
|
const conflicts = [];
|
|
@@ -434,8 +549,8 @@ var getCompatibleRoles = (role) => {
|
|
|
434
549
|
var normalizeCompanyId = (id) => {
|
|
435
550
|
return id.split("-").map((value) => upperFirst2(value.toLowerCase())).join(" ");
|
|
436
551
|
};
|
|
437
|
-
var
|
|
438
|
-
value =
|
|
552
|
+
var normalizeNidKey = (value) => {
|
|
553
|
+
value = ClientIdentity.shape.nid.unwrap().keyof().parse(value);
|
|
439
554
|
if (value === "nin") return "National Id No.";
|
|
440
555
|
if (value === "trn") return "Tax Registration No.";
|
|
441
556
|
return camelCaseToLetter(value.replace("No", "No."));
|
|
@@ -446,51 +561,22 @@ var parseClientName = ({
|
|
|
446
561
|
lastName
|
|
447
562
|
}) => [firstName, middleName[0] + ".", lastName].join(" ");
|
|
448
563
|
|
|
449
|
-
// src/schemas/profiles/User.ts
|
|
450
|
-
import { UserModel } from "@wavy/util";
|
|
451
|
-
import * as z13 from "zod";
|
|
452
|
-
var UserDetails = z13.object({
|
|
453
|
-
...UserModel.shape,
|
|
454
|
-
_id: z13.uuidv4(),
|
|
455
|
-
name: z13.string().transform((data) => {
|
|
456
|
-
const [firstName = "", lastName = ""] = data.split(" ");
|
|
457
|
-
return (firstName + " " + lastName).trim();
|
|
458
|
-
}).superRefine((data, ctx) => {
|
|
459
|
-
data.split(" ").forEach((name, idx) => {
|
|
460
|
-
const nty = idx === 0 ? "First" : "Last";
|
|
461
|
-
if (idx === 0 && name.length < 2) {
|
|
462
|
-
ctx.addIssue(`${nty} name must have at least (2) characters.`);
|
|
463
|
-
}
|
|
464
|
-
if (name.length > MAX_NAME_LENGTH) {
|
|
465
|
-
ctx.addIssue(`${nty} name can't have more than (${MAX_NAME_LENGTH}) characters.`);
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
}),
|
|
469
|
-
email: UserModel.shape.email,
|
|
470
|
-
publicKey: z13.string().nullable(),
|
|
471
|
-
notifications: z13.array(Notification),
|
|
472
|
-
version: Version,
|
|
473
|
-
companyUids: z13.array(CompanyState.shape._id).min(1).optional(),
|
|
474
|
-
resumeToken: z13.uuidv4().optional(),
|
|
475
|
-
...TimeLog.shape
|
|
476
|
-
}).omit({ uid: true });
|
|
477
|
-
|
|
478
564
|
// src/schemas/company/components/User.ts
|
|
479
|
-
var CompanyUserSession =
|
|
480
|
-
_id:
|
|
565
|
+
var CompanyUserSession = z15.object({
|
|
566
|
+
_id: z15.uuidv4(),
|
|
481
567
|
user: UserDetails.pick({ _id: true, name: true, email: true }),
|
|
482
568
|
companyId: CompanyState.shape._id,
|
|
483
|
-
deviceId:
|
|
484
|
-
isAvailable:
|
|
485
|
-
value:
|
|
569
|
+
deviceId: z15.string().trim().min(15),
|
|
570
|
+
isAvailable: z15.object({
|
|
571
|
+
value: z15.boolean(),
|
|
486
572
|
lastModified: Timestamp.nullable()
|
|
487
573
|
}),
|
|
488
|
-
isBusy:
|
|
489
|
-
value:
|
|
574
|
+
isBusy: z15.object({
|
|
575
|
+
value: z15.boolean(),
|
|
490
576
|
lastModified: Timestamp.nullable()
|
|
491
577
|
}),
|
|
492
|
-
appointments:
|
|
493
|
-
roles:
|
|
578
|
+
appointments: z15.record(z15.literal(["ongoing", "completed"]), z15.int().min(0)),
|
|
579
|
+
roles: z15.array(companyUserRoles).transform((roles) => {
|
|
494
580
|
const newRoles = [];
|
|
495
581
|
for (const role of roles) {
|
|
496
582
|
if (!!role && !newRoles.includes(role)) newRoles.push(role);
|
|
@@ -501,11 +587,11 @@ var CompanyUserSession = z14.object({
|
|
|
501
587
|
(role, i) => i === 0 || getCompatibleRoles(roles[0]).includes(role)
|
|
502
588
|
);
|
|
503
589
|
}, "A user is not allowed to have conflicting roles."),
|
|
504
|
-
ttl:
|
|
590
|
+
ttl: z15.number(),
|
|
505
591
|
lastModified: Timestamp.nullable(),
|
|
506
|
-
expiresAfter:
|
|
592
|
+
expiresAfter: z15.date()
|
|
507
593
|
});
|
|
508
|
-
var MiniCompanyUser2 =
|
|
594
|
+
var MiniCompanyUser2 = z15.object({
|
|
509
595
|
_id: UserDetails.shape._id,
|
|
510
596
|
...CompanyUserSession.pick({
|
|
511
597
|
roles: true,
|
|
@@ -519,7 +605,7 @@ var MiniCompanyUser2 = z14.object({
|
|
|
519
605
|
inviteSent: Timestamp.nullish(),
|
|
520
606
|
inviteAccepted: Timestamp.nullable()
|
|
521
607
|
});
|
|
522
|
-
var CompanyUser =
|
|
608
|
+
var CompanyUser = z15.object({
|
|
523
609
|
...MiniCompanyUser2.shape,
|
|
524
610
|
...CompanyUserSession.shape.user.shape,
|
|
525
611
|
// Determined based on:
|
|
@@ -530,9 +616,9 @@ var CompanyUser = z14.object({
|
|
|
530
616
|
});
|
|
531
617
|
|
|
532
618
|
// src/schemas/company/components/Staff.ts
|
|
533
|
-
var MiniRawCompanyStaff =
|
|
619
|
+
var MiniRawCompanyStaff = z16.object({
|
|
534
620
|
_id: CompanyState.shape._id,
|
|
535
|
-
members:
|
|
621
|
+
members: z16.record(
|
|
536
622
|
MiniCompanyUser2.shape._id,
|
|
537
623
|
MiniCompanyUser2.omit({ _id: true })
|
|
538
624
|
),
|
|
@@ -540,15 +626,15 @@ var MiniRawCompanyStaff = z15.object({
|
|
|
540
626
|
/**
|
|
541
627
|
* @relationship one -> many
|
|
542
628
|
*@description A map of doctor `uids` to their assistants `uids` */
|
|
543
|
-
partnerMap:
|
|
629
|
+
partnerMap: z16.record(
|
|
544
630
|
CompanyUser.shape._id,
|
|
545
|
-
|
|
631
|
+
z16.record(CompanyUser.shape._id, z16.object({ addedAt: Timestamp }))
|
|
546
632
|
),
|
|
547
|
-
updateQueue:
|
|
633
|
+
updateQueue: z16.record(
|
|
548
634
|
CompanyUser.shape._id,
|
|
549
|
-
|
|
550
|
-
$REMOVE:
|
|
551
|
-
$CHANGE_ROLES:
|
|
635
|
+
z16.object({
|
|
636
|
+
$REMOVE: z16.object({ addedAt: Timestamp }),
|
|
637
|
+
$CHANGE_ROLES: z16.object({
|
|
552
638
|
newRoles: CompanyUser.shape.roles,
|
|
553
639
|
addedAt: Timestamp
|
|
554
640
|
})
|
|
@@ -557,9 +643,9 @@ var MiniRawCompanyStaff = z15.object({
|
|
|
557
643
|
version: Version,
|
|
558
644
|
lastModified: Timestamp.nullable()
|
|
559
645
|
});
|
|
560
|
-
var RawCompanyStaff =
|
|
646
|
+
var RawCompanyStaff = z16.object({
|
|
561
647
|
...MiniRawCompanyStaff.shape,
|
|
562
|
-
members:
|
|
648
|
+
members: z16.record(CompanyUser.shape._id, CompanyUser.omit({ _id: true }))
|
|
563
649
|
});
|
|
564
650
|
var transformStaff = (object17) => {
|
|
565
651
|
return object17.transform((d) => {
|
|
@@ -620,7 +706,7 @@ var MutableCompanyStaff = RawCompanyStaff.pick({
|
|
|
620
706
|
});
|
|
621
707
|
|
|
622
708
|
// src/schemas/company/CompanyDetails.ts
|
|
623
|
-
var CompanyDetails =
|
|
709
|
+
var CompanyDetails = z17.object({
|
|
624
710
|
_id: CompanyState.shape._id,
|
|
625
711
|
identity: CompanyIdentity.omit({ _id: true }),
|
|
626
712
|
notifications: CompanyNotifications,
|
|
@@ -630,7 +716,7 @@ var CompanyDetails = z16.object({
|
|
|
630
716
|
billing: CompanyBilling.omit({ _id: true }),
|
|
631
717
|
staff: RawCompanyStaff.omit({ _id: true })
|
|
632
718
|
});
|
|
633
|
-
var MutableCompanyDetails =
|
|
719
|
+
var MutableCompanyDetails = z17.object({
|
|
634
720
|
_id: CompanyDetails.shape._id,
|
|
635
721
|
identity: MutableCompanyIdentity.partial().optional(),
|
|
636
722
|
preferences: MutableCompanyPreferences.partial().optional(),
|
|
@@ -639,23 +725,23 @@ var MutableCompanyDetails = z16.object({
|
|
|
639
725
|
});
|
|
640
726
|
|
|
641
727
|
// src/schemas/company/utils/InviteList.ts
|
|
642
|
-
import * as
|
|
643
|
-
var CompanyInviteList =
|
|
728
|
+
import * as z18 from "zod";
|
|
729
|
+
var CompanyInviteList = z18.record(
|
|
644
730
|
CompanyUser.shape.email,
|
|
645
|
-
|
|
731
|
+
z18.object({ createdAt: Timestamp, roles: CompanyUser.shape.roles })
|
|
646
732
|
).refine(
|
|
647
733
|
(data) => Object.keys(data).length > 0,
|
|
648
734
|
"Insufficient amount of members invited."
|
|
649
735
|
);
|
|
650
736
|
|
|
651
737
|
// src/schemas/company/utils/CreateCompanyForm.ts
|
|
652
|
-
import * as
|
|
653
|
-
var CreateCompanyForm =
|
|
738
|
+
import * as z19 from "zod";
|
|
739
|
+
var CreateCompanyForm = z19.object({
|
|
654
740
|
domain: CompanyIdentity.shape._id,
|
|
655
741
|
alias: CompanyIdentity.shape.alias.optional(),
|
|
656
742
|
picture: CompanyIdentity.shape.logo,
|
|
657
743
|
...CompanyIdentity.shape.contact.pick({ email: true, phoneNumber: true }).shape,
|
|
658
|
-
|
|
744
|
+
industry: CompanyIdentity.shape.industry,
|
|
659
745
|
address: CompanyIdentity.shape.address
|
|
660
746
|
}).transform((data) => {
|
|
661
747
|
if (!("alias" in data)) {
|
|
@@ -665,114 +751,64 @@ var CreateCompanyForm = z18.object({
|
|
|
665
751
|
});
|
|
666
752
|
|
|
667
753
|
// src/schemas/appointment/components/Medical.ts
|
|
668
|
-
import * as
|
|
669
|
-
var Vitals =
|
|
754
|
+
import * as z20 from "zod";
|
|
755
|
+
var Vitals = z20.record(
|
|
670
756
|
vitalKeys,
|
|
671
|
-
|
|
672
|
-
value:
|
|
757
|
+
z20.object({
|
|
758
|
+
value: z20.string().trim().regex(/^\d{0,3}((\/|\.)\d{1,3})?/),
|
|
673
759
|
lastModified: Timestamp.nullable()
|
|
674
760
|
})
|
|
675
761
|
);
|
|
676
|
-
var Medicine =
|
|
677
|
-
brand:
|
|
762
|
+
var Medicine = z20.object({
|
|
763
|
+
brand: z20.string().trim(),
|
|
678
764
|
expiresAt: Timestamp.nullish(),
|
|
679
|
-
quantity:
|
|
765
|
+
quantity: z20.string().trim().regex(/^\d+(\.\d{1,3})? ?[a-zA-Z]{1,20}/, {
|
|
680
766
|
error: "Failed to match the pattern <number>+(.<number>{1,3})? ?[a-zA-Z]{1,20}"
|
|
681
767
|
}),
|
|
682
|
-
refills:
|
|
683
|
-
directions:
|
|
768
|
+
refills: z20.string().trim().regex(/^[0-8]/, { error: "Must be between 0 and 8" }),
|
|
769
|
+
directions: z20.string().trim().max(100, { error: "Must be 100 characters or less" }),
|
|
684
770
|
...TimeLog.shape
|
|
685
771
|
});
|
|
686
|
-
var MedicalDetails =
|
|
772
|
+
var MedicalDetails = z20.object({
|
|
687
773
|
vitals: Vitals,
|
|
688
|
-
prescriptions:
|
|
689
|
-
doctorNote:
|
|
690
|
-
value:
|
|
774
|
+
prescriptions: z20.array(z20.array(Medicine)).nullish(),
|
|
775
|
+
doctorNote: z20.object({
|
|
776
|
+
value: z20.string(),
|
|
691
777
|
lastModified: Timestamp.nullable()
|
|
692
778
|
}),
|
|
693
|
-
physAsstNotes:
|
|
694
|
-
|
|
695
|
-
title:
|
|
696
|
-
content:
|
|
779
|
+
physAsstNotes: z20.array(
|
|
780
|
+
z20.object({
|
|
781
|
+
title: z20.string(),
|
|
782
|
+
content: z20.string(),
|
|
697
783
|
...TimeLog.shape
|
|
698
784
|
})
|
|
699
785
|
).optional()
|
|
700
786
|
});
|
|
701
787
|
|
|
702
|
-
// src/schemas/profiles/Client.ts
|
|
703
|
-
import * as z20 from "zod";
|
|
704
|
-
import { Address as Address2 } from "@wavy/util";
|
|
705
|
-
var Name = z20.string().trim().min(2).max(MAX_NAME_LENGTH).transform((d) => d.replace(/-+/g, "-").replace(/'+/g, "'")).superRefine((data, ctx) => {
|
|
706
|
-
const invalidCharIdx = data.search(/[^a-z'-]/i);
|
|
707
|
-
if (invalidCharIdx >= 0) {
|
|
708
|
-
const char = data[invalidCharIdx].includes('"') ? `(${data[invalidCharIdx]})` : `"${data[invalidCharIdx]}"`;
|
|
709
|
-
ctx.addIssue(`${char} is not an allowed character.`);
|
|
710
|
-
}
|
|
711
|
-
});
|
|
712
|
-
var ClientIdentity = UserDetails.pick({
|
|
713
|
-
_id: true,
|
|
714
|
-
createdAt: true,
|
|
715
|
-
lastModified: true,
|
|
716
|
-
phoneNumber: true,
|
|
717
|
-
version: true,
|
|
718
|
-
photoUrl: true
|
|
719
|
-
}).safeExtend(
|
|
720
|
-
z20.object({
|
|
721
|
-
firstName: Name,
|
|
722
|
-
middleName: Name,
|
|
723
|
-
lastName: Name,
|
|
724
|
-
email: UserDetails.shape.email.optional(),
|
|
725
|
-
dob: Timestamp,
|
|
726
|
-
sex: genders,
|
|
727
|
-
isGlobal: z20.boolean(),
|
|
728
|
-
origin: CompanyIdentity.shape._id,
|
|
729
|
-
// National id
|
|
730
|
-
nid: z20.object({
|
|
731
|
-
class: nidClasses,
|
|
732
|
-
// Hash this value
|
|
733
|
-
value: z20.string().min(5).max(20)
|
|
734
|
-
}).superRefine((data, ctx) => {
|
|
735
|
-
const invalidCharIdx = data.value.search(/[^a-z0-9]/i);
|
|
736
|
-
if (data.class === "trn") {
|
|
737
|
-
const parsedData = Trn.safeParse(data.value);
|
|
738
|
-
if (!parsedData.success) {
|
|
739
|
-
ctx.addIssue(
|
|
740
|
-
parsedData.error?.issues?.[0]?.message || parsedData.error.message
|
|
741
|
-
);
|
|
742
|
-
}
|
|
743
|
-
} else if (invalidCharIdx >= 0) {
|
|
744
|
-
const char = data.value[invalidCharIdx] === '"' ? `(${data.value[invalidCharIdx]})` : `"${data.value[invalidCharIdx]}"`;
|
|
745
|
-
ctx.addIssue(`${char} is not an allowed character.`);
|
|
746
|
-
}
|
|
747
|
-
}).optional(),
|
|
748
|
-
// Don't hash the attributes, they can be used to help accurately identify a client by whoever is searching for
|
|
749
|
-
// the client
|
|
750
|
-
attributes: z20.object({
|
|
751
|
-
mothersMaidenName: Name,
|
|
752
|
-
fathersMiddleName: Name,
|
|
753
|
-
mothersMiddleName: Name,
|
|
754
|
-
oldestSiblingMiddleName: Name,
|
|
755
|
-
firstSchoolName: z20.string().trim().min(3).max(60)
|
|
756
|
-
// nickname: z.string().trim().min(1).max(40),
|
|
757
|
-
}).partial().refine(
|
|
758
|
-
(data) => Object.keys(data).length > 0,
|
|
759
|
-
"At least (1) attribute must be defined."
|
|
760
|
-
),
|
|
761
|
-
address: Address2.optional(),
|
|
762
|
-
linkedTo: UserDetails.shape._id.optional()
|
|
763
|
-
}).shape
|
|
764
|
-
);
|
|
765
|
-
var ClientForm = ClientIdentity.pick({
|
|
766
|
-
firstName: true,
|
|
767
|
-
middleName: true,
|
|
768
|
-
lastName: true,
|
|
769
|
-
dob: true,
|
|
770
|
-
sex: true
|
|
771
|
-
// attributes: true,
|
|
772
|
-
}).required();
|
|
773
|
-
|
|
774
788
|
// src/schemas/appointment/Appointment.ts
|
|
775
789
|
import * as z21 from "zod";
|
|
790
|
+
import { sumOf as sumOf2 } from "@wavy/fn";
|
|
791
|
+
|
|
792
|
+
// src/functions/calcAppointmentFee.ts
|
|
793
|
+
import { sumOf } from "@wavy/fn";
|
|
794
|
+
function calcAppointmentFee(appointment) {
|
|
795
|
+
const subtotal = sumOf(appointment.charges?.map((c) => c.cost));
|
|
796
|
+
const discount = calcAdjustment(appointment.discounts, subtotal);
|
|
797
|
+
const additionalFees = calcAdjustment(appointment.additionalFees, subtotal);
|
|
798
|
+
const prepayments = calcAdjustment(appointment.prepayments, subtotal);
|
|
799
|
+
console.log({ subtotal, discount, additionalFees, prepayments });
|
|
800
|
+
return subtotal + additionalFees - (discount + prepayments);
|
|
801
|
+
}
|
|
802
|
+
var calcAdjustment = (adjustments, subtotal) => {
|
|
803
|
+
if (!adjustments || adjustments.length < 1) return 0;
|
|
804
|
+
return sumOf(
|
|
805
|
+
adjustments?.map(
|
|
806
|
+
(d) => (d.fixedAmount?.value || 0) + (d.percentage ? d.percentage * 0.01 * subtotal : 0)
|
|
807
|
+
)
|
|
808
|
+
);
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
// src/schemas/appointment/Appointment.ts
|
|
776
812
|
var TimelineActivity = z21.object({
|
|
777
813
|
postedAt: Timestamp.nullish(),
|
|
778
814
|
userUid: CompanyUser.shape._id.nonoptional()
|
|
@@ -797,7 +833,7 @@ var MiniAppointmentDetails = z21.object({
|
|
|
797
833
|
*/
|
|
798
834
|
invoiceNo: InvoiceNo.optional(),
|
|
799
835
|
/** The services that the client has done/will do. */
|
|
800
|
-
charges: z21.array(PriceTag
|
|
836
|
+
charges: z21.array(PriceTag).max(20),
|
|
801
837
|
/**Required to calculate the accurate grandTotal of the charges */
|
|
802
838
|
additionalFees: z21.array(PriceAdjustment).nullable().readonly(),
|
|
803
839
|
/**Required to calculate the accurate grandTotal of the charges */
|
|
@@ -822,22 +858,34 @@ var MiniAppointmentDetails = z21.object({
|
|
|
822
858
|
}).optional(),
|
|
823
859
|
/** Add this after consulting with company owners about payment expectations */
|
|
824
860
|
// paymentDueDate: Timestamp.nullish(),
|
|
825
|
-
payments: z21.array(
|
|
826
|
-
z21.object({
|
|
827
|
-
method: paymentMethods,
|
|
828
|
-
amount: z21.number().positive(),
|
|
829
|
-
...TimeLog.shape
|
|
830
|
-
})
|
|
831
|
-
).max(100).nullish(),
|
|
861
|
+
payments: z21.array(PaymentDetails).max(100).nullish(),
|
|
832
862
|
// The user that is currently modifying the appointment
|
|
833
863
|
lockedBy: UserDetails.shape._id.optional(),
|
|
834
864
|
timeline: z21.object({
|
|
835
865
|
scheduler: TimelineActivity,
|
|
836
866
|
physAsst: TimelineActivity.or(z21.literal("none")),
|
|
837
867
|
doctor: TimelineActivity,
|
|
838
|
-
|
|
868
|
+
// Array used to accurately record payments made by the "a/r" and the "cshr"
|
|
869
|
+
debtCollector: z21.array(
|
|
870
|
+
z21.object({
|
|
871
|
+
...TimelineActivity.shape,
|
|
872
|
+
// Payment uid -> collection time
|
|
873
|
+
collectedPayments: z21.record(z21.uuidv4(), Timestamp)
|
|
874
|
+
})
|
|
875
|
+
).min(1).nullable()
|
|
839
876
|
}),
|
|
840
877
|
...TimeLog.shape
|
|
878
|
+
}).superRefine((data, ctx) => {
|
|
879
|
+
if (data.payments && data.charges && sumOf2(data.payments.map((p) => p.amount)) >= calcAppointmentFee(data)) {
|
|
880
|
+
const untrackedPayment = data.payments.find(
|
|
881
|
+
(p) => !data.timeline.debtCollector?.some(
|
|
882
|
+
(d) => p.uid in d.collectedPayments
|
|
883
|
+
)
|
|
884
|
+
);
|
|
885
|
+
if (untrackedPayment) {
|
|
886
|
+
ctx.addIssue(`Untracked payment found (${untrackedPayment.uid})`);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
841
889
|
});
|
|
842
890
|
var AppointmentDetails = MiniAppointmentDetails.omit({
|
|
843
891
|
clientUid: true
|
|
@@ -1015,8 +1063,9 @@ async function scheduleAppointment(request) {
|
|
|
1015
1063
|
scheduler: { userUid: request.sender._id, postedAt: today },
|
|
1016
1064
|
doctor: { userUid: selectedDoctor },
|
|
1017
1065
|
physAsst: selectedPhysAsst ? { userUid: selectedPhysAsst } : "none",
|
|
1018
|
-
get
|
|
1019
|
-
if (request.preferences.enforcePaidAppointments)
|
|
1066
|
+
get debtCollector() {
|
|
1067
|
+
if (request.preferences.enforcePaidAppointments)
|
|
1068
|
+
return [{ ...this.scheduler, collectedPayments: {} }];
|
|
1020
1069
|
return null;
|
|
1021
1070
|
}
|
|
1022
1071
|
},
|
|
@@ -1049,6 +1098,7 @@ function createNotifId(options) {
|
|
|
1049
1098
|
return nid;
|
|
1050
1099
|
}
|
|
1051
1100
|
export {
|
|
1101
|
+
AlphaNumeric,
|
|
1052
1102
|
AppointmentDetails,
|
|
1053
1103
|
ClientForm,
|
|
1054
1104
|
ClientIdentity,
|
|
@@ -1076,6 +1126,7 @@ export {
|
|
|
1076
1126
|
MutableCompanyIdentity,
|
|
1077
1127
|
MutableCompanyPreferences,
|
|
1078
1128
|
Notification,
|
|
1129
|
+
PaymentDetails,
|
|
1079
1130
|
PriceAdjustment,
|
|
1080
1131
|
PriceTag,
|
|
1081
1132
|
Reason,
|
|
@@ -1090,11 +1141,12 @@ export {
|
|
|
1090
1141
|
UserDetails,
|
|
1091
1142
|
Version,
|
|
1092
1143
|
Vitals,
|
|
1144
|
+
acceptedCurrencies,
|
|
1093
1145
|
adminRoles,
|
|
1094
1146
|
appointmentDistAlgs,
|
|
1147
|
+
calcAppointmentFee,
|
|
1095
1148
|
companyPartnerRoles,
|
|
1096
1149
|
companyServiceSelectors,
|
|
1097
|
-
companyTypes,
|
|
1098
1150
|
companyUserRoles,
|
|
1099
1151
|
companyUserStatus,
|
|
1100
1152
|
createNotifId,
|
|
@@ -1105,9 +1157,9 @@ export {
|
|
|
1105
1157
|
genders,
|
|
1106
1158
|
getCompatibleRoles,
|
|
1107
1159
|
healthcareProviderRoles,
|
|
1108
|
-
|
|
1160
|
+
industries,
|
|
1109
1161
|
normalizeCompanyId,
|
|
1110
|
-
|
|
1162
|
+
normalizeNidKey,
|
|
1111
1163
|
parseClientName,
|
|
1112
1164
|
paymentMethods,
|
|
1113
1165
|
scheduleAppointment,
|