fixed worksheet modal
This commit is contained in:
parent
d2f2a9089e
commit
2642906a9b
254
public/userarea/ajax/worksheet-linked-data.php
Normal file
254
public/userarea/ajax/worksheet-linked-data.php
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
<?php
|
||||||
|
ob_start();
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
require_once(__DIR__ . '/../../../extra/auth.php');
|
||||||
|
require_once(__DIR__ . '/../class/db-functions.php');
|
||||||
|
|
||||||
|
while (ob_get_level()) {
|
||||||
|
ob_end_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
if (!class_exists('Auth')) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Classe Auth non disponibile'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Auth::check()) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Sessione non valida o utente non autenticato'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DBHandlerSelect::getInstance();
|
||||||
|
$pdo = $db->getConnection();
|
||||||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
function formatDateIT($d)
|
||||||
|
{
|
||||||
|
if (!$d || $d === '0000-00-00') return '';
|
||||||
|
return date("d/m/Y", strtotime($d));
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDateTimeIT($d)
|
||||||
|
{
|
||||||
|
if (!$d || $d === '0000-00-00 00:00:00') return '';
|
||||||
|
return date("d/m/Y H:i", strtotime($d));
|
||||||
|
}
|
||||||
|
|
||||||
|
function worksheetNumberLabel($n)
|
||||||
|
{
|
||||||
|
$n = (int)$n;
|
||||||
|
return $n > 0 ? 'FL' . $n : '—';
|
||||||
|
}
|
||||||
|
|
||||||
|
function revisionLabel($rev)
|
||||||
|
{
|
||||||
|
$rev = trim((string)$rev);
|
||||||
|
return $rev !== '' ? $rev : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$action = $_POST['action'] ?? '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($action === 'get_matrice_worksheets') {
|
||||||
|
$idmatrice = isset($_POST['idmatrice']) ? (int)$_POST['idmatrice'] : 0;
|
||||||
|
if ($idmatrice <= 0) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'ID matrice non valido'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT
|
||||||
|
ws.id,
|
||||||
|
ws.idmatrice,
|
||||||
|
ws.worksheet_number,
|
||||||
|
ws.revision_code,
|
||||||
|
ws.worksheet_status,
|
||||||
|
ws.worksheet_date,
|
||||||
|
ws.customer_name,
|
||||||
|
ws.profile_type_code,
|
||||||
|
ws.marking,
|
||||||
|
ws.approved_by,
|
||||||
|
ws.created_at,
|
||||||
|
ws.updated_at,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM work_sheet_mescole wsm
|
||||||
|
WHERE wsm.worksheet_id = ws.id
|
||||||
|
) AS mix_count
|
||||||
|
FROM work_sheets ws
|
||||||
|
WHERE ws.idmatrice = ?
|
||||||
|
ORDER BY
|
||||||
|
ws.worksheet_number DESC,
|
||||||
|
CASE
|
||||||
|
WHEN ws.revision_code IS NULL OR ws.revision_code = '' THEN 0
|
||||||
|
WHEN ws.revision_code REGEXP '^R[0-9]+$' THEN CAST(SUBSTRING(ws.revision_code, 2) AS UNSIGNED)
|
||||||
|
ELSE 0
|
||||||
|
END DESC,
|
||||||
|
ws.id DESC
|
||||||
|
");
|
||||||
|
$stmt->execute([$idmatrice]);
|
||||||
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$data[] = [
|
||||||
|
'id' => (int)$r['id'],
|
||||||
|
'idmatrice' => (int)$r['idmatrice'],
|
||||||
|
'worksheet_number' => (int)($r['worksheet_number'] ?? 0),
|
||||||
|
'worksheet_number_label' => worksheetNumberLabel($r['worksheet_number'] ?? 0),
|
||||||
|
'revision_code' => $r['revision_code'] ?? '',
|
||||||
|
'revision_label' => revisionLabel($r['revision_code'] ?? ''),
|
||||||
|
'worksheet_status' => $r['worksheet_status'] ?? 'active',
|
||||||
|
'worksheet_status_label' => (($r['worksheet_status'] ?? 'active') === 'inactive') ? 'Inattivo' : 'Attivo',
|
||||||
|
'worksheet_date' => $r['worksheet_date'],
|
||||||
|
'worksheet_date_it' => formatDateIT($r['worksheet_date']),
|
||||||
|
'customer_name' => $r['customer_name'] ?? '',
|
||||||
|
'profile_type_code' => $r['profile_type_code'] ?? '',
|
||||||
|
'marking' => $r['marking'] ?? '',
|
||||||
|
'approved_by' => $r['approved_by'] ?? '',
|
||||||
|
'created_at' => $r['created_at'] ?? '',
|
||||||
|
'created_at_it' => formatDateTimeIT($r['created_at'] ?? ''),
|
||||||
|
'updated_at' => $r['updated_at'] ?? '',
|
||||||
|
'updated_at_it' => formatDateTimeIT($r['updated_at'] ?? ''),
|
||||||
|
'mix_count' => (int)($r['mix_count'] ?? 0)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'worksheets' => $data
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($action === 'get_worksheet_detail') {
|
||||||
|
$worksheetId = isset($_POST['worksheet_id']) ? (int)$_POST['worksheet_id'] : 0;
|
||||||
|
if ($worksheetId <= 0) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'ID foglio non valido'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT
|
||||||
|
ws.*,
|
||||||
|
m.nome AS matrice_nome,
|
||||||
|
m.cliente AS matrice_cliente
|
||||||
|
FROM work_sheets ws
|
||||||
|
LEFT JOIN matrice m ON m.id = ws.idmatrice
|
||||||
|
WHERE ws.id = ?
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
$stmt->execute([$worksheetId]);
|
||||||
|
$ws = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$ws) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Foglio di lavoro non trovato'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmtMix = $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
|
||||||
|
");
|
||||||
|
$stmtMix->execute([$worksheetId]);
|
||||||
|
$mixRows = $stmtMix->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'worksheet' => [
|
||||||
|
'id' => (int)$ws['id'],
|
||||||
|
'worksheet_number' => (int)($ws['worksheet_number'] ?? 0),
|
||||||
|
'worksheet_number_label' => worksheetNumberLabel($ws['worksheet_number'] ?? 0),
|
||||||
|
'revision_code' => $ws['revision_code'] ?? '',
|
||||||
|
'revision_label' => revisionLabel($ws['revision_code'] ?? ''),
|
||||||
|
'worksheet_status' => $ws['worksheet_status'] ?? 'active',
|
||||||
|
'worksheet_status_label' => (($ws['worksheet_status'] ?? 'active') === 'inactive') ? 'Inattivo' : 'Attivo',
|
||||||
|
'idmatrice' => (int)$ws['idmatrice'],
|
||||||
|
'matrice_nome' => $ws['matrice_nome'] ?? '',
|
||||||
|
'matrice_cliente' => $ws['matrice_cliente'] ?? '',
|
||||||
|
'worksheet_date' => $ws['worksheet_date'] ?? '',
|
||||||
|
'worksheet_date_it' => formatDateIT($ws['worksheet_date'] ?? ''),
|
||||||
|
'customer_name' => $ws['customer_name'] ?? '',
|
||||||
|
'profile_type_code' => $ws['profile_type_code'] ?? '',
|
||||||
|
'marking' => $ws['marking'] ?? '',
|
||||||
|
'prod_control_measure_settings' => $ws['prod_control_measure_settings'] ?? '',
|
||||||
|
'control_frequency_cut' => $ws['control_frequency_cut'] ?? '',
|
||||||
|
'control_frequency_drawing' => $ws['control_frequency_drawing'] ?? '',
|
||||||
|
'control_frequency_jig' => $ws['control_frequency_jig'] ?? '',
|
||||||
|
'control_mode_jig' => $ws['control_mode_jig'] ?? '',
|
||||||
|
'requested_package_code' => $ws['requested_package_code'] ?? '',
|
||||||
|
'meters_per_package' => $ws['meters_per_package'] ?? '',
|
||||||
|
'meters_per_package_tolerance' => $ws['meters_per_package_tolerance'] ?? '',
|
||||||
|
'meters_per_package_notes' => $ws['meters_per_package_notes'] ?? '',
|
||||||
|
'box_type' => $ws['box_type'] ?? '',
|
||||||
|
'packages_or_pieces_per_box' => $ws['packages_or_pieces_per_box'] ?? '',
|
||||||
|
'meters_per_box' => $ws['meters_per_box'] ?? '',
|
||||||
|
'pallet_type' => $ws['pallet_type'] ?? '',
|
||||||
|
'boxes_or_packages_per_pallet' => $ws['boxes_or_packages_per_pallet'] ?? '',
|
||||||
|
'speed_expected_kg_h' => $ws['speed_expected_kg_h'] ?? '',
|
||||||
|
'speed_actual_kg_h' => $ws['speed_actual_kg_h'] ?? '',
|
||||||
|
'speed_expected_m_h' => $ws['speed_expected_m_h'] ?? '',
|
||||||
|
'speed_actual_m_h' => $ws['speed_actual_m_h'] ?? '',
|
||||||
|
'approved_by' => $ws['approved_by'] ?? '',
|
||||||
|
'notes' => $ws['notes'] ?? '',
|
||||||
|
'created_at' => $ws['created_at'] ?? '',
|
||||||
|
'created_at_it' => formatDateTimeIT($ws['created_at'] ?? ''),
|
||||||
|
'updated_at' => $ws['updated_at'] ?? '',
|
||||||
|
'updated_at_it' => formatDateTimeIT($ws['updated_at'] ?? '')
|
||||||
|
],
|
||||||
|
'mix_rows' => array_map(function ($r) {
|
||||||
|
return [
|
||||||
|
'id' => (int)$r['id'],
|
||||||
|
'mix_position' => (int)$r['mix_position'],
|
||||||
|
'mescola_nome' => $r['mescola_nome'] ?? '',
|
||||||
|
'mescola_uscita' => $r['mescola_uscita'] ?? '',
|
||||||
|
'mix_weight_g_m' => $r['mix_weight_g_m'] ?? '',
|
||||||
|
'required_density' => $r['required_density'] ?? '',
|
||||||
|
'required_hardness_shore_a' => $r['required_hardness_shore_a'] ?? '',
|
||||||
|
'lubrication_type' => $r['lubrication_type'] ?? '',
|
||||||
|
'lubrication_notes' => $r['lubrication_notes'] ?? ''
|
||||||
|
];
|
||||||
|
}, $mixRows)
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Azione AJAX sconosciuta'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
362
public/userarea/assets/js/worksheets-linked-modals.js
Normal file
362
public/userarea/assets/js/worksheets-linked-modals.js
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
(function () {
|
||||||
|
function escapeHtml(str) {
|
||||||
|
return String(str || "")
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
function valueOrDash(v) {
|
||||||
|
return v === null || v === undefined || String(v).trim() === ""
|
||||||
|
? "—"
|
||||||
|
: escapeHtml(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderReadonlyField(label, value) {
|
||||||
|
return `
|
||||||
|
<div class="readonly-label">${escapeHtml(label)}</div>
|
||||||
|
<div class="readonly-value">${valueOrDash(value)}</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.loadMatriceWorksheets = function (idmatrice, matriceNome, endpoint) {
|
||||||
|
endpoint = endpoint || "ajax/worksheet-linked-data.php";
|
||||||
|
|
||||||
|
$("#wl_idmatrice").val(idmatrice);
|
||||||
|
$("#wl_matrice_name").html(
|
||||||
|
`<span class="worksheet-chip"><i class="fa-solid fa-layer-group"></i>${escapeHtml(matriceNome || "")}</span>`,
|
||||||
|
);
|
||||||
|
$("#worksheetsListContainer").html(
|
||||||
|
'<div class="text-muted">Caricamento fogli di lavoro...</div>',
|
||||||
|
);
|
||||||
|
|
||||||
|
fetch(endpoint, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
|
body:
|
||||||
|
"action=get_matrice_worksheets&idmatrice=" +
|
||||||
|
encodeURIComponent(idmatrice),
|
||||||
|
})
|
||||||
|
.then(async (r) => {
|
||||||
|
const text = await r.text();
|
||||||
|
try {
|
||||||
|
return JSON.parse(text);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Risposta non JSON worksheets:", text);
|
||||||
|
throw new Error("Risposta non JSON, vedi console");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (!data.success) {
|
||||||
|
$("#worksheetsListContainer").html(
|
||||||
|
'<div class="text-danger">Errore nel caricamento dei fogli</div>',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = data.worksheets || [];
|
||||||
|
|
||||||
|
if (!rows.length) {
|
||||||
|
$("#worksheetsListContainer").html(
|
||||||
|
'<div class="text-muted">Nessun foglio di lavoro collegato a questo profilo</div>',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let html = `
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped align-middle worksheet-list-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:110px;">Foglio</th>
|
||||||
|
<th style="width:100px;">Rev.</th>
|
||||||
|
<th style="width:110px;">Stato</th>
|
||||||
|
<th style="width:140px;">Data foglio</th>
|
||||||
|
<th>Cliente</th>
|
||||||
|
<th>Codice profilo</th>
|
||||||
|
<th style="width:110px;">Mescole</th>
|
||||||
|
<th style="width:230px;">Azioni</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
`;
|
||||||
|
|
||||||
|
rows.forEach((r) => {
|
||||||
|
const statusBadge =
|
||||||
|
r.worksheet_status === "inactive"
|
||||||
|
? `<span class="worksheet-badge-status-inactive">Inattivo</span>`
|
||||||
|
: `<span class="worksheet-badge-status-active">Attivo</span>`;
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<tr>
|
||||||
|
<td><span class="worksheet-badge-fl">${escapeHtml(r.worksheet_number_label || "—")}</span></td>
|
||||||
|
<td><span class="worksheet-badge-rev">${escapeHtml(r.revision_label || "0")}</span></td>
|
||||||
|
<td>${statusBadge}</td>
|
||||||
|
<td>${escapeHtml(r.worksheet_date_it || "—")}</td>
|
||||||
|
<td title="${escapeHtml(r.customer_name || "")}">${escapeHtml(r.customer_name || "—")}</td>
|
||||||
|
<td>${escapeHtml(r.profile_type_code || "—")}</td>
|
||||||
|
<td>${escapeHtml(String(r.mix_count || 0))}</td>
|
||||||
|
<td class="text-nowrap">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-view-worksheet open-worksheet-detail"
|
||||||
|
data-id="${r.id}"
|
||||||
|
data-endpoint="${escapeHtml(endpoint)}">
|
||||||
|
<i class="fa-solid fa-eye me-1"></i>Apri dettaglio
|
||||||
|
</button>
|
||||||
|
<a class="worksheet-open-link ms-1"
|
||||||
|
href="manage-worksheet.php?id=${r.id}"
|
||||||
|
target="_blank">
|
||||||
|
<i class="fa-solid fa-arrow-up-right-from-square"></i>Apri pagina
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
html += `
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
$("#worksheetsListContainer").html(html);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
$("#worksheetsListContainer").html(
|
||||||
|
'<div class="text-danger">Errore nel caricamento dei fogli</div>',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
window.loadWorksheetDetail = function (worksheetId, endpoint) {
|
||||||
|
endpoint = endpoint || "ajax/worksheet-linked-data.php";
|
||||||
|
|
||||||
|
$("#worksheetDetailContainer").html(
|
||||||
|
'<div class="text-muted">Caricamento dettaglio foglio...</div>',
|
||||||
|
);
|
||||||
|
|
||||||
|
fetch(endpoint, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
|
body:
|
||||||
|
"action=get_worksheet_detail&worksheet_id=" +
|
||||||
|
encodeURIComponent(worksheetId),
|
||||||
|
})
|
||||||
|
.then(async (r) => {
|
||||||
|
const text = await r.text();
|
||||||
|
try {
|
||||||
|
return JSON.parse(text);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Risposta non JSON worksheet detail:", text);
|
||||||
|
throw new Error("Risposta non JSON, vedi console");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (!data.success) {
|
||||||
|
console.error("Errore worksheets:", data);
|
||||||
|
|
||||||
|
$("#worksheetsListContainer").html(
|
||||||
|
'<div class="text-danger">Errore nel caricamento dei fogli: ' +
|
||||||
|
escapeHtml(
|
||||||
|
data.message || "nessun dettaglio restituito",
|
||||||
|
) +
|
||||||
|
"</div>",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ws = data.worksheet || {};
|
||||||
|
const mixRows = data.mix_rows || [];
|
||||||
|
|
||||||
|
let mixHtml = `<div class="text-muted">Nessuna mescola associata</div>`;
|
||||||
|
|
||||||
|
if (mixRows.length) {
|
||||||
|
mixHtml = `
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped align-middle mix-readonly-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:80px;">Pos</th>
|
||||||
|
<th>Mescola</th>
|
||||||
|
<th style="width:120px;">Peso g/m</th>
|
||||||
|
<th style="width:140px;">Densità</th>
|
||||||
|
<th style="width:150px;">Durezza</th>
|
||||||
|
<th style="width:130px;">Lubr.</th>
|
||||||
|
<th>Note lubr.</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
`;
|
||||||
|
|
||||||
|
mixRows.forEach((r) => {
|
||||||
|
const nomeMescola = r.mescola_uscita
|
||||||
|
? `${escapeHtml(r.mescola_nome || "—")} <div class="small text-muted">${escapeHtml(r.mescola_uscita)}</div>`
|
||||||
|
: escapeHtml(r.mescola_nome || "—");
|
||||||
|
|
||||||
|
mixHtml += `
|
||||||
|
<tr>
|
||||||
|
<td>${escapeHtml(String(r.mix_position || ""))}</td>
|
||||||
|
<td>${nomeMescola}</td>
|
||||||
|
<td>${valueOrDash(r.mix_weight_g_m)}</td>
|
||||||
|
<td>${valueOrDash(r.required_density)}</td>
|
||||||
|
<td>${valueOrDash(r.required_hardness_shore_a)}</td>
|
||||||
|
<td>${valueOrDash(r.lubrication_type)}</td>
|
||||||
|
<td>${valueOrDash(r.lubrication_notes)}</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
mixHtml += `
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const html = `
|
||||||
|
<div class="worksheet-title-box mb-4">
|
||||||
|
<div class="d-flex justify-content-between align-items-start gap-3 flex-wrap">
|
||||||
|
<div>
|
||||||
|
<h4 class="mb-1">${escapeHtml(ws.worksheet_number_label || "—")} / Rev. ${escapeHtml(ws.revision_label || "0")}</h4>
|
||||||
|
<small>
|
||||||
|
Stato: ${escapeHtml(ws.worksheet_status_label || "Attivo")}
|
||||||
|
${ws.matrice_nome ? " • Profilo: " + escapeHtml(ws.matrice_nome) : ""}
|
||||||
|
${ws.matrice_cliente ? " • Cliente matrice: " + escapeHtml(ws.matrice_cliente) : ""}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="manage-worksheet.php?id=${escapeHtml(String(ws.id || ""))}"
|
||||||
|
target="_blank"
|
||||||
|
class="worksheet-open-link">
|
||||||
|
<i class="fa-solid fa-arrow-up-right-from-square"></i>
|
||||||
|
Apri foglio completo
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="readonly-card">
|
||||||
|
<div class="readonly-card-header">Dati principali</div>
|
||||||
|
<div class="readonly-card-body">
|
||||||
|
<div class="readonly-grid">
|
||||||
|
${renderReadonlyField("Foglio", ws.worksheet_number_label)}
|
||||||
|
${renderReadonlyField("Revisione", ws.revision_label)}
|
||||||
|
${renderReadonlyField("Stato", ws.worksheet_status_label)}
|
||||||
|
${renderReadonlyField("Data foglio", ws.worksheet_date_it)}
|
||||||
|
${renderReadonlyField("Cliente override", ws.customer_name)}
|
||||||
|
${renderReadonlyField("Codice profilo", ws.profile_type_code)}
|
||||||
|
${renderReadonlyField("Marchiatura", ws.marking)}
|
||||||
|
${renderReadonlyField("Approvato da", ws.approved_by)}
|
||||||
|
${renderReadonlyField("Creato il", ws.created_at_it)}
|
||||||
|
${renderReadonlyField("Ultimo aggiornamento", ws.updated_at_it)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="readonly-card">
|
||||||
|
<div class="readonly-card-header">Controlli produzione</div>
|
||||||
|
<div class="readonly-card-body">
|
||||||
|
<div class="readonly-grid">
|
||||||
|
${renderReadonlyField("Taglio", ws.control_frequency_cut)}
|
||||||
|
${renderReadonlyField("Disegno", ws.control_frequency_drawing)}
|
||||||
|
${renderReadonlyField("Dima", ws.control_frequency_jig)}
|
||||||
|
${renderReadonlyField("Modalità dima", ws.control_mode_jig)}
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="readonly-label mb-2">Impostazione misure controllo produzione</div>
|
||||||
|
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.prod_control_measure_settings)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="readonly-card">
|
||||||
|
<div class="readonly-card-header">Packaging / Confezionamento</div>
|
||||||
|
<div class="readonly-card-body">
|
||||||
|
<div class="readonly-grid">
|
||||||
|
${renderReadonlyField("Codice confezione", ws.requested_package_code)}
|
||||||
|
${renderReadonlyField("Metri per confezione", ws.meters_per_package)}
|
||||||
|
${renderReadonlyField("Tolleranza metri/conf.", ws.meters_per_package_tolerance)}
|
||||||
|
${renderReadonlyField("Scatola tipo", ws.box_type)}
|
||||||
|
${renderReadonlyField("Conf./pezzi per scatola", ws.packages_or_pieces_per_box)}
|
||||||
|
${renderReadonlyField("Metri per scatola", ws.meters_per_box)}
|
||||||
|
${renderReadonlyField("Bancale tipo", ws.pallet_type)}
|
||||||
|
${renderReadonlyField("Scatole/conf. per bancale", ws.boxes_or_packages_per_pallet)}
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="readonly-label mb-2">Note metri / confezione</div>
|
||||||
|
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.meters_per_package_notes)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="readonly-card">
|
||||||
|
<div class="readonly-card-header">Velocità e note</div>
|
||||||
|
<div class="readonly-card-body">
|
||||||
|
<div class="readonly-grid">
|
||||||
|
${renderReadonlyField("Vel. prevista kg/h", ws.speed_expected_kg_h)}
|
||||||
|
${renderReadonlyField("Vel. effettiva kg/h", ws.speed_actual_kg_h)}
|
||||||
|
${renderReadonlyField("Vel. prevista m/h", ws.speed_expected_m_h)}
|
||||||
|
${renderReadonlyField("Vel. effettiva m/h", ws.speed_actual_m_h)}
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="readonly-label mb-2">Note</div>
|
||||||
|
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.notes)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="readonly-card">
|
||||||
|
<div class="readonly-card-header">Mescole associate al foglio</div>
|
||||||
|
<div class="readonly-card-body">
|
||||||
|
${mixHtml}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
$("#worksheetDetailContainer").html(html);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Catch loadMatriceWorksheets:", err);
|
||||||
|
|
||||||
|
$("#worksheetsListContainer").html(
|
||||||
|
'<div class="text-danger">Errore nel caricamento dei fogli: ' +
|
||||||
|
escapeHtml(err.message || "errore JavaScript/fetch") +
|
||||||
|
"</div>",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).on("click", ".worksheets, .show-worksheets", function () {
|
||||||
|
const idmatrice = $(this).data("id");
|
||||||
|
const nome = $(this).data("nome") || "";
|
||||||
|
const endpoint =
|
||||||
|
$(this).data("endpoint") || "ajax/worksheet-linked-data.php";
|
||||||
|
|
||||||
|
loadMatriceWorksheets(idmatrice, nome, endpoint);
|
||||||
|
new bootstrap.Modal(
|
||||||
|
document.getElementById("worksheetsListModal"),
|
||||||
|
).show();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("click", ".open-worksheet-detail", function () {
|
||||||
|
const worksheetId = $(this).data("id");
|
||||||
|
const endpoint =
|
||||||
|
$(this).data("endpoint") || "ajax/worksheet-linked-data.php";
|
||||||
|
|
||||||
|
loadWorksheetDetail(worksheetId, endpoint);
|
||||||
|
new bootstrap.Modal(
|
||||||
|
document.getElementById("worksheetDetailModal"),
|
||||||
|
).show();
|
||||||
|
});
|
||||||
|
})();
|
||||||
46
public/userarea/include/worksheets-linked-modals.php
Normal file
46
public/userarea/include/worksheets-linked-modals.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!-- MODALE LISTA FOGLI DI LAVORO -->
|
||||||
|
<div class="modal fade" id="worksheetsListModal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-worksheet-list">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header" style="background:linear-gradient(135deg,#e7f1ff,#d6e9ff);">
|
||||||
|
<div>
|
||||||
|
<h5 class="modal-title mb-0">
|
||||||
|
<i class="fa-solid fa-clipboard-list me-2"></i>Fogli di lavoro collegati
|
||||||
|
</h5>
|
||||||
|
<small class="text-muted">Elenco fogli associati al profilo selezionato</small>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<input type="hidden" id="wl_idmatrice">
|
||||||
|
<div class="fw-semibold mb-3" id="wl_matrice_name" style="color:#0b3d91;"></div>
|
||||||
|
|
||||||
|
<div id="worksheetsListContainer">
|
||||||
|
<div class="text-muted">Caricamento fogli di lavoro...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- MODALE DETTAGLIO FOGLIO DI LAVORO -->
|
||||||
|
<div class="modal fade" id="worksheetDetailModal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-worksheet-view">
|
||||||
|
<div class="modal-content" style="min-height:92vh;">
|
||||||
|
<div class="modal-header" style="background:linear-gradient(135deg,#e7f1ff,#d6e9ff);">
|
||||||
|
<div>
|
||||||
|
<h5 class="modal-title mb-0">
|
||||||
|
<i class="fa-solid fa-file-lines me-2"></i>Dettaglio foglio di lavoro
|
||||||
|
</h5>
|
||||||
|
<small class="text-muted">Visualizzazione completa in sola lettura</small>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body" id="worksheetDetailContainer">
|
||||||
|
<div class="text-muted">Caricamento dettaglio foglio...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -64,6 +64,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
|
|
||||||
$approved_by = trim($_POST['approved_by'] ?? '');
|
$approved_by = trim($_POST['approved_by'] ?? '');
|
||||||
$notes = trim($_POST['notes'] ?? '');
|
$notes = trim($_POST['notes'] ?? '');
|
||||||
|
$worksheet_number = null;
|
||||||
|
|
||||||
if ($id > 0) {
|
if ($id > 0) {
|
||||||
$stmt = $pdo->prepare("
|
$stmt = $pdo->prepare("
|
||||||
@ -128,34 +129,65 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
|
$stmtNum = $pdo->query("
|
||||||
|
SELECT IFNULL(MAX(worksheet_number), 0) + 1 AS next_number
|
||||||
|
FROM work_sheets
|
||||||
|
");
|
||||||
|
$worksheet_number = (int)$stmtNum->fetchColumn();
|
||||||
|
if ($worksheet_number <= 0) {
|
||||||
|
$worksheet_number = 1;
|
||||||
|
}
|
||||||
|
|
||||||
$stmt = $pdo->prepare("
|
$stmt = $pdo->prepare("
|
||||||
INSERT INTO work_sheets
|
INSERT INTO work_sheets
|
||||||
(
|
(
|
||||||
idmatrice, worksheet_date, customer_name, profile_type_code, marking,
|
worksheet_number,
|
||||||
prod_control_measure_settings, control_frequency_cut, control_frequency_drawing,
|
idmatrice,
|
||||||
control_frequency_jig, control_mode_jig,
|
worksheet_date,
|
||||||
requested_package_code, meters_per_package, meters_per_package_tolerance, meters_per_package_notes,
|
customer_name,
|
||||||
box_type, packages_or_pieces_per_box, meters_per_box,
|
profile_type_code,
|
||||||
pallet_type, boxes_or_packages_per_pallet,
|
revision_code,
|
||||||
speed_expected_kg_h, speed_actual_kg_h, speed_expected_m_h, speed_actual_m_h,
|
worksheet_status,
|
||||||
approved_by, notes
|
marking,
|
||||||
)
|
prod_control_measure_settings,
|
||||||
VALUES
|
control_frequency_cut,
|
||||||
(
|
control_frequency_drawing,
|
||||||
?, ?, ?, ?, ?,
|
control_frequency_jig,
|
||||||
?, ?, ?, ?, ?,
|
control_mode_jig,
|
||||||
?, ?, ?, ?,
|
requested_package_code,
|
||||||
?, ?, ?,
|
meters_per_package,
|
||||||
?, ?,
|
meters_per_package_tolerance,
|
||||||
?, ?, ?, ?,
|
meters_per_package_notes,
|
||||||
?, ?
|
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([
|
$stmt->execute([
|
||||||
|
$worksheet_number,
|
||||||
$idmatrice,
|
$idmatrice,
|
||||||
$worksheet_date,
|
$worksheet_date,
|
||||||
$customer_name !== '' ? $customer_name : null,
|
$customer_name !== '' ? $customer_name : null,
|
||||||
$profile_code !== '' ? $profile_code : null,
|
$profile_code !== '' ? $profile_code : null,
|
||||||
|
null, // revision_code = vuoto => revisione 0
|
||||||
|
'active', // worksheet_status
|
||||||
$marking,
|
$marking,
|
||||||
$prod_control !== '' ? $prod_control : null,
|
$prod_control !== '' ? $prod_control : null,
|
||||||
$freq_cut !== '' ? $freq_cut : null,
|
$freq_cut !== '' ? $freq_cut : null,
|
||||||
@ -180,7 +212,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$newId = (int)$pdo->lastInsertId();
|
$newId = (int)$pdo->lastInsertId();
|
||||||
echo json_encode(['success' => true, 'id' => $newId]);
|
$pdo->commit();
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'id' => $newId,
|
||||||
|
'worksheet_number' => $worksheet_number,
|
||||||
|
'worksheet_number_label' => worksheet_number_label($worksheet_number)
|
||||||
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,6 +438,12 @@ function h($v)
|
|||||||
return htmlspecialchars((string)$v, ENT_QUOTES);
|
return htmlspecialchars((string)$v, ENT_QUOTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function worksheet_number_label($n)
|
||||||
|
{
|
||||||
|
$n = (int)$n;
|
||||||
|
return $n > 0 ? 'FL' . $n : 'Non assegnato';
|
||||||
|
}
|
||||||
|
|
||||||
function ws_options($rows, $selectedValue, $defaultValue = '')
|
function ws_options($rows, $selectedValue, $defaultValue = '')
|
||||||
{
|
{
|
||||||
$selectedValue = (string)$selectedValue;
|
$selectedValue = (string)$selectedValue;
|
||||||
@ -855,8 +900,20 @@ $isEdit = ($worksheet_id > 0);
|
|||||||
<div class="value"><?= $isEdit ? 'In modifica' : 'Nuovo foglio' ?></div>
|
<div class="value"><?= $isEdit ? 'In modifica' : 'Nuovo foglio' ?></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-item">
|
<div class="summary-item">
|
||||||
<div class="label">ID foglio</div>
|
<div class="label">Foglio / Revisione</div>
|
||||||
<div class="value" id="summaryWsId"><?= $worksheet_id > 0 ? (int)$worksheet_id : 'Non salvato' ?></div>
|
<div class="value" id="summaryWsId">
|
||||||
|
<?php
|
||||||
|
$wsNumberLabel = ($worksheet && !empty($worksheet['worksheet_number']))
|
||||||
|
? worksheet_number_label($worksheet['worksheet_number'])
|
||||||
|
: 'Non assegnato';
|
||||||
|
|
||||||
|
$wsRevisionLabel = ($worksheet && isset($worksheet['revision_code']) && trim((string)$worksheet['revision_code']) !== '')
|
||||||
|
? trim((string)$worksheet['revision_code'])
|
||||||
|
: '0';
|
||||||
|
|
||||||
|
echo h($wsNumberLabel . ' / Rev. ' . $wsRevisionLabel);
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-item">
|
<div class="summary-item">
|
||||||
<div class="label">Mescole inserite</div>
|
<div class="label">Mescole inserite</div>
|
||||||
@ -1298,11 +1355,14 @@ $isEdit = ($worksheet_id > 0);
|
|||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
btnAddMix.prop('disabled', false);
|
btnAddMix.prop('disabled', false);
|
||||||
$('#mixWorksheetId').val(id);
|
$('#mixWorksheetId').val(id);
|
||||||
summaryWsId.text(id);
|
|
||||||
|
if (!summaryWsId.text().trim()) {
|
||||||
|
summaryWsId.text('Assegnato');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
btnAddMix.prop('disabled', true);
|
btnAddMix.prop('disabled', true);
|
||||||
$('#mixWorksheetId').val('0');
|
$('#mixWorksheetId').val('0');
|
||||||
summaryWsId.text('Non salvato');
|
summaryWsId.text('Non assegnato');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enableMixButtonIfSaved();
|
enableMixButtonIfSaved();
|
||||||
@ -1350,6 +1410,11 @@ $isEdit = ($worksheet_id > 0);
|
|||||||
}
|
}
|
||||||
|
|
||||||
wsIdInput.val(data.id);
|
wsIdInput.val(data.id);
|
||||||
|
|
||||||
|
if (data.worksheet_number_label) {
|
||||||
|
summaryWsId.text(data.worksheet_number_label);
|
||||||
|
}
|
||||||
|
|
||||||
enableMixButtonIfSaved();
|
enableMixButtonIfSaved();
|
||||||
|
|
||||||
if (!window.location.search.includes('id=')) {
|
if (!window.location.search.includes('id=')) {
|
||||||
@ -1360,7 +1425,7 @@ $isEdit = ($worksheet_id > 0);
|
|||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
title: 'Testata salvata',
|
title: 'Testata salvata',
|
||||||
text: 'Vuoi aggiungere subito le mescole?',
|
text: (data.worksheet_number_label ? ('Foglio ' + data.worksheet_number_label + ' creato correttamente. Vuoi aggiungere subito le mescole?') : 'Vuoi aggiungere subito le mescole?'),
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonText: 'Sì, aggiungi mescole',
|
confirmButtonText: 'Sì, aggiungi mescole',
|
||||||
cancelButtonText: 'No'
|
cancelButtonText: 'No'
|
||||||
|
|||||||
@ -34,192 +34,18 @@ function formatNullable($v, $fallback = '—')
|
|||||||
return $v !== '' ? $v : $fallback;
|
return $v !== '' ? $v : $fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function worksheetNumberLabel($n)
|
||||||
* AJAX HANDLERS
|
{
|
||||||
*/
|
$n = (int)$n;
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
return $n > 0 ? 'FL' . $n : '—';
|
||||||
while (ob_get_level()) {
|
|
||||||
ob_end_clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
|
|
||||||
$action = $_POST['action'] ?? '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ($action === 'get_matrice_worksheets') {
|
|
||||||
$idmatrice = isset($_POST['idmatrice']) ? (int)$_POST['idmatrice'] : 0;
|
|
||||||
if ($idmatrice <= 0) {
|
|
||||||
echo json_encode([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'ID matrice non valido'
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $pdo->prepare("
|
|
||||||
SELECT
|
|
||||||
ws.id,
|
|
||||||
ws.idmatrice,
|
|
||||||
ws.worksheet_date,
|
|
||||||
ws.customer_name,
|
|
||||||
ws.profile_type_code,
|
|
||||||
ws.marking,
|
|
||||||
ws.approved_by,
|
|
||||||
ws.created_at,
|
|
||||||
ws.updated_at,
|
|
||||||
(
|
|
||||||
SELECT COUNT(*)
|
|
||||||
FROM work_sheet_mescole wsm
|
|
||||||
WHERE wsm.worksheet_id = ws.id
|
|
||||||
) AS mix_count
|
|
||||||
FROM work_sheets ws
|
|
||||||
WHERE ws.idmatrice = ?
|
|
||||||
ORDER BY
|
|
||||||
CASE WHEN ws.worksheet_date IS NULL THEN 1 ELSE 0 END,
|
|
||||||
ws.worksheet_date DESC,
|
|
||||||
ws.id DESC
|
|
||||||
");
|
|
||||||
$stmt->execute([$idmatrice]);
|
|
||||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
$data = [];
|
|
||||||
foreach ($rows as $r) {
|
|
||||||
$data[] = [
|
|
||||||
'id' => (int)$r['id'],
|
|
||||||
'idmatrice' => (int)$r['idmatrice'],
|
|
||||||
'worksheet_date' => $r['worksheet_date'],
|
|
||||||
'worksheet_date_it' => formatDateIT($r['worksheet_date']),
|
|
||||||
'customer_name' => $r['customer_name'] ?? '',
|
|
||||||
'profile_type_code' => $r['profile_type_code'] ?? '',
|
|
||||||
'marking' => $r['marking'] ?? '',
|
|
||||||
'approved_by' => $r['approved_by'] ?? '',
|
|
||||||
'created_at' => $r['created_at'] ?? '',
|
|
||||||
'created_at_it' => formatDateTimeIT($r['created_at'] ?? ''),
|
|
||||||
'updated_at' => $r['updated_at'] ?? '',
|
|
||||||
'updated_at_it' => formatDateTimeIT($r['updated_at'] ?? ''),
|
|
||||||
'mix_count' => (int)($r['mix_count'] ?? 0)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode([
|
|
||||||
'success' => true,
|
|
||||||
'worksheets' => $data
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($action === 'get_worksheet_detail') {
|
|
||||||
$worksheetId = isset($_POST['worksheet_id']) ? (int)$_POST['worksheet_id'] : 0;
|
|
||||||
if ($worksheetId <= 0) {
|
|
||||||
echo json_encode([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'ID foglio non valido'
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $pdo->prepare("
|
|
||||||
SELECT
|
|
||||||
ws.*,
|
|
||||||
m.nome AS matrice_nome,
|
|
||||||
m.cliente AS matrice_cliente
|
|
||||||
FROM work_sheets ws
|
|
||||||
LEFT JOIN matrice m ON m.id = ws.idmatrice
|
|
||||||
WHERE ws.id = ?
|
|
||||||
LIMIT 1
|
|
||||||
");
|
|
||||||
$stmt->execute([$worksheetId]);
|
|
||||||
$ws = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
if (!$ws) {
|
|
||||||
echo json_encode([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'Foglio di lavoro non trovato'
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmtMix = $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
|
|
||||||
");
|
|
||||||
$stmtMix->execute([$worksheetId]);
|
|
||||||
$mixRows = $stmtMix->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
echo json_encode([
|
|
||||||
'success' => true,
|
|
||||||
'worksheet' => [
|
|
||||||
'id' => (int)$ws['id'],
|
|
||||||
'idmatrice' => (int)$ws['idmatrice'],
|
|
||||||
'matrice_nome' => $ws['matrice_nome'] ?? '',
|
|
||||||
'matrice_cliente' => $ws['matrice_cliente'] ?? '',
|
|
||||||
'worksheet_date' => $ws['worksheet_date'] ?? '',
|
|
||||||
'worksheet_date_it' => formatDateIT($ws['worksheet_date'] ?? ''),
|
|
||||||
'customer_name' => $ws['customer_name'] ?? '',
|
|
||||||
'profile_type_code' => $ws['profile_type_code'] ?? '',
|
|
||||||
'marking' => $ws['marking'] ?? '',
|
|
||||||
'prod_control_measure_settings' => $ws['prod_control_measure_settings'] ?? '',
|
|
||||||
'control_frequency_cut' => $ws['control_frequency_cut'] ?? '',
|
|
||||||
'control_frequency_drawing' => $ws['control_frequency_drawing'] ?? '',
|
|
||||||
'control_frequency_jig' => $ws['control_frequency_jig'] ?? '',
|
|
||||||
'control_mode_jig' => $ws['control_mode_jig'] ?? '',
|
|
||||||
'requested_package_code' => $ws['requested_package_code'] ?? '',
|
|
||||||
'meters_per_package' => $ws['meters_per_package'] ?? '',
|
|
||||||
'meters_per_package_tolerance' => $ws['meters_per_package_tolerance'] ?? '',
|
|
||||||
'meters_per_package_notes' => $ws['meters_per_package_notes'] ?? '',
|
|
||||||
'box_type' => $ws['box_type'] ?? '',
|
|
||||||
'packages_or_pieces_per_box' => $ws['packages_or_pieces_per_box'] ?? '',
|
|
||||||
'meters_per_box' => $ws['meters_per_box'] ?? '',
|
|
||||||
'pallet_type' => $ws['pallet_type'] ?? '',
|
|
||||||
'boxes_or_packages_per_pallet' => $ws['boxes_or_packages_per_pallet'] ?? '',
|
|
||||||
'speed_expected_kg_h' => $ws['speed_expected_kg_h'] ?? '',
|
|
||||||
'speed_actual_kg_h' => $ws['speed_actual_kg_h'] ?? '',
|
|
||||||
'speed_expected_m_h' => $ws['speed_expected_m_h'] ?? '',
|
|
||||||
'speed_actual_m_h' => $ws['speed_actual_m_h'] ?? '',
|
|
||||||
'approved_by' => $ws['approved_by'] ?? '',
|
|
||||||
'notes' => $ws['notes'] ?? '',
|
|
||||||
'created_at' => $ws['created_at'] ?? '',
|
|
||||||
'created_at_it' => formatDateTimeIT($ws['created_at'] ?? ''),
|
|
||||||
'updated_at' => $ws['updated_at'] ?? '',
|
|
||||||
'updated_at_it' => formatDateTimeIT($ws['updated_at'] ?? '')
|
|
||||||
],
|
|
||||||
'mix_rows' => array_map(function ($r) {
|
|
||||||
return [
|
|
||||||
'id' => (int)$r['id'],
|
|
||||||
'mix_position' => (int)$r['mix_position'],
|
|
||||||
'mescola_nome' => $r['mescola_nome'] ?? '',
|
|
||||||
'mescola_uscita' => $r['mescola_uscita'] ?? '',
|
|
||||||
'mix_weight_g_m' => $r['mix_weight_g_m'] ?? '',
|
|
||||||
'required_density' => $r['required_density'] ?? '',
|
|
||||||
'required_hardness_shore_a' => $r['required_hardness_shore_a'] ?? '',
|
|
||||||
'lubrication_type' => $r['lubrication_type'] ?? '',
|
|
||||||
'lubrication_notes' => $r['lubrication_notes'] ?? ''
|
|
||||||
];
|
|
||||||
}, $mixRows)
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'Azione AJAX sconosciuta'
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo json_encode([
|
|
||||||
'success' => false,
|
|
||||||
'message' => $e->getMessage()
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function revisionLabel($rev)
|
||||||
|
{
|
||||||
|
$rev = trim((string)$rev);
|
||||||
|
return $rev !== '' ? $rev : '0';
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="it">
|
<html lang="it">
|
||||||
@ -524,8 +350,60 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-worksheet-list {
|
.modal-worksheet-list {
|
||||||
max-width: 980px;
|
max-width: 1320px;
|
||||||
width: 94vw;
|
width: 97vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worksheet-badge-fl {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 68px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #e8f7ee;
|
||||||
|
color: #198754;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: .85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worksheet-badge-rev {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 54px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #e7f1ff;
|
||||||
|
color: #0d6efd;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: .84rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worksheet-badge-status-active {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 88px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #d1e7dd;
|
||||||
|
color: #0f5132;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: .84rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worksheet-badge-status-inactive {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 88px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f8d7da;
|
||||||
|
color: #842029;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: .84rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-worksheet-view {
|
.modal-worksheet-view {
|
||||||
@ -1104,53 +982,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- MODALE LISTA FOGLI DI LAVORO -->
|
|
||||||
<div class="modal fade" id="worksheetsListModal" tabindex="-1" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-dialog-centered modal-worksheet-list">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header" style="background:linear-gradient(135deg,#e7f1ff,#d6e9ff);">
|
|
||||||
<div>
|
|
||||||
<h5 class="modal-title mb-0">
|
|
||||||
<i class="fa-solid fa-clipboard-list me-2"></i>Fogli di lavoro collegati
|
|
||||||
</h5>
|
|
||||||
<small class="text-muted">Elenco fogli associati al profilo selezionato</small>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-body">
|
|
||||||
<input type="hidden" id="wl_idmatrice">
|
|
||||||
<div class="fw-semibold mb-3" id="wl_matrice_name" style="color:#0b3d91;"></div>
|
|
||||||
|
|
||||||
<div id="worksheetsListContainer">
|
|
||||||
<div class="text-muted">Caricamento fogli di lavoro...</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- MODALE DETTAGLIO FOGLIO DI LAVORO -->
|
|
||||||
<div class="modal fade" id="worksheetDetailModal" tabindex="-1" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-worksheet-view">
|
|
||||||
<div class="modal-content" style="min-height:92vh;">
|
|
||||||
<div class="modal-header" style="background:linear-gradient(135deg,#ede9fe,#ddd6fe);">
|
|
||||||
<div>
|
|
||||||
<h5 class="modal-title mb-0">
|
|
||||||
<i class="fa-solid fa-file-lines me-2"></i>Dettaglio foglio di lavoro
|
|
||||||
</h5>
|
|
||||||
<small class="text-muted">Visualizzazione completa in sola lettura</small>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-body" id="worksheetDetailContainer">
|
|
||||||
<div class="text-muted">Caricamento dettaglio foglio...</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- MODALE PREVIEW FILE -->
|
<!-- MODALE PREVIEW FILE -->
|
||||||
<div class="modal fade" id="filePreviewModal" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="filePreviewModal" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" style="max-width:1400px; width:98vw;">
|
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" style="max-width:1400px; width:98vw;">
|
||||||
@ -1164,9 +995,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php include('include/worksheets-linked-modals.php'); ?>
|
||||||
<?php include('jsinclude.php'); ?>
|
<?php include('jsinclude.php'); ?>
|
||||||
|
<script src="assets/js/worksheets-linked-modals.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function convertToMySQLDate(dateStr) {
|
function convertToMySQLDate(dateStr) {
|
||||||
if (!dateStr) return "";
|
if (!dateStr) return "";
|
||||||
@ -1221,16 +1052,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic', 'heif'].includes(ext);
|
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic', 'heif'].includes(ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
function valueOrDash(v) {
|
|
||||||
return (v === null || v === undefined || String(v).trim() === '') ? '—' : escapeHtml(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderReadonlyField(label, value) {
|
|
||||||
return `
|
|
||||||
<div class="readonly-label">${escapeHtml(label)}</div>
|
|
||||||
<div class="readonly-value">${valueOrDash(value)}</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
let selectedAttachmentFiles = [];
|
let selectedAttachmentFiles = [];
|
||||||
|
|
||||||
@ -1421,262 +1242,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
modal.show();
|
modal.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadMatriceWorksheets(idmatrice, matriceNome) {
|
|
||||||
$("#wl_idmatrice").val(idmatrice);
|
|
||||||
$("#wl_matrice_name").html(`<span class="worksheet-chip"><i class="fa-solid fa-layer-group"></i>${escapeHtml(matriceNome || '')}</span>`);
|
|
||||||
$("#worksheetsListContainer").html('<div class="text-muted">Caricamento fogli di lavoro...</div>');
|
|
||||||
|
|
||||||
fetch(window.location.href, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
body: 'ajax=1&action=get_matrice_worksheets&idmatrice=' + encodeURIComponent(idmatrice)
|
|
||||||
})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
if (!data.success) {
|
|
||||||
$("#worksheetsListContainer").html('<div class="text-danger">Errore nel caricamento dei fogli</div>');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rows = data.worksheets || [];
|
|
||||||
|
|
||||||
if (!rows.length) {
|
|
||||||
$("#worksheetsListContainer").html('<div class="text-muted">Nessun foglio di lavoro collegato a questo profilo</div>');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let html = `
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-striped align-middle worksheet-list-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width:90px;">ID</th>
|
|
||||||
<th style="width:140px;">Data foglio</th>
|
|
||||||
<th>Cliente</th>
|
|
||||||
<th>Codice profilo</th>
|
|
||||||
<th style="width:110px;">Mescole</th>
|
|
||||||
<th style="width:230px;">Azioni</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
`;
|
|
||||||
|
|
||||||
rows.forEach(r => {
|
|
||||||
html += `
|
|
||||||
<tr>
|
|
||||||
<td><strong>#${r.id}</strong></td>
|
|
||||||
<td>${escapeHtml(r.worksheet_date_it || '—')}</td>
|
|
||||||
<td title="${escapeHtml(r.customer_name || '')}">${escapeHtml(r.customer_name || '—')}</td>
|
|
||||||
<td>${escapeHtml(r.profile_type_code || '—')}</td>
|
|
||||||
<td>${escapeHtml(String(r.mix_count || 0))}</td>
|
|
||||||
<td class="text-nowrap">
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-view-worksheet open-worksheet-detail"
|
|
||||||
data-id="${r.id}">
|
|
||||||
<i class="fa-solid fa-eye me-1"></i>Apri dettaglio
|
|
||||||
</button>
|
|
||||||
<a class="worksheet-open-link ms-1"
|
|
||||||
href="manage-worksheet.php?id=${r.id}"
|
|
||||||
target="_blank">
|
|
||||||
<i class="fa-solid fa-arrow-up-right-from-square"></i>Apri pagina
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
|
|
||||||
html += `
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
$("#worksheetsListContainer").html(html);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
$("#worksheetsListContainer").html('<div class="text-danger">Errore nel caricamento dei fogli</div>');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadWorksheetDetail(worksheetId) {
|
|
||||||
$("#worksheetDetailContainer").html('<div class="text-muted">Caricamento dettaglio foglio...</div>');
|
|
||||||
|
|
||||||
fetch(window.location.href, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
body: 'ajax=1&action=get_worksheet_detail&worksheet_id=' + encodeURIComponent(worksheetId)
|
|
||||||
})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
if (!data.success) {
|
|
||||||
$("#worksheetDetailContainer").html('<div class="text-danger">Errore nel caricamento del dettaglio foglio</div>');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ws = data.worksheet || {};
|
|
||||||
const mixRows = data.mix_rows || [];
|
|
||||||
|
|
||||||
let mixHtml = `
|
|
||||||
<div class="text-muted">Nessuna mescola associata</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
if (mixRows.length) {
|
|
||||||
mixHtml = `
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-striped align-middle mix-readonly-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width:80px;">Pos</th>
|
|
||||||
<th>Mescola</th>
|
|
||||||
<th style="width:120px;">Peso g/m</th>
|
|
||||||
<th style="width:140px;">Densità</th>
|
|
||||||
<th style="width:150px;">Durezza</th>
|
|
||||||
<th style="width:130px;">Lubr.</th>
|
|
||||||
<th>Note lubr.</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
`;
|
|
||||||
|
|
||||||
mixRows.forEach(r => {
|
|
||||||
const nomeMescola = r.mescola_uscita ?
|
|
||||||
`${escapeHtml(r.mescola_nome || '—')} <div class="small text-muted">${escapeHtml(r.mescola_uscita)}</div>` :
|
|
||||||
escapeHtml(r.mescola_nome || '—');
|
|
||||||
|
|
||||||
mixHtml += `
|
|
||||||
<tr>
|
|
||||||
<td>${escapeHtml(String(r.mix_position || ''))}</td>
|
|
||||||
<td>${nomeMescola}</td>
|
|
||||||
<td>${valueOrDash(r.mix_weight_g_m)}</td>
|
|
||||||
<td>${valueOrDash(r.required_density)}</td>
|
|
||||||
<td>${valueOrDash(r.required_hardness_shore_a)}</td>
|
|
||||||
<td>${valueOrDash(r.lubrication_type)}</td>
|
|
||||||
<td>${valueOrDash(r.lubrication_notes)}</td>
|
|
||||||
</tr>
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
|
|
||||||
mixHtml += `
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const html = `
|
|
||||||
<div class="worksheet-title-box mb-4">
|
|
||||||
<div class="d-flex justify-content-between align-items-start gap-3 flex-wrap">
|
|
||||||
<div>
|
|
||||||
<h4 class="mb-1">Foglio di lavoro #${escapeHtml(String(ws.id || ''))}</h4>
|
|
||||||
<small>Profilo: ${escapeHtml(ws.matrice_nome || '—')} ${ws.matrice_cliente ? '• Cliente matrice: ' + escapeHtml(ws.matrice_cliente) : ''}</small>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a href="manage-worksheet.php?id=${escapeHtml(String(ws.id || ''))}"
|
|
||||||
target="_blank"
|
|
||||||
class="worksheet-open-link">
|
|
||||||
<i class="fa-solid fa-arrow-up-right-from-square"></i>
|
|
||||||
Apri foglio completo
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row g-3">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="readonly-card">
|
|
||||||
<div class="readonly-card-header">Dati principali</div>
|
|
||||||
<div class="readonly-card-body">
|
|
||||||
<div class="readonly-grid">
|
|
||||||
${renderReadonlyField('ID foglio', ws.id)}
|
|
||||||
${renderReadonlyField('Data foglio', ws.worksheet_date_it)}
|
|
||||||
${renderReadonlyField('Cliente override', ws.customer_name)}
|
|
||||||
${renderReadonlyField('Codice profilo', ws.profile_type_code)}
|
|
||||||
${renderReadonlyField('Marchiatura', ws.marking)}
|
|
||||||
${renderReadonlyField('Approvato da', ws.approved_by)}
|
|
||||||
${renderReadonlyField('Creato il', ws.created_at_it)}
|
|
||||||
${renderReadonlyField('Ultimo aggiornamento', ws.updated_at_it)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="readonly-card">
|
|
||||||
<div class="readonly-card-header">Controlli produzione</div>
|
|
||||||
<div class="readonly-card-body">
|
|
||||||
<div class="readonly-grid">
|
|
||||||
${renderReadonlyField('Taglio', ws.control_frequency_cut)}
|
|
||||||
${renderReadonlyField('Disegno', ws.control_frequency_drawing)}
|
|
||||||
${renderReadonlyField('Dima', ws.control_frequency_jig)}
|
|
||||||
${renderReadonlyField('Modalità dima', ws.control_mode_jig)}
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<div class="readonly-label mb-2">Impostazione misure controllo produzione</div>
|
|
||||||
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.prod_control_measure_settings)}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="readonly-card">
|
|
||||||
<div class="readonly-card-header">Packaging / Confezionamento</div>
|
|
||||||
<div class="readonly-card-body">
|
|
||||||
<div class="readonly-grid">
|
|
||||||
${renderReadonlyField('Codice confezione', ws.requested_package_code)}
|
|
||||||
${renderReadonlyField('Metri per confezione', ws.meters_per_package)}
|
|
||||||
${renderReadonlyField('Tolleranza metri/conf.', ws.meters_per_package_tolerance)}
|
|
||||||
${renderReadonlyField('Scatola tipo', ws.box_type)}
|
|
||||||
${renderReadonlyField('Conf./pezzi per scatola', ws.packages_or_pieces_per_box)}
|
|
||||||
${renderReadonlyField('Metri per scatola', ws.meters_per_box)}
|
|
||||||
${renderReadonlyField('Bancale tipo', ws.pallet_type)}
|
|
||||||
${renderReadonlyField('Scatole/conf. per bancale', ws.boxes_or_packages_per_pallet)}
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<div class="readonly-label mb-2">Note metri / confezione</div>
|
|
||||||
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.meters_per_package_notes)}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="readonly-card">
|
|
||||||
<div class="readonly-card-header">Velocità e note</div>
|
|
||||||
<div class="readonly-card-body">
|
|
||||||
<div class="readonly-grid">
|
|
||||||
${renderReadonlyField('Vel. prevista kg/h', ws.speed_expected_kg_h)}
|
|
||||||
${renderReadonlyField('Vel. effettiva kg/h', ws.speed_actual_kg_h)}
|
|
||||||
${renderReadonlyField('Vel. prevista m/h', ws.speed_expected_m_h)}
|
|
||||||
${renderReadonlyField('Vel. effettiva m/h', ws.speed_actual_m_h)}
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<div class="readonly-label mb-2">Note</div>
|
|
||||||
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.notes)}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="readonly-card">
|
|
||||||
<div class="readonly-card-header">Mescole associate al foglio</div>
|
|
||||||
<div class="readonly-card-body">
|
|
||||||
${mixHtml}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
$("#worksheetDetailContainer").html(html);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
$("#worksheetDetailContainer").html('<div class="text-danger">Errore nel caricamento del dettaglio foglio</div>');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
$('#tabellaMatrici').DataTable({
|
$('#tabellaMatrici').DataTable({
|
||||||
@ -2117,21 +1682,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
$("#filePreviewContainer").html("");
|
$("#filePreviewContainer").html("");
|
||||||
});
|
});
|
||||||
|
|
||||||
// OPEN WORKSHEETS LIST
|
|
||||||
$(document).on("click", ".worksheets, .show-worksheets", function() {
|
|
||||||
const idmatrice = $(this).data("id");
|
|
||||||
const nome = $(this).data("nome") || "";
|
|
||||||
|
|
||||||
loadMatriceWorksheets(idmatrice, nome);
|
|
||||||
new bootstrap.Modal(document.getElementById('worksheetsListModal')).show();
|
|
||||||
});
|
|
||||||
|
|
||||||
// OPEN WORKSHEET DETAIL
|
|
||||||
$(document).on("click", ".open-worksheet-detail", function() {
|
|
||||||
const worksheetId = $(this).data("id");
|
|
||||||
loadWorksheetDetail(worksheetId);
|
|
||||||
new bootstrap.Modal(document.getElementById('worksheetDetailModal')).show();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("click", ".thumb-img", function() {
|
$(document).on("click", ".thumb-img", function() {
|
||||||
|
|||||||
@ -7,9 +7,38 @@ include('include/headscript.php');
|
|||||||
$db = DBHandlerSelect::getInstance();
|
$db = DBHandlerSelect::getInstance();
|
||||||
$pdo = $db->getConnection();
|
$pdo = $db->getConnection();
|
||||||
|
|
||||||
|
function h($v)
|
||||||
|
{
|
||||||
|
return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDateIT($d)
|
||||||
|
{
|
||||||
|
if (!$d || $d === '0000-00-00') return '—';
|
||||||
|
return date('d/m/Y', strtotime($d));
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDateTimeIT($d)
|
||||||
|
{
|
||||||
|
if (!$d || $d === '0000-00-00 00:00:00') return '—';
|
||||||
|
return date('d/m/Y H:i', strtotime($d));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRevisionLabel($rev)
|
||||||
|
{
|
||||||
|
$rev = trim((string)$rev);
|
||||||
|
return $rev !== '' ? $rev : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWorksheetLabel($num)
|
||||||
|
{
|
||||||
|
$num = (int)$num;
|
||||||
|
return $num > 0 ? 'FL' . $num : '—';
|
||||||
|
}
|
||||||
|
|
||||||
// AJAX HANDLERS
|
// AJAX HANDLERS
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
$action = $_POST['action'] ?? '';
|
$action = $_POST['action'] ?? '';
|
||||||
|
|
||||||
@ -21,7 +50,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete header (rows will be deleted by FK cascade if constraints exist)
|
|
||||||
$stmt = $pdo->prepare("DELETE FROM work_sheets WHERE id = ?");
|
$stmt = $pdo->prepare("DELETE FROM work_sheets WHERE id = ?");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
|
|
||||||
@ -29,9 +57,216 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($action === 'create_revision') {
|
||||||
|
$id = (int)($_POST['id'] ?? 0);
|
||||||
|
if ($id <= 0) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'ID non valido']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT *
|
||||||
|
FROM work_sheets
|
||||||
|
WHERE id = ?
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$source = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$source) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Foglio non trovato']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($source['worksheet_status'] ?? 'active') !== 'active') {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Questo foglio è già inattivo/revisionato e non può essere revisionato di nuovo'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$idmatrice = (int)$source['idmatrice'];
|
||||||
|
if ($idmatrice <= 0) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'ID matrice non valido']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$worksheetNumber = (int)($source['worksheet_number'] ?? 0);
|
||||||
|
if ($worksheetNumber <= 0) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Numero foglio non valido o non valorizzato']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
|
// Trova la prossima revisione sulla stessa numerazione foglio
|
||||||
|
$stmtMaxRev = $pdo->prepare("
|
||||||
|
SELECT revision_code
|
||||||
|
FROM work_sheets
|
||||||
|
WHERE worksheet_number = ?
|
||||||
|
ORDER BY
|
||||||
|
CASE
|
||||||
|
WHEN revision_code IS NULL OR revision_code = '' THEN 0
|
||||||
|
WHEN revision_code REGEXP '^R[0-9]+$' THEN CAST(SUBSTRING(revision_code, 2) AS UNSIGNED)
|
||||||
|
ELSE 0
|
||||||
|
END DESC,
|
||||||
|
id DESC
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
$stmtMaxRev->execute([$worksheetNumber]);
|
||||||
|
$lastRevisionCode = $stmtMaxRev->fetchColumn();
|
||||||
|
|
||||||
|
$nextRevisionNumber = 1;
|
||||||
|
if ($lastRevisionCode && preg_match('/^R(\d+)$/', $lastRevisionCode, $m)) {
|
||||||
|
$nextRevisionNumber = ((int)$m[1]) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$newRevisionCode = 'R' . $nextRevisionNumber;
|
||||||
|
|
||||||
|
// Rendi inattivo il foglio corrente
|
||||||
|
$stmtDeactivate = $pdo->prepare("
|
||||||
|
UPDATE work_sheets
|
||||||
|
SET worksheet_status = 'inactive'
|
||||||
|
WHERE id = ?
|
||||||
|
");
|
||||||
|
$stmtDeactivate->execute([$id]);
|
||||||
|
|
||||||
|
// Crea clone del foglio mantenendo lo stesso worksheet_number
|
||||||
|
$stmtInsert = $pdo->prepare("
|
||||||
|
INSERT INTO work_sheets (
|
||||||
|
worksheet_number,
|
||||||
|
idmatrice,
|
||||||
|
worksheet_date,
|
||||||
|
customer_name,
|
||||||
|
profile_type_code,
|
||||||
|
revision_code,
|
||||||
|
worksheet_status,
|
||||||
|
marking,
|
||||||
|
prod_control_measure_settings,
|
||||||
|
control_frequency_cut,
|
||||||
|
control_frequency_drawing,
|
||||||
|
control_frequency_jig,
|
||||||
|
control_mode_jig,
|
||||||
|
requested_package_code,
|
||||||
|
meters_per_package,
|
||||||
|
meters_per_package_tolerance,
|
||||||
|
meters_per_package_notes,
|
||||||
|
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 (
|
||||||
|
?, ?, ?, ?, ?, ?, ?,
|
||||||
|
?, ?, ?, ?, ?, ?,
|
||||||
|
?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||||||
|
?, ?, ?, ?, ?, ?
|
||||||
|
)
|
||||||
|
");
|
||||||
|
|
||||||
|
$stmtInsert->execute([
|
||||||
|
$worksheetNumber,
|
||||||
|
$source['idmatrice'],
|
||||||
|
$source['worksheet_date'],
|
||||||
|
$source['customer_name'],
|
||||||
|
$source['profile_type_code'],
|
||||||
|
$newRevisionCode,
|
||||||
|
'active',
|
||||||
|
$source['marking'],
|
||||||
|
$source['prod_control_measure_settings'],
|
||||||
|
$source['control_frequency_cut'],
|
||||||
|
$source['control_frequency_drawing'],
|
||||||
|
$source['control_frequency_jig'],
|
||||||
|
$source['control_mode_jig'],
|
||||||
|
$source['requested_package_code'],
|
||||||
|
$source['meters_per_package'],
|
||||||
|
$source['meters_per_package_tolerance'],
|
||||||
|
$source['meters_per_package_notes'],
|
||||||
|
$source['box_type'],
|
||||||
|
$source['packages_or_pieces_per_box'],
|
||||||
|
$source['meters_per_box'],
|
||||||
|
$source['pallet_type'],
|
||||||
|
$source['boxes_or_packages_per_pallet'],
|
||||||
|
$source['speed_expected_kg_h'],
|
||||||
|
$source['speed_actual_kg_h'],
|
||||||
|
$source['speed_expected_m_h'],
|
||||||
|
$source['speed_actual_m_h'],
|
||||||
|
$source['approved_by'],
|
||||||
|
$source['notes']
|
||||||
|
]);
|
||||||
|
|
||||||
|
$newWorksheetId = (int)$pdo->lastInsertId();
|
||||||
|
|
||||||
|
// Duplica le mescole collegate
|
||||||
|
$stmtMixes = $pdo->prepare("
|
||||||
|
SELECT
|
||||||
|
idmescola,
|
||||||
|
mix_position,
|
||||||
|
mix_weight_g_m,
|
||||||
|
required_density,
|
||||||
|
required_hardness_shore_a,
|
||||||
|
lubrication_type,
|
||||||
|
lubrication_notes
|
||||||
|
FROM work_sheet_mescole
|
||||||
|
WHERE worksheet_id = ?
|
||||||
|
ORDER BY mix_position ASC, id ASC
|
||||||
|
");
|
||||||
|
$stmtMixes->execute([$id]);
|
||||||
|
$mixRows = $stmtMixes->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if ($mixRows) {
|
||||||
|
$stmtInsertMix = $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
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
");
|
||||||
|
|
||||||
|
foreach ($mixRows as $mix) {
|
||||||
|
$stmtInsertMix->execute([
|
||||||
|
$newWorksheetId,
|
||||||
|
$mix['idmescola'],
|
||||||
|
$mix['mix_position'],
|
||||||
|
$mix['mix_weight_g_m'],
|
||||||
|
$mix['required_density'],
|
||||||
|
$mix['required_hardness_shore_a'],
|
||||||
|
$mix['lubrication_type'],
|
||||||
|
$mix['lubrication_notes']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo->commit();
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Revisione creata correttamente',
|
||||||
|
'new_id' => $newWorksheetId,
|
||||||
|
'new_revision_code' => $newRevisionCode,
|
||||||
|
'worksheet_number_label' => 'FL' . $worksheetNumber
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Azione sconosciuta']);
|
echo json_encode(['success' => false, 'message' => 'Azione sconosciuta']);
|
||||||
exit;
|
exit;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
if ($pdo->inTransaction()) {
|
||||||
|
$pdo->rollBack();
|
||||||
|
}
|
||||||
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@ -41,17 +276,25 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
|||||||
$worksheets = $pdo->query("
|
$worksheets = $pdo->query("
|
||||||
SELECT
|
SELECT
|
||||||
ws.id,
|
ws.id,
|
||||||
|
ws.worksheet_number,
|
||||||
ws.worksheet_date,
|
ws.worksheet_date,
|
||||||
ws.customer_name,
|
ws.customer_name,
|
||||||
ws.profile_type_code,
|
ws.profile_type_code,
|
||||||
|
ws.revision_code,
|
||||||
|
ws.worksheet_status,
|
||||||
ws.approved_by,
|
ws.approved_by,
|
||||||
ws.created_at,
|
ws.created_at,
|
||||||
|
ws.updated_at,
|
||||||
m.nome AS matrice_nome,
|
m.nome AS matrice_nome,
|
||||||
m.cliente AS matrice_cliente,
|
m.cliente AS matrice_cliente,
|
||||||
(SELECT COUNT(*) FROM work_sheet_mescole wsm WHERE wsm.worksheet_id = ws.id) AS mixes_count
|
(
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM work_sheet_mescole wsm
|
||||||
|
WHERE wsm.worksheet_id = ws.id
|
||||||
|
) AS mixes_count
|
||||||
FROM work_sheets ws
|
FROM work_sheets ws
|
||||||
LEFT JOIN matrice m ON ws.idmatrice = m.id
|
LEFT JOIN matrice m ON ws.idmatrice = m.id
|
||||||
ORDER BY ws.id DESC
|
ORDER BY ws.worksheet_number DESC, ws.id DESC
|
||||||
")->fetchAll(PDO::FETCH_ASSOC);
|
")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
@ -74,10 +317,8 @@ $worksheets = $pdo->query("
|
|||||||
|
|
||||||
<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/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" />
|
<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>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
@ -106,15 +347,90 @@ $worksheets = $pdo->query("
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-add:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.table thead {
|
.table thead {
|
||||||
background: #cfe3ff;
|
background: #cfe3ff;
|
||||||
color: #1f2d3d;
|
color: #1f2d3d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.badge-revision {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 48px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #e7f1ff;
|
||||||
|
color: #0d6efd;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-fl {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 68px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #e8f7ee;
|
||||||
|
color: #198754;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-status-active {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 90px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #d1e7dd;
|
||||||
|
color: #0f5132;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-status-inactive {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 90px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f8d7da;
|
||||||
|
color: #842029;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-inactive {
|
||||||
|
opacity: 0.78;
|
||||||
|
background: #fcfcfd !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-rev {
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-rev[disabled] {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.65;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table td,
|
||||||
|
.table th {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
/* Select2 Bootstrap sizing alignment */
|
/* Select2 Bootstrap sizing alignment */
|
||||||
.select2-container .select2-selection--single {
|
.select2-container .select2-selection--single {
|
||||||
height: calc(2.375rem + 2px);
|
height: calc(2.375rem + 2px);
|
||||||
/* matches .form-select default height */
|
|
||||||
padding: 0.375rem 0.75rem;
|
padding: 0.375rem 0.75rem;
|
||||||
border: 1px solid #ced4da;
|
border: 1px solid #ced4da;
|
||||||
border-radius: 0.375rem;
|
border-radius: 0.375rem;
|
||||||
@ -131,7 +447,6 @@ $worksheets = $pdo->query("
|
|||||||
height: calc(2.375rem + 2px);
|
height: calc(2.375rem + 2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make it full width */
|
|
||||||
.select2-container {
|
.select2-container {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
@ -158,14 +473,16 @@ $worksheets = $pdo->query("
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="tabellaWorksheets" class="table table-striped table-bordered">
|
<table id="tabellaWorksheets" class="table table-striped table-bordered align-middle">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>Foglio</th>
|
||||||
|
<th>Rev</th>
|
||||||
<th>Data</th>
|
<th>Data</th>
|
||||||
<th>Matrice/Profilo</th>
|
<th>Matrice/Profilo</th>
|
||||||
<th>Cliente</th>
|
<th>Cliente</th>
|
||||||
<th>Codice Profilo</th>
|
<th>Codice Profilo</th>
|
||||||
|
<th>Stato</th>
|
||||||
<th>Mescole</th>
|
<th>Mescole</th>
|
||||||
<th>Visto</th>
|
<th>Visto</th>
|
||||||
<th>Creato</th>
|
<th>Creato</th>
|
||||||
@ -174,24 +491,60 @@ $worksheets = $pdo->query("
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($worksheets as $ws): ?>
|
<?php foreach ($worksheets as $ws): ?>
|
||||||
<tr>
|
<?php
|
||||||
<td><?= (int)$ws['id'] ?></td>
|
$status = trim((string)($ws['worksheet_status'] ?? 'active'));
|
||||||
<td><?= htmlspecialchars($ws['worksheet_date'] ?? '-') ?></td>
|
if ($status === '') $status = 'active';
|
||||||
<td><?= htmlspecialchars($ws['matrice_nome'] ?? '-') ?></td>
|
|
||||||
<td><?= htmlspecialchars($ws['customer_name'] ?: ($ws['matrice_cliente'] ?? '-')) ?></td>
|
$isActive = ($status === 'active');
|
||||||
<td><?= htmlspecialchars($ws['profile_type_code'] ?? '-') ?></td>
|
$revisionLabel = getRevisionLabel($ws['revision_code'] ?? '');
|
||||||
|
$worksheetLabel = getWorksheetLabel($ws['worksheet_number'] ?? 0);
|
||||||
|
?>
|
||||||
|
<tr class="<?= !$isActive ? 'row-inactive' : '' ?>">
|
||||||
|
<td>
|
||||||
|
<span class="badge-fl"><?= h($worksheetLabel) ?></span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge-revision"><?= h($revisionLabel) ?></span>
|
||||||
|
</td>
|
||||||
|
<td><?= h(formatDateIT($ws['worksheet_date'] ?? '')) ?></td>
|
||||||
|
<td><?= h($ws['matrice_nome'] ?? '-') ?></td>
|
||||||
|
<td><?= h($ws['customer_name'] ?: ($ws['matrice_cliente'] ?? '-')) ?></td>
|
||||||
|
<td><?= h($ws['profile_type_code'] ?? '-') ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if ($isActive): ?>
|
||||||
|
<span class="badge-status-active">Attivo</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="badge-status-inactive">Inattivo</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
<td><?= (int)$ws['mixes_count'] ?></td>
|
<td><?= (int)$ws['mixes_count'] ?></td>
|
||||||
<td><?= htmlspecialchars($ws['approved_by'] ?? '-') ?></td>
|
<td><?= h($ws['approved_by'] ?? '-') ?></td>
|
||||||
<td><?= htmlspecialchars($ws['created_at'] ?? '-') ?></td>
|
<td><?= h(formatDateTimeIT($ws['created_at'] ?? '')) ?></td>
|
||||||
<td class="text-nowrap">
|
<td class="text-nowrap">
|
||||||
<button class="btn btn-sm btn-outline-primary"
|
<?php if ($isActive): ?>
|
||||||
onclick="location.href='manage-worksheet.php?id=<?= (int)$ws['id'] ?>'">
|
<button class="btn btn-sm btn-outline-primary"
|
||||||
✏️ Modifica
|
onclick="location.href='manage-worksheet.php?id=<?= (int)$ws['id'] ?>'">
|
||||||
|
✏️ Modifica
|
||||||
|
</button>
|
||||||
|
<?php else: ?>
|
||||||
|
<button class="btn btn-sm btn-outline-secondary"
|
||||||
|
onclick="location.href='manage-worksheet.php?id=<?= (int)$ws['id'] ?>'">
|
||||||
|
👁️ Vedi
|
||||||
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<button class="btn btn-sm btn-outline-info btn-rev create-revision"
|
||||||
|
data-id="<?= (int)$ws['id'] ?>"
|
||||||
|
data-name="<?= h(($ws['matrice_nome'] ?? 'Foglio') . ' ' . $worksheetLabel) ?>"
|
||||||
|
data-rev="<?= h($revisionLabel) ?>"
|
||||||
|
data-fl="<?= h($worksheetLabel) ?>"
|
||||||
|
<?= !$isActive ? 'disabled title="Foglio già revisionato/inattivo"' : '' ?>>
|
||||||
|
REV
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-sm btn-outline-danger delete-ws"
|
<button class="btn btn-sm btn-outline-danger delete-ws"
|
||||||
data-id="<?= (int)$ws['id'] ?>"
|
data-id="<?= (int)$ws['id'] ?>"
|
||||||
data-name="<?= htmlspecialchars(($ws['matrice_nome'] ?? 'Foglio') . ' #' . $ws['id'], ENT_QUOTES) ?>">
|
data-name="<?= h(($ws['matrice_nome'] ?? 'Foglio') . ' ' . $worksheetLabel . ' rev. ' . $revisionLabel) ?>">
|
||||||
🗑️ Elimina
|
🗑️ Elimina
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
@ -251,11 +604,10 @@ $worksheets = $pdo->query("
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
title: 'Eliminato!',
|
title: 'Eliminato!',
|
||||||
timer: 900
|
timer: 900
|
||||||
})
|
}).then(() => location.reload());
|
||||||
.then(() => location.reload());
|
|
||||||
} else {
|
} else {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: 'error',
|
icon: 'error',
|
||||||
@ -266,6 +618,89 @@ $worksheets = $pdo->query("
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.create-revision', function() {
|
||||||
|
if ($(this).is(':disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = $(this).data('id');
|
||||||
|
const name = $(this).data('name');
|
||||||
|
const rev = $(this).data('rev');
|
||||||
|
const fl = $(this).data('fl');
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Creare una nuova revisione?',
|
||||||
|
html: `
|
||||||
|
<div class="text-start">
|
||||||
|
<div><strong>Foglio:</strong> ${fl}</div>
|
||||||
|
<div><strong>Profilo:</strong> ${name}</div>
|
||||||
|
<div><strong>Revisione attuale:</strong> ${rev}</div>
|
||||||
|
<hr>
|
||||||
|
<div>Il sistema:</div>
|
||||||
|
<ul style="text-align:left; margin-top:8px;">
|
||||||
|
<li>renderà inattivo il foglio corrente</li>
|
||||||
|
<li>creerà un clone completo</li>
|
||||||
|
<li>duplicherà anche le mescole</li>
|
||||||
|
<li>manterrà lo stesso numero foglio</li>
|
||||||
|
<li>assegnerà la nuova revisione progressiva</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: '#0dcaf0',
|
||||||
|
cancelButtonColor: '#6c757d',
|
||||||
|
confirmButtonText: 'Sì, crea revisione',
|
||||||
|
cancelButtonText: 'Annulla'
|
||||||
|
}).then(result => {
|
||||||
|
if (!result.isConfirmed) return;
|
||||||
|
|
||||||
|
fetch('', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
},
|
||||||
|
body: `ajax=1&action=create_revision&id=${id}`
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Revisione creata',
|
||||||
|
html: `
|
||||||
|
<div>Foglio: <strong>${data.worksheet_number_label}</strong></div>
|
||||||
|
<div class="mt-1">Nuova revisione: <strong>${data.new_revision_code}</strong></div>
|
||||||
|
<div class="mt-2">Vuoi aprire subito il nuovo foglio?</div>
|
||||||
|
`,
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Apri nuovo foglio',
|
||||||
|
cancelButtonText: 'Resta qui'
|
||||||
|
}).then(res => {
|
||||||
|
if (res.isConfirmed) {
|
||||||
|
window.location.href = 'manage-worksheet.php?id=' + data.new_id;
|
||||||
|
} else {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Errore',
|
||||||
|
text: data.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Errore',
|
||||||
|
text: 'Errore durante la creazione della revisione'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user