cart
This commit is contained in:
@@ -19,66 +19,65 @@ export class CartController {
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Get cart for current user and shop' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
async findOne(@UserId() userId: string, @ShopId() restaurantId: string) {
|
||||
return this.cartService.getOrCreateCart(userId, restaurantId);
|
||||
async findOne(@UserId() userId: string, @ShopId() shopId: string) {
|
||||
return this.cartService.getOrCreateCart(userId, shopId);
|
||||
}
|
||||
|
||||
@Post('items/:foodId/increment')
|
||||
@Post('product/:productId/increment')
|
||||
@ApiOperation({ summary: 'Increment item quantity in cart by 1' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@ApiParam({ name: 'foodId', description: 'Product ID to increment in cart' })
|
||||
async incrementItem(@UserId() userId: string, @ShopId() restaurantId: string, @Param('foodId') foodId: string) {
|
||||
return this.cartService.incrementItem(userId, restaurantId, foodId, 1);
|
||||
@ApiParam({ name: 'productId', description: 'Product ID to increment in cart' })
|
||||
async incrementItem(@UserId() userId: string, @ShopId() shopId: string, @Param('productId') productId: string) {
|
||||
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)' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@ApiParam({ name: 'foodId', description: 'Product ID to decrement in cart' })
|
||||
async decrementItem(@UserId() userId: string, @ShopId() restaurantId: string, @Param('foodId') foodId: string) {
|
||||
return this.cartService.decrementItem(userId, restaurantId, foodId);
|
||||
@ApiParam({ name: 'productId', description: 'Product ID to decrement in cart' })
|
||||
async decrementItem(@UserId() userId: string, @ShopId() shopId: string, @Param('productId') productId: string) {
|
||||
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)' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@ApiBody({ type: BulkAddItemsToCartDto })
|
||||
bulkAddItems(
|
||||
@UserId() userId: string,
|
||||
@ShopId() restaurantId: string,
|
||||
@ShopId() shopId: string,
|
||||
@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' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@ApiParam({ name: 'foodId', description: 'Product ID in the cart' })
|
||||
async removeItem(@UserId() userId: string, @ShopId() restaurantId: string, @Param('foodId') foodId: string) {
|
||||
return this.cartService.removeItem(userId, restaurantId, foodId);
|
||||
@ApiParam({ name: 'productId', description: 'Product ID in the cart' })
|
||||
async removeItem(@UserId() userId: string, @ShopId() shopId: string, @Param('productId') productId: string) {
|
||||
return this.cartService.removeItem(userId, shopId, productId);
|
||||
}
|
||||
|
||||
@Delete()
|
||||
@ApiOperation({ summary: 'Clear entire cart' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
async clearCart(@UserId() userId: string, @ShopId() restaurantId: string) {
|
||||
return this.cartService.clearCart(userId, restaurantId);
|
||||
async clearCart(@UserId() userId: string, @ShopId() shopId: string) {
|
||||
return this.cartService.clearCart(userId, shopId);
|
||||
}
|
||||
|
||||
@Post('apply-coupon')
|
||||
@Post('coupon')
|
||||
@ApiOperation({ summary: 'Apply coupon to cart' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@ApiBody({ type: ApplyCouponDto })
|
||||
async applyCoupon(@UserId() userId: string, @ShopId() restaurantId: string, @Body() applyCouponDto: ApplyCouponDto) {
|
||||
return this.cartService.applyCoupon(userId, restaurantId, applyCouponDto);
|
||||
async applyCoupon(@UserId() userId: string, @ShopId() shopId: string, @Body() applyCouponDto: ApplyCouponDto) {
|
||||
return this.cartService.applyCoupon(userId, shopId, applyCouponDto);
|
||||
}
|
||||
|
||||
@Delete('coupon')
|
||||
@ApiOperation({ summary: 'Remove coupon from cart' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
async removeCoupon(@UserId() userId: string, @ShopId() restaurantId: string) {
|
||||
return this.cartService.removeCoupon(userId, restaurantId);
|
||||
async removeCoupon(@UserId() userId: string, @ShopId() shopId: string) {
|
||||
return this.cartService.removeCoupon(userId, shopId);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +85,7 @@ export class CartController {
|
||||
@ApiOperation({ summary: 'Set all cart params' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@ApiBody({ type: SetAllCartParmsDto })
|
||||
setAllCartParams(@UserId() userId: string, @ShopId() restaurantId: string, @Body() dto: SetAllCartParmsDto) {
|
||||
return this.cartService.setAllCartParams(userId, restaurantId, dto);
|
||||
setAllCartParams(@UserId() userId: string, @ShopId() shopId: string, @Body() dto: SetAllCartParmsDto) {
|
||||
return this.cartService.setAllCartParams(userId, shopId, dto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class AddItemToCartDto {
|
||||
@ApiProperty({ description: 'Product ID' })
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
foodId!: string;
|
||||
productId!: string;
|
||||
}
|
||||
|
||||
export class BulkAddItemsToCartDto {
|
||||
@@ -21,8 +21,8 @@ export class BulkAddItemsToCartDto {
|
||||
description: 'Array of items to add to cart',
|
||||
type: [AddItemToCartDto],
|
||||
example: [
|
||||
{ foodId: 'product-123', quantity: 2 },
|
||||
{ foodId: 'product-456', quantity: 1 },
|
||||
{ productId: 'product-123', quantity: 2 },
|
||||
{ productId: 'product-456', quantity: 1 },
|
||||
],
|
||||
})
|
||||
@IsNotEmpty()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsObject, IsOptional, IsString } from 'class-validator';
|
||||
import { SetCarDeliveryDto } from './set-car-delivery.dto';
|
||||
|
||||
|
||||
|
||||
export class SetAllCartParmsDto {
|
||||
@ApiProperty({
|
||||
description: 'Cart description or notes',
|
||||
@@ -27,14 +25,4 @@ export class SetAllCartParmsDto {
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
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 {
|
||||
userId: string;
|
||||
restaurantId: string;
|
||||
restaurantName?: string;
|
||||
shopId: string;
|
||||
shopName?: string;
|
||||
|
||||
items: CartItem[];
|
||||
coupon?: OrderCouponDetail;
|
||||
|
||||
@@ -173,7 +173,7 @@ export class CartCalculationService {
|
||||
cart.couponDiscount = couponDiscount;
|
||||
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);
|
||||
|
||||
// total = subtotal – totalDiscount + tax + deliveryFee
|
||||
|
||||
@@ -58,8 +58,8 @@ export class CartItemService {
|
||||
/**
|
||||
* Add or increment item in cart
|
||||
*/
|
||||
async addOrIncrementItem(cart: Cart, shopId: string, restaurantId: string, quantityToAdd: number): Promise<void> {
|
||||
const product = await this.validationService.validateAndGetFood(shopId, restaurantId, quantityToAdd);
|
||||
async addOrIncrementItem(cart: Cart, productId: string, shopId: string, quantityToAdd: number): Promise<void> {
|
||||
const product = await this.validationService.validateAndGetFood(productId, shopId, quantityToAdd);
|
||||
|
||||
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 { ShopService } from 'src/modules/shops/providers/shops.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';
|
||||
|
||||
@Injectable()
|
||||
|
||||
@@ -5,7 +5,7 @@ import { OrderCouponDetail } from 'src/modules/orders/interface/order.interface'
|
||||
import { Cart } from '../interfaces/cart.interface';
|
||||
import { BulkAddItemsToCartDto } from '../dto/bulk-add-items.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 { CartRepository } from '../repositories/cart.repository';
|
||||
import { CartValidationService } from './cart-validation.service';
|
||||
@@ -32,15 +32,15 @@ export class CartService {
|
||||
/**
|
||||
* Set all cart parameters at once
|
||||
*/
|
||||
async setAllCartParams(userId: string, restaurantId: string, params: SetAllCartParmsDto): Promise<Cart> {
|
||||
const { deliveryMethodId, paymentMethodId, addressId, carAddress, description, tableNumber } = params;
|
||||
async setAllCartParams(userId: string, shopId: string, params: SetAllCartParmsDto): Promise<Cart> {
|
||||
const { deliveryMethodId, paymentMethodId, addressId, description } = params;
|
||||
|
||||
// get existing cart (or throw)
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
|
||||
// Validate and get delivery method
|
||||
const deliveryMethod = await this.validationService.getEnabledDeliveryMethodOrFail(
|
||||
restaurantId,
|
||||
shopId,
|
||||
deliveryMethodId,
|
||||
);
|
||||
cart.deliveryMethodId = deliveryMethodId;
|
||||
@@ -65,7 +65,7 @@ export class CartService {
|
||||
|
||||
// ensure address is within shop service area
|
||||
await this.validationService.assertAddressInsideServiceArea(
|
||||
restaurantId,
|
||||
shopId,
|
||||
address.latitude,
|
||||
address.longitude,
|
||||
);
|
||||
@@ -85,7 +85,7 @@ export class CartService {
|
||||
|
||||
// Validate and set payment method
|
||||
const paymentMethod = await this.validationService.getEnabledPaymentMethodOrFail(
|
||||
restaurantId,
|
||||
shopId,
|
||||
paymentMethodId,
|
||||
);
|
||||
|
||||
@@ -93,7 +93,7 @@ export class CartService {
|
||||
await this.calculationService.recalculateCartTotals(cart);
|
||||
|
||||
if (paymentMethod.method === PaymentMethodEnum.Wallet) {
|
||||
await this.validationService.assertWalletHasEnoughBalance(userId, restaurantId, cart.total);
|
||||
await this.validationService.assertWalletHasEnoughBalance(userId, shopId, cart.total);
|
||||
}
|
||||
|
||||
cart.paymentMethodId = paymentMethodId;
|
||||
@@ -110,21 +110,21 @@ export class CartService {
|
||||
/**
|
||||
* Get or create cart for user and shop
|
||||
*/
|
||||
async getOrCreateCart(userId: string, restaurantId: string): Promise<Cart> {
|
||||
const existingCart = await this.cartRepository.findByUserAndRestaurant(userId, restaurantId);
|
||||
async getOrCreateCart(userId: string, shopId: string): Promise<Cart> {
|
||||
const existingCart = await this.cartRepository.findByUserAndShop(userId, shopId);
|
||||
if (existingCart) {
|
||||
return existingCart;
|
||||
}
|
||||
|
||||
// Find shop
|
||||
const shop = await this.shopService.findOrFail(restaurantId);
|
||||
const shop = await this.shopService.findOrFail(shopId);
|
||||
|
||||
// Create new cart
|
||||
const now = this.nowIso();
|
||||
const cart: Cart = {
|
||||
userId,
|
||||
restaurantId,
|
||||
restaurantName: shop.name,
|
||||
shopId: shop.id,
|
||||
shopName: shop.name,
|
||||
items: [],
|
||||
deliveryFee: 0,
|
||||
subTotal: 0,
|
||||
@@ -145,8 +145,8 @@ export class CartService {
|
||||
/**
|
||||
* Find cart by user and shop
|
||||
*/
|
||||
async findOneOrFail(userId: string, restaurantId: string): Promise<Cart> {
|
||||
const cart = await this.cartRepository.findByUserAndRestaurant(userId, restaurantId);
|
||||
async findOneOrFail(userId: string, shopId: string): Promise<Cart> {
|
||||
const cart = await this.cartRepository.findByUserAndShop(userId, shopId);
|
||||
if (!cart) {
|
||||
throw new NotFoundException(CartMessage.NOT_FOUND);
|
||||
}
|
||||
@@ -156,17 +156,17 @@ export class CartService {
|
||||
/**
|
||||
* Increment item quantity in cart
|
||||
*/
|
||||
async incrementItem(userId: string, restaurantId: string, foodId: string, quantity: number): Promise<Cart> {
|
||||
const cart = await this.getOrCreateCart(userId, restaurantId);
|
||||
await this.itemService.addOrIncrementItem(cart, foodId, restaurantId, quantity);
|
||||
async incrementItem(userId: string, shopId: string, foodId: string, quantity: number): Promise<Cart> {
|
||||
const cart = await this.getOrCreateCart(userId, shopId);
|
||||
await this.itemService.addOrIncrementItem(cart, foodId, shopId, quantity);
|
||||
return this.recalculateAndSaveCart(cart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement item quantity in cart by 1 (removes item if quantity reaches 0)
|
||||
*/
|
||||
async decrementItem(userId: string, restaurantId: string, foodId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
async decrementItem(userId: string, shopId: string, foodId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
await this.itemService.decrementOrRemoveItem(cart, foodId);
|
||||
return this.recalculateAndSaveCart(cart);
|
||||
}
|
||||
@@ -174,11 +174,11 @@ export class CartService {
|
||||
/**
|
||||
* Bulk add items to cart (increments quantity if items exist)
|
||||
*/
|
||||
async bulkAddItems(userId: string, restaurantId: string, bulkAddItemsDto: BulkAddItemsToCartDto): Promise<Cart> {
|
||||
const cart = await this.getOrCreateCart(userId, restaurantId);
|
||||
async bulkAddItems(userId: string, shopId: string, bulkAddItemsDto: BulkAddItemsToCartDto): Promise<Cart> {
|
||||
const cart = await this.getOrCreateCart(userId, shopId);
|
||||
|
||||
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);
|
||||
@@ -187,8 +187,8 @@ export class CartService {
|
||||
/**
|
||||
* Remove item from cart
|
||||
*/
|
||||
async removeItem(userId: string, restaurantId: string, foodId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
async removeItem(userId: string, shopId: string, foodId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
this.itemService.removeItemOrFail(cart, foodId);
|
||||
return this.recalculateAndSaveCart(cart);
|
||||
}
|
||||
@@ -196,15 +196,15 @@ export class CartService {
|
||||
/**
|
||||
* Apply coupon to cart
|
||||
*/
|
||||
async applyCoupon(userId: string, restaurantId: string, applyCouponDto: ApplyCouponDto): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
async applyCoupon(userId: string, shopId: string, applyCouponDto: ApplyCouponDto): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
|
||||
const orderAmount = cart.subTotal - cart.itemsDiscount;
|
||||
const user = await this.userService.findOneOrFail(userId);
|
||||
// check if coupon is valid and belong to the shop
|
||||
const { valid, coupon, message } = await this.couponService.validateCoupon(
|
||||
applyCouponDto.code,
|
||||
restaurantId,
|
||||
shopId,
|
||||
Number(orderAmount),
|
||||
user.phone,
|
||||
);
|
||||
@@ -241,8 +241,8 @@ export class CartService {
|
||||
/**
|
||||
* Remove coupon from cart
|
||||
*/
|
||||
async removeCoupon(userId: string, restaurantId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
async removeCoupon(userId: string, shopId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
|
||||
cart.coupon = undefined;
|
||||
return this.recalculateAndSaveCart(cart);
|
||||
@@ -251,14 +251,14 @@ export class CartService {
|
||||
/**
|
||||
* Set address for cart
|
||||
*/
|
||||
async setAddress(userId: string, restaurantId: string, addressId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
async setAddress(userId: string, shopId: string, addressId: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
|
||||
const deliveryMethodId = this.validationService.requireDeliveryMethodId(
|
||||
cart,
|
||||
'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(
|
||||
deliveryMethod.method,
|
||||
@@ -274,7 +274,7 @@ export class CartService {
|
||||
|
||||
// ensure address is within shop service area
|
||||
await this.validationService.assertAddressInsideServiceArea(
|
||||
restaurantId,
|
||||
shopId,
|
||||
address.latitude,
|
||||
address.longitude,
|
||||
);
|
||||
@@ -298,17 +298,17 @@ export class CartService {
|
||||
*/
|
||||
async setPaymentMethod(
|
||||
userId: string,
|
||||
restaurantId: string,
|
||||
shopId: string,
|
||||
paymentMethodId: string,
|
||||
): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
|
||||
const paymentMethod = await this.validationService.getEnabledPaymentMethodOrFail(
|
||||
restaurantId,
|
||||
shopId,
|
||||
paymentMethodId,
|
||||
);
|
||||
if (paymentMethod.method === PaymentMethodEnum.Wallet) {
|
||||
await this.validationService.assertWalletHasEnoughBalance(userId, restaurantId, cart.total);
|
||||
await this.validationService.assertWalletHasEnoughBalance(userId, shopId, cart.total);
|
||||
}
|
||||
cart.paymentMethodId = paymentMethodId;
|
||||
return this.recalculateAndSaveCart(cart);
|
||||
@@ -319,13 +319,13 @@ export class CartService {
|
||||
*/
|
||||
async setDeliveryMethod(
|
||||
userId: string,
|
||||
restaurantId: string,
|
||||
shopId: string,
|
||||
deliveryMethodId: string,
|
||||
): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
|
||||
const deliveryMethod = await this.validationService.getEnabledDeliveryMethodOrFail(
|
||||
restaurantId,
|
||||
shopId,
|
||||
deliveryMethodId,
|
||||
);
|
||||
|
||||
@@ -338,8 +338,8 @@ export class CartService {
|
||||
/**
|
||||
* Set description for cart
|
||||
*/
|
||||
async setDescription(userId: string, restaurantId: string, description: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, restaurantId);
|
||||
async setDescription(userId: string, shopId: string, description: string): Promise<Cart> {
|
||||
const cart = await this.findOneOrFail(userId, shopId);
|
||||
|
||||
cart.description = description;
|
||||
return this.saveTouchedCart(cart);
|
||||
@@ -349,8 +349,8 @@ export class CartService {
|
||||
/**
|
||||
* Clear cart from cache
|
||||
*/
|
||||
async clearCart(userId: string, restaurantId: string): Promise<void> {
|
||||
return this.cartRepository.delete(userId, restaurantId);
|
||||
async clearCart(userId: string, shopId: string): Promise<void> {
|
||||
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_KEY_PREFIX = 'cart';
|
||||
|
||||
constructor(private readonly cacheService: CacheService) {}
|
||||
constructor(private readonly cacheService: CacheService) { }
|
||||
|
||||
/**
|
||||
* Get cart by user and shop
|
||||
*/
|
||||
async findByUserAndRestaurant(userId: string, restaurantId: string): Promise<Cart | null> {
|
||||
const cacheKey = this.getCacheKey(userId, restaurantId);
|
||||
async findByUserAndShop(userId: string, shopId: string): Promise<Cart | null> {
|
||||
const cacheKey = this.getCacheKey(userId, shopId);
|
||||
const cachedCart = await this.cacheService.get<string>(cacheKey);
|
||||
|
||||
if (cachedCart) {
|
||||
try {
|
||||
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;
|
||||
}
|
||||
} catch {
|
||||
@@ -34,23 +34,23 @@ export class CartRepository {
|
||||
* Save cart to cache
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cart from cache
|
||||
*/
|
||||
async delete(userId: string, restaurantId: string): Promise<void> {
|
||||
const cacheKey = this.getCacheKey(userId, restaurantId);
|
||||
async delete(userId: string, shopId: string): Promise<void> {
|
||||
const cacheKey = this.getCacheKey(userId, shopId);
|
||||
await this.cacheService.del(cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate cache key for cart
|
||||
*/
|
||||
private getCacheKey(userId: string, restaurantId: string): string {
|
||||
return `${this.CART_KEY_PREFIX}:${userId}:${restaurantId}`;
|
||||
private getCacheKey(userId: string, shopId: string): string {
|
||||
return `${this.CART_KEY_PREFIX}:${userId}:${shopId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +63,7 @@ export class CartRepository {
|
||||
const cart = obj as Record<string, unknown>;
|
||||
return (
|
||||
typeof cart.userId === 'string' &&
|
||||
typeof cart.restaurantId === 'string' &&
|
||||
typeof cart.shopId === 'string' &&
|
||||
Array.isArray(cart.items) &&
|
||||
typeof cart.subTotal === 'number' &&
|
||||
typeof cart.itemsDiscount === 'number' &&
|
||||
|
||||
Reference in New Issue
Block a user