# Resource Service (`Api/src/services/resource/`)

Server-side service for managing clinic resources and their instances. Extends `BaseService` and provides full CRUD operations backed by Firestore.

## File: `resource.service.ts`

### Class: `ResourceService extends BaseService`

#### Constructor

```typescript
constructor(db: Firestore, auth: Auth, app: FirebaseApp)
```

Inherits Firestore, Auth, and Firebase App from `BaseService`.

---

### Methods

#### `createResource(data: CreateResourceData): Promise<Resource>`

Creates a new resource and auto-generates instances.

- Validates input with `createResourceSchema` (Zod)
- Creates the `Resource` document under `clinics/{clinicBranchId}/resources/{id}`
- Batch-creates `N` `ResourceInstance` subdocuments (where N = `data.quantity`)
- Each instance gets label `"{name} #{index}"` (1-based)
- Returns the created `Resource`

#### `getResource(clinicBranchId: string, resourceId: string): Promise<Resource | null>`

Fetches a single resource by ID.

#### `getResourcesByClinic(clinicBranchId: string): Promise<Resource[]>`

Fetches all resources for a clinic branch.

#### `getActiveResourcesByClinic(clinicBranchId: string): Promise<Resource[]>`

Fetches only active resources (`status === 'active'`) for a clinic branch.

#### `updateResource(clinicBranchId: string, resourceId: string, data: UpdateResourceData): Promise<Resource>`

Updates a resource. Handles quantity changes:

- **Quantity increase**: Creates new instances starting from `currentQuantity + 1`
- **Quantity decrease**: Checks if affected instances (from the end) have future bookings. If any do, the operation is **rejected** with an error. Otherwise, instances are deactivated (status set to `inactive`).

#### `deleteResource(clinicBranchId: string, resourceId: string): Promise<void>`

Soft-deletes a resource by setting `status: 'inactive'`. Does not remove documents from Firestore.

#### `getResourceInstances(clinicBranchId: string, resourceId: string): Promise<ResourceInstance[]>`

Fetches all instances for a resource, ordered by `index`.

#### `getActiveResourceInstances(clinicBranchId: string, resourceId: string): Promise<ResourceInstance[]>`

Fetches only active instances (`status === 'active'`), ordered by `index`.

#### `getResourceCalendarEvents(clinicBranchId, resourceId, instanceId, start, end): Promise<ResourceCalendarEvent[]>`

Fetches calendar events for a specific instance within a time range. Used by the booking engine to check instance availability.

#### `instanceHasFutureBookings(clinicBranchId, resourceId, instanceId): Promise<boolean>`

Checks if an instance has any future booking events. Used when decreasing resource quantity to prevent deactivating instances with active bookings.

---

### Blocking Event Methods

CRUD operations for managing blocking events on resource instance calendars. Blocking events mark an instance as unavailable for a time period (maintenance, out of order, etc.).

#### `createResourceBlockingEvent(params: CreateResourceBlockingEventParams): Promise<ResourceCalendarEvent>`

Creates a blocking event on an instance's calendar.

- Validates input with `createResourceBlockingEventSchema` (Zod)
- Creates document at `clinics/{clinicBranchId}/resources/{resourceId}/instances/{instanceId}/calendar/{eventId}`
- Sets `eventType: BLOCKING`, `status: CONFIRMED`
- Appointment-specific fields are omitted

#### `updateResourceBlockingEvent(params: UpdateResourceBlockingEventParams): Promise<ResourceCalendarEvent>`

Updates an existing blocking event. Only provided fields are modified.

- Validates input with `updateResourceBlockingEventSchema`
- Verifies event exists before updating
- Returns the updated event

#### `deleteResourceBlockingEvent(clinicBranchId, resourceId, instanceId, eventId): Promise<void>`

Hard deletes a blocking event from the instance's calendar.

- Verifies event exists before deleting

#### `getResourceInstanceBlockingEvents(clinicBranchId, resourceId, instanceId): Promise<ResourceCalendarEvent[]>`

Fetches all blocking events for a specific instance, ordered by start time. Filters by `eventType == "blocking"`.

---

### Firestore Paths

| Entity | Path |
|--------|------|
| Resource | `clinics/{clinicBranchId}/resources/{resourceId}` |
| Instance | `clinics/{clinicBranchId}/resources/{resourceId}/instances/{instanceId}` |
| Calendar Event | `clinics/{clinicBranchId}/resources/{resourceId}/instances/{instanceId}/calendar/{eventId}` |

---

### Export

`index.ts` re-exports `ResourceService` from `resource.service.ts`. The service is also exported via `Api/src/services/index.ts`.

See [main Resource System README](../../../../docs/RESOURCE_SYSTEM.md) for the full system overview.
