HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux Bradford-Sitios 6.14.0-1017-azure #17~24.04.1-Ubuntu SMP Mon Dec 1 20:10:50 UTC 2025 x86_64
User: www-data (33)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/middleware-citas-dev/app/Services/OdooService.php
<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class OdooService
{
    private $url;
    private $db;
    private $username;
    private $apiKey;
    private $uid;

    public function __construct()
    {
        $this->url = rtrim(env('ODOO_URL', ''), '/');
        $this->db = env('ODOO_DB', '');
        $this->username = env('ODOO_USERNAME', '');
        $this->apiKey = env('ODOO_API_KEY', '');
    }

    /**
     * Autenticarse con Odoo via JSON-RPC y obtener el uid.
     */
    public function authenticate()
    {
        if ($this->uid) {
            return $this->uid;
        }

        $response = $this->jsonRpc('common', 'authenticate', [
            $this->db,
            $this->username,
            $this->apiKey,
            [],
        ]);

        if (!$response || isset($response['error'])) {
            Log::error('[OdooService] Error de autenticacion', [
                'error' => $response['error'] ?? 'uid vacĂ­o',
            ]);
            throw new \Exception('Error al autenticarse con Odoo');
        }

        $this->uid = $response['result'];

        Log::info('[OdooService] Autenticacion exitosa', ['uid' => $this->uid]);

        return $this->uid;
    }

    /**
     * Ejecutar un metodo en un modelo de Odoo (execute_kw).
     */
    public function executeKw($model, $method, $args = [], $kwargs = [])
    {
        $this->authenticate();

        $params = [
            $this->db,
            $this->uid,
            $this->apiKey,
            $model,
            $method,
            $args,
        ];

        if (!empty($kwargs)) {
            $params[] = $kwargs;
        }

        $response = $this->jsonRpc('object', 'execute_kw', $params);

        if (isset($response['error'])) {
            Log::error("[OdooService] Error en execute_kw", [
                'model' => $model,
                'method' => $method,
                'error' => $response['error'],
            ]);
            throw new \Exception('Error Odoo: ' . ($response['error']['data']['message'] ?? $response['error']['message'] ?? 'Error desconocido'));
        }

        return $response['result'];
    }

    /**
     * Buscar y leer registros de un modelo.
     */
    public function searchRead($model, $domain = [], $fields = [], $limit = 0)
    {
        $kwargs = ['fields' => $fields];
        if ($limit > 0) {
            $kwargs['limit'] = $limit;
        }

        return $this->executeKw($model, 'search_read', [$domain], $kwargs);
    }

    /**
     * Crear un registro en un modelo.
     */
    public function create($model, $data)
    {
        return $this->executeKw($model, 'create', [$data]);
    }

    /**
     * Verificar si un partner existe en Odoo por su ID.
     */
    public function partnerExists($partnerId)
    {
        $result = $this->searchRead(
            'res.partner',
            [['id', '=', (int) $partnerId]],
            ['id', 'name', 'email', 'vat', 'phone', 'mobile'],
            1
        );

        return !empty($result) ? $result[0] : null;
    }

    /**
     * Verificar si un usuario existe en Odoo por su ID.
     */
    public function userExists($userId)
    {
        $result = $this->searchRead(
            'res.users',
            [['id', '=', (int) $userId]],
            ['id', 'name', 'login'],
            1
        );

        return !empty($result) ? $result[0] : null;
    }

    /**
     * Crear un pago de cliente (account.payment) en Odoo.
     */
    public function createAccountPayment($data)
    {
        return $this->create('account.payment', $data);
    }

    /**
     * Llamada JSON-RPC generica a Odoo.
     */
    private function jsonRpc($service, $method, $args)
    {
        $payload = [
            'jsonrpc' => '2.0',
            'method' => 'call',
            'params' => [
                'service' => $service,
                'method' => $method,
                'args' => $args,
            ],
            'id' => rand(1, 999999),
        ];

        $response = Http::timeout(30)->post($this->url . '/jsonrpc', $payload);

        if (!$response->successful()) {
            Log::error('[OdooService] HTTP error', [
                'status' => $response->status(),
                'body' => $response->body(),
            ]);
            throw new \Exception('Error HTTP al conectar con Odoo: ' . $response->status());
        }

        return $response->json();
    }
}