[DB] Hardening integrità chiavi (mig.058): +4 UNIQUE +8 FK, retry-on-1062, bonifica 16 righe stale — v1.23.1
Estende l'audit mig.039 ai moduli 040-057 (non coperti). TIER1 additivo (0 dup/0 orfani verificati su DB live): - UNIQUE internal_audits/management_reviews (org,code), kb_uploaded_documents.qdrant_doc_uuid, whistleblowing_reports.anonymous_token (drop idx_token ridondante) - retry-on-1062 in InternalAuditController/ManagementReviewController (allineati a periodic_controls) - 6 FK: consulting_firm_id (organizations/users/kb)->consulting_firms; isms_soa.linked_control_id; isms_documents.linked_policy_id; management_review_decisions.capa_id (tutte SET NULL) TIER2 bonifica (backup pre-DELETE in .backups/): -9 firm_org_assignments orfane (org 126-129, chiude deferred-b mig.039) -7 active_sessions scadute, +2 FK CASCADE. FK totali 196->204. Sonda diagnostica db_integrity_probe.php. audit_logs lasciato by-design. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f32b6f28f5
commit
2b6c5087ad
@@ -140,10 +140,11 @@ class InternalAuditController extends BaseController
|
||||
$leadUserId = $this->validateUser($b['lead_auditor_user_id'] ?? null, $orgId);
|
||||
$leadRoleId = $this->validateRole($b['lead_auditor_role_id'] ?? null, $orgId);
|
||||
|
||||
$code = $this->generateAuditCode($orgId);
|
||||
$id = (int) Database::insert('internal_audits', [
|
||||
// Retry-on-duplicate: generateAuditCode() è check-poi-insert non atomico (race su
|
||||
// create concorrenti); la UNIQUE (organization_id, code) [mig.058] blocca i doppioni
|
||||
// e qui si rigenera il codice.
|
||||
$base = [
|
||||
'organization_id' => $orgId,
|
||||
'code' => $code,
|
||||
'title' => $title,
|
||||
'scope' => $this->nullableStr($b['scope'] ?? null),
|
||||
'criteria' => $this->nullableStr($b['criteria'] ?? null),
|
||||
@@ -154,7 +155,18 @@ class InternalAuditController extends BaseController
|
||||
'lead_auditor_role_id' => $leadRoleId,
|
||||
'conclusion' => $this->nullableStr($b['conclusion'] ?? null),
|
||||
'created_by' => $this->getCurrentUserId(),
|
||||
]);
|
||||
];
|
||||
$code = null; $id = 0;
|
||||
for ($attempt = 0; ; $attempt++) {
|
||||
$code = $this->generateAuditCode($orgId);
|
||||
try {
|
||||
$id = (int) Database::insert('internal_audits', ['code' => $code] + $base);
|
||||
break;
|
||||
} catch (\PDOException $e) {
|
||||
if (($e->errorInfo[1] ?? 0) === 1062 && $attempt < 4) { continue; }
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$seeded = $this->seedChecklist($id, $orgId);
|
||||
$this->upsertCalendar($id, $orgId, $code, $title, $planned);
|
||||
|
||||
@@ -111,11 +111,11 @@ class ManagementReviewController extends BaseController
|
||||
$conclusions = $this->nullableStr($b['conclusions'] ?? null);
|
||||
|
||||
$year = $reviewDate ? (int) substr($reviewDate, 0, 4) : (int) date('Y');
|
||||
$code = $this->nextCode($orgId, $year);
|
||||
|
||||
$id = Database::insert('management_reviews', [
|
||||
// Retry-on-duplicate: il codice RD-AAAA-NN è MAX+1 (race su create concorrenti);
|
||||
// la UNIQUE (organization_id, code) [mig.058] blocca i doppioni e qui si rigenera.
|
||||
$base = [
|
||||
'organization_id' => $orgId,
|
||||
'code' => $code,
|
||||
'review_date' => $reviewDate,
|
||||
'period_label' => $period,
|
||||
'chair_user_id' => $chairId,
|
||||
@@ -123,7 +123,18 @@ class ManagementReviewController extends BaseController
|
||||
'status' => 'draft',
|
||||
'conclusions' => $conclusions,
|
||||
'created_by' => $this->getCurrentUserId(),
|
||||
]);
|
||||
];
|
||||
$code = null; $id = 0;
|
||||
for ($attempt = 0; ; $attempt++) {
|
||||
$code = $this->nextCode($orgId, $year);
|
||||
try {
|
||||
$id = (int) Database::insert('management_reviews', ['code' => $code] + $base);
|
||||
break;
|
||||
} catch (\PDOException $e) {
|
||||
if (($e->errorInfo[1] ?? 0) === 1062 && $attempt < 4) { continue; }
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
$this->logAudit('mgmt_review_created', 'management_review', (int) $id, ['code' => $code]);
|
||||
$this->jsonSuccess(['id' => (int) $id, 'code' => $code], 'Riesame creato', 201);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user