@shophost/rest-api 2.0.69 → 2.0.70
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/package.json +1 -1
- package/schema.prisma +1 -0
- package/src/core/db/__generated__/client/internal/class.js +19 -18
- package/src/core/db/__generated__/client/internal/prismaNamespace.d.ts +1 -0
- package/src/core/db/__generated__/client/internal/prismaNamespace.js +1 -1
- package/src/core/db/__generated__/client/internal/prismaNamespaceBrowser.d.ts +1 -0
- package/src/core/db/__generated__/client/internal/prismaNamespaceBrowser.js +1 -1
- package/src/core/db/__generated__/client/models/Reservation.d.ts +42 -1
- package/src/features/customer/customer.route.d.ts +1 -0
- package/src/features/customer/customer.schema.d.ts +1 -0
- package/src/features/customer/customer.service.d.ts +1 -0
- package/src/features/reservation/emails/reservation-cancellation.email.js +1 -1
- package/src/features/reservation/reservation.handler.js +1 -1
- package/src/features/reservation/reservation.route.d.ts +10 -1
- package/src/features/reservation/reservation.route.js +1 -1
- package/src/features/reservation/reservation.schema.d.ts +5 -0
- package/src/features/reservation/reservation.schema.js +1 -1
- package/src/features/reservation/reservation.service.d.ts +9 -2
- package/src/features/reservation/reservation.service.js +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as a}from"@hono/zod-openapi";import{createApiRoute as t}from"../../core/hono/hono";import{CreateReservationSchema as p,ErrorSchema as e,HeaderSchema as r,OrganizationParams as n,PaginationMetaSchema as i,PaginationQuerySchema as d,ReservationListQuerySchema as v,ReservationSchema as
|
|
1
|
+
import{z as a}from"@hono/zod-openapi";import{createApiRoute as t}from"../../core/hono/hono";import{CreateReservationSchema as p,ErrorSchema as e,HeaderSchema as r,OrganizationParams as n,PaginationMetaSchema as i,PaginationQuerySchema as d,ReservationListQuerySchema as v,ReservationSchema as s,UpdateReservationSchema as m,UpdateReservationStatusSchema as c}from"../../schemas";const o=a.object({organizationId:a.string().openapi({description:"Organization ID",example:"clj1234567890abcdef",param:{in:"path",name:"organizationId"}}),reservationId:a.string().openapi({description:"Reservation ID",example:"clj1234567890abcdef",param:{in:"path",name:"reservationId"}})}),R=a.object({organizationId:a.string().openapi({description:"Organization ID",example:"clj1234567890abcdef",param:{in:"path",name:"organizationId"}}),userId:a.string().openapi({description:"User ID",example:"clj1234567890abcdef",param:{in:"path",name:"userId"}})}),h=o.extend({operation:a.enum(["accept","cancel"]).openapi({description:"Operation",example:"accept",param:{in:"path",name:"operation"}})}),u=t({body:p,description:"Create a new reservation",headers:r,method:"POST",operationId:"createReservation",path:"/:organizationId/reservations",pathParams:n,responses:{201:s,400:e,401:e,500:e},summary:"Create Reservation",tags:["Reservation"]}),g=t({description:"Get a specific reservation by ID",headers:r,method:"GET",operationId:"getReservation",path:"/:organizationId/reservations/:reservationId",pathParams:o,responses:{200:s,400:e,401:e,404:e,500:e},summary:"Get Reservation",tags:["Reservation"]}),I=t({description:"Get all reservations for an organization",headers:r,method:"GET",operationId:"getReservations",path:"/:organizationId/reservations",pathParams:n,query:v,responses:{200:a.object({list:a.array(s),meta:i}),400:e,401:e,500:e},summary:"Get Reservations",tags:["Reservation"]}),l=t({description:"Get paginated reservations for the authenticated user",headers:r,method:"GET",operationId:"getMyReservations",path:"/:organizationId/reservations/me",pathParams:n,query:d,responses:{200:a.object({list:a.array(s),meta:i}),400:e,401:e,500:e},summary:"Get My Reservations",tags:["Reservation"]}),y=t({description:"Get all reservations for a user",headers:r,method:"GET",operationId:"getUserReservations",path:"/:organizationId/reservations/user/:userId",pathParams:R,responses:{200:a.array(s),400:e,401:e,404:e,500:e},summary:"Get User Reservations",tags:["Reservation"]}),z=t({body:m,description:"Update an existing reservation",headers:r,method:"PATCH",operationId:"updateReservation",path:"/:organizationId/reservations/:reservationId",pathParams:o,responses:{200:s,400:e,401:e,404:e,500:e},summary:"Update Reservation",tags:["Reservation"]}),P=t({body:c,bodyRequired:!1,description:"Update the status of a reservation",headers:r,method:"PATCH",operationId:"updateReservationStatus",path:"/:organizationId/reservations/:reservationId/:operation",pathParams:h,responses:{200:s,400:e,401:e,404:e,500:e},summary:"Update Reservation Status",tags:["Reservation"]}),b=t({body:a.object({}).optional(),bodyRequired:!1,description:"Delete a reservation",headers:r,method:"DELETE",operationId:"deleteReservation",path:"/:organizationId/reservations/:reservationId",pathParams:o,responses:{204:null,400:e,401:e,404:e,500:e},summary:"Delete Reservation",tags:["Reservation"]});export const reservationRoute={createReservation:u,getReservation:g,getReservations:I,getMyReservations:l,getUserReservations:y,updateReservation:z,updateReservationStatus:P,deleteReservation:b};
|
|
@@ -9,6 +9,7 @@ export declare const ReservationSchema: z.ZodObject<{
|
|
|
9
9
|
referenceId: z.ZodString;
|
|
10
10
|
acceptedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
11
11
|
cancelledAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
12
|
+
cancellationMessage: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
12
13
|
createdAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
13
14
|
}, z.core.$strip>;
|
|
14
15
|
export declare const CreateReservationSchema: z.ZodObject<{
|
|
@@ -24,6 +25,9 @@ export declare const UpdateReservationSchema: z.ZodObject<{
|
|
|
24
25
|
firstname: z.ZodPipe<z.ZodAny, z.ZodTransform<string, any>>;
|
|
25
26
|
lastname: z.ZodPipe<z.ZodAny, z.ZodTransform<string, any>>;
|
|
26
27
|
}, z.core.$strip>;
|
|
28
|
+
export declare const UpdateReservationStatusSchema: z.ZodObject<{
|
|
29
|
+
message: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, z.core.$strip>;
|
|
27
31
|
export declare const ReservationListQuerySchema: z.ZodObject<{
|
|
28
32
|
page: z.ZodDefault<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
|
|
29
33
|
limit: z.ZodDefault<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
|
|
@@ -150,4 +154,5 @@ export declare const ReservationListQuerySchema: z.ZodObject<{
|
|
|
150
154
|
export type Reservation = z.infer<typeof ReservationSchema>;
|
|
151
155
|
export type CreateReservation = z.infer<typeof CreateReservationSchema>;
|
|
152
156
|
export type UpdateReservation = z.infer<typeof UpdateReservationSchema>;
|
|
157
|
+
export type UpdateReservationStatus = z.infer<typeof UpdateReservationStatusSchema>;
|
|
153
158
|
export type ReservationListQuery = z.infer<typeof ReservationListQuerySchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as
|
|
1
|
+
import{z as e}from"@hono/zod-openapi";import{requiredNumber as r}from"../../schemas/number.schema";import{PaginationQuerySchema as i}from"../../schemas/pagination.schema";const n=t=>e.any().transform(a=>typeof a=="string"?a.trim():"").refine(a=>a.length>0,{message:`${t} is required`}),o=e.any().transform(t=>t==null||t===""?Number.NaN:Number(t)).refine(t=>Number.isFinite(t)&&t>0,{message:"Number of guests is required"}),s=e.any().refine(t=>t!=null&&t!=="",{message:"Reservation date is required"}).transform(t=>new Date(t)).refine(t=>!Number.isNaN(t.getTime()),{message:"Reservation date is required"});export const ReservationSchema=e.object({id:e.string().openapi({description:"Unique identifier for the order",example:"clj1234567890abcdef"}),firstname:e.string().openapi({description:"Customer's first name",example:"John"}),lastname:e.string().openapi({description:"Customer's last name",example:"Doe"}),guests:r,phone:e.string().openapi({description:"Customer's phone number",example:"+1234567890"}),date:e.coerce.date().openapi({description:"Reservation date and time",example:"2023-06-14T16:20:00Z"}),referenceId:e.string().openapi({description:"External reference ID for the order",example:"ORD-12345"}),acceptedAt:e.date().nullable().optional().openapi({description:"Date when the order was accepted",example:"2023-06-15T14:30:00Z"}),cancelledAt:e.date().nullable().optional().openapi({description:"Date when the order was cancelled",example:"2023-06-14T16:20:00Z"}),cancellationMessage:e.string().nullable().optional().openapi({description:"Optional cancellation message sent to the user",example:"We need to close early tonight."}),createdAt:e.date().nullable().optional().openapi({description:"Date when the order was created",example:"2023-06-14T16:20:00Z"})}).openapi("Reservation"),CreateReservationSchema=ReservationSchema.pick({firstname:!0,lastname:!0,guests:!0,phone:!0,date:!0}).extend({firstname:n("First name").openapi({description:"Customer's first name",example:"John"}),lastname:n("Last name").openapi({description:"Customer's last name",example:"Doe"}),guests:o.openapi({description:"Number of guests included in the reservation",example:2}),phone:n("Phone number").openapi({description:"Customer's phone number",example:"+1234567890"}),date:s.openapi({description:"Reservation date and time",example:"2023-06-14T16:20:00Z"})}).openapi("CreateReservation"),UpdateReservationSchema=CreateReservationSchema.pick({firstname:!0,lastname:!0,guests:!0,date:!0}).openapi("UpdateReservation"),UpdateReservationStatusSchema=e.object({message:e.string().trim().min(1,"Message cannot be empty").max(1e3,"Message must be 1000 characters or fewer").optional().openapi({description:"Optional message sent to the user when cancelling a reservation",example:"We need to close early tonight. Please book another slot."})}).openapi("UpdateReservationStatus"),ReservationListQuerySchema=i.extend({from:e.coerce.date().optional().openapi({description:"Filter reservations scheduled from this date and time",example:"2026-03-01T00:00:00.000Z"}),to:e.coerce.date().optional().openapi({description:"Filter reservations scheduled up to this date and time",example:"2026-03-31T23:59:59.999Z"})}).openapi("ReservationListQuery");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "@hono/zod-openapi";
|
|
2
2
|
import { PrismaClientType } from "../../core/lib/prisma";
|
|
3
3
|
import { EmailService } from "../../core/notifications/email.service";
|
|
4
|
-
import { CreateReservationSchema, ReservationListQuery, UpdateReservationSchema, User } from "../../schemas";
|
|
4
|
+
import { CreateReservationSchema, ReservationListQuery, UpdateReservationSchema, UpdateReservationStatusSchema, User } from "../../schemas";
|
|
5
5
|
declare class ReservationService {
|
|
6
6
|
private readonly prisma;
|
|
7
7
|
private readonly emailService;
|
|
@@ -20,6 +20,7 @@ declare class ReservationService {
|
|
|
20
20
|
referenceId: string;
|
|
21
21
|
acceptedAt?: Date | null | undefined;
|
|
22
22
|
cancelledAt?: Date | null | undefined;
|
|
23
|
+
cancellationMessage?: string | null | undefined;
|
|
23
24
|
createdAt?: Date | null | undefined;
|
|
24
25
|
}>;
|
|
25
26
|
/**
|
|
@@ -35,6 +36,7 @@ declare class ReservationService {
|
|
|
35
36
|
referenceId: string;
|
|
36
37
|
acceptedAt?: Date | null | undefined;
|
|
37
38
|
cancelledAt?: Date | null | undefined;
|
|
39
|
+
cancellationMessage?: string | null | undefined;
|
|
38
40
|
createdAt?: Date | null | undefined;
|
|
39
41
|
}>;
|
|
40
42
|
/**
|
|
@@ -60,6 +62,7 @@ declare class ReservationService {
|
|
|
60
62
|
referenceId: string;
|
|
61
63
|
acceptedAt?: Date | null | undefined;
|
|
62
64
|
cancelledAt?: Date | null | undefined;
|
|
65
|
+
cancellationMessage?: string | null | undefined;
|
|
63
66
|
createdAt?: Date | null | undefined;
|
|
64
67
|
}[];
|
|
65
68
|
}>;
|
|
@@ -87,6 +90,7 @@ declare class ReservationService {
|
|
|
87
90
|
referenceId: string;
|
|
88
91
|
acceptedAt?: Date | null | undefined;
|
|
89
92
|
cancelledAt?: Date | null | undefined;
|
|
93
|
+
cancellationMessage?: string | null | undefined;
|
|
90
94
|
createdAt?: Date | null | undefined;
|
|
91
95
|
}[];
|
|
92
96
|
}>;
|
|
@@ -103,6 +107,7 @@ declare class ReservationService {
|
|
|
103
107
|
referenceId: string;
|
|
104
108
|
acceptedAt?: Date | null | undefined;
|
|
105
109
|
cancelledAt?: Date | null | undefined;
|
|
110
|
+
cancellationMessage?: string | null | undefined;
|
|
106
111
|
createdAt?: Date | null | undefined;
|
|
107
112
|
}[]>;
|
|
108
113
|
/**
|
|
@@ -118,12 +123,13 @@ declare class ReservationService {
|
|
|
118
123
|
referenceId: string;
|
|
119
124
|
acceptedAt?: Date | null | undefined;
|
|
120
125
|
cancelledAt?: Date | null | undefined;
|
|
126
|
+
cancellationMessage?: string | null | undefined;
|
|
121
127
|
createdAt?: Date | null | undefined;
|
|
122
128
|
}>;
|
|
123
129
|
/**
|
|
124
130
|
* Update reservation status
|
|
125
131
|
*/
|
|
126
|
-
updateStatus(organizationId: string, reservationId: string, operation: "accept" | "cancel"): Promise<{
|
|
132
|
+
updateStatus(organizationId: string, reservationId: string, operation: "accept" | "cancel", body?: z.infer<typeof UpdateReservationStatusSchema>): Promise<{
|
|
127
133
|
id: string;
|
|
128
134
|
firstname: string;
|
|
129
135
|
lastname: string;
|
|
@@ -133,6 +139,7 @@ declare class ReservationService {
|
|
|
133
139
|
referenceId: string;
|
|
134
140
|
acceptedAt?: Date | null | undefined;
|
|
135
141
|
cancelledAt?: Date | null | undefined;
|
|
142
|
+
cancellationMessage?: string | null | undefined;
|
|
136
143
|
createdAt?: Date | null | undefined;
|
|
137
144
|
}>;
|
|
138
145
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__awaiter as
|
|
1
|
+
import{__awaiter as o}from"tslib";import{z as m}from"@hono/zod-openapi";import{customAlphabet as g}from"nanoid";import{HttpException as c}from"../../core/exceptions/http-exception";import{logger as w}from"../../core/logging/pino";import{PaginationMetaSchema as p,ReservationSchema as l}from"../../schemas";const y=g("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ",6);class R{constructor(e,t){this.prisma=e,this.emailService=t}safelySendEmail(e,t){return o(this,void 0,void 0,function*(){try{yield t()}catch(i){w.error(Object.assign({err:i},e),"Email delivery failed")}})}createReservation(e,t,i){return o(this,void 0,void 0,function*(){var r;const n=yield this.prisma.organization.findFirst({where:{id:e},include:{configuration:!0}});if(!n)throw new c(404,"Organization not found");if(!(!((r=n.configuration)===null||r===void 0)&&r.isAcceptingReservations))throw new c(400,"This organization is not accepting reservations at the moment");const a=yield this.prisma.reservation.create({data:Object.assign({referenceId:y(),firstname:i.firstname,lastname:i.lastname,guests:i.guests,phone:i.phone,date:i.date,organization:{connect:{id:e}}},t?{user:{connect:{id:t.id}}}:{}),include:{organization:{include:{address:!0,configuration:!0,logoFile:!0,members:{include:{user:!0}}}},user:!0}});for(const s of a.organization.members)yield this.safelySendEmail({emailType:"reservation-notification",memberId:s.user.id,organizationId:e,reservationId:a.id},()=>this.emailService.sendReservationNotificationEmail(e,s.user,a));return l.parse(a)})}getReservation(e,t,i){return o(this,void 0,void 0,function*(){const r=yield this.prisma.reservation.findUnique({where:{id:i,organizationId:t,user:{id:e.id}}});if(!r)throw new c(404,"Reservation not found");return l.parse(r)})}getReservations(e,t){return o(this,void 0,void 0,function*(){const{page:i=1,limit:r=10,search:n,from:a,to:s}=t,[d,h]=yield this.prisma.reservation.paginate({orderBy:{createdAt:"desc"},where:Object.assign(Object.assign({organizationId:e},a||s?{date:Object.assign(Object.assign({},a?{gte:a}:{}),s?{lte:s}:{})}:{}),n&&{OR:[{firstname:{contains:n,mode:"insensitive"}},{lastname:{contains:n,mode:"insensitive"}},{referenceId:{contains:n,mode:"insensitive"}}]}),include:{user:!0}}).withPages({page:i,limit:r});return m.object({meta:p,list:m.array(l)}).parse({meta:h,list:d})})}getMyReservations(e,t,i){return o(this,void 0,void 0,function*(){const{page:r=1,limit:n=10,search:a}=i,[s,d]=yield this.prisma.reservation.paginate({orderBy:{createdAt:"desc"},where:Object.assign({organizationId:t,userId:e},a&&{referenceId:{contains:a,mode:"insensitive"}})}).withPages({page:r,limit:n});return m.object({meta:p,list:m.array(l)}).parse({meta:d,list:s})})}getUserReservations(e,t){return o(this,void 0,void 0,function*(){const i=yield this.prisma.reservation.findMany({where:{organizationId:t,userId:e}});return m.array(l).parse(i)})}updateReservation(e,t,i){return o(this,void 0,void 0,function*(){const r=yield this.prisma.reservation.findUnique({where:{id:t,organizationId:e}});if(!r)throw new c(404,"Reservation not found");if(r.cancelledAt)throw new c(400,"Cancelled reservations cannot be edited");const n=yield this.prisma.reservation.update({where:{id:t},data:{firstname:i.firstname,lastname:i.lastname,guests:i.guests,date:i.date},include:{organization:{include:{address:!0,configuration:!0,logoFile:!0,members:{include:{user:!0}}}},user:!0}});return yield this.safelySendEmail({emailType:"reservation-updated",organizationId:e,reservationId:n.id},()=>this.emailService.sendReservationUpdatedEmail(e,n)),l.parse(n)})}updateStatus(e,t,i){return o(this,arguments,void 0,function*(r,n,a,s={}){var d;if(!(yield this.prisma.reservation.findUnique({where:{id:n,organizationId:r}})))throw new c(404,"Reservation not found");const v=((d=s.message)===null||d===void 0?void 0:d.trim())||void 0;let f={};switch(a){case"accept":f={acceptedAt:new Date};break;case"cancel":f={cancelledAt:new Date,cancellationMessage:v??null};break}const u=yield this.prisma.reservation.update({where:{id:n},data:f,include:{organization:{include:{address:!0,configuration:!0,logoFile:!0,members:{include:{user:!0}}}},user:!0}});return a==="cancel"&&(yield this.safelySendEmail({emailType:"reservation-cancelled",organizationId:r,reservationId:u.id},()=>this.emailService.sendReservationCancellationEmail(r,u))),a==="accept"&&(yield this.safelySendEmail({emailType:"reservation-confirmed",organizationId:r,reservationId:u.id},()=>this.emailService.sendReservationConfirmationEmail(r,u))),l.parse(u)})}deleteReservation(e,t){return o(this,void 0,void 0,function*(){if(!(yield this.prisma.reservation.findUnique({where:{id:t,organizationId:e}})))throw new c(404,"Reservation not found");yield this.prisma.reservation.delete({where:{id:t}})})}}export{R as ReservationService};
|