feat: implement booking and customer order flow
This commit is contained in:
@@ -4,16 +4,18 @@ import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Injectable,
|
||||
Module,
|
||||
Param,
|
||||
Post,
|
||||
Req,
|
||||
} from "@nestjs/common";
|
||||
import { NestFactory } from "@nestjs/core";
|
||||
import { FastifyAdapter } from "@nestjs/platform-fastify";
|
||||
import type { NestFastifyApplication } from "@nestjs/platform-fastify";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { PrismaService } from "./prisma.service.js";
|
||||
import { WechatAuthService } from "./wechat-auth.js";
|
||||
import { BookingService } from "./booking.service.js";
|
||||
import type { CreateBookingInput } from "./booking.service.js";
|
||||
import type { FastifyRequest } from "fastify";
|
||||
import { createHmac } from "node:crypto";
|
||||
|
||||
@@ -37,13 +39,6 @@ function readIdentity(token: string): { brandId: string; openid: string } {
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PrismaService extends PrismaClient {
|
||||
async onModuleDestroy(): Promise<void> {
|
||||
await this.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Controller("health")
|
||||
export class HealthController {
|
||||
@Get()
|
||||
@@ -114,27 +109,39 @@ export class CustomerSessionController {
|
||||
|
||||
@Controller("customer/bookings")
|
||||
export class CustomerBookingController {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly bookings: BookingService,
|
||||
) {}
|
||||
|
||||
@Post()
|
||||
async create(@Req() request: FastifyRequest, @Body() body: CreateBookingInput): Promise<unknown> {
|
||||
const identity = this.identity(request);
|
||||
const customer = await this.prisma.customerUser.findUnique({
|
||||
where: { brandId_openid: identity },
|
||||
});
|
||||
if (!customer) throw new BadRequestException("请先完成微信登录");
|
||||
return this.bookings.create(identity.brandId, customer.id, body);
|
||||
}
|
||||
|
||||
@Get()
|
||||
async list(@Req() request: FastifyRequest): Promise<unknown> {
|
||||
const identity = this.identity(request);
|
||||
return this.prisma.booking.findMany({
|
||||
where: { customerUser: { brandId: identity.brandId, openid: identity.openid } },
|
||||
orderBy: { createdAt: "desc" },
|
||||
select: {
|
||||
bookingNo: true,
|
||||
requestType: true,
|
||||
customerName: true,
|
||||
status: true,
|
||||
estimatedAmount: true,
|
||||
requestedDate: true,
|
||||
requestedTime: true,
|
||||
fulfillmentType: true,
|
||||
createdAt: true,
|
||||
items: { select: { serviceNameSnapshot: true, quantity: true, subtotalSnapshot: true } },
|
||||
},
|
||||
const customer = await this.prisma.customerUser.findUnique({
|
||||
where: { brandId_openid: identity },
|
||||
});
|
||||
if (!customer) throw new BadRequestException("请先完成微信登录");
|
||||
return this.bookings.listForCustomer(identity.brandId, customer.id);
|
||||
}
|
||||
|
||||
@Post(":id/cancel")
|
||||
async cancel(@Req() request: FastifyRequest, @Param("id") id: string): Promise<unknown> {
|
||||
const identity = this.identity(request);
|
||||
const customer = await this.prisma.customerUser.findUnique({
|
||||
where: { brandId_openid: identity },
|
||||
});
|
||||
if (!customer) throw new BadRequestException("请先完成微信登录");
|
||||
return this.bookings.cancelForCustomer(identity.brandId, customer.id, id);
|
||||
}
|
||||
|
||||
private identity(request: FastifyRequest): { brandId: string; openid: string } {
|
||||
@@ -149,14 +156,42 @@ export class CustomerBookingController {
|
||||
}
|
||||
}
|
||||
|
||||
@Controller("admin/bookings")
|
||||
export class AdminBookingController {
|
||||
constructor(private readonly bookings: BookingService) {}
|
||||
@Get()
|
||||
list(): Promise<unknown> {
|
||||
return this.bookings.listForAdmin(
|
||||
process.env.DEFAULT_BRAND_ID ?? "00000000-0000-0000-0000-000000000001",
|
||||
);
|
||||
}
|
||||
@Post(":id/status")
|
||||
update(
|
||||
@Param("id") id: string,
|
||||
@Body()
|
||||
body: {
|
||||
status: "received" | "contacting" | "confirmed" | "completed" | "cancelled";
|
||||
adminNote?: string;
|
||||
},
|
||||
): Promise<unknown> {
|
||||
return this.bookings.updateStatus(
|
||||
process.env.DEFAULT_BRAND_ID ?? "00000000-0000-0000-0000-000000000001",
|
||||
id,
|
||||
body.status,
|
||||
body.adminNote,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
controllers: [
|
||||
HealthController,
|
||||
PublicController,
|
||||
CustomerSessionController,
|
||||
CustomerBookingController,
|
||||
AdminBookingController,
|
||||
],
|
||||
providers: [PrismaService, WechatAuthService],
|
||||
providers: [PrismaService, WechatAuthService, BookingService],
|
||||
exports: [PrismaService, WechatAuthService],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
Reference in New Issue
Block a user