2025-08-04 17:45:44 +02:00
|
|
|
import { TRPCError } from "@trpc/server";
|
2025-08-07 14:50:40 +02:00
|
|
|
import { z } from "zod/v4";
|
2026-04-28 20:32:19 +02:00
|
|
|
import { orderTypeEnum } from "~/schemas/public/OrderTypeEnum";
|
|
|
|
|
import { ordiniOrdineId } from "~/schemas/public/Ordini";
|
|
|
|
|
import { rinnoviId } from "~/schemas/public/Rinnovi";
|
|
|
|
|
import { servizioServizioId } from "~/schemas/public/Servizio";
|
2025-08-04 17:45:44 +02:00
|
|
|
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
2026-03-08 01:02:57 +01:00
|
|
|
import {
|
|
|
|
|
getPagamentoDataForCheckout,
|
2026-04-03 18:57:39 +02:00
|
|
|
getRicevutaData,
|
2026-03-08 15:33:50 +01:00
|
|
|
type PreparedPaymentData,
|
2026-04-17 17:15:13 +02:00
|
|
|
type PreparePaymentError,
|
2026-03-09 10:15:59 +01:00
|
|
|
preparePayment,
|
2026-03-27 20:23:21 +01:00
|
|
|
previewSaldo,
|
2026-03-08 01:02:57 +01:00
|
|
|
} from "~/server/controllers/pagamenti.controller";
|
|
|
|
|
|
2025-08-04 17:45:44 +02:00
|
|
|
import { db } from "~/server/db";
|
2026-04-03 18:57:39 +02:00
|
|
|
import { TypstGenerate } from "~/server/services/typst.service";
|
2026-04-17 17:15:13 +02:00
|
|
|
import { zResult } from "~/utils/result";
|
2025-08-04 17:45:44 +02:00
|
|
|
// Create a new ratelimiter, that allows 10 requests per 10 seconds
|
|
|
|
|
/*
|
|
|
|
|
const ratelimit = new RateLimiterHandler({
|
|
|
|
|
maxRequests: 10,
|
|
|
|
|
windowSize: 60,
|
|
|
|
|
analytics: false,
|
|
|
|
|
});
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
export const pagamentiRouter = createTRPCRouter({
|
2025-08-28 18:27:07 +02:00
|
|
|
getPaymentFromIntent: protectedProcedure
|
|
|
|
|
.input(z.object({ pIntentId: z.string() }))
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
try {
|
2026-03-08 01:02:57 +01:00
|
|
|
const ordine = await db
|
|
|
|
|
.selectFrom("ordini")
|
|
|
|
|
.selectAll("ordini")
|
|
|
|
|
.where("ordini.intent_id", "=", input.pIntentId)
|
|
|
|
|
.executeTakeFirst();
|
|
|
|
|
return ordine || null;
|
2025-08-28 18:27:07 +02:00
|
|
|
} catch (error) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
2026-03-08 01:02:57 +01:00
|
|
|
message: `Errore durante il recupero del pagamento: ${(error as Error).message}`,
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}),
|
2026-03-08 01:02:57 +01:00
|
|
|
preparePayment: protectedProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
servizioId: servizioServizioId,
|
|
|
|
|
type: orderTypeEnum,
|
2026-03-08 01:02:57 +01:00
|
|
|
}),
|
|
|
|
|
)
|
2026-04-17 17:15:13 +02:00
|
|
|
.output(zResult<PreparedPaymentData, PreparePaymentError>())
|
2026-03-08 01:02:57 +01:00
|
|
|
.query(async ({ input }) => {
|
2026-04-28 20:32:19 +02:00
|
|
|
if (input.type === orderTypeEnum.enum.Rinnovo) {
|
2026-03-17 18:46:43 +01:00
|
|
|
return {
|
2026-04-17 17:15:13 +02:00
|
|
|
ok: false,
|
|
|
|
|
error: {
|
|
|
|
|
_tag: "InvalidInput",
|
|
|
|
|
message: "Use preparePaymentRinnovi for Rinnovo payments",
|
|
|
|
|
},
|
2026-03-17 18:46:43 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return await preparePayment({
|
|
|
|
|
type: input.type,
|
|
|
|
|
servizioId: input.servizioId,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2026-03-27 20:23:21 +01:00
|
|
|
previewSaldo: protectedProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
servizioId: servizioServizioId,
|
2026-03-27 20:23:21 +01:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await previewSaldo(input.servizioId);
|
|
|
|
|
}),
|
2026-03-17 18:46:43 +01:00
|
|
|
preparePaymentRinnovi: protectedProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
rinnovoId: rinnoviId,
|
2026-03-17 18:46:43 +01:00
|
|
|
}),
|
|
|
|
|
)
|
2026-04-17 17:15:13 +02:00
|
|
|
.output(zResult<PreparedPaymentData, PreparePaymentError>())
|
2026-03-17 18:46:43 +01:00
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await preparePayment({
|
2026-04-28 20:32:19 +02:00
|
|
|
type: orderTypeEnum.enum.Rinnovo,
|
2026-03-17 18:46:43 +01:00
|
|
|
rinnovoId: input.rinnovoId,
|
|
|
|
|
});
|
2026-03-08 01:02:57 +01:00
|
|
|
}),
|
2026-02-20 11:36:47 +01:00
|
|
|
|
|
|
|
|
getPagamentoDataForCheckout: protectedProcedure
|
2026-04-28 20:32:19 +02:00
|
|
|
.input(z.object({ ordineId: ordiniOrdineId }))
|
2026-02-20 11:36:47 +01:00
|
|
|
.query(async ({ input }) => {
|
2026-03-08 01:02:57 +01:00
|
|
|
return await getPagamentoDataForCheckout(input.ordineId);
|
|
|
|
|
}),
|
|
|
|
|
getRicevutaCortesiaPdf: protectedProcedure
|
2026-04-28 20:32:19 +02:00
|
|
|
.input(z.object({ ordineId: ordiniOrdineId }))
|
2026-03-08 01:02:57 +01:00
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
try {
|
2026-04-03 18:57:39 +02:00
|
|
|
const ricData = await getRicevutaData(input.ordineId);
|
|
|
|
|
const pdf = await TypstGenerate({
|
|
|
|
|
templateId: "receipt.typ",
|
|
|
|
|
data: ricData.data,
|
|
|
|
|
});
|
|
|
|
|
return { title: ricData.title, pdf: pdf.toString("base64") };
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore nella generazione della ricevuta di cortesia: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
getRicevutaCortesiaPdfQuery: protectedProcedure
|
2026-04-28 20:32:19 +02:00
|
|
|
.input(z.object({ ordineId: ordiniOrdineId }))
|
2026-04-03 18:57:39 +02:00
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
try {
|
|
|
|
|
const ricData = await getRicevutaData(input.ordineId);
|
|
|
|
|
const pdf = await TypstGenerate({
|
|
|
|
|
templateId: "receipt.typ",
|
|
|
|
|
data: ricData.data,
|
|
|
|
|
});
|
|
|
|
|
return { title: ricData.title, pdf: pdf.toString("base64") };
|
2026-03-08 01:02:57 +01:00
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore nella generazione della ricevuta di cortesia: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-02-20 11:36:47 +01:00
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
});
|