fix bug in order
This commit is contained in:
@@ -28,6 +28,7 @@ import { getMinQuantity, isValidProductQuantity, roundQuantity } from '../../pro
|
|||||||
import { CouponService } from 'src/modules/coupons/providers/coupon.service';
|
import { CouponService } from 'src/modules/coupons/providers/coupon.service';
|
||||||
import { CouponType } from 'src/modules/coupons/interface/coupon';
|
import { CouponType } from 'src/modules/coupons/interface/coupon';
|
||||||
import { roundMoney } from 'src/common/utils/money.utils';
|
import { roundMoney } from 'src/common/utils/money.utils';
|
||||||
|
import { WalletTransactionRepository } from 'src/modules/users/repositories/wallet-transaction.repository';
|
||||||
|
|
||||||
type OrderItemData = { variant: Variant; quantity: number; unitPrice: number; discount: number };
|
type OrderItemData = { variant: Variant; quantity: number; unitPrice: number; discount: number };
|
||||||
|
|
||||||
@@ -65,6 +66,7 @@ export class OrdersService {
|
|||||||
private readonly eventEmitter: EventEmitter2,
|
private readonly eventEmitter: EventEmitter2,
|
||||||
private readonly userService: UserService,
|
private readonly userService: UserService,
|
||||||
private readonly couponService: CouponService,
|
private readonly couponService: CouponService,
|
||||||
|
private readonly walletTransactionRepository: WalletTransactionRepository,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async checkout(userId: string, shopId: string) {
|
async checkout(userId: string, shopId: string) {
|
||||||
@@ -154,6 +156,10 @@ export class OrdersService {
|
|||||||
const paymentMethod = await this.paymentMethodService.findOneOrFail(cart.paymentMethodId!);
|
const paymentMethod = await this.paymentMethodService.findOneOrFail(cart.paymentMethodId!);
|
||||||
this.assertPaymentMethodEnabled(paymentMethod);
|
this.assertPaymentMethodEnabled(paymentMethod);
|
||||||
|
|
||||||
|
if (paymentMethod.method === PaymentMethodEnum.Wallet) {
|
||||||
|
await this.assertWalletHasEnoughBalance(userId, shopId, cart.total || 0);
|
||||||
|
}
|
||||||
|
|
||||||
const orderItemsData = await this.buildOrderItemsData(cart, shopId);
|
const orderItemsData = await this.buildOrderItemsData(cart, shopId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -238,6 +244,15 @@ export class OrdersService {
|
|||||||
|
|
||||||
this.assertStatusTransitionAllowed(order, toStatus, ref);
|
this.assertStatusTransitionAllowed(order, toStatus, ref);
|
||||||
|
|
||||||
|
if (previousStatus === OrderStatus.NEED_CONFIRMATION && toStatus === OrderStatus.PENDING_PAYMENT) {
|
||||||
|
await this.em.populate(order, ['items']);
|
||||||
|
for (const item of order.items) {
|
||||||
|
if (item.status === OrderItemStatus.needConfirmation) {
|
||||||
|
item.status = OrderItemStatus.confirmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
order.status = toStatus;
|
order.status = toStatus;
|
||||||
order.history.push({ status: toStatus, changedAt: new Date(), desc: desc || null });
|
order.history.push({ status: toStatus, changedAt: new Date(), desc: desc || null });
|
||||||
await this.em.persistAndFlush(order);
|
await this.em.persistAndFlush(order);
|
||||||
@@ -507,6 +522,14 @@ export class OrdersService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async assertWalletHasEnoughBalance(userId: string, shopId: string, amount: number): Promise<void> {
|
||||||
|
const balance = await this.walletTransactionRepository.getCurrentWalletBalance(userId, shopId);
|
||||||
|
|
||||||
|
if (balance < amount) {
|
||||||
|
throw new BadRequestException(CartMessage.WALLET_INSUFFICIENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async buildOrderItemsData(cart: Cart, shopId: string): Promise<OrderItemData[]> {
|
private async buildOrderItemsData(cart: Cart, shopId: string): Promise<OrderItemData[]> {
|
||||||
const orderItemsData: OrderItemData[] = [];
|
const orderItemsData: OrderItemData[] = [];
|
||||||
const productQuantityMap = new Map<string, number>();
|
const productQuantityMap = new Map<string, number>();
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ import { PaymentListeners } from './listeners/payment.listeners';
|
|||||||
import { AdminModule } from '../admin/admin.module';
|
import { AdminModule } from '../admin/admin.module';
|
||||||
import { NotificationsModule } from '../notifications/notifications.module';
|
import { NotificationsModule } from '../notifications/notifications.module';
|
||||||
import { OrdersModule } from '../orders/orders.module';
|
import { OrdersModule } from '../orders/orders.module';
|
||||||
|
import { UserModule } from '../users/user.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [MikroOrmModule.forFeature([PaymentMethod, Payment, Shop]),
|
imports: [MikroOrmModule.forFeature([PaymentMethod, Payment, Shop]),
|
||||||
AuthModule, JwtModule, AdminModule, NotificationsModule,
|
AuthModule, JwtModule, AdminModule, NotificationsModule,
|
||||||
forwardRef(() => OrdersModule)],
|
forwardRef(() => OrdersModule), UserModule],
|
||||||
controllers: [PaymentsController],
|
controllers: [PaymentsController],
|
||||||
providers: [PaymentsService, PaymentMethodService, PaymentMethodRepository,
|
providers: [PaymentsService, PaymentMethodService, PaymentMethodRepository,
|
||||||
PaymentRepository, ZarinpalGateway, GatewayManager, PaymentListeners],
|
PaymentRepository, ZarinpalGateway, GatewayManager, PaymentListeners],
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { onlinePaymentSucceedEvent, paymentSucceedEvent } from '../events/paymen
|
|||||||
import { WalletTransactionReason, WalletTransactionType } from 'src/modules/users/interface/wallet';
|
import { WalletTransactionReason, WalletTransactionType } from 'src/modules/users/interface/wallet';
|
||||||
import { PaymentRepository } from '../repositories/payment.repository';
|
import { PaymentRepository } from '../repositories/payment.repository';
|
||||||
import { roundMoney } from 'src/common/utils/money.utils';
|
import { roundMoney } from 'src/common/utils/money.utils';
|
||||||
|
import { WalletTransactionRepository } from 'src/modules/users/repositories/wallet-transaction.repository';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PaymentsService {
|
export class PaymentsService {
|
||||||
@@ -25,6 +26,7 @@ export class PaymentsService {
|
|||||||
private readonly gatewayManager: GatewayManager,
|
private readonly gatewayManager: GatewayManager,
|
||||||
private readonly eventEmitter: EventEmitter2,
|
private readonly eventEmitter: EventEmitter2,
|
||||||
private readonly paymentRepository: PaymentRepository,
|
private readonly paymentRepository: PaymentRepository,
|
||||||
|
private readonly walletTransactionRepository: WalletTransactionRepository,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async payOrder(orderId: string): Promise<{ paymentUrl: string | null }> {
|
async payOrder(orderId: string): Promise<{ paymentUrl: string | null }> {
|
||||||
@@ -39,6 +41,10 @@ export class PaymentsService {
|
|||||||
throw new BadRequestException('سفارش به تایید نیاز دارد');
|
throw new BadRequestException('سفارش به تایید نیاز دارد');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx.method === PaymentMethodEnum.Wallet) {
|
||||||
|
await this.assertWalletHasEnoughBalance(ctx.order.user.id, ctx.order.shop.id, ctx.amount);
|
||||||
|
}
|
||||||
|
|
||||||
switch (ctx.method) {
|
switch (ctx.method) {
|
||||||
case PaymentMethodEnum.Cash:
|
case PaymentMethodEnum.Cash:
|
||||||
await this.handleCashPayment(ctx);
|
await this.handleCashPayment(ctx);
|
||||||
@@ -56,6 +62,14 @@ export class PaymentsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async assertWalletHasEnoughBalance(userId: string, shopId: string, amount: number): Promise<void> {
|
||||||
|
const balance = await this.walletTransactionRepository.getCurrentWalletBalance(userId, shopId);
|
||||||
|
|
||||||
|
if (balance < amount) {
|
||||||
|
throw new BadRequestException(PaymentMessage.INSUFFICIENT_WALLET_BALANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async loadAndValidateOrder(orderId: string): Promise<OrderPaymentContext> {
|
private async loadAndValidateOrder(orderId: string): Promise<OrderPaymentContext> {
|
||||||
const order = await this.em.findOne(
|
const order = await this.em.findOne(
|
||||||
Order,
|
Order,
|
||||||
@@ -121,11 +135,12 @@ export class PaymentsService {
|
|||||||
throw new NotFoundException(PaymentMessage.WALLET_NOT_FOUND);
|
throw new NotFoundException(PaymentMessage.WALLET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (walletTransaction.balance < ctx.amount) {
|
const currentBalance = Number(walletTransaction.balance) || 0;
|
||||||
|
if (currentBalance < ctx.amount) {
|
||||||
throw new BadRequestException(PaymentMessage.INSUFFICIENT_WALLET_BALANCE);
|
throw new BadRequestException(PaymentMessage.INSUFFICIENT_WALLET_BALANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBalance = walletTransaction.balance - ctx.amount;
|
const newBalance = currentBalance - ctx.amount;
|
||||||
|
|
||||||
|
|
||||||
const payment = await this.getOrCreateLatestPendingPayment(order.id, {
|
const payment = await this.getOrCreateLatestPendingPayment(order.id, {
|
||||||
|
|||||||
Reference in New Issue
Block a user