diff --git a/apps/backend/package.json b/apps/backend/package.json index 2966797..67632fc 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -31,12 +31,16 @@ "@nestjs/config": "^4.0.0", "@nestjs/core": "^11.0.1", "@nestjs/graphql": "^13.0.2", + "@nestjs/jwt": "^11.0.0", "@nestjs/mapped-types": "*", + "@nestjs/passport": "^11.0.5", "@nestjs/platform-express": "^11.0.7", "@prisma/client": "^6.3.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "graphql": "^16.10.0", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "slugify": "^1.6.6" diff --git a/apps/backend/prisma/migrations/20250426051812_add_orders/migration.sql b/apps/backend/prisma/migrations/20250426051812_add_orders/migration.sql new file mode 100644 index 0000000..458ec20 --- /dev/null +++ b/apps/backend/prisma/migrations/20250426051812_add_orders/migration.sql @@ -0,0 +1,24 @@ +/* + Warnings: + + - Added the required column `buyer_address` to the `Order` table without a default value. This is not possible if the table is not empty. + - Added the required column `escrow_id` to the `Order` table without a default value. This is not possible if the table is not empty. + - Added the required column `product_id` to the `Order` table without a default value. This is not possible if the table is not empty. + - Added the required column `seller_address` to the `Order` table without a default value. This is not possible if the table is not empty. + - Added the required column `updated_at` to the `Order` table without a default value. This is not possible if the table is not empty. + +*/ +-- CreateEnum +CREATE TYPE "OrderStatus" AS ENUM ('PENDING', 'ON_DISPUTE', 'FOR_REVIEW', 'APPROVED'); + +-- AlterTable +ALTER TABLE "Order" ADD COLUMN "buyer_address" TEXT NOT NULL, +ADD COLUMN "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "escrow_id" TEXT NOT NULL, +ADD COLUMN "product_id" TEXT NOT NULL, +ADD COLUMN "seller_address" TEXT NOT NULL, +ADD COLUMN "status" "OrderStatus" NOT NULL DEFAULT 'PENDING', +ADD COLUMN "updated_at" TIMESTAMP(3) NOT NULL; + +-- AddForeignKey +ALTER TABLE "Order" ADD CONSTRAINT "Order_product_id_fkey" FOREIGN KEY ("product_id") REFERENCES "products"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/backend/prisma/migrations/20250427015007_update_order_field_name_convention/migration.sql b/apps/backend/prisma/migrations/20250427015007_update_order_field_name_convention/migration.sql new file mode 100644 index 0000000..f95a3fe --- /dev/null +++ b/apps/backend/prisma/migrations/20250427015007_update_order_field_name_convention/migration.sql @@ -0,0 +1,34 @@ +/* + Warnings: + + - You are about to drop the `Order` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "Order" DROP CONSTRAINT "Order_product_id_fkey"; + +-- DropForeignKey +ALTER TABLE "messages" DROP CONSTRAINT "messages_order_id_fkey"; + +-- DropTable +DROP TABLE "Order"; + +-- CreateTable +CREATE TABLE "orders" ( + "id" TEXT NOT NULL, + "product_id" TEXT NOT NULL, + "buyer_address" TEXT NOT NULL, + "seller_address" TEXT NOT NULL, + "escrow_id" TEXT NOT NULL, + "status" "OrderStatus" NOT NULL DEFAULT 'PENDING', + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "orders_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "messages" ADD CONSTRAINT "messages_order_id_fkey" FOREIGN KEY ("order_id") REFERENCES "orders"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "orders" ADD CONSTRAINT "orders_product_id_fkey" FOREIGN KEY ("product_id") REFERENCES "products"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/backend/prisma/schema.prisma b/apps/backend/prisma/schema.prisma index c1fc905..45ef559 100644 --- a/apps/backend/prisma/schema.prisma +++ b/apps/backend/prisma/schema.prisma @@ -39,7 +39,7 @@ model Product { sellerAddress String @map("seller_address") user User @relation(fields: [sellerAddress], references: [walletAddress]) category Category @relation(fields: [categoryId], references: [id]) - + orders Order[] @@map("products") } @@ -84,7 +84,25 @@ model Message { @@map("messages") } -model Order { - id String @id @default(uuid()) - messages Message[] +enum OrderStatus { + PENDING + ON_DISPUTE + FOR_REVIEW + APPROVED } + +model Order { + id String @id @default(uuid()) + productId String @map("product_id") + buyerAddress String @map("buyer_address") + sellerAddress String @map("seller_address") + escrowId String @map("escrow_id") + status OrderStatus @default(PENDING) + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + messages Message[] + + product Product @relation(fields: [productId], references: [id]) + + @@map("orders") +} \ No newline at end of file diff --git a/apps/backend/src/core/core.module.ts b/apps/backend/src/core/core.module.ts index 171398c..9036738 100644 --- a/apps/backend/src/core/core.module.ts +++ b/apps/backend/src/core/core.module.ts @@ -13,6 +13,7 @@ import { MessageModule } from "../modules/message/message.module"; import { getGraphQLConfig } from "./config/graphql.config"; import { PrismaModule } from "./prisma/prisma.module"; +import { OrderModule } from "src/modules/order/order.module"; @Module({ imports: [ AuthModule, @@ -31,6 +32,7 @@ import { PrismaModule } from "./prisma/prisma.module"; ProductModule, ProductImageModule, UsersModule, + OrderModule, MessageModule, ], controllers: [], diff --git a/apps/backend/src/core/graphql/schema.gql b/apps/backend/src/core/graphql/schema.gql index ab2caa4..b166639 100644 --- a/apps/backend/src/core/graphql/schema.gql +++ b/apps/backend/src/core/graphql/schema.gql @@ -20,6 +20,14 @@ input CreateMessageInput { senderAddress: String! } +input CreateOrderInput { + buyerAddress: String! + escrowId: String! + productId: String! + sellerAddress: String! + status: OrderStatus! = PENDING +} + input CreateProductInput { categoryId: String! condition: String! @@ -56,13 +64,33 @@ type Message { type Mutation { createCategory(data: CreateCategoryInput!): Category! + createOrder(data: CreateOrderInput!): Order! createProduct(data: CreateProductInput!): ProductDTO! createProductImage(createProductImage: ProductImageDTO!): ProductImage! createUser(data: CreateUserInput!): User! sendMessage(data: CreateMessageInput!): Message! + updateOrderStatus(data: UpdateOrderStatusInput!): Order! updateUser(data: UpdateUserInput!, walletAddress: String!): User! } +type Order { + buyerAddress: String! + createdAt: DateTime! + escrowId: String! + id: String! + productId: String! + sellerAddress: String! + status: OrderStatus! + updatedAt: DateTime! +} + +enum OrderStatus { + APPROVED + FOR_REVIEW + ON_DISPUTE + PENDING +} + type ProductDTO { categoryId: String! @@ -93,6 +121,9 @@ input ProductImageDTO { type Query { categories: [Category!]! category(id: String!): Category + getOrder(orderId: String!): Order! + getOrdersByBuyer(buyerAddress: String!): [Order!]! + getOrdersBySeller(sellerAddress: String!): [Order!]! getMessagesByOrder(orderId: String!): [Message!]! product(id: String!): ProductDTO productImage(id: String!): ProductImage @@ -102,6 +133,11 @@ type Query { users: [User!]! } +input UpdateOrderStatusInput { + orderId: String! + status: OrderStatus! +} + input UpdateUserInput { country: String email: String diff --git a/apps/backend/src/modules/order/dto/create-order.input.ts b/apps/backend/src/modules/order/dto/create-order.input.ts new file mode 100644 index 0000000..66425ee --- /dev/null +++ b/apps/backend/src/modules/order/dto/create-order.input.ts @@ -0,0 +1,20 @@ +import { InputType, Field } from '@nestjs/graphql'; +import { OrderStatus } from '../entities/order.entity'; + +@InputType() +export class CreateOrderInput { + @Field() + productId: string; + + @Field() + buyerAddress: string; + + @Field() + sellerAddress: string; + + @Field() + escrowId: string; + + @Field(() => OrderStatus, { defaultValue: OrderStatus.PENDING }) + status: OrderStatus; +} diff --git a/apps/backend/src/modules/order/dto/update-order-status.input.ts b/apps/backend/src/modules/order/dto/update-order-status.input.ts new file mode 100644 index 0000000..95ce0b5 --- /dev/null +++ b/apps/backend/src/modules/order/dto/update-order-status.input.ts @@ -0,0 +1,11 @@ +import { InputType, Field } from '@nestjs/graphql'; +import { OrderStatus } from '../entities/order.entity'; + +@InputType() +export class UpdateOrderStatusInput { + @Field() + orderId: string; + + @Field(() => OrderStatus) + status: OrderStatus; +} \ No newline at end of file diff --git a/apps/backend/src/modules/order/dto/update-order.input.ts b/apps/backend/src/modules/order/dto/update-order.input.ts new file mode 100644 index 0000000..10f31a1 --- /dev/null +++ b/apps/backend/src/modules/order/dto/update-order.input.ts @@ -0,0 +1,8 @@ +import { CreateOrderInput } from './create-order.input'; +import { InputType, Field, Int, PartialType } from '@nestjs/graphql'; + +@InputType() +export class UpdateOrderInput extends PartialType(CreateOrderInput) { + @Field(() => Int) + id: number; +} diff --git a/apps/backend/src/modules/order/entities/order.entity.ts b/apps/backend/src/modules/order/entities/order.entity.ts new file mode 100644 index 0000000..9ca5c9f --- /dev/null +++ b/apps/backend/src/modules/order/entities/order.entity.ts @@ -0,0 +1,39 @@ +import { ObjectType, Field, registerEnumType } from '@nestjs/graphql'; + +export enum OrderStatus { + PENDING = 'PENDING', + ON_DISPUTE = 'ON_DISPUTE', + FOR_REVIEW = 'FOR_REVIEW', + APPROVED = 'APPROVED', +} + +registerEnumType(OrderStatus, { + name: 'OrderStatus', +}); + +@ObjectType() +export class Order { + @Field() + id: string; + + @Field() + productId: string; + + @Field() + buyerAddress: string; + + @Field() + sellerAddress: string; + + @Field() + escrowId: string; + + @Field(() => OrderStatus) + status: OrderStatus; + + @Field() + createdAt: Date; + + @Field() + updatedAt: Date; +} diff --git a/apps/backend/src/modules/order/order.module.ts b/apps/backend/src/modules/order/order.module.ts new file mode 100644 index 0000000..cd9da24 --- /dev/null +++ b/apps/backend/src/modules/order/order.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { OrderService } from './order.service'; +import { OrderResolver } from './order.resolver'; + +@Module({ + providers: [OrderResolver, OrderService], +}) +export class OrderModule {} diff --git a/apps/backend/src/modules/order/order.resolver.spec.ts b/apps/backend/src/modules/order/order.resolver.spec.ts new file mode 100644 index 0000000..a3523fd --- /dev/null +++ b/apps/backend/src/modules/order/order.resolver.spec.ts @@ -0,0 +1,175 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { OrderResolver } from './order.resolver'; +import { OrderService } from './order.service'; +import { OrderStatus } from './entities/order.entity'; +import { CreateOrderInput } from './dto/create-order.input'; +import { UpdateOrderStatusInput } from './dto/update-order-status.input'; + +describe('OrderResolver', () => { + let resolver: OrderResolver; + let orderService: OrderService; + + const mockOrderService = { + create: jest.fn(), + findAllByBuyer: jest.fn(), + findAllBySeller: jest.fn(), + findOne: jest.fn(), + updateStatus: jest.fn(), + }; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + OrderResolver, + { + provide: OrderService, + useValue: mockOrderService, + }, + ], + }).compile(); + + resolver = module.get(OrderResolver); + orderService = module.get(OrderService); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(resolver).toBeDefined(); + }); + + describe('getOrdersByBuyer', () => { + it('should return orders for a specific buyer', async () => { + const buyerAddress = 'buyer-address-123'; + const mockOrders = [ + { + id: 'order-123', + productId: 'product-123', + buyerAddress: buyerAddress, + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + createdAt: new Date(), + updatedAt: new Date(), + }, + ]; + + mockOrderService.findAllByBuyer.mockResolvedValue(mockOrders); + + const result = await resolver.getOrdersByBuyer(buyerAddress); + + expect(mockOrderService.findAllByBuyer).toHaveBeenCalledWith(buyerAddress); + expect(result).toEqual(mockOrders); + }); + }); + + describe('getOrdersBySeller', () => { + it('should return orders for a specific seller', async () => { + const sellerAddress = 'seller-address-123'; + const mockOrders = [ + { + id: 'order-123', + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: sellerAddress, + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + createdAt: new Date(), + updatedAt: new Date(), + }, + ]; + + mockOrderService.findAllBySeller.mockResolvedValue(mockOrders); + + const result = await resolver.getOrdersBySeller(sellerAddress); + + expect(mockOrderService.findAllBySeller).toHaveBeenCalledWith(sellerAddress); + expect(result).toEqual(mockOrders); + }); + }); + + describe('getOrder', () => { + it('should return a single order by ID', async () => { + const orderId = 'order-123'; + const mockOrder = { + id: orderId, + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + createdAt: new Date(), + updatedAt: new Date(), + }; + + mockOrderService.findOne.mockResolvedValue(mockOrder); + + const result = await resolver.getOrder(orderId); + + expect(mockOrderService.findOne).toHaveBeenCalledWith(orderId); + expect(result).toEqual(mockOrder); + }); + }); + + describe('createOrder', () => { + it('should create a new order', async () => { + const orderData: CreateOrderInput = { + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + }; + + const mockOrder = { + id: 'order-123', + productId: orderData.productId, + buyerAddress: orderData.buyerAddress, + sellerAddress: orderData.sellerAddress, + escrowId: orderData.escrowId, + status: orderData.status, + createdAt: new Date(), + updatedAt: new Date(), + }; + + mockOrderService.create.mockResolvedValue(mockOrder); + + const result = await resolver.createOrder(orderData); + + expect(mockOrderService.create).toHaveBeenCalledWith(orderData); + expect(result).toEqual(mockOrder); + }); + }); + + describe('updateOrderStatus', () => { + it('should update an order status', async () => { + const orderId = 'order-123'; + const newStatus = OrderStatus.APPROVED; + + const updateData: UpdateOrderStatusInput = { + orderId: orderId, + status: newStatus, + }; + + const mockOrder = { + id: orderId, + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: newStatus, + createdAt: new Date(), + updatedAt: new Date(), + }; + + mockOrderService.updateStatus.mockResolvedValue(mockOrder); + + const result = await resolver.updateOrderStatus(updateData); + + expect(mockOrderService.updateStatus).toHaveBeenCalledWith(orderId, newStatus); + expect(result).toEqual(mockOrder); + }); + }); +}); \ No newline at end of file diff --git a/apps/backend/src/modules/order/order.resolver.ts b/apps/backend/src/modules/order/order.resolver.ts new file mode 100644 index 0000000..648d928 --- /dev/null +++ b/apps/backend/src/modules/order/order.resolver.ts @@ -0,0 +1,35 @@ +import { Resolver, Query, Mutation, Args } from '@nestjs/graphql'; +import { OrderService } from './order.service'; +import { Order, OrderStatus } from './entities/order.entity'; +import { CreateOrderInput } from './dto/create-order.input'; +import { UpdateOrderStatusInput } from './dto/update-order-status.input'; + +@Resolver(() => Order) +export class OrderResolver { + constructor(private readonly ordersService: OrderService) {} + + @Query(() => [Order], { name: 'getOrdersByBuyer' }) + getOrdersByBuyer(@Args('buyerAddress') buyerAddress: string) { + return this.ordersService.findAllByBuyer(buyerAddress); + } + + @Query(() => [Order], { name: 'getOrdersBySeller' }) + getOrdersBySeller(@Args('sellerAddress') sellerAddress: string) { + return this.ordersService.findAllBySeller(sellerAddress); + } + + @Query(() => Order, { name: 'getOrder' }) + getOrder(@Args('orderId') orderId: string) { + return this.ordersService.findOne(orderId); + } + + @Mutation(() => Order) + createOrder(@Args('data') data: CreateOrderInput) { + return this.ordersService.create(data); + } + + @Mutation(() => Order) + updateOrderStatus(@Args('data') data: UpdateOrderStatusInput) { + return this.ordersService.updateStatus(data.orderId, data.status); + } +} diff --git a/apps/backend/src/modules/order/order.service.spec.ts b/apps/backend/src/modules/order/order.service.spec.ts new file mode 100644 index 0000000..ebfc6bb --- /dev/null +++ b/apps/backend/src/modules/order/order.service.spec.ts @@ -0,0 +1,185 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { OrderService } from './order.service'; +import { PrismaService } from 'src/core/prisma/prisma.service'; +import { OrderStatus } from './entities/order.entity'; + +describe('OrderService', () => { + let service: OrderService; + let prismaService: PrismaService; + + const mockPrismaService = { + order: { + create: jest.fn(), + findMany: jest.fn(), + findUnique: jest.fn(), + update: jest.fn(), + }, + }; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + OrderService, + { + provide: PrismaService, + useValue: mockPrismaService, + }, + ], + }).compile(); + + service = module.get(OrderService); + prismaService = module.get(PrismaService); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('create', () => { + it('should create a new order', async () => { + const orderData = { + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + }; + + const expectedOrder = { + id: 'order-123', + productId: orderData.productId, + buyerAddress: orderData.buyerAddress, + sellerAddress: orderData.sellerAddress, + escrowId: orderData.escrowId, + status: orderData.status, + createdAt: new Date(), + updatedAt: new Date(), + }; + + mockPrismaService.order.create.mockResolvedValue(expectedOrder); + + const result = await service.create(orderData); + + expect(mockPrismaService.order.create).toHaveBeenCalledWith({ + data: { + productId: orderData.productId, + buyerAddress: orderData.buyerAddress, + sellerAddress: orderData.sellerAddress, + escrowId: orderData.escrowId, + status: orderData.status, + }, + }); + expect(result).toEqual(expectedOrder); + }); + }); + + describe('findAllByBuyer', () => { + it('should return orders for a specific buyer', async () => { + const buyerAddress = 'buyer-address-123'; + const mockOrders = [ + { + id: 'order-123', + productId: 'product-123', + buyerAddress: buyerAddress, + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + createdAt: new Date(), + updatedAt: new Date(), + }, + ]; + + mockPrismaService.order.findMany.mockResolvedValue(mockOrders); + + const result = await service.findAllByBuyer(buyerAddress); + + expect(mockPrismaService.order.findMany).toHaveBeenCalledWith({ + where: { buyerAddress: buyerAddress }, + }); + expect(result).toEqual(mockOrders); + }); + }); + + describe('findAllBySeller', () => { + it('should return orders for a specific seller', async () => { + const sellerAddress = 'seller-address-123'; + const mockOrders = [ + { + id: 'order-123', + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: sellerAddress, + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + createdAt: new Date(), + updatedAt: new Date(), + }, + ]; + + mockPrismaService.order.findMany.mockResolvedValue(mockOrders); + + const result = await service.findAllBySeller(sellerAddress); + + expect(mockPrismaService.order.findMany).toHaveBeenCalledWith({ + where: { sellerAddress: sellerAddress }, + }); + expect(result).toEqual(mockOrders); + }); + }); + + describe('findOne', () => { + it('should return a single order by ID', async () => { + const orderId = 'order-123'; + const mockOrder = { + id: orderId, + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: OrderStatus.PENDING, + createdAt: new Date(), + updatedAt: new Date(), + }; + + mockPrismaService.order.findUnique.mockResolvedValue(mockOrder); + + const result = await service.findOne(orderId); + + expect(mockPrismaService.order.findUnique).toHaveBeenCalledWith({ + where: { id: orderId }, + }); + expect(result).toEqual(mockOrder); + }); + }); + + describe('updateStatus', () => { + it('should update an order status', async () => { + const orderId = 'order-123'; + const newStatus = OrderStatus.APPROVED; + const mockOrder = { + id: orderId, + productId: 'product-123', + buyerAddress: 'buyer-address-123', + sellerAddress: 'seller-address-123', + escrowId: 'escrow-123', + status: newStatus, + createdAt: new Date(), + updatedAt: new Date(), + }; + + mockPrismaService.order.update.mockResolvedValue(mockOrder); + + const result = await service.updateStatus(orderId, newStatus); + + expect(mockPrismaService.order.update).toHaveBeenCalledWith({ + where: { id: orderId }, + data: { status: newStatus }, + }); + expect(result).toEqual(mockOrder); + }); + }); +}); diff --git a/apps/backend/src/modules/order/order.service.ts b/apps/backend/src/modules/order/order.service.ts new file mode 100644 index 0000000..8217722 --- /dev/null +++ b/apps/backend/src/modules/order/order.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@nestjs/common'; +import { PrismaService } from 'src/core/prisma/prisma.service'; +import { CreateOrderInput } from './dto/create-order.input'; +import { OrderStatus } from './entities/order.entity'; + +@Injectable() +export class OrderService { + constructor(private prisma: PrismaService) {} + + create(data: CreateOrderInput) { + return this.prisma.order.create({ + data: { + productId: data.productId, + buyerAddress: data.buyerAddress, + sellerAddress: data.sellerAddress, + escrowId: data.escrowId, + status: data.status, + }, + }); + } + + findAllByBuyer(buyerAddress: string) { + return this.prisma.order.findMany({ + where: { buyerAddress }, + }); + } + + findAllBySeller(sellerAddress: string) { + return this.prisma.order.findMany({ + where: { sellerAddress }, + }); + } + + findOne(id: string) { + return this.prisma.order.findUnique({ where: { id } }); + } + + updateStatus(orderId: string, status: OrderStatus) { + return this.prisma.order.update({ + where: { id: orderId }, + data: { status }, + }); + } +} diff --git a/package-lock.json b/package-lock.json index 569e4c7..7f490e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,12 +37,16 @@ "@nestjs/config": "^4.0.0", "@nestjs/core": "^11.0.1", "@nestjs/graphql": "^13.0.2", + "@nestjs/jwt": "^11.0.0", "@nestjs/mapped-types": "*", + "@nestjs/passport": "^11.0.5", "@nestjs/platform-express": "^11.0.7", "@prisma/client": "^6.3.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "graphql": "^16.10.0", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "slugify": "^1.6.6"