fix bug in order

This commit is contained in:
2026-06-29 09:13:10 +03:30
parent 1b7ccaf643
commit 8d679dc5e0
3 changed files with 42 additions and 3 deletions
@@ -28,6 +28,7 @@ import { getMinQuantity, isValidProductQuantity, roundQuantity } from '../../pro
import { CouponService } from 'src/modules/coupons/providers/coupon.service';
import { CouponType } from 'src/modules/coupons/interface/coupon';
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 };
@@ -65,6 +66,7 @@ export class OrdersService {
private readonly eventEmitter: EventEmitter2,
private readonly userService: UserService,
private readonly couponService: CouponService,
private readonly walletTransactionRepository: WalletTransactionRepository,
) { }
async checkout(userId: string, shopId: string) {
@@ -154,6 +156,10 @@ export class OrdersService {
const paymentMethod = await this.paymentMethodService.findOneOrFail(cart.paymentMethodId!);
this.assertPaymentMethodEnabled(paymentMethod);
if (paymentMethod.method === PaymentMethodEnum.Wallet) {
await this.assertWalletHasEnoughBalance(userId, shopId, cart.total || 0);
}
const orderItemsData = await this.buildOrderItemsData(cart, shopId);
return {
@@ -238,6 +244,15 @@ export class OrdersService {
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.history.push({ status: toStatus, changedAt: new Date(), desc: desc || null });
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[]> {
const orderItemsData: OrderItemData[] = [];
const productQuantityMap = new Map<string, number>();
+2 -1
View File
@@ -16,11 +16,12 @@ import { PaymentListeners } from './listeners/payment.listeners';
import { AdminModule } from '../admin/admin.module';
import { NotificationsModule } from '../notifications/notifications.module';
import { OrdersModule } from '../orders/orders.module';
import { UserModule } from '../users/user.module';
@Module({
imports: [MikroOrmModule.forFeature([PaymentMethod, Payment, Shop]),
AuthModule, JwtModule, AdminModule, NotificationsModule,
forwardRef(() => OrdersModule)],
forwardRef(() => OrdersModule), UserModule],
controllers: [PaymentsController],
providers: [PaymentsService, PaymentMethodService, PaymentMethodRepository,
PaymentRepository, ZarinpalGateway, GatewayManager, PaymentListeners],
@@ -15,6 +15,7 @@ import { onlinePaymentSucceedEvent, paymentSucceedEvent } from '../events/paymen
import { WalletTransactionReason, WalletTransactionType } from 'src/modules/users/interface/wallet';
import { PaymentRepository } from '../repositories/payment.repository';
import { roundMoney } from 'src/common/utils/money.utils';
import { WalletTransactionRepository } from 'src/modules/users/repositories/wallet-transaction.repository';
@Injectable()
export class PaymentsService {
@@ -25,6 +26,7 @@ export class PaymentsService {
private readonly gatewayManager: GatewayManager,
private readonly eventEmitter: EventEmitter2,
private readonly paymentRepository: PaymentRepository,
private readonly walletTransactionRepository: WalletTransactionRepository,
) { }
async payOrder(orderId: string): Promise<{ paymentUrl: string | null }> {
@@ -39,6 +41,10 @@ export class PaymentsService {
throw new BadRequestException('سفارش به تایید نیاز دارد');
}
if (ctx.method === PaymentMethodEnum.Wallet) {
await this.assertWalletHasEnoughBalance(ctx.order.user.id, ctx.order.shop.id, ctx.amount);
}
switch (ctx.method) {
case PaymentMethodEnum.Cash:
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> {
const order = await this.em.findOne(
Order,
@@ -121,11 +135,12 @@ export class PaymentsService {
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);
}
const newBalance = walletTransaction.balance - ctx.amount;
const newBalance = currentBalance - ctx.amount;
const payment = await this.getOrCreateLatestPendingPayment(order.id, {