@blackcode_sa/metaestetics-api 1.15.17-staging.7 → 1.15.17-staging.9

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.mts CHANGED
@@ -10113,6 +10113,11 @@ declare class ResourceService extends BaseService {
10113
10113
  * Soft deletes a resource by setting status to INACTIVE
10114
10114
  */
10115
10115
  deleteResource(clinicBranchId: string, resourceId: string): Promise<void>;
10116
+ /**
10117
+ * Hard deletes a specific instance and all its calendar events.
10118
+ * Only works on INACTIVE instances with no future bookings.
10119
+ */
10120
+ hardDeleteInstance(clinicBranchId: string, resourceId: string, instanceId: string): Promise<void>;
10116
10121
  /**
10117
10122
  * Gets all instances for a resource
10118
10123
  */
@@ -10277,14 +10282,25 @@ declare const getFirebaseFunctions: () => Promise<Functions>;
10277
10282
  * what a given role (owner/admin/receptionist/assistant) can do.
10278
10283
  * New roles can be added by extending the ClinicRole enum and adding
10279
10284
  * a corresponding entry here.
10285
+ *
10286
+ * v2 (2026-03-31): Expanded from 23 to 40 permissions.
10287
+ * - providers.manage → providers.create, providers.invite, providers.edit
10288
+ * - staff.manage → staff.view, staff.edit, staff.invite, staff.delete, staff.viewTokens, staff.deleteTokens
10289
+ * - Added: clinic.create, calendar.addEvent, calendar.editEvent, calendar.deleteEvent,
10290
+ * appointments.reschedule, patients.viewDetails, patients.create, patients.manageTokens, billing.view
10280
10291
  */
10281
10292
  declare const PERMISSION_KEYS: {
10282
10293
  readonly 'clinic.view': true;
10283
10294
  readonly 'clinic.edit': true;
10295
+ readonly 'clinic.create': true;
10284
10296
  readonly 'reviews.view': true;
10285
10297
  readonly 'calendar.view': true;
10298
+ readonly 'calendar.addEvent': true;
10299
+ readonly 'calendar.editEvent': true;
10300
+ readonly 'calendar.deleteEvent': true;
10286
10301
  readonly 'appointments.view': true;
10287
10302
  readonly 'appointments.confirm': true;
10303
+ readonly 'appointments.reschedule': true;
10288
10304
  readonly 'appointments.cancel': true;
10289
10305
  readonly messaging: true;
10290
10306
  readonly 'procedures.view': true;
@@ -10296,12 +10312,23 @@ declare const PERMISSION_KEYS: {
10296
10312
  readonly 'resources.edit': true;
10297
10313
  readonly 'resources.delete': true;
10298
10314
  readonly 'patients.view': true;
10315
+ readonly 'patients.viewDetails': true;
10316
+ readonly 'patients.create': true;
10299
10317
  readonly 'patients.edit': true;
10318
+ readonly 'patients.manageTokens': true;
10300
10319
  readonly 'providers.view': true;
10301
- readonly 'providers.manage': true;
10320
+ readonly 'providers.create': true;
10321
+ readonly 'providers.invite': true;
10322
+ readonly 'providers.edit': true;
10302
10323
  readonly 'analytics.view': true;
10303
- readonly 'staff.manage': true;
10324
+ readonly 'staff.view': true;
10325
+ readonly 'staff.edit': true;
10326
+ readonly 'staff.invite': true;
10327
+ readonly 'staff.delete': true;
10328
+ readonly 'staff.viewTokens': true;
10329
+ readonly 'staff.deleteTokens': true;
10304
10330
  readonly 'settings.manage': true;
10331
+ readonly 'billing.view': true;
10305
10332
  readonly 'billing.manage': true;
10306
10333
  };
10307
10334
  type PermissionKey = keyof typeof PERMISSION_KEYS;
@@ -10343,7 +10370,7 @@ declare const PERMISSION_LABELS: Record<string, {
10343
10370
  category: string;
10344
10371
  }>;
10345
10372
  /** All unique permission categories in display order. */
10346
- declare const PERMISSION_CATEGORIES: readonly ["Clinic", "Calendar", "Appointments", "Messaging", "Procedures", "Resources", "Patients", "Providers", "Analytics", "Administration"];
10373
+ declare const PERMISSION_CATEGORIES: readonly ["Clinic", "Calendar", "Appointments", "Messaging", "Procedures", "Resources", "Patients", "Providers", "Analytics", "Staff Management", "Administration"];
10347
10374
  /**
10348
10375
  * Resolves the effective tier for a subscription model string.
10349
10376
  */
package/dist/index.d.ts CHANGED
@@ -10113,6 +10113,11 @@ declare class ResourceService extends BaseService {
10113
10113
  * Soft deletes a resource by setting status to INACTIVE
10114
10114
  */
10115
10115
  deleteResource(clinicBranchId: string, resourceId: string): Promise<void>;
10116
+ /**
10117
+ * Hard deletes a specific instance and all its calendar events.
10118
+ * Only works on INACTIVE instances with no future bookings.
10119
+ */
10120
+ hardDeleteInstance(clinicBranchId: string, resourceId: string, instanceId: string): Promise<void>;
10116
10121
  /**
10117
10122
  * Gets all instances for a resource
10118
10123
  */
@@ -10277,14 +10282,25 @@ declare const getFirebaseFunctions: () => Promise<Functions>;
10277
10282
  * what a given role (owner/admin/receptionist/assistant) can do.
10278
10283
  * New roles can be added by extending the ClinicRole enum and adding
10279
10284
  * a corresponding entry here.
10285
+ *
10286
+ * v2 (2026-03-31): Expanded from 23 to 40 permissions.
10287
+ * - providers.manage → providers.create, providers.invite, providers.edit
10288
+ * - staff.manage → staff.view, staff.edit, staff.invite, staff.delete, staff.viewTokens, staff.deleteTokens
10289
+ * - Added: clinic.create, calendar.addEvent, calendar.editEvent, calendar.deleteEvent,
10290
+ * appointments.reschedule, patients.viewDetails, patients.create, patients.manageTokens, billing.view
10280
10291
  */
10281
10292
  declare const PERMISSION_KEYS: {
10282
10293
  readonly 'clinic.view': true;
10283
10294
  readonly 'clinic.edit': true;
10295
+ readonly 'clinic.create': true;
10284
10296
  readonly 'reviews.view': true;
10285
10297
  readonly 'calendar.view': true;
10298
+ readonly 'calendar.addEvent': true;
10299
+ readonly 'calendar.editEvent': true;
10300
+ readonly 'calendar.deleteEvent': true;
10286
10301
  readonly 'appointments.view': true;
10287
10302
  readonly 'appointments.confirm': true;
10303
+ readonly 'appointments.reschedule': true;
10288
10304
  readonly 'appointments.cancel': true;
10289
10305
  readonly messaging: true;
10290
10306
  readonly 'procedures.view': true;
@@ -10296,12 +10312,23 @@ declare const PERMISSION_KEYS: {
10296
10312
  readonly 'resources.edit': true;
10297
10313
  readonly 'resources.delete': true;
10298
10314
  readonly 'patients.view': true;
10315
+ readonly 'patients.viewDetails': true;
10316
+ readonly 'patients.create': true;
10299
10317
  readonly 'patients.edit': true;
10318
+ readonly 'patients.manageTokens': true;
10300
10319
  readonly 'providers.view': true;
10301
- readonly 'providers.manage': true;
10320
+ readonly 'providers.create': true;
10321
+ readonly 'providers.invite': true;
10322
+ readonly 'providers.edit': true;
10302
10323
  readonly 'analytics.view': true;
10303
- readonly 'staff.manage': true;
10324
+ readonly 'staff.view': true;
10325
+ readonly 'staff.edit': true;
10326
+ readonly 'staff.invite': true;
10327
+ readonly 'staff.delete': true;
10328
+ readonly 'staff.viewTokens': true;
10329
+ readonly 'staff.deleteTokens': true;
10304
10330
  readonly 'settings.manage': true;
10331
+ readonly 'billing.view': true;
10305
10332
  readonly 'billing.manage': true;
10306
10333
  };
10307
10334
  type PermissionKey = keyof typeof PERMISSION_KEYS;
@@ -10343,7 +10370,7 @@ declare const PERMISSION_LABELS: Record<string, {
10343
10370
  category: string;
10344
10371
  }>;
10345
10372
  /** All unique permission categories in display order. */
10346
- declare const PERMISSION_CATEGORIES: readonly ["Clinic", "Calendar", "Appointments", "Messaging", "Procedures", "Resources", "Patients", "Providers", "Analytics", "Administration"];
10373
+ declare const PERMISSION_CATEGORIES: readonly ["Clinic", "Calendar", "Appointments", "Messaging", "Procedures", "Resources", "Patients", "Providers", "Analytics", "Staff Management", "Administration"];
10347
10374
  /**
10348
10375
  * Resolves the effective tier for a subscription model string.
10349
10376
  */
package/dist/index.js CHANGED
@@ -12751,14 +12751,20 @@ var import_firestore36 = require("firebase/firestore");
12751
12751
 
12752
12752
  // src/config/tiers.config.ts
12753
12753
  var PERMISSION_KEYS = {
12754
- // Listing & profile
12754
+ // Clinic
12755
12755
  "clinic.view": true,
12756
12756
  "clinic.edit": true,
12757
+ "clinic.create": true,
12757
12758
  "reviews.view": true,
12758
- // Calendar & Appointments
12759
+ // Calendar
12759
12760
  "calendar.view": true,
12761
+ "calendar.addEvent": true,
12762
+ "calendar.editEvent": true,
12763
+ "calendar.deleteEvent": true,
12764
+ // Appointments
12760
12765
  "appointments.view": true,
12761
12766
  "appointments.confirm": true,
12767
+ "appointments.reschedule": true,
12762
12768
  "appointments.cancel": true,
12763
12769
  // Messaging
12764
12770
  "messaging": true,
@@ -12774,16 +12780,27 @@ var PERMISSION_KEYS = {
12774
12780
  "resources.delete": true,
12775
12781
  // Patients
12776
12782
  "patients.view": true,
12783
+ "patients.viewDetails": true,
12784
+ "patients.create": true,
12777
12785
  "patients.edit": true,
12786
+ "patients.manageTokens": true,
12778
12787
  // Providers (doctors, nurses, laser assistants, etc.)
12779
12788
  "providers.view": true,
12780
- "providers.manage": true,
12789
+ "providers.create": true,
12790
+ "providers.invite": true,
12791
+ "providers.edit": true,
12781
12792
  // Analytics
12782
12793
  "analytics.view": true,
12783
12794
  // Staff management
12784
- "staff.manage": true,
12795
+ "staff.view": true,
12796
+ "staff.edit": true,
12797
+ "staff.invite": true,
12798
+ "staff.delete": true,
12799
+ "staff.viewTokens": true,
12800
+ "staff.deleteTokens": true,
12785
12801
  // Settings / Admin
12786
12802
  "settings.manage": true,
12803
+ "billing.view": true,
12787
12804
  "billing.manage": true
12788
12805
  };
12789
12806
  var TIER_CONFIG = {
@@ -12819,10 +12836,15 @@ var DEFAULT_ROLE_PERMISSIONS = {
12819
12836
  ["owner" /* OWNER */]: {
12820
12837
  "clinic.view": true,
12821
12838
  "clinic.edit": true,
12839
+ "clinic.create": true,
12822
12840
  "reviews.view": true,
12823
12841
  "calendar.view": true,
12842
+ "calendar.addEvent": true,
12843
+ "calendar.editEvent": true,
12844
+ "calendar.deleteEvent": true,
12824
12845
  "appointments.view": true,
12825
12846
  "appointments.confirm": true,
12847
+ "appointments.reschedule": true,
12826
12848
  "appointments.cancel": true,
12827
12849
  "messaging": true,
12828
12850
  "procedures.view": true,
@@ -12834,21 +12856,37 @@ var DEFAULT_ROLE_PERMISSIONS = {
12834
12856
  "resources.edit": true,
12835
12857
  "resources.delete": true,
12836
12858
  "patients.view": true,
12859
+ "patients.viewDetails": true,
12860
+ "patients.create": true,
12837
12861
  "patients.edit": true,
12862
+ "patients.manageTokens": true,
12838
12863
  "providers.view": true,
12839
- "providers.manage": true,
12864
+ "providers.create": true,
12865
+ "providers.invite": true,
12866
+ "providers.edit": true,
12840
12867
  "analytics.view": true,
12841
- "staff.manage": true,
12868
+ "staff.view": true,
12869
+ "staff.edit": true,
12870
+ "staff.invite": true,
12871
+ "staff.delete": true,
12872
+ "staff.viewTokens": true,
12873
+ "staff.deleteTokens": true,
12842
12874
  "settings.manage": true,
12875
+ "billing.view": true,
12843
12876
  "billing.manage": true
12844
12877
  },
12845
12878
  ["admin" /* ADMIN */]: {
12846
12879
  "clinic.view": true,
12847
12880
  "clinic.edit": true,
12881
+ "clinic.create": false,
12848
12882
  "reviews.view": true,
12849
12883
  "calendar.view": true,
12884
+ "calendar.addEvent": true,
12885
+ "calendar.editEvent": true,
12886
+ "calendar.deleteEvent": true,
12850
12887
  "appointments.view": true,
12851
12888
  "appointments.confirm": true,
12889
+ "appointments.reschedule": true,
12852
12890
  "appointments.cancel": true,
12853
12891
  "messaging": true,
12854
12892
  "procedures.view": true,
@@ -12860,21 +12898,37 @@ var DEFAULT_ROLE_PERMISSIONS = {
12860
12898
  "resources.edit": true,
12861
12899
  "resources.delete": true,
12862
12900
  "patients.view": true,
12901
+ "patients.viewDetails": true,
12902
+ "patients.create": true,
12863
12903
  "patients.edit": true,
12904
+ "patients.manageTokens": true,
12864
12905
  "providers.view": true,
12865
- "providers.manage": true,
12906
+ "providers.create": true,
12907
+ "providers.invite": true,
12908
+ "providers.edit": true,
12866
12909
  "analytics.view": true,
12867
- "staff.manage": false,
12910
+ "staff.view": true,
12911
+ "staff.edit": false,
12912
+ "staff.invite": false,
12913
+ "staff.delete": false,
12914
+ "staff.viewTokens": false,
12915
+ "staff.deleteTokens": false,
12868
12916
  "settings.manage": true,
12917
+ "billing.view": true,
12869
12918
  "billing.manage": false
12870
12919
  },
12871
12920
  ["receptionist" /* RECEPTIONIST */]: {
12872
12921
  "clinic.view": true,
12873
12922
  "clinic.edit": false,
12923
+ "clinic.create": false,
12874
12924
  "reviews.view": true,
12875
12925
  "calendar.view": true,
12926
+ "calendar.addEvent": true,
12927
+ "calendar.editEvent": false,
12928
+ "calendar.deleteEvent": false,
12876
12929
  "appointments.view": true,
12877
12930
  "appointments.confirm": true,
12931
+ "appointments.reschedule": true,
12878
12932
  "appointments.cancel": false,
12879
12933
  "messaging": true,
12880
12934
  "procedures.view": true,
@@ -12886,21 +12940,37 @@ var DEFAULT_ROLE_PERMISSIONS = {
12886
12940
  "resources.edit": false,
12887
12941
  "resources.delete": false,
12888
12942
  "patients.view": true,
12943
+ "patients.viewDetails": true,
12944
+ "patients.create": true,
12889
12945
  "patients.edit": false,
12946
+ "patients.manageTokens": false,
12890
12947
  "providers.view": true,
12891
- "providers.manage": false,
12948
+ "providers.create": false,
12949
+ "providers.invite": false,
12950
+ "providers.edit": false,
12892
12951
  "analytics.view": false,
12893
- "staff.manage": false,
12952
+ "staff.view": false,
12953
+ "staff.edit": false,
12954
+ "staff.invite": false,
12955
+ "staff.delete": false,
12956
+ "staff.viewTokens": false,
12957
+ "staff.deleteTokens": false,
12894
12958
  "settings.manage": false,
12959
+ "billing.view": false,
12895
12960
  "billing.manage": false
12896
12961
  },
12897
12962
  ["assistant" /* ASSISTANT */]: {
12898
12963
  "clinic.view": true,
12899
12964
  "clinic.edit": false,
12965
+ "clinic.create": false,
12900
12966
  "reviews.view": true,
12901
12967
  "calendar.view": true,
12968
+ "calendar.addEvent": false,
12969
+ "calendar.editEvent": false,
12970
+ "calendar.deleteEvent": false,
12902
12971
  "appointments.view": true,
12903
12972
  "appointments.confirm": false,
12973
+ "appointments.reschedule": false,
12904
12974
  "appointments.cancel": false,
12905
12975
  "messaging": false,
12906
12976
  "procedures.view": true,
@@ -12912,12 +12982,23 @@ var DEFAULT_ROLE_PERMISSIONS = {
12912
12982
  "resources.edit": false,
12913
12983
  "resources.delete": false,
12914
12984
  "patients.view": true,
12985
+ "patients.viewDetails": false,
12986
+ "patients.create": false,
12915
12987
  "patients.edit": false,
12988
+ "patients.manageTokens": false,
12916
12989
  "providers.view": true,
12917
- "providers.manage": false,
12990
+ "providers.create": false,
12991
+ "providers.invite": false,
12992
+ "providers.edit": false,
12918
12993
  "analytics.view": false,
12919
- "staff.manage": false,
12994
+ "staff.view": false,
12995
+ "staff.edit": false,
12996
+ "staff.invite": false,
12997
+ "staff.delete": false,
12998
+ "staff.viewTokens": false,
12999
+ "staff.deleteTokens": false,
12920
13000
  "settings.manage": false,
13001
+ "billing.view": false,
12921
13002
  "billing.manage": false
12922
13003
  }
12923
13004
  };
@@ -13004,28 +13085,44 @@ var DEFAULT_PLAN_CONFIG = {
13004
13085
  var PERMISSION_LABELS = {
13005
13086
  "clinic.view": { label: "View Clinic", description: "See clinic information and profile", category: "Clinic" },
13006
13087
  "clinic.edit": { label: "Edit Clinic", description: "Modify clinic settings and profile", category: "Clinic" },
13088
+ "clinic.create": { label: "Create Clinic", description: "Create new clinic branches", category: "Clinic" },
13007
13089
  "reviews.view": { label: "View Reviews", description: "See patient reviews and ratings", category: "Clinic" },
13008
13090
  "calendar.view": { label: "View Calendar", description: "See the clinic calendar and schedules", category: "Calendar" },
13091
+ "calendar.addEvent": { label: "Add Events", description: "Create appointments and blocking events on the calendar", category: "Calendar" },
13092
+ "calendar.editEvent": { label: "Edit Events", description: "Edit blocking events on the calendar", category: "Calendar" },
13093
+ "calendar.deleteEvent": { label: "Delete Events", description: "Delete blocking events from the calendar", category: "Calendar" },
13009
13094
  "appointments.view": { label: "View Appointments", description: "See appointment list and details", category: "Appointments" },
13010
- "appointments.confirm": { label: "Confirm Appointments", description: "Confirm pending appointment requests", category: "Appointments" },
13095
+ "appointments.confirm": { label: "Confirm Appointments", description: "Confirm, reject, check in, and manage appointment status", category: "Appointments" },
13096
+ "appointments.reschedule": { label: "Reschedule Appointments", description: "Reschedule confirmed appointments to a new time", category: "Appointments" },
13011
13097
  "appointments.cancel": { label: "Cancel Appointments", description: "Cancel existing appointments", category: "Appointments" },
13012
13098
  "messaging": { label: "Messaging", description: "Send and receive messages with patients", category: "Messaging" },
13013
13099
  "procedures.view": { label: "View Procedures", description: "See the procedures catalog", category: "Procedures" },
13014
- "procedures.create": { label: "Create Procedures", description: "Add new procedures to the catalog", category: "Procedures" },
13100
+ "procedures.create": { label: "Create Procedures", description: "Add new procedures and assign to practitioners", category: "Procedures" },
13015
13101
  "procedures.edit": { label: "Edit Procedures", description: "Modify existing procedures", category: "Procedures" },
13016
13102
  "procedures.delete": { label: "Delete Procedures", description: "Remove procedures from the catalog", category: "Procedures" },
13017
13103
  "resources.view": { label: "View Resources", description: "See clinic resources and equipment", category: "Resources" },
13018
13104
  "resources.create": { label: "Create Resources", description: "Add new resources", category: "Resources" },
13019
- "resources.edit": { label: "Edit Resources", description: "Modify existing resources", category: "Resources" },
13020
- "resources.delete": { label: "Delete Resources", description: "Remove resources", category: "Resources" },
13021
- "patients.view": { label: "View Patients", description: "See patient list and profiles", category: "Patients" },
13022
- "patients.edit": { label: "Edit Patients", description: "Modify patient records", category: "Patients" },
13105
+ "resources.edit": { label: "Edit Resources", description: "Modify existing resources and activate instances", category: "Resources" },
13106
+ "resources.delete": { label: "Delete Resources", description: "Deactivate resources and delete instances", category: "Resources" },
13107
+ "patients.view": { label: "View Patients", description: "See patient list", category: "Patients" },
13108
+ "patients.viewDetails": { label: "View Patient Details", description: "Open patient file and detailed profile", category: "Patients" },
13109
+ "patients.create": { label: "Create Patients", description: "Add new patients", category: "Patients" },
13110
+ "patients.edit": { label: "Edit Patients", description: "Modify patient records and schedule appointments", category: "Patients" },
13111
+ "patients.manageTokens": { label: "Manage Patient Tokens", description: "Create and manage patient invitation tokens", category: "Patients" },
13023
13112
  "providers.view": { label: "View Providers", description: "See the practitioners/providers list", category: "Providers" },
13024
- "providers.manage": { label: "Manage Providers", description: "Add, edit, or remove providers", category: "Providers" },
13113
+ "providers.create": { label: "Create Providers", description: "Add new practitioners to the clinic", category: "Providers" },
13114
+ "providers.invite": { label: "Invite Providers", description: "Invite existing practitioners to the clinic", category: "Providers" },
13115
+ "providers.edit": { label: "Edit Providers", description: "Edit practitioner profiles and manage tokens", category: "Providers" },
13025
13116
  "analytics.view": { label: "View Analytics", description: "Access analytics dashboards and reports", category: "Analytics" },
13026
- "staff.manage": { label: "Manage Staff", description: "Add, remove, and assign roles to staff", category: "Administration" },
13117
+ "staff.view": { label: "View Staff", description: "See staff management page and team members", category: "Staff Management" },
13118
+ "staff.edit": { label: "Edit Staff", description: "Edit roles, permissions, and clinic assignments", category: "Staff Management" },
13119
+ "staff.invite": { label: "Invite Staff", description: "Invite new team members", category: "Staff Management" },
13120
+ "staff.delete": { label: "Delete Staff", description: "Remove team members and cancel invitations", category: "Staff Management" },
13121
+ "staff.viewTokens": { label: "View Tokens", description: "See registration tokens", category: "Staff Management" },
13122
+ "staff.deleteTokens": { label: "Delete Tokens", description: "Delete registration tokens", category: "Staff Management" },
13027
13123
  "settings.manage": { label: "Manage Settings", description: "Modify clinic group settings", category: "Administration" },
13028
- "billing.manage": { label: "Manage Billing", description: "Access billing, subscriptions, and payments", category: "Administration" }
13124
+ "billing.view": { label: "View Billing", description: "View subscription plans and billing history", category: "Administration" },
13125
+ "billing.manage": { label: "Manage Billing", description: "Manage subscriptions, upgrades, and payments", category: "Administration" }
13029
13126
  };
13030
13127
  var PERMISSION_CATEGORIES = [
13031
13128
  "Clinic",
@@ -13037,6 +13134,7 @@ var PERMISSION_CATEGORIES = [
13037
13134
  "Patients",
13038
13135
  "Providers",
13039
13136
  "Analytics",
13137
+ "Staff Management",
13040
13138
  "Administration"
13041
13139
  ];
13042
13140
  var TIER_MAP = {
@@ -25151,24 +25249,46 @@ var ResourceService = class extends BaseService {
25151
25249
  if (data.status !== void 0) updateData.status = data.status;
25152
25250
  if (data.quantity !== void 0 && data.quantity !== existing.quantity) {
25153
25251
  if (data.quantity > existing.quantity) {
25252
+ const allInstances = await this.getResourceInstances(clinicBranchId, resourceId);
25253
+ const activeInstances = allInstances.filter((i) => i.status === "active" /* ACTIVE */);
25254
+ const inactiveInstances = allInstances.filter((i) => i.status === "inactive" /* INACTIVE */);
25255
+ const needed = data.quantity - activeInstances.length;
25154
25256
  const batch = (0, import_firestore65.writeBatch)(this.db);
25155
25257
  const now = (0, import_firestore65.serverTimestamp)();
25156
25258
  const resourceName = data.name || existing.name;
25157
- for (let i = existing.quantity + 1; i <= data.quantity; i++) {
25259
+ let reactivated = 0;
25260
+ const sortedInactive = [...inactiveInstances].sort((a, b) => a.index - b.index);
25261
+ for (const instance of sortedInactive) {
25262
+ if (reactivated >= needed) break;
25158
25263
  const instanceRef = (0, import_firestore65.doc)(
25159
- this.getInstancesRef(clinicBranchId, resourceId)
25264
+ this.getInstancesRef(clinicBranchId, resourceId),
25265
+ instance.id
25160
25266
  );
25161
- const instanceData = {
25162
- id: instanceRef.id,
25163
- resourceId,
25164
- clinicBranchId,
25165
- label: `${resourceName} #${i}`,
25166
- index: i,
25267
+ batch.update(instanceRef, {
25167
25268
  status: "active" /* ACTIVE */,
25168
- createdAt: now,
25169
25269
  updatedAt: now
25170
- };
25171
- batch.set(instanceRef, instanceData);
25270
+ });
25271
+ reactivated++;
25272
+ }
25273
+ const remaining = needed - reactivated;
25274
+ if (remaining > 0) {
25275
+ const maxIndex = allInstances.reduce((max, i) => Math.max(max, i.index), 0);
25276
+ for (let i = 1; i <= remaining; i++) {
25277
+ const instanceRef = (0, import_firestore65.doc)(
25278
+ this.getInstancesRef(clinicBranchId, resourceId)
25279
+ );
25280
+ const instanceData = {
25281
+ id: instanceRef.id,
25282
+ resourceId,
25283
+ clinicBranchId,
25284
+ label: `${resourceName} #${maxIndex + i}`,
25285
+ index: maxIndex + i,
25286
+ status: "active" /* ACTIVE */,
25287
+ createdAt: now,
25288
+ updatedAt: now
25289
+ };
25290
+ batch.set(instanceRef, instanceData);
25291
+ }
25172
25292
  }
25173
25293
  updateData.quantity = data.quantity;
25174
25294
  const resourceDocRef2 = this.getResourceDocRef(
@@ -25235,6 +25355,40 @@ var ResourceService = class extends BaseService {
25235
25355
  status: "inactive" /* INACTIVE */
25236
25356
  });
25237
25357
  }
25358
+ /**
25359
+ * Hard deletes a specific instance and all its calendar events.
25360
+ * Only works on INACTIVE instances with no future bookings.
25361
+ */
25362
+ async hardDeleteInstance(clinicBranchId, resourceId, instanceId) {
25363
+ const instanceRef = (0, import_firestore65.doc)(
25364
+ this.getInstancesRef(clinicBranchId, resourceId),
25365
+ instanceId
25366
+ );
25367
+ const instanceSnap = await (0, import_firestore65.getDoc)(instanceRef);
25368
+ if (!instanceSnap.exists()) throw new Error("Instance not found");
25369
+ const instance = instanceSnap.data();
25370
+ if (instance.status === "active" /* ACTIVE */) {
25371
+ throw new Error("Cannot hard-delete an active instance. Deactivate it first.");
25372
+ }
25373
+ const hasFutureBookings = await this.instanceHasFutureBookings(
25374
+ clinicBranchId,
25375
+ resourceId,
25376
+ instanceId
25377
+ );
25378
+ if (hasFutureBookings) {
25379
+ throw new Error("Cannot delete instance with future bookings.");
25380
+ }
25381
+ const calendarRef = this.getInstanceCalendarRef(
25382
+ clinicBranchId,
25383
+ resourceId,
25384
+ instanceId
25385
+ );
25386
+ const calendarSnap = await (0, import_firestore65.getDocs)(calendarRef);
25387
+ const batch = (0, import_firestore65.writeBatch)(this.db);
25388
+ calendarSnap.docs.forEach((d) => batch.delete(d.ref));
25389
+ batch.delete(instanceRef);
25390
+ await batch.commit();
25391
+ }
25238
25392
  /**
25239
25393
  * Gets all instances for a resource
25240
25394
  */