infoalloggi-monorepo/apps/infoalloggi/src/server/api/routers/servizio.ts
Marco Pedone f52dd96c11 feat: implement Stripe reports management for admin panel
- Add new page for managing Stripe reports with functionality to generate and view reports.
- Create API router for handling Stripe report operations including listing, setting up, and generating reports.
- Introduce caching service for managing cache invalidation related to reports.
- Update Typst templates for formatting financial reports in EUR.
- Enhance utility functions for price formatting and error handling.
- Implement a script to check for unused tRPC procedures in the codebase.
2026-04-03 18:57:39 +02:00

484 lines
10 KiB
TypeScript

import z from "zod";
import type { NewOrdini, OrdiniUpdate } from "~/schemas/public/Ordini";
import type {
NewRinnovi,
Rinnovi,
RinnoviUpdate,
} from "~/schemas/public/Rinnovi";
import type { NewServizio, ServizioUpdate } from "~/schemas/public/Servizio";
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
import type { Users } from "~/schemas/public/Users";
import type { UsersAnagraficaUpdate } from "~/schemas/public/UsersAnagrafica";
import {
adminProcedure,
createTRPCRouter,
protectedProcedure,
} from "~/server/api/trpc";
import { getPacksPerServizio } from "~/server/controllers/pagamenti.controller";
import {
AdminAttivaServizio_Ufficio,
addServizioAnnunci,
adminUpdateConfermaStatus,
attivaServizio_SaltaPagamentoAcconto,
getAllServizioAnnunci,
getAnnunciAvailableToAdd,
getCompatibileAnnunci,
getDataPerAcquisto,
getRichieste,
getServiziByUserId,
getServizioDataById,
InteractionLogicTipologia,
interruzioneServizio,
processServizioOnboard,
SbloccaContatti,
type ServizioData,
userAccettaConferma,
userSendConfermaIntent,
} from "~/server/controllers/servizio.controller";
import {
createOrdine,
getOrdineById,
getOrdini,
removeOrder,
updateOrder,
} from "~/server/services/ordini.service";
import {
createRinnovo,
deleteRinnovo,
getRinnoviUser,
getRinnovoData,
updateRinnovo,
} from "~/server/services/rinnovi.service";
import {
addServizio,
deleteServizio,
deleteServizioAnnuncio,
getServizioAnnuncio,
getServizioById,
updateServizio,
updateServizioAnnuncio,
} from "~/server/services/servizio.service";
import {
zAnnuncioId,
zOrdineId,
zRinnovoId,
zServizioId,
zUserId,
} from "~/server/utils/zod_types";
export const servizioRouter = createTRPCRouter({
AnnuncioServizioTipologiaMatch: protectedProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
tipologia: z.string(),
userId: zUserId,
}),
)
.query(async ({ input }) => {
return await InteractionLogicTipologia({
annuncioId: input.annuncioId,
tipologia: input.tipologia,
userId: input.userId,
});
}),
addServizio: adminProcedure
.input(
z.object({
data: z.custom<NewServizio>(),
}),
)
.mutation(async ({ input }) => {
return await addServizio(input.data);
}),
addServizioAnnunci: adminProcedure
.input(
z.object({
annunci: z.array(zAnnuncioId),
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await addServizioAnnunci({
annunci: input.annunci,
servizioId: input.servizioId,
});
}),
deleteServizio: adminProcedure
.input(
z.object({
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await deleteServizio(input.servizioId);
}),
getAcquistoData: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
}),
)
.query(async ({ input }) => {
return await getDataPerAcquisto(input.servizioId);
}),
getRichieste: adminProcedure.query(async () => {
return await getRichieste();
}),
getServizioData: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
}),
)
.query(async ({ input }) => {
return await getServizioDataById(input.servizioId);
}),
getAnnunciAvailableToAdd: adminProcedure
.input(
z.object({
servizioId: zServizioId,
}),
)
.query(async ({ input }) => {
return await getAnnunciAvailableToAdd(input.servizioId);
}),
getCompatibileAnnunci: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
adminOverride: z.boolean().optional(),
}),
)
.query(async ({ input }) => {
return await getCompatibileAnnunci({ ...input });
}),
getOrdineById: protectedProcedure
.input(
z.object({
ordineId: zOrdineId,
}),
)
.query(async ({ input }) => {
return await getOrdineById(input.ordineId);
}),
getOrdini: protectedProcedure
.input(
z.object({
userId: zUserId.optional(),
}),
)
.query(async ({ input }) => {
return await getOrdini(input.userId);
}),
isOnboardAvailable: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
}),
)
.output(
z.discriminatedUnion("available", [
z.object({
available: z.literal(true),
userId: zUserId,
}),
z.object({
available: z.literal(false),
userId: z.null(),
}),
]),
)
.query(async ({ input }) => {
const servizio = await getServizioById(input.servizioId);
if (
!servizio ||
servizio.isOkAcconto ||
servizio.isInterrotto ||
servizio.decorrenza !== null
) {
return { available: false, userId: null };
}
return { available: true, userId: servizio.user_id };
}),
getServizioAnnuncio: protectedProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
servizioId: zServizioId,
}),
)
.query(async ({ input }) => {
return await getServizioAnnuncio({
annuncioId: input.annuncioId,
servizioId: input.servizioId,
});
}),
getUserServizi: adminProcedure
.input(
z.object({
userId: zUserId,
}),
)
.query(async ({ input }) => {
return await getServiziByUserId(input.userId);
}),
interruzioneServizio: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
isAdmin: z.boolean(),
}),
)
.mutation(async ({ input }) => {
return await interruzioneServizio(input.servizioId, input.isAdmin);
}),
processServizioOnboard: protectedProcedure
.input(
z.object({
anagrafica: z.custom<UsersAnagraficaUpdate>(),
servizio: z.custom<ServizioUpdate>(),
servizioId: zServizioId,
user: z.custom<
Pick<Users, "nome" | "cognome" | "email" | "telefono" | "username">
>(),
userId: zUserId,
}),
)
.mutation(async ({ input }) => {
return await processServizioOnboard({
...input,
});
}),
attivazioneSenzaPagamento: protectedProcedure
.input(
z.object({
ordineId: zOrdineId,
}),
)
.mutation(async ({ input }) => {
return await attivaServizio_SaltaPagamentoAcconto(input.ordineId);
}),
AdminAttivaServizio_Ufficio: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await AdminAttivaServizio_Ufficio(input.servizioId);
}),
removeAnnuncioServizio: protectedProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await deleteServizioAnnuncio(input.servizioId, input.annuncioId);
}),
removeOrder: adminProcedure
.input(
z.object({
ordineId: zOrdineId,
}),
)
.mutation(async ({ input }) => {
return await removeOrder(input.ordineId);
}),
getPacksSolution: protectedProcedure
.input(
z.object({
servizioId: zServizioId,
}),
)
.query(async ({ input }) => {
return await getPacksPerServizio(input.servizioId);
}),
unlockServizioContatti: protectedProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await SbloccaContatti({
annuncioId: input.annuncioId,
servizioId: input.servizioId,
});
}),
createOrdine: adminProcedure
.input(
z.object({
data: z.custom<NewOrdini>(),
}),
)
.mutation(async ({ input }) => {
return await createOrdine(input.data);
}),
updateOrder: adminProcedure
.input(
z.object({
data: z.custom<OrdiniUpdate>(),
ordineId: zOrdineId,
}),
)
.mutation(async ({ input }) => {
return await updateOrder({
data: input.data,
ordineId: input.ordineId,
});
}),
updateServizio: protectedProcedure
.input(
z.object({
data: z.custom<ServizioUpdate>(),
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await updateServizio({
data: input.data,
servizioId: input.servizioId,
});
}),
updateServizioAnnunci: protectedProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
data: z.custom<ServizioAnnunciUpdate>(),
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await updateServizioAnnuncio({
annuncioId: input.annuncioId,
data: input.data,
servizioId: input.servizioId,
});
}),
adminUpdateConfermaStatus: adminProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
servizioId: zServizioId,
status: z.boolean(),
}),
)
.mutation(async ({ input }) => {
return await adminUpdateConfermaStatus({
annuncioId: input.annuncioId,
servizioId: input.servizioId,
status: input.status,
});
}),
userSendConfermaIntent: protectedProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await userSendConfermaIntent({
annuncioId: input.annuncioId,
servizioId: input.servizioId,
});
}),
userAcceptConfermaImmobile: protectedProcedure
.input(
z.object({
annuncioId: zAnnuncioId,
servizioId: zServizioId,
}),
)
.mutation(async ({ input }) => {
return await userAccettaConferma({
annuncioId: input.annuncioId,
servizioId: input.servizioId,
});
}),
getAllServiziData: protectedProcedure
.input(
z.object({
userId: zUserId,
}),
)
.query(async ({ input }) => {
const data: (
| { d: Date; type: "servizio"; data: ServizioData }
| { d: Date; type: "rinnovo"; data: Rinnovi }
)[] = [];
const servizio = await getAllServizioAnnunci(input.userId);
const rinnovi = await getRinnoviUser(input.userId);
servizio.forEach((s) => {
data.push({
d: s.created_at,
type: "servizio",
data: s,
});
});
rinnovi.forEach((r) => {
data.push({
d: r.decorrenza,
type: "rinnovo",
data: r,
});
});
data.sort((a, b) => b.d.getTime() - a.d.getTime());
return data;
}),
createRinnovo: adminProcedure
.input(
z.object({
data: z.custom<NewRinnovi>(),
}),
)
.mutation(async ({ input }) => {
return await createRinnovo(input.data);
}),
updateRinnovo: adminProcedure
.input(
z.object({
data: z.custom<RinnoviUpdate>(),
rinnovoId: zRinnovoId,
}),
)
.mutation(async ({ input }) => {
return await updateRinnovo({
rinnovoId: input.rinnovoId,
data: input.data,
});
}),
getRinnovo: protectedProcedure
.input(
z.object({
rinnovoId: zRinnovoId,
}),
)
.query(async ({ input }) => {
return await getRinnovoData(input.rinnovoId);
}),
removeRinnovo: adminProcedure
.input(
z.object({
rinnovoId: zRinnovoId,
}),
)
.mutation(async ({ input }) => {
return await deleteRinnovo(input.rinnovoId);
}),
});