Files
Lizandro GuarnizoandClaude Sonnet 4.6 838cc651b2 fix: repair ErpSync upsert — no duplicate key + preserve config_json
- Added UNIQUE KEY on companies.name in DB so ON DUPLICATE KEY UPDATE
  actually fires instead of always inserting
- Removed config_json and phone_number_id from upsert: those hold
  admin-configured bot data and should never be overwritten by ERP sync
- Skip placeholder API key to avoid sending a fake Bearer token
- Improved error reporting: curl errors, raw response preview, per-company
  error labels

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 17:44:31 -05:00

96 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
class ErpSync
{
public static function sync(): array
{
$apiUrl = env('ERP_SYNC_API_URL', '');
$apiKey = env('ERP_SYNC_API_KEY', '');
if ($apiUrl === '') {
return ['error' => 'ERP_SYNC_API_URL no configurado en .env'];
}
$httpHeader = ['Accept: application/json'];
if ($apiKey !== '' && $apiKey !== 'token_para_sincronizar_empresas') {
$httpHeader[] = 'Authorization: Bearer ' . $apiKey;
}
$ch = curl_init($apiUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $httpHeader,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
curl_close($ch);
if ($curlErr !== '') {
return ['error' => 'cURL error: ' . $curlErr];
}
if ($httpCode !== 200) {
return ['error' => "HTTP {$httpCode}", 'response' => mb_substr((string)$response, 0, 500)];
}
$companies = json_decode($response, true);
if (!is_array($companies)) {
return ['error' => 'Respuesta no es JSON válido', 'raw' => mb_substr((string)$response, 0, 300)];
}
$synced = 0;
$errors = [];
foreach ($companies as $company) {
try {
self::upsert($company);
$synced++;
} catch (\Exception $e) {
$errors[] = ($company['name'] ?? '?') . ': ' . $e->getMessage();
}
}
return ['synced' => $synced, 'total' => count($companies), 'errors' => $errors];
}
private static function upsert(array $data): void
{
$name = trim($data['name'] ?? '');
if ($name === '') {
throw new \InvalidArgumentException('name es requerido');
}
// Never overwrite config_json — that holds all bot flows/menus configured by admins.
// Never overwrite phone_number_id — set manually per company.
$stmt = db()->prepare("
INSERT INTO companies
(name, display_name, display_phone, api_base_url, api_key, bot_type, requires_approval, is_active)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
display_name = VALUES(display_name),
display_phone = VALUES(display_phone),
api_base_url = VALUES(api_base_url),
api_key = VALUES(api_key),
bot_type = VALUES(bot_type),
requires_approval = VALUES(requires_approval),
is_active = VALUES(is_active),
updated_at = NOW()
");
$stmt->execute([
$name,
$data['display_name'] ?? $name,
$data['display_phone'] ?? '',
$data['api_base_url'] ?? '',
$data['api_key'] ?? '',
in_array($data['bot_type'] ?? '', ['ai', 'normal', 'hybrid']) ? $data['bot_type'] : 'normal',
(int)($data['requires_approval'] ?? 0),
(int)($data['is_active'] ?? 1),
]);
}
}