66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
|
|
import type { AutomationRule } from "@prisma/client";
|
|||
|
|
import { prisma } from "@/lib/db";
|
|||
|
|
import {
|
|||
|
|
AUTOMATION_TASK_TYPES,
|
|||
|
|
DEFAULT_DAILY_CAP,
|
|||
|
|
type AutomationMode,
|
|||
|
|
type AutomationTaskType,
|
|||
|
|
} from "./types";
|
|||
|
|
|
|||
|
|
const DEFAULT_SCHEDULE: Record<AutomationTaskType, string> = {
|
|||
|
|
scan: "0 */4 * * *",
|
|||
|
|
generate: "10 */4 * * *",
|
|||
|
|
publish: "0 10,15,20 * * *",
|
|||
|
|
outreach: "30 */2 * * *",
|
|||
|
|
engagement: "*/30 * * * *",
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/** 取得帳號的所有任務規則,缺的補上預設(manual / 未啟用)。 */
|
|||
|
|
export async function getRulesForAccount(accountId: string): Promise<AutomationRule[]> {
|
|||
|
|
const existing = await prisma.automationRule.findMany({ where: { accountId } });
|
|||
|
|
const byType = new Map(existing.map((r) => [r.taskType, r]));
|
|||
|
|
|
|||
|
|
const missing = AUTOMATION_TASK_TYPES.filter((t) => !byType.has(t));
|
|||
|
|
if (missing.length > 0) {
|
|||
|
|
await prisma.automationRule.createMany({
|
|||
|
|
data: missing.map((taskType) => ({
|
|||
|
|
accountId,
|
|||
|
|
taskType,
|
|||
|
|
mode: "manual",
|
|||
|
|
dailyCap: DEFAULT_DAILY_CAP[taskType],
|
|||
|
|
schedule: DEFAULT_SCHEDULE[taskType],
|
|||
|
|
enabled: false,
|
|||
|
|
})),
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return prisma.automationRule.findMany({
|
|||
|
|
where: { accountId },
|
|||
|
|
orderBy: { taskType: "asc" },
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export async function upsertRule(
|
|||
|
|
accountId: string,
|
|||
|
|
taskType: AutomationTaskType,
|
|||
|
|
data: Partial<{ mode: AutomationMode; dailyCap: number; schedule: string; enabled: boolean }>
|
|||
|
|
): Promise<AutomationRule> {
|
|||
|
|
return prisma.automationRule.upsert({
|
|||
|
|
where: { accountId_taskType: { accountId, taskType } },
|
|||
|
|
create: {
|
|||
|
|
accountId,
|
|||
|
|
taskType,
|
|||
|
|
mode: data.mode ?? "manual",
|
|||
|
|
dailyCap: data.dailyCap ?? DEFAULT_DAILY_CAP[taskType],
|
|||
|
|
schedule: data.schedule ?? DEFAULT_SCHEDULE[taskType],
|
|||
|
|
enabled: data.enabled ?? false,
|
|||
|
|
},
|
|||
|
|
update: {
|
|||
|
|
...(data.mode !== undefined && { mode: data.mode }),
|
|||
|
|
...(data.dailyCap !== undefined && { dailyCap: data.dailyCap }),
|
|||
|
|
...(data.schedule !== undefined && { schedule: data.schedule }),
|
|||
|
|
...(data.enabled !== undefined && { enabled: data.enabled }),
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
}
|