- 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.
103 lines
3.0 KiB
PHP
103 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Support\Listini;
|
|
|
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
|
|
|
/**
|
|
* Legge il file Excel dei listini (primo foglio). Il file contiene più tabelle una
|
|
* sotto l'altra, ciascuna nella forma (misure in mm, come salvate a sistema):
|
|
*
|
|
* codice_infisso | 400 | 500 | ... ← larghezze in mm
|
|
* 400 | p | p | ... ← altezza in mm + prezzi
|
|
* ...
|
|
*
|
|
* Se la riga del titolo non contiene larghezze, l'intestazione è sulla riga successiva
|
|
* (es. "CASSONETTO PVC" seguito da "mm | 500 | 600 ...").
|
|
*/
|
|
class ListinoExcelParser
|
|
{
|
|
/**
|
|
* @return list<array{codice: string, prezzi: list<array{larghezza: int, altezza: int, prezzo: float}>}>
|
|
*/
|
|
public static function parse(string $path): array
|
|
{
|
|
$reader = IOFactory::createReader(IOFactory::identify($path));
|
|
$reader->setReadDataOnly(true);
|
|
|
|
$righe = $reader->load($path)->getSheet(0)->toArray(null, true, false, false);
|
|
|
|
return self::parseRighe($righe);
|
|
}
|
|
|
|
/**
|
|
* @param list<list<mixed>> $righe
|
|
*/
|
|
public static function parseRighe(array $righe): array
|
|
{
|
|
$blocchi = [];
|
|
$n = count($righe);
|
|
|
|
for ($r = 0; $r < $n; $r++) {
|
|
$titolo = $righe[$r][0] ?? null;
|
|
if (! is_string($titolo) || trim($titolo) === '') {
|
|
continue;
|
|
}
|
|
|
|
$intestazione = $r;
|
|
$larghezze = self::larghezze($righe[$r]);
|
|
if (! $larghezze && isset($righe[$r + 1])) {
|
|
$intestazione = $r + 1;
|
|
$larghezze = self::larghezze($righe[$r + 1]);
|
|
}
|
|
if (! $larghezze) {
|
|
continue;
|
|
}
|
|
|
|
$prezzi = [];
|
|
for ($rr = $intestazione + 1; $rr < $n; $rr++) {
|
|
$altezza = $righe[$rr][0] ?? null;
|
|
if (! is_numeric($altezza)) {
|
|
break;
|
|
}
|
|
|
|
foreach ($larghezze as $colonna => $larghezza) {
|
|
$prezzo = $righe[$rr][$colonna] ?? null;
|
|
if (! is_numeric($prezzo)) {
|
|
continue;
|
|
}
|
|
|
|
$prezzi[] = [
|
|
'larghezza' => (int) round($larghezza),
|
|
'altezza' => (int) round((float) $altezza),
|
|
'prezzo' => round((float) $prezzo, 2),
|
|
];
|
|
}
|
|
}
|
|
|
|
if ($prezzi) {
|
|
$blocchi[] = ['codice' => trim($titolo), 'prezzi' => $prezzi];
|
|
}
|
|
|
|
$r = $rr - 1;
|
|
}
|
|
|
|
return $blocchi;
|
|
}
|
|
|
|
/**
|
|
* Larghezze consecutive a partire dalla colonna B, indicizzate per colonna.
|
|
*
|
|
* @return array<int, float>
|
|
*/
|
|
private static function larghezze(array $riga): array
|
|
{
|
|
$larghezze = [];
|
|
for ($c = 1; $c < count($riga) && is_numeric($riga[$c]); $c++) {
|
|
$larghezze[$c] = (float) $riga[$c];
|
|
}
|
|
|
|
return $larghezze;
|
|
}
|
|
}
|