infoalloggi-monorepo/apps/infoalloggi/src/server/api/routers/comunicazioni.ts

278 lines
7.1 KiB
TypeScript

import { z } from "zod/v4";
import type { EmailsIdEmail } from "~/schemas/public/Emails";
import type { TestiEStringheStingaId } from "~/schemas/public/TestiEStringhe";
import {
adminProcedure,
createTRPCRouter,
protectedProcedure,
publicProcedure,
} from "~/server/api/trpc";
import { addEventToQueue } from "~/server/controllers/event_queue.controller";
import { SendContattoAnnuncioEmail } from "~/server/controllers/servizio.controller";
import { db } from "~/server/db";
import {
deleteAllUserEmails,
deleteEmail,
getEmails,
} from "~/server/services/email.service";
import { NewMail } from "~/server/services/mailer";
import { CONDIZIONI_DEFAULT } from "~/server/services/prezziario.service";
import { genPdfSchedaAnnuncioBase64 } from "~/server/services/puppeteer.service";
import { zAnnuncioId, zOrdineId, zUserId } from "~/server/utils/zod_types";
export const comunicazioniRouter = createTRPCRouter({
getEmails: protectedProcedure
.input(z.object({ userId: zUserId }))
.query(async ({ input }) => {
return await getEmails({
userId: input.userId,
});
}),
deleteEmail: adminProcedure
.input(
z.object({
id_email: z.custom<EmailsIdEmail>(),
}),
)
.mutation(async ({ input }) => {
return await deleteEmail({
id_email: input.id_email,
});
}),
deleteAllUserEmails: adminProcedure
.input(z.object({ userId: zUserId }))
.mutation(async ({ input }) => {
return await deleteAllUserEmails({
userId: input.userId,
});
}),
sendEmailContatto: publicProcedure
.input(
z.object({
cognome: z.string(),
email: z.email(),
messaggio: z.string(),
nome: z.string(),
telefono: z.string(),
}),
)
.mutation(async ({ input }) => {
await NewMail({
template: {
mailType: "contattoAdminEmail",
props: {
cognome: input.cognome,
email: input.email,
messaggio: input.messaggio,
nome: input.nome,
telefono: input.telefono,
},
},
mail: {
subject: `Richiesta di contatto da ${input.nome}`,
to: "web@infoalloggi.it",
},
});
return { success: true };
}),
sendSchedaAnnuncioEmail: adminProcedure
.input(
z.object({
id: zAnnuncioId,
codice: z.string(),
numero: z.string(),
nominativo: z.string(),
indirizzo: z.string(),
to: z.email(),
}),
)
.mutation(async ({ input }) => {
try {
const scheda = await genPdfSchedaAnnuncioBase64(input.id);
await NewMail({
template: {
mailType: "emailSchedaContatto",
props: {
nominativo: input.nominativo,
telefono: input.numero,
indirizzo: input.indirizzo,
},
},
mail: {
subject: `Scheda Annuncio ${input.codice} - Infoalloggi.it`,
to: input.to,
attachments: [
{
filename: `scheda annuncio ${input.codice}.pdf`,
content: scheda,
encoding: "base64",
contentType: "application/pdf",
},
],
},
});
await NewMail({
template: {
mailType: "generic",
props: {
title: `Ricevuta invio Scheda ${input.codice} a ${input.to}`,
testo: `La scheda dell'annuncio ${input.codice} è stata inviata a ${input.to} con successo.`,
},
},
mail: {
subject: `Ricevuta invio Scheda ${input.codice} a ${input.to}`,
to: "web@infoalloggi.it",
},
});
} catch (e) {
throw new Error(
`Errore nell'invio dell'email: ${(e as Error).message}`,
);
}
}),
sendSchedaAnnuncioServizio: adminProcedure
.input(
z.object({
userId: zUserId,
annuncioId: zAnnuncioId,
}),
)
.mutation(async ({ input }) => {
try {
const scheda = await genPdfSchedaAnnuncioBase64(input.annuncioId);
const user = await db
.selectFrom("users")
.select("email")
.where("id", "=", input.userId)
.executeTakeFirstOrThrow(() => {
throw new Error(`User not found - userId: ${input.userId}`);
});
const annuncio = await db
.selectFrom("annunci")
.select([
"codice",
"locatore",
"indirizzo",
"civico",
"comune",
"cap",
"provincia",
"numero",
])
.where("id", "=", input.annuncioId)
.executeTakeFirstOrThrow(
() =>
new Error(`Annuncio not found - annuncioId: ${input.annuncioId}`),
);
await NewMail({
template: {
mailType: "emailContattiConScheda",
props: {
codice: annuncio.codice,
nominativo: annuncio.locatore || "",
telefono: annuncio.numero || "",
indirizzo: `${annuncio.indirizzo || ""}, ${annuncio.civico || ""} ${annuncio.comune || ""} ${annuncio.cap || ""} (${annuncio.provincia || ""})`,
},
},
mail: {
subject: `Contatti Annuncio ${annuncio.codice} - Infoalloggi.it`,
to: user.email,
attachments: [
{
filename: `scheda annuncio ${annuncio.codice}.pdf`,
content: scheda,
encoding: "base64",
contentType: "application/pdf",
},
],
},
});
} catch (e) {
throw new Error(
`Errore nell'invio dell'email: ${(e as Error).message}`,
);
}
}),
sendContattoAnnuncioEmail: publicProcedure
.input(
z.object({
codice: z.string(),
email: z.string(),
messaggio: z.string(),
nome: z.string(),
telefono: z.string(),
}),
)
.mutation(async ({ input }) => {
return await SendContattoAnnuncioEmail({
...input,
});
}),
sendRicevutaECondizioniEmail: adminProcedure
.input(
z.object({
ordineId: zOrdineId,
}),
)
.mutation(async ({ input }) => {
try {
const ordine = await db
.selectFrom("ordini")
.selectAll()
.innerJoin("users", "users.id", "ordini.userid")
.select(["users.email"])
.innerJoin("prezziario", "prezziario.idprezziario", "ordini.packid")
.select(["prezziario.testo_condizioni"])
.where("ordine_id", "=", input.ordineId)
.executeTakeFirstOrThrow(() => {
throw new Error(`Ordine not found - ordineId: ${input.ordineId}`);
});
await addEventToQueue({
data: {
tipo: "email",
data: {
template: {
mailType: "servizioAttivato",
},
mail: {
subject: "Pagamento Confermato - Acconto Infoalloggi.it",
to: ordine.email,
attachments: [
{
filename: `condizioni_contrattuali_${ordine.created_at.toISOString()}.pdf`,
generate: {
type: "condizioni",
stringId: (ordine.testo_condizioni ||
CONDIZIONI_DEFAULT) as TestiEStringheStingaId,
},
encoding: "base64",
contentType: "application/pdf",
},
{
filename: `ricevuta_cortesia_${ordine.ordine_id}.pdf`,
generate: {
type: "ricevuta_cortesia",
ordineId: ordine.ordine_id,
},
encoding: "base64",
contentType: "application/pdf",
},
],
},
userId: ordine.userid,
},
},
lock_expires: new Date(Date.now() + 3000), // Lock for 30 sec
});
} catch (e) {
throw new Error(
`Errore nell'invio dell'email: ${(e as Error).message}`,
);
}
}),
});