fix: company save 500 error — catch DB exceptions, show error to user

- CompanyRepository::save() now catches PDOException and throws a
  RuntimeException with a human-readable message (duplicate name, etc.)
- Also fixes unchecked checkboxes (requires_approval, is_active) not
  being saved as 0 on UPDATE
- index.php save handler catches RuntimeException and redirects back to
  the form with an ?error= param instead of crashing with 500
- companyEdit() renders the error banner when ?error= is present

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-28 18:05:38 -05:00
co-authored by Claude Sonnet 4.6
parent 68317da748
commit b25126e52b
3 changed files with 51 additions and 20 deletions
+33 -13
View File
@@ -33,12 +33,23 @@ class CompanyRepository
return db()->query("SELECT * FROM companies WHERE {$where} ORDER BY name")->fetchAll();
}
/**
* @throws \RuntimeException with a human-readable message on DB error
*/
public static function save(array $data): int
{
$db = db();
$id = (int)($data['id'] ?? 0);
$fields = ['name', 'display_name', 'phone_number_id', 'display_phone', 'api_base_url', 'api_key', 'bot_type', 'requires_approval', 'is_active', 'config_json', 'erp_active_users'];
// Checkboxes: absent when unchecked — explicitly set to 0 so UPDATE clears them
foreach (['requires_approval', 'is_active'] as $cb) {
if (!array_key_exists($cb, $data)) {
$data[$cb] = 0;
}
}
$params = [];
$sets = [];
foreach ($fields as $f) {
@@ -48,18 +59,19 @@ class CompanyRepository
}
}
if ($id > 0) {
$params[] = $id;
$stmt = $db->prepare("UPDATE companies SET " . implode(', ', $sets) . " WHERE id = ?");
$stmt->execute($params);
return $id;
} else {
// Ensure required fields
$required = ['name', 'api_base_url'];
$insertData = [];
foreach ($required as $r) {
$insertData[$r] = $data[$r] ?? '';
try {
if ($id > 0) {
$params[] = $id;
$db->prepare("UPDATE companies SET " . implode(', ', $sets) . " WHERE id = ?")
->execute($params);
return $id;
}
// INSERT — require name
if (trim($data['name'] ?? '') === '') {
throw new \RuntimeException('El nombre de la empresa es requerido.');
}
$insertData = [];
foreach ($fields as $f) {
if (array_key_exists($f, $data)) {
$insertData[$f] = $data[$f];
@@ -67,9 +79,17 @@ class CompanyRepository
}
$cols = implode(', ', array_keys($insertData));
$vals = implode(', ', array_fill(0, count($insertData), '?'));
$stmt = $db->prepare("INSERT INTO companies ({$cols}) VALUES ({$vals})");
$stmt->execute(array_values($insertData));
$db->prepare("INSERT INTO companies ({$cols}) VALUES ({$vals})")
->execute(array_values($insertData));
return (int)$db->lastInsertId();
} catch (\PDOException $e) {
$msg = $e->getMessage();
// Duplicate entry on name unique key
if (str_contains($msg, '1062') || str_contains($msg, 'Duplicate entry')) {
throw new \RuntimeException('Ya existe una empresa con ese nombre.');
}
throw new \RuntimeException('Error al guardar: ' . $msg);
}
}