producstion pause
This commit is contained in:
@@ -77,14 +77,33 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['start_production']))
|
||||
// 3) Ripresa: da PAUSA (7) → PRODUZIONE (2) **senza toccare start_time**
|
||||
} elseif ((int)$currentStatus === (int)$statusPausaId) {
|
||||
|
||||
// Chiudo l'ultima pausa aperta di questa produzione
|
||||
// Il motivo è obbligatorio alla ripresa: lo ricevo dal form
|
||||
$resumeReasonId = isset($_POST['reason_id']) ? (int)$_POST['reason_id'] : 0;
|
||||
|
||||
// Verifico se la pausa aperta ha già un motivo
|
||||
$stmtChk = $pdo->prepare("SELECT reason_id FROM production_pauses
|
||||
WHERE id_production = :id AND end_pause IS NULL
|
||||
ORDER BY start_pause DESC LIMIT 1");
|
||||
$stmtChk->execute(['id' => $id]);
|
||||
$existingReason = $stmtChk->fetchColumn();
|
||||
|
||||
// Se manca il motivo (sia sulla pausa che nel form) → blocco
|
||||
if (($existingReason === null || $existingReason === false) && $resumeReasonId <= 0) {
|
||||
echo json_encode(['success' => false, 'msg' => 'Seleziona il motivo della pausa prima di riprendere.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Chiudo l'ultima pausa aperta + scrivo il motivo se fornito ora
|
||||
$sqlClose = "UPDATE production_pauses
|
||||
SET end_pause = UTC_TIMESTAMP()
|
||||
SET end_pause = UTC_TIMESTAMP()"
|
||||
. ($resumeReasonId > 0 ? ", reason_id = :reason_id" : "") . "
|
||||
WHERE id_production = :id AND end_pause IS NULL
|
||||
ORDER BY start_pause DESC
|
||||
LIMIT 1";
|
||||
$stmtClose = $pdo->prepare($sqlClose);
|
||||
$stmtClose->execute(['id' => $id]);
|
||||
$paramsClose = ['id' => $id];
|
||||
if ($resumeReasonId > 0) $paramsClose['reason_id'] = $resumeReasonId;
|
||||
$stmtClose->execute($paramsClose);
|
||||
|
||||
$sqlUpdate = "UPDATE productiondata
|
||||
SET id_status = :status,
|
||||
@@ -123,23 +142,22 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['pause_production']))
|
||||
|
||||
try {
|
||||
|
||||
if ($reasonId <= 0) {
|
||||
echo json_encode(['success' => false, 'msg' => 'Motivo pausa non valido.']);
|
||||
exit;
|
||||
// Motivo pausa ora OPZIONALE: se non lo sanno, salvano NULL e lo mettono al riprendi
|
||||
if ($reasonId > 0) {
|
||||
$sql = "SELECT is_problem FROM pause_reasons WHERE id = :id LIMIT 1";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute(['id' => $reasonId]);
|
||||
$isProblem = $stmt->fetchColumn();
|
||||
|
||||
if ($isProblem === false) {
|
||||
echo json_encode(['success' => false, 'msg' => 'Motivo pausa non trovato.']);
|
||||
exit;
|
||||
}
|
||||
$isProblem = (int)$isProblem;
|
||||
} else {
|
||||
$reasonId = null; // nessun motivo scelto ora
|
||||
$isProblem = 0;
|
||||
}
|
||||
|
||||
// Leggo se il motivo è "problema" oppure pausa normale
|
||||
$sql = "SELECT is_problem FROM pause_reasons WHERE id = :id LIMIT 1";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute(['id' => $reasonId]);
|
||||
$isProblem = $stmt->fetchColumn();
|
||||
|
||||
if ($isProblem === false) {
|
||||
echo json_encode(['success' => false, 'msg' => 'Motivo pausa non trovato.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$isProblem = (int)$isProblem;
|
||||
// ❌ PRIMA – sbagliato per la tua logica:
|
||||
// $nextStatus = $isProblem ? 8 : $statusPausaId; // 8 = Problema in produzione
|
||||
|
||||
@@ -294,8 +312,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['save_final_data']))
|
||||
$scartoPerc = round(($scarto / $totaleKg) * 100, 2);
|
||||
}
|
||||
|
||||
// Stato destinazione
|
||||
$nextStatus = ($reason === 'problema') ? 8 : $statusQualita;
|
||||
// "Compila dopo" → stato 11 (dati da inserire), altrimenti flusso normale
|
||||
$compilaDopo = !empty($_POST['compila_dopo']);
|
||||
|
||||
if ($compilaDopo) {
|
||||
$nextStatus = 11; // Da compilare dati
|
||||
} else {
|
||||
$nextStatus = ($reason === 'problema') ? 8 : $statusQualita;
|
||||
}
|
||||
|
||||
// Update finale
|
||||
$sql = "UPDATE productiondata
|
||||
@@ -410,6 +434,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['create_quick'])) {
|
||||
}
|
||||
|
||||
|
||||
// --- AJAX: la pausa aperta di questa produzione ha già un motivo? ---
|
||||
if (!empty($_GET['check_pause_reason'])) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
$pid = (int)($_GET['id'] ?? 0);
|
||||
if ($pid <= 0) {
|
||||
echo json_encode(['success' => false]);
|
||||
exit;
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT reason_id FROM production_pauses
|
||||
WHERE id_production = :id AND end_pause IS NULL
|
||||
ORDER BY start_pause DESC LIMIT 1");
|
||||
$stmt->execute(['id' => $pid]);
|
||||
$rid = $stmt->fetchColumn();
|
||||
// has_reason = true se esiste una pausa aperta con reason_id non NULL
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'has_reason' => ($rid !== false && $rid !== null)
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- AJAX: mescole collegate a una matrice ---
|
||||
if (!empty($_GET['mescole_by_matrice'])) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
@@ -1497,17 +1542,32 @@ if (!empty($_GET['ajax'])) {
|
||||
</div>
|
||||
<!-- Motivo pausa (dropdown, solo per PAUSA) -->
|
||||
<div id="pauseReasonContainer" style="margin-top:1rem; display:none;">
|
||||
<label for="pauseReason"><strong>Motivo pausa:</strong></label>
|
||||
<select id="pauseReason"
|
||||
style="width:100%;padding:0.5rem;border-radius:0.5rem;border:1px solid #ccc;">
|
||||
<option value="">Seleziona un motivo</option>
|
||||
<?php foreach ($pauseReasons as $pr): ?>
|
||||
<option value="<?= $pr['id'] ?>"
|
||||
data-problem="<?= (int)$pr['is_problem'] ?>">
|
||||
<?= htmlspecialchars($pr['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<!-- Toggle "motivo dopo" (comodo per tablet) -->
|
||||
<label id="laterToggleWrap" for="pauseLater"
|
||||
style="display:flex; align-items:center; gap:0.8rem; padding:0.9rem 1rem;
|
||||
background:#f1f5f9; border:2px solid #cbd5e1; border-radius:0.8rem;
|
||||
cursor:pointer; margin-bottom:1rem; user-select:none;">
|
||||
<input type="checkbox" id="pauseLater"
|
||||
style="width:1.6rem; height:1.6rem; cursor:pointer; flex:0 0 auto;">
|
||||
<span style="font-weight:700; font-size:1.1rem; color:#1e3a8a;">
|
||||
Inserisco il motivo dopo (al riprendi)
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<div id="pauseReasonSelectWrap">
|
||||
<label for="pauseReason"><strong>Motivo pausa:</strong></label>
|
||||
<select id="pauseReason"
|
||||
style="width:100%;padding:0.5rem;border-radius:0.5rem;border:1px solid #ccc;">
|
||||
<option value="">Seleziona un motivo</option>
|
||||
<?php foreach ($pauseReasons as $pr): ?>
|
||||
<option value="<?= $pr['id'] ?>"
|
||||
data-problem="<?= (int)$pr['is_problem'] ?>">
|
||||
<?= htmlspecialchars($pr['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1579,8 +1639,10 @@ if (!empty($_GET['ajax'])) {
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-buttons" style="margin-top:1.5rem;">
|
||||
<div class="modal-buttons" style="margin-top:1.5rem; flex-wrap:wrap;">
|
||||
<button id="finalCancel" class="modal-btn modal-cancel">Annulla</button>
|
||||
<button id="finalLater" class="modal-btn modal-confirm"
|
||||
style="background:#7c3aed;">Compila dopo</button>
|
||||
<button id="finalConfirm" class="modal-btn modal-confirm">Conferma</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2183,7 +2245,20 @@ if (!empty($_GET['ajax'])) {
|
||||
e.stopPropagation();
|
||||
playBeep();
|
||||
const id = $(this).data('id');
|
||||
showReasonModal('resume', id);
|
||||
|
||||
// Chiedo al server se la pausa ha già un motivo
|
||||
$.getJSON('', {
|
||||
check_pause_reason: 1,
|
||||
id: id
|
||||
}, function(r) {
|
||||
const hasReason = r && r.success && r.has_reason;
|
||||
// 'resume' → motivo già presente: solo conferma
|
||||
// 'resume_ask' → motivo mancante: chiedi il motivo
|
||||
showReasonModal(hasReason ? 'resume' : 'resume_ask', id);
|
||||
}).fail(function() {
|
||||
// In caso di errore, per sicurezza chiedo il motivo
|
||||
showReasonModal('resume_ask', id);
|
||||
});
|
||||
});
|
||||
|
||||
// --- PAUSA ---
|
||||
@@ -2216,6 +2291,17 @@ if (!empty($_GET['ajax'])) {
|
||||
return `${day} ${month} ${year}`;
|
||||
}
|
||||
|
||||
// Toggle "motivo dopo": nasconde/disabilita la tendina
|
||||
$(document).off('change', '#pauseLater').on('change', '#pauseLater', function() {
|
||||
const later = $(this).is(':checked');
|
||||
if (later) {
|
||||
$('#pauseReason').val('').prop('disabled', true);
|
||||
$('#pauseReasonSelectWrap').slideUp(120);
|
||||
} else {
|
||||
$('#pauseReason').prop('disabled', false);
|
||||
$('#pauseReasonSelectWrap').slideDown(120);
|
||||
}
|
||||
});
|
||||
|
||||
// --- MODALE UNIFICATA PER TUTTE LE AZIONI ---
|
||||
function showReasonModal(action, id) {
|
||||
@@ -2226,6 +2312,10 @@ if (!empty($_GET['ajax'])) {
|
||||
$('#noteContainer').hide();
|
||||
$('#pauseReasonContainer').hide();
|
||||
$('#pauseReason').val('');
|
||||
// reset toggle "motivo dopo"
|
||||
$('#pauseLater').prop('checked', false);
|
||||
$('#pauseReasonSelectWrap').show();
|
||||
$('#pauseReason').prop('disabled', false);
|
||||
|
||||
// Titolo e testo dinamici
|
||||
switch (action) {
|
||||
@@ -2235,8 +2325,22 @@ if (!empty($_GET['ajax'])) {
|
||||
break;
|
||||
|
||||
case 'resume':
|
||||
// Motivo già presente in pausa → solo conferma
|
||||
$('#modalTitle').text('Ripresa produzione');
|
||||
$('#modalQuestion').text('Vuoi riprendere la produzione?');
|
||||
$('#pauseReasonContainer').hide();
|
||||
$('#noteContainer').hide();
|
||||
break;
|
||||
|
||||
case 'resume_ask':
|
||||
// Pausa senza motivo → lo chiedo ora (obbligatorio)
|
||||
$('#modalTitle').text('Ripresa produzione');
|
||||
$('#modalQuestion').text('Indica il motivo della pausa per riprendere:');
|
||||
$('#pauseReasonContainer').show();
|
||||
$('#laterToggleWrap').hide(); // niente "motivo dopo" al riprendi
|
||||
$('#pauseReasonSelectWrap').show();
|
||||
$('#pauseReason').prop('disabled', false);
|
||||
$('#noteContainer').show();
|
||||
break;
|
||||
|
||||
case 'pause':
|
||||
@@ -2244,6 +2348,7 @@ if (!empty($_GET['ajax'])) {
|
||||
$('#modalQuestion').text('Seleziona il motivo della pausa:');
|
||||
$('#modalOptions').hide(); // niente radio
|
||||
$('#pauseReasonContainer').show(); // mostra tendina
|
||||
$('#laterToggleWrap').show(); // toggle "motivo dopo" visibile
|
||||
$('#noteContainer').show(); // nota opzionale / obbligatoria se problema
|
||||
break;
|
||||
|
||||
@@ -2266,15 +2371,21 @@ if (!empty($_GET['ajax'])) {
|
||||
|
||||
// --- LOGICA PAUSA ---
|
||||
if (action === 'pause') {
|
||||
const pauseReasonId = $('#pauseReason').val();
|
||||
if (!pauseReasonId) {
|
||||
alert('Seleziona un motivo di pausa.');
|
||||
const later = $('#pauseLater').is(':checked');
|
||||
|
||||
// Se NON ha scelto "motivo dopo", il motivo è obbligatorio ora
|
||||
if (!later && !$('#pauseReason').val()) {
|
||||
alert('Seleziona un motivo, oppure attiva "Inserisco il motivo dopo".');
|
||||
return;
|
||||
}
|
||||
|
||||
// Se "motivo dopo" → NULL (0), altrimenti l'id scelto
|
||||
const pauseReasonId = later ? 0 : ($('#pauseReason').val() || 0);
|
||||
|
||||
const isProblem = $('#pauseReason option:selected').data('problem') == 1;
|
||||
|
||||
if (isProblem && note === '') {
|
||||
// "Problema" richiede la nota (solo se il motivo è stato scelto ora)
|
||||
if (!later && isProblem && note === '') {
|
||||
alert('Inserisci una nota per una pausa con problema tecnico.');
|
||||
return;
|
||||
}
|
||||
@@ -2304,10 +2415,24 @@ if (!empty($_GET['ajax'])) {
|
||||
// Azioni specifiche
|
||||
switch (action) {
|
||||
case 'start':
|
||||
case 'resume':
|
||||
startProduction(id);
|
||||
break;
|
||||
|
||||
case 'resume':
|
||||
// Motivo già presente: riprendo senza inviare reason_id
|
||||
startProduction(id);
|
||||
break;
|
||||
|
||||
case 'resume_ask':
|
||||
// Motivo mancante: obbligatorio sceglierlo ora
|
||||
const resumeReasonId = $('#pauseReason').val();
|
||||
if (!resumeReasonId) {
|
||||
alert('Seleziona il motivo della pausa prima di riprendere.');
|
||||
return;
|
||||
}
|
||||
startProduction(id, resumeReasonId);
|
||||
break;
|
||||
|
||||
case 'stop':
|
||||
// Sia "fine" che "problema" aprono il modale dati finali.
|
||||
// Il reason viene passato e conservato per il salvataggio.
|
||||
@@ -2375,6 +2500,28 @@ if (!empty($_GET['ajax'])) {
|
||||
$('#finalCancel').off('click').on('click', function() {
|
||||
$('#finalDataModal').removeClass('active');
|
||||
});
|
||||
|
||||
// "Compila dopo": chiude la produzione senza kg/metri, va in stato 11
|
||||
$('#finalLater').off('click').on('click', function() {
|
||||
if (!confirm('La produzione verrà terminata e i dati (kg, metri, scarto) resteranno da inserire nella pagina dedicata. Confermi?')) {
|
||||
return;
|
||||
}
|
||||
$('#finalDataModal').removeClass('active');
|
||||
|
||||
$.post('', {
|
||||
save_final_data: 1,
|
||||
id: id,
|
||||
reason: reason,
|
||||
compila_dopo: 1, // flag: rimanda la compilazione
|
||||
kgprod: 0,
|
||||
mtprod: 0,
|
||||
scarto: 0,
|
||||
note: $('#finalNote').val().trim()
|
||||
}, function(r) {
|
||||
if (r.success) loadRecords();
|
||||
else alert(r.msg || 'Errore nel salvataggio.');
|
||||
}, 'json');
|
||||
});
|
||||
}
|
||||
|
||||
function recalcScrapPerc() {
|
||||
@@ -2394,10 +2541,11 @@ if (!empty($_GET['ajax'])) {
|
||||
|
||||
|
||||
// --- START PRODUZIONE ---
|
||||
function startProduction(id) {
|
||||
function startProduction(id, reasonId) {
|
||||
$.post('', {
|
||||
start_production: 1,
|
||||
id: id
|
||||
id: id,
|
||||
reason_id: reasonId || 0
|
||||
}, function(r) {
|
||||
if (r.success) loadRecords();
|
||||
else alert(r.msg || 'Errore durante l\'avvio.');
|
||||
|
||||
Reference in New Issue
Block a user