@bizmap/sdk 0.0.58 → 0.0.59

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 CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as z from 'zod';
2
+ import { SafeOmit } from '@wavy/util';
2
3
 
3
4
  declare const companyUserRoles: z.ZodEnum<{
4
5
  doc: "doc";
@@ -275,6 +276,128 @@ declare const CompanyDetails: z.ZodObject<{
275
276
  }, z.core.$strip>;
276
277
  }, z.core.$strip>;
277
278
  type CompanyDetails = z.infer<typeof CompanyDetails>;
279
+ declare const MutableCompanyDetails: z.ZodObject<{
280
+ uid: z.ZodUUID;
281
+ identity: z.ZodOptional<z.ZodObject<{
282
+ address: z.ZodOptional<z.ZodObject<{
283
+ streetAddress: z.ZodString;
284
+ city: z.ZodOptional<z.ZodString>;
285
+ parish: z.ZodString;
286
+ country: z.ZodString;
287
+ }, z.core.$strip>>;
288
+ logo: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
289
+ contact: z.ZodOptional<z.ZodObject<{
290
+ email: z.ZodEmail;
291
+ phoneNumber: z.ZodOptional<z.ZodString>;
292
+ }, z.core.$strip>>;
293
+ legal: z.ZodOptional<z.ZodObject<{
294
+ regNo: z.ZodReadonly<z.ZodString>;
295
+ trn: z.ZodOptional<z.ZodNullable<z.ZodString>>;
296
+ gctRegNo: z.ZodOptional<z.ZodNullable<z.ZodString>>;
297
+ }, z.core.$strip>>;
298
+ }, z.core.$strip>>;
299
+ preferences: z.ZodOptional<z.ZodObject<{
300
+ serviceSelector: z.ZodOptional<z.ZodEnum<{
301
+ scheduler: "scheduler";
302
+ doctor: "doctor";
303
+ }>>;
304
+ enforcePaidServices: z.ZodOptional<z.ZodBoolean>;
305
+ serviceDistAlg: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
306
+ RR: "RR";
307
+ LOR: "LOR";
308
+ }>>>;
309
+ }, z.core.$strip>>;
310
+ billing: z.ZodOptional<z.ZodObject<{
311
+ additionalFees: z.ZodOptional<z.ZodRecord<z.ZodUUID, z.ZodObject<{
312
+ createdAt: z.ZodReadonly<z.ZodInt>;
313
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
314
+ description: z.ZodOptional<z.ZodString>;
315
+ fixedAmount: z.ZodObject<{
316
+ value: z.ZodNumber;
317
+ currency: z.ZodEnum<{
318
+ JMD: "JMD";
319
+ USD: "USD";
320
+ EUR: "EUR";
321
+ GBP: "GBP";
322
+ CAD: "CAD";
323
+ }>;
324
+ }, z.core.$strip>;
325
+ percentage: z.ZodNumber;
326
+ isOptional: z.ZodBoolean;
327
+ }, z.core.$strip>>>;
328
+ discounts: z.ZodOptional<z.ZodRecord<z.ZodUUID, z.ZodObject<{
329
+ createdAt: z.ZodReadonly<z.ZodInt>;
330
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
331
+ description: z.ZodOptional<z.ZodString>;
332
+ fixedAmount: z.ZodObject<{
333
+ value: z.ZodNumber;
334
+ currency: z.ZodEnum<{
335
+ JMD: "JMD";
336
+ USD: "USD";
337
+ EUR: "EUR";
338
+ GBP: "GBP";
339
+ CAD: "CAD";
340
+ }>;
341
+ }, z.core.$strip>;
342
+ percentage: z.ZodNumber;
343
+ isOptional: z.ZodBoolean;
344
+ }, z.core.$strip>>>;
345
+ prepayments: z.ZodOptional<z.ZodRecord<z.ZodUUID, z.ZodObject<{
346
+ createdAt: z.ZodReadonly<z.ZodInt>;
347
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
348
+ description: z.ZodOptional<z.ZodString>;
349
+ fixedAmount: z.ZodObject<{
350
+ value: z.ZodNumber;
351
+ currency: z.ZodEnum<{
352
+ JMD: "JMD";
353
+ USD: "USD";
354
+ EUR: "EUR";
355
+ GBP: "GBP";
356
+ CAD: "CAD";
357
+ }>;
358
+ }, z.core.$strip>;
359
+ percentage: z.ZodNumber;
360
+ isOptional: z.ZodBoolean;
361
+ }, z.core.$strip>>>;
362
+ services: z.ZodOptional<z.ZodObject<{
363
+ deployed: z.ZodBoolean;
364
+ value: z.ZodRecord<z.ZodString, z.ZodObject<{
365
+ createdAt: z.ZodReadonly<z.ZodInt>;
366
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
367
+ currency: z.ZodEnum<{
368
+ JMD: "JMD";
369
+ USD: "USD";
370
+ EUR: "EUR";
371
+ GBP: "GBP";
372
+ CAD: "CAD";
373
+ }>;
374
+ item: z.ZodString;
375
+ cost: z.ZodNumber;
376
+ }, z.core.$strip>>;
377
+ }, z.core.$strip>>;
378
+ }, z.core.$strip>>;
379
+ staff: z.ZodOptional<z.ZodObject<{
380
+ partnerMap: z.ZodOptional<z.ZodRecord<z.ZodUUID, z.ZodRecord<z.ZodUUID, z.ZodObject<{
381
+ addedAt: z.ZodInt;
382
+ }, z.core.$strip>>>>;
383
+ updateQueue: z.ZodOptional<z.ZodRecord<z.ZodUUID, z.ZodObject<{
384
+ $REMOVE: z.ZodOptional<z.ZodObject<{
385
+ addedAt: z.ZodInt;
386
+ }, z.core.$strip>>;
387
+ $CHANGE_ROLES: z.ZodOptional<z.ZodObject<{
388
+ newRoles: z.ZodPipe<z.ZodArray<z.ZodEnum<{
389
+ doc: "doc";
390
+ physAsst: "physAsst";
391
+ rcpst: "rcpst";
392
+ cshr: "cshr";
393
+ admin: "admin";
394
+ }>>, z.ZodTransform<("doc" | "physAsst" | "rcpst" | "cshr" | "admin")[], ("doc" | "physAsst" | "rcpst" | "cshr" | "admin")[]>>;
395
+ addedAt: z.ZodInt;
396
+ }, z.core.$strip>>;
397
+ }, z.core.$strip>>>;
398
+ }, z.core.$strip>>;
399
+ }, z.core.$strip>;
400
+ type MutableCompanyDetails = z.infer<typeof MutableCompanyDetails>;
278
401
 
279
402
  declare const CompanyBilling: z.ZodObject<{
280
403
  uid: z.ZodUUID;
@@ -348,6 +471,76 @@ declare const CompanyBilling: z.ZodObject<{
348
471
  lastModified: z.ZodNullable<z.ZodInt>;
349
472
  }, z.core.$strip>;
350
473
  type CompanyBilling = z.infer<typeof CompanyBilling>;
474
+ declare const MutableCompanyBilling: z.ZodObject<{
475
+ additionalFees: z.ZodRecord<z.ZodUUID, z.ZodObject<{
476
+ createdAt: z.ZodReadonly<z.ZodInt>;
477
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
478
+ description: z.ZodOptional<z.ZodString>;
479
+ fixedAmount: z.ZodObject<{
480
+ value: z.ZodNumber;
481
+ currency: z.ZodEnum<{
482
+ JMD: "JMD";
483
+ USD: "USD";
484
+ EUR: "EUR";
485
+ GBP: "GBP";
486
+ CAD: "CAD";
487
+ }>;
488
+ }, z.core.$strip>;
489
+ percentage: z.ZodNumber;
490
+ isOptional: z.ZodBoolean;
491
+ }, z.core.$strip>>;
492
+ discounts: z.ZodRecord<z.ZodUUID, z.ZodObject<{
493
+ createdAt: z.ZodReadonly<z.ZodInt>;
494
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
495
+ description: z.ZodOptional<z.ZodString>;
496
+ fixedAmount: z.ZodObject<{
497
+ value: z.ZodNumber;
498
+ currency: z.ZodEnum<{
499
+ JMD: "JMD";
500
+ USD: "USD";
501
+ EUR: "EUR";
502
+ GBP: "GBP";
503
+ CAD: "CAD";
504
+ }>;
505
+ }, z.core.$strip>;
506
+ percentage: z.ZodNumber;
507
+ isOptional: z.ZodBoolean;
508
+ }, z.core.$strip>>;
509
+ prepayments: z.ZodRecord<z.ZodUUID, z.ZodObject<{
510
+ createdAt: z.ZodReadonly<z.ZodInt>;
511
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
512
+ description: z.ZodOptional<z.ZodString>;
513
+ fixedAmount: z.ZodObject<{
514
+ value: z.ZodNumber;
515
+ currency: z.ZodEnum<{
516
+ JMD: "JMD";
517
+ USD: "USD";
518
+ EUR: "EUR";
519
+ GBP: "GBP";
520
+ CAD: "CAD";
521
+ }>;
522
+ }, z.core.$strip>;
523
+ percentage: z.ZodNumber;
524
+ isOptional: z.ZodBoolean;
525
+ }, z.core.$strip>>;
526
+ services: z.ZodObject<{
527
+ deployed: z.ZodBoolean;
528
+ value: z.ZodRecord<z.ZodString, z.ZodObject<{
529
+ createdAt: z.ZodReadonly<z.ZodInt>;
530
+ lastModified: z.ZodOptional<z.ZodNullable<z.ZodInt>>;
531
+ currency: z.ZodEnum<{
532
+ JMD: "JMD";
533
+ USD: "USD";
534
+ EUR: "EUR";
535
+ GBP: "GBP";
536
+ CAD: "CAD";
537
+ }>;
538
+ item: z.ZodString;
539
+ cost: z.ZodNumber;
540
+ }, z.core.$strip>>;
541
+ }, z.core.$strip>;
542
+ }, z.core.$strip>;
543
+ type MutableCompanyBilling = z.infer<typeof MutableCompanyBilling>;
351
544
 
352
545
  declare const CompanyIdentity: z.ZodObject<{
353
546
  uid: z.ZodUUID;
@@ -380,6 +573,25 @@ declare const CompanyIdentity: z.ZodObject<{
380
573
  lastModified: z.ZodNullable<z.ZodInt>;
381
574
  }, z.core.$strip>;
382
575
  type CompanyIdentity = z.infer<typeof CompanyIdentity>;
576
+ declare const MutableCompanyIdentity: z.ZodObject<{
577
+ address: z.ZodObject<{
578
+ streetAddress: z.ZodString;
579
+ city: z.ZodOptional<z.ZodString>;
580
+ parish: z.ZodString;
581
+ country: z.ZodString;
582
+ }, z.core.$strip>;
583
+ logo: z.ZodOptional<z.ZodNullable<z.ZodString>>;
584
+ contact: z.ZodObject<{
585
+ email: z.ZodEmail;
586
+ phoneNumber: z.ZodOptional<z.ZodString>;
587
+ }, z.core.$strip>;
588
+ legal: z.ZodObject<{
589
+ regNo: z.ZodReadonly<z.ZodString>;
590
+ trn: z.ZodOptional<z.ZodNullable<z.ZodString>>;
591
+ gctRegNo: z.ZodOptional<z.ZodNullable<z.ZodString>>;
592
+ }, z.core.$strip>;
593
+ }, z.core.$strip>;
594
+ type MutableCompanyIdentity = z.infer<typeof MutableCompanyIdentity>;
383
595
 
384
596
  declare const CompanyNotifications: z.ZodArray<z.ZodObject<{
385
597
  code: z.ZodLiteral<"COMPANY_INVITE" | "INVITE_RESPONSE" | "DEV_MESSAGE" | "ALERT">;
@@ -408,6 +620,18 @@ declare const CompanyPreferences: z.ZodObject<{
408
620
  lastModified: z.ZodNullable<z.ZodInt>;
409
621
  }, z.core.$strip>;
410
622
  type CompanyPreferences = z.infer<typeof CompanyPreferences>;
623
+ declare const MutableCompanyPreferences: z.ZodObject<{
624
+ serviceSelector: z.ZodEnum<{
625
+ scheduler: "scheduler";
626
+ doctor: "doctor";
627
+ }>;
628
+ enforcePaidServices: z.ZodBoolean;
629
+ serviceDistAlg: z.ZodDefault<z.ZodEnum<{
630
+ RR: "RR";
631
+ LOR: "LOR";
632
+ }>>;
633
+ }, z.core.$strip>;
634
+ type MutableCompanyPreferences = z.infer<typeof MutableCompanyPreferences>;
411
635
 
412
636
  declare const CompanyStaff: z.ZodPipe<z.ZodObject<{
413
637
  uid: z.ZodUUID;
@@ -1353,6 +1577,213 @@ declare const CreateServiceForm: z.ZodObject<{
1353
1577
  }, z.core.$strip>;
1354
1578
  type CreateServiceForm = z.infer<typeof CreateServiceForm>;
1355
1579
 
1580
+ declare function createCompanyService(request: {
1581
+ form: CreateServiceForm;
1582
+ sender: UserDetails;
1583
+ billing: SafeOmit<CompanyBilling, "uid" | "prepayments" | "lastModified">;
1584
+ preferences: SafeOmit<CompanyPreferences, "uid" | "lastModified">;
1585
+ state: CompanyState;
1586
+ staff: CompanyStaff;
1587
+ cost: number;
1588
+ findClient: (uid: string) => Promise<ClientIdentity>;
1589
+ encryptCopy: (service: SafeOmit<MutableServiceDetails, "_hash">) => string;
1590
+ options?: Partial<{
1591
+ ignoreBalanceCheck: boolean;
1592
+ }>;
1593
+ }): Promise<{
1594
+ updates: {
1595
+ state: {
1596
+ uid: string;
1597
+ credits: {
1598
+ current: number;
1599
+ lastModified: number | null;
1600
+ };
1601
+ maxStaff: {
1602
+ current: number;
1603
+ lastModified: number | null;
1604
+ };
1605
+ storageInBytes: Record<"used" | "max", {
1606
+ current: number;
1607
+ lastModified: number | null;
1608
+ }>;
1609
+ invoiceNoCounter: number;
1610
+ tktNoCounter: number;
1611
+ lastSavedAt: number | null;
1612
+ lastModified: number | null;
1613
+ createdAt: number;
1614
+ };
1615
+ staffDetails: {
1616
+ uid: string;
1617
+ members: Record<string, {
1618
+ uid: string;
1619
+ roles: ("doc" | "physAsst" | "rcpst" | "cshr" | "admin")[];
1620
+ isAvailable: boolean;
1621
+ isBusy: boolean;
1622
+ status: "inviteSent" | "active" | "inactive";
1623
+ services: Record<"ongoing" | "completed", number>;
1624
+ lastActive: number | null;
1625
+ isAvailableLastModified: number | null;
1626
+ isBusyLastModified: number | null;
1627
+ name: Record<"first" | "last", string>;
1628
+ email: string;
1629
+ photoUrl?: string | null | undefined;
1630
+ phoneNumber?: string | undefined;
1631
+ }>;
1632
+ partnerMap: Record<string, Record<string, {
1633
+ addedAt: number;
1634
+ }>>;
1635
+ updateQueue: Record<string, {
1636
+ $REMOVE?: {
1637
+ addedAt: number;
1638
+ } | undefined;
1639
+ $CHANGE_ROLES?: {
1640
+ newRoles: ("doc" | "physAsst" | "rcpst" | "cshr" | "admin")[];
1641
+ addedAt: number;
1642
+ } | undefined;
1643
+ }>;
1644
+ timeline: Record<string, {
1645
+ inviteSent: number | null;
1646
+ inviteAccepted: number | null;
1647
+ }>;
1648
+ lastModified: number | null;
1649
+ };
1650
+ };
1651
+ appointment: {
1652
+ createdAt: number;
1653
+ additionalFees: readonly {
1654
+ createdAt: number;
1655
+ fixedAmount: {
1656
+ value: number;
1657
+ currency: "JMD" | "USD" | "EUR" | "GBP" | "CAD";
1658
+ };
1659
+ percentage: number;
1660
+ isOptional: boolean;
1661
+ lastModified?: number | null | undefined;
1662
+ description?: string | undefined;
1663
+ }[] | null;
1664
+ discounts: readonly {
1665
+ createdAt: number;
1666
+ fixedAmount: {
1667
+ value: number;
1668
+ currency: "JMD" | "USD" | "EUR" | "GBP" | "CAD";
1669
+ };
1670
+ percentage: number;
1671
+ isOptional: boolean;
1672
+ lastModified?: number | null | undefined;
1673
+ description?: string | undefined;
1674
+ }[] | null;
1675
+ prepayments: {
1676
+ createdAt: number;
1677
+ fixedAmount: {
1678
+ value: number;
1679
+ currency: "JMD" | "USD" | "EUR" | "GBP" | "CAD";
1680
+ };
1681
+ percentage: number;
1682
+ isOptional: boolean;
1683
+ lastModified?: number | null | undefined;
1684
+ description?: string | undefined;
1685
+ }[] | null;
1686
+ src: string;
1687
+ timeline: {
1688
+ scheduler: {
1689
+ userUid: string;
1690
+ postedAt?: number | null | undefined;
1691
+ };
1692
+ physAsst: "none" | {
1693
+ userUid: string;
1694
+ postedAt?: number | null | undefined;
1695
+ };
1696
+ doctor: {
1697
+ userUid: string;
1698
+ postedAt?: number | null | undefined;
1699
+ };
1700
+ cashier: {
1701
+ userUid: string;
1702
+ postedAt?: number | null | undefined;
1703
+ } | null;
1704
+ };
1705
+ tkt: number;
1706
+ _id: string;
1707
+ charges: {
1708
+ createdAt: number;
1709
+ currency: "JMD" | "USD" | "EUR" | "GBP" | "CAD";
1710
+ item: string;
1711
+ cost: number;
1712
+ lastModified?: number | null | undefined;
1713
+ }[];
1714
+ client: {
1715
+ createdAt: number;
1716
+ uid: string;
1717
+ name: Record<"first" | "last", string>;
1718
+ publicKey: string | null;
1719
+ activated: boolean;
1720
+ lastModified?: number | null | undefined;
1721
+ email?: string | null | undefined;
1722
+ address?: {
1723
+ streetAddress: string;
1724
+ parish: string;
1725
+ country: string;
1726
+ city?: string | undefined;
1727
+ } | undefined;
1728
+ phoneNumber?: string | undefined;
1729
+ photoUrl?: string | null | undefined;
1730
+ dob?: number | undefined;
1731
+ };
1732
+ _hash: string;
1733
+ lastModified?: number | null | undefined;
1734
+ payload?: {
1735
+ lastModified: number | null;
1736
+ vitals: Record<"heartRate" | "respiratoryRate" | "bloodPressure" | "bloodOxygen" | "bodyTemp", {
1737
+ value: string;
1738
+ lastModified: number | null;
1739
+ }>;
1740
+ doctorNote: {
1741
+ value: string;
1742
+ lastModified: number | null;
1743
+ };
1744
+ prescriptions?: {
1745
+ createdAt: number;
1746
+ brand: string;
1747
+ quantity: string;
1748
+ refills: string;
1749
+ directions: string;
1750
+ lastModified?: number | null | undefined;
1751
+ expiresAt?: number | null | undefined;
1752
+ }[][] | null | undefined;
1753
+ physAsstNotes?: {
1754
+ createdAt: number;
1755
+ title: string;
1756
+ content: string;
1757
+ lastModified?: number | null | undefined;
1758
+ }[] | undefined;
1759
+ } | null | undefined;
1760
+ reason?: {
1761
+ createdAt: number;
1762
+ value: string;
1763
+ lastModified?: number | null | undefined;
1764
+ } | undefined;
1765
+ invoiceNo?: string | undefined;
1766
+ cancelled?: {
1767
+ doneAt: number;
1768
+ reason: {
1769
+ value: string;
1770
+ lastModified: number;
1771
+ };
1772
+ doneBy: "doc" | "physAsst";
1773
+ } | undefined;
1774
+ payments?: {
1775
+ createdAt: number;
1776
+ method: "cash" | "card" | "insurance";
1777
+ amount: number;
1778
+ lastModified?: number | null | undefined;
1779
+ }[] | null | undefined;
1780
+ };
1781
+ }>;
1782
+
1783
+ declare function findAvailableStaff(role: CompanyUserRole, staff: CompanyStaff): string[];
1784
+
1785
+ declare function findNextAvailableStaff(userUids: string[], algorithm: CompanyPreferences["serviceDistAlg"], staff: CompanyStaff): string | null;
1786
+
1356
1787
  /**@returns an array of the users that have conflicting roles or are incompatible with the other partners, or null if none was found. */
1357
1788
  declare const findConflictingPartners: (...partners: CompanyUser[]) => {
1358
1789
  uid: string;
@@ -1372,4 +1803,4 @@ declare const findConflictingPartners: (...partners: CompanyUser[]) => {
1372
1803
  /**@returns the roles that are compatible with the selected role. */
1373
1804
  declare const getCompatibleRoles: (role: CompanyUserRole) => CompanyUserRole[];
1374
1805
 
1375
- export { ClientIdentity, CompanyBilling, CompanyDetails, CompanyIdentity, CompanyInviteList, CompanyNotifications, type CompanyPartnerRole, CompanyPreferences, type CompanyServiceSelector, CompanyStaff, CompanyState, CompanyUser, type CompanyUserRole, CreateServiceForm, CreditCurrency, type EmployeeRole, type HealthcareProviderRole, InviteResponse, InvoiceNo, MedicalDetails, Medicine, MiniServiceDetails, MutableServiceDetails, Notification, type PaymentMethod, PriceAdjustment, PriceTag, Reason, Receipts, ServiceDetails, type ServiceDistAlg, StandardTime, TicketNo, type Tier, TierList, TimeLog, Timestamp, UserDetails, Vitals, companyPartnerRoles, companyServiceSelectors, companyUserRoles, employeeRoles, findConflictingPartners, getCompatibleRoles, healthcareProviderRoles, paymentMethods, serviceDistAlgs, serviceProviders, tiers, vitalKeys };
1806
+ export { ClientIdentity, CompanyBilling, CompanyDetails, CompanyIdentity, CompanyInviteList, CompanyNotifications, type CompanyPartnerRole, CompanyPreferences, type CompanyServiceSelector, CompanyStaff, CompanyState, CompanyUser, type CompanyUserRole, CreateServiceForm, CreditCurrency, type EmployeeRole, type HealthcareProviderRole, InviteResponse, InvoiceNo, MedicalDetails, Medicine, MiniServiceDetails, MutableCompanyBilling, MutableCompanyDetails, MutableCompanyIdentity, MutableCompanyPreferences, MutableServiceDetails, Notification, type PaymentMethod, PriceAdjustment, PriceTag, Reason, Receipts, ServiceDetails, type ServiceDistAlg, StandardTime, TicketNo, type Tier, TierList, TimeLog, Timestamp, UserDetails, Vitals, companyPartnerRoles, companyServiceSelectors, companyUserRoles, createCompanyService, employeeRoles, findAvailableStaff, findConflictingPartners, findNextAvailableStaff, getCompatibleRoles, healthcareProviderRoles, paymentMethods, serviceDistAlgs, serviceProviders, tiers, vitalKeys };
package/dist/main.js CHANGED
@@ -174,6 +174,10 @@ var CompanyBilling = z8.object({
174
174
  }),
175
175
  lastModified: Timestamp.nullable()
176
176
  });
177
+ var MutableCompanyBilling = CompanyBilling.omit({
178
+ uid: true,
179
+ lastModified: true
180
+ });
177
181
 
178
182
  // src/schemas/company/components/Identity.ts
179
183
  import * as z9 from "zod";
@@ -202,6 +206,12 @@ var CompanyIdentity = z9.object({
202
206
  }),
203
207
  lastModified: Timestamp.nullable()
204
208
  });
209
+ var MutableCompanyIdentity = CompanyIdentity.pick({
210
+ address: true,
211
+ contact: true,
212
+ logo: true,
213
+ legal: true
214
+ });
205
215
 
206
216
  // src/schemas/company/components/Notifications.ts
207
217
  import * as z11 from "zod";
@@ -299,6 +309,10 @@ var CompanyPreferences = z12.object({
299
309
  (data) => !data.enforcePaidServices || data.enforcePaidServices && data.serviceSelector === "scheduler",
300
310
  'Enforcing paid appointments is only allowed when the service selector is the "scheduler".'
301
311
  );
312
+ var MutableCompanyPreferences = CompanyPreferences.omit({
313
+ uid: true,
314
+ lastModified: true
315
+ });
302
316
 
303
317
  // src/schemas/company/components/Staff.ts
304
318
  import * as z15 from "zod";
@@ -495,6 +509,10 @@ var CompanyStaff = RawCompanyStaff.transform((d) => {
495
509
  }
496
510
  }
497
511
  });
512
+ var MutableCompanyStaff = RawCompanyStaff.pick({
513
+ updateQueue: true,
514
+ partnerMap: true
515
+ });
498
516
 
499
517
  // src/schemas/company/CompanyDetails.ts
500
518
  var CompanyDetails = z16.object({
@@ -507,6 +525,13 @@ var CompanyDetails = z16.object({
507
525
  billing: CompanyBilling.omit({ uid: true }),
508
526
  staff: RawCompanyStaff.omit({ uid: true })
509
527
  });
528
+ var MutableCompanyDetails = z16.object({
529
+ uid: CompanyDetails.shape.uid,
530
+ identity: MutableCompanyIdentity.partial().optional(),
531
+ preferences: MutableCompanyPreferences.partial().optional(),
532
+ billing: MutableCompanyBilling.partial().optional(),
533
+ staff: MutableCompanyStaff.partial().optional()
534
+ });
510
535
 
511
536
  // src/schemas/company/utils/InviteList.ts
512
537
  import * as z17 from "zod";
@@ -647,6 +672,173 @@ var CreateServiceForm = z19.object({
647
672
  // src/functions/createCompanyService.ts
648
673
  import { findChanges, omit, TODO } from "@wavy/fn";
649
674
  import { v4 } from "uuid";
675
+
676
+ // src/functions/findAvailableStaff.ts
677
+ function findAvailableStaff(role, staff) {
678
+ return Object.keys(role === "doc" ? staff.partnerMap : staff.members).filter(
679
+ (uid) => {
680
+ const user = staff.members[uid];
681
+ return !(uid in staff.updateQueue) && user.roles.includes(role) && user.status === "active" && user.isAvailable;
682
+ }
683
+ );
684
+ }
685
+
686
+ // src/functions/findNextAvailableStaff.ts
687
+ function findNextAvailableStaff(userUids, algorithm, staff) {
688
+ let nextAvailable = null;
689
+ if (userUids.length === 1) return userUids[0];
690
+ switch (algorithm) {
691
+ case "RR": {
692
+ nextAvailable = userUids.find(
693
+ (uid) => staff.members[uid].services.ongoing < staff.members[userUids[0]].services.ongoing
694
+ ) || userUids[0];
695
+ break;
696
+ }
697
+ case "LOR": {
698
+ for (const uid of userUids) {
699
+ const user = staff.members[uid];
700
+ if (!nextAvailable || user.services.ongoing < staff.members[nextAvailable].services.ongoing) {
701
+ nextAvailable = uid;
702
+ }
703
+ }
704
+ break;
705
+ }
706
+ default:
707
+ return algorithm;
708
+ }
709
+ return nextAvailable;
710
+ }
711
+
712
+ // src/functions/createCompanyService.ts
713
+ async function createCompanyService(request) {
714
+ request.form = CreateServiceForm.parse(request.form);
715
+ request.sender = UserDetails.parse(request.sender);
716
+ request.preferences = CompanyPreferences.omit({
717
+ uid: true,
718
+ lastModified: true
719
+ }).parse(request.preferences);
720
+ request.billing = CompanyBilling.omit({
721
+ uid: true,
722
+ prepayments: true,
723
+ lastModified: true
724
+ }).parse(request.billing);
725
+ const companyUser = request.staff?.members[request.sender.uid];
726
+ const staffDetailsCopy = CompanyStaff.parse(structuredClone(request.staff));
727
+ const stateCopy = CompanyState.parse(structuredClone(request.state));
728
+ let selectedDoctor = null;
729
+ let selectedPhysAsst = null;
730
+ const availableDoctors = findAvailableStaff("doc", staffDetailsCopy);
731
+ const today = Date.now();
732
+ if (!companyUser || !companyUser?.roles?.includes?.("rcpst")) {
733
+ throw new Error("Permissions missing.");
734
+ }
735
+ if (availableDoctors.length < 1) {
736
+ throw new Error("Insufficient staff available.");
737
+ }
738
+ if (request.form.serviceProviderUid && availableDoctors.includes(request.form.serviceProviderUid)) {
739
+ selectedDoctor = request.form.serviceProviderUid;
740
+ } else if (request.form.serviceProviderUid && staffDetailsCopy.members[request.form.serviceProviderUid]?.roles?.includes?.("doc")) {
741
+ throw new Error("Unavailable doctor selected.");
742
+ } else if (request.form.serviceProviderUid) {
743
+ throw new Error("Invalid doctor selected.");
744
+ }
745
+ if (request.form.serviceProviderUid === null || request.form.serviceProviderUid === void 0) {
746
+ selectedDoctor = findNextAvailableStaff(
747
+ availableDoctors,
748
+ request.preferences.serviceDistAlg,
749
+ staffDetailsCopy
750
+ );
751
+ }
752
+ if (!selectedDoctor) {
753
+ throw new Error(
754
+ "Internal error found. Failed to find an available doctor."
755
+ );
756
+ } else {
757
+ selectedPhysAsst = findNextAvailableStaff(
758
+ Object.keys(staffDetailsCopy.partnerMap[selectedDoctor]),
759
+ "LOR",
760
+ staffDetailsCopy
761
+ );
762
+ }
763
+ if (request.preferences.serviceSelector === "scheduler" && (!request.form.charges || request.form.charges.length < 1)) {
764
+ throw new Error("Insufficient services selected.");
765
+ } else if (request.preferences.serviceSelector === "scheduler" && request.billing.services.deployed && request.form.charges.find(
766
+ (service2) => !!Object.values(request.billing.services.value).find(
767
+ (predefService) => findChanges(service2, predefService).length > 0
768
+ )
769
+ )) {
770
+ throw new Error("Invalid service(s) selected.");
771
+ }
772
+ if (request.preferences.enforcePaidServices && (!request.form.payments || request.form.payments.length < 1)) {
773
+ throw new Error("Insufficient payment transactions recorded.");
774
+ } else if (request.preferences.enforcePaidServices) {
775
+ const maxIterations = Math.max(
776
+ request.form.charges.length,
777
+ request.form.payments.length
778
+ );
779
+ let totalPaid = 0;
780
+ let totalOwed = 0;
781
+ for (let idx = 0; idx < maxIterations; idx++) {
782
+ totalPaid += request.form.payments[idx]?.amount || 0;
783
+ totalOwed += request.form.charges[idx]?.cost || 0;
784
+ }
785
+ if (totalPaid < totalOwed) throw new Error("Insufficient payments made.");
786
+ }
787
+ if (stateCopy.credits.current < request.cost) {
788
+ if (companyUser.roles.includes("admin")) {
789
+ throw new Error("Account balance has insufficient funds.");
790
+ } else {
791
+ throw new Error(
792
+ "Something went wrong. Please contact an admin to rectify the problem."
793
+ );
794
+ }
795
+ }
796
+ stateCopy.tktNoCounter++;
797
+ stateCopy.credits.current -= request.cost;
798
+ stateCopy.credits.lastModified = today;
799
+ stateCopy.lastModified = today;
800
+ staffDetailsCopy.members[selectedDoctor].services.ongoing++;
801
+ if (selectedPhysAsst) {
802
+ staffDetailsCopy.members[selectedPhysAsst].services.ongoing++;
803
+ }
804
+ staffDetailsCopy.lastModified = today;
805
+ const service = {
806
+ _id: v4(),
807
+ src: stateCopy.uid,
808
+ tkt: request.state.tktNoCounter,
809
+ discounts: Object.values(request.billing.discounts || {}).filter(
810
+ (disc) => !disc.isOptional
811
+ ),
812
+ additionalFees: Object.values(request.billing.additionalFees || {}).filter(
813
+ (fee) => !fee.isOptional
814
+ ),
815
+ payments: request.preferences.enforcePaidServices ? request.form.payments : null,
816
+ prepayments: request.preferences.enforcePaidServices ? request.form.prepayments || [] : null,
817
+ charges: request.preferences.serviceSelector === "scheduler" ? request.form.charges : [],
818
+ client: await request.findClient(request.form.clientUid),
819
+ _hash: "aa.aa.aa",
820
+ lastModified: null,
821
+ timeline: {
822
+ scheduler: { userUid: request.sender.uid, postedAt: today },
823
+ doctor: { userUid: selectedDoctor },
824
+ physAsst: selectedPhysAsst ? { userUid: selectedPhysAsst } : "none",
825
+ get cashier() {
826
+ if (request.preferences.enforcePaidServices) return this.scheduler;
827
+ return null;
828
+ }
829
+ },
830
+ createdAt: today
831
+ };
832
+ TODO("Encrypt the service and assign the cipher text to _hash...");
833
+ service._hash = request.encryptCopy(omit(service, ["_hash"]));
834
+ return {
835
+ updates: {
836
+ state: stateCopy,
837
+ staffDetails: staffDetailsCopy
838
+ },
839
+ appointment: MutableServiceDetails.parse(service)
840
+ };
841
+ }
650
842
  export {
651
843
  ClientIdentity,
652
844
  CompanyBilling,
@@ -665,6 +857,10 @@ export {
665
857
  MedicalDetails,
666
858
  Medicine,
667
859
  MiniServiceDetails,
860
+ MutableCompanyBilling,
861
+ MutableCompanyDetails,
862
+ MutableCompanyIdentity,
863
+ MutableCompanyPreferences,
668
864
  MutableServiceDetails,
669
865
  Notification,
670
866
  PriceAdjustment,
@@ -682,8 +878,11 @@ export {
682
878
  companyPartnerRoles,
683
879
  companyServiceSelectors,
684
880
  companyUserRoles,
881
+ createCompanyService,
685
882
  employeeRoles,
883
+ findAvailableStaff,
686
884
  findConflictingPartners,
885
+ findNextAvailableStaff,
687
886
  getCompatibleRoles,
688
887
  healthcareProviderRoles,
689
888
  paymentMethods,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bizmap/sdk",
3
- "version": "0.0.58",
3
+ "version": "0.0.59",
4
4
  "main": "./dist/main.js",
5
5
  "types": "./dist/main.d.ts",
6
6
  "type": "module",