Fix plugin purchase 500 when subscription catalog columns are missing.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-10 10:33:48 +03:30
co-authored by Cursor
parent 6cc10e3333
commit cf92635c0e
2 changed files with 66 additions and 31 deletions
@@ -0,0 +1,13 @@
-- Catalog linkage on plugin_subscriptions was in schema.prisma without a
-- CREATE COLUMN migration. Remote store GET swallows the missing column;
-- POST create did not, so purchase requests returned HTTP 500.
ALTER TABLE "plugin_subscriptions"
ADD COLUMN IF NOT EXISTS "setting_key" VARCHAR(50);
ALTER TABLE "plugin_subscriptions"
ADD COLUMN IF NOT EXISTS "auto_cut_on_expiry" BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE "plugin_subscriptions"
ADD COLUMN IF NOT EXISTS "alert_marks" JSONB;
CREATE INDEX IF NOT EXISTS "plugin_subscriptions_setting_key_idx"
ON "plugin_subscriptions"("setting_key");
+23 -1
View File
@@ -3,6 +3,7 @@ import {
ConflictException,
ForbiddenException,
Injectable,
InternalServerErrorException,
Logger,
NotFoundException,
OnModuleDestroy,
@@ -722,10 +723,16 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
throw new ConflictException('درخواست در انتظار برای این افزونه وجود دارد');
}
const sub = await this.prisma.pluginSubscription.findFirst({
let sub: { isActive: boolean; expiresAt: Date | null } | null = null;
try {
sub = await this.prisma.pluginSubscription.findFirst({
where: { tenantId, settingKey: item.settingKey, isActive: true },
orderBy: { expiresAt: 'desc' },
select: { isActive: true, expiresAt: true },
});
} catch (error: any) {
this.logger.warn(`remoteCreateRequest sub skipped: ${error?.message || error}`);
}
if (sub?.isActive && !sub.expiresAt) {
throw new ConflictException('این افزونه یکبار پرداخت شده و فعال است');
}
@@ -736,6 +743,7 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
}
}
try {
const created = await this.prisma.pluginPurchaseRequest.create({
data: {
tenantId,
@@ -765,6 +773,20 @@ export class PluginStoreService implements OnModuleInit, OnModuleDestroy {
product: ProductType.khanegi,
},
} as any);
} catch (error: any) {
if (
error instanceof BadRequestException ||
error instanceof ConflictException ||
error instanceof ForbiddenException ||
error instanceof NotFoundException
) {
throw error;
}
this.logger.error(`remoteCreateRequest failed: ${error?.message || error}`);
throw new InternalServerErrorException(
error?.message || 'ثبت درخواست افزونه ناموفق بود',
);
}
}
async remoteCancelRequest(tenantId: string, product: string, requestId: string) {