feat: separate prior records behind an owner switch and count last-period questions

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-15 10:48:30 +03:30
co-authored by Cursor
parent 3a8a684aa4
commit 6bc5e1bec7
29 changed files with 775 additions and 77 deletions
+47 -1
View File
@@ -4,6 +4,7 @@ import {
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { Prisma } from '@prisma/client';
import type {
ApplyBillingPlanRequest,
BillingAccountDto,
@@ -251,13 +252,58 @@ export class BillingService {
modules.filter(isOrgModuleKey),
),
] as OrgModuleKey[];
const prev = await this.prisma.organization.findUnique({
where: { id: organizationId },
select: { priorArchiveEnabledAt: true },
});
const enablePrior = cleaned.includes('prior_data_archive');
const cutoff = prev?.priorArchiveEnabledAt ?? new Date();
await this.prisma.organization.update({
where: { id: organizationId },
data: { enabledModules: cleaned },
data: {
enabledModules: cleaned,
...(enablePrior && !prev?.priorArchiveEnabledAt
? { priorArchiveEnabledAt: cutoff }
: {}),
},
});
if (enablePrior) await this.backfillPriorActivities(organizationId, cutoff);
return cleaned;
}
/** فعالیت‌های منتقل‌شده را یک‌بار (و تکرار بی‌اثر) به‌عنوان اطلاعات قبل علامت می‌زند. */
private async backfillPriorActivities(organizationId: string, cutoff: Date) {
await this.prisma.$executeRaw(Prisma.sql`
UPDATE "Activity" AS a
SET "importSource" = 'didar'
WHERE a."organizationId" = ${organizationId}
AND a."importSource" = 'manual'
AND (
(
a."dealId" IS NOT NULL
AND EXISTS (
SELECT 1 FROM "Deal" AS d
WHERE d."id" = a."dealId" AND d."importSource" = 'didar'
)
)
OR (
a."dealId" IS NULL
AND a."createdAt" < ${cutoff}
AND (
EXISTS (
SELECT 1 FROM "Person" AS p
WHERE p."id" = a."personId" AND p."importSource" = 'didar'
)
OR EXISTS (
SELECT 1 FROM "Company" AS c
WHERE c."id" = a."companyId" AND c."importSource" = 'didar'
)
)
)
)
`);
}
normalizeModules(raw: string[] | null | undefined): OrgModuleKey[] {
if (!raw?.length) return defaultEnabledModules();
const cleaned = raw.filter(isOrgModuleKey) as OrgModuleKey[];