Add Mellat e-payment, videos/instructions CMS, and legacy domain lookup.

Store gateway credentials per business, initiate/verify Mellat at checkout, and resolve old CMS ids from domains in the migrate modal.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-13 09:51:17 +03:30
co-authored by Cursor
parent 513673a7da
commit d5e502cf77
44 changed files with 9303 additions and 996 deletions
+57 -1
View File
@@ -15,6 +15,11 @@ import {
UpdateCartItemDto,
} from './dto/cart.dto';
import { OrdersService } from '../orders/orders.service';
import { PaymentsService } from '../payments/payments.service';
import { TransactionType } from '@prisma/client';
import { BusinessSettingsService } from '../business-settings/business-settings.service';
import type { PaymentGatewayId } from '../business-settings/business-settings.types';
import { listPublicPaymentGateways } from '../business-settings/business-settings.util';
const cartVariantInclude = {
storeItem: {
@@ -52,6 +57,8 @@ export class CartService {
private readonly prisma: PrismaService,
private readonly permissions: PermissionsService,
private readonly orders: OrdersService,
private readonly payments: PaymentsService,
private readonly businessSettings: BusinessSettingsService,
) {}
async getCart(businessIdRaw: string, actor: AuthUser) {
@@ -193,6 +200,30 @@ export class CartService {
dto.shippingAddress,
);
const isEPayment = dto.payment.type === TransactionType.e_payment_gate;
let gatewayType: PaymentGatewayId | undefined;
if (isEPayment) {
if (!dto.returnUrl?.trim()) {
throw new BadRequestException(
'returnUrl is required for e-payment checkout',
);
}
const settings =
await this.businessSettings.getNormalizedSettings(businessId);
const publicMethods = listPublicPaymentGateways(settings.store.ePayment);
if (!publicMethods.enabled) {
throw new BadRequestException(
'Online payment is not enabled for this store',
);
}
gatewayType = this.payments.resolveGatewayType(
dto.payment.gatewayType,
publicMethods,
);
}
const order = await this.orders.createFromCart({
businessId,
userId: actor.id,
@@ -207,13 +238,38 @@ export class CartService {
payment: {
type: dto.payment.type,
posType: dto.payment.posType,
gatewayType: dto.payment.gatewayType,
gatewayType: isEPayment ? gatewayType : dto.payment.gatewayType,
transferAccount: dto.payment.transferAccount,
transferRefNumber: dto.payment.transferRefNumber,
notes: dto.payment.notes?.trim() || null,
},
});
if (isEPayment && gatewayType) {
const payment = await this.payments.initiateForCheckout({
businessId,
order: {
id: order.id,
total: order.total,
transactions: order.transactions,
},
gatewayType,
returnUrl: dto.returnUrl!.trim(),
});
await this.prisma.cartItem.deleteMany({ where: { cartId: cart.id } });
return {
message: 'Redirect customer to payment gateway',
order,
payment: {
gatewayType: payment.gatewayType,
transactionId: payment.transactionId,
redirect: payment.redirect,
},
};
}
await this.prisma.cartItem.deleteMany({ where: { cartId: cart.id } });
return {