HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
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/vhost/disk-apps/demo.sports-crowd.com/app/Http/Controllers/ERPSiesaController.php
<?php

namespace App\Http\Controllers;

use App\ErpCode;
use App\ErpCustomItem;
use Carbon\Carbon;
use App\Repositories\ERPRepository;
use Illuminate\Support\Facades\Schema;
use GuzzleHttp\Exception\RequestException;
use stdClass;

class ERPSiesaController extends Controller implements ERPRepository
{
    private $api;
    private $key;
    private $token;
    private $clientGuzzle;
    private $headers;
    private $util;

    public $erpId;

    public function __construct($erpId)
    {
        $this->erpId = $erpId;
        $this->api      = config('erp_siesa.api');
        $this->key      = config('erp_siesa.key');
        $this->token    = config('erp_siesa.token');
        $this->util = new UtilController();

        $this->clientGuzzle = new \GuzzleHttp\Client([
            'base_uri' => $this->api,
            'defaults' => [
                'exceptions' => false,
            ]
        ]);
        $this->headers = [
            'Accept'        => 'application/json',
            'ConniKey'      => $this->key,
            'ConniToken'    => $this->token,
        ];
    }

    public function thirdClientValidate($document)
    {
        $data = [];
        $response = $this->getThirdClient($document);

        if ($response['r'] && $response['d'] && $response['d']->detalle) {
            $data = $response['d']->detalle->Table;
            $data = json_decode(json_encode($data), true);
        }
        return $data;
    }

    public function getThirdClient($parameters)
    {
        $params = $this->mapParams('third_client_criteria');
        $params .= '&parametros=' . 'IdTercero=' . ($parameters ?? '-1');
        try {
            $responseGuzzle = $this->clientGuzzle->get('ejecutarconsulta' . $params, [
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }
            return array('r' => true, 'd' => $body);
        } catch (\Exception $e) {
            return array('r' => false, 'm' => array($e->getMessage()));
        }
    }

    private function searchThirdClientByDocument($data, $document)
    {
        $result = array_filter($data, function ($v) use ($document) {
            return stripos($v['Nit'], $document) !== false;
        }, ARRAY_FILTER_USE_BOTH);
        if (count($result)) {
            $result = [reset($result)];
        }
        return $result;
    }

    public function clientAddressValidation($country, $province, $city)
    {
        $data = [];
        $response = $this->getErpAddressCodes($country, $province, $city);

        if (!$response['r'])
            return $response;
        if ($response['r']) {
            if (count($response['d']->detalle->Table) == 1) {
                $data = $response['d']->detalle->Table;
                $data = json_decode(json_encode($data), true);
            } else if ($country && $province && $city) {
                $data = $response['d']->detalle->Table;
                $data = json_decode(json_encode($data), true);
                $result = $this->searchErpCodesByAddress($data, $country, $province, $city);
                if (!count($result)) {
                    $result = $this->searchErpCodesByAddress($data, $country, $city, $province);
                }
                $data = $result;
            }
        }

        return array('r' => true, 'd' => $data);
    }

    public function clientAddressValidationByName($address, $latitude = null, $longitude = null)
    {
        $controller = new AddressController;
        $decodedData = [];
        if ($latitude && $longitude) {
            $response = $controller->geocodeAddressByCoordinates($latitude, $longitude);
            $decodedData = $this->decodeGmapsData($response, 0);
        }

        if (!$decodedData) {
            $response = $controller->geocodeAddress($address);
            $decodedData = $this->decodeGmapsData($response, 0);
        }

        return $decodedData;
    }


    private function decodeGmapsData($response, $index)
    {
        $data = [];
        $arrayLenght = count($response);
        if ($arrayLenght && $arrayLenght > $index && count($response[$index]->address_components)) {
            $data = $response[$index]->address_components;
            $neighborhood = $this->searchAddressData($data, 'neighborhood');
            if (!$neighborhood)
                $neighborhood = $this->searchAddressData($data, 'route');

            $country = $this->searchAddressData($data, 'country');
            $province = $this->searchAddressData($data, 'administrative_area_level_1');
            $city = $this->searchAddressData($data, 'locality');
            if (!$city)
                $city = $this->searchAddressData($data, 'administrative_area_level_2');

            if (is_array($country) || is_array($province) || is_array($city)) {
                return $this->decodeGmapsData($response, $index + 1);
            }

            return array(
                'country'    => $country,
                'province'   => $province,
                'city'       => $city
            );
        }
        return $data;
    }

    private function searchAddressData($data, $type)
    {
        $result = array_filter($data, function ($v) use ($type) {
            return in_array($type, $v->types);
        }, ARRAY_FILTER_USE_BOTH);
        if (count($result)) {
            $result = [reset($result)];
            $result = $result[0]->long_name;
        }
        return $result;
    }

    private function searchErpCodesByAddress($data, $country, $province, $city)
    {
        $result = array_filter($data, function ($v) use ($country, $province, $city) {
            return stripos($v['DescripcionPais'], $country) !== false
                && stripos($v['DescripcionDepartamento'], $province) !== false
                && stripos($v['DescripcionCiuda'], $city) !== false;
        }, ARRAY_FILTER_USE_BOTH);
        if (count($result)) {
            $result = [reset($result)];
        }
        return $result;
    }

    private function getErpAddressCodes($country, $province, $city)
    {
        $params = $this->mapParams('direction_client_criteria');
        $params .= '&parametros=' . 'Pais=' . ($this->translate($country) ?? '-1') . '|';
        $params .= 'Departamento=' . ($province ?? '-1') . '|';
        $params .= 'Ciudad=' . ($city ?? '-1');

        try {
            $responseGuzzle = $this->clientGuzzle->get('ejecutarconsulta' . $params, [
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }
            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            $response = $e->getResponse();
            $data = json_decode((string) $response->getBody());
            $data->uri = $e->getRequest()->getUri()->getQuery();
            return array('r' => false, 'd' => $data, 'm' => $e->getMessage());
        }
    }

    public function createThirdClient($parameters)
    {
        $params = $this->mapParams('third_client');
        $addressCodeResponse = $this->getAddressCodes($parameters);

        if (!$addressCodeResponse['r']) {
            return $addressCodeResponse;
        }
        $addressCode = $addressCodeResponse['d'];
        $addressCode = $addressCode[0] ?? $addressCode;
        $response = $this->mapThirdClientData($parameters, $addressCode);

        if (!$response['r']) {
            return $response;
        }
        $body = $response['d'];

        try {
            $responseGuzzle = $this->clientGuzzle->post('conectoresimportar' . $params, [
                \GuzzleHttp\RequestOptions::JSON    => $body,
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }

            if ($parameters->createThirdPos) {
                $response = $this->createThirdClientPOS($parameters, $addressCode);
            }

            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, $body);
        }
    }

    public function createThirdClientPOS($parameters, $addressCode)
    {
        $params = $this->mapParams('third_client_pos');
        $body = $this->mapThirdClientDataPOS($parameters, $addressCode);
        try {
            $responseGuzzle = $this->clientGuzzle->post('conectoresimportar' . $params, [
                \GuzzleHttp\RequestOptions::JSON    => $body,
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }

            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, $body);
        }
    }

    private function mapParams($document)
    {
        $params = '?idCompania=' . config('erp_siesa.companyId');

        switch ($document) {
            case 'third_client_criteria':
                $params .= '&descripcion=' . config('erp_siesa.third_client_criteria.description');
                break;

            case 'direction_client_criteria':
                $params .= '&descripcion=' . config('erp_siesa.direction_client_criteria.description');
                break;

            case 'third_client':
                $params .=  '&idInterface=' . config('erp_siesa.interfaceId') . '&idDocumento=' . config('erp_siesa.third_client.id') . '&nombreDocumento=' . config('erp_siesa.third_client.name');
                break;

            case 'third_client_pos':
                $params .= '&idInterface=' . config('erp_siesa.interfaceId') . '&idDocumento=' . config('erp_siesa.third_client_pos.id') . '&nombreDocumento=' . config('erp_siesa.third_client_pos.name');
                break;

            case 'order':
                $params .=  '&idInterface=' . config('erp_siesa.interfaceId') . '&idDocumento=' . config('erp_siesa.order.id') . '&nombreDocumento=' . config('erp_siesa.order.name');
                break;

            case 'rc':
                $params .=  '&idInterface=' . config('erp_siesa.interfaceId') . '&idDocumento=' . config('erp_siesa.rc.id') . '&nombreDocumento=' . config('erp_siesa.rc.name');
                break;
            case 'get_order':
                $params .=  '&descripcion=' . config('erp_siesa.get_order.description');
                break;
            case 'create_address':
                $params .=  '&idInterface=' . config('erp_siesa.interfaceId') . '&idDocumento=' . config('erp_siesa.create_address.id') . '&nombreDocumento=' . config('erp_siesa.create_address.name');
                break;
            case 'bill':
                $params .=  '&idInterface=' . config('erp_siesa.interfaceId') . '&idDocumento=' . config('erp_siesa.bill.id') . '&nombreDocumento=' . config('erp_siesa.bill.name');
                break;
            case 'get_inventory':
                $params .=  '&descripcion=' . config('erp_siesa.get_inventory.description') . '&Parametros=';
                break;
            case 'get_next_rc':
                $params .=  '&descripcion=' . config('erp_siesa.get_next_rc.description');
                break;
            case 'get_rc':
                $params .=  '&descripcion=' . config('erp_siesa.get_rc.description');
                break;
            case 'get_bill':
                $params .=  '&descripcion=' . config('erp_siesa.get_bill.description') . '&Parametros=';
                break;
        }
        return $params;
    }

    private function createAddress($body)
    {
        $params = $this->mapParams('create_address');

        try {
            $responseGuzzle = $this->clientGuzzle->post('conectoresimportar' . $params, [
                \GuzzleHttp\RequestOptions::JSON    => $body,
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }

            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, $body);
        }
    }


    private function getAddressCodes($params)
    {
        if ($params->country == 'Colombia' && is_numeric($params->city) && is_numeric($params->province)) {
            $data = array(
                "CodigoPais" => "169",
                "CodigoDepartamento" => $params->province,
                "CodigoCiudad" => $params->city
            );
            return array('r' => true, 'd' => $data);
        }

        if (Schema::hasTable('erp_codes') && $params->country == 'Colombia') {
            $codes = ErpCode::where('province', $params->province)->where('city', $params->city)->first();

            if ($codes) {
                $data = array(
                    "CodigoPais" => $codes->country_code,
                    "CodigoDepartamento" => $codes->province_code,
                    "CodigoCiudad" => $codes->city_code
                );
                return array('r' => true, 'd' => $data);
            }
        }

        $gmapsData = $this->clientAddressValidationByName(
            $params->shortAddress . (', ' . $params->city . ', ' . $params->province . ', ' . $params->country),
            $params->latitude ?? null,
            $params->longitude ?? null
        );

        if (count($gmapsData)) {
            $params->country = is_array($gmapsData['country']) ? $params->country : $gmapsData['country'];
            $params->province = is_array($gmapsData['province']) ? $params->city : $gmapsData['province'];
            $params->city = is_array($gmapsData['city']) ? $params->city : $gmapsData['city'];
        }
        $params->city = str_replace("'", "", $params->city);

        $cityLowerCase = strtolower($params->city);
        $provinceLowerCase = strtolower($params->province);
        if (
            str_contains($cityLowerCase, 'bogotá') ||
            str_contains($cityLowerCase, 'bogota') ||
            str_contains($provinceLowerCase, 'bogotá') ||
            str_contains($provinceLowerCase, 'bogota')
        ) {
            $data = array(
                "CodigoPais" => "169",
                "CodigoDepartamento" => "11",
                "CodigoCiudad" => "001"
            );
            return array('r' => true, 'd' => $data);
        }

        $response = $this->getErpAddressCodes($params->country, $params->province, $params->city);
        if (!$response['r']) {
            if ($params->country == 'Colombia') {
                return $response;
            }
            $response = $this->getErpAddressCodes($params->country, $params->province, null);
            if (!$response['r']) {
                $response = $this->getErpAddressCodes($params->country, null, null);
                if (!$response['r']) {
                    return $response;
                }

                $previousAdrress = end($response['d']->detalle->Table);
                $provinceCode = $this->util->completeLeadingZeros($previousAdrress->CodigoDepartamento + 1, 2);

                $body = array(
                    'Departamento' => [
                        array(
                            'F012_ID_PAIS'      => $previousAdrress->CodigoPais,
                            'F012_ID'           => $provinceCode,
                            'F012_DESCRIPCION'  => $params->province,
                        )
                    ],
                    'Ciudad' => [
                        array(
                            'F013_ID_PAIS'      => $previousAdrress->CodigoPais,
                            'F013_ID_DEPTO'     => $provinceCode,
                            'F013_ID'           => '001',
                            'F013_DESCRIPCION'  => $params->city,
                            'F013_INDICATIVO'  => '1',
                        )
                    ]
                );

                $response = $this->createAddress($body);
                if (!$response['r']) {
                    return $response;
                }
                return $this->getAddressCodes($params);
            }

            $previousAdrresses = $response['d']->detalle->Table;
            asort($previousAdrresses);
            $previousAdrress = end($previousAdrresses);
            $body = array(
                'Ciudad' => [
                    array(
                        'F013_ID_PAIS'      => $previousAdrress->CodigoPais,
                        'F013_ID_DEPTO'     => $previousAdrress->CodigoDepartamento,
                        'F013_ID'           => $this->util->completeLeadingZeros($previousAdrress->CodigoCiudad + 1, 3),
                        'F013_DESCRIPCION'  => $params->city,
                        'F013_INDICATIVO'  => '1',
                    )
                ]
            );

            $response = $this->createAddress($body);
            if (!$response['r']) {
                return $response;
            }
            return $this->getAddressCodes($params);
        }

        if (count($response['d']->detalle->Table) == 1) {
            $data = $response['d']->detalle->Table[0];
            $data = json_decode(json_encode($data), true);
        } else if ($params->country && $params->province && $params->city) {
            $data = $response['d']->detalle->Table;
            $data = json_decode(json_encode($data), true);
            $result = $this->searchErpCodesByAddress($data, $params->country, $params->province, $params->city);
            if (count($result)) {
                $data = $result[0];
            }
        }

        if (!isset($data)) {
            return array('r' => false, 'd' => 'Dirección invalida (' . $params->shortAddress . ')');
        }

        return array('r' => true, 'd' => $data);
    }

    private function mapThirdClientData($params, $addressCode)
    {
        $address = $params->address;
        $address = $this->replace_special_chars($address);
        $addres1 = mb_substr($address, 0, 40, 'UTF-8');
        $addres2 = strlen($address) > 40 ? mb_substr($address, 40, 40, 'UTF-8') : '';
        $addres3 = strlen($address) > 80 ? mb_substr($address, 80, 40, 'UTF-8') : '';
        $thirdPhone = mb_substr($params->third->phone, 0, 10, 'UTF-8');
        $clientPhone = mb_substr($params->client->phone, 0, 10, 'UTF-8');

        $typeCustomer = $this->mapTypeCustomerThird($params->third->typeThird);

        $thirds = [
            array(
                'F200_ID'                   => strtoupper($params->third->document ?? ''),
                'F200_NIT'                  => strtoupper($params->third->document ?? ''),
                'F200_ID_TIPO_IDENT'        => $typeCustomer == 0 ? '' : $params->third->documentType,                                             // Validar si el tipo de documento se manejaria el mismo para ventas nacionales o internacionales, lo recomendado es que a futuro se pueda diligenciar desde la tienda.
                'F200_IND_TIPO_TERCERO'     => $typeCustomer,                                              //
                'F200_RAZON_SOCIAL'         => mb_strtoupper($params->third->socialReason ?? '', 'UTF-8'),
                'F200_APELLIDO1'            => mb_strtoupper(explode(' ', $params->third->lastName)[0] ?? '', 'UTF-8'),
                'F200_APELLIDO2'            => strtoupper(explode(' ', $params->third->lastName)[1] ?? ''),
                'F200_NOMBRES'              => strtoupper($params->third->firstName ?? ''),
                'F015_CONTACTO'             => mb_strtoupper($params->third->contact ?? '', 'UTF-8'),
                'F015_DIRECCION1'           => mb_strtoupper($addres1, 'UTF-8'),
                'F015_DIRECCION2'           => mb_strtoupper($addres2, 'UTF-8'),
                'F015_DIRECCION3'           => $addres3,
                'F015_ID_PAIS'              => $addressCode['CodigoPais'],
                'F015_ID_DEPTO'             => $addressCode['CodigoDepartamento'],
                'F015_ID_CIUDAD'            => $addressCode['CodigoCiudad'],
                'F015_ID_BARRIO'            => $addressCode['neighborhood'] ?? '',
                'F015_TELEFONO'             => $thirdPhone,
                'F015_COD_POSTAL'           => strtoupper($params->postal ?? ''),
                'F015_EMAIL'                => strtoupper($params->third->email ?? ''),
                'F200_FECHA_NACIMIENTO'     => $params->third->birthDate,
                'F200_ID_CIIU'              => $params->third->ciiu ?? '0081',                                             // Codigos de la DIAN para algunos de terceros
                'F015_CELULAR'              => $thirdPhone
            )
        ];

        $clients = [
            array(
                'F201_ID_TERCERO'           => strtoupper($params->third->document ?? ''),
                'F201_ID_SUCURSAL'          => $params->sucursal,
                'F201_DESCRIPCION_SUCURSAL' => mb_substr(mb_strtoupper($params->client->contact ?? '', 'UTF-8'), 0, 40, 'UTF-8'),
                'F201_ID_MONEDA'            => $params->currency,
                'F201_ID_TIPO_CLI'          => $params->typeClient,
                'F201_ID_LISTA_PRECIO'      => $params->price_list,
                'F015_CONTACTO'             => mb_strtoupper($params->third->contact ?? '', 'UTF-8'),
                'F015_DIRECCION1'           => mb_strtoupper($addres1, 'UTF-8'),
                'F015_DIRECCION2'           => mb_strtoupper($addres2, 'UTF-8'),
                'F015_DIRECCION3'           => $addres3,
                'F015_ID_PAIS'              => $addressCode['CodigoPais'],
                'F015_ID_DEPTO'             => $addressCode['CodigoDepartamento'],
                'F015_ID_CIUDAD'            => $addressCode['CodigoCiudad'],
                'F015_ID_BARRIO'            => $addressCode['neighborhood'] ?? '',
                'F015_TELEFONO'             => $clientPhone,
                'F015_COD_POSTAL'           => strtoupper($params->postal ?? ''),
                'F015_EMAIL'                => strtoupper($params->client->email ?? ''),
                'F201_FECHA_INGRESO'        => Carbon::now()->format('Ymd'), // '20230716',                  // Fecha en la cual se carga el tercero
                'f015_celular'              => $clientPhone,
            )
        ];

        $taxes = [
            array(
                'F_ID_TERCERO'              => strtoupper($params->third->document ?? ''),
                'F_ID_SUCURSAL'             => $params->sucursal,
                'F_ID_VALOR_TERCERO'        => $params->hasTaxes
            )
        ];

        $clientCriteria = [];
        if ($params->idCriteria && $params->criteria) {
            $clientCriteria = [
                array(
                    'F207_ID_TERCERO'           => strtoupper($params->third->document ?? ''),
                    'F207_ID_SUCURSAL'          => $params->sucursal,
                    'F207_ID_PLAN_CRITERIOS'    => $params->idCriteria,
                    'F207_ID_CRITERIO_MAYOR'    => $params->criteria
                )
            ];
        }

        $thirdDynamicEntities = [];
        if (count($this->thirdClientValidate($params->third->document)) == 0) {
            $thirdDynamicEntities = [
                array(
                    'f200_id'                   => strtoupper($params->third->document ?? ''),
                    'f753_id_entidad'           => 'EUNOECO017',
                    'f753_id_atributo'          => 'co017_codigo_regimen',
                    'f753_id_maestro'           => 'MUNOECO016',
                    'f753_id_maestro_detalle'   => $typeCustomer == '2' ? '48' : '49'
                ),
                array(
                    'f200_id'                   => strtoupper($params->third->document ?? ''),
                    'f753_id_entidad'           => 'EUNOECO017',
                    'f753_id_atributo'          => 'co017_cod_tipo_oblig',
                    'f753_id_maestro'           => 'MUNOECO019',
                    'f753_id_maestro_detalle'   => 'R-99-PN'
                ),
                array(
                    'f200_id'                   => strtoupper($params->third->document ?? ''),
                    'f753_id_entidad'           => 'EUNOECO031',
                    'f753_id_atributo'          => 'co031_detalle_tributario1',
                    'f753_id_maestro'           => 'MUNOECO035',
                    'f753_id_maestro_detalle'   => $typeCustomer == '2' ? '01' : 'ZZ'
                )
            ];
        }

        $clientDynamicEntities = [
            array(
                'f201_id_tercero'           => strtoupper($params->third->document ?? ''),
                'f201_id_sucursal'          => $params->sucursal,
                'f753_dato_texto'           => strtoupper($params->third->email ?? '')
            )
        ];

        $body = array(
            'Terceros'              => $thirds,
            'Clientes'              => $clients,
            'ImptosyReten'          => $taxes,
            'CriteriosClientes'     => $clientCriteria,
            'EntDinamicaTercero'    => $thirdDynamicEntities,
            'EntDinamicaCliente'    => $clientDynamicEntities
        );

        return array('r' => true, 'd' => $body);
    }

    private function mapThirdClientDataPOS($params, $addressCode)
    {
        $address = $params->address;
        $addres1 = mb_substr($address, 0, 40, 'UTF-8');
        $addres2 = strlen($address) > 40 ? mb_substr($address, 40, 40, 'UTF-8') : '';
        $typeCustomer = $this->mapTypeCustomerThirdPos($params->third->typeThird);
        $thirdPhone = mb_substr($params->third->phone, 0, 10, 'UTF-8');

        $thirds = [
            array(
                'F9740_ID'                  => strtoupper($params->third->document ?? ''),
                'F9740_NIT'                 => strtoupper($params->third->document ?? ''),
                'F9740_ID_TIPO_IDENT'       => strtoupper($params->third->documentType ?? 'C'),                                             // Validar si el tipo de documento se manejaria el mismo para ventas nacionales o internacionales, lo recomendado es que a futuro se pueda diligenciar desde la tienda.
                'F9740_IND_TIPO_TERCERO'    => $typeCustomer,                                              //
                'F9740_RAZON_SOCIAL'        => strtoupper($params->third->socialReason ?? ''),
                'F9740_APELLIDO_1'          => strtoupper(explode(' ', $params->third->lastName)[0] ?? ''),
                'F9740_APELLIDO_2'          => strtoupper(explode(' ', $params->third->lastName)[1] ?? ''),
                'F9740_NOMBRE'              => strtoupper($params->third->firstName ?? ''),
                'F9740_FECHA_INGRESO'       => Carbon::now()->format('Ymd'),
                'F9740_FECHA_NACIMIENTO'    => $params->third->birthDate,
                'F9740_CONTACTO'            => strtoupper($params->third->contact ?? ''),
                'F9740_DIRECCION1'          => $addres1,
                'F9740_DIRECCION2'          => $addres2,
                'F9740_ID_PAIS'             => $addressCode['CodigoPais'],
                'F9740_ID_DEPTO'            => $addressCode['CodigoDepartamento'],
                'F9740_ID_CIUDAD'           => $addressCode['CodigoCiudad'],
                'F9740_ID_BARRIO'           => $addressCode['neighborhood'] ?? '',
                'F9740_TELEFONO'            => $thirdPhone,
                'F9740_COD_POSTAL'          => strtoupper($params->postal ?? ''),
                'F9740_EMAIL'               => strtoupper($params->third->email ?? ''),
                'F9740_CELULAR'             => $thirdPhone,
                'F9740_ID_CIIU'             => $params->third->ciiu ?? '0081',
                "F9740_IND_SEXO"            => $params->third->gender,
                "f9740_ind_habeas_data"     => "1"
            )
        ];

        $body = array(
            'ClientesOcasionalesV01' => $thirds,
        );
        return $body;
    }

    public function createOrder($parameters)
    {
        $params = $this->mapParams('order');
        $body = $this->mapOrderData($parameters);
        try {
            $responseGuzzle = $this->clientGuzzle->post('conectoresimportar' . $params, [
                \GuzzleHttp\RequestOptions::JSON    => $body,
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }

            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, $body);
        }
    }

    public function createOrderShop($order = null, $parentController)
    {
        $params = $this->mapParams('order');

        $response = $this->mapOrderDataShop($order, $parentController);
        if (!$response['r']) {
            return $response;
        }
        $body = $response['d'];

        try {
            $responseGuzzle = $this->clientGuzzle->post('conectoresimportar' . $params, [
                \GuzzleHttp\RequestOptions::JSON    => $body,
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }

            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, $body);
        }
    }

    private function mapOrderData($parameters)
    {
        $orders = [
            array(
                'f430_id_co'                => $parameters->operationCenter,
                'f430_consec_docto'         => '1',
                'f430_id_fecha'             => $parameters->date,
                'f430_id_tercero_fact'      => $parameters->document,
                'f430_id_sucursal_fact'     => $parameters->sucursal,
                'f430_id_tercero_rem'       => $parameters->document,
                'f430_id_sucursal_rem'      => $parameters->sucursal,
                'f430_id_tipo_cli_fact'     => $parameters->customerType,
                'f430_id_co_fact'           => $parameters->operationCenter,
                'f430_fecha_entrega'        => $parameters->date,
                'f430_num_docto_referencia' => $parameters->reference,
                'f430_referencia'           => $parameters->reference,
                'f430_id_moneda_docto'      => 'COP',  // PENDIENTE
                'f430_id_moneda_conv'       => 'COP',  // PENDIENTE
                'f430_tasa_conv'            => '1',
                'f430_tasa_local'           => '1',
                'f430_id_cond_pago'         => 'CTD',
                'f430_notas'                => $parameters->note,
            )
        ];

        $items = $parameters->items;

        $body = array(
            'Pedidos'                       => $orders,
            'MovtoPedidoscomercial'         => $items,
        );
        if (count($parameters->discounts))
            $body['Descuentos'] = $parameters->discounts;

        return $body;
    }

    private function mapOrderDataShop($order, $parentController)
    {
        $isHED              = $parentController->isHED($order);
        // TODO Se realiza ajuste para pedidos compuestos con mas productos diferentes a HED
        // $operationCenter    = $isHED ? '601' : config('erp_siesa.shopOperationCenterId');
        $operationCenter    = $isHED && count($order['line_items']) == 1 ? '601' : config('erp_siesa.shopOperationCenterId');
        $prefixNote         = $isHED && count($order['line_items']) == 1 ? 'HED - ' : '';
        $billingAddress     = $order['billing_address'];
        $isLocal            = $order['currency'] == 'COP';
        $document           = $parentController->getBuyerDocument($order);
        $sucursal           = $isLocal ? '001' : '010';
        $price_list         = $isLocal ? '001' : '014';
        $salesReason        = $isLocal ? '05' : '09';
        $businessUnit       = '102';
        $costCenter         = '4001';
        $date               = $order['created_at'] ? Carbon::parse($order['created_at'])->format('Ymd') : Carbon::now()->format('Ymd');
        $transaction = $parentController->getSuccessTransaction($order);
        $note = $prefixNote . 'Número de pedido:' . $order['order_number'] . ' - IDPAGO:' . $transaction['payment_id'];

        if (!$isLocal) {
            $client = new \GuzzleHttp\Client();
            $url = 'https://trm-colombia.vercel.app/?date=' . Carbon::now()->format('Y-m-d');
            $response = json_decode($client->get($url)->getBody()->getContents(), true);
            $TRM = $response['data']['value'];
        }

        $orders = [
            array(
                'f430_id_co'                => $operationCenter,
                'f430_consec_docto'         => '1',
                'f430_id_fecha'             => $date,
                'f430_id_tercero_fact'      => strtoupper($document ?? ''),
                'f430_id_sucursal_fact'     => $sucursal,
                'f430_id_tercero_rem'       => strtoupper($document ?? ''),
                'f430_id_sucursal_rem'      => $sucursal,
                'f430_id_tipo_cli_fact'     => $isHED ? 'CHED' : ($isLocal ? 'CTDS' : 'CTTI'),
                'f430_id_co_fact'           => $operationCenter,
                'f430_fecha_entrega'        => $date,
                'f430_num_docto_referencia' => $order['order_number'],
                'f430_referencia'           => $order['order_number'],
                'f430_id_moneda_docto'      => $order['currency'],  // PENDIENTE
                'f430_id_moneda_conv'       => 'COP',
                'f430_tasa_conv'            => $isLocal ? '1' : $TRM,
                'f430_tasa_local'           => $isLocal ? '1' : $TRM,
                'f430_id_cond_pago'         => 'CTD',
                'f430_notas'                => $note
            )
        ];

        // Mapeo de los productos de compra del pedido
        $items = [];
        $discounts = [];
        foreach ($order['line_items'] as $index => $item) {
            $properties = $item['properties'];
            if (!$item['product_exists']) {
                if (count($properties)) {
                    $quantity = $item['quantity'] ?? 1;
                    $includedItemsArray = array_map(fn($item) => $item['value'], $properties);
                    $includedItemsArray = array_filter($includedItemsArray, function ($value) {
                        return trim($value) !== '' && strlen($value) > 1;
                    });

                    $erpCustomItems = ErpCustomItem::select('reference', 'barcode', 'is_gift', 'amount')
                        ->where('active', true)
                        ->where('amount', '>', 0)
                        ->where('modules', 'like', '%shopify%')
                        ->where(function ($query) use ($includedItemsArray) {
                            foreach ($includedItemsArray as $item) {
                                $query->orWhereRaw("FIND_IN_SET(?, labels)", [$item]);
                            }
                        })
                        ->get();

                    foreach ($erpCustomItems as $erpCustomItem) {
                        $customItem = array(
                            'f431_id_co'                => $operationCenter,
                            'f431_consec_docto'         => '1',
                            'f431_nro_registro'         => ($index + 1),
                            'f431_referencia_item'      => $erpCustomItem->reference ?? '',
                            'f431_codigo_barras'        => $erpCustomItem->barcode ?? '',
                            'f431_id_bodega'            => config('erp_siesa.shopWarehouseId'),
                            'f431_id_motivo'            => $erpCustomItem->is_gift ? '08' : $salesReason,
                            'f431_id_co_movto'          => $operationCenter,
                            'f431_id_un_movto'          => $businessUnit,
                            'f431_id_ccosto_movto'      => $costCenter,
                            'f431_fecha_entrega'        => $date,
                            'f431_id_lista_precio'      => $erpCustomItem->is_gift ? ($isLocal ? '015' : '021') : $price_list,
                            'f431_id_unidad_medida'     => 'UND',
                            'f431_cant_pedida_base'     => $erpCustomItem->amount * $quantity,
                            'f431_precio_unitario'      => 1,
                            'f431_ind_precio'           => '1',
                            'f431_ind_obsequio'         => $erpCustomItem->is_gift ? '1' : '0',
                            'f431_ind_impto_asumido'    => $erpCustomItem->is_gift ? '1' : '0'
                        );
                        array_push($items, $customItem);
                    }

                    //---------------------------------------NUMBERS_AMOUNT---------------------------------------------
                    $numbers = array_filter($properties, function ($prop) {
                        return str_contains($prop['name'], 'Número');
                    }, ARRAY_FILTER_USE_BOTH);

                    $numberAmount = count($numbers) ? strlen(end($numbers)['value']) : 0;
                    //--------------------------------------/NUMBERS_AMOUNT---------------------------------------------

                    if ($numberAmount) {
                        if ($numberAmount == 1) $reference = '108440217';
                        if ($numberAmount == 2) $reference = '108440317';

                        $numberPropertieName = end($numbers)['name'];
                        $erpCustomItem = ErpCustomItem::select('reference', 'barcode', 'is_gift')
                            ->where('active', true)
                            ->where('amount', '>', 0)
                            ->where('modules', 'like', '%shopify%')
                            ->whereRaw("FIND_IN_SET(?, labels)", [$numberPropertieName])
                            ->first();

                        if (!$erpCustomItem) {
                            return array(
                                'r' => false,
                                'd' => 'No existe ítem de personalización para "' . $numberPropertieName . '"'
                            );
                        }

                        $customItem = array(
                            'f431_id_co'                => $operationCenter,
                            'f431_consec_docto'         => '1',
                            'f431_nro_registro'         => ($index + 1),
                            'f431_referencia_item'      => $erpCustomItem->reference ?? '', //$productVariant['sku'],
                            'f431_codigo_barras'        => $erpCustomItem->barcode ?? '',
                            'f431_id_bodega'            => config('erp_siesa.shopWarehouseId'),
                            'f431_id_motivo'            => $erpCustomItem->is_gift ? '08' : $salesReason,
                            'f431_id_co_movto'          => $operationCenter,
                            'f431_id_un_movto'          => $businessUnit,  // PENDIENTE = Valida en maestro, código de centro de operación del movimiento
                            'f431_id_ccosto_movto'      => $costCenter,  // PENDIENTE = Obligatorio si la cuenta contable exige ccosto. Valida en maestro, código de centro de costo del movimiento.
                            'f431_fecha_entrega'        => $date,
                            'f431_id_lista_precio'      => $erpCustomItem->is_gift ? ($isLocal ? '015' : '021') : $price_list,
                            'f431_id_unidad_medida'     => 'UND',
                            'f431_cant_pedida_base'     => $numberAmount * $quantity,
                            'f431_precio_unitario'      => 1,
                            'f431_ind_precio'           => '1',
                            'f431_ind_obsequio'         => $erpCustomItem->is_gift ? '1' : '0',
                            'f431_ind_impto_asumido'    => $erpCustomItem->is_gift ? '1' : '0'
                        );
                        array_push($items, $customItem);
                    }


                    //---------------------------------------LETTERS_AMOUNT---------------------------------------------
                    $letters = array_filter($properties, function ($prop) {
                        return str_contains($prop['name'], 'Nombre');
                    }, ARRAY_FILTER_USE_BOTH);
                    $lettersAmount =  count($letters) ? strlen(end($letters)['value']) : 0;
                    //--------------------------------------/LETTERS_AMOUNT---------------------------------------------

                    if ($lettersAmount) {
                        if ($numberAmount == 0) $reference = '108440117';
                        if ($numberAmount == 1) $reference = '108440417';
                        if ($numberAmount == 2) $reference = '108440517';

                        $lettersPropertieName = end($letters)['name'];
                        $erpCustomItem = ErpCustomItem::select('reference', 'barcode', 'is_gift')
                            ->where('active', true)
                            ->where('amount', '>', 0)
                            ->where('modules', 'like', '%shopify%')
                            ->whereRaw("FIND_IN_SET(?, labels)", [$lettersPropertieName])
                            ->first();

                        if (!$erpCustomItem) {
                            return array(
                                'r' => false,
                                'd' => 'No existe ítem de personalización para "' . $lettersPropertieName . '"'
                            );
                        }

                        $customItem = array(
                            'f431_id_co'                => $operationCenter,
                            'f431_consec_docto'         => '1',
                            'f431_nro_registro'         => ($index + 1),
                            'f431_referencia_item'      => $erpCustomItem->reference ?? '', //$productVariant['sku'],
                            'f431_codigo_barras'        => $erpCustomItem->barcode ?? '',
                            'f431_id_bodega'            => config('erp_siesa.shopWarehouseId'),
                            'f431_id_motivo'            => $erpCustomItem->is_gift ? '08' : $salesReason,
                            'f431_id_co_movto'          => $operationCenter,
                            'f431_id_un_movto'          => $businessUnit,  // PENDIENTE = Valida en maestro, código de centro de operación del movimiento
                            'f431_id_ccosto_movto'      => $costCenter,  // PENDIENTE = Obligatorio si la cuenta contable exige ccosto. Valida en maestro, código de centro de costo del movimiento.
                            'f431_fecha_entrega'        => $date,
                            'f431_id_lista_precio'      => $erpCustomItem->is_gift ? ($isLocal ? '015' : '021') : $price_list,
                            'f431_id_unidad_medida'     => 'UND',
                            'f431_cant_pedida_base'     => $lettersAmount * $quantity,
                            'f431_precio_unitario'      => 1,
                            'f431_ind_precio'           => '1',
                            'f431_ind_obsequio'         => $erpCustomItem->is_gift ? '1' : '0',
                            'f431_ind_impto_asumido'    => $erpCustomItem->is_gift ? '1' : '0'
                        );
                        array_push($items, $customItem);
                    }

                    if (isset($reference)) {
                        $customItem = array(
                            'f431_id_co'                => $operationCenter,
                            'f431_consec_docto'         => '1',
                            'f431_nro_registro'         => ($index + 1),
                            'f431_referencia_item'      => $reference, //$productVariant['sku'],
                            'f431_codigo_barras'        => '',
                            'f431_id_bodega'            => config('erp_siesa.shopWarehouseId'),
                            'f431_id_motivo'            => '05',  // PENDIENTE = 05	VENTAS TIENDAS, 08	OBSEQUIO COMERCIAL, 09	VENTAS TIENDAS EXPORTACION
                            'f431_id_co_movto'          => $operationCenter,
                            'f431_id_un_movto'          => $businessUnit,  // PENDIENTE = Valida en maestro, código de centro de operación del movimiento
                            'f431_id_ccosto_movto'      => $costCenter,  // PENDIENTE = Obligatorio si la cuenta contable exige ccosto. Valida en maestro, código de centro de costo del movimiento.
                            'f431_fecha_entrega'        => $date,
                            'f431_id_lista_precio'      => $price_list,
                            'f431_id_unidad_medida'     => 'UND',
                            'f431_cant_pedida_base'     => 1,
                            'f431_precio_unitario'      => 1,
                            'f431_ind_precio'           => '1',
                            'f431_ind_obsequio'         => '0',
                            'f431_ind_impto_asumido'    => '0'
                        );
                        array_push($items, $customItem);
                    }
                }
                continue;
            }

            $product = $parentController->getProduct($item['product_id'], $order['currency']);
            $reference = null;
            if ($product) {
                $productVariant = $parentController->searchProductVariant($product['variants'], $item['variant_id']);
                if ($productVariant) {
                    if (!$productVariant['barcode'] && $productVariant['sku']) {

                        $included = array_filter($properties, function ($prop) {
                            return $prop['name'] == 'Talla';
                        }, ARRAY_FILTER_USE_BOTH);

                        if (count($included) == 0) {
                            return array('r' => false, 'd' => 'El producto no tiene codigo de barras asociado y no se puede obtener desde el inventario');
                        }

                        $size = end($included)['value'];

                        $inventory = $this->getInventory($price_list, config('erp_siesa.shopWarehouseId'));
                        if ($inventory['r']) {
                            $inventory = array_filter($inventory['d']->detalle->Table, function ($inventoryProduct) use ($productVariant, $size) {
                                return $inventoryProduct->Referencia && $inventoryProduct->Referencia == $productVariant['sku'] && $inventoryProduct->Talla == $size;
                            }, ARRAY_FILTER_USE_BOTH);

                            if (count($inventory)) {
                                $productVariant['barcode'] = end($inventory)->CodigoDeBarras;
                            }
                        }
                    }

                    $isHEDMembership = $parentController->productHasMemberships($product);

                    $orderItem = array(
                        'f431_id_co'                => $operationCenter,
                        'f431_consec_docto'         => '1',
                        'f431_nro_registro'         => ($index + 1),
                        'f431_referencia_item'      => '', //$productVariant['sku'],
                        'f431_codigo_barras'        => $productVariant['barcode'],
                        'f431_id_bodega'            => $isHEDMembership ? 'BDHED' : config('erp_siesa.shopWarehouseId'),
                        'f431_id_motivo'            => $isHEDMembership ? '60'    : $salesReason,
                        'f431_id_co_movto'          => $isHEDMembership ? '601'   : $operationCenter,
                        'f431_id_un_movto'          => $isHEDMembership ? '104'   : $businessUnit,
                        'f431_id_ccosto_movto'      => $isHEDMembership ? '1201'  : $costCenter,
                        'f431_fecha_entrega'        => $date,
                        'f431_id_lista_precio'      => $price_list,
                        'f431_id_unidad_medida'     => 'UND',
                        'f431_cant_pedida_base'     => $item['quantity'],
                        'f431_precio_unitario'      => $item['price'],
                        'f431_ind_precio'           => '1',
                        'f431_ind_obsequio'         => '0',
                        'f431_ind_impto_asumido'    => '0'
                    );

                    array_push($items, $orderItem);

                    foreach ($item['discount_allocations'] as $index2 => $shippingDiscount) {
                        if ($shippingDiscount['amount'] > 0) {
                            $itemDiscount = array(
                                'f430_id_co'                => $operationCenter,
                                'f430_consec_docto'         => '1',
                                'f431_nro_registro'         => ($index + 1),
                                'f432_tasa'                 => '0000.000',
                                'f432_vlr_uni'              => $shippingDiscount['amount']
                            );
                            array_push($discounts, $itemDiscount);
                        }
                    }
                }
            }
        }

        foreach ($order['shipping_lines'] as $index => $item) {
            if ($item['price'] > 0) {
                $orderItem = array(
                    'f431_id_co'                => $operationCenter,
                    'f431_consec_docto'         => '1',
                    'f431_nro_registro'         => count($items) + 1,
                    'f431_referencia_item'      => $billingAddress['country_code'] == 'CO' ? '110440022' : '0001709',
                    'f431_codigo_barras'        => '',
                    'f431_id_bodega'            => $isHED ? 'BDHED' : config('erp_siesa.shopWarehouseId'),
                    'f431_id_motivo'            => '05',
                    'f431_id_co_movto'          => $operationCenter,
                    'f431_id_un_movto'          => $businessUnit,
                    'f431_id_ccosto_movto'      => '4001',
                    'f431_fecha_entrega'        => $date,
                    'f431_id_lista_precio'      => $isLocal ? '005' : '013',
                    'f431_id_unidad_medida'     => 'UND',
                    'f431_cant_pedida_base'     => '1',
                    'f431_precio_unitario'      => round($item['price']),
                    'f431_ind_precio'           => '2',
                    'f431_ind_obsequio'         => '0',
                    'f431_ind_impto_asumido'    => '0'
                );

                array_push($items, $orderItem);

                foreach ($item['discount_allocations'] as $index2 => $shippingDiscount) {
                    if ($shippingDiscount['amount'] > 0) {
                        $itemDiscount = array(
                            'f430_id_co'                => $operationCenter,
                            'f430_consec_docto'         => '1',
                            'f431_nro_registro'         => count($items),
                            'f432_tasa'                 => '0000.000',
                            'f432_vlr_uni'              => $shippingDiscount['amount']
                        );
                        array_push($discounts, $itemDiscount);
                    }
                }
            }
        }

        $erpCustomItems = ErpCustomItem::where('active', true)
            ->where('amount', '>', 0)
            ->where(function ($query) use ($isHED) {
                $query->orWhere('modules', 'like', '%shopify%');
                if ($isHED) {
                    $query->orWhere('modules', 'like', '%membership%');
                }
            })
            ->where(function ($query) {
                $query->orWhereNull('labels');
                $query->orWhere('labels', '');
            })
            ->get();

        foreach ($erpCustomItems as $erpCustomItem) {
            $customItem = array(
                'f431_id_co'                => $operationCenter,
                'f431_consec_docto'         => '1',
                'f431_nro_registro'         => count($items) + 1,
                'f431_referencia_item'      => $erpCustomItem->reference ?? '',
                'f431_codigo_barras'        => $erpCustomItem->barcode ?? '',
                'f431_id_bodega'            => $isHED ? 'BDHED' : config('erp_siesa.shopWarehouseId'),
                'f431_id_motivo'            => $erpCustomItem->is_gift ? '08' : $salesReason,
                'f431_id_co_movto'          => $isHED ? '601'   : $operationCenter,
                'f431_id_un_movto'          => $isHED ? '104'   : $businessUnit,
                'f431_id_ccosto_movto'      => $isHED ? '1201'  : $costCenter,
                'f431_fecha_entrega'        => $date,
                'f431_id_lista_precio'      => $erpCustomItem->is_gift ? ($isLocal ? '015' : '021') : $price_list,
                'f431_id_unidad_medida'     => 'UND',
                'f431_cant_pedida_base'     => $erpCustomItem->amount,
                'f431_precio_unitario'      => 1,
                'f431_ind_precio'           => '1',
                'f431_ind_obsequio'         => $erpCustomItem->is_gift ? '1' : '0',
                'f431_ind_impto_asumido'    => $erpCustomItem->is_gift ? '1' : '0'
            );
            array_push($items, $customItem);
        }

        $body = array(
            'Pedidos'                       => $orders,
            'MovtoPedidoscomercial'         => $items,
        );
        if (count($discounts))
            $body['Descuentos'] = $discounts;

        return array('r' => true, 'd' => $body);
    }

    public function mapDocumentType($typeDocument)
    {
        switch ($typeDocument) {
            case 'CC':
            case 'Cedula de Ciudadania':
            case 'cedula_ciudadania':
                return 'C';
            case 'CE':
            case 'Cedula de Extranjeria':
            case 'cedula_extranjeria':
                return 'E';
            case 'PA':
            case 'Pasaporte':
            case 'pasaporte':
                return 'P';
            case 'TI':
            case 'Tarjeta de identidad':
            case 'tarjeta_identidad':
                return 'T';
            case 'nit':
                return 'N';
            default:
                return 'O';
        }
    }

    public function mapDocumentTypeOrder($typeDocument)
    {
        return $this->mapDocumentType($typeDocument);
    }

    public function mapGender($gender)
    {
        switch ($gender) {
            case 'Hombre':
            case 'hombre':
            case 'M':
                return '2';
            case 'Mujer':
            case 'mujer':
            case 'F':
                return '1';
            default:
                return '0';
        }
    }

    private function mapTypeCustomerThird($type)
    {
        switch ($type) {
            case 'persona_juridica':
            case 'JURIDICAL_PERSON':
                return '2';
            case 'persona_natural':
            case 'NATURAL_PERSON':
                return '1';
            default:
                return '0';
        }
    }

    private function mapTypeCustomerThirdPos($type)
    {
        switch ($type) {
            case 'persona_juridica':
            case 'JURIDICAL_PERSON':
                return '1';
            default:
                return '0';
        }
    }

    public function createRC($parameters)
    {
        sleep(30);
        $params = $this->mapParams('rc');
        $response = $this->mapRCData($parameters);
        if (!$response['r']) {
            return $response;
        }

        $body = $response['d'];
        try {
            $responseGuzzle = $this->clientGuzzle->post('conectoresimportar' . $params, [
                \GuzzleHttp\RequestOptions::JSON    => $body,
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }

            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, $body);
        }
    }

    private function getNextRC($operationCenter)
    {
        $params = $this->mapParams('get_next_rc');
        $params .= '&parametros=' . 'IdCo=' . $operationCenter;
        try {
            $responseGuzzle = $this->clientGuzzle->get('ejecutarconsulta' . $params, [
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }
            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, __('messages.match_event_tickets.skip'));
        }
    }

    private function mapRCData($parameters)
    {
        $response = $this->getNextRC($parameters->siesaOrder->CentroDeOperacion);
        if (!$response['r'] || !isset($response['d']->detalle)) {
            return $response;
        }
        $nextRC = $response['d']->detalle->Table[0]->ProximoConsecutivo;
        $isLocal = $parameters->currency == 'COP';

        if (!$isLocal) {
            $client = new \GuzzleHttp\Client();
            $url = 'https://trm-colombia.vercel.app/?date=' . Carbon::now()->format('Y-m-d');
            $response = json_decode($client->get($url)->getBody()->getContents(), true);
            $TRM = $response['data']['value'];
        }

        $note = $parameters->siesaOrder->CentroDeOperacion . '-' . $parameters->siesaOrder->TipoDocumento . '-' . $parameters->siesaOrder->ConsecutivoDocto;
        $other = [
            array(
                'F350_ID_CO'                => $parameters->siesaOrder->CentroDeOperacion,
                'F350_ID_TIPO_DOCTO'        => 'RCI',
                'F350_CONSEC_DOCTO'         => $nextRC,
                'F350_FECHA'                => $parameters->paymentDate,
                'F357_ID_CAJA'              => '001',
                'F357_FECHA_RECAUDO'        => $parameters->paymentDate,
                'F350_ID_TERCERO'           => $parameters->idThird,
                'F357_ID_MONEDA_INGRESO'    => 'COP',
                'F357_VALOR_INGRESO'        => $isLocal ? $parameters->price : round($parameters->price * $TRM),
                'F357_ID_MONEDA_APLICAR'    => 'COP',
                'F357_ID_UN'                => '099',
                'F357_ID_FE'                => $parameters->fe,
                'F350_NOTAS'                => $parameters->note,
                'F357_REFERENCIA'           => $nextRC
            )
        ];

        $cashRegister = [
            array(
                'F350_ID_CO'                => $parameters->siesaOrder->CentroDeOperacion,
                'F350_ID_TIPO_DOCTO'        => 'RCI',
                'F350_CONSEC_DOCTO'         => $nextRC,
                'F358_ID_MEDIOS_PAGO'       => $parameters->paymetMethod,
                'F358_VALOR'                => $isLocal ? $parameters->price : round($parameters->price * $TRM),
                'F358_NRO_CUENTA'           => '',
                'F358_NRO_AUTORIZACION'     => '',
                'F358_FECHA_VCTO'           => $parameters->paymentDate,
                'F358_REFERENCIA_OTROS'     => $note,
                'F358_FECHA_CONSIGNACION'   => $parameters->paymentDate,
                'f358_docto_banco_cg'       => 'NC'
            )
        ];

        $movements = [
            array(
                'F350_ID_CO'                => $parameters->siesaOrder->CentroDeOperacion,
                'F350_ID_TIPO_DOCTO'        => 'RCI',
                'F350_CONSEC_DOCTO'         => $nextRC,
                'F351_ID_AUXILIAR'          => $parameters->assistant,
                'F351_ID_TERCERO'           => $parameters->idThird,
                'F351_ID_CO_MOV'            => $parameters->siesaOrder->CentroDeOperacion,
                'F351_ID_UN'                => $parameters->UN,
                'F351_VALOR_DB'             => '0',
                'F351_VALOR_CR'             => $isLocal ? $parameters->price : round($parameters->price * $TRM),
                'F351_VALOR_DB_ALT'         => '0',
                'F351_VALOR_CR_ALT'         => $isLocal ? '0' : $parameters->price,
                'F353_ID_SUCURSAL'          => $parameters->sucursal,
                'F353_ID_TIPO_DOCTO_CRUCE'  => 'RCI',
                'F353_CONSEC_DOCTO_CRUCE'   => $nextRC,
                'F353_FECHA_VCTO'           => $parameters->paymentDate,
                'F353_FECHA_DSCTO_PP'       => $parameters->paymentDate,
                "F354_TERCERO_VEND"         => "900430878",
                "F354_NOTAS"                => $note,
            )
        ];

        $body = array(
            'RCyotros ingresos' => $other,
            'Caja'              => $cashRegister,
            'MovimientoCxCV2'   => $movements
        );

        return array('r' => true, 'd' => $body);
    }

    public function getOrder($reference, $operationCenter = null)
    {
        $params = $this->mapParams('get_order');
        $params .= '&parametros=' . "NUMDOCTOREFE='" . ($reference ?? '-1') . "'|";
        $params .= 'IDCO=' . ($operationCenter ?? '-1');

        try {
            $responseGuzzle = $this->clientGuzzle->get('ejecutarconsulta' . $params, [
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }
            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, __('messages.match_event_tickets.skip'));
        }
    }

    public function createBill($parameters)
    {
        $params = $this->mapParams('bill');
        $response = $this->mapBillData($parameters);

        if (!$response['r']) {
            return $response;
        }

        $body = $response['d'];

        try {
            $responseGuzzle = $this->clientGuzzle->post('conectoresimportar' . $params, [
                \GuzzleHttp\RequestOptions::JSON    => $body,
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }

            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, $body);
        }
    }

    public function getRC($thirdDocument, $operationCenter, $date = '-1')
    {
        $params = $this->mapParams('get_rc');
        $params .= '&parametros=IdCo=' . $operationCenter;
        $params .= '|Fecha=' . $date;
        $params .= '|IdTercero=' . $thirdDocument;

        try {
            $responseGuzzle = $this->clientGuzzle->get('ejecutarconsulta' . $params, [
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }
            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, __('messages.match_event_tickets.skip'));
        }
    }

    private function mapBillData($parameters)
    {
        $response = $this->getRC($parameters->thirdDocument, $parameters->siesaOrder->CentroDeOperacion);
        if (!$response['r'] || !isset($response['d']->detalle)) {
            return $response;
        }

        $previousRC = array_filter($response['d']->detalle->Table, function ($item) use ($parameters) {
            return str_contains($item->Notas, $parameters->note);
        }, ARRAY_FILTER_USE_BOTH);

        $date = Carbon::now()->format('Ymd');

        $sales = [
            array(
                'F350_ID_CO'                => $parameters->siesaOrder->CentroDeOperacion,
                'F350_ID_TIPO_DOCTO'        => $parameters->typeDocument,
                'F350_CONSEC_DOCTO'         => '1',                                             // Validar si el tipo de documento se manejaria el mismo para ventas nacionales o internacionales, lo recomendado es que a futuro se pueda diligenciar desde la tienda.
                'F350_FECHA'                => $date,                                              //
                'F430_ID_TIPO_DOCTO'        => $parameters->siesaOrder->TipoDocumento,
                'F430_CONSEC_DOCTO'         => $parameters->siesaOrder->ConsecutivoDocto,
                'f462_notas'                => $parameters->siesaOrder->CentroDeOperacion . '-' . $parameters->siesaOrder->TipoDocumento . '-' . $parameters->siesaOrder->ConsecutivoDocto
            )
        ];

        $fees = [
            array(
                'F350_ID_CO'                => $parameters->siesaOrder->CentroDeOperacion,
                'F350_ID_TIPO_DOCTO'        => $parameters->typeDocument,
                'F350_CONSEC_DOCTO'         => '1',                                             // Validar si el tipo de documento se manejaria el mismo para ventas nacionales o internacionales, lo recomendado es que a futuro se pueda diligenciar desde la tienda.
                'F353_ID_TIPO_DOCTO_CRUCE'  => 'RCI',                                              //
                'F353_CONSEC_DOCTO_CRUCE'   => end($previousRC)->ConsecutivoDocto,
                'F353_VLR_CRUCE'            => $parameters->siesaOrder->ValorPedido,
                'F353_FECHA_VCTO'           => $date,
                'F353_FECHA_DSCTO_PP'       => $date,
            )
        ];

        $body = array(
            'Doctoventascomercial' => $sales,
            'CuotasCxC'            => $fees
        );

        return array('r' => true, 'd' => $body);
    }

    public function getInventory($priceList, $locationName)
    {
        $params = $this->mapParams('get_inventory');
        $params .= "IdBodega=" . $locationName .  "|IdListaDePrecio=" . $priceList;

        try {
            $responseGuzzle = $this->clientGuzzle->get('ejecutarconsulta' . $params, [
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }
            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, __('messages.match_event_tickets.skip'));
        }
    }

    public function getBill($reference)
    {
        $params = $this->mapParams('get_bill');
        $params .= "IdTipoDocto=-1|IdCentroOP=-1|ConsecutiDocto=-1|Referencia=" . $reference;
        try {
            $responseGuzzle = $this->clientGuzzle->get('ejecutarconsulta' . $params, [
                'headers'                           => $this->headers
            ]);

            $body = (string) $responseGuzzle->getBody();
            if ($responseGuzzle->getStatusCode() == 200) {
                $body = json_decode($body);
            }
            return array('r' => true, 'd' => $body);
        } catch (RequestException $e) {
            return $this->buildErrorResponseData($e, __('messages.match_event_tickets.skip'));
        }
    }

    public function hasPreviousBill($reference)
    {
        $previousBill = $this->getBill($reference);
        if ($previousBill['r'] && count($previousBill['d']->detalle->Table)) {
            return array('r' => true, 'd' => $previousBill['d']->detalle->Table);
        }
        return $previousBill;
    }

    public function hasPreviousOrder($reference, $transactionReference, $transactionId)
    {
        $response = $this->getOrder($reference);
        if ($response['r']) {
            $previousOrders = array_filter(
                $response['d']->detalle->Table,
                function ($siesaOrder) use ($transactionReference, $transactionId) {
                    return str_contains($siesaOrder->Notas, $transactionId) || str_contains($siesaOrder->Notas, $transactionReference);
                },
                ARRAY_FILTER_USE_BOTH
            );

            if (count($previousOrders)) {
                return true;
            }
        }

        return false;
    }

    public function generateOrderItem($parameters)
    {
        return array(
            'f431_id_co'                => $parameters->operation_center,
            'f431_consec_docto'         => '1',
            'f431_nro_registro'         => '1',
            'f431_referencia_item'      => $parameters->serviceCode,
            'f431_codigo_barras'        => '',
            'f431_id_bodega'            => $parameters->warehouse,
            'f431_id_motivo'            => $parameters->reason ?? '06',
            'f431_id_co_movto'          => $parameters->operation_center,
            'f431_id_un_movto'          => $parameters->un ?? '100',
            'f431_id_ccosto_movto'      => $parameters->cost_center,
            'f431_fecha_entrega'        => $parameters->date,
            'f431_id_lista_precio'      => $parameters->price_list,
            'f431_id_unidad_medida'     => 'UND',
            'f431_cant_pedida_base'     => '1',
            'f431_precio_unitario'      => $parameters->fullPrice,
            'f431_ind_precio'           => '2',
            'f431_ind_obsequio'         => '0',
            'f431_ind_impto_asumido'    => '0'
        );
    }

    public function createCreditNote($parameters) {}

    public function getNextReference($reference)
    {
        return $reference;
    }

    public function getDefaultAddress($userId)
    {
        $addressController =  new AddressController;
        $addressId = $addressController->create(
            "Generada automaticamente",
            "Calle 90 #19-41, Bogotá, Bogotá, Colombia",
            "",
            "",
            null,
            null,
            null,
            $userId
        );

        return  $addressId;
    }

    private function replace_special_chars($string): string
    {
        if (!$string) {
            return '';
        }
        return str_replace([
            '&amp;',
            '\u{c001}',
            '|',
            '\\',
            '/',
        ], '-', trim($string));
    }

    function buildErrorResponseData($error, $body)
    {
        $response = $error->getResponse();
        $data = new \stdClass();
        $data->response = json_decode((string) $response->getBody());
        $data->url = stripslashes(urldecode((string) $error->getRequest()->getUri()));
        $data->body = $body;

        return array('r' => false, 'd' => $data, 'm' => $error->getMessage());
    }
}