feat: add dotenv package for environment variable management and update payment logic to use new database queries
This commit is contained in:
parent
547b1d6ce6
commit
6c53ef130c
8 changed files with 318 additions and 133 deletions
14
apps/infoalloggi/package-lock.json
generated
14
apps/infoalloggi/package-lock.json
generated
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -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,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue