infoalloggi-monorepo/apps/infoalloggi/src/server/controllers/ordini.controller.ts
Marco Pedone 280e0ab5c2 feat: update payment recap links and add new receipt page
- Changed payment recap link in OrdiniModal to point to the new receipt page.
- Added new PaymentRecapPage for displaying receipt details.
- Updated PaymentsTable to set paid_at date based on payment status.
- Introduced manual payment type in PaymentType and updated related strings.
- Refactored getOrdineRicevutaData to use overridableProcedure for access control.
- Enhanced mail sending functionality to include PDF attachments for receipts and conditions.
- Updated PDF generation service to handle new receipt PDF generation.
- Cleaned up context checking utilities by removing unnecessary session checks.
2026-03-04 19:12:01 +01:00

171 lines
4.3 KiB
TypeScript

import { TRPCError } from "@trpc/server";
import { jsonArrayFrom } from "kysely/helpers/postgres";
import type {
NewOrdini,
OrdiniOrdineId,
OrdiniUpdate,
} from "~/schemas/public/Ordini";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import type { UsersId } from "~/schemas/public/Users";
import { db, type Querier } from "~/server/db";
export type OrdiniWPagamenti = Awaited<ReturnType<typeof getOrdini>>[number];
export const getOrdini = async (userId: UsersId | undefined) => {
try {
let qry = db
.selectFrom("ordini")
.selectAll("ordini")
.innerJoin("users", "users.id", "ordini.userid")
.select("users.username")
.select((eb) => [
jsonArrayFrom(
eb
.selectFrom("payments")
.selectAll("payments")
.whereRef("payments.ordine_id", "=", "ordini.ordine_id")
.orderBy("payments.created_at", "desc"),
).as("pagamenti"),
]);
if (userId) {
qry = qry.where("ordini.userid", "=", userId);
}
return await qry.orderBy("created_at", "desc").execute();
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error fetching ordini by user ID: ${(e as Error).message}`,
});
}
};
export const getOrdineById = async (ordineId: OrdiniOrdineId) => {
try {
return await db
.selectFrom("ordini")
.selectAll("ordini")
.innerJoin("users", "users.id", "ordini.userid")
.select("users.username")
.select((eb) => [
jsonArrayFrom(
eb
.selectFrom("payments")
.selectAll("payments")
.whereRef("payments.ordine_id", "=", "ordini.ordine_id")
.orderBy("payments.created_at", "desc"),
).as("pagamenti"),
])
.where("ordini.ordine_id", "=", ordineId)
.orderBy("created_at", "desc")
.executeTakeFirstOrThrow();
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error fetching ordini by user ID: ${(e as Error).message}`,
});
}
};
export const createOrdine = async (data: NewOrdini) => {
try {
return await db.transaction().execute(async (tx) => {
const prezzo = await tx
.selectFrom("prezziario")
.select(["prezzo_cent", "nome_it"])
.where("prezziario.idprezziario", "=", data.packid)
.executeTakeFirstOrThrow();
const order = await tx
.insertInto("ordini")
.values(data)
.returningAll()
.executeTakeFirstOrThrow();
await tx
.insertInto("payments")
.values({
ordine_id: order.ordine_id,
servizio_id: order.servizio_id,
userid: order.userid,
amount_cent: prezzo.prezzo_cent,
paymentname: prezzo.nome_it,
paymentmethod: "manual",
paymentstatus: data.isActive
? PaymentStatusEnum.success
: PaymentStatusEnum.processing,
paid_at: data.isActive ? new Date() : null,
})
.execute();
return order;
});
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error creating ordine: ${(e as Error).message}`,
});
}
};
export const removeOrder = async (ordineId: OrdiniOrdineId) => {
try {
await db
.deleteFrom("ordini")
.where("ordine_id", "=", ordineId)
.executeTakeFirstOrThrow();
return true;
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error removing order: ${(e as Error).message}`,
});
}
};
export const updateOrder = async ({
ordineId,
data,
}: {
ordineId: OrdiniOrdineId;
data: OrdiniUpdate;
}) => {
try {
const updated = await db
.updateTable("ordini")
.set(data)
.where("ordine_id", "=", ordineId)
.returningAll()
.executeTakeFirstOrThrow();
return updated;
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error updating order: ${(e as Error).message}`,
});
}
};
export const cleanupUnusedOrders = async ({ db }: { db: Querier }) => {
try {
const orders = await db
.selectFrom("ordini")
.select("ordini.ordine_id")
.leftJoin("payments", "payments.ordine_id", "ordini.ordine_id")
.where("payments.paymentstatus", "is", null)
.where("ordini.isActive", "=", false)
.distinct()
.execute();
if (orders.length === 0) {
return "ok";
}
const ordineIds = orders.map((o) => o.ordine_id);
await db.deleteFrom("ordini").where("ordine_id", "in", ordineIds).execute();
return "ok";
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error cleaning up old orders: ${(e as Error).message}`,
});
}
};