cart
This commit is contained in:
@@ -4,12 +4,19 @@ import { CartService } from './providers/cart.service';
|
|||||||
import { CartController } from './controllers/cart.controller';
|
import { CartController } from './controllers/cart.controller';
|
||||||
import { Food } from '../foods/entities/food.entity';
|
import { Food } from '../foods/entities/food.entity';
|
||||||
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
||||||
|
import { PaymentMethod } from '../payments/entities/payment-method.entity';
|
||||||
|
import { UserAddress } from '../users/entities/user-address.entity';
|
||||||
import { AuthModule } from '../auth/auth.module';
|
import { AuthModule } from '../auth/auth.module';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
import { UtilsModule } from '../utils/utils.module';
|
import { UtilsModule } from '../utils/utils.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [MikroOrmModule.forFeature([Food, Restaurant]), AuthModule, JwtModule, UtilsModule],
|
imports: [
|
||||||
|
MikroOrmModule.forFeature([Food, Restaurant, PaymentMethod, UserAddress]),
|
||||||
|
AuthModule,
|
||||||
|
JwtModule,
|
||||||
|
UtilsModule,
|
||||||
|
],
|
||||||
controllers: [CartController],
|
controllers: [CartController],
|
||||||
providers: [CartService],
|
providers: [CartService],
|
||||||
exports: [CartService],
|
exports: [CartService],
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { ApplyCouponDto } from '../dto/apply-coupon.dto';
|
|||||||
import { SetAddressDto } from '../dto/set-address.dto';
|
import { SetAddressDto } from '../dto/set-address.dto';
|
||||||
import { SetPaymentMethodDto } from '../dto/set-payment-method.dto';
|
import { SetPaymentMethodDto } from '../dto/set-payment-method.dto';
|
||||||
import { UserAddress } from '../../users/entities/user-address.entity';
|
import { UserAddress } from '../../users/entities/user-address.entity';
|
||||||
import { RestaurantPaymentMethod } from '../../payments/entities/restaurant-payment-method.entity';
|
import { PaymentMethod } from '../../payments/entities/payment-method.entity';
|
||||||
import { Cart, CartItem, CartCoupon } from '../interfaces/cart.interface';
|
import { Cart, CartItem, CartCoupon } from '../interfaces/cart.interface';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -423,35 +423,29 @@ export class CartService {
|
|||||||
const cart = await this.findOne(userId, restaurantId);
|
const cart = await this.findOne(userId, restaurantId);
|
||||||
|
|
||||||
// Find and validate payment method belongs to restaurant
|
// Find and validate payment method belongs to restaurant
|
||||||
const restaurantPaymentMethod = await this.em.findOne(
|
const paymentMethod = await this.em.findOne(
|
||||||
RestaurantPaymentMethod,
|
PaymentMethod,
|
||||||
{
|
{
|
||||||
|
id: setPaymentMethodDto.paymentMethodId,
|
||||||
restaurant: { id: restaurantId },
|
restaurant: { id: restaurantId },
|
||||||
paymentMethod: { id: setPaymentMethodDto.paymentMethodId },
|
|
||||||
},
|
},
|
||||||
{ populate: ['restaurant', 'paymentMethod'] },
|
{ populate: ['restaurant'] },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!restaurantPaymentMethod) {
|
if (!paymentMethod) {
|
||||||
throw new NotFoundException(
|
throw new NotFoundException(
|
||||||
`Payment method with ID ${setPaymentMethodDto.paymentMethodId} not found for restaurant ${restaurantId}`,
|
`Payment method with ID ${setPaymentMethodDto.paymentMethodId} not found for restaurant ${restaurantId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify payment method is active
|
// Verify payment method is enabled
|
||||||
if (!restaurantPaymentMethod.isActive) {
|
if (!paymentMethod.enabled) {
|
||||||
throw new BadRequestException('Payment method is not active for this restaurant');
|
throw new BadRequestException('Payment method is not enabled for this restaurant');
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the payment method itself is active
|
|
||||||
if (!restaurantPaymentMethod.paymentMethod.isActive) {
|
|
||||||
throw new BadRequestException('Payment method is not active');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cart.paymentMethodId = setPaymentMethodDto.paymentMethodId;
|
cart.paymentMethodId = setPaymentMethodDto.paymentMethodId;
|
||||||
// cart.shipmentFee = Number(restaurantPaymentMethod.price) || 0;
|
|
||||||
|
|
||||||
// Recalculate cart totals to include delivery fee
|
// Recalculate cart totals
|
||||||
await this.recalculateCartTotals(cart);
|
await this.recalculateCartTotals(cart);
|
||||||
await this.saveCart(cart);
|
await this.saveCart(cart);
|
||||||
|
|
||||||
@@ -505,22 +499,12 @@ export class CartService {
|
|||||||
|
|
||||||
cart.tax = tax;
|
cart.tax = tax;
|
||||||
|
|
||||||
// Get shipment fee if payment method is set
|
// Shipment fee is calculated separately via delivery method
|
||||||
let shipmentFee = 0;
|
// For now, it's set to 0. It should be set when a delivery method is selected
|
||||||
// if (cart.paymentMethodId) {
|
cart.shipmentFee = 0;
|
||||||
// const restaurantPaymentMethod = await this.em.findOne(RestaurantPaymentMethod, {
|
|
||||||
// restaurant: { id: cart.restaurantId },
|
|
||||||
// paymentMethod: { id: cart.paymentMethodId },
|
|
||||||
// });
|
|
||||||
// if (restaurantPaymentMethod) {
|
|
||||||
// shipmentFee = Number(restaurantPaymentMethod.price) || 0;
|
|
||||||
// shipmentFee = 1;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
cart.shipmentFee = shipmentFee;
|
|
||||||
|
|
||||||
// Calculate total: total = subtotal – totalDiscount + tax + shipmentFee
|
// Calculate total: total = subtotal – totalDiscount + tax + shipmentFee
|
||||||
cart.total = subTotal - cart.totalDiscount + tax + shipmentFee;
|
cart.total = subTotal - cart.totalDiscount + tax + cart.shipmentFee;
|
||||||
cart.totalItems = totalItems;
|
cart.totalItems = totalItems;
|
||||||
cart.updatedAt = new Date().toISOString();
|
cart.updatedAt = new Date().toISOString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { OrderStatus } from '../interface/order-status';
|
|||||||
import { User } from '../../users/entities/user.entity';
|
import { User } from '../../users/entities/user.entity';
|
||||||
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
||||||
import { UserAddress } from '../../users/entities/user-address.entity';
|
import { UserAddress } from '../../users/entities/user-address.entity';
|
||||||
import { RestaurantPaymentMethod } from '../../payments/entities/restaurant-payment-method.entity';
|
import { PaymentMethod } from '../../payments/entities/payment-method.entity';
|
||||||
import { OrderItem } from './order-item.entity';
|
import { OrderItem } from './order-item.entity';
|
||||||
|
|
||||||
@Entity({ tableName: 'orders' })
|
@Entity({ tableName: 'orders' })
|
||||||
@@ -25,8 +25,8 @@ export class Order extends BaseEntity {
|
|||||||
@ManyToOne(() => UserAddress, { nullable: true })
|
@ManyToOne(() => UserAddress, { nullable: true })
|
||||||
address?: UserAddress;
|
address?: UserAddress;
|
||||||
|
|
||||||
@ManyToOne(() => RestaurantPaymentMethod, { nullable: true })
|
@ManyToOne(() => PaymentMethod, { nullable: true })
|
||||||
paymentMethod?: RestaurantPaymentMethod;
|
paymentMethod?: PaymentMethod;
|
||||||
|
|
||||||
@Property({ type: 'decimal', precision: 10, scale: 0, default: 0 })
|
@Property({ type: 'decimal', precision: 10, scale: 0, default: 0 })
|
||||||
couponDiscount: number = 0;
|
couponDiscount: number = 0;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { User } from '../users/entities/user.entity';
|
|||||||
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
||||||
import { Food } from '../foods/entities/food.entity';
|
import { Food } from '../foods/entities/food.entity';
|
||||||
import { UserAddress } from '../users/entities/user-address.entity';
|
import { UserAddress } from '../users/entities/user-address.entity';
|
||||||
import { RestaurantPaymentMethod } from '../payments/entities/restaurant-payment-method.entity';
|
import { PaymentMethod } from '../payments/entities/payment-method.entity';
|
||||||
import { CartModule } from '../cart/cart.module';
|
import { CartModule } from '../cart/cart.module';
|
||||||
import { UtilsModule } from '../utils/utils.module';
|
import { UtilsModule } from '../utils/utils.module';
|
||||||
import { AuthModule } from '../auth/auth.module';
|
import { AuthModule } from '../auth/auth.module';
|
||||||
@@ -17,7 +17,7 @@ import { JwtModule } from '@nestjs/jwt';
|
|||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
MikroOrmModule.forFeature([Order, OrderItem, User, Restaurant, Food, UserAddress, RestaurantPaymentMethod]),
|
MikroOrmModule.forFeature([Order, OrderItem, User, Restaurant, Food, UserAddress, PaymentMethod]),
|
||||||
CartModule,
|
CartModule,
|
||||||
UtilsModule,
|
UtilsModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
|
|||||||
@@ -6,12 +6,11 @@ import { User } from '../users/entities/user.entity';
|
|||||||
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
||||||
import { Food } from '../foods/entities/food.entity';
|
import { Food } from '../foods/entities/food.entity';
|
||||||
import { UserAddress } from '../users/entities/user-address.entity';
|
import { UserAddress } from '../users/entities/user-address.entity';
|
||||||
import { RestaurantPaymentMethod } from '../payments/entities/restaurant-payment-method.entity';
|
|
||||||
import { CartService } from '../cart/providers/cart.service';
|
import { CartService } from '../cart/providers/cart.service';
|
||||||
import { OrderStatus } from './interface/order-status';
|
import { OrderStatus } from './interface/order-status';
|
||||||
import { PaymentStatusEnum } from '../payments/interface/payment';
|
import { PaymentStatusEnum } from '../payments/interface/payment';
|
||||||
import { Cart } from '../cart/interfaces/cart.interface';
|
import { Cart } from '../cart/interfaces/cart.interface';
|
||||||
import { RestaurantPaymentMethodRepository } from '../payments/repositories/restaurant-payment-method.repository';
|
import { PaymentMethod } from '../payments/entities/payment-method.entity';
|
||||||
// import { PaymentGatewayService } from '../payments/services/payment-gateway.service.tss';
|
// import { PaymentGatewayService } from '../payments/services/payment-gateway.service.tss';
|
||||||
import { PaymentsService } from '../payments/services/payments.service';
|
import { PaymentsService } from '../payments/services/payments.service';
|
||||||
|
|
||||||
@@ -21,14 +20,13 @@ export class OrdersService {
|
|||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
private readonly cartService: CartService,
|
private readonly cartService: CartService,
|
||||||
private readonly paymentsService: PaymentsService,
|
private readonly paymentsService: PaymentsService,
|
||||||
private readonly RestaurantPaymentMethodRepository: RestaurantPaymentMethodRepository,
|
|
||||||
// private readonly paymentGatewayService: PaymentGatewayService,
|
// private readonly paymentGatewayService: PaymentGatewayService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async checkout(userId: string, restaurantId: string) {
|
async checkout(userId: string, restaurantId: string) {
|
||||||
const cart = await this.cartService.findOne(userId, restaurantId);
|
const cart = await this.cartService.findOne(userId, restaurantId);
|
||||||
|
|
||||||
const { order } = await this.create(userId, restaurantId, cart);
|
const { order } = await this.createOrder(userId, restaurantId, cart);
|
||||||
|
|
||||||
await this.cartService.clearCart(userId, restaurantId);
|
await this.cartService.clearCart(userId, restaurantId);
|
||||||
|
|
||||||
@@ -40,7 +38,7 @@ export class OrdersService {
|
|||||||
return { order, paymentUrl };
|
return { order, paymentUrl };
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(userId: string, restaurantId: string, cart: Cart) {
|
async createOrder(userId: string, restaurantId: string, cart: Cart) {
|
||||||
const validationResult = await this.validateCartForOrder(userId, restaurantId, cart);
|
const validationResult = await this.validateCartForOrder(userId, restaurantId, cart);
|
||||||
// Create order within a transaction
|
// Create order within a transaction
|
||||||
return this.em.transactional(async em => {
|
return this.em.transactional(async em => {
|
||||||
@@ -108,7 +106,7 @@ export class OrdersService {
|
|||||||
user: User;
|
user: User;
|
||||||
restaurant: Restaurant;
|
restaurant: Restaurant;
|
||||||
address: UserAddress;
|
address: UserAddress;
|
||||||
paymentMethod: RestaurantPaymentMethod;
|
paymentMethod: PaymentMethod;
|
||||||
orderItemsData: Array<{ food: Food; quantity: number; unitPrice: number; discount: number }>;
|
orderItemsData: Array<{ food: Food; quantity: number; unitPrice: number; discount: number }>;
|
||||||
}> {
|
}> {
|
||||||
// Validate cart has items
|
// Validate cart has items
|
||||||
@@ -150,12 +148,12 @@ export class OrdersService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const paymentMethod = await this.em.findOne(
|
const paymentMethod = await this.em.findOne(
|
||||||
RestaurantPaymentMethod,
|
PaymentMethod,
|
||||||
{
|
{
|
||||||
|
id: cart.paymentMethodId,
|
||||||
restaurant: { id: restaurantId },
|
restaurant: { id: restaurantId },
|
||||||
paymentMethod: { id: cart.paymentMethodId },
|
|
||||||
},
|
},
|
||||||
{ populate: ['restaurant', 'paymentMethod'] },
|
{ populate: ['restaurant'] },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!paymentMethod) {
|
if (!paymentMethod) {
|
||||||
@@ -164,8 +162,8 @@ export class OrdersService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!paymentMethod.isActive) {
|
if (!paymentMethod.enabled) {
|
||||||
throw new BadRequestException('Payment method is not active for this restaurant');
|
throw new BadRequestException('Payment method is not enabled for this restaurant');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate stock and prepare order items data
|
// Validate stock and prepare order items data
|
||||||
|
|||||||
Reference in New Issue
Block a user