From f13a83c992a5f28620f887ee658cc335646110f6 Mon Sep 17 00:00:00 2001 From: andwati Date: Tue, 13 Jan 2026 00:52:29 +0300 Subject: [PATCH] feat: update order and user repositories to use instance methods for creation and improve session handling; enhance order service with transaction management for payment and cancellation --- src/repositories/order.repo.ts | 8 ++-- src/repositories/user.repo.ts | 3 +- src/services/order.service.ts | 83 ++++++++++++++++++++++++++++++++-- src/types/express.d.ts | 2 +- tsconfig.json | 2 +- 5 files changed, 87 insertions(+), 11 deletions(-) diff --git a/src/repositories/order.repo.ts b/src/repositories/order.repo.ts index 8103e6a..fa73f21 100644 --- a/src/repositories/order.repo.ts +++ b/src/repositories/order.repo.ts @@ -4,13 +4,15 @@ import { OrderModel, type OrderDocument } from "../models/order.model.js"; export class OrderRepository { static create( data: Omit, - session: ClientSession, + session?: ClientSession, ): Promise { - return OrderModel.create(data, { session }); + const order = new OrderModel(data); + return order.save({ session: session ?? undefined }); } static findById(id: string, session?: ClientSession) { - return OrderModel.findById(id).session(session ?? null); + const query = OrderModel.findById(id); + return session ? query.session(session) : query; } static findAll() { diff --git a/src/repositories/user.repo.ts b/src/repositories/user.repo.ts index c3b9a47..1d37ea9 100644 --- a/src/repositories/user.repo.ts +++ b/src/repositories/user.repo.ts @@ -15,6 +15,7 @@ export class UserRepository { data: Pick, session?: ClientSession, ): Promise { - return UserModel.create([data], { session }).then((res) => res[0]); + const user = new UserModel(data); + return user.save({ session: session ?? undefined }); } } diff --git a/src/services/order.service.ts b/src/services/order.service.ts index 07f877b..b70f1e4 100644 --- a/src/services/order.service.ts +++ b/src/services/order.service.ts @@ -4,13 +4,86 @@ import { OrderRepository } from "../repositories/order.repo.js"; export class OrderService { static listOrders(userId: string, role: string) { - throw new Error("Method not implemented."); + if (String(role).toLowerCase() === "admin") { + return OrderRepository.findAll(); + } + + return OrderRepository.findByUser(userId); } - static payOrder(id: string | string[] | undefined) { - throw new Error("Method not implemented."); + static async payOrder(id: string | string[] | undefined) { + if (!id || Array.isArray(id)) { + throw { statusCode: 400, message: "Invalid order id" }; + } + + const session = await mongoose.startSession(); + session.startTransaction(); + + try { + const order = await OrderRepository.findById(id, session); + + if (!order) { + throw { statusCode: 404, message: "Order not found" }; + } + + if (order.status === "paid") { + throw { statusCode: 409, message: "Order is already paid" }; + } + + if (order.status === "cancelled") { + throw { statusCode: 409, message: "Cannot pay a cancelled order" }; + } + + order.status = "paid"; + await OrderRepository.save(order, session); + + await session.commitTransaction(); + return order; + } catch (err) { + await session.abortTransaction(); + throw err; + } finally { + session.endSession(); + } } - static cancelOrder(id: string | string[] | undefined) { - throw new Error("Method not implemented."); + static async cancelOrder(id: string | string[] | undefined) { + if (!id || Array.isArray(id)) { + throw { statusCode: 400, message: "Invalid order id" }; + } + + const session = await mongoose.startSession(); + session.startTransaction(); + + try { + const order = await OrderRepository.findById(id, session); + + if (!order) { + throw { statusCode: 404, message: "Order not found" }; + } + + if (order.status === "cancelled") { + throw { statusCode: 409, message: "Order is already cancelled" }; + } + + // restore stock for each item + for (const item of order.items) { + await ProductRepository.incrementStock( + item.productId, + item.quantity, + session, + ); + } + + order.status = "cancelled"; + await OrderRepository.save(order, session); + + await session.commitTransaction(); + return order; + } catch (err) { + await session.abortTransaction(); + throw err; + } finally { + session.endSession(); + } } static async createOrder( userId: string, diff --git a/src/types/express.d.ts b/src/types/express.d.ts index 5f62b7c..b97ac97 100644 --- a/src/types/express.d.ts +++ b/src/types/express.d.ts @@ -1,4 +1,4 @@ -import { JwtPayload } from "../utils/jwt.js"; +import { JwtPayload } from "../utils/jwt.ts"; declare global { namespace Express { diff --git a/tsconfig.json b/tsconfig.json index 0ff4ac6..f39be98 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { // File Layout "rootDir": "./src", - // "outDir": "./dist", + "outDir": "./dist", // Environment Settings // See also https://aka.ms/tsconfig/module