added note and date to identification parts

This commit is contained in:
Claudio 2025-10-08 17:34:21 +02:00
parent b51936f784
commit a9827e4e81
6 changed files with 1307 additions and 208 deletions

View File

@ -0,0 +1,59 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php'; // Risale a root/vendor/
use Dotenv\Dotenv;
// Set JSON header
header('Content-Type: application/json');
// Debug: Log the path where we expect the .env file
$envPath = dirname(__DIR__, 2);
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Expected .env path: ' . $envPath . PHP_EOL, FILE_APPEND);
// Carica il file .env dalla root del progetto
try {
$dotenv = Dotenv::createImmutable($envPath);
$dotenv->load();
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore caricamento .env: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
echo json_encode(['success' => false, 'message' => 'Errore caricamento configurazione: ' . $e->getMessage()]);
exit(1);
}
// Recupera le variabili d'ambiente
$dbHost = $_ENV['DB_HOST'];
$dbName = $_ENV['DB_DATABASE'];
$dbUser = $_ENV['DB_USERNAME'];
$dbPass = $_ENV['DB_PASSWORD'];
$dbPrefix = $_ENV['DB_PREFIX'];
// Debug: Log database connection details (excluding password)
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . " - DB Connection: host=$dbHost, dbname=$dbName, user=$dbUser, prefix=$dbPrefix" . PHP_EOL, FILE_APPEND);
// Connessione al database MySQL
try {
$pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore connessione DB: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
echo json_encode(['success' => false, 'message' => 'Errore connessione al database: ' . $e->getMessage()]);
exit(1);
}
try {
// Query per recuperare i valori distinti di MacroMatrice, escludendo quelli che iniziano con '*' e ordinandoli
$query = "SELECT DISTINCT MacroMatrice FROM {$dbPrefix}matrici WHERE MacroMatrice IS NOT NULL AND MacroMatrice NOT LIKE '*%' ORDER BY MacroMatrice ASC";
$stmt = $pdo->prepare($query);
$stmt->execute();
$macroMatrici = $stmt->fetchAll(PDO::FETCH_COLUMN);
// Debug: Log del numero di MacroMatrice recuperate
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Retrieved ' . count($macroMatrici) . ' MacroMatrice from database' . PHP_EOL, FILE_APPEND);
// Restituisci risposta JSON
echo json_encode(['success' => true, 'value' => $macroMatrici]);
} catch (PDOException $e) {
// Log errore e restituisci risposta di errore
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore nel recupero delle MacroMatrice: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
echo json_encode(['success' => false, 'message' => 'Errore nel recupero delle MacroMatrice: ' . $e->getMessage()]);
exit(1);
}

View File

@ -40,19 +40,19 @@ try {
}
try {
// Query to fetch matrices, excluding those starting with '*' and sorting by NomeMatrice
$query = "SELECT IdMatrice, NomeMatrice FROM {$dbPrefix}matrici WHERE NomeMatrice NOT LIKE '*%' ORDER BY NomeMatrice ASC";
// Query per recuperare le matrici, includendo MacroMatrice, escludendo quelle che iniziano con '*' e ordinandole
$query = "SELECT IdMatrice, NomeMatrice, MacroMatrice FROM {$dbPrefix}matrici WHERE NomeMatrice NOT LIKE '*%' ORDER BY NomeMatrice ASC";
$stmt = $pdo->prepare($query);
$stmt->execute();
$matrici = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Debug: Log the number of matrices retrieved
// Debug: Log del numero di matrici recuperate
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Retrieved ' . count($matrici) . ' matrices from database' . PHP_EOL, FILE_APPEND);
// Return JSON response
// Restituisci risposta JSON
echo json_encode(['success' => true, 'value' => $matrici]);
} catch (PDOException $e) {
// Log error and return error response
// Log errore e restituisci risposta di errore
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore nel recupero delle matrici: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
echo json_encode(['success' => false, 'message' => 'Errore nel recupero delle matrici: ' . $e->getMessage()]);
exit(1);

View File

@ -14,9 +14,9 @@ if (!$iddatadb) {
}
try {
$stmt = $pdo->prepare("SELECT id, iddatadb, part_number, part_description FROM identification_parts WHERE iddatadb = :iddatadb ORDER BY part_number ASC");
$stmt = $pdo->prepare("SELECT id, iddatadb, part_number, part_description, idmatrice, note, dateexpiry FROM identification_parts WHERE iddatadb = :iddatadb ORDER BY part_number ASC");
$stmt->execute([':iddatadb' => $iddatadb]);
$parts = $stmt->fetchAll();
$parts = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'parts' => $parts]);
} catch (PDOException $e) {

View File

@ -8,34 +8,61 @@
<div class="modal-body">
<div class="row">
<div class="col-md-9">
<!-- Prima riga: Elenco Parti, Mix, Rinumera, Voce -->
<!-- Prima riga: Elenco Parti, Rinumera, Voce -->
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<h6 style="margin: 0;">Elenco Parti</h6>
<div style="display: flex; align-items: center;">
<input type="checkbox" id="showMixParts" name="showMixParts" style="margin-right: 5px;">
<label for="showMixParts" style="font-size: 0.9rem; margin-right: 10px;">Mix</label>
<button type="button" class="btn btn-info btn-sm" id="renumberPartsBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Rinumera Parti</button>
<button type="button" class="btn btn-secondary btn-sm ms-2" id="toggleVoiceBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;"><i class="fas fa-microphone"></i> Voce</button>
</div>
</div>
<!-- Seconda riga: +, M, Matrice globale, Propaga -->
<!-- Seconda riga: +, M, MacroMatrice, Matrice globale, Propaga -->
<div style="display: flex; align-items: center; margin-bottom: 10px;">
<button type="button" class="btn btn-success btn-sm add-row-global" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; margin-right: 5px;"><i class="fas fa-plus fa-xs"></i></button>
<button type="button" class="btn btn-primary btn-sm add-mix-global" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; margin-right: 10px;">M</button>
<select id="macro-matrice-filter" class="form-control form-control-sm ms-2" style="width: 200px !important; min-width: 200px !important; margin-right: 10px;">
<option value="">Tutte le MacroMatrici</option>
</select>
<select id="global-matrice" class="form-control form-control-sm" style="width: 350px !important; margin-right: 10px;"></select>
<button type="button" class="btn btn-primary btn-sm propagate-all-btn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;"><i class="fas fa-arrow-right fa-xs"></i> Propaga a tutte</button>
</div>
<table class="table table-striped table-sm" id="partsTable">
<thead>
<tr>
<th>Num. Parte</th>
<th>Descrizione Parte</th>
<th>Matrice</th>
<th>Azioni</th>
<th style="width: 80px;">Numero</th>
<th>Descrizione</th>
<th style="width: 200px;">Matrice</th>
<th style="width: 150px;">
<input type="date" class="form-control form-control-sm propagate-date-input" style="width: 130px; margin-left: 5px; display: inline-block;" title="Propaga data a tutte le parti">
</th>
<th style="width: 200px;">
<button type="button" class="btn btn-light btn-sm propagate-note-btn" style="padding: 0.2rem 0.4rem; font-size: 0.9rem; margin-left: 5px;" title="Propaga nota a tutte le parti">
<i class="fas fa-sticky-note"></i>
</button>
Azioni
</th>
</tr>
</thead>
<tbody id="partsTableBody">
<!-- Righe generate dinamicamente -->
<tr data-part-id="new">
<td><input type="number" class="form-control form-control-sm part-number" value="1" style="width: 80px;"></td>
<td><input type="text" class="form-control form-control-sm part-description" placeholder="Inserisci descrizione"></td>
<td>
<div style="display: flex; align-items: center;">
<button type="button" class="btn btn-primary btn-sm propagate-matrice-btn" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; margin-right: 3px;"><i class="fas fa-arrow-right fa-xs"></i></button>
<select class="part-matrice form-control form-control-sm" style="width: 150px;"></select>
</div>
</td>
<td><input type="date" class="form-control form-control-sm part-dateexpiry" style="width: 130px;"></td>
<td>
<button type="button" class="btn btn-light btn-sm note-btn" style="padding: 0.2rem 0.4rem; font-size: 0.9rem;" title="Aggiungi/Modifica nota"><i class="fas fa-sticky-note"></i></button>
<button type="button" class="btn btn-warning btn-sm add-mix-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;">M+</button>
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; display: none;"><i class="fas fa-trash fa-xs"></i></button>
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check fa-xs"></i></span>
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin fa-xs"></i></span>
</td>
</tr>
</tbody>
</table>
</div>
@ -59,6 +86,62 @@
</div>
</div>
<!-- Modale per la nota -->
<div class="modal fade" id="noteModal" tabindex="-1" aria-labelledby="noteModalLabel" aria-hidden="true">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="noteModalLabel">Nota per Parte</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<textarea class="form-control part-note" rows="5" placeholder="Inserisci una nota"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annulla</button>
<button type="button" class="btn btn-primary btn-sm save-note-btn">Salva</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="commonNoteModal" tabindex="-1" aria-labelledby="commonNoteModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="commonNoteModalLabel">Nota comune per tutte le parti</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<textarea class="form-control part-note" rows="4" placeholder="Inserisci nota comune"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Chiudi</button>
<button type="button" class="btn btn-primary save-common-note-btn">Salva</button>
</div>
</div>
</div>
</div>
<!-- Modale di conferma per l'eliminazione -->
<div class="modal fade" id="confirmDeleteModal" tabindex="-1" aria-labelledby="confirmDeleteModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmDeleteModalLabel">Conferma Eliminazione</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Sei sicuro di voler eliminare questa parte?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annulla</button>
<button type="button" class="btn btn-danger btn-sm" id="confirmDeleteBtn">Elimina</button>
</div>
</div>
</div>
</div>
<style>
#partsModal {
z-index: 1060 !important;
@ -104,20 +187,25 @@
}
#global-matrice,
.part-matrice {
.part-matrice,
#macro-matrice-filter {
width: 100% !important;
min-width: 100% !important;
}
.select2-container--default #global-matrice {
width: 350px !important;
/* Aumentato per dropdown più lungo */
min-width: 350px !important;
}
.select2-container--default #macro-matrice-filter {
width: 200px !important;
min-width: 200px !important;
}
.select2-container--default .part-matrice {
width: 100% !important;
min-width: 100% !important;
width: 150px !important;
min-width: 150px !important;
}
.select2-container--default .select2-selection--single {
@ -152,4 +240,75 @@
padding: 0.1rem 0.3rem !important;
font-size: 0.8rem !important;
}
.save-status,
.save-loading {
margin-left: 5px;
}
#confirmDeleteModal {
z-index: 1070 !important;
}
#confirmDeleteModal .modal-backdrop {
z-index: 1065 !important;
}
.note-btn {
padding: 0.2rem 0.4rem !important;
/* Aumentato leggermente il padding per un pulsante più grande */
font-size: 0.9rem !important;
/* Aumentato il font-size per un'icona più grande */
}
.note-btn.has-note {
color: #dc3545 !important;
/* Rosso quando la nota è presente */
}
#noteModal {
z-index: 1090 !important;
}
#noteModal .modal-backdrop {
z-index: 1085 !important;
}
#noteModal .modal-dialog {
position: relative;
z-index: 1090 !important;
}
#noteModal textarea {
resize: vertical;
}
.propagate-date-btn {
padding: 0.2rem 0.4rem !important;
font-size: 0.9rem !important;
}
.propagate-note-btn {
padding: 0.2rem 0.4rem !important;
font-size: 0.9rem !important;
}
#commonNoteModal {
z-index: 1095 !important;
/* Sopra #noteModal (1090) */
}
#commonNoteModal .modal-backdrop {
z-index: 1090 !important;
/* Sopra il backdrop di #noteModal (1085) */
}
#commonNoteModal .modal-dialog {
position: relative;
z-index: 1095 !important;
}
#commonNoteModal textarea {
resize: vertical;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -15,15 +15,20 @@ if (!$iddatadb || empty($parts)) {
exit;
}
$part = $parts[0];
try {
$pdo->beginTransaction();
$results = [];
foreach ($parts as $part) {
$partId = $part['id'] ?? null;
$partNumber = $part['part_number'] ?? null;
$partDescription = $part['part_description'] ?? '';
$mix = $part['mix'] ?? 'N';
$idmatrice = $part['idmatrice'] ?? null; // Nuovo campo idmatrice
$idmatrice = $part['idmatrice'] ?? null;
$note = $part['note'] ?? null;
$dateexpiry = $part['dateexpiry'] ?? null;
if ($partDescription) {
try {
if ($partDescription || $note || $dateexpiry) {
if ($partId) {
// UPDATE se la parte esiste
$stmt = $pdo->prepare("UPDATE identification_parts
@ -31,6 +36,8 @@ if ($partDescription) {
part_description = :part_description,
mix = :mix,
idmatrice = :idmatrice,
note = :note,
dateexpiry = :dateexpiry,
updated_at = NOW()
WHERE id = :id");
$stmt->execute([
@ -38,27 +45,34 @@ if ($partDescription) {
':part_number' => $partNumber,
':part_description' => $partDescription,
':mix' => $mix,
':idmatrice' => $idmatrice // Può essere NULL
':idmatrice' => $idmatrice,
':note' => $note,
':dateexpiry' => $dateexpiry,
]);
echo json_encode(['success' => true, 'part_id' => $partId, 'part_number' => $partNumber, 'message' => 'Parte aggiornata con successo']);
$results[] = ['part_id' => $partId, 'part_number' => $partNumber, 'message' => 'Parte aggiornata con successo'];
} else {
// INSERT per nuova parte
$stmt = $pdo->prepare("INSERT INTO identification_parts
(iddatadb, part_number, part_description, mix, idmatrice, created_at, updated_at)
VALUES (:iddatadb, :part_number, :part_description, :mix, :idmatrice, NOW(), NOW())");
(iddatadb, part_number, part_description, mix, idmatrice, note, dateexpiry, created_at, updated_at)
VALUES (:iddatadb, :part_number, :part_description, :mix, :idmatrice, :note, :dateexpiry, NOW(), NOW())");
$stmt->execute([
':iddatadb' => $iddatadb,
':part_number' => $partNumber,
':part_description' => $partDescription,
':mix' => $mix,
':idmatrice' => $idmatrice // Può essere NULL
':idmatrice' => $idmatrice,
':note' => $note,
':dateexpiry' => $dateexpiry,
]);
$newId = $pdo->lastInsertId();
echo json_encode(['success' => true, 'part_id' => $newId, 'part_number' => $partNumber, 'message' => 'Parte salvata con successo']);
$results[] = ['part_id' => $newId, 'part_number' => $partNumber, 'message' => 'Parte salvata con successo'];
}
}
}
$pdo->commit();
echo json_encode(['success' => true, 'results' => $results]);
} catch (PDOException $e) {
$pdo->rollBack();
echo json_encode(['success' => false, 'message' => 'Errore nel salvataggio: ' . $e->getMessage()]);
}
} else {
echo json_encode(['success' => false, 'message' => 'Descrizione mancante']);
}