mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 15:51:15 +00:00
feat(availability): per-staff working hours and class/session management
- Working-hours repo accepts nullable staff scope (pgx + memory); staff rules live in availability_rules and drive public slot generation - Protected routes for staff working hours, class templates, and class sessions with tenant-ownership checks and input validation - Sessions derive endsAt/capacity from templates; list resolves location names and live booked counts; template delete cascades sessions, session delete preserves bookings via SET NULL (mirrored in memory) - Zones page: staff-scope selector on working hours, new Classes tab with template/session CRUD, CS+EN strings, mobile tab wrapping - Normalize availability_rules times to HH:MM in the service layer Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
d9aa29dbcb
commit
0405106587
12 files changed
+2069
-58
No files matched your search
@@ -986,6 +986,171 @@ paths:
|
||||
description: Working hours updated
|
||||
"400":
|
||||
description: Invalid request
|
||||
/v1/catalog/staff/{staffID}/working-hours:
|
||||
get:
|
||||
tags: [Catalog]
|
||||
operationId: listStaffWorkingHours
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: staffID
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
"200":
|
||||
description: Staff member's weekly working hours
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/WorkingHours"
|
||||
"404":
|
||||
description: Staff member not found
|
||||
/v1/catalog/staff/{staffID}/working-hours/{dayOfWeek}:
|
||||
put:
|
||||
tags: [Catalog]
|
||||
operationId: updateStaffWorkingHours
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: staffID
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: path
|
||||
name: dayOfWeek
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 6
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UpdateWorkingHoursRequest"
|
||||
responses:
|
||||
"200":
|
||||
description: Staff working hours updated
|
||||
"400":
|
||||
description: Invalid request
|
||||
"404":
|
||||
description: Staff member not found
|
||||
/v1/catalog/class-templates:
|
||||
get:
|
||||
tags: [Catalog]
|
||||
operationId: listClassTemplates
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: Class templates
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/ClassTemplate"
|
||||
post:
|
||||
tags: [Catalog]
|
||||
operationId: createClassTemplate
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UpsertClassTemplateRequest"
|
||||
responses:
|
||||
"201":
|
||||
description: Class template created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ClassTemplate"
|
||||
"400":
|
||||
description: Invalid request
|
||||
/v1/catalog/class-templates/{templateID}:
|
||||
delete:
|
||||
tags: [Catalog]
|
||||
operationId: deleteClassTemplate
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: templateID
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
"200":
|
||||
description: Class template deleted
|
||||
"404":
|
||||
description: Class template not found
|
||||
/v1/catalog/class-sessions:
|
||||
get:
|
||||
tags: [Catalog]
|
||||
operationId: listClassSessions
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: Upcoming class sessions
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/ClassSession"
|
||||
post:
|
||||
tags: [Catalog]
|
||||
operationId: createClassSession
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CreateClassSessionRequest"
|
||||
responses:
|
||||
"201":
|
||||
description: Class session created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ClassSession"
|
||||
"400":
|
||||
description: Invalid request
|
||||
"404":
|
||||
description: Template or location not found
|
||||
/v1/catalog/class-sessions/{sessionID}:
|
||||
delete:
|
||||
tags: [Catalog]
|
||||
operationId: deleteClassSession
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: sessionID
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
"200":
|
||||
description: Class session deleted
|
||||
"404":
|
||||
description: Class session not found
|
||||
# ---------------- Billing ----------------
|
||||
/v1/billing/subscription:
|
||||
get:
|
||||
@@ -1880,6 +2045,80 @@ components:
|
||||
example: "18:00"
|
||||
isOpen:
|
||||
type: boolean
|
||||
ClassTemplate:
|
||||
type: object
|
||||
required: [id, tenantId, title, durationMinutes, capacity, createdAt]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
tenantId:
|
||||
type: string
|
||||
format: uuid
|
||||
title:
|
||||
type: string
|
||||
durationMinutes:
|
||||
type: integer
|
||||
capacity:
|
||||
type: integer
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
UpsertClassTemplateRequest:
|
||||
type: object
|
||||
required: [title, durationMinutes, capacity]
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
durationMinutes:
|
||||
type: integer
|
||||
capacity:
|
||||
type: integer
|
||||
ClassSession:
|
||||
type: object
|
||||
required: [id, tenantId, templateId, templateTitle, startsAt, endsAt, capacity, bookedCount]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
tenantId:
|
||||
type: string
|
||||
format: uuid
|
||||
templateId:
|
||||
type: string
|
||||
format: uuid
|
||||
templateTitle:
|
||||
type: string
|
||||
locationId:
|
||||
type: string
|
||||
format: uuid
|
||||
locationName:
|
||||
type: string
|
||||
startsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
endsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
capacity:
|
||||
type: integer
|
||||
bookedCount:
|
||||
type: integer
|
||||
CreateClassSessionRequest:
|
||||
type: object
|
||||
required: [templateId, startsAt]
|
||||
properties:
|
||||
templateId:
|
||||
type: string
|
||||
format: uuid
|
||||
locationId:
|
||||
type: string
|
||||
format: uuid
|
||||
startsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
capacity:
|
||||
type: integer
|
||||
PlanEntitlements:
|
||||
type: object
|
||||
required: [maxLocations, maxStaff, emailReminders, advancedReporting, widgetEmbedding, umamiTracking]
|
||||
|
||||
Reference in new issue
Block a user