@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.
Files changed (3) hide show
  1. package/dist/main.d.ts +134 -238
  2. package/dist/main.js +230 -178
  3. 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 companyTypes = z.enum(["MEDICAL"]);
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 nidClasses = z2.enum(["passportNo", "trn", "nin"]);
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
- "cashier"
54
+ "debtCollector"
51
55
  ]);
52
56
 
53
57
  // src/schemas/company/CompanyDetails.ts
54
- import * as z16 from "zod";
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.").optional(),
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: currencies
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: currencies,
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
- type: companyTypes.readonly(),
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: currencies2 }),
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 z15 from "zod";
422
+ import * as z16 from "zod";
399
423
 
400
424
  // src/schemas/company/components/User.ts
401
- import * as z14 from "zod";
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 normalizeNidClass = (value) => {
438
- value = nidClasses.parse(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 = z14.object({
480
- _id: z14.uuidv4(),
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: z14.string().trim().min(15),
484
- isAvailable: z14.object({
485
- value: z14.boolean(),
569
+ deviceId: z15.string().trim().min(15),
570
+ isAvailable: z15.object({
571
+ value: z15.boolean(),
486
572
  lastModified: Timestamp.nullable()
487
573
  }),
488
- isBusy: z14.object({
489
- value: z14.boolean(),
574
+ isBusy: z15.object({
575
+ value: z15.boolean(),
490
576
  lastModified: Timestamp.nullable()
491
577
  }),
492
- appointments: z14.record(z14.literal(["ongoing", "completed"]), z14.int().min(0)),
493
- roles: z14.array(companyUserRoles).transform((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: z14.number(),
590
+ ttl: z15.number(),
505
591
  lastModified: Timestamp.nullable(),
506
- expiresAfter: z14.date()
592
+ expiresAfter: z15.date()
507
593
  });
508
- var MiniCompanyUser2 = z14.object({
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 = z14.object({
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 = z15.object({
619
+ var MiniRawCompanyStaff = z16.object({
534
620
  _id: CompanyState.shape._id,
535
- members: z15.record(
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: z15.record(
629
+ partnerMap: z16.record(
544
630
  CompanyUser.shape._id,
545
- z15.record(CompanyUser.shape._id, z15.object({ addedAt: Timestamp }))
631
+ z16.record(CompanyUser.shape._id, z16.object({ addedAt: Timestamp }))
546
632
  ),
547
- updateQueue: z15.record(
633
+ updateQueue: z16.record(
548
634
  CompanyUser.shape._id,
549
- z15.object({
550
- $REMOVE: z15.object({ addedAt: Timestamp }),
551
- $CHANGE_ROLES: z15.object({
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 = z15.object({
646
+ var RawCompanyStaff = z16.object({
561
647
  ...MiniRawCompanyStaff.shape,
562
- members: z15.record(CompanyUser.shape._id, CompanyUser.omit({ _id: true }))
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 = z16.object({
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 = z16.object({
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 z17 from "zod";
643
- var CompanyInviteList = z17.record(
728
+ import * as z18 from "zod";
729
+ var CompanyInviteList = z18.record(
644
730
  CompanyUser.shape.email,
645
- z17.object({ createdAt: Timestamp, roles: CompanyUser.shape.roles })
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 z18 from "zod";
653
- var CreateCompanyForm = z18.object({
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
- type: CompanyIdentity.shape.type,
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 z19 from "zod";
669
- var Vitals = z19.record(
754
+ import * as z20 from "zod";
755
+ var Vitals = z20.record(
670
756
  vitalKeys,
671
- z19.object({
672
- value: z19.string().trim().regex(/^\d{0,3}((\/|\.)\d{1,3})?/),
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 = z19.object({
677
- brand: z19.string().trim(),
762
+ var Medicine = z20.object({
763
+ brand: z20.string().trim(),
678
764
  expiresAt: Timestamp.nullish(),
679
- quantity: z19.string().trim().regex(/^\d+(\.\d{1,3})? ?[a-zA-Z]{1,20}/, {
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: z19.string().trim().regex(/^[0-8]/, { error: "Must be between 0 and 8" }),
683
- directions: z19.string().trim().max(100, { error: "Must be 100 characters or less" }),
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 = z19.object({
772
+ var MedicalDetails = z20.object({
687
773
  vitals: Vitals,
688
- prescriptions: z19.array(z19.array(Medicine)).nullish(),
689
- doctorNote: z19.object({
690
- value: z19.string(),
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: z19.array(
694
- z19.object({
695
- title: z19.string(),
696
- content: z19.string(),
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.omit({ uid: true })).max(4),
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
- cashier: TimelineActivity.nullable()
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 cashier() {
1019
- if (request.preferences.enforcePaidAppointments) return this.scheduler;
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
- nidClasses,
1160
+ industries,
1109
1161
  normalizeCompanyId,
1110
- normalizeNidClass,
1162
+ normalizeNidKey,
1111
1163
  parseClientName,
1112
1164
  paymentMethods,
1113
1165
  scheduleAppointment,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bizmap/sdk",
3
- "version": "0.0.92",
3
+ "version": "0.0.94",
4
4
  "main": "./dist/main.js",
5
5
  "types": "./dist/main.d.ts",
6
6
  "type": "module",