infoalloggi-monorepo/apps/infoalloggi/src/server/api/routers/pagamenti.ts
Marco Pedone 1307f352a4 feat: enhance payment preparation logic and add rinnovo handling
- Refactor `preparePayment` function to handle multiple order types including Rinnovo.
- Introduce new `RinnovoSolver` function to calculate renewal packs based on duration.
- Add `createRinnovo` service to manage the creation of renewal orders.
- Update `whIntentSucceededHandler` to handle payment confirmations for Rinnovo and other order types.
- Introduce default conditions for packs in `prezziario.service.ts`.
- Add new utility functions for managing renewal durations and permanenza.
- Update database interactions to ensure proper handling of orders and renewals.
- Enhance error handling and logging throughout the payment and renewal processes.
2026-03-17 18:46:43 +01:00

114 lines
2.9 KiB
TypeScript

import { TRPCError } from "@trpc/server";
import { z } from "zod/v4";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
import {
getPagamentoDataForCheckout,
type PreparedPaymentData,
preparePayment,
} from "~/server/controllers/pagamenti.controller";
import { db } from "~/server/db";
import { genPdfRicevutaCortesia } from "~/server/services/puppeteer.service";
import { zOrdineId, zRinnovoId, zServizioId } from "~/server/utils/zod_types";
// 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({
getPaymentFromIntent: protectedProcedure
.input(z.object({ pIntentId: z.string() }))
.query(async ({ input }) => {
try {
const ordine = await db
.selectFrom("ordini")
.selectAll("ordini")
.where("ordini.intent_id", "=", input.pIntentId)
.executeTakeFirst();
return ordine || null;
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Errore durante il recupero del pagamento: ${(error as Error).message}`,
});
}
}),
preparePayment: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
type: z.enum(OrderTypeEnum),
}),
)
.output(
z.discriminatedUnion("success", [
z.object({
success: z.literal(true),
data: z.custom<PreparedPaymentData>(),
}),
z.object({
success: z.literal(false),
message: z.string(),
}),
]),
)
.query(async ({ input }) => {
if (input.type === OrderTypeEnum.Rinnovo) {
return {
success: false,
message: "Use preparePaymentRinnovi for Rinnovo payments",
};
}
return await preparePayment({
type: input.type,
servizioId: input.servizioId,
});
}),
preparePaymentRinnovi: protectedProcedure
.input(
z.object({
rinnovoId: zRinnovoId,
}),
)
.output(
z.discriminatedUnion("success", [
z.object({
success: z.literal(true),
data: z.custom<PreparedPaymentData>(),
}),
z.object({
success: z.literal(false),
message: z.string(),
}),
]),
)
.query(async ({ input }) => {
return await preparePayment({
type: OrderTypeEnum.Rinnovo,
rinnovoId: input.rinnovoId,
});
}),
getPagamentoDataForCheckout: protectedProcedure
.input(z.object({ ordineId: zOrdineId }))
.query(async ({ input }) => {
return await getPagamentoDataForCheckout(input.ordineId);
}),
getRicevutaCortesiaPdf: protectedProcedure
.input(z.object({ ordineId: zOrdineId }))
.mutation(async ({ input }) => {
try {
return await genPdfRicevutaCortesia(input.ordineId);
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Errore nella generazione della ricevuta di cortesia: ${(e as Error).message}`,
});
}
}),
});