This commit is contained in:
2025-12-18 10:38:52 +03:30
parent 44bce1e6d7
commit 99a81c43a1
4 changed files with 135 additions and 3 deletions
@@ -22,6 +22,7 @@ import { OrderCouponDetail } from 'src/modules/orders/interface/order.interface'
import { CouponType } from 'src/modules/coupons/interface/coupon';
import { UserWallet } from 'src/modules/users/entities/user-wallet.entity';
import { PaymentMethodEnum } from 'src/modules/payments/interface/payment';
import { SetAllCartParmsDto } from '../dto/set-all-cart-params.dto';
@Injectable()
export class CartService {
@@ -34,6 +35,92 @@ export class CartService {
private readonly couponService: CouponService,
) { }
async setAllCartParams(userId: string, restaurantId: string, params: SetAllCartParmsDto): Promise<Cart> {
const { deliveryMethodId, paymentMethodId, addressId, carAddress, description } = params;
// get existing cart (or throw)
const cart = await this.findOneOrFail(userId, restaurantId);
// If deliveryMethodId is provided -> validate and set it first
if (deliveryMethodId) {
const deliveryMethod = await this.getEnabledDeliveryMethodOrFail(restaurantId, deliveryMethodId);
cart.deliveryMethodId = deliveryMethodId;
// clear fields incompatible with the chosen delivery method
this.clearFieldsIncompatibleWithDeliveryMethod(cart, deliveryMethod.method);
}
// If addressId is provided -> must have delivery method (either provided above or already on cart)
if (addressId) {
const effectiveDeliveryMethodId = deliveryMethodId ?? cart.deliveryMethodId;
if (!effectiveDeliveryMethodId) {
throw new BadRequestException('Delivery method must be set before setting address');
}
const deliveryMethod = await this.getDeliveryMethodForRestaurantOrFail(restaurantId, effectiveDeliveryMethodId);
this.assertDeliveryMethod(deliveryMethod.method, DeliveryMethodEnum.DeliveryCourier, 'Delivery method must be DeliveryCourier');
const address = await this.getUserAddressOrFail(addressId);
if (address.user.id !== userId) {
throw new BadRequestException('Address does not belong to the current user');
}
// ensure cart fields are compatible and set address
this.clearFieldsIncompatibleWithDeliveryMethod(cart, DeliveryMethodEnum.DeliveryCourier);
cart.userAddress = {
address: address.address,
latitude: address.latitude,
longitude: address.longitude,
city: address.city,
province: address.province || '',
postalCode: address.postalCode || undefined,
fullName: `${address.user.firstName || ''} ${address.user.lastName || ''}`.trim(),
phone: address.user.phone,
};
}
// If carAddress is provided -> must have delivery method DeliveryCar
if (carAddress) {
const effectiveDeliveryMethodId = deliveryMethodId ?? cart.deliveryMethodId;
if (!effectiveDeliveryMethodId) {
throw new BadRequestException('Delivery method must be set before setting car delivery');
}
const deliveryMethod = await this.getDeliveryMethodForRestaurantOrFail(restaurantId, effectiveDeliveryMethodId);
this.assertDeliveryMethod(deliveryMethod.method, DeliveryMethodEnum.DeliveryCar, 'Delivery method must be DeliveryCar');
const user = await this.getUserOrFail(userId);
// make sure incompatible fields are cleared and set car address (phone comes from user)
this.clearFieldsIncompatibleWithDeliveryMethod(cart, DeliveryMethodEnum.DeliveryCar);
cart.carAddress = {
carModel: carAddress.carModel,
carColor: carAddress.carColor,
plateNumber: carAddress.plateNumber,
phone: user.phone,
};
}
// If payment method is provided -> validate and (for wallet) ensure enough balance.
if (paymentMethodId) {
const paymentMethod = await this.getEnabledPaymentMethodOrFail(restaurantId, paymentMethodId);
// Recalculate totals first so wallet check uses up-to-date total (delivery method may have changed above).
await this.recalculateCartTotals(cart);
if (paymentMethod.method === PaymentMethodEnum.Wallet) {
await this.assertWalletHasEnoughBalance(userId, restaurantId, cart.total);
}
cart.paymentMethodId = paymentMethodId;
}
// Description (if provided)
if (description !== undefined) {
cart.description = description;
}
// Final recalculation + save and return cart
return this.recalculateAndSaveCart(cart);
}
/**
* Get or create cart for user and restaurant
*/