feat: add dotenv package for environment variable management and update payment logic to use new database queries

This commit is contained in:
Marco Pedone 2026-03-12 16:24:16 +01:00
parent 547b1d6ce6
commit 6c53ef130c
8 changed files with 318 additions and 133 deletions

View file

@ -110,6 +110,7 @@
"@types/uuid": "^11.0.0", "@types/uuid": "^11.0.0",
"@vitejs/plugin-react": "^5.1.4", "@vitejs/plugin-react": "^5.1.4",
"cross-env": "^10.1.0", "cross-env": "^10.1.0",
"dotenv": "^17.3.1",
"jiti": "^2.6.1", "jiti": "^2.6.1",
"jsdom": "^28.1.0", "jsdom": "^28.1.0",
"kanel": "^3.16.1", "kanel": "^3.16.1",
@ -8205,6 +8206,19 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/dotenv": {
"version": "17.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
"integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/dunder-proto": { "node_modules/dunder-proto": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",

View file

@ -123,6 +123,7 @@
"@types/uuid": "^11.0.0", "@types/uuid": "^11.0.0",
"@vitejs/plugin-react": "^5.1.4", "@vitejs/plugin-react": "^5.1.4",
"cross-env": "^10.1.0", "cross-env": "^10.1.0",
"dotenv": "^17.3.1",
"jiti": "^2.6.1", "jiti": "^2.6.1",
"jsdom": "^28.1.0", "jsdom": "^28.1.0",
"kanel": "^3.16.1", "kanel": "^3.16.1",

View file

@ -0,0 +1,124 @@
import { assert, describe, expect, it } from "vitest";
import type { PrezziarioIdprezziario } from "~/schemas/public/Prezziario";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import {
AccontoSolver,
SaldoSolver,
} from "~/server/controllers/pagamenti.controller";
type TestInput = {
tipologia: TipologiaPosizioneEnum;
permanenza: number | null;
budget: number;
};
type TestCase = {
input: TestInput;
exp_acconto: PrezziarioIdprezziario;
exp_saldo: PrezziarioIdprezziario;
descrizione: string;
};
const testCases: TestCase[] = [
{
input: {
tipologia: TipologiaPosizioneEnum.Transitorio,
permanenza: 0,
budget: 500,
},
exp_acconto: "ACCONTO_BD" as PrezziarioIdprezziario,
exp_saldo: "SALDOBD_1MESE" as PrezziarioIdprezziario,
descrizione: "1MESE BD",
},
{
input: {
tipologia: TipologiaPosizioneEnum.Transitorio,
permanenza: 1,
budget: 500,
},
exp_acconto: "ACCONTO_BD" as PrezziarioIdprezziario,
exp_saldo: "SALDOBD_3MESI" as PrezziarioIdprezziario,
descrizione: "3MESI BD",
},
{
input: {
tipologia: TipologiaPosizioneEnum.Transitorio,
permanenza: 2,
budget: 500,
},
exp_acconto: "ACCONTO_BD" as PrezziarioIdprezziario,
exp_saldo: "SALDOBD_6MESI" as PrezziarioIdprezziario,
descrizione: "6MESI BD",
},
{
input: {
tipologia: TipologiaPosizioneEnum.Transitorio,
permanenza: 3,
budget: 500,
},
exp_acconto: "ACCONTO_BD" as PrezziarioIdprezziario,
exp_saldo: "SALDOBD_9MESI" as PrezziarioIdprezziario,
descrizione: "9MESI BD",
},
{
input: {
tipologia: TipologiaPosizioneEnum.Transitorio,
permanenza: 4,
budget: 500,
},
exp_acconto: "ACCONTO_BD" as PrezziarioIdprezziario,
exp_saldo: "SALDOBD_12MESI" as PrezziarioIdprezziario,
descrizione: "12MESI BD",
},
{
input: {
tipologia: TipologiaPosizioneEnum.Stabile,
permanenza: null,
budget: 500,
},
exp_acconto: "ACCONTO_CA" as PrezziarioIdprezziario,
exp_saldo: "SALDOCA500" as PrezziarioIdprezziario,
descrizione: "CA 500",
},
{
input: {
tipologia: TipologiaPosizioneEnum.Stabile,
permanenza: null,
budget: 600,
},
exp_acconto: "ACCONTO_CA" as PrezziarioIdprezziario,
exp_saldo: "SALDOCA500+" as PrezziarioIdprezziario,
descrizione: "CA 500+",
},
{
input: {
tipologia: TipologiaPosizioneEnum.Stabile,
permanenza: null,
budget: 800,
},
exp_acconto: "ACCONTO_CA" as PrezziarioIdprezziario,
exp_saldo: "SALDOCA700+" as PrezziarioIdprezziario,
descrizione: "CA 700+",
},
];
describe("Test AccontoSolver", () => {
it.each(testCases)("$descrizione", async ({ input, exp_acconto }) => {
const pack = await AccontoSolver(input.tipologia);
assert(pack.success, "AccontoSolver failed");
expect(pack.pack.idprezziario).toEqual(exp_acconto);
});
});
describe("Test SaldoSolver", () => {
it.each(testCases)("$descrizione", async ({ input, exp_saldo }) => {
const pack = await SaldoSolver({
tipologia: input.tipologia,
permanenza: input.permanenza,
budget: input.budget,
});
assert(pack.success, "SaldoSolver failed");
expect(pack.pack.idprezziario).toEqual(exp_saldo);
});
});

View file

@ -5,16 +5,13 @@ import type {
Prezziario, Prezziario,
PrezziarioIdprezziario, PrezziarioIdprezziario,
} from "~/schemas/public/Prezziario"; } from "~/schemas/public/Prezziario";
import type { Servizio, ServizioServizioId } from "~/schemas/public/Servizio"; import type { ServizioServizioId } from "~/schemas/public/Servizio";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum"; import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { db } from "../db"; import { db } from "../db";
import { createOrdine } from "../services/ordini.service"; import { createOrdine } from "../services/ordini.service";
import { getPrezziarioByIdHandler } from "../services/prezziario.service"; import { getPrezziarioByIdHandler } from "../services/prezziario.service";
import { getServizioById } from "../services/servizio.service"; import { getServizioById } from "../services/servizio.service";
export const ACCONTO_TRANSITORIO = "ACCONTO_BD" as PrezziarioIdprezziario;
export const ACCONTO_STABILE = "ACCONTO_CA" as PrezziarioIdprezziario;
export type PreparedPaymentData = { export type PreparedPaymentData = {
ordine_id: OrdiniOrdineId; ordine_id: OrdiniOrdineId;
packid: PrezziarioIdprezziario; packid: PrezziarioIdprezziario;
@ -27,7 +24,10 @@ export type PreparedPaymentData = {
export const preparePayment = async ( export const preparePayment = async (
servizioId: ServizioServizioId, servizioId: ServizioServizioId,
type: OrderTypeEnum, type: OrderTypeEnum,
): Promise<{success: true, data: PreparedPaymentData} | {success:false, message: string}> => { ): Promise<
| { success: true; data: PreparedPaymentData }
| { success: false; message: string }
> => {
try { try {
const servizio = await getServizioById(servizioId); const servizio = await getServizioById(servizioId);
const inactiveOrders = await db const inactiveOrders = await db
@ -41,13 +41,12 @@ export const preparePayment = async (
switch (type) { switch (type) {
case OrderTypeEnum.Acconto: { case OrderTypeEnum.Acconto: {
if (!servizio.isOkAcconto) { if (!servizio.isOkAcconto) {
const acconto = await AccontoSolver(servizio); const acconto = await AccontoSolver(servizio.tipologia);
if (!acconto.success) { if (!acconto.success) {
return { return {
success: false, success: false,
message: `Acconto non trovato per il servizio: ${acconto.message}`, message: `Acconto non trovato per il servizio: ${acconto.message}`,
}; };
} }
if (!acconto.pack.testo_condizioni) { if (!acconto.pack.testo_condizioni) {
return { return {
@ -64,7 +63,9 @@ export const preparePayment = async (
if (preExistingAcconto) { if (preExistingAcconto) {
// acconto già creato, procedere con questo // acconto già creato, procedere con questo
return {success: true, data: { return {
success: true,
data: {
ordine_id: preExistingAcconto.ordine_id, ordine_id: preExistingAcconto.ordine_id,
packid: preExistingAcconto.packid, packid: preExistingAcconto.packid,
amount_cent: preExistingAcconto.amount_cent, amount_cent: preExistingAcconto.amount_cent,
@ -72,7 +73,8 @@ export const preparePayment = async (
packName: acconto.pack.nome_it, packName: acconto.pack.nome_it,
packDesc: acconto.pack.desc_it, packDesc: acconto.pack.desc_it,
condizioni: acconto.pack.testo_condizioni, condizioni: acconto.pack.testo_condizioni,
}}; },
};
} }
// nessun acconto preesistente, crearne uno nuovo // nessun acconto preesistente, crearne uno nuovo
@ -83,7 +85,9 @@ export const preparePayment = async (
type: OrderTypeEnum.Acconto, type: OrderTypeEnum.Acconto,
userid: servizio.user_id, userid: servizio.user_id,
}); });
return {success: true, data: { return {
success: true,
data: {
ordine_id: ordine.ordine_id, ordine_id: ordine.ordine_id,
packid: acconto.pack.idprezziario, packid: acconto.pack.idprezziario,
amount_cent: acconto.pack.prezzo_cent, amount_cent: acconto.pack.prezzo_cent,
@ -91,21 +95,22 @@ export const preparePayment = async (
packName: acconto.pack.nome_it, packName: acconto.pack.nome_it,
packDesc: acconto.pack.desc_it, packDesc: acconto.pack.desc_it,
condizioni: acconto.pack.testo_condizioni, condizioni: acconto.pack.testo_condizioni,
}}; },
};
} }
return { return {
success: false, success: false,
message: "Il servizio ha già un acconto attivo, non è possibile preparare un nuovo pagamento" message:
} "Il servizio ha già un acconto attivo, non è possibile preparare un nuovo pagamento",
};
} }
case OrderTypeEnum.Saldo: { case OrderTypeEnum.Saldo: {
if (!servizio.isOkAcconto) { if (!servizio.isOkAcconto) {
return { return {
success: false, success: false,
message: "Non è possibile procedere con il pagamento del saldo prima di aver attivato l'acconto", message:
"Non è possibile procedere con il pagamento del saldo prima di aver attivato l'acconto",
}; };
} }
if (!servizio.isOkSaldo) { if (!servizio.isOkSaldo) {
//find saldo pack based on servizio tipologia and permanenza/budget, if tipologia posizione //find saldo pack based on servizio tipologia and permanenza/budget, if tipologia posizione
@ -127,7 +132,9 @@ export const preparePayment = async (
); );
if (preExistingSaldo) { if (preExistingSaldo) {
// saldo già creato, procedere con questo // saldo già creato, procedere con questo
return{success: true, data: { return {
success: true,
data: {
ordine_id: preExistingSaldo.ordine_id, ordine_id: preExistingSaldo.ordine_id,
packid: preExistingSaldo.packid, packid: preExistingSaldo.packid,
amount_cent: preExistingSaldo.amount_cent, amount_cent: preExistingSaldo.amount_cent,
@ -135,7 +142,8 @@ export const preparePayment = async (
packName: saldo.pack.nome_it, packName: saldo.pack.nome_it,
packDesc: saldo.pack.desc_it, packDesc: saldo.pack.desc_it,
condizioni: saldo.pack.testo_condizioni, condizioni: saldo.pack.testo_condizioni,
}}; },
};
} }
// nessun saldo preesistente, crearne uno nuovo // nessun saldo preesistente, crearne uno nuovo
const ordine = await createOrdine({ const ordine = await createOrdine({
@ -145,7 +153,9 @@ export const preparePayment = async (
type: OrderTypeEnum.Saldo, type: OrderTypeEnum.Saldo,
userid: servizio.user_id, userid: servizio.user_id,
}); });
return {success: true, data: { return {
success: true,
data: {
ordine_id: ordine.ordine_id, ordine_id: ordine.ordine_id,
packid: saldo.pack.idprezziario, packid: saldo.pack.idprezziario,
amount_cent: saldo.pack.prezzo_cent, amount_cent: saldo.pack.prezzo_cent,
@ -153,19 +163,22 @@ export const preparePayment = async (
packName: saldo.pack.nome_it, packName: saldo.pack.nome_it,
packDesc: saldo.pack.desc_it, packDesc: saldo.pack.desc_it,
condizioni: saldo.pack.testo_condizioni, condizioni: saldo.pack.testo_condizioni,
}}; },
};
} }
return { return {
success: false, success: false,
message: "Il servizio ha già un saldo attivo, non è possibile preparare un nuovo pagamento" message:
} "Il servizio ha già un saldo attivo, non è possibile preparare un nuovo pagamento",
};
} }
case OrderTypeEnum.Consulenza: { case OrderTypeEnum.Consulenza: {
if (!servizio.isOkAcconto || !servizio.isOkSaldo) { if (!servizio.isOkAcconto || !servizio.isOkSaldo) {
return { return {
success: false, success: false,
message: "Non è possibile procedere con il pagamento della consulenza prima di aver attivato acconto e saldo", message:
"Non è possibile procedere con il pagamento della consulenza prima di aver attivato acconto e saldo",
}; };
} }
if (!servizio.isOkConsulenza) { if (!servizio.isOkConsulenza) {
@ -181,7 +194,7 @@ export const preparePayment = async (
return { return {
success: false, success: false,
message: `Pack della consulenza non trovato: ${existingConsulenza.packid}`, message: `Pack della consulenza non trovato: ${existingConsulenza.packid}`,
} };
} }
if (!consulenzaPack.testo_condizioni) { if (!consulenzaPack.testo_condizioni) {
return { return {
@ -205,13 +218,15 @@ export const preparePayment = async (
return { return {
success: false, success: false,
message: "Il servizio non ha un pacchetto di consulenza, è necessario inserirlo prima di procedere", message:
"Il servizio non ha un pacchetto di consulenza, è necessario inserirlo prima di procedere",
}; };
} }
return { return {
success: false, success: false,
message: "Il servizio ha già una consulenza attiva, non è possibile preparare un nuovo pagamento", message:
"Il servizio ha già una consulenza attiva, non è possibile preparare un nuovo pagamento",
}; };
} }
case OrderTypeEnum.Rinnovo: { case OrderTypeEnum.Rinnovo: {
@ -227,7 +242,7 @@ export const preparePayment = async (
return { return {
success: false, success: false,
message: `Pack del rinnovo non trovato: ${existingRinnovo.packid}`, message: `Pack del rinnovo non trovato: ${existingRinnovo.packid}`,
} };
} }
if (!rinnovoPack.testo_condizioni) { if (!rinnovoPack.testo_condizioni) {
return { return {
@ -250,7 +265,8 @@ export const preparePayment = async (
} }
return { return {
success: false, success: false,
message: "Il servizio non ha un pacchetto di rinnovo, è necessario inserirlo prima di procedere", message:
"Il servizio non ha un pacchetto di rinnovo, è necessario inserirlo prima di procedere",
}; };
} }
case OrderTypeEnum.Altro: { case OrderTypeEnum.Altro: {
@ -266,14 +282,13 @@ export const preparePayment = async (
return { return {
success: false, success: false,
message: `Pack dell'altro non trovato: ${existingAltro.packid}`, message: `Pack dell'altro non trovato: ${existingAltro.packid}`,
} };
} }
if (!altroPack.testo_condizioni) { if (!altroPack.testo_condizioni) {
return { return {
success: false, success: false,
message: `Condizioni non trovate per altro: ${altroPack.nome_it}`, message: `Condizioni non trovate per altro: ${altroPack.nome_it}`,
}; };
} }
return { return {
success: true, success: true,
@ -291,7 +306,8 @@ export const preparePayment = async (
return { return {
success: false, success: false,
message: "La preparazione del pagamento per questa tipologia non è supportata", message:
"La preparazione del pagamento per questa tipologia non è supportata",
}; };
} }
default: default:
@ -333,13 +349,13 @@ export const getPagamentoDataForCheckout = async (ordineId: OrdiniOrdineId) => {
} }
}; };
const SaldoTransitorioMapping: Record<number, PrezziarioIdprezziario> = { // const SaldoTransitorioMapping: Record<number, PrezziarioIdprezziario> = {
0: "SALDOBD_1MESE" as PrezziarioIdprezziario, // 0: "SALDOBD_1MESE" as PrezziarioIdprezziario,
1: "SALDOBD_3MESI" as PrezziarioIdprezziario, // 1: "SALDOBD_3MESI" as PrezziarioIdprezziario,
2: "SALDOBD_6MESI" as PrezziarioIdprezziario, // 2: "SALDOBD_6MESI" as PrezziarioIdprezziario,
3: "SALDOBD_9MESI" as PrezziarioIdprezziario, // 3: "SALDOBD_9MESI" as PrezziarioIdprezziario,
4: "SALDOBD_12MESI" as PrezziarioIdprezziario, // 4: "SALDOBD_12MESI" as PrezziarioIdprezziario,
}; // };
// const ConsulenzaPriceMapping = { // const ConsulenzaPriceMapping = {
// "4 + 4": "CONS_4+4" as PrezziarioIdprezziario, // "4 + 4": "CONS_4+4" as PrezziarioIdprezziario,
@ -359,12 +375,19 @@ type ServizioPacks = {
saldo: GetPackResult | GetPackError; saldo: GetPackResult | GetPackError;
}; };
const AccontoSolver = async ( export const AccontoSolver = async (
servizio: Servizio, tipologia: TipologiaPosizioneEnum,
): Promise<GetPackResult | GetPackError> => { ): Promise<GetPackResult | GetPackError> => {
switch (servizio.tipologia) { switch (tipologia) {
case TipologiaPosizioneEnum.Transitorio: { case TipologiaPosizioneEnum.Transitorio: {
const pack = await getPrezziarioByIdHandler(ACCONTO_TRANSITORIO); const pack = await db
.selectFrom("prezziario")
.selectAll()
.where("isActive", "=", true)
.where("order_type", "=", OrderTypeEnum.Acconto)
.where("service_type", "=", TipologiaPosizioneEnum.Transitorio)
.limit(1)
.executeTakeFirst();
if (!pack) { if (!pack) {
return { success: false, message: "Pack non trovato" }; return { success: false, message: "Pack non trovato" };
@ -376,7 +399,14 @@ const AccontoSolver = async (
} }
case TipologiaPosizioneEnum.Stabile: { case TipologiaPosizioneEnum.Stabile: {
const pack = await getPrezziarioByIdHandler(ACCONTO_STABILE); const pack = await db
.selectFrom("prezziario")
.selectAll()
.where("isActive", "=", true)
.where("order_type", "=", OrderTypeEnum.Acconto)
.where("service_type", "=", TipologiaPosizioneEnum.Stabile)
.limit(1)
.executeTakeFirst();
if (!pack) { if (!pack) {
return { success: false, message: "Pack non trovato" }; return { success: false, message: "Pack non trovato" };
@ -391,20 +421,34 @@ const AccontoSolver = async (
} }
}; };
export const SaldoSolver = async ( export const SaldoSolver = async ({
servizio: Servizio, tipologia,
): Promise<GetPackResult | GetPackError> => { permanenza,
switch (servizio.tipologia) { budget,
}: {
tipologia: TipologiaPosizioneEnum;
permanenza: number | null;
budget: number;
}): Promise<GetPackResult | GetPackError> => {
switch (tipologia) {
case TipologiaPosizioneEnum.Transitorio: { case TipologiaPosizioneEnum.Transitorio: {
const mpp = if (permanenza === null) {
servizio.permanenza && SaldoTransitorioMapping[servizio.permanenza];
if (!servizio.permanenza || !mpp) {
return { return {
success: false, success: false,
message: "Permanenza non selezionata", message: "Permanenza non selezionata",
}; };
} }
const pack = await getPrezziarioByIdHandler(mpp);
const pack = await db
.selectFrom("prezziario")
.selectAll()
.where("isActive", "=", true)
.where("order_type", "=", OrderTypeEnum.Saldo)
.where("service_type", "=", TipologiaPosizioneEnum.Transitorio)
.where("service_variant", "=", permanenza)
.limit(1)
.executeTakeFirst();
if (!pack) { if (!pack) {
return { success: false, message: "Pack non trovato" }; return { success: false, message: "Pack non trovato" };
} }
@ -412,13 +456,17 @@ export const SaldoSolver = async (
return { success: true, pack }; return { success: true, pack };
} }
case TipologiaPosizioneEnum.Stabile: { case TipologiaPosizioneEnum.Stabile: {
const pack = await getPrezziarioByIdHandler( const budget_step = budget > 700 ? 2 : budget > 500 ? 1 : 0;
(servizio.budget > 700 const pack = await db
? "SALDOCA700+" .selectFrom("prezziario")
: servizio.budget > 500 .selectAll()
? "SALDOCA500+" .where("isActive", "=", true)
: "SALDOCA500") as PrezziarioIdprezziario, .where("order_type", "=", OrderTypeEnum.Saldo)
); .where("service_type", "=", TipologiaPosizioneEnum.Stabile)
.where("service_variant", "=", budget_step)
.limit(1)
.executeTakeFirst();
if (!pack) { if (!pack) {
return { success: false, message: "Pack non trovato" }; return { success: false, message: "Pack non trovato" };
} }
@ -443,7 +491,11 @@ export const getPacksPerServizio = async (
}); });
} }
return { return {
acconto: await AccontoSolver(servizio), acconto: await AccontoSolver(servizio.tipologia),
saldo: await SaldoSolver(servizio), saldo: await SaldoSolver({
tipologia: servizio.tipologia,
permanenza: servizio.permanenza,
budget: servizio.budget,
}),
}; };
}; };

View file

@ -1101,7 +1101,11 @@ export const adminUpdateConfermaStatus = async ({
const servizio = await getServizioById(servizioId); const servizio = await getServizioById(servizioId);
const utente = await getUser({ db, userId: servizio.user_id }); const utente = await getUser({ db, userId: servizio.user_id });
const saldo = await SaldoSolver(servizio); const saldo = await SaldoSolver({
tipologia: servizio.tipologia,
permanenza: servizio.permanenza,
budget: servizio.budget,
});
if (saldo.success) { if (saldo.success) {
await createOrdine({ await createOrdine({
servizio_id: servizioId, servizio_id: servizioId,

View file

@ -1,5 +1,5 @@
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { sql } from "kysely"; import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { import type {
NewPrezziario, NewPrezziario,
Prezziario, Prezziario,
@ -127,20 +127,13 @@ export const getPrezziarioByTipologia = async ({
}): Promise<PrezziarioByTipologia> => { }): Promise<PrezziarioByTipologia> => {
try { try {
const { acconto, saldi } = await db.transaction().execute(async (trx) => { const { acconto, saldi } = await db.transaction().execute(async (trx) => {
let qry = trx const acconto = await trx
.selectFrom("prezziario") .selectFrom("prezziario")
.select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"]) .select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
.where("isAcconto", "=", true) .where("order_type", "=", OrderTypeEnum.Acconto)
.where("isSaldo", "=", false) .where("service_type", "=", tipologia)
.where("isActive", "=", true); .where("isActive", "=", true)
.executeTakeFirst();
if (tipologia === TipologiaPosizioneEnum.Transitorio) {
qry = qry.where("isTransitorio", "=", true);
} else if (tipologia === TipologiaPosizioneEnum.Stabile) {
qry = qry.where("isStabile", "=", true);
}
const acconto = await qry.executeTakeFirst();
if (!acconto) { if (!acconto) {
throw new TRPCError({ throw new TRPCError({
@ -148,25 +141,15 @@ export const getPrezziarioByTipologia = async ({
message: "Acconto not found", message: "Acconto not found",
}); });
} }
let qry2 = trx const saldi = await trx
.selectFrom("prezziario") .selectFrom("prezziario")
.select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"]) .select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
.where("isAcconto", "=", false) .where("order_type", "=", OrderTypeEnum.Saldo)
.where("isSaldo", "=", true) .where("service_type", "=", tipologia)
.where("isActive", "=", true); .where("isActive", "=", true)
if (tipologia === TipologiaPosizioneEnum.Transitorio) { .orderBy("service_variant", "asc")
qry2 = qry2.where("isTransitorio", "=", true);
} else if (tipologia === TipologiaPosizioneEnum.Stabile) {
qry2 = qry2.where("isStabile", "=", true);
}
// query with order by numeric part of idprezziario, handling '+' at the end
const saldi = await qry2
.orderBy(
sql`CAST(REGEXP_REPLACE(idprezziario, '[^0-9]+', '', 'g') AS INTEGER),
CASE WHEN idprezziario LIKE '%+%' THEN 1 ELSE 0 END`,
)
.execute(); .execute();
//const saldi = await qry2.orderBy("prezzo_cent", "asc").execute();
if (!saldi) { if (!saldi) {
throw new TRPCError({ throw new TRPCError({
@ -193,11 +176,9 @@ export const getPrezziarioConsulenza = async ({ db }: { db: Querier }) => {
const prezzi = await trx const prezzi = await trx
.selectFrom("prezziario") .selectFrom("prezziario")
.select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"]) .select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
.where("isConsulenza", "=", true) .where("order_type", "=", OrderTypeEnum.Consulenza)
.where("isAcconto", "=", false)
.where("isSaldo", "=", false)
.where("isActive", "=", true) .where("isActive", "=", true)
.where("isStabile", "=", true) .where("service_type", "=", TipologiaPosizioneEnum.Stabile)
.orderBy("prezzo_cent", "asc") .orderBy("prezzo_cent", "asc")
.execute(); .execute();

View file

@ -7,6 +7,7 @@ import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { getPrezziarioByIdHandler } from "./prezziario.service"; import { getPrezziarioByIdHandler } from "./prezziario.service";
import type { AnnunciId } from "~/schemas/public/Annunci"; import type { AnnunciId } from "~/schemas/public/Annunci";
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci"; import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
import { db } from "../db";
export const addServizio = async (data: NewServizio) => { export const addServizio = async (data: NewServizio) => {
try { try {
@ -19,11 +20,15 @@ export const addServizio = async (data: NewServizio) => {
() => new Error("Failed to insert new servizio into database"), () => new Error("Failed to insert new servizio into database"),
); );
const acconto = await getPrezziarioByIdHandler( const acconto = await db
data.tipologia === TipologiaPosizioneEnum.Transitorio .selectFrom("prezziario")
? ACCONTO_TRANSITORIO .selectAll()
: ACCONTO_STABILE, .where("isActive", "=", true)
); .where("order_type", "=", OrderTypeEnum.Acconto)
.where("service_type", "=", data.tipologia)
.limit(1)
.executeTakeFirst();
if (!acconto) { if (!acconto) {
throw new Error("Acconto not found for new servizio"); throw new Error("Acconto not found for new servizio");
} }

View file

@ -1,10 +1,14 @@
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import { config } from "dotenv";
import tsconfigPaths from "vite-tsconfig-paths"; import tsconfigPaths from "vite-tsconfig-paths";
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
config();
export default defineConfig({ export default defineConfig({
plugins: [tsconfigPaths(), react()], plugins: [tsconfigPaths(), react()],
test: { test: {
environment: "jsdom", environment: "node",
env: process.env,
}, },
}); });