1052 lines
47 KiB
PHP
1052 lines
47 KiB
PHP
<?php
|
||
ob_start(); // buffer any accidental output
|
||
ini_set('display_errors', 1);
|
||
error_reporting(E_ALL);
|
||
|
||
include('include/headscript.php');
|
||
|
||
$db = DBHandlerSelect::getInstance();
|
||
$pdo = $db->getConnection();
|
||
|
||
$worksheet_id = isset($_GET['id']) && is_numeric($_GET['id']) ? (int)$_GET['id'] : 0;
|
||
|
||
// AJAX HANDLERS
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||
// Ensure clean JSON output (remove any echoed HTML/notices)
|
||
while (ob_get_level()) {
|
||
ob_end_clean();
|
||
}
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
|
||
header('Content-Type: application/json');
|
||
|
||
$action = $_POST['action'] ?? '';
|
||
|
||
try {
|
||
// Save header (insert/update)
|
||
if ($action === 'save_header') {
|
||
$idmatrice = (int)($_POST['idmatrice'] ?? 0);
|
||
if ($idmatrice <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'Seleziona una matrice/profilo']);
|
||
exit;
|
||
}
|
||
|
||
$id = (int)($_POST['id'] ?? 0);
|
||
|
||
$worksheet_date = $_POST['worksheet_date'] !== '' ? $_POST['worksheet_date'] : null;
|
||
$customer_name = trim($_POST['customer_name'] ?? '');
|
||
$profile_code = trim($_POST['profile_type_code'] ?? '');
|
||
$marking = ($_POST['marking'] ?? '') !== '' ? $_POST['marking'] : null;
|
||
|
||
$prod_control = trim($_POST['prod_control_measure_settings'] ?? '');
|
||
|
||
$freq_cut = trim($_POST['control_frequency_cut'] ?? '');
|
||
$freq_draw = trim($_POST['control_frequency_drawing'] ?? '');
|
||
$freq_jig = trim($_POST['control_frequency_jig'] ?? '');
|
||
$mode_jig = trim($_POST['control_mode_jig'] ?? '');
|
||
|
||
$box_type = trim($_POST['box_type'] ?? '');
|
||
$pkg_box = $_POST['packages_or_pieces_per_box'] !== '' ? (int)$_POST['packages_or_pieces_per_box'] : null;
|
||
$m_box = $_POST['meters_per_box'] !== '' ? (int)$_POST['meters_per_box'] : null;
|
||
|
||
$pallet_type = trim($_POST['pallet_type'] ?? '');
|
||
$per_pallet = $_POST['boxes_or_packages_per_pallet'] !== '' ? (int)$_POST['boxes_or_packages_per_pallet'] : null;
|
||
|
||
$sp_exp_kg = $_POST['speed_expected_kg_h'] !== '' ? (float)$_POST['speed_expected_kg_h'] : null;
|
||
$sp_act_kg = $_POST['speed_actual_kg_h'] !== '' ? (float)$_POST['speed_actual_kg_h'] : null;
|
||
$sp_exp_m = $_POST['speed_expected_m_h'] !== '' ? (float)$_POST['speed_expected_m_h'] : null;
|
||
$sp_act_m = $_POST['speed_actual_m_h'] !== '' ? (float)$_POST['speed_actual_m_h'] : null;
|
||
|
||
$approved_by = trim($_POST['approved_by'] ?? '');
|
||
$notes = trim($_POST['notes'] ?? '');
|
||
|
||
if ($id > 0) {
|
||
$stmt = $pdo->prepare("
|
||
UPDATE work_sheets SET
|
||
idmatrice = ?,
|
||
worksheet_date = ?,
|
||
customer_name = ?,
|
||
profile_type_code = ?,
|
||
marking = ?,
|
||
prod_control_measure_settings = ?,
|
||
control_frequency_cut = ?,
|
||
control_frequency_drawing = ?,
|
||
control_frequency_jig = ?,
|
||
control_mode_jig = ?,
|
||
box_type = ?,
|
||
packages_or_pieces_per_box = ?,
|
||
meters_per_box = ?,
|
||
pallet_type = ?,
|
||
boxes_or_packages_per_pallet = ?,
|
||
speed_expected_kg_h = ?,
|
||
speed_actual_kg_h = ?,
|
||
speed_expected_m_h = ?,
|
||
speed_actual_m_h = ?,
|
||
approved_by = ?,
|
||
notes = ?
|
||
WHERE id = ?
|
||
");
|
||
$stmt->execute([
|
||
$idmatrice,
|
||
$worksheet_date,
|
||
$customer_name !== '' ? $customer_name : null,
|
||
$profile_code !== '' ? $profile_code : null,
|
||
$marking,
|
||
$prod_control !== '' ? $prod_control : null,
|
||
$freq_cut !== '' ? $freq_cut : null,
|
||
$freq_draw !== '' ? $freq_draw : null,
|
||
$freq_jig !== '' ? $freq_jig : null,
|
||
$mode_jig !== '' ? $mode_jig : null,
|
||
$box_type !== '' ? $box_type : null,
|
||
$pkg_box,
|
||
$m_box,
|
||
$pallet_type !== '' ? $pallet_type : null,
|
||
$per_pallet,
|
||
$sp_exp_kg,
|
||
$sp_act_kg,
|
||
$sp_exp_m,
|
||
$sp_act_m,
|
||
$approved_by !== '' ? $approved_by : null,
|
||
$notes !== '' ? $notes : null,
|
||
$id
|
||
]);
|
||
|
||
echo json_encode(['success' => true, 'id' => $id]);
|
||
exit;
|
||
}
|
||
|
||
$stmt = $pdo->prepare("
|
||
INSERT INTO work_sheets
|
||
(idmatrice, worksheet_date, customer_name, profile_type_code, marking,
|
||
prod_control_measure_settings, control_frequency_cut, control_frequency_drawing, control_frequency_jig, control_mode_jig,
|
||
box_type, packages_or_pieces_per_box, meters_per_box,
|
||
pallet_type, boxes_or_packages_per_pallet,
|
||
speed_expected_kg_h, speed_actual_kg_h, speed_expected_m_h, speed_actual_m_h,
|
||
approved_by, notes)
|
||
VALUES
|
||
(?, ?, ?, ?, ?,
|
||
?, ?, ?, ?, ?,
|
||
?, ?, ?,
|
||
?, ?,
|
||
?, ?, ?, ?,
|
||
?, ?)
|
||
");
|
||
$stmt->execute([
|
||
$idmatrice,
|
||
$worksheet_date,
|
||
$customer_name !== '' ? $customer_name : null,
|
||
$profile_code !== '' ? $profile_code : null,
|
||
$marking,
|
||
$prod_control !== '' ? $prod_control : null,
|
||
$freq_cut !== '' ? $freq_cut : null,
|
||
$freq_draw !== '' ? $freq_draw : null,
|
||
$freq_jig !== '' ? $freq_jig : null,
|
||
$mode_jig !== '' ? $mode_jig : null,
|
||
$box_type !== '' ? $box_type : null,
|
||
$pkg_box,
|
||
$m_box,
|
||
$pallet_type !== '' ? $pallet_type : null,
|
||
$per_pallet,
|
||
$sp_exp_kg,
|
||
$sp_act_kg,
|
||
$sp_exp_m,
|
||
$sp_act_m,
|
||
$approved_by !== '' ? $approved_by : null,
|
||
$notes !== '' ? $notes : null
|
||
]);
|
||
|
||
$newId = (int)$pdo->lastInsertId();
|
||
echo json_encode(['success' => true, 'id' => $newId]);
|
||
exit;
|
||
}
|
||
|
||
// Add or edit mix row
|
||
if ($action === 'save_mix_row') {
|
||
$worksheet_id = (int)($_POST['worksheet_id'] ?? 0);
|
||
if ($worksheet_id <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'Salva prima il foglio (testata)']);
|
||
exit;
|
||
}
|
||
|
||
$row_id = (int)($_POST['row_id'] ?? 0);
|
||
$idmescola = (int)($_POST['idmescola'] ?? 0);
|
||
$pos = 0; // auto-assign
|
||
|
||
|
||
if ($idmescola <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'Seleziona una mescola']);
|
||
exit;
|
||
}
|
||
if ($pos <= 0) $pos = 1;
|
||
|
||
$mix_weight = $_POST['mix_weight_g_m'] !== '' ? (float)$_POST['mix_weight_g_m'] : null;
|
||
$density = trim($_POST['required_density'] ?? '');
|
||
$hardness = trim($_POST['required_hardness_shore_a'] ?? '');
|
||
|
||
$lub_type = ($_POST['lubrication_type'] ?? '') !== '' ? $_POST['lubrication_type'] : null;
|
||
$lub_note = trim($_POST['lubrication_notes'] ?? '');
|
||
|
||
$pkg_code = trim($_POST['requested_package_code'] ?? '');
|
||
$m_pkg = $_POST['meters_per_package'] !== '' ? (int)$_POST['meters_per_package'] : null;
|
||
$m_pkg_note = trim($_POST['meters_per_package_notes'] ?? '');
|
||
$m_pkg_tol = trim($_POST['meters_per_package_tolerance'] ?? '');
|
||
|
||
// Use transaction to keep constraints consistent
|
||
$pdo->beginTransaction();
|
||
|
||
if ($row_id > 0) {
|
||
|
||
// Auto-assign mix_position = max + 1 for this worksheet
|
||
$stmtPos = $pdo->prepare("
|
||
SELECT IFNULL(MAX(mix_position), 0) + 1
|
||
FROM work_sheet_mescole
|
||
WHERE worksheet_id = ?
|
||
FOR UPDATE
|
||
");
|
||
$stmtPos->execute([$worksheet_id]);
|
||
$pos = (int)$stmtPos->fetchColumn();
|
||
if ($pos <= 0) $pos = 1;
|
||
|
||
|
||
$stmt = $pdo->prepare("
|
||
UPDATE work_sheet_mescole SET
|
||
idmescola = ?,
|
||
mix_weight_g_m = ?,
|
||
required_density = ?,
|
||
required_hardness_shore_a = ?,
|
||
lubrication_type = ?,
|
||
lubrication_notes = ?,
|
||
requested_package_code = ?,
|
||
meters_per_package = ?,
|
||
meters_per_package_notes = ?,
|
||
meters_per_package_tolerance = ?
|
||
WHERE id = ? AND worksheet_id = ?
|
||
");
|
||
|
||
$stmt->execute([
|
||
$idmescola,
|
||
$mix_weight,
|
||
$density !== '' ? $density : null,
|
||
$hardness !== '' ? $hardness : null,
|
||
$lub_type,
|
||
$lub_note !== '' ? $lub_note : null,
|
||
$pkg_code !== '' ? $pkg_code : null,
|
||
$m_pkg,
|
||
$m_pkg_note !== '' ? $m_pkg_note : null,
|
||
$m_pkg_tol !== '' ? $m_pkg_tol : null,
|
||
$row_id,
|
||
$worksheet_id
|
||
]);
|
||
|
||
|
||
$pdo->commit();
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
}
|
||
|
||
// If position already used, auto-assign next (max+1)
|
||
$chk = $pdo->prepare("SELECT COUNT(*) FROM work_sheet_mescole WHERE worksheet_id = ? AND mix_position = ?");
|
||
$chk->execute([$worksheet_id, $pos]);
|
||
if ((int)$chk->fetchColumn() > 0) {
|
||
$mx = $pdo->prepare("SELECT IFNULL(MAX(mix_position),0) + 1 FROM work_sheet_mescole WHERE worksheet_id = ?");
|
||
$mx->execute([$worksheet_id]);
|
||
$pos = (int)$mx->fetchColumn();
|
||
}
|
||
|
||
|
||
|
||
$stmt = $pdo->prepare("
|
||
INSERT INTO work_sheet_mescole
|
||
(worksheet_id, idmescola, mix_position, mix_weight_g_m, required_density, required_hardness_shore_a,
|
||
lubrication_type, lubrication_notes,
|
||
requested_package_code, meters_per_package, meters_per_package_notes, meters_per_package_tolerance)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||
");
|
||
$stmt->execute([
|
||
$worksheet_id,
|
||
$idmescola,
|
||
$pos,
|
||
$mix_weight,
|
||
$density !== '' ? $density : null,
|
||
$hardness !== '' ? $hardness : null,
|
||
$lub_type,
|
||
$lub_note !== '' ? $lub_note : null,
|
||
$pkg_code !== '' ? $pkg_code : null,
|
||
$m_pkg,
|
||
$m_pkg_note !== '' ? $m_pkg_note : null,
|
||
$m_pkg_tol !== '' ? $m_pkg_tol : null
|
||
]);
|
||
|
||
$pdo->commit();
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
}
|
||
|
||
// Delete mix row
|
||
if ($action === 'delete_mix_row') {
|
||
$row_id = (int)($_POST['row_id'] ?? 0);
|
||
if ($row_id <= 0) {
|
||
echo json_encode(['success' => false, 'message' => 'ID riga non valido']);
|
||
exit;
|
||
}
|
||
|
||
$stmt = $pdo->prepare("DELETE FROM work_sheet_mescole WHERE id = ?");
|
||
$stmt->execute([$row_id]);
|
||
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
}
|
||
|
||
echo json_encode(['success' => false, 'message' => 'Azione sconosciuta']);
|
||
exit;
|
||
} catch (Exception $e) {
|
||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
||
exit;
|
||
}
|
||
}
|
||
|
||
// Load matrices dropdown
|
||
$matrici = $pdo->query("
|
||
SELECT id, nome, cliente
|
||
FROM matrice
|
||
ORDER BY nome ASC
|
||
")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
// Load worksheet lookup options
|
||
$lookup = [];
|
||
$lookupDefault = [];
|
||
|
||
$stmt = $pdo->prepare("
|
||
SELECT category, value, label, is_default
|
||
FROM ws_lookup_options
|
||
WHERE is_active = 1
|
||
ORDER BY category ASC, sort_order ASC, label ASC
|
||
");
|
||
$stmt->execute();
|
||
|
||
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||
$lookup[$r['category']][] = $r;
|
||
|
||
if ((int)$r['is_default'] === 1 && !isset($lookupDefault[$r['category']])) {
|
||
$lookupDefault[$r['category']] = $r['value'];
|
||
}
|
||
}
|
||
|
||
|
||
// Load mescole dropdown for modal
|
||
$mescole = $pdo->query("
|
||
SELECT id, nome, nomeuscita
|
||
FROM mescole
|
||
ORDER BY nome ASC
|
||
")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
// Load worksheet (edit)
|
||
$worksheet = null;
|
||
$mixRows = [];
|
||
|
||
if ($worksheet_id > 0) {
|
||
$stmt = $pdo->prepare("
|
||
SELECT ws.*, m.nome AS matrice_nome
|
||
FROM work_sheets ws
|
||
LEFT JOIN matrice m ON ws.idmatrice = m.id
|
||
WHERE ws.id = ?
|
||
");
|
||
$stmt->execute([$worksheet_id]);
|
||
$worksheet = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if ($worksheet) {
|
||
$stmt = $pdo->prepare("
|
||
SELECT
|
||
wsm.*,
|
||
me.nome AS mescola_nome,
|
||
me.nomeuscita AS mescola_uscita
|
||
FROM work_sheet_mescole wsm
|
||
LEFT JOIN mescole me ON me.id = wsm.idmescola
|
||
WHERE wsm.worksheet_id = ?
|
||
ORDER BY wsm.mix_position ASC, wsm.id ASC
|
||
");
|
||
$stmt->execute([$worksheet_id]);
|
||
$mixRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||
} else {
|
||
$worksheet_id = 0;
|
||
}
|
||
}
|
||
|
||
// Helpers
|
||
function h($v)
|
||
{
|
||
return htmlspecialchars((string)$v, ENT_QUOTES);
|
||
}
|
||
|
||
function ws_options($rows, $selectedValue, $defaultValue = '')
|
||
{
|
||
$selectedValue = (string)$selectedValue;
|
||
if ($selectedValue === '' && $defaultValue !== '') {
|
||
$selectedValue = (string)$defaultValue;
|
||
}
|
||
|
||
$html = '<option value="">--</option>';
|
||
if (!$rows) return $html;
|
||
|
||
foreach ($rows as $r) {
|
||
$val = h($r['value']);
|
||
$lab = h($r['label']);
|
||
$sel = ((string)$r['value'] === $selectedValue) ? ' selected' : '';
|
||
$html .= "<option value=\"{$val}\"{$sel}>{$lab}</option>";
|
||
}
|
||
return $html;
|
||
}
|
||
|
||
$isEdit = ($worksheet_id > 0);
|
||
?>
|
||
|
||
<!doctype html>
|
||
<html lang="it">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<?php include('cssinclude.php'); ?>
|
||
<title><?= $isEdit ? 'Modifica Foglio di Lavoro' : 'Nuovo Foglio di Lavoro' ?></title>
|
||
|
||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||
|
||
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
|
||
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
|
||
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
|
||
|
||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
||
<link href="https://cdn.jsdelivr.net/npm/@ttskch/select2-bootstrap4-theme@1.5.2/dist/select2-bootstrap4.min.css" rel="stylesheet" />
|
||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||
|
||
|
||
<style>
|
||
body {
|
||
font-size: 0.95rem;
|
||
background: #f8fafc;
|
||
}
|
||
|
||
.card {
|
||
border-radius: 16px;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.back-dashboard {
|
||
background: #cfe3ff !important;
|
||
color: #1f2d3d !important;
|
||
border: 1px solid #bcd4f4 !important;
|
||
border-radius: 10px;
|
||
font-weight: 600;
|
||
padding: 10px 18px;
|
||
}
|
||
|
||
.btn-add {
|
||
background: #0d6efd;
|
||
color: white;
|
||
border-radius: 8px;
|
||
padding: 10px 20px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.table thead {
|
||
background: #cfe3ff;
|
||
color: #1f2d3d;
|
||
}
|
||
|
||
.modal-content {
|
||
border-radius: 16px;
|
||
}
|
||
|
||
.section-title {
|
||
font-weight: 700;
|
||
color: #1f2d3d;
|
||
}
|
||
|
||
.small-hint {
|
||
color: #6b7280;
|
||
font-size: 0.85rem;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<div class="wrapper toggled">
|
||
<?php include('include/navbar.php'); ?>
|
||
<?php include('include/topbar.php'); ?>
|
||
|
||
<div class="page-wrapper">
|
||
<div class="page-content">
|
||
|
||
<div class="card p-3">
|
||
<div class="card-header d-flex justify-content-between align-items-center">
|
||
<div>
|
||
<h5 class="mb-0"><?= $isEdit ? 'Modifica Foglio di Lavoro' : 'Nuovo Foglio di Lavoro' ?></h5>
|
||
<div class="small-hint">Prima salva la testata, poi aggiungi le mescole con il modale</div>
|
||
</div>
|
||
<div class="d-flex gap-2">
|
||
<button class="btn back-dashboard" onclick="location.href='worksheets.php'">↩️ Storico</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card-body">
|
||
<!-- HEADER FORM -->
|
||
<form id="worksheetHeaderForm">
|
||
<input type="hidden" name="id" id="wsId" value="<?= (int)$worksheet_id ?>">
|
||
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label class="form-label fw-semibold">Matrice / Profilo *</label>
|
||
<select class="form-select" name="idmatrice" id="idmatrice" required>
|
||
<option value="">-- Seleziona --</option>
|
||
<?php foreach ($matrici as $m): ?>
|
||
<option value="<?= (int)$m['id'] ?>"
|
||
<?= $worksheet && (int)$worksheet['idmatrice'] === (int)$m['id'] ? 'selected' : '' ?>>
|
||
<?= h($m['nome']) ?><?= $m['cliente'] ? ' — ' . h($m['cliente']) : '' ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Data foglio</label>
|
||
<input type="date" class="form-control" name="worksheet_date"
|
||
value="<?= $worksheet ? h($worksheet['worksheet_date']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Codice profilo</label>
|
||
<input type="text" class="form-control" name="profile_type_code"
|
||
value="<?= $worksheet ? h($worksheet['profile_type_code']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label fw-semibold">Cliente (override)</label>
|
||
<input type="text" class="form-control" name="customer_name"
|
||
value="<?= $worksheet ? h($worksheet['customer_name']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Marchiatura</label>
|
||
<select class="form-select" name="marking" id="marking">
|
||
<?= ws_options($lookup['marking'] ?? [], $worksheet['marking'] ?? '', $lookupDefault['marking'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Visto / Approvazione</label>
|
||
<input type="text" class="form-control" name="approved_by"
|
||
value="<?= $worksheet ? h($worksheet['approved_by']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<label class="form-label fw-semibold">Impostazione misure controllo produzione</label>
|
||
<textarea class="form-control" name="prod_control_measure_settings" rows="2"><?= $worksheet ? h($worksheet['prod_control_measure_settings']) : '' ?></textarea>
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Controlli - Taglio</label>
|
||
<select class="form-select" name="control_frequency_cut" id="control_frequency_cut">
|
||
<?= ws_options($lookup['control_frequency_cut'] ?? [], $worksheet['control_frequency_cut'] ?? '', $lookupDefault['control_frequency_cut'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Controlli - Disegno</label>
|
||
<select class="form-select" name="control_frequency_drawing" id="control_frequency_drawing">
|
||
<?= ws_options($lookup['control_frequency_drawing'] ?? [], $worksheet['control_frequency_drawing'] ?? '', $lookupDefault['control_frequency_drawing'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Controlli - Dima</label>
|
||
<select class="form-select" name="control_frequency_jig" id="control_frequency_jig">
|
||
<?= ws_options($lookup['control_frequency_jig'] ?? [], $worksheet['control_frequency_jig'] ?? '', $lookupDefault['control_frequency_jig'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Modalità dima</label>
|
||
<select class="form-select" name="control_mode_jig" id="control_mode_jig">
|
||
<?= ws_options($lookup['control_mode_jig'] ?? [], $worksheet['control_mode_jig'] ?? '', $lookupDefault['control_mode_jig'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Scatola (tipo)</label>
|
||
<select class="form-select" name="box_type" id="box_type">
|
||
<?= ws_options($lookup['box_type'] ?? [], $worksheet['box_type'] ?? '', $lookupDefault['box_type'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">N° conf./pezzi per scatola</label>
|
||
<input type="number" class="form-control" name="packages_or_pieces_per_box"
|
||
value="<?= $worksheet ? h($worksheet['packages_or_pieces_per_box']) : '' ?>">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Metri per scatola</label>
|
||
<input type="number" class="form-control" name="meters_per_box"
|
||
value="<?= $worksheet ? h($worksheet['meters_per_box']) : '' ?>">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Bancale (tipo)</label>
|
||
<select class="form-select" name="pallet_type" id="pallet_type">
|
||
<?= ws_options($lookup['pallet_type'] ?? [], $worksheet['pallet_type'] ?? '', $lookupDefault['pallet_type'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Scatole/conf. per bancale</label>
|
||
<input type="number" class="form-control" name="boxes_or_packages_per_pallet"
|
||
value="<?= $worksheet ? h($worksheet['boxes_or_packages_per_pallet']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Vel. prevista (kg/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_expected_kg_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_expected_kg_h']) : '' ?>">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Vel. effettiva (kg/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_actual_kg_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_actual_kg_h']) : '' ?>">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Vel. prevista (m/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_expected_m_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_expected_m_h']) : '' ?>">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label fw-semibold">Vel. effettiva (m/h)</label>
|
||
<input type="number" step="0.01" class="form-control" name="speed_actual_m_h"
|
||
value="<?= $worksheet ? h($worksheet['speed_actual_m_h']) : '' ?>">
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<label class="form-label fw-semibold">Note</label>
|
||
<textarea class="form-control" name="notes" rows="2"><?= $worksheet ? h($worksheet['notes']) : '' ?></textarea>
|
||
</div>
|
||
|
||
<div class="col-12 d-flex justify-content-center gap-2 mt-2">
|
||
<button type="submit" class="btn btn-add">💾 Salva Testata</button>
|
||
<button type="button" class="btn btn-outline-primary"
|
||
id="btnAddMix" data-bs-toggle="modal" data-bs-target="#mixModal" disabled>
|
||
➕ Aggiungi Mescola
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<hr class="my-4">
|
||
|
||
<!-- MIX ROWS TABLE -->
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<div class="section-title">Mescole associate al foglio</div>
|
||
<div class="small-hint">Usa “Aggiungi Mescola” per inserire una o più righe</div>
|
||
</div>
|
||
|
||
<div class="table-responsive">
|
||
<table id="tabellaMixRows" class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th>Pos</th>
|
||
<th>Mescola</th>
|
||
<th>Peso (g/m)</th>
|
||
<th>Densità</th>
|
||
<th>Durezza</th>
|
||
<th>Lubr.</th>
|
||
<th>Confez.</th>
|
||
<th>m/conf.</th>
|
||
<th>Azioni</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($mixRows as $r): ?>
|
||
<tr>
|
||
<td><?= (int)$r['mix_position'] ?></td>
|
||
<td>
|
||
<?= h($r['mescola_nome'] ?? '-') ?>
|
||
<?php if (!empty($r['mescola_uscita'])): ?>
|
||
<div class="small-hint"><?= h($r['mescola_uscita']) ?></div>
|
||
<?php endif; ?>
|
||
</td>
|
||
<td><?= h($r['mix_weight_g_m'] ?? '-') ?></td>
|
||
<td><?= h($r['required_density'] ?? '-') ?></td>
|
||
<td><?= h($r['required_hardness_shore_a'] ?? '-') ?></td>
|
||
<td><?= h($r['lubrication_type'] ?? '-') ?></td>
|
||
<td><?= h($r['requested_package_code'] ?? '-') ?></td>
|
||
<td><?= h($r['meters_per_package'] ?? '-') ?></td>
|
||
<td class="text-nowrap">
|
||
<button class="btn btn-sm btn-outline-primary edit-mix"
|
||
data-row='<?= h(json_encode($r, JSON_UNESCAPED_UNICODE)) ?>'>
|
||
✏️ Modifica
|
||
</button>
|
||
<button class="btn btn-sm btn-outline-danger delete-mix"
|
||
data-id="<?= (int)$r['id'] ?>">
|
||
🗑️
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<?php include('include/footer.php'); ?>
|
||
</div>
|
||
|
||
<!-- MODAL MIX -->
|
||
<div class="modal fade" id="mixModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header" style="background:#cfe3ff;">
|
||
<h5 class="modal-title" id="mixModalTitle">Aggiungi Mescola</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="mixForm">
|
||
<input type="hidden" name="worksheet_id" id="mixWorksheetId" value="<?= (int)$worksheet_id ?>">
|
||
<input type="hidden" name="row_id" id="mixRowId" value="0">
|
||
|
||
<div class="row g-3">
|
||
<div class="col-md-8">
|
||
<label class="form-label fw-semibold">Mescola *</label>
|
||
<select class="form-select" name="idmescola" id="idmescola" required>
|
||
<option value="">-- Seleziona --</option>
|
||
<?php foreach ($mescole as $me): ?>
|
||
<option value="<?= (int)$me['id'] ?>">
|
||
<?= h($me['nome']) ?><?= $me['nomeuscita'] ? ' — ' . h($me['nomeuscita']) : '' ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<input type="hidden" name="mix_position" id="mix_position" value="">
|
||
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Peso metro mescola (g/m)</label>
|
||
<input type="number" step="0.01" class="form-control" name="mix_weight_g_m" id="mix_weight_g_m">
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Densità richiesta</label>
|
||
<input type="text" class="form-control" name="required_density" id="required_density" placeholder="es. 1,22 +/- 0,03">
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Durezza richiesta (shore A)</label>
|
||
<input type="text" class="form-control" name="required_hardness_shore_a" id="required_hardness_shore_a" placeholder="es. 70 +/- 5">
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Lubrificazione</label>
|
||
<select class="form-select" name="lubrication_type" id="lubrication_type">
|
||
<?= ws_options($lookup['lubrication_type'] ?? [], '', $lookupDefault['lubrication_type'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
|
||
<div class="col-md-8">
|
||
<label class="form-label fw-semibold">Note lubrificazione</label>
|
||
<input type="text" class="form-control" name="lubrication_notes" id="lubrication_notes">
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Codice confezione</label>
|
||
<select class="form-select" name="requested_package_code" id="requested_package_code">
|
||
<?= ws_options($lookup['requested_package_code'] ?? [], '', $lookupDefault['requested_package_code'] ?? '') ?>
|
||
</select>
|
||
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Metri per confezione</label>
|
||
<input type="number" class="form-control" name="meters_per_package" id="meters_per_package">
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Tolleranza metri/confezione</label>
|
||
<input type="text" class="form-control" name="meters_per_package_tolerance" id="meters_per_package_tolerance" placeholder="es. +/- 4m">
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<label class="form-label fw-semibold">Note metri/confezione</label>
|
||
<input type="text" class="form-control" name="meters_per_package_notes" id="meters_per_package_notes">
|
||
</div>
|
||
|
||
<div class="col-12 text-center mt-2">
|
||
<button type="submit" class="btn btn-add">💾 Salva Mescola</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php include('jsinclude.php'); ?>
|
||
|
||
<script>
|
||
$(document).ready(function() {
|
||
|
||
const wsIdInput = $('#wsId');
|
||
const btnAddMix = $('#btnAddMix');
|
||
|
||
if ($('#idmatrice').length) {
|
||
$('#idmatrice').select2({
|
||
theme: 'bootstrap4',
|
||
width: '100%',
|
||
placeholder: '-- Seleziona --',
|
||
allowClear: true
|
||
});
|
||
}
|
||
|
||
$('#mixModal').on('shown.bs.modal', function() {
|
||
if (!$('#idmescola').data('select2')) {
|
||
$('#idmescola').select2({
|
||
theme: 'bootstrap4',
|
||
width: '100%',
|
||
dropdownParent: $('#mixModal'),
|
||
placeholder: '-- Seleziona --',
|
||
allowClear: true
|
||
});
|
||
}
|
||
});
|
||
|
||
|
||
function enableMixButtonIfSaved() {
|
||
const id = parseInt(wsIdInput.val() || '0', 10);
|
||
if (id > 0) {
|
||
btnAddMix.prop('disabled', false);
|
||
$('#mixWorksheetId').val(id);
|
||
} else {
|
||
btnAddMix.prop('disabled', true);
|
||
$('#mixWorksheetId').val('0');
|
||
}
|
||
}
|
||
enableMixButtonIfSaved();
|
||
|
||
$('#tabellaMixRows').DataTable({
|
||
pageLength: 25,
|
||
lengthMenu: [10, 25, 50, 100],
|
||
order: [
|
||
[0, 'asc']
|
||
],
|
||
language: {
|
||
url: 'https://cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json'
|
||
}
|
||
});
|
||
|
||
// Save header
|
||
$('#worksheetHeaderForm').on('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const formData = new FormData(this);
|
||
formData.append('ajax', '1');
|
||
formData.append('action', 'save_header');
|
||
|
||
fetch(window.location.href, {
|
||
method: 'POST',
|
||
body: new URLSearchParams(formData)
|
||
})
|
||
.then(async (r) => {
|
||
const text = await r.text();
|
||
|
||
// Debug: if server returns warnings/HTML, you'll see it in console
|
||
try {
|
||
return JSON.parse(text);
|
||
} catch (err) {
|
||
console.error('Response is not valid JSON:', text);
|
||
throw new Error('Risposta non JSON (vedi console)');
|
||
}
|
||
})
|
||
.then(data => {
|
||
if (!data.success) {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore',
|
||
text: data.message
|
||
});
|
||
return;
|
||
}
|
||
|
||
wsIdInput.val(data.id);
|
||
enableMixButtonIfSaved();
|
||
|
||
// If new, update URL to edit mode
|
||
if (!window.location.search.includes('id=')) {
|
||
const newUrl = 'manage-worksheet.php?id=' + data.id;
|
||
window.history.replaceState({}, '', newUrl);
|
||
}
|
||
|
||
// ✅ What you want: confirm + stay on page + open modal if user wants
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Testata salvata',
|
||
text: 'Vuoi aggiungere subito le mescole?',
|
||
showCancelButton: true,
|
||
confirmButtonText: 'Sì, aggiungi mescole',
|
||
cancelButtonText: 'No'
|
||
}).then(res => {
|
||
if (res.isConfirmed) {
|
||
const modal = new bootstrap.Modal(document.getElementById('mixModal'));
|
||
modal.show();
|
||
}
|
||
});
|
||
})
|
||
.catch(err => {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore AJAX',
|
||
text: err.message
|
||
});
|
||
});
|
||
});
|
||
|
||
|
||
// Prepare modal for add
|
||
$('#mixModal').on('show.bs.modal', function() {
|
||
const wsId = parseInt(wsIdInput.val() || '0', 10);
|
||
if (wsId <= 0) {
|
||
Swal.fire({
|
||
icon: 'warning',
|
||
title: 'Salva prima la testata',
|
||
timer: 1200
|
||
});
|
||
return false;
|
||
}
|
||
|
||
// Reset for add by default
|
||
$('#mixModalTitle').text('Aggiungi Mescola');
|
||
$('#mixForm')[0].reset();
|
||
$('#mixRowId').val('0');
|
||
$('#mixWorksheetId').val(wsId);
|
||
$('#idmescola').prop('disabled', false);
|
||
});
|
||
|
||
// Edit mix row
|
||
$(document).on('click', '.edit-mix', function() {
|
||
let row = $(this).attr('data-row');
|
||
row = JSON.parse(row);
|
||
|
||
// Titolo modale
|
||
$('#mixModalTitle').text('Modifica Mescola');
|
||
|
||
// NON resettare in "add"
|
||
$('#mixForm')[0].reset();
|
||
|
||
// Set id riga e worksheet
|
||
$('#mixRowId').val(row.id);
|
||
$('#mixWorksheetId').val(row.worksheet_id);
|
||
|
||
// Mescola (se usi select2 devi triggerare change)
|
||
$('#idmescola').prop('disabled', false);
|
||
$('#idmescola').val(row.idmescola).trigger('change');
|
||
|
||
// Campi
|
||
$('#mix_weight_g_m').val(row.mix_weight_g_m ?? '');
|
||
$('#required_density').val(row.required_density ?? '');
|
||
$('#required_hardness_shore_a').val(row.required_hardness_shore_a ?? '');
|
||
$('#lubrication_type').val(row.lubrication_type ?? '');
|
||
$('#lubrication_notes').val(row.lubrication_notes ?? '');
|
||
$('#requested_package_code').val(row.requested_package_code ?? '');
|
||
$('#meters_per_package').val(row.meters_per_package ?? '');
|
||
$('#meters_per_package_tolerance').val(row.meters_per_package_tolerance ?? '');
|
||
$('#meters_per_package_notes').val(row.meters_per_package_notes ?? '');
|
||
|
||
// Apri modale
|
||
const modal = new bootstrap.Modal(document.getElementById('mixModal'));
|
||
modal.show();
|
||
});
|
||
|
||
// Save mix row
|
||
$('#mixForm').on('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const formData = new FormData(this);
|
||
formData.append('ajax', '1');
|
||
formData.append('action', 'save_mix_row');
|
||
|
||
fetch('', {
|
||
method: 'POST',
|
||
body: new URLSearchParams(formData)
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Salvata!',
|
||
timer: 800
|
||
})
|
||
.then(() => location.reload());
|
||
} else {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore',
|
||
text: data.message
|
||
});
|
||
}
|
||
});
|
||
});
|
||
|
||
// Delete mix row
|
||
$(document).on('click', '.delete-mix', function() {
|
||
const rowId = $(this).data('id');
|
||
|
||
Swal.fire({
|
||
title: 'Eliminare questa mescola dal foglio?',
|
||
icon: 'warning',
|
||
showCancelButton: true,
|
||
confirmButtonColor: '#d33',
|
||
cancelButtonColor: '#6c757d',
|
||
confirmButtonText: 'Sì, elimina',
|
||
cancelButtonText: 'Annulla'
|
||
}).then(result => {
|
||
if (!result.isConfirmed) return;
|
||
|
||
fetch('', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body: `ajax=1&action=delete_mix_row&row_id=${rowId}`
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Eliminata!',
|
||
timer: 800
|
||
})
|
||
.then(() => location.reload());
|
||
} else {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Errore',
|
||
text: data.message
|
||
});
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|