- 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>
103 lines
3.5 KiB
PHP
103 lines
3.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
class CompanyRepository
|
|
{
|
|
public static function findByPhoneNumberId(string $phoneNumberId): ?array
|
|
{
|
|
$stmt = db()->prepare("SELECT * FROM companies WHERE phone_number_id = ? AND is_active = 1 LIMIT 1");
|
|
$stmt->execute([$phoneNumberId]);
|
|
$row = $stmt->fetch();
|
|
return $row ?: null;
|
|
}
|
|
|
|
public static function findById(int $id): ?array
|
|
{
|
|
$stmt = db()->prepare("SELECT * FROM companies WHERE id = ? LIMIT 1");
|
|
$stmt->execute([$id]);
|
|
$row = $stmt->fetch();
|
|
return $row ?: null;
|
|
}
|
|
|
|
public static function findByApiKey(string $apiKey): ?array
|
|
{
|
|
$stmt = db()->prepare("SELECT * FROM companies WHERE api_key = ? AND is_active = 1 LIMIT 1");
|
|
$stmt->execute([$apiKey]);
|
|
$row = $stmt->fetch();
|
|
return $row ?: null;
|
|
}
|
|
|
|
public static function findAll(bool $includeInactive = false): array
|
|
{
|
|
$where = $includeInactive ? '1=1' : 'is_active = 1';
|
|
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) {
|
|
if (array_key_exists($f, $data)) {
|
|
$sets[] = "{$f} = ?";
|
|
$params[] = is_array($data[$f]) || is_object($data[$f]) ? json_encode($data[$f]) : $data[$f];
|
|
}
|
|
}
|
|
|
|
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];
|
|
}
|
|
}
|
|
$cols = implode(', ', array_keys($insertData));
|
|
$vals = implode(', ', array_fill(0, count($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);
|
|
}
|
|
}
|
|
|
|
public static function delete(int $id): bool
|
|
{
|
|
$stmt = db()->prepare("DELETE FROM companies WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
return $stmt->rowCount() > 0;
|
|
}
|
|
}
|