feat: enhance error handling with custom messages for database operations

This commit is contained in:
Marco Pedone 2026-03-05 10:29:08 +01:00
parent 728ba71c84
commit 8d89be35d5
11 changed files with 180 additions and 78 deletions

View file

@ -123,7 +123,9 @@ export const comunicazioniRouter = createTRPCRouter({
.selectFrom("users")
.select("email")
.where("id", "=", input.userId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => {
throw new Error(`User not found - userId: ${input.userId}`);
});
const annuncio = await db
.selectFrom("annunci")
.select([
@ -137,7 +139,10 @@ export const comunicazioniRouter = createTRPCRouter({
"numero",
])
.where("id", "=", input.annuncioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(`Annuncio not found - annuncioId: ${input.annuncioId}`),
);
await NewMail({
template: {
mailType: "emailContattiConScheda",

View file

@ -39,7 +39,9 @@ export const messagesSSERouter = createTRPCRouter({
time: new Date(),
})
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error("Failed to insert message into database"),
);
const userInfos = await db
.selectFrom("users")
@ -193,7 +195,9 @@ export const messagesSSERouter = createTRPCRouter({
.selectFrom("messages")
.selectAll()
.where("messageid", "=", lastEventId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => {
throw new Error(`Message not found - messageId: ${lastEventId}`);
});
return messageById?.time ?? null;
})();

View file

@ -440,7 +440,9 @@ export const editAnnuncioHandler = async ({
})
.where("id", "=", annuncioId)
.returning("codice")
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => {
throw new Error(`Annuncio not found - annuncioId: ${annuncioId}`);
});
await revalidate(`/annuncio/${annuncio.codice}`);
return true;
} catch (e) {
@ -485,7 +487,9 @@ export const getProprietarioDataHandler = async ({
"locatore",
])
.where("id", "=", annuncioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => {
throw new Error(`Annuncio not found - annuncioId: ${annuncioId}`);
});
return { opened_at: opened_at.open_contatti_at, propData };
} catch (e) {

View file

@ -167,7 +167,9 @@ export const getUserByChatHandler = async ({
.selectFrom("chats")
.select(["chatid", "created_at", "user_ref", getUserInfo()])
.where("chats.chatid", "=", chatId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Chat not found - chatId: ${chatId}`),
);
if (!chat.userinfo) {
throw new TRPCError({ code: "NOT_FOUND" });

View file

@ -57,7 +57,9 @@ export const getOrdineById = async (ordineId: OrdiniOrdineId) => {
])
.where("ordini.ordine_id", "=", ordineId)
.orderBy("created_at", "desc")
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Ordine not found - ordineId: ${ordineId}`),
);
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
@ -73,13 +75,15 @@ export const createOrdine = async (data: NewOrdini) => {
.selectFrom("prezziario")
.select(["prezzo_cent", "nome_it"])
.where("prezziario.idprezziario", "=", data.packid)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Prezziario not found - packid: ${data.packid}`),
);
const order = await tx
.insertInto("ordini")
.values(data)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => new Error("Failed to create ordine"));
await tx
.insertInto("payments")
.values({
@ -108,10 +112,7 @@ export const createOrdine = async (data: NewOrdini) => {
export const removeOrder = async (ordineId: OrdiniOrdineId) => {
try {
await db
.deleteFrom("ordini")
.where("ordine_id", "=", ordineId)
.executeTakeFirstOrThrow();
await db.deleteFrom("ordini").where("ordine_id", "=", ordineId).execute();
return true;
} catch (e) {
throw new TRPCError({
@ -134,7 +135,9 @@ export const updateOrder = async ({
.set(data)
.where("ordine_id", "=", ordineId)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Failed to update ordine - ordineId: ${ordineId}`),
);
return updated;
} catch (e) {
throw new TRPCError({

View file

@ -61,7 +61,9 @@ export const addServizio = async (data: NewServizio) => {
.insertInto("servizio")
.values(data)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error("Failed to insert new servizio into database"),
);
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
@ -76,7 +78,9 @@ export const getServizioById = async (servizioId: ServizioServizioId) => {
.selectFrom("servizio")
.selectAll()
.where("servizio_id", "=", servizioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Servizio not found - servizioId: ${servizioId}`),
);
} catch (e) {
throw new TRPCError({
code: "NOT_FOUND",
@ -98,7 +102,10 @@ export const updateServizio = async ({
.set(data)
.where("servizio_id", "=", servizioId)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(`Failed to update servizio - servizioId: ${servizioId}`),
);
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
@ -112,7 +119,7 @@ export const deleteServizio = async (servizioId: ServizioServizioId) => {
await db
.deleteFrom("servizio")
.where("servizio_id", "=", servizioId)
.executeTakeFirstOrThrow();
.execute();
return true;
} catch (e) {
throw new TRPCError({
@ -172,7 +179,9 @@ export const getPreOnboardData = async (servizioId: ServizioServizioId) => {
"users.telefono",
])
.where("id", "=", servizio.user_id)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`User not found - userId: ${servizio.user_id}`),
);
if (!userData) {
throw new TRPCError({
@ -217,7 +226,9 @@ export const getDataPerAcquisto = async (servizioId: ServizioServizioId) => {
"users.telefono",
])
.where("id", "=", servizio.user_id)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`User not found - userId: ${servizio.user_id}`),
);
if (!userData) {
throw new TRPCError({
@ -263,7 +274,7 @@ export const postAcquistoDataHandler = async ({
.updateTable("users")
.set(user)
.where("id", "=", userId)
.executeTakeFirstOrThrow();
.execute();
const { idanagrafica, ...rest } = anagrafica;
if (idanagrafica) {
@ -275,7 +286,12 @@ export const postAcquistoDataHandler = async ({
})
.where("idanagrafica", "=", idanagrafica)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(
`Failed to update users_anagrafica - idanagrafica: ${idanagrafica}`,
),
);
} else {
await tx
.insertInto("users_anagrafica")
@ -284,7 +300,9 @@ export const postAcquistoDataHandler = async ({
userid: userId,
})
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error("Failed to insert new users_anagrafica"),
);
}
// Update servizio data
return await tx
@ -292,7 +310,10 @@ export const postAcquistoDataHandler = async ({
.set(servizio)
.where("servizio_id", "=", servizioId)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(`Failed to update servizio - servizioId: ${servizioId}`),
);
});
if (servizioData.skipPayment) {
@ -374,7 +395,7 @@ export const postAcquistoDataHandler = async ({
userid: userId,
})
.returning("ordine_id")
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => new Error("Failed to create ordine"));
return { ordineIdForPayment: order.ordine_id };
} catch (e) {
@ -409,7 +430,9 @@ export const setupSaldoServizio = async ({
.selectFrom("servizio")
.selectAll()
.where("servizio_id", "=", servizioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Servizio not found - servizioId: ${servizioId}`),
);
if (
!servizio.isOkAcconto ||
@ -428,7 +451,12 @@ export const setupSaldoServizio = async ({
.selectAll()
.where("servizio_id", "=", servizioId)
.where("annunci_id", "=", annuncioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(
`Annuncio not found - servizioId: ${servizioId}, annunciId: ${annuncioId}`,
),
);
if (
annuncio.user_confirmed_at == null ||
annuncio.accettato_conferma_at == null
@ -498,7 +526,7 @@ export const setupSaldoServizio = async ({
userid: servizio.user_id,
})
.returning("ordine_id")
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => new Error("Failed to create ordine"));
return order.ordine_id;
});
@ -633,7 +661,9 @@ export const setupSaldoConsulenzaServizio = async ({
.selectFrom("servizio")
.selectAll()
.where("servizio_id", "=", servizioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Servizio not found - servizioId: ${servizioId}`),
);
if (
!servizio.isOkAcconto ||
@ -653,7 +683,12 @@ export const setupSaldoConsulenzaServizio = async ({
.selectAll()
.where("servizio_id", "=", servizioId)
.where("annunci_id", "=", annuncioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(
`Annuncio not found - servizioId: ${servizioId}, annunciId: ${annuncioId}`,
),
);
if (
annuncio.user_confirmed_at == null ||
annuncio.accettato_conferma_at == null ||
@ -706,7 +741,7 @@ export const setupSaldoConsulenzaServizio = async ({
userid: servizio.user_id,
})
.returning("ordine_id")
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => new Error("Failed to create ordine"));
return order.ordine_id;
});
@ -1133,7 +1168,12 @@ export const getServizioAnnuncio = async ({
.selectAll()
.where("servizio_id", "=", servizioId)
.where("annunci_id", "=", annuncioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(
`Servizio not found - servizioId: ${servizioId}, annunciId: ${annuncioId}`,
),
);
} catch (e) {
throw new TRPCError({
code: "NOT_FOUND",
@ -1422,7 +1462,7 @@ export const interruzioneServizio = async (servizioId: ServizioServizioId) => {
isInterrotto: true,
})
.where("servizio_id", "=", servizioId)
.executeTakeFirstOrThrow();
.execute();
// NOTIFICHE EMAIL INTERRUZIONE SERVIZIO
const utente = await getUser({ db, userId: servizio.user_id });
@ -1549,7 +1589,7 @@ export const userSendConfermaIntent = async ({
})
.where("servizio_id", "=", servizioId)
.where("annunci_id", "=", annuncioId)
.executeTakeFirstOrThrow();
.execute();
// NOTIFICHE EMAIL CONFERMA IMMOBILE
@ -1559,7 +1599,12 @@ export const userSendConfermaIntent = async ({
.selectFrom("annunci")
.select("codice")
.where("id", "=", annuncioId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(
`Annuncio not found - servizioId: ${servizioId}, annunciId: ${annuncioId}`,
),
);
await NewMail({
template: {
@ -1751,13 +1796,17 @@ export const getServizioPagamentoData = async (ordineId: OrdiniOrdineId) => {
.selectFrom("ordini")
.selectAll()
.where("ordine_id", "=", ordineId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Ordine not found - ordineId: ${ordineId}`),
);
const pack = await db
.selectFrom("prezziario")
.selectAll()
.where("idprezziario", "=", ordine.packid)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Prezziario not found - packid: ${ordine.packid}`),
);
const payment = await db
.insertInto("payments")
@ -1769,13 +1818,18 @@ export const getServizioPagamentoData = async (ordineId: OrdiniOrdineId) => {
userid: ordine.userid,
})
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Failed to create payment - ordineId: ${ordineId}`),
);
const servizio = await db
.selectFrom("servizio")
.selectAll()
.where("servizio.servizio_id", "=", payment.servizio_id)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(`Servizio not found - servizioId: ${payment.servizio_id}`),
);
if (!servizio) {
throw new TRPCError({
@ -1808,7 +1862,9 @@ export const getPagamentoDataForCheckout = async (paymentId: PaymentsId) => {
.innerJoin("prezziario", "prezziario.idprezziario", "ordini.packid")
.select(["prezziario.nome_it", "prezziario.desc_it"])
.where("payments.id", "=", paymentId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Payment not found - paymentId: ${paymentId}`),
);
} catch (e) {
throw new TRPCError({
code: "NOT_FOUND",
@ -1848,7 +1904,9 @@ export const updatePagamento = async ({
.set(data)
.where("id", "=", paymentId)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Failed to update pagamento - paymentId: ${paymentId}`),
);
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
@ -2065,7 +2123,9 @@ export const getOrdineRicevutaData = async ({
.where("payments.ordine_id", "=", ordineId)
.where("payments.paymentstatus", "=", PaymentStatusEnum.success)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Ordine not found - ordineId: ${ordineId}`),
);
if (!data || !data.user || !data.anagrafica) {
throw new TRPCError({

View file

@ -96,7 +96,12 @@ export const getStorageIdFromUserStorageId = async ({
.selectFrom("users_storage")
.select("storageId")
.where("user_storage_id", "=", userStorageId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() =>
new Error(
`User storage entry not found - userStorageId: ${userStorageId}`,
),
);
return storage.storageId;
} catch (e) {
throw new TRPCError({

View file

@ -9,10 +9,6 @@ import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { db } from "~/server/db";
import { NewMail } from "~/server/services/mailer";
import { getUser } from "~/server/services/user.service";
import {
genPdfCondizioniBase64,
genPdfRicevutaCortesiaBase64,
} from "../services/puppeteer.service";
import { addEventToQueue } from "./event_queue.controller";
export const stripeHealthCheck = async () => {
@ -50,7 +46,9 @@ export const createIntentHandler = async ({
.innerJoin("prezziario", "prezziario.idprezziario", "ordini.packid")
.select(["prezziario.nome_it", "prezziario.desc_it"])
.where("payments.id", "=", paymentId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Payment not found - paymentId: ${paymentId}`),
);
const paymentIntent = await stripe.paymentIntents.create({
amount: payment.amount_cent,
@ -130,13 +128,19 @@ export const whIntentSucceededHandler = async ({
.where("intent_id", "=", pIntentId)
.where("payments.id", "=", paymentId)
.returning(["servizio_id", "ordine_id"])
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => {
throw new Error(
`Payment not found - intent_id: ${pIntentId}, paymentId: ${paymentId}`,
);
});
const ordine = await trx
.selectFrom("ordini")
.selectAll("ordini")
.where("ordine_id", "=", payment.ordine_id)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => {
throw new Error(`Ordine not found - ordine_id: ${payment.ordine_id}`);
});
await trx
.updateTable("ordini")
@ -150,12 +154,17 @@ export const whIntentSucceededHandler = async ({
.selectFrom("servizio")
.select("servizio.tipologia")
.where("servizio_id", "=", payment.servizio_id)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(() => {
throw new Error(
`Servizio not found - servizio_id: ${payment.servizio_id}`,
);
});
const utente = await getUser({
db: trx,
userId: ordine.userid,
});
const lock_expires = new Date(Date.now() + 60 * 1000); // Lock for 1 minute
switch (ordine.type) {
case OrderTypeEnum.Acconto:
@ -168,7 +177,6 @@ export const whIntentSucceededHandler = async ({
})
.execute();
//TODO inserire gli allegati solo se si ha il pdf generato
await addEventToQueue({
data: {
tipo: "email",
@ -183,9 +191,7 @@ export const whIntentSucceededHandler = async ({
{
filename: `condizioni_contrattuali_${ordine.created_at.toISOString()}.pdf`,
//ATTENTION: hardcoded condizioni key
// content: await genPdfCondizioniBase64(
// "CONDIZIONI_CERCHI" as TestiEStringheStingaId,
// ),
generate: {
type: "condizioni",
stringId: "CONDIZIONI_CERCHI" as TestiEStringheStingaId,
@ -195,9 +201,7 @@ export const whIntentSucceededHandler = async ({
},
{
filename: `ricevuta_cortesia_${ordine.ordine_id}.pdf`,
// content: await genPdfRicevutaCortesiaBase64(
// ordine.ordine_id,
// ),
generate: {
type: "ricevuta_cortesia",
ordineId: ordine.ordine_id,
@ -210,7 +214,7 @@ export const whIntentSucceededHandler = async ({
userId: utente.id,
},
},
lock_expires: new Date(Date.now() + 60 * 1000), // Lock for 1 minute
lock_expires,
});
//SERVIZIO ATTIVATO
@ -243,9 +247,7 @@ export const whIntentSucceededHandler = async ({
type: "ricevuta_cortesia",
ordineId: ordine.ordine_id,
},
// content: await genPdfRicevutaCortesiaBase64(
// ordine.ordine_id,
// ),
encoding: "base64",
contentType: "application/pdf",
},
@ -254,7 +256,7 @@ export const whIntentSucceededHandler = async ({
userId: utente.id,
},
},
lock_expires: new Date(Date.now() + 60 * 1000), // Lock for 1 minute
lock_expires,
});
//PAGAMENTO SALDO CONFERMATO
break;
@ -279,9 +281,7 @@ export const whIntentSucceededHandler = async ({
attachments: [
{
filename: `ricevuta_cortesia_${ordine.ordine_id}.pdf`,
// content: await genPdfRicevutaCortesiaBase64(
// ordine.ordine_id,
// ),
generate: {
type: "ricevuta_cortesia",
ordineId: ordine.ordine_id,
@ -294,7 +294,7 @@ export const whIntentSucceededHandler = async ({
userId: utente.id,
},
},
lock_expires: new Date(Date.now() + 60 * 1000), // Lock for 1 minute
lock_expires,
});
//CONSULENZA ATTIVATA
break;
@ -313,9 +313,7 @@ export const whIntentSucceededHandler = async ({
attachments: [
{
filename: `ricevuta_cortesia_${ordine.ordine_id}.pdf`,
// content: await genPdfRicevutaCortesiaBase64(
// ordine.ordine_id,
// ),
generate: {
type: "ricevuta_cortesia",
ordineId: ordine.ordine_id,
@ -328,16 +326,25 @@ export const whIntentSucceededHandler = async ({
userId: utente.id,
},
},
lock_expires: new Date(Date.now() + 60 * 1000), // Lock for 1 minute
lock_expires,
});
break;
}
});
return true;
} catch (error) {
// Enhanced error logging
console.error("whIntentSucceededHandler error:", {
pIntentId,
paymentId,
pm_id,
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
});
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error updating payment intent: ${(error as Error).message}`,
cause: error,
});
}
};

View file

@ -21,7 +21,9 @@ export const getRaw = async ({
.selectFrom("chats")
.selectAll()
.where("chats.chatid", "=", chatId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Chat not found - chatId: ${chatId}`),
);
} catch (e) {
throw new TRPCError({
code: "BAD_REQUEST",
@ -39,7 +41,9 @@ export const add = async ({ db, userId }: { db: Querier; userId: UsersId }) => {
user_ref: userId,
})
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Error while creating chat for userId: ${userId}`),
);
return newChat;
} catch (e) {
throw new TRPCError({

View file

@ -56,7 +56,9 @@ export const addPrezziario = async ({
.insertInto("prezziario")
.values(input)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Failed to add prezziario with name: ${input.nome_it}`),
);
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
@ -79,7 +81,9 @@ export const updatePrezziario = async ({
.set(input)
.where("prezziario.idprezziario", "=", prezziarioId)
.returningAll()
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`Failed to update prezziario with id: ${prezziarioId}`),
);
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",

View file

@ -71,7 +71,9 @@ export const getUser = async ({
.selectFrom("users")
.selectAll()
.where("id", "=", userId)
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`User not found - userId: ${userId}`),
);
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
@ -160,7 +162,9 @@ export const getClientProfilo = async ({
),
).as("doc_personale_retro"),
])
.executeTakeFirstOrThrow();
.executeTakeFirstOrThrow(
() => new Error(`User not found - userId: ${userId}`),
);
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",