Files
zibo-dashboard/public/userarea/ws_packaging_parser.php
T
2026-10-26 13:56:01 +01:00

144 lines
5.1 KiB
PHP

<?php
/**
* Lettura sezione "Imballo e confezionamento" dal foglio di lavoro Excel (mod. 7.5.1-5).
*
* $rows = foglio come array di righe, indici numerici da 0
* (es. PhpSpreadsheet: $sheet->toArray(null, true, false, false)).
* Restituisce solo le chiavi trovate:
* meters_per_package, meters_per_package_tolerance, meters_per_package_notes,
* packages_or_pieces_per_box, meters_per_box, boxes_or_packages_per_pallet
*/
function ws_parse_packaging(array $rows): array
{
$out = [];
$notes = [];
// indicizza le righe: etichetta (colonne A-C) + valori (dalla colonna D)
$list = [];
foreach ($rows as $r) {
$r = array_values((array)$r);
$label = ws_pk_norm(implode(' ', array_map('strval', array_slice($r, 0, 3))));
$vals = [];
foreach (array_slice($r, 3) as $v) {
$v = trim((string)$v);
if ($v !== '') $vals[] = $v;
}
$list[] = ['label' => $label, 'vals' => $vals];
}
$n = count($list);
for ($i = 0; $i < $n; $i++) {
$label = $list[$i]['label'];
$vals = $list[$i]['vals'];
if ($label === '') continue;
// righe successive senza etichetta (continuazione: tolleranze, note)
$extra = [];
for ($j = $i + 1; $j < $n && $list[$j]['label'] === ''; $j++) {
$extra = array_merge($extra, $list[$j]['vals']);
}
// --- metri / confezione ---
if (preg_match('/^metri\s*\/?\s*confezion/', $label)) {
$first = $vals[0] ?? '';
$num = ws_pk_int($first);
if ($num !== null) $out['meters_per_package'] = $num;
$tol = null;
foreach (array_merge(array_slice($vals, 1), $extra) as $v) {
if ($tol === null && ws_pk_is_tolerance($v)) {
$tol = ws_pk_tolerance($v);
} elseif (!ws_pk_is_tolerance($v)) {
$notes[] = $v; // es. "40x2"
}
}
// la tolleranza a volte è nella stessa cella del valore
if ($tol === null && ws_pk_is_tolerance($first)) $tol = ws_pk_tolerance($first);
if ($tol !== null) $out['meters_per_package_tolerance'] = $tol;
continue;
}
// --- n° confezioni o pezzi per scatola ---
if (strpos($label, 'per scatola') !== false && strpos($label, 'confezion') !== false) {
$num = ws_pk_int($vals[0] ?? '');
if ($num !== null) $out['packages_or_pieces_per_box'] = $num;
if (ws_pk_multi($vals[0] ?? '')) $notes[] = 'Conf. x scatola ' . $vals[0];
continue;
}
// --- metri / scatola ---
if (preg_match('/^metri\s*\/?\s*scatol/', $label)) {
$num = ws_pk_int($vals[0] ?? '');
if ($num !== null) $out['meters_per_box'] = $num;
continue;
}
// --- n° confezioni o scatole per bancale ---
if (strpos($label, 'bancale') !== false && strpos($label, 'tipo') === false) {
$num = ws_pk_int($vals[0] ?? '');
if ($num !== null) $out['boxes_or_packages_per_pallet'] = $num;
// "12 o 14": nel campo numerico va 12, il testo completo nelle note
if (ws_pk_multi($vals[0] ?? '')) $notes[] = 'Scatole x Bancale ' . $vals[0];
continue;
}
}
if ($notes) {
$out['meters_per_package_notes'] = implode('. ', array_unique($notes));
}
return $out;
}
function ws_pk_norm($s): string
{
$s = mb_strtolower(trim((string)$s), 'UTF-8');
$s = str_replace(['°', 'º'], '', $s);
return trim(preg_replace('/\s+/', ' ', $s));
}
/** primo numero intero della cella ("80", "80.0", "12 o 14", "160 m") */
function ws_pk_int($v): ?int
{
if (is_int($v) || is_float($v)) return (int)round($v);
if (preg_match('/\d+(?:[.,]\d+)?/', (string)$v, $m)) {
return (int)round((float)str_replace(',', '.', $m[0]));
}
return null;
}
/** la cella contiene più numeri alternativi? ("12 o 14", "12/14") */
function ws_pk_multi($v): bool
{
return preg_match_all('/\d+/', (string)$v) > 1;
}
function ws_pk_is_tolerance($v): bool
{
$v = mb_strtolower((string)$v, 'UTF-8');
return strpos($v, 'toll') !== false || preg_match('/[+-]\s*\d/', $v) || strpos($v, '+/-') !== false;
}
/** "Toll Metrat. + 1,5m/-0" → "-0/+1.5m" "+/- 4m" → "+/- 4m" */
function ws_pk_tolerance($v): string
{
$s = str_replace(',', '.', (string)$v);
$num = '(\d+(?:\.\d+)?)';
if (preg_match('/\+\s*\/\s*-\s*' . $num . '/', $s, $m) || preg_match('/±\s*' . $num . '/u', $s, $m)) {
return '+/- ' . ws_pk_num($m[1]) . 'm';
}
$plus = preg_match('/\+\s*' . $num . '/', $s, $mp) ? ws_pk_num($mp[1]) : null;
$minus = preg_match('/-\s*' . $num . '/', $s, $mm) ? ws_pk_num($mm[1]) : null;
if ($plus !== null || $minus !== null) {
return '-' . ($minus ?? '0') . '/+' . ($plus ?? '0') . 'm';
}
return trim((string)$v); // formato non riconosciuto: testo originale
}
function ws_pk_num($n): string
{
$f = (float)$n;
return (floor($f) == $f) ? (string)(int)$f : rtrim(rtrim(number_format($f, 2, '.', ''), '0'), '.');
}