diff --git a/prisma/migrations/20260412181256_order_schema_change/migration.sql b/prisma/migrations/20260412181256_order_schema_change/migration.sql new file mode 100644 index 0000000..01ce630 --- /dev/null +++ b/prisma/migrations/20260412181256_order_schema_change/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "Order" ADD COLUMN "customerEmail" TEXT, +ALTER COLUMN "customerNote" DROP NOT NULL; diff --git a/prisma/schema/order.prisma b/prisma/schema/order.prisma index db25e7a..b6c39c9 100644 --- a/prisma/schema/order.prisma +++ b/prisma/schema/order.prisma @@ -20,8 +20,9 @@ model Order { status STATUS customerName String customerPhone String + customerEmail String? customerAddress String - customerNote String + customerNote String? paymentType PAYMENT_TYPE createdAt DateTime @default(now()) diff --git a/src/app/errors/configs/index.ts b/src/app/configs/index.ts similarity index 100% rename from src/app/errors/configs/index.ts rename to src/app/configs/index.ts diff --git a/src/app/middlewares/auth.ts b/src/app/middlewares/auth.ts index 408421e..5723cf3 100644 --- a/src/app/middlewares/auth.ts +++ b/src/app/middlewares/auth.ts @@ -1,5 +1,5 @@ import { NextFunction, Request, Response } from "express"; -import { configs } from "../errors/configs"; +import { configs } from "../configs"; import { AppError } from "../utils/app_error"; import { jwtHelpers, JwtPayloadType } from "../utils/JWT"; diff --git a/src/app/middlewares/global_error_handler.ts b/src/app/middlewares/global_error_handler.ts index 7c1d72f..c361f7f 100644 --- a/src/app/middlewares/global_error_handler.ts +++ b/src/app/middlewares/global_error_handler.ts @@ -1,6 +1,6 @@ import { ErrorRequestHandler } from "express"; import { ZodError } from "zod"; -import { configs } from "../errors/configs"; +import { configs } from "../configs"; import handleZodError from "../errors/zodError"; import { TErrorSources } from "../types/error"; import { AppError } from "../utils/app_error"; diff --git a/src/app/modules/account/account.controller.ts b/src/app/modules/account/account.controller.ts index 4904117..f0a467d 100644 --- a/src/app/modules/account/account.controller.ts +++ b/src/app/modules/account/account.controller.ts @@ -1,4 +1,4 @@ -import { configs } from "../../errors/configs"; +import { configs } from "../../configs"; import catchAsync from "../../utils/catch_async"; import manageResponse from "../../utils/manage_response"; import { account_services } from "./account.service"; diff --git a/src/app/modules/account/account.service.ts b/src/app/modules/account/account.service.ts index ae01b8d..33868fa 100644 --- a/src/app/modules/account/account.service.ts +++ b/src/app/modules/account/account.service.ts @@ -1,6 +1,6 @@ import bcrypt from "bcrypt"; import { Request } from "express"; -import { configs } from "../../errors/configs"; +import { configs } from "../../configs"; import { prisma } from "../../lib/prisma"; import { emailQueue } from "../../queues/email/email.queue"; import { AppError } from "../../utils/app_error"; @@ -72,7 +72,7 @@ const create_account_into_db = async (req: Request) => { email: payload.email, textBody: "You can use otp or verification link for verifying your account" }) - return result; + return null; }; const verify_account_using_otp_into_db = async (req: Request) => { diff --git a/src/app/modules/order/order.service.ts b/src/app/modules/order/order.service.ts index 7b54a28..371301b 100644 --- a/src/app/modules/order/order.service.ts +++ b/src/app/modules/order/order.service.ts @@ -1,7 +1,8 @@ import { Request } from "express"; +import { configs } from "../../configs"; import { prisma } from "../../lib/prisma"; -import { AppError } from "../../utils/app_error"; +import { orderEmailQueue } from "../../queues/email/order/order.email.queue"; const get_all_order_from_db = async (req: Request) => { // define your own login here @@ -11,68 +12,42 @@ const get_all_order_from_db = async (req: Request) => { const get_single_order_from_db = async (req: Request) => { // define your own login here - const { id } = req.params; + const { id } = req.params as { id: string }; const result = await prisma.order.findUnique({ where: { id } }); return result; }; const create_order_into_db = async (req: Request) => { - // define your own login here + const payload = req?.body; + payload.status = "INITIATED"; + payload.paymentType = "COD" - const user = req.user - console.log(user) - const { - shopAccountId, - productPrice, - productQuantity, - productName, - customerName, - customerPhone, - customerAddress, - customerNote, - paymentType, - status, - } = req.body - const isUserExists = await prisma.account.findFirst({ - where: { - id: user?.accountId - } - }) - if (!isUserExists) { - throw new AppError("Account not found", 404); + // nwo init order + const result = await prisma.order.create({ data: payload }); + + // if email exist sent tracking link + if (payload.customerEmail) { + const trackingLink = `${configs.jwt.front_end_url}/track-order/${result.id}`; + await orderEmailQueue.add("order-email-queue", { + email: payload.customerEmail, + subject: "Order Tracking", + textBody: `Your order has been created. Track your order here: ${trackingLink}`, + htmlBody: `
Your order has been created. Track your order here: Track Order
` + }) } - - const result = await prisma.order.create({ - data: { - productPrice, - productQuantity, - productName, - customerName, - customerPhone, - customerAddress, - customerNote, - paymentType, - status, - account: { - connect: { - id: user?.accountId, - }, - }, - } - }); return result; }; const update_order_into_db = async (req: Request) => { // define your own login here - const { id } = req.params; + const { id } = req.params as { id: string }; const result = await prisma.order.update({ where: { id }, data: req.body }); return result; }; const delete_order_from_db = async (req: Request) => { // define your own login here - const { id } = req.params; + const { id } = req.params as { id: string }; const result = await prisma.order.delete({ where: { id } }); return result; }; diff --git a/src/app/modules/order/order.swagger.ts b/src/app/modules/order/order.swagger.ts index 04368b7..3d37735 100644 --- a/src/app/modules/order/order.swagger.ts +++ b/src/app/modules/order/order.swagger.ts @@ -10,18 +10,16 @@ export const orderSwaggerDocs = { content: { "application/json": { example: JSON.stringify({ - + "shopAccountId": "", "productPrice": 1500, "productQuantity": 2, "productName": "Wireless Mouse", "customerName": "Rahim Uddin", "customerPhone": "+8801712345678", + "customerEmail": "softvence.abumahid@gmail.com", "customerAddress": "Rangpur, Bangladesh", - "customerNote": "Please deliver between 3-5 PM", - "paymentType": "Cash on Delivery", - "status": "Pending" - - }), // put your request body + "customerNote": "Please deliver between 3-5 PM" + }) }, }, }, diff --git a/src/app/modules/order/order.validation.ts b/src/app/modules/order/order.validation.ts index 52eaab8..114c4ff 100644 --- a/src/app/modules/order/order.validation.ts +++ b/src/app/modules/order/order.validation.ts @@ -1,29 +1,28 @@ -import { uuid, z } from "zod"; +import { z } from "zod"; const create_order = z.object({ - shopAccountId:z.string(), - productPrice:z.number(), - productQuantity:z.number(), - productName:z.string(), - customerName:z.string(), - customerPhone:z.string(), - customerAddress:z.string(), - customerNote:z.string(), - paymentType:z.string(), - status:z.string() + shopAccountId: z.string(), + productPrice: z.number(), + productQuantity: z.number(), + productName: z.string(), + customerName: z.string(), + customerPhone: z.string(), + customerEmail: z.string().optional(), + customerAddress: z.string(), + customerNote: z.string().optional() }); const update_order = z.object({ - shopAccountId:z.string().optional(), - productPrice:z.number().optional(), - productQuantity:z.number().optional(), - productName:z.string().optional(), - customerName:z.string().optional(), - customerPhone:z.string().optional(), - customerAddress:z.string().optional(), - customerNote:z.string().optional(), - paymentType:z.string().optional(), - status:z.string().optional() + shopAccountId: z.string().optional(), + productPrice: z.number().optional(), + productQuantity: z.number().optional(), + productName: z.string().optional(), + customerName: z.string().optional(), + customerPhone: z.string().optional(), + customerEmail: z.string().optional(), + customerAddress: z.string().optional(), + customerNote: z.string().optional(), + status: z.string().optional() }); export const order_validations = { diff --git a/src/app/queues/email/order/order.email.processor.ts b/src/app/queues/email/order/order.email.processor.ts new file mode 100644 index 0000000..1a81c35 --- /dev/null +++ b/src/app/queues/email/order/order.email.processor.ts @@ -0,0 +1,14 @@ +import sendMail from "../../../utils/mail_sender"; +import { TOrderEmailQueue } from "./order.email.queue"; + +// email.processor.ts +export const orderEmailProcessor = async (job: any) => { + const payload: TOrderEmailQueue = job.data; + await sendMail({ + to: payload.email as string, + subject: payload.subject, + htmlBody: payload.htmlBody as string, + textBody: payload.textBody as string, + }); + console.log("Sending email job complete:", job.id); +}; \ No newline at end of file diff --git a/src/app/queues/email/order/order.email.queue.ts b/src/app/queues/email/order/order.email.queue.ts new file mode 100644 index 0000000..db7d087 --- /dev/null +++ b/src/app/queues/email/order/order.email.queue.ts @@ -0,0 +1,15 @@ +import { Queue } from "bullmq"; +import { redisConnection } from "../../connection"; + +export type TOrderEmailQueue = { + email: string; + subject: string; + textBody?: string; + htmlBody?: string; + +} + + +export const orderEmailQueue = new Queue