mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 07:41:16 +00:00
feat: scheduled report digests + per-session capacity (M33)
POST /v1/internal/jobs/reports/dispatch emails each tenant owner a trailing-window digest (bookings, revenue, per-service and per-staff breakdown) localized to the tenant locale; zero-activity tenants are skipped. Metrics cores extracted to tenant-scoped variants so the job needs no principal. PATCH /v1/catalog/class-sessions/:id sets a session's seat count with a confirmed-bookings floor — shrinking below it needs allowOverCapacity, matching the waitlist-promotion convention. Session rows gain an inline capacity editor with an overbook confirm state. 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
e6f1ec38a4
commit
e680e0c2b8
14 files changed
+808
-10
No files matched your search
@@ -461,7 +461,8 @@ export interface paths {
|
||||
delete: operations["deleteClassSession"];
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
/** Patch a class session (currently capacity only) */
|
||||
patch: operations["updateClassSession"];
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/catalog/class-sessions/{sessionID}/roster": {
|
||||
@@ -816,6 +817,23 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/internal/jobs/reports/dispatch": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/** Email each tenant owner a trailing-window business digest */
|
||||
post: operations["dispatchReportDigests"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/internal/jobs/sms/invoices": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1564,6 +1582,12 @@ export interface components {
|
||||
sentCount: number;
|
||||
skippedCount: number;
|
||||
};
|
||||
DispatchReportDigestsResponse: {
|
||||
failedCount: number;
|
||||
sentCount: number;
|
||||
skippedCount: number;
|
||||
tenantCount: number;
|
||||
};
|
||||
EmailTemplate: {
|
||||
bodyText?: string;
|
||||
isEnabled?: boolean;
|
||||
@@ -1922,6 +1946,11 @@ export interface components {
|
||||
/** @description Tenant-local start time, HH:MM */
|
||||
startsLocal?: string;
|
||||
};
|
||||
UpdateClassSessionRequest: {
|
||||
/** @description Permit shrinking below the confirmed seat count */
|
||||
allowOverCapacity?: boolean;
|
||||
capacity: number;
|
||||
};
|
||||
UpdateEmailTemplateRequest: {
|
||||
body?: string;
|
||||
isEnabled?: boolean;
|
||||
@@ -3039,6 +3068,53 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
updateClassSession: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
sessionID: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["UpdateClassSessionRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Updated class session */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ClassSession"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid request */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Class session not found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Capacity below confirmed bookings (pass allowOverCapacity to force) */
|
||||
409: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
getSessionRoster: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -3965,6 +4041,38 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
dispatchReportDigests: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/** @description Trailing window length in days */
|
||||
days?: number;
|
||||
/** @description Scope the run to a single tenant */
|
||||
tenantId?: string;
|
||||
};
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Digests dispatched */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["DispatchReportDigestsResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
generateSmsInvoices: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
Reference in new issue
Block a user