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];
@@ -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 === 180) return 6;
if (days === 360) return 12;
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 {
const n = String(name || '').trim();
if (!n) return null;
+22 -10
View File
@@ -38,6 +38,7 @@ import {
inferSettingKeyFromName,
PLUGIN_CATALOG_SEED,
PLUGIN_STORE_DURATIONS,
pluginStoreDurationLabel,
} from './plugin-catalog.seed';
import {
ApprovePurchaseDto,
@@ -380,6 +381,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
}
const months = daysToPlanMonths(req.durationDays);
const oneTime = req.durationDays === 0;
const existing = await this.prisma.pluginSubscription.findFirst({
where: {
tenantId: req.tenantId,
@@ -393,10 +395,12 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
existing?.expiresAt && existing.expiresAt.getTime() > now.getTime()
? existing.expiresAt
: now;
const expiresAt =
existing?.expiresAt && existing.expiresAt.getTime() > now.getTime()
const expiresAt = oneTime
? null
: existing?.expiresAt && existing.expiresAt.getTime() > now.getTime()
? addIranMonths(from, months)
: addIranPlanExpiry(now, months);
const chargeExpiresAt = expiresAt ?? new Date('9999-12-31T00:00:00.000Z');
const plugin = existing
? await this.prisma.pluginSubscription.update({
@@ -410,7 +414,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
chargedAt: now,
expiresAt,
isActive: true,
autoCutOnExpiry: dto.autoCutOnExpiry,
autoCutOnExpiry: oneTime ? false : dto.autoCutOnExpiry,
lastAlertDate: null,
alertMarks: Prisma.DbNull,
},
@@ -426,7 +430,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
chargedAt: now,
expiresAt,
isActive: true,
autoCutOnExpiry: dto.autoCutOnExpiry,
autoCutOnExpiry: oneTime ? false : dto.autoCutOnExpiry,
},
});
@@ -436,7 +440,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
chargedAt: now,
planMonths: months,
priceRials: req.finalPriceRials,
expiresAt,
expiresAt: chargeExpiresAt,
note: 'خرید از فروشگاه',
createdById: userId,
},
@@ -460,10 +464,13 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
entityId: id,
tenantId: req.tenantId,
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) {
@@ -544,12 +551,14 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
.sort((a, b) => (b.expiresAt?.getTime() || 0) - (a.expiresAt?.getTime() || 0))[0];
const daysLeft = sub?.expiresAt ? iranDaysUntil(sub.expiresAt) : null;
const hasPending = pendingIds.has(item.id);
const lifetime = Boolean(sub?.isActive && !sub.expiresAt);
const lockedByDays =
sub?.isActive &&
lifetime ||
(sub?.isActive &&
sub.expiresAt &&
sub.expiresAt.getTime() > now &&
daysLeft != null &&
daysLeft > 3;
daysLeft > 3);
return {
id: item.id,
settingKey: item.settingKey,
@@ -640,6 +649,9 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
where: { tenantId, settingKey: item.settingKey, isActive: true },
orderBy: { expiresAt: 'desc' },
});
if (sub?.isActive && !sub.expiresAt) {
throw new ConflictException('این افزونه یکبار پرداخت شده و فعال است');
}
if (sub?.expiresAt && sub.expiresAt.getTime() > Date.now()) {
const daysLeft = iranDaysUntil(sub.expiresAt);
if (daysLeft > 3) {
@@ -663,7 +675,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
});
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({