From cc28b78596866aece9e9bcdfdf381b4f510e5940 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Sun, 23 Nov 2025 01:07:49 +0330 Subject: [PATCH] address --- src/modules/cart/cart.module.ts | 7 +-- .../cart/controllers/cart.controller.ts | 11 ++++ src/modules/cart/dto/set-address.dto.ts | 10 ++++ src/modules/cart/interfaces/cart.interface.ts | 32 ++++++++++ src/modules/cart/providers/cart.service.ts | 59 +++++++++---------- 5 files changed, 82 insertions(+), 37 deletions(-) create mode 100644 src/modules/cart/dto/set-address.dto.ts create mode 100644 src/modules/cart/interfaces/cart.interface.ts diff --git a/src/modules/cart/cart.module.ts b/src/modules/cart/cart.module.ts index 34ae69a..25dafc8 100644 --- a/src/modules/cart/cart.module.ts +++ b/src/modules/cart/cart.module.ts @@ -9,12 +9,7 @@ import { JwtModule } from '@nestjs/jwt'; import { UtilsModule } from '../utils/utils.module'; @Module({ - imports: [ - MikroOrmModule.forFeature([Food, Restaurant]), - AuthModule, - JwtModule, - UtilsModule, - ], + imports: [MikroOrmModule.forFeature([Food, Restaurant]), AuthModule, JwtModule, UtilsModule], controllers: [CartController], providers: [CartService], exports: [CartService], diff --git a/src/modules/cart/controllers/cart.controller.ts b/src/modules/cart/controllers/cart.controller.ts index f58dcd5..70156d9 100644 --- a/src/modules/cart/controllers/cart.controller.ts +++ b/src/modules/cart/controllers/cart.controller.ts @@ -3,6 +3,7 @@ import { CartService } from '../providers/cart.service'; import { AddItemToCartDto } from '../dto/add-item.dto'; import { UpdateItemQuantityDto } from '../dto/update-item.dto'; import { ApplyCouponDto } from '../dto/apply-coupon.dto'; +import { SetAddressDto } from '../dto/set-address.dto'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiBody, ApiParam } from '@nestjs/swagger'; import { AuthGuard } from '../../auth/guards/auth.guard'; import { UserId } from 'src/common/decorators/user-id.decorator'; @@ -73,4 +74,14 @@ export class CartController { async removeCoupon(@UserId() userId: string, @RestId() restaurantId: string) { return this.cartService.removeCoupon(userId, restaurantId); } + + @Patch('address') + @ApiOperation({ summary: 'Set address for cart' }) + @ApiBody({ type: SetAddressDto }) + @ApiResponse({ status: 200, description: 'Address set successfully' }) + @ApiResponse({ status: 400, description: 'Bad request (e.g., address does not belong to user)' }) + @ApiResponse({ status: 404, description: 'Address not found' }) + async setAddress(@UserId() userId: string, @RestId() restaurantId: string, @Body() setAddressDto: SetAddressDto) { + return this.cartService.setAddress(userId, restaurantId, setAddressDto); + } } diff --git a/src/modules/cart/dto/set-address.dto.ts b/src/modules/cart/dto/set-address.dto.ts new file mode 100644 index 0000000..d521793 --- /dev/null +++ b/src/modules/cart/dto/set-address.dto.ts @@ -0,0 +1,10 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString } from 'class-validator'; + +export class SetAddressDto { + @ApiProperty({ description: 'User address ID', example: '01ARZ3NDEKTSV4RRFFQ69G5FAV' }) + @IsNotEmpty() + @IsString() + addressId!: string; +} + diff --git a/src/modules/cart/interfaces/cart.interface.ts b/src/modules/cart/interfaces/cart.interface.ts new file mode 100644 index 0000000..602fc67 --- /dev/null +++ b/src/modules/cart/interfaces/cart.interface.ts @@ -0,0 +1,32 @@ +export interface CartItem { + itemId: string; + foodId: string; + foodTitle?: string; + quantity: number; + price: number; + discount: number; + totalPrice: number; +} + +export interface CartCoupon { + code: string; + discount: number; + discountType: 'amount' | 'percentage'; +} + +export interface Cart { + userId: string; + restaurantId: string; + restaurantName?: string; + items: CartItem[]; + coupon?: CartCoupon; + addressId?: string; + totalPrice: number; + totalDiscount: number; + couponDiscount: number; + vatAmount: number; + finalPrice: number; + totalItems: number; + createdAt: string; + updatedAt: string; +} diff --git a/src/modules/cart/providers/cart.service.ts b/src/modules/cart/providers/cart.service.ts index 9ee48e7..70c4816 100644 --- a/src/modules/cart/providers/cart.service.ts +++ b/src/modules/cart/providers/cart.service.ts @@ -7,38 +7,10 @@ import { ulid } from 'ulid'; import { AddItemToCartDto } from '../dto/add-item.dto'; import { UpdateItemQuantityDto } from '../dto/update-item.dto'; import { ApplyCouponDto } from '../dto/apply-coupon.dto'; +import { SetAddressDto } from '../dto/set-address.dto'; +import { UserAddress } from '../../users/entities/user-address.entity'; +import { Cart, CartItem, CartCoupon } from '../interfaces/cart.interface'; -export interface CartItem { - itemId: string; - foodId: string; - foodTitle?: string; - quantity: number; - price: number; - discount: number; - totalPrice: number; -} - -export interface CartCoupon { - code: string; - discount: number; - discountType: 'amount' | 'percentage'; -} - -export interface Cart { - userId: string; - restaurantId: string; - restaurantName?: string; - items: CartItem[]; - coupon?: CartCoupon; - totalPrice: number; - totalDiscount: number; - couponDiscount: number; - vatAmount: number; - finalPrice: number; - totalItems: number; - createdAt: string; - updatedAt: string; -} @Injectable() export class CartService { @@ -282,6 +254,31 @@ export class CartService { return cart; } + /** + * Set address for cart + */ + async setAddress(userId: string, restaurantId: string, setAddressDto: SetAddressDto): Promise { + const cart = await this.findOne(userId, restaurantId); + + // Find and validate address belongs to user + const address = await this.em.findOne(UserAddress, { id: setAddressDto.addressId }, { populate: ['user'] }); + if (!address) { + throw new NotFoundException(`Address with ID ${setAddressDto.addressId} not found`); + } + + // Verify address belongs to the user + if (address.user.id !== userId) { + throw new BadRequestException('Address does not belong to the current user'); + } + + cart.addressId = setAddressDto.addressId; + cart.updatedAt = new Date().toISOString(); + + await this.saveCart(cart); + + return cart; + } + /** * Recalculate cart totals (including coupon discount and VAT) */