diff --git a/apps/dashboard/.env-example b/apps/dashboard/.env-example index 8b6e917cec..bd1af14435 100644 --- a/apps/dashboard/.env-example +++ b/apps/dashboard/.env-example @@ -81,4 +81,7 @@ AZURE_DOCUMENT_INTELLIGENCE_KEY= NEXT_PUBLIC_GOOGLE_API_KEY= # VatCheckAPI -VATCHECKAPI_API_KEY= \ No newline at end of file +VATCHECKAPI_API_KEY= + +# Invoice +INVOICE_JWT_SECRET=secret diff --git a/apps/dashboard/src/actions/create-customer-action.ts b/apps/dashboard/src/actions/create-customer-action.ts index abba7c2e4d..ebb5df7b0d 100644 --- a/apps/dashboard/src/actions/create-customer-action.ts +++ b/apps/dashboard/src/actions/create-customer-action.ts @@ -1,6 +1,7 @@ "use server"; import { LogEvents } from "@midday/events/events"; +import { generateToken } from "@midday/invoice/token"; import { revalidateTag } from "next/cache"; import { authActionClient } from "./safe-action"; import { createCustomerSchema } from "./schema"; @@ -15,10 +16,13 @@ export const createCustomerAction = authActionClient }, }) .action(async ({ parsedInput: input, ctx: { user, supabase } }) => { + const token = await generateToken(user.id); + const { data } = await supabase .from("customers") .insert({ ...input, + token, team_id: user.team_id, }) .select("id, name") diff --git a/apps/dashboard/src/actions/invoice/delete-invoice-action.ts b/apps/dashboard/src/actions/invoice/delete-invoice-action.ts index 5ae908b7c2..19c1a98502 100644 --- a/apps/dashboard/src/actions/invoice/delete-invoice-action.ts +++ b/apps/dashboard/src/actions/invoice/delete-invoice-action.ts @@ -21,7 +21,7 @@ export const deleteInvoiceAction = authActionClient revalidateTag(`invoices_${teamId}`); revalidateTag(`invoice_summary_${teamId}`); - revalidateTag(`invoice_number_count_${teamId}`); + revalidateTag(`invoice_number_${teamId}`); return data; }); diff --git a/apps/dashboard/src/actions/invoice/draft-invoice-action.ts b/apps/dashboard/src/actions/invoice/draft-invoice-action.ts index 99d1690fed..a490c545da 100644 --- a/apps/dashboard/src/actions/invoice/draft-invoice-action.ts +++ b/apps/dashboard/src/actions/invoice/draft-invoice-action.ts @@ -1,6 +1,7 @@ "use server"; import { authActionClient } from "@/actions/safe-action"; +import { generateToken } from "@midday/invoice/token"; import { revalidateTag } from "next/cache"; import { draftInvoiceSchema } from "./schema"; @@ -16,6 +17,10 @@ export const draftInvoiceAction = authActionClient }) => { const teamId = user.team_id; + // Generate token if customer_id is not provided because it's a new invoice + // We use upsert so we don't have to check if the invoice already exists + const token = !input.customer_id && (await generateToken(id)); + const { payment_details, from_details, ...restTemplate } = template; const { data } = await supabase @@ -28,6 +33,7 @@ export const draftInvoiceAction = authActionClient payment_details, from_details, template: restTemplate, + token, ...input, }, { @@ -40,7 +46,7 @@ export const draftInvoiceAction = authActionClient revalidateTag(`invoice_summary_${teamId}`); revalidateTag(`invoices_${teamId}`); - revalidateTag(`invoice_number_count_${teamId}`); + revalidateTag(`invoice_number_${teamId}`); return data; }, diff --git a/apps/dashboard/src/actions/invoice/schema.ts b/apps/dashboard/src/actions/invoice/schema.ts index a061d4070a..7bca7ba1bd 100644 --- a/apps/dashboard/src/actions/invoice/schema.ts +++ b/apps/dashboard/src/actions/invoice/schema.ts @@ -48,6 +48,7 @@ export const draftInvoiceSchema = z.object({ from_details: z.any().optional(), customer_details: z.any().optional(), customer_id: z.string().uuid().optional(), + customer_name: z.string().optional(), payment_details: z.any().optional(), note_details: z.any().optional(), due_date: z.coerce.date(), @@ -99,6 +100,7 @@ export const invoiceFormSchema = z.object({ from_details: z.any(), customer_details: z.any(), customer_id: z.string().uuid(), + customer_name: z.string().optional(), payment_details: z.any(), note_details: z.any().optional(), due_date: z.coerce.date(), diff --git a/apps/dashboard/src/actions/invoice/update-invoice-action.ts b/apps/dashboard/src/actions/invoice/update-invoice-action.ts index cf55e4dcab..1ce78798af 100644 --- a/apps/dashboard/src/actions/invoice/update-invoice-action.ts +++ b/apps/dashboard/src/actions/invoice/update-invoice-action.ts @@ -22,7 +22,7 @@ export const updateInvoiceAction = authActionClient revalidateTag(`invoice_summary_${teamId}`); revalidateTag(`invoices_${teamId}`); - revalidateTag(`invoice_number_count_${teamId}`); + revalidateTag(`invoice_number_${teamId}`); return data; }, diff --git a/apps/dashboard/src/app/[locale]/(app)/preview/invoice/[id]/page.tsx b/apps/dashboard/src/app/[locale]/(app)/preview/invoice/[id]/page.tsx deleted file mode 100644 index 31dda26b52..0000000000 --- a/apps/dashboard/src/app/[locale]/(app)/preview/invoice/[id]/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import Template from "@/components/invoice/template"; -import { getInvoiceQuery } from "@midday/supabase/queries"; -import { createClient } from "@midday/supabase/server"; - -export default async function Page({ params }: { params: { id: string } }) { - const supabase = createClient(); - const { data } = await getInvoiceQuery(supabase, params.id); - - return