fix pluggin bug 2

This commit is contained in:
2026-09-09 20:19:01 +03:30
parent 08f648457f
commit bd12337f6e
2 changed files with 37 additions and 15 deletions
+12 -2
View File
@@ -1,4 +1,4 @@
export const PLUGIN_STORE_DURATIONS = [30, 90, 180, 360] as const; export const PLUGIN_STORE_DURATIONS = [30, 90, 180, 360, 0] as const;
export type PluginStoreDuration = (typeof PLUGIN_STORE_DURATIONS)[number]; export type PluginStoreDuration = (typeof PLUGIN_STORE_DURATIONS)[number];
@@ -90,13 +90,23 @@ export const PLUGIN_CATALOG_SEED: Array<{
}, },
]; ];
export function daysToPlanMonths(days: number): 1 | 3 | 6 | 12 { export function daysToPlanMonths(days: number): 0 | 1 | 3 | 6 | 12 {
if (days === 0) return 0;
if (days === 90) return 3; if (days === 90) return 3;
if (days === 180) return 6; if (days === 180) return 6;
if (days === 360) return 12; if (days === 360) return 12;
return 1; return 1;
} }
export function pluginStoreDurationLabel(days: number): string {
if (Number(days) === 0) return 'یکبار پرداخت';
if (days === 30) return '۳۰ روزه';
if (days === 90) return '۹۰ روزه';
if (days === 180) return '۱۸۰ روزه';
if (days === 360) return '۳۶۰ روزه';
return `${days} روزه`;
}
export function inferSettingKeyFromName(name: string): string | null { export function inferSettingKeyFromName(name: string): string | null {
const n = String(name || '').trim(); const n = String(name || '').trim();
if (!n) return null; if (!n) return null;
+25 -13
View File
@@ -38,6 +38,7 @@ import {
inferSettingKeyFromName, inferSettingKeyFromName,
PLUGIN_CATALOG_SEED, PLUGIN_CATALOG_SEED,
PLUGIN_STORE_DURATIONS, PLUGIN_STORE_DURATIONS,
pluginStoreDurationLabel,
} from './plugin-catalog.seed'; } from './plugin-catalog.seed';
import { import {
ApprovePurchaseDto, ApprovePurchaseDto,
@@ -380,6 +381,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
} }
const months = daysToPlanMonths(req.durationDays); const months = daysToPlanMonths(req.durationDays);
const oneTime = req.durationDays === 0;
const existing = await this.prisma.pluginSubscription.findFirst({ const existing = await this.prisma.pluginSubscription.findFirst({
where: { where: {
tenantId: req.tenantId, tenantId: req.tenantId,
@@ -393,10 +395,12 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
existing?.expiresAt && existing.expiresAt.getTime() > now.getTime() existing?.expiresAt && existing.expiresAt.getTime() > now.getTime()
? existing.expiresAt ? existing.expiresAt
: now; : now;
const expiresAt = const expiresAt = oneTime
existing?.expiresAt && existing.expiresAt.getTime() > now.getTime() ? null
: existing?.expiresAt && existing.expiresAt.getTime() > now.getTime()
? addIranMonths(from, months) ? addIranMonths(from, months)
: addIranPlanExpiry(now, months); : addIranPlanExpiry(now, months);
const chargeExpiresAt = expiresAt ?? new Date('9999-12-31T00:00:00.000Z');
const plugin = existing const plugin = existing
? await this.prisma.pluginSubscription.update({ ? await this.prisma.pluginSubscription.update({
@@ -410,7 +414,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
chargedAt: now, chargedAt: now,
expiresAt, expiresAt,
isActive: true, isActive: true,
autoCutOnExpiry: dto.autoCutOnExpiry, autoCutOnExpiry: oneTime ? false : dto.autoCutOnExpiry,
lastAlertDate: null, lastAlertDate: null,
alertMarks: Prisma.DbNull, alertMarks: Prisma.DbNull,
}, },
@@ -426,7 +430,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
chargedAt: now, chargedAt: now,
expiresAt, expiresAt,
isActive: true, isActive: true,
autoCutOnExpiry: dto.autoCutOnExpiry, autoCutOnExpiry: oneTime ? false : dto.autoCutOnExpiry,
}, },
}); });
@@ -436,7 +440,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
chargedAt: now, chargedAt: now,
planMonths: months, planMonths: months,
priceRials: req.finalPriceRials, priceRials: req.finalPriceRials,
expiresAt, expiresAt: chargeExpiresAt,
note: 'خرید از فروشگاه', note: 'خرید از فروشگاه',
createdById: userId, createdById: userId,
}, },
@@ -460,10 +464,13 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
entityId: id, entityId: id,
tenantId: req.tenantId, tenantId: req.tenantId,
userId, userId,
after: { settingKey: req.catalogItem.settingKey, expiresAt: expiresAt.toISOString() } as Prisma.InputJsonValue, after: {
settingKey: req.catalogItem.settingKey,
expiresAt: expiresAt?.toISOString() ?? null,
} as Prisma.InputJsonValue,
}); });
return { ok: true, expiresAt: expiresAt.toISOString() }; return { ok: true, expiresAt: expiresAt?.toISOString() ?? null };
} }
async rejectRequest(id: string, userId?: string) { async rejectRequest(id: string, userId?: string) {
@@ -544,12 +551,14 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
.sort((a, b) => (b.expiresAt?.getTime() || 0) - (a.expiresAt?.getTime() || 0))[0]; .sort((a, b) => (b.expiresAt?.getTime() || 0) - (a.expiresAt?.getTime() || 0))[0];
const daysLeft = sub?.expiresAt ? iranDaysUntil(sub.expiresAt) : null; const daysLeft = sub?.expiresAt ? iranDaysUntil(sub.expiresAt) : null;
const hasPending = pendingIds.has(item.id); const hasPending = pendingIds.has(item.id);
const lifetime = Boolean(sub?.isActive && !sub.expiresAt);
const lockedByDays = const lockedByDays =
sub?.isActive && lifetime ||
sub.expiresAt && (sub?.isActive &&
sub.expiresAt.getTime() > now && sub.expiresAt &&
daysLeft != null && sub.expiresAt.getTime() > now &&
daysLeft > 3; daysLeft != null &&
daysLeft > 3);
return { return {
id: item.id, id: item.id,
settingKey: item.settingKey, settingKey: item.settingKey,
@@ -640,6 +649,9 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
where: { tenantId, settingKey: item.settingKey, isActive: true }, where: { tenantId, settingKey: item.settingKey, isActive: true },
orderBy: { expiresAt: 'desc' }, orderBy: { expiresAt: 'desc' },
}); });
if (sub?.isActive && !sub.expiresAt) {
throw new ConflictException('این افزونه یکبار پرداخت شده و فعال است');
}
if (sub?.expiresAt && sub.expiresAt.getTime() > Date.now()) { if (sub?.expiresAt && sub.expiresAt.getTime() > Date.now()) {
const daysLeft = iranDaysUntil(sub.expiresAt); const daysLeft = iranDaysUntil(sub.expiresAt);
if (daysLeft > 3) { if (daysLeft > 3) {
@@ -663,7 +675,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
}); });
this.notify.notifyAdmins( this.notify.notifyAdmins(
`درخواست افزونه: «${created.catalogItem.titleFa}» ${dto.durationDays}روزه برای «${created.tenant.nameFa}» (${created.tenant.domain}) — ${price.finalPriceRials.toLocaleString('fa-IR')} ریال`, `درخواست افزونه: «${created.catalogItem.titleFa}» ${pluginStoreDurationLabel(dto.durationDays)} برای «${created.tenant.nameFa}» (${created.tenant.domain}) — ${price.finalPriceRials.toLocaleString('fa-IR')} ریال`,
); );
return this.toRequestRow({ return this.toRequestRow({