This commit is contained in:
2025-11-23 01:07:49 +03:30
parent d9dde39a20
commit cc28b78596
5 changed files with 82 additions and 37 deletions
+1 -6
View File
@@ -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],
@@ -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);
}
}
+10
View File
@@ -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;
}
@@ -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;
}
+28 -31
View File
@@ -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<Cart> {
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)
*/