[FEAT] Inventario: rinomina/rimuovi sottoclassi org dalla modifica bene (ticket #426)
Aggiunti endpoint PUT/DELETE /api/assets/subclasses/{id} (org-scoped, le
sottoclassi di sistema restano protette; FK ON DELETE SET NULL scollega i
beni senza cancellarli) + link UI «rinomina»/«rimuovi» accanto a «aggiungi».
Cache-buster api.js + bump version 1.24.8.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7529c59a75
commit
637e1ec510
@@ -340,6 +340,59 @@ class AssetController extends BaseController
|
||||
$this->jsonSuccess(['id' => $id, 'voce_code' => $voce, 'label' => $label], 'Sottoclasse aggiunta', 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT /api/assets/subclasses/{id} { label* }
|
||||
* Rinomina una sottoclasse ORGANIZZATIVA dell'org corrente. Le sottoclassi di
|
||||
* sistema (organization_id NULL) NON sono modificabili dall'utente.
|
||||
*/
|
||||
public function updateSubclass(int $id): void
|
||||
{
|
||||
$this->requireOrgRole(['org_admin', 'compliance_manager']);
|
||||
$body = $this->getJsonBody();
|
||||
$label = trim((string) ($body['label'] ?? ''));
|
||||
if ($label === '' || mb_strlen($label) > 120) {
|
||||
$this->jsonError('Etichetta sottoclasse obbligatoria (max 120 caratteri)', 422, 'INVALID_LABEL');
|
||||
}
|
||||
$orgId = $this->getCurrentOrgId();
|
||||
$row = Database::fetchOne(
|
||||
'SELECT id, voce_code FROM inventory_subclassi WHERE id = ? AND organization_id = ?',
|
||||
[$id, $orgId]
|
||||
);
|
||||
if (!$row) {
|
||||
$this->jsonError('Sottoclasse non trovata o non modificabile (le voci di sistema non si modificano)', 404, 'SUBCLASS_NOT_FOUND');
|
||||
}
|
||||
$dup = Database::fetchOne(
|
||||
'SELECT id FROM inventory_subclassi WHERE voce_code = ? AND label = ? AND (organization_id = ? OR organization_id IS NULL) AND id <> ?',
|
||||
[$row['voce_code'], $label, $orgId, $id]
|
||||
);
|
||||
if ($dup) { $this->jsonError('Sottoclasse già esistente', 409, 'DUPLICATE'); }
|
||||
Database::update('inventory_subclassi', ['label' => $label], 'id = ? AND organization_id = ?', [$id, $orgId]);
|
||||
$this->jsonSuccess(['id' => $id, 'label' => $label], 'Sottoclasse aggiornata');
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /api/assets/subclasses/{id}
|
||||
* Rimuove una sottoclasse ORGANIZZATIVA dell'org corrente. Gli asset che la
|
||||
* usano restano senza sottoclasse (FK ON DELETE SET NULL su assets.subclass_id).
|
||||
* Le sottoclassi di sistema (organization_id NULL) NON sono eliminabili.
|
||||
*/
|
||||
public function deleteSubclass(int $id): void
|
||||
{
|
||||
$this->requireOrgRole(['org_admin', 'compliance_manager']);
|
||||
$orgId = $this->getCurrentOrgId();
|
||||
$row = Database::fetchOne(
|
||||
'SELECT id FROM inventory_subclassi WHERE id = ? AND organization_id = ?',
|
||||
[$id, $orgId]
|
||||
);
|
||||
if (!$row) {
|
||||
$this->jsonError('Sottoclasse non trovata o non eliminabile (le voci di sistema non si rimuovono)', 404, 'SUBCLASS_NOT_FOUND');
|
||||
}
|
||||
$used = Database::fetchOne('SELECT COUNT(*) AS c FROM assets WHERE subclass_id = ?', [$id]);
|
||||
$usedCount = (int) ($used['c'] ?? 0);
|
||||
Database::delete('inventory_subclassi', 'id = ? AND organization_id = ?', [$id, $orgId]);
|
||||
$this->jsonSuccess(['id' => $id, 'unlinked_assets' => $usedCount], 'Sottoclasse rimossa');
|
||||
}
|
||||
|
||||
public function delete(int $id): void
|
||||
{
|
||||
$this->requireOrgRole(['org_admin']);
|
||||
|
||||
Reference in New Issue
Block a user