feat: Implement price list management and import functionality

- Added ListinoRelationManager for managing price lists associated with models.
- Introduced ImportaListiniAction for importing price lists from Excel files.
- Created ListinoPrezzo model to represent price entries in the database.
- Developed ListinoExcelParser for parsing Excel files containing price lists.
- Implemented ListinoImporter to handle the import logic and associations.
- Added migration for creating listino_prezzi table and converting measures to mm.
- Updated frontend logic to handle new price list features and validations.
- Enhanced tests for price list import and conversion functionalities.
This commit is contained in:
2026-10-19 16:51:24 +02:00
parent a8aa6d9927
commit 1e352eb2ef
46 changed files with 1575 additions and 327 deletions
+16 -13
View File
@@ -25,24 +25,27 @@ const PriceCalculator = {
return firstSize;
},
// Misure in mm: entro min/max del listino si usa la prima misura >= a quella
// richiesta (le griglie non sono sempre a passo regolare, es. traslanti da 1450 mm).
getGridPrice: (width, height) => {
let altezza = parseFloat(height);
let larghezza = parseFloat(width);
const larghezza = PriceCalculator.misuraListino('larghezza', width);
const altezza = PriceCalculator.misuraListino('altezza', height);
if (larghezza == null || altezza == null) return -1;
const misure = listini.misure.find(el => el.altezza == altezza && el.larghezza == larghezza);
let mod_altezza = altezza % 10;
let mod_larghezza = larghezza % 10;
if(mod_altezza > 0) altezza = (altezza - mod_altezza) + 10;
if(mod_larghezza > 0) larghezza = (larghezza - mod_larghezza) + 10;
let misure = listini.misure.find((el) => {
if(el.altezza == altezza && el.larghezza == larghezza)
return el;
});
if(misure == null) return -1;
return misure.prezzo;
},
misuraListino: (campo, valore) => {
const v = parseFloat(valore);
if (isNaN(v)) return null;
const misure = [...new Set(listini.misure.map(el => el[campo]))].sort((a, b) => a - b);
// Min/max del listino vincolanti: fuori range la misura non è disponibile.
if (!misure.length || v < misure[0]) return null;
return misure.find(m => m >= v) ?? null;
},
getConfigurationPrice: (data) => {
let prezzo_finale = data.prezzo_base;