mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 02:51:46 +00:00
145 lines
3.6 KiB
TypeScript
145 lines
3.6 KiB
TypeScript
"use server";
|
|
|
|
import { and, eq } from "drizzle-orm";
|
|
import { recurringSeries } from "@/db/schema";
|
|
import { generateRecurringTransactions } from "@/features/recurring/generate-recurring";
|
|
import {
|
|
handleActionError,
|
|
revalidateForEntity,
|
|
} from "@/shared/lib/actions/helpers";
|
|
import { getUser } from "@/shared/lib/auth/server";
|
|
import { db } from "@/shared/lib/db";
|
|
import { recurringSeriesActionSchema } from "@/shared/lib/schemas/recurring-series";
|
|
import type { ActionResult } from "@/shared/lib/types/actions";
|
|
|
|
const revalidate = () => revalidateForEntity("recurring");
|
|
|
|
async function findRecurringSeriesForUser(userId: string, seriesId: string) {
|
|
const [series] = await db
|
|
.select({
|
|
id: recurringSeries.id,
|
|
status: recurringSeries.status,
|
|
})
|
|
.from(recurringSeries)
|
|
.where(
|
|
and(eq(recurringSeries.id, seriesId), eq(recurringSeries.userId, userId)),
|
|
)
|
|
.limit(1);
|
|
|
|
return series ?? null;
|
|
}
|
|
|
|
export async function pauseRecurringSeriesAction(input: {
|
|
seriesId: string;
|
|
}): Promise<ActionResult> {
|
|
try {
|
|
const user = await getUser();
|
|
const data = recurringSeriesActionSchema.parse(input);
|
|
|
|
const existing = await findRecurringSeriesForUser(user.id, data.seriesId);
|
|
|
|
if (!existing) {
|
|
return { success: false, error: "Série recorrente não encontrada." };
|
|
}
|
|
|
|
if (existing.status !== "active") {
|
|
return {
|
|
success: false,
|
|
error: "Apenas séries ativas podem ser pausadas.",
|
|
};
|
|
}
|
|
|
|
await db
|
|
.update(recurringSeries)
|
|
.set({ status: "paused", updatedAt: new Date() })
|
|
.where(
|
|
and(
|
|
eq(recurringSeries.id, data.seriesId),
|
|
eq(recurringSeries.userId, user.id),
|
|
),
|
|
);
|
|
|
|
revalidate();
|
|
return { success: true, message: "Série recorrente pausada." };
|
|
} catch (error) {
|
|
return handleActionError(error);
|
|
}
|
|
}
|
|
|
|
export async function resumeRecurringSeriesAction(input: {
|
|
seriesId: string;
|
|
}): Promise<ActionResult> {
|
|
try {
|
|
const user = await getUser();
|
|
const data = recurringSeriesActionSchema.parse(input);
|
|
|
|
const existing = await findRecurringSeriesForUser(user.id, data.seriesId);
|
|
|
|
if (!existing) {
|
|
return { success: false, error: "Série recorrente não encontrada." };
|
|
}
|
|
|
|
if (existing.status !== "paused") {
|
|
return {
|
|
success: false,
|
|
error: "Apenas séries pausadas podem ser retomadas.",
|
|
};
|
|
}
|
|
|
|
await db
|
|
.update(recurringSeries)
|
|
.set({ status: "active", updatedAt: new Date() })
|
|
.where(
|
|
and(
|
|
eq(recurringSeries.id, data.seriesId),
|
|
eq(recurringSeries.userId, user.id),
|
|
),
|
|
);
|
|
|
|
// Trigger catch-up generation for missed months
|
|
await generateRecurringTransactions(user.id);
|
|
|
|
revalidate();
|
|
return { success: true, message: "Série recorrente retomada." };
|
|
} catch (error) {
|
|
return handleActionError(error);
|
|
}
|
|
}
|
|
|
|
export async function cancelRecurringSeriesAction(input: {
|
|
seriesId: string;
|
|
}): Promise<ActionResult> {
|
|
try {
|
|
const user = await getUser();
|
|
const data = recurringSeriesActionSchema.parse(input);
|
|
|
|
const existing = await findRecurringSeriesForUser(user.id, data.seriesId);
|
|
|
|
if (!existing) {
|
|
return { success: false, error: "Série recorrente não encontrada." };
|
|
}
|
|
|
|
if (existing.status === "cancelled") {
|
|
return {
|
|
success: false,
|
|
error: "Esta série já está cancelada.",
|
|
};
|
|
}
|
|
|
|
await db
|
|
.update(recurringSeries)
|
|
.set({ status: "cancelled", updatedAt: new Date() })
|
|
.where(
|
|
and(
|
|
eq(recurringSeries.id, data.seriesId),
|
|
eq(recurringSeries.userId, user.id),
|
|
),
|
|
);
|
|
|
|
revalidate();
|
|
return { success: true, message: "Série recorrente cancelada." };
|
|
} catch (error) {
|
|
return handleActionError(error);
|
|
}
|
|
}
|