2025-08-07 14:50:40 +02:00
|
|
|
import { z } from "zod/v4";
|
2025-12-01 12:29:48 +01:00
|
|
|
import type { EmailsIdEmail } from "~/schemas/public/Emails";
|
2026-03-10 13:16:32 +01:00
|
|
|
import type { TestiEStringheStingaId } from "~/schemas/public/TestiEStringhe";
|
2025-11-19 17:18:28 +01:00
|
|
|
import {
|
|
|
|
|
adminProcedure,
|
|
|
|
|
createTRPCRouter,
|
|
|
|
|
protectedProcedure,
|
2026-03-05 12:32:03 +01:00
|
|
|
publicProcedure,
|
2025-11-19 17:18:28 +01:00
|
|
|
} from "~/server/api/trpc";
|
2026-03-10 13:16:32 +01:00
|
|
|
import { addEventToQueue } from "~/server/controllers/event_queue.controller";
|
2026-03-05 12:32:03 +01:00
|
|
|
import { SendContattoAnnuncioEmail } from "~/server/controllers/servizio.controller";
|
2026-01-27 16:30:19 +01:00
|
|
|
import { db } from "~/server/db";
|
2025-12-29 16:00:57 +01:00
|
|
|
import {
|
|
|
|
|
deleteAllUserEmails,
|
|
|
|
|
deleteEmail,
|
|
|
|
|
getEmails,
|
|
|
|
|
} from "~/server/services/email.service";
|
2025-11-19 17:18:28 +01:00
|
|
|
import { NewMail } from "~/server/services/mailer";
|
2026-03-17 18:47:35 +01:00
|
|
|
import { CONDIZIONI_DEFAULT } from "~/server/services/prezziario.service";
|
2026-03-04 16:39:27 +01:00
|
|
|
import { genPdfSchedaAnnuncioBase64 } from "~/server/services/puppeteer.service";
|
2026-03-10 13:16:32 +01:00
|
|
|
import { zAnnuncioId, zOrdineId, zUserId } from "~/server/utils/zod_types";
|
2025-08-04 17:45:44 +02:00
|
|
|
|
|
|
|
|
export const comunicazioniRouter = createTRPCRouter({
|
2025-10-20 18:00:53 +02:00
|
|
|
getEmails: protectedProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(z.object({ userId: zUserId }))
|
|
|
|
|
.query(async ({ input }) => {
|
2025-12-29 16:00:57 +01:00
|
|
|
return await getEmails({
|
2025-08-28 18:27:07 +02:00
|
|
|
userId: input.userId,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2025-12-01 12:29:48 +01:00
|
|
|
deleteEmail: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
id_email: z.custom<EmailsIdEmail>(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
2025-12-29 16:00:57 +01:00
|
|
|
return await deleteEmail({
|
2025-12-01 12:29:48 +01:00
|
|
|
id_email: input.id_email,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2025-12-29 16:00:57 +01:00
|
|
|
deleteAllUserEmails: adminProcedure
|
|
|
|
|
.input(z.object({ userId: zUserId }))
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await deleteAllUserEmails({
|
|
|
|
|
userId: input.userId,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2026-03-05 12:32:03 +01:00
|
|
|
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 };
|
|
|
|
|
}),
|
2025-11-19 17:18:28 +01:00
|
|
|
sendSchedaAnnuncioEmail: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-03-04 16:39:27 +01:00
|
|
|
id: zAnnuncioId,
|
2025-11-19 17:18:28 +01:00
|
|
|
codice: z.string(),
|
2025-11-20 11:59:24 +01:00
|
|
|
numero: z.string(),
|
|
|
|
|
nominativo: z.string(),
|
|
|
|
|
indirizzo: z.string(),
|
2025-11-19 17:18:28 +01:00
|
|
|
to: z.email(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
try {
|
2026-03-04 16:39:27 +01:00
|
|
|
const scheda = await genPdfSchedaAnnuncioBase64(input.id);
|
2025-11-20 11:59:24 +01:00
|
|
|
|
2025-11-19 17:18:28 +01:00
|
|
|
await NewMail({
|
|
|
|
|
template: {
|
2025-11-20 11:59:24 +01:00
|
|
|
mailType: "emailSchedaContatto",
|
2025-11-19 17:18:28 +01:00
|
|
|
props: {
|
2025-11-20 11:59:24 +01:00
|
|
|
nominativo: input.nominativo,
|
|
|
|
|
telefono: input.numero,
|
|
|
|
|
indirizzo: input.indirizzo,
|
2025-11-19 17:18:28 +01:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
mail: {
|
|
|
|
|
subject: `Scheda Annuncio ${input.codice} - Infoalloggi.it`,
|
|
|
|
|
to: input.to,
|
|
|
|
|
attachments: [
|
|
|
|
|
{
|
2025-11-20 11:59:24 +01:00
|
|
|
filename: `scheda annuncio ${input.codice}.pdf`,
|
2026-03-04 16:39:27 +01:00
|
|
|
content: scheda,
|
2025-11-19 17:18:28 +01:00
|
|
|
encoding: "base64",
|
|
|
|
|
contentType: "application/pdf",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
});
|
2026-02-18 10:20:15 +01:00
|
|
|
|
2026-02-17 12:38:42 +01:00
|
|
|
await NewMail({
|
|
|
|
|
template: {
|
2026-02-18 10:20:15 +01:00
|
|
|
mailType: "generic",
|
2026-02-17 12:38:42 +01:00
|
|
|
props: {
|
2026-02-18 10:20:15 +01:00
|
|
|
title: `Ricevuta invio Scheda ${input.codice} a ${input.to}`,
|
|
|
|
|
testo: `La scheda dell'annuncio ${input.codice} è stata inviata a ${input.to} con successo.`,
|
2026-02-17 12:38:42 +01:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
mail: {
|
2026-02-18 10:20:15 +01:00
|
|
|
subject: `Ricevuta invio Scheda ${input.codice} a ${input.to}`,
|
2026-02-17 12:38:42 +01:00
|
|
|
to: "web@infoalloggi.it",
|
|
|
|
|
},
|
|
|
|
|
});
|
2025-11-19 17:18:28 +01:00
|
|
|
} catch (e) {
|
2026-03-04 16:39:27 +01:00
|
|
|
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)
|
2026-03-05 10:29:08 +01:00
|
|
|
.executeTakeFirstOrThrow(() => {
|
|
|
|
|
throw new Error(`User not found - userId: ${input.userId}`);
|
|
|
|
|
});
|
2026-03-04 16:39:27 +01:00
|
|
|
const annuncio = await db
|
|
|
|
|
.selectFrom("annunci")
|
|
|
|
|
.select([
|
|
|
|
|
"codice",
|
|
|
|
|
"locatore",
|
|
|
|
|
"indirizzo",
|
|
|
|
|
"civico",
|
|
|
|
|
"comune",
|
|
|
|
|
"cap",
|
|
|
|
|
"provincia",
|
|
|
|
|
"numero",
|
|
|
|
|
])
|
|
|
|
|
.where("id", "=", input.annuncioId)
|
2026-03-05 10:29:08 +01:00
|
|
|
.executeTakeFirstOrThrow(
|
|
|
|
|
() =>
|
|
|
|
|
new Error(`Annuncio not found - annuncioId: ${input.annuncioId}`),
|
|
|
|
|
);
|
2026-03-04 16:39:27 +01:00
|
|
|
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) {
|
2025-11-19 17:18:28 +01:00
|
|
|
throw new Error(
|
|
|
|
|
`Errore nell'invio dell'email: ${(e as Error).message}`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}),
|
2026-03-05 12:32:03 +01:00
|
|
|
|
|
|
|
|
sendContattoAnnuncioEmail: publicProcedure
|
2026-01-27 16:30:19 +01:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-03-05 12:32:03 +01:00
|
|
|
codice: z.string(),
|
|
|
|
|
email: z.string(),
|
|
|
|
|
messaggio: z.string(),
|
|
|
|
|
nome: z.string(),
|
|
|
|
|
telefono: z.string(),
|
2026-01-27 16:30:19 +01:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
2026-03-05 12:32:03 +01:00
|
|
|
return await SendContattoAnnuncioEmail({
|
|
|
|
|
...input,
|
|
|
|
|
});
|
2026-01-27 16:30:19 +01:00
|
|
|
}),
|
2026-03-10 13:16:32 +01:00
|
|
|
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 ||
|
2026-03-17 18:47:35 +01:00
|
|
|
CONDIZIONI_DEFAULT) as TestiEStringheStingaId,
|
2026-03-10 13:16:32 +01:00
|
|
|
},
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
},
|
2026-03-17 18:47:35 +01:00
|
|
|
lock_expires: new Date(Date.now() + 3000), // Lock for 30 sec
|
2026-03-10 13:16:32 +01:00
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`Errore nell'invio dell'email: ${(e as Error).message}`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
});
|