This commit is contained in:
2026-02-09 15:47:17 +03:30
parent 65b937d662
commit 8c9e7053f5
10 changed files with 90 additions and 123 deletions
+26 -27
View File
@@ -19,66 +19,65 @@ export class CartController {
@Get() @Get()
@ApiOperation({ summary: 'Get cart for current user and shop' }) @ApiOperation({ summary: 'Get cart for current user and shop' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
async findOne(@UserId() userId: string, @ShopId() restaurantId: string) { async findOne(@UserId() userId: string, @ShopId() shopId: string) {
return this.cartService.getOrCreateCart(userId, restaurantId); return this.cartService.getOrCreateCart(userId, shopId);
} }
@Post('items/:foodId/increment') @Post('product/:productId/increment')
@ApiOperation({ summary: 'Increment item quantity in cart by 1' }) @ApiOperation({ summary: 'Increment item quantity in cart by 1' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
@ApiParam({ name: 'foodId', description: 'Product ID to increment in cart' }) @ApiParam({ name: 'productId', description: 'Product ID to increment in cart' })
async incrementItem(@UserId() userId: string, @ShopId() restaurantId: string, @Param('foodId') foodId: string) { async incrementItem(@UserId() userId: string, @ShopId() shopId: string, @Param('productId') productId: string) {
return this.cartService.incrementItem(userId, restaurantId, foodId, 1); return this.cartService.incrementItem(userId, shopId, productId, 1);
} }
@Post('items/:foodId/decrement') @Post('product/:productId/decrement')
@ApiOperation({ summary: 'Decrement item quantity in cart by 1 (removes item if quantity reaches 0)' }) @ApiOperation({ summary: 'Decrement item quantity in cart by 1 (removes item if quantity reaches 0)' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
@ApiParam({ name: 'foodId', description: 'Product ID to decrement in cart' }) @ApiParam({ name: 'productId', description: 'Product ID to decrement in cart' })
async decrementItem(@UserId() userId: string, @ShopId() restaurantId: string, @Param('foodId') foodId: string) { async decrementItem(@UserId() userId: string, @ShopId() shopId: string, @Param('productId') productId: string) {
return this.cartService.decrementItem(userId, restaurantId, foodId); return this.cartService.decrementItem(userId, shopId, productId);
} }
@Post('items/bulk') @Post('product/bulk')
@ApiOperation({ summary: 'Bulk add items to cart (increments quantity if items exist)' }) @ApiOperation({ summary: 'Bulk add items to cart (increments quantity if items exist)' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
@ApiBody({ type: BulkAddItemsToCartDto }) @ApiBody({ type: BulkAddItemsToCartDto })
bulkAddItems( bulkAddItems(
@UserId() userId: string, @UserId() userId: string,
@ShopId() restaurantId: string, @ShopId() shopId: string,
@Body() bulkAddItemsDto: BulkAddItemsToCartDto, @Body() bulkAddItemsDto: BulkAddItemsToCartDto,
) { ) {
return this.cartService.bulkAddItems(userId, restaurantId, bulkAddItemsDto); return this.cartService.bulkAddItems(userId, shopId, bulkAddItemsDto);
} }
@Delete('items/:foodId') @Delete('product/:productId')
@ApiOperation({ summary: 'Remove item from cart' }) @ApiOperation({ summary: 'Remove item from cart' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
@ApiParam({ name: 'foodId', description: 'Product ID in the cart' }) @ApiParam({ name: 'productId', description: 'Product ID in the cart' })
async removeItem(@UserId() userId: string, @ShopId() restaurantId: string, @Param('foodId') foodId: string) { async removeItem(@UserId() userId: string, @ShopId() shopId: string, @Param('productId') productId: string) {
return this.cartService.removeItem(userId, restaurantId, foodId); return this.cartService.removeItem(userId, shopId, productId);
} }
@Delete() @Delete()
@ApiOperation({ summary: 'Clear entire cart' }) @ApiOperation({ summary: 'Clear entire cart' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
async clearCart(@UserId() userId: string, @ShopId() restaurantId: string) { async clearCart(@UserId() userId: string, @ShopId() shopId: string) {
return this.cartService.clearCart(userId, restaurantId); return this.cartService.clearCart(userId, shopId);
} }
@Post('apply-coupon') @Post('coupon')
@ApiOperation({ summary: 'Apply coupon to cart' }) @ApiOperation({ summary: 'Apply coupon to cart' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
@ApiBody({ type: ApplyCouponDto }) async applyCoupon(@UserId() userId: string, @ShopId() shopId: string, @Body() applyCouponDto: ApplyCouponDto) {
async applyCoupon(@UserId() userId: string, @ShopId() restaurantId: string, @Body() applyCouponDto: ApplyCouponDto) { return this.cartService.applyCoupon(userId, shopId, applyCouponDto);
return this.cartService.applyCoupon(userId, restaurantId, applyCouponDto);
} }
@Delete('coupon') @Delete('coupon')
@ApiOperation({ summary: 'Remove coupon from cart' }) @ApiOperation({ summary: 'Remove coupon from cart' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
async removeCoupon(@UserId() userId: string, @ShopId() restaurantId: string) { async removeCoupon(@UserId() userId: string, @ShopId() shopId: string) {
return this.cartService.removeCoupon(userId, restaurantId); return this.cartService.removeCoupon(userId, shopId);
} }
@@ -86,7 +85,7 @@ export class CartController {
@ApiOperation({ summary: 'Set all cart params' }) @ApiOperation({ summary: 'Set all cart params' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
@ApiBody({ type: SetAllCartParmsDto }) @ApiBody({ type: SetAllCartParmsDto })
setAllCartParams(@UserId() userId: string, @ShopId() restaurantId: string, @Body() dto: SetAllCartParmsDto) { setAllCartParams(@UserId() userId: string, @ShopId() shopId: string, @Body() dto: SetAllCartParmsDto) {
return this.cartService.setAllCartParams(userId, restaurantId, dto); return this.cartService.setAllCartParams(userId, shopId, dto);
} }
} }
+3 -3
View File
@@ -13,7 +13,7 @@ class AddItemToCartDto {
@ApiProperty({ description: 'Product ID' }) @ApiProperty({ description: 'Product ID' })
@IsNotEmpty() @IsNotEmpty()
@IsString() @IsString()
foodId!: string; productId!: string;
} }
export class BulkAddItemsToCartDto { export class BulkAddItemsToCartDto {
@@ -21,8 +21,8 @@ export class BulkAddItemsToCartDto {
description: 'Array of items to add to cart', description: 'Array of items to add to cart',
type: [AddItemToCartDto], type: [AddItemToCartDto],
example: [ example: [
{ foodId: 'product-123', quantity: 2 }, { productId: 'product-123', quantity: 2 },
{ foodId: 'product-456', quantity: 1 }, { productId: 'product-456', quantity: 1 },
], ],
}) })
@IsNotEmpty() @IsNotEmpty()
@@ -1,8 +1,6 @@
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsObject, IsOptional, IsString } from 'class-validator'; import { IsNotEmpty, IsObject, IsOptional, IsString } from 'class-validator';
import { SetCarDeliveryDto } from './set-car-delivery.dto';
export class SetAllCartParmsDto { export class SetAllCartParmsDto {
@ApiProperty({ @ApiProperty({
description: 'Cart description or notes', description: 'Cart description or notes',
@@ -27,14 +25,4 @@ export class SetAllCartParmsDto {
@IsNotEmpty() @IsNotEmpty()
@IsString() @IsString()
paymentMethodId!: string; paymentMethodId!: string;
@ApiProperty({ description: 'Table number for dine-in orders', example: '5', required: false })
@IsOptional()
@IsString()
tableNumber?: string;
@ApiProperty()
@IsOptional()
@IsObject()
carAddress?: SetCarDeliveryDto;
} }
@@ -1,19 +0,0 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class SetCarDeliveryDto {
@ApiProperty({ description: 'Car model', example: 'Toyota Camry' })
@IsNotEmpty()
@IsString()
carModel!: string;
@ApiProperty({ description: 'Car color', example: 'White' })
@IsNotEmpty()
@IsString()
carColor!: string;
@ApiProperty({ description: 'License plate number', example: '12ABC345' })
@IsNotEmpty()
@IsString()
plateNumber!: string;
}
@@ -11,8 +11,8 @@ export interface CartItem {
export interface Cart { export interface Cart {
userId: string; userId: string;
restaurantId: string; shopId: string;
restaurantName?: string; shopName?: string;
items: CartItem[]; items: CartItem[];
coupon?: OrderCouponDetail; coupon?: OrderCouponDetail;
@@ -173,7 +173,7 @@ export class CartCalculationService {
cart.couponDiscount = couponDiscount; cart.couponDiscount = couponDiscount;
cart.totalDiscount = couponDiscount + itemsDiscount; cart.totalDiscount = couponDiscount + itemsDiscount;
cart.tax = await this.calculateTax(cart.restaurantId, Math.max(0, subTotal - cart.totalDiscount)); cart.tax = await this.calculateTax(cart.shopId, Math.max(0, subTotal - cart.totalDiscount));
cart.deliveryFee = await this.calculateDeliveryFee(cart); cart.deliveryFee = await this.calculateDeliveryFee(cart);
// total = subtotal totalDiscount + tax + deliveryFee // total = subtotal totalDiscount + tax + deliveryFee
@@ -58,8 +58,8 @@ export class CartItemService {
/** /**
* Add or increment item in cart * Add or increment item in cart
*/ */
async addOrIncrementItem(cart: Cart, shopId: string, restaurantId: string, quantityToAdd: number): Promise<void> { async addOrIncrementItem(cart: Cart, productId: string, shopId: string, quantityToAdd: number): Promise<void> {
const product = await this.validationService.validateAndGetFood(shopId, restaurantId, quantityToAdd); const product = await this.validationService.validateAndGetFood(productId, shopId, quantityToAdd);
const index = this.getItemIndex(cart, product.id); const index = this.getItemIndex(cart, product.id);
@@ -14,7 +14,6 @@ import { WalletTransactionRepository } from 'src/modules/users/repositories/wall
import { ProductService } from 'src/modules/products/providers/product.service'; import { ProductService } from 'src/modules/products/providers/product.service';
import { ShopService } from 'src/modules/shops/providers/shops.service'; import { ShopService } from 'src/modules/shops/providers/shops.service';
import { DeliveryService } from 'src/modules/delivery/providers/delivery.service'; import { DeliveryService } from 'src/modules/delivery/providers/delivery.service';
import { PaymentsService } from 'src/modules/payments/services/payments.service';
import { PaymentMethodService } from 'src/modules/payments/services/payment-method.service'; import { PaymentMethodService } from 'src/modules/payments/services/payment-method.service';
@Injectable() @Injectable()
+45 -45
View File
@@ -5,7 +5,7 @@ import { OrderCouponDetail } from 'src/modules/orders/interface/order.interface'
import { Cart } from '../interfaces/cart.interface'; import { Cart } from '../interfaces/cart.interface';
import { BulkAddItemsToCartDto } from '../dto/bulk-add-items.dto'; import { BulkAddItemsToCartDto } from '../dto/bulk-add-items.dto';
import { ApplyCouponDto } from '../dto/apply-coupon.dto'; import { ApplyCouponDto } from '../dto/apply-coupon.dto';
import { SetAllCartParmsDto } from '../dto/set-all-cart-params.dto'; import { SetAllCartParmsDto } from '../dto/set-all-cart-params.dto';
import { CouponService } from 'src/modules/coupons/providers/coupon.service'; import { CouponService } from 'src/modules/coupons/providers/coupon.service';
import { CartRepository } from '../repositories/cart.repository'; import { CartRepository } from '../repositories/cart.repository';
import { CartValidationService } from './cart-validation.service'; import { CartValidationService } from './cart-validation.service';
@@ -32,15 +32,15 @@ export class CartService {
/** /**
* Set all cart parameters at once * Set all cart parameters at once
*/ */
async setAllCartParams(userId: string, restaurantId: string, params: SetAllCartParmsDto): Promise<Cart> { async setAllCartParams(userId: string, shopId: string, params: SetAllCartParmsDto): Promise<Cart> {
const { deliveryMethodId, paymentMethodId, addressId, carAddress, description, tableNumber } = params; const { deliveryMethodId, paymentMethodId, addressId, description } = params;
// get existing cart (or throw) // get existing cart (or throw)
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
// Validate and get delivery method // Validate and get delivery method
const deliveryMethod = await this.validationService.getEnabledDeliveryMethodOrFail( const deliveryMethod = await this.validationService.getEnabledDeliveryMethodOrFail(
restaurantId, shopId,
deliveryMethodId, deliveryMethodId,
); );
cart.deliveryMethodId = deliveryMethodId; cart.deliveryMethodId = deliveryMethodId;
@@ -65,7 +65,7 @@ export class CartService {
// ensure address is within shop service area // ensure address is within shop service area
await this.validationService.assertAddressInsideServiceArea( await this.validationService.assertAddressInsideServiceArea(
restaurantId, shopId,
address.latitude, address.latitude,
address.longitude, address.longitude,
); );
@@ -85,7 +85,7 @@ export class CartService {
// Validate and set payment method // Validate and set payment method
const paymentMethod = await this.validationService.getEnabledPaymentMethodOrFail( const paymentMethod = await this.validationService.getEnabledPaymentMethodOrFail(
restaurantId, shopId,
paymentMethodId, paymentMethodId,
); );
@@ -93,7 +93,7 @@ export class CartService {
await this.calculationService.recalculateCartTotals(cart); await this.calculationService.recalculateCartTotals(cart);
if (paymentMethod.method === PaymentMethodEnum.Wallet) { if (paymentMethod.method === PaymentMethodEnum.Wallet) {
await this.validationService.assertWalletHasEnoughBalance(userId, restaurantId, cart.total); await this.validationService.assertWalletHasEnoughBalance(userId, shopId, cart.total);
} }
cart.paymentMethodId = paymentMethodId; cart.paymentMethodId = paymentMethodId;
@@ -110,21 +110,21 @@ export class CartService {
/** /**
* Get or create cart for user and shop * Get or create cart for user and shop
*/ */
async getOrCreateCart(userId: string, restaurantId: string): Promise<Cart> { async getOrCreateCart(userId: string, shopId: string): Promise<Cart> {
const existingCart = await this.cartRepository.findByUserAndRestaurant(userId, restaurantId); const existingCart = await this.cartRepository.findByUserAndShop(userId, shopId);
if (existingCart) { if (existingCart) {
return existingCart; return existingCart;
} }
// Find shop // Find shop
const shop = await this.shopService.findOrFail(restaurantId); const shop = await this.shopService.findOrFail(shopId);
// Create new cart // Create new cart
const now = this.nowIso(); const now = this.nowIso();
const cart: Cart = { const cart: Cart = {
userId, userId,
restaurantId, shopId: shop.id,
restaurantName: shop.name, shopName: shop.name,
items: [], items: [],
deliveryFee: 0, deliveryFee: 0,
subTotal: 0, subTotal: 0,
@@ -145,8 +145,8 @@ export class CartService {
/** /**
* Find cart by user and shop * Find cart by user and shop
*/ */
async findOneOrFail(userId: string, restaurantId: string): Promise<Cart> { async findOneOrFail(userId: string, shopId: string): Promise<Cart> {
const cart = await this.cartRepository.findByUserAndRestaurant(userId, restaurantId); const cart = await this.cartRepository.findByUserAndShop(userId, shopId);
if (!cart) { if (!cart) {
throw new NotFoundException(CartMessage.NOT_FOUND); throw new NotFoundException(CartMessage.NOT_FOUND);
} }
@@ -156,17 +156,17 @@ export class CartService {
/** /**
* Increment item quantity in cart * Increment item quantity in cart
*/ */
async incrementItem(userId: string, restaurantId: string, foodId: string, quantity: number): Promise<Cart> { async incrementItem(userId: string, shopId: string, foodId: string, quantity: number): Promise<Cart> {
const cart = await this.getOrCreateCart(userId, restaurantId); const cart = await this.getOrCreateCart(userId, shopId);
await this.itemService.addOrIncrementItem(cart, foodId, restaurantId, quantity); await this.itemService.addOrIncrementItem(cart, foodId, shopId, quantity);
return this.recalculateAndSaveCart(cart); return this.recalculateAndSaveCart(cart);
} }
/** /**
* Decrement item quantity in cart by 1 (removes item if quantity reaches 0) * Decrement item quantity in cart by 1 (removes item if quantity reaches 0)
*/ */
async decrementItem(userId: string, restaurantId: string, foodId: string): Promise<Cart> { async decrementItem(userId: string, shopId: string, foodId: string): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
await this.itemService.decrementOrRemoveItem(cart, foodId); await this.itemService.decrementOrRemoveItem(cart, foodId);
return this.recalculateAndSaveCart(cart); return this.recalculateAndSaveCart(cart);
} }
@@ -174,11 +174,11 @@ export class CartService {
/** /**
* Bulk add items to cart (increments quantity if items exist) * Bulk add items to cart (increments quantity if items exist)
*/ */
async bulkAddItems(userId: string, restaurantId: string, bulkAddItemsDto: BulkAddItemsToCartDto): Promise<Cart> { async bulkAddItems(userId: string, shopId: string, bulkAddItemsDto: BulkAddItemsToCartDto): Promise<Cart> {
const cart = await this.getOrCreateCart(userId, restaurantId); const cart = await this.getOrCreateCart(userId, shopId);
for (const addItemDto of bulkAddItemsDto.items) { for (const addItemDto of bulkAddItemsDto.items) {
await this.itemService.addOrIncrementItem(cart, addItemDto.foodId, restaurantId, addItemDto.quantity); await this.itemService.addOrIncrementItem(cart, addItemDto.productId, shopId, addItemDto.quantity);
} }
return this.recalculateAndSaveCart(cart); return this.recalculateAndSaveCart(cart);
@@ -187,8 +187,8 @@ export class CartService {
/** /**
* Remove item from cart * Remove item from cart
*/ */
async removeItem(userId: string, restaurantId: string, foodId: string): Promise<Cart> { async removeItem(userId: string, shopId: string, foodId: string): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
this.itemService.removeItemOrFail(cart, foodId); this.itemService.removeItemOrFail(cart, foodId);
return this.recalculateAndSaveCart(cart); return this.recalculateAndSaveCart(cart);
} }
@@ -196,15 +196,15 @@ export class CartService {
/** /**
* Apply coupon to cart * Apply coupon to cart
*/ */
async applyCoupon(userId: string, restaurantId: string, applyCouponDto: ApplyCouponDto): Promise<Cart> { async applyCoupon(userId: string, shopId: string, applyCouponDto: ApplyCouponDto): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
const orderAmount = cart.subTotal - cart.itemsDiscount; const orderAmount = cart.subTotal - cart.itemsDiscount;
const user = await this.userService.findOneOrFail(userId); const user = await this.userService.findOneOrFail(userId);
// check if coupon is valid and belong to the shop // check if coupon is valid and belong to the shop
const { valid, coupon, message } = await this.couponService.validateCoupon( const { valid, coupon, message } = await this.couponService.validateCoupon(
applyCouponDto.code, applyCouponDto.code,
restaurantId, shopId,
Number(orderAmount), Number(orderAmount),
user.phone, user.phone,
); );
@@ -241,8 +241,8 @@ export class CartService {
/** /**
* Remove coupon from cart * Remove coupon from cart
*/ */
async removeCoupon(userId: string, restaurantId: string): Promise<Cart> { async removeCoupon(userId: string, shopId: string): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
cart.coupon = undefined; cart.coupon = undefined;
return this.recalculateAndSaveCart(cart); return this.recalculateAndSaveCart(cart);
@@ -251,14 +251,14 @@ export class CartService {
/** /**
* Set address for cart * Set address for cart
*/ */
async setAddress(userId: string, restaurantId: string, addressId: string): Promise<Cart> { async setAddress(userId: string, shopId: string, addressId: string): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
const deliveryMethodId = this.validationService.requireDeliveryMethodId( const deliveryMethodId = this.validationService.requireDeliveryMethodId(
cart, cart,
'Delivery method must be set before setting address', 'Delivery method must be set before setting address',
); );
const deliveryMethod = await this.deliveryService.findOrFail(restaurantId, deliveryMethodId); const deliveryMethod = await this.deliveryService.findOrFail(shopId, deliveryMethodId);
this.validationService.assertDeliveryMethod( this.validationService.assertDeliveryMethod(
deliveryMethod.method, deliveryMethod.method,
@@ -274,7 +274,7 @@ export class CartService {
// ensure address is within shop service area // ensure address is within shop service area
await this.validationService.assertAddressInsideServiceArea( await this.validationService.assertAddressInsideServiceArea(
restaurantId, shopId,
address.latitude, address.latitude,
address.longitude, address.longitude,
); );
@@ -298,17 +298,17 @@ export class CartService {
*/ */
async setPaymentMethod( async setPaymentMethod(
userId: string, userId: string,
restaurantId: string, shopId: string,
paymentMethodId: string, paymentMethodId: string,
): Promise<Cart> { ): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
const paymentMethod = await this.validationService.getEnabledPaymentMethodOrFail( const paymentMethod = await this.validationService.getEnabledPaymentMethodOrFail(
restaurantId, shopId,
paymentMethodId, paymentMethodId,
); );
if (paymentMethod.method === PaymentMethodEnum.Wallet) { if (paymentMethod.method === PaymentMethodEnum.Wallet) {
await this.validationService.assertWalletHasEnoughBalance(userId, restaurantId, cart.total); await this.validationService.assertWalletHasEnoughBalance(userId, shopId, cart.total);
} }
cart.paymentMethodId = paymentMethodId; cart.paymentMethodId = paymentMethodId;
return this.recalculateAndSaveCart(cart); return this.recalculateAndSaveCart(cart);
@@ -319,13 +319,13 @@ export class CartService {
*/ */
async setDeliveryMethod( async setDeliveryMethod(
userId: string, userId: string,
restaurantId: string, shopId: string,
deliveryMethodId: string, deliveryMethodId: string,
): Promise<Cart> { ): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
const deliveryMethod = await this.validationService.getEnabledDeliveryMethodOrFail( const deliveryMethod = await this.validationService.getEnabledDeliveryMethodOrFail(
restaurantId, shopId,
deliveryMethodId, deliveryMethodId,
); );
@@ -338,8 +338,8 @@ export class CartService {
/** /**
* Set description for cart * Set description for cart
*/ */
async setDescription(userId: string, restaurantId: string, description: string): Promise<Cart> { async setDescription(userId: string, shopId: string, description: string): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, shopId);
cart.description = description; cart.description = description;
return this.saveTouchedCart(cart); return this.saveTouchedCart(cart);
@@ -349,8 +349,8 @@ export class CartService {
/** /**
* Clear cart from cache * Clear cart from cache
*/ */
async clearCart(userId: string, restaurantId: string): Promise<void> { async clearCart(userId: string, shopId: string): Promise<void> {
return this.cartRepository.delete(userId, restaurantId); return this.cartRepository.delete(userId, shopId);
} }
/** /**
@@ -7,19 +7,19 @@ export class CartRepository {
private readonly CART_TTL = 3600; // 1 hour in seconds private readonly CART_TTL = 3600; // 1 hour in seconds
private readonly CART_KEY_PREFIX = 'cart'; private readonly CART_KEY_PREFIX = 'cart';
constructor(private readonly cacheService: CacheService) {} constructor(private readonly cacheService: CacheService) { }
/** /**
* Get cart by user and shop * Get cart by user and shop
*/ */
async findByUserAndRestaurant(userId: string, restaurantId: string): Promise<Cart | null> { async findByUserAndShop(userId: string, shopId: string): Promise<Cart | null> {
const cacheKey = this.getCacheKey(userId, restaurantId); const cacheKey = this.getCacheKey(userId, shopId);
const cachedCart = await this.cacheService.get<string>(cacheKey); const cachedCart = await this.cacheService.get<string>(cacheKey);
if (cachedCart) { if (cachedCart) {
try { try {
const parsed: unknown = JSON.parse(cachedCart); const parsed: unknown = JSON.parse(cachedCart);
if (this.isCart(parsed) && parsed.userId === userId && parsed.restaurantId === restaurantId) { if (this.isCart(parsed) && parsed.userId === userId && parsed.shopId === shopId) {
return parsed; return parsed;
} }
} catch { } catch {
@@ -34,23 +34,23 @@ export class CartRepository {
* Save cart to cache * Save cart to cache
*/ */
async save(cart: Cart): Promise<void> { async save(cart: Cart): Promise<void> {
const cacheKey = this.getCacheKey(cart.userId, cart.restaurantId); const cacheKey = this.getCacheKey(cart.userId, cart.shopId);
await this.cacheService.set(cacheKey, JSON.stringify(cart), this.CART_TTL); await this.cacheService.set(cacheKey, JSON.stringify(cart), this.CART_TTL);
} }
/** /**
* Delete cart from cache * Delete cart from cache
*/ */
async delete(userId: string, restaurantId: string): Promise<void> { async delete(userId: string, shopId: string): Promise<void> {
const cacheKey = this.getCacheKey(userId, restaurantId); const cacheKey = this.getCacheKey(userId, shopId);
await this.cacheService.del(cacheKey); await this.cacheService.del(cacheKey);
} }
/** /**
* Generate cache key for cart * Generate cache key for cart
*/ */
private getCacheKey(userId: string, restaurantId: string): string { private getCacheKey(userId: string, shopId: string): string {
return `${this.CART_KEY_PREFIX}:${userId}:${restaurantId}`; return `${this.CART_KEY_PREFIX}:${userId}:${shopId}`;
} }
/** /**
@@ -63,7 +63,7 @@ export class CartRepository {
const cart = obj as Record<string, unknown>; const cart = obj as Record<string, unknown>;
return ( return (
typeof cart.userId === 'string' && typeof cart.userId === 'string' &&
typeof cart.restaurantId === 'string' && typeof cart.shopId === 'string' &&
Array.isArray(cart.items) && Array.isArray(cart.items) &&
typeof cart.subTotal === 'number' && typeof cart.subTotal === 'number' &&
typeof cart.itemsDiscount === 'number' && typeof cart.itemsDiscount === 'number' &&