<?php
/*
    Desarrollador: Ing. Jean Jairo Benitez Meza
    Ultima Modificación: 11/04/2023
    Módulo: Gestión de Adquisiciones
*/
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Controllers\ResponseController;
use App\Http\Controllers\EncryptionController;
use App\Http\Controllers\FunctionsController;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use \Mpdf\Mpdf as PDF; 

use PhpOffice\PhpSpreadsheet\Calculation\Category;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
use PhpOffice\PhpSpreadsheet\Worksheet\Table\TableStyle;


class ProviderController extends Controller{

    private $responseController;
    private $encController;
    private $resourcesController;
    private $functionsController;

    private $arrAlphabet = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","U","V","W","X","Y","Z");

    private $arrHeader = array(
        array(
            'POSITION' => 'A',
            'CODE' => 'ARTI_IDAR',
            'COLUMN' => 'ID Artículo',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'B',
            'CODE' => 'ARTI_NOMB',
            'COLUMN' => 'Artículo',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'C',
            'CODE' => 'FAMI_NOMB',
            'COLUMN' => 'Familia',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'D',
            'CODE' => 'SUBF_NOMB',
            'COLUMN' => 'Subfamilia',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'E',
            'CODE' => 'ARTI_CODI',
            'COLUMN' => 'Código de Barra',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'F',
            'CODE' => 'DEAR_COWE',
            'COLUMN' => 'Compra Web',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'G',
            'CODE' => 'DEAR_IDUN',
            'COLUMN' => 'Tipo de Unidad',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'H',
            'CODE' => 'DEAR_DESC',
            'COLUMN' => 'Descripción',
            'OBLIGATORY' => true
        ),
        array(
            'POSITION' => 'I',
            'CODE' => 'DEAR_CARA',
            'COLUMN' => 'Características',
            'OBLIGATORY' => false
        ),
    );

    private $arrHeaderDetails = array(
        array(
            'POSITION' => 'A',
            'CODE' => 'INAR_IDIN',
            'COLUMN' => 'ID Detalle',
            'OBLIGATORY' => true,
        ),
        array(
            'POSITION' => 'B',
            'CODE' => 'INAR_CODI',
            'COLUMN' => 'Código',
            'OBLIGATORY' => true,
        ),
        array(
            'POSITION' => 'C',
            'CODE' => 'INAR_MODE',
            'COLUMN' => 'Modelo',
            'OBLIGATORY' => true,
        ),
        array(
            'POSITION' => 'D',
            'CODE' => 'INAR_PREC',
            'COLUMN' => 'Precio',
            'OBLIGATORY' => true,
        ),
        array(
            'POSITION' => 'E',
            'CODE' => 'INAR_MONE',
            'COLUMN' => 'Moneda',
            'OBLIGATORY' => true,
        ),
        array(
            'POSITION' => 'F',
            'CODE' => 'INAR_MOMI',
            'COLUMN' => 'Monto Mínimo',
            'OBLIGATORY' => true,
        ),
        array(
            'POSITION' => 'G',
            'CODE' => 'INAR_CARA',
            'COLUMN' => 'Características',
            'OBLIGATORY' => true,
        ),
    );

    public function __construct() {
        $this->responseController = new ResponseController();
        $this->encController = new EncryptionController();
        $this->resourcesController = new ResourcesController();
        $this->functionsController = new FunctionsController();
    }

    public function getAllProvider($line){
        try {
            $arrProvider = DB::table('S002V01TPROV')
                ->where('PROV_NULI', '=', $line)
                ->join('S002V01TREFI', 'REFI_CRFI', '=', 'PROV_CRFI')
                ->get([
                    'PROV_NUPR AS NUMERO_PROVEEDOR',
                    'PROV_NOCO AS RAZON_SOCIAL',
                    'PROV_NOMB AS NOMBRE',
                    'PROV_APPA AS PRIMER_APELLIDO',
                    'PROV_APMA AS SEGUNDO_APELLIDO',
                    'PROV_CORR AS CORREO',
                    'PROV_LAD1 AS LADA1',
                    'PROV_TEL1 AS TELEFONO1',
                    'PROV_LAD2 AS LADA2',
                    'PROV_TEL2 AS TELEFONO2',
                    'PROV_XRFC AS RFC',
                    'PROV_XTAX AS TAXID',
                    'PROV_CRFI AS REGIMEN_FISCAL',
                    DB::raw('CONCAT(REFI_DRFI, " (", REFI_CRFI, ")") AS REGIMEN_FISCAL'),
                    'PROV_TIPO AS TIPO',
                    'PROV_TICO AS TIPO_CONTRIBUYENTE',
                    'PROV_SIWE AS SITIOWEB',
                    'PROV_MEPA AS METODO_PAGO',
                    'PROV_ESTA AS ESTADO',
                    'PROV_USRE AS USUARIO_REGISTRA',
                    'PROV_FERE AS FECHA_REGISTRA',
                    'PROV_USMO AS USUARIO_MODIFICA',
                    'PROV_FEMO AS FECHA_MODIFICA',
                    'PROV_CALL AS CALLE',
                    'PROV_NUEX AS EXTERIOR',
                    'PROV_NUIN AS INTERIOR',
                    'PROV_COPO AS CODIGO_POSTAL',
                    'PROV_COLO AS COLONIA',
                    'PROV_LOCA AS LOCALIDAD',
                    'PROV_MUNI AS MUNICIPIO',
                    'PROV_ENTI AS ENTIDAD',
                    'PROV_PAIS AS PAIS',
                ]);


            $arrResponse = array();
            foreach ($arrProvider as $provider) {
                $provider = (array) $provider;
                $provider['SEGUNDO_APELLIDO'] = $provider['SEGUNDO_APELLIDO'] == null ? '' : $provider['SEGUNDO_APELLIDO'];

                $arrReferences = DB::table('S002V01TPRRE')
                    ->where('PRRE_NULI', '=', $line)
                    ->where('PRRE_ESTA', '=', 'Activo')
                    ->where('PRRE_NUPR', '=', $provider['NUMERO_PROVEEDOR'])
                    ->get([
                        'PRRE_IDRE AS NUMERO_REFERENCIA',
                        'PRRE_EMPR AS RAZON_SOCIAL',
                        'PRRE_CORR AS CORREO',
                        'PRRE_LADA AS LADA',
                        'PRRE_TELE AS TELEFONO',
                        'PRRE_XRFC AS RFC',
                        'PRRE_DIRE AS DIRECCION',
                        'PRRE_ESTA AS ESTADO',
                        'PRRE_USRE AS USUARIO_REGISTRA',
                        'PRRE_FERE AS FECHA_REGISTRA',
                        'PRRE_USMO AS USUARIO_MODIFICA',
                        'PRRE_FEMO AS FECHA_MODIFICA',
                    ]);

                $arrContacts = DB::table('S002V01TPRCO')
                    ->where('PRCO_NULI', '=', $line)
                    ->where('PRCO_ESTA', '=', 'Activo')
                    ->where('PRCO_NUPR', '=', $provider['NUMERO_PROVEEDOR'])
                    ->get([
                        'PRCO_IDCP AS NUMERO_CONTACTO',
                        'PRCO_NOMB AS NOMBRE_CONTACTO',
                        'PRCO_TIPO AS TIPO_CONTACTO',
                        'PRCO_CALL AS CALLE',
                        'PRCO_NUEX AS NUMERO_EXTERIOR',
                        'PRCO_NUIN AS NUMERO_INTERIOR',
                        'PRCO_COPO AS CODIGO_POSTAL',
                        'PRCO_COLO AS COLONIA',
                        'PRCO_LOCA AS LOCALIDAD',
                        'PRCO_MUNI AS MUNICIPIO',
                        'PRCO_ENTI AS ENTIDAD',
                        'PRCO_PAIS AS PAIS',
                        'PRCO_LAD1 AS LADA1',
                        'PRCO_TEL1 AS TELEFONO1',
                        'PRCO_LAD2 AS LADA2',
                        'PRCO_TEL2 AS TELEFONO2',
                        'PRCO_COR1 AS CORREO1',
                        'PRCO_COR2 AS CORREO2',
                        'PRCO_OBSE AS OBSERVACIONES',
                        'PRCO_ESTA AS ESTADO',
                        'PRCO_USRE AS USUARIO_REGISTRA',
                        'PRCO_FERE AS FECHA_REGISTRA',
                        'PRCO_USMO AS USUARIO_MODIFICA',
                        'PRCO_FEMO AS FECHA_MODIFICA',
                    ]);

                $arrConditions = DB::table('S002V01TPRCN')
                    ->where('PRCN_NULI', '=', $line)
                    ->where('PRCN_ESTA', '=', 'Activo')
                    ->where('PRCN_NUPR', '=', $provider['NUMERO_PROVEEDOR'])
                    ->get([
                        'PRCN_IDCM AS NUMERO_CONDICION',
                        'PRCN_TIPO AS TIPO_CONDICION',
                        'PRCN_INFO AS INFORMACION',
                        'PRCN_ESTA AS ESTADO',
                        'PRCN_USRE AS USUARIO_REGISTRA',
                        'PRCN_FERE AS FECHA_REGISTRA',
                        'PRCN_USMO AS USUARIO_MODIFICA',
                        'PRCN_FEMO AS FECHA_MODIFICA',
                    ]);

                $arrCatalogs = DB::table('S002V01TPRCE')
                    ->where('PRCE_NULI', '=', $line)
                    ->where('PRCE_ESTA', '=', 'Activo')
                    ->where('PRCE_NUPR', '=', $provider['NUMERO_PROVEEDOR'])
                    ->get([
                        'PRCE_IDCE AS NUMERO_CATALAGO',
                        'PRCE_CATA AS CATALAGO',
                        'PRCE_DESC AS DESCRIPCION',
                        'PRCE_XURL AS URL_CATALAGO',
                        'PRCE_ESTA AS ESTADO',
                        'PRCE_USRE AS USUARIO_REGISTRA',
                        'PRCE_FERE AS FECHA_REGISTRA',
                        'PRCE_USMO AS USUARIO_MODIFICA',
                        'PRCE_FEMO AS FECHA_MODIFICA',
                    ]);


                $arrPayment = json_decode($provider['METODO_PAGO']);

                $arrPaymentFormat = array();
                foreach ($arrPayment as $key => $payment) {
                    $arrPaymentFormat[] = [
                        'MEPA_IDME' => $key,
                        'MEPA_NOMB' => $payment,
                    ];
                }

                $provider['REFERENCIAS'] = $arrReferences;
                $provider['CONTACTOS'] = $arrContacts;
                $provider['CONDICIONES'] = $arrConditions;
                $provider['CATALAGOS'] = $arrCatalogs;
                $provider['METODOS_PAGO'] = $arrPaymentFormat;

                $arrResponse[] = $provider;
            }


        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_GET000: No se pudo realizar la consulta a la base.", $th->getMessage(), 500);
        }

        return $this->responseController->makeResponse(false, "ÉXITO: Consulta Exitosa", $arrResponse);
    }

    public function getProvidersActives($line) {
        try {
            $arrProvider = DB::table('S002V01TPROV')
                ->where('PROV_ESTA', '=', 'Activo')
                ->where('PROV_NULI', '=', $line)
                ->get([
                    'PROV_NUPR AS NUMERO_PROVEEDOR',
                    'PROV_NOCO AS RAZON_SOCIAL',
                    'PROV_NOMB AS NOMBRE',
                    'PROV_APPA AS PRIMER_APELLIDO',
                    'PROV_APMA AS SEGUNDO_APELLIDO',
                    'PROV_CORR AS CORREO',
                    'PROV_LAD1 AS LADA1',
                    'PROV_TEL1 AS TELEFONO1',
                    'PROV_LAD2 AS LADA2',
                    'PROV_TEL2 AS TELEFONO2',
                    'PROV_TICO AS TIPO_CONTRIBUYENTE',
                    'PROV_XRFC AS RFC',
                    'PROV_XTAX AS TAXID',
                    'PROV_CRFI AS REGIMEN_FISCAL',
                    'PROV_TIPO AS TIPO',
                    'PROV_SIWE AS SITIOWEB',
                    'PROV_MEPA AS METODO_PAGO',
                    'PROV_USRE AS USUARIO_REGISTRA',
                    'PROV_FERE AS FECHA_REGISTRA',
                    'PROV_USMO AS USUARIO_MODIFICA',
                    'PROV_FEMO AS FECHA_MODIFICA',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_GETACTIVE000: No se pudo realizar la consulta a la base.", $th->getMessage(), 500);
        }
        return $this->responseController->makeResponse(false, "ÉXITO: Consulta Exitosa", $arrProvider);
    }

    public function getProvidersByNumber($provider, $line) {
        try {
            $arrProvider = DB::table('S002V01TPROV')
                ->where('PROV_NUPR', '=', $provider)
                ->where('PROV_ESTA', '=', 'Activo')
                ->where('PROV_NULI', '=', $line)
                ->first([
                    'PROV_NUPR AS NUMERO_PROVEEDOR',
                    'PROV_NOCO AS RAZON_SOCIAL',
                    'PROV_NOMB AS NOMBRE',
                    'PROV_APPA AS PRIMER_APELLIDO',
                    'PROV_APMA AS SEGUNDO_APELLIDO',
                    'PROV_CORR AS CORREO',
                    'PROV_LAD1 AS LADA1',
                    'PROV_TEL1 AS TELEFONO1',
                    'PROV_LAD2 AS LADA2',
                    'PROV_TEL2 AS TELEFONO2',
                    'PROV_TICO AS TIPO_CONTRIBUYENTE',
                    'PROV_XRFC AS RFC',
                    'PROV_XTAX AS TAXID',
                    'PROV_CRFI AS REGIMEN_FISCAL',
                    'PROV_TIPO AS TIPO',
                    'PROV_SIWE AS SITIOWEB',
                    'PROV_MEPA AS METODO_PAGO',
                    'PROV_USRE AS USUARIO_REGISTRA',
                    'PROV_FERE AS FECHA_REGISTRA',
                    'PROV_USMO AS USUARIO_MODIFICA',
                    'PROV_FEMO AS FECHA_MODIFICA',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_GETBYNUMBER000: No se pudo realizar la consulta a la base.", $th->getMessage(), 500);
        }
        return $this->responseController->makeResponse(false, "ÉXITO: Consulta Exitosa", $arrProvider);

    }

    public function updateProvider(Request $request) {
        $validator = Validator::make($request->all(), [
            'line' => 'required|string',
            'user' => 'required|string',
            'obj_response' => 'required',
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_PROVIDER_MOD000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        DB::beginTransaction();
        $requestData = $request->all();
        $line = $requestData['line'];

        try {
            $user = $this->encController->decrypt($request['user']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD001: No se pudo obtener el usuario.", $th->getMessage(), 500);
        }

        $arrInformationPersonal = $requestData['obj_response']['INFORMACION'];
        $arrReferences = $requestData['obj_response']['REFERENCIAS'];
        $arrContacts = $requestData['obj_response']['CONTACTOS'];
        $arrConditions = $requestData['obj_response']['CONDICIONES'];
        $arrPaymentMedia = $requestData['obj_response']['METODOS_PAGO'];
        $arrCatalogs = $requestData['obj_response']['CATALAGOS'];

        $numeroProveedor = $arrInformationPersonal['NUMERO_PROVEEDOR'];

        $now = $this->functionsController->now();
        $currentDate = $now->toDateTimeString();

        $arrPaymentTemp = array();
        foreach ($arrPaymentMedia as $payment) {
            $arrPaymentTemp[$payment['MEPA_IDME']] = $payment['MEPA_NOMB'];
        }
        try {
            $strPayment = json_encode($arrPaymentTemp);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD003: Ocurrió un error al obtener los datos del método de pago.", $th->getMessage(), 500);
        }

        
        try {
            $validateUpdateInformation = DB::table('S002V01TPROV')
                ->where('PROV_NUPR', '=', $numeroProveedor)
                ->where('PROV_NULI', '=', $line)
                ->update([
                    'PROV_NOCO' => $arrInformationPersonal['RAZON_SOCIAL'],
                    'PROV_NOMB' => $arrInformationPersonal['NOMBRE'],
                    'PROV_APPA' => $arrInformationPersonal['PRIMER_APELLIDO'],
                    'PROV_APMA' => $arrInformationPersonal['SEGUNDO_APELLIDO'] != '' ? $arrInformationPersonal['SEGUNDO_APELLIDO'] : null,
                    'PROV_CORR' => $arrInformationPersonal['CORREO'],
                    'PROV_LAD1' => $arrInformationPersonal['LADA1'],
                    'PROV_TEL1' => $arrInformationPersonal['TELEFONO1'],
                    'PROV_LAD2' => $arrInformationPersonal['LADA2'] != '' ? $arrInformationPersonal['LADA2'] : null,
                    'PROV_TEL2' => $arrInformationPersonal['TELEFONO2'] != '' ? $arrInformationPersonal['TELEFONO2'] : null,
                    'PROV_TICO' => $arrInformationPersonal['TIPO_CONTRIBUYENTE'],
                    'PROV_XRFC' => $arrInformationPersonal['RFC'],
                    'PROV_XTAX' => $arrInformationPersonal['TAXID'] != '' ? $arrInformationPersonal['TAXID'] : null,
                    'PROV_CRFI' => $arrInformationPersonal['REGIMEN_FISCAL'],
                    'PROV_TIPO' => $arrInformationPersonal['TIPO'],
                    'PROV_SIWE' => $arrInformationPersonal['SITIOWEB'],
                    'PROV_MEPA' => $strPayment,
                    'PROV_CALL' => $arrInformationPersonal['CALLE'],
                    'PROV_NUEX' => $arrInformationPersonal['EXTERIOR'],
                    'PROV_NUIN' => $arrInformationPersonal['INTERIOR'],
                    'PROV_COPO' => $arrInformationPersonal['CODIGO_POSTAL'],
                    'PROV_COLO' => $arrInformationPersonal['COLONIA'],
                    'PROV_LOCA' => $arrInformationPersonal['LOCALIDAD'],
                    'PROV_MUNI' => $arrInformationPersonal['MUNICIPIO'],
                    'PROV_ENTI' => $arrInformationPersonal['ENTIDAD'],
                    'PROV_PAIS' => $arrInformationPersonal['PAIS'],
                    'PROV_USMO' => $user,
                    'PROV_FEMO' => $currentDate,
                    'PROV_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD005: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }
        if (!$validateUpdateInformation) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD004: Ocurrió un error al obtener el contenido.", [], 500);
        }


        foreach ($arrReferences as $references) {
            if ($references['ESTADO'] == 'Activo' || $references['ESTADO'] == 'Modificado') {
                try {
                    $validateUpdateReference = DB::table('S002V01TPRRE')
                        ->where('PRRE_IDRE', '=', $references['NUMERO_REFERENCIA'])
                        ->where('PRRE_NUPR', '=', $numeroProveedor)
                        ->where('PRRE_NULI', '=', $line)
                        ->update([
                            'PRRE_EMPR' => $references['RAZON_SOCIAL'],
                            'PRRE_CORR' => $references['CORREO'],
                            'PRRE_LADA' => $references['LADA'],
                            'PRRE_TELE' => $references['TELEFONO'],
                            'PRRE_XRFC' => $references['RFC'],
                            'PRRE_DIRE' => $references['DIRECCION'],
                            'PRRE_USMO' => $user,
                            'PRRE_FEMO' => $currentDate,
                            'PRRE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                        ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD007: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateUpdateReference) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD006: Ocurrió un error al obtener el contenido. ", [], 500);
                }
            } else if ($references['ESTADO'] == 'Nuevo') {
                try {
                    $validateInsertReference = DB::table('S002V01TPRRE')->insert([
                        'PRRE_NUPR' => $numeroProveedor,
                        'PRRE_EMPR' => $references['RAZON_SOCIAL'],
                        'PRRE_CORR' => $references['CORREO'],
                        'PRRE_LADA' => $references['LADA'],
                        'PRRE_TELE' => $references['TELEFONO'],
                        'PRRE_XRFC' => $references['RFC'],
                        'PRRE_DIRE' => $references['DIRECCION'],
                        'PRRE_NULI' => $line,
                        'PRRE_USRE' => $user,
                        'PRRE_FERE' => $currentDate,
                        'PRRE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                    ]); 
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD009: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateInsertReference) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD008: Ocurrió un error al obtener el contenido.", [], 500);
                }
            } else if ($references['ESTADO'] == 'Eliminado'){
                try {
                    $validateUpdateReference = DB::table('S002V01TPRRE')
                        ->where('PRRE_IDRE', '=', $references['NUMERO_REFERENCIA'])
                        ->where('PRRE_NUPR', '=', $numeroProveedor)
                        ->where('PRRE_NULI', '=', $line)
                        ->update([
                            'PRRE_ESTA' => 'Eliminado',
                            'PRRE_USMO' => $user,
                            'PRRE_FEMO' => $currentDate,
                            'PRRE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                        ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD011: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateUpdateReference) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD010: Ocurrió un error al obtener el contenido.", [], 500);
                }
            }
        }

        foreach ($arrContacts as $contacts) {
            if ($contacts['ESTADO'] == 'Activo' || $contacts['ESTADO'] == 'Modificado') {
                try {
                    $validateUpdateContact = DB::table('S002V01TPRCO')
                        ->where('PRCO_IDCP', '=', $contacts['NUMERO_CONTACTO'])
                        ->where('PRCO_NUPR', '=', $numeroProveedor)
                        ->where('PRCO_NULI', '=', $line)
                        ->update([
                            'PRCO_NOMB' => $contacts['NOMBRE_CONTACTO'],
                            'PRCO_TIPO' => $contacts['TIPO_CONTACTO'],
                            'PRCO_CALL' => $contacts['CALLE'],
                            'PRCO_NUEX' => $contacts['NUMERO_EXTERIOR'],
                            'PRCO_NUIN' => $contacts['NUMERO_INTERIOR'] != '' ? $contacts['NUMERO_INTERIOR'] : null,
                            'PRCO_COPO' => $contacts['CODIGO_POSTAL'],
                            'PRCO_COLO' => $contacts['COLONIA'],
                            'PRCO_LOCA' => $contacts['LOCALIDAD'],
                            'PRCO_MUNI' => $contacts['MUNICIPIO'],
                            'PRCO_ENTI' => $contacts['ENTIDAD'],
                            'PRCO_PAIS' => $contacts['PAIS'],
                            'PRCO_TEL1' => $contacts['TELEFONO1'],
                            'PRCO_TEL2' => $contacts['TELEFONO2'] != '' ? $contacts['TELEFONO2'] : null,
                            'PRCO_COR1' => $contacts['CORREO1'],
                            'PRCO_COR2' => $contacts['CORREO2'] != '' ? $contacts['CORREO2'] : null,
                            'PRCO_OBSE' => $contacts['OBSERVACIONES'],
                            'PRCO_USMO' => $user,
                            'PRCO_FEMO' => $currentDate,
                            'PRCO_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                        ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD013: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateUpdateContact) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD012: Ocurrió un error al obtener el contenido.", [], 500);
                }
            } else if ($contacts['ESTADO'] == 'Nuevo') {
                try {
                    $validateInsertContact = DB::table('S002V01TPRCO')->insert([
                        'PRCO_NUPR' => $numeroProveedor,
                        'PRCO_NOMB' => $contacts['NOMBRE_CONTACTO'],
                        'PRCO_TIPO' => $contacts['TIPO_CONTACTO'],
                        'PRCO_CALL' => $contacts['CALLE'],
                        'PRCO_NUEX' => $contacts['NUMERO_EXTERIOR'],
                        'PRCO_NUIN' => $contacts['NUMERO_INTERIOR'] != '' ? $contacts['NUMERO_INTERIOR'] : null,
                        'PRCO_COPO' => $contacts['CODIGO_POSTAL'],
                        'PRCO_COLO' => $contacts['COLONIA'],
                        'PRCO_LOCA' => $contacts['LOCALIDAD'],
                        'PRCO_MUNI' => $contacts['MUNICIPIO'],
                        'PRCO_ENTI' => $contacts['ENTIDAD'],
                        'PRCO_PAIS' => $contacts['PAIS'],
                        'PRCO_LAD1' => $contacts['LADA1'],
                        'PRCO_TEL1' => $contacts['TELEFONO1'],
                        'PRCO_LAD2' => $contacts['LADA2'] != '' ? $contacts['LADA2'] : null,
                        'PRCO_TEL2' => $contacts['TELEFONO2'] != '' ? $contacts['TELEFONO2'] : null,
                        'PRCO_COR1' => $contacts['CORREO1'],
                        'PRCO_COR2' => $contacts['CORREO2'] != '' ? $contacts['CORREO2'] : null,
                        'PRCO_OBSE' => $contacts['OBSERVACIONES'],
                        'PRCO_NULI' => $line,
                        'PRCO_USRE' => $user,
                        'PRCO_FERE' => $currentDate,
                        'PRCO_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                    ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD015: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateInsertContact) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD014: Ocurrió un error al obtener el contenido.", [], 500);
                }
            } else if ($contacts['ESTADO'] == 'Eliminado'){
                try {
                    $validateUpdateContact = DB::table('S002V01TPRCO')
                        ->where('PRCO_IDCP', '=', $contacts['NUMERO_CONTACTO'])
                        ->where('PRCO_NUPR', '=', $numeroProveedor)
                        ->where('PRCO_NULI', '=', $line)
                        ->update([
                            'PRCO_ESTA' => 'Eliminado',
                            'PRCO_USMO' => $user,
                            'PRCO_FEMO' => $currentDate,
                            'PRCO_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                        ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD017: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateUpdateContact) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD016: Ocurrió un error al obtener el contenido.", [], 500);
                }
            }
        }

        foreach ($arrConditions as $conditions) {
            if ($conditions['ESTADO'] == 'Activo' || $conditions['ESTADO'] == 'Modificado') {
                try {
                    $validateUpdateCondition = DB::table('S002V01TPRCN')
                        ->where('PRCN_IDCM', '=', $conditions['NUMERO_CONDICION'])
                        ->where('PRCN_NUPR', '=', $numeroProveedor)
                        ->where('PRCN_NULI', '=', $line)
                        ->update([
                            'PRCN_TIPO' => $conditions['TIPO_CONDICION'],
                            'PRCN_INFO' => $conditions['INFORMACION'],
                            'PRCN_USMO' => $user,
                            'PRCN_FEMO' => $currentDate,
                            'PRCN_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                        ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD019: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateUpdateCondition) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD018: Ocurrió un error al obtener el contenido.", [], 500);
                }
            } else if ($conditions['ESTADO'] == 'Nuevo'){
                try {
                    $validateInsertCondition = DB::table('S002V01TPRCN')->insert([
                        'PRCN_NUPR' => $numeroProveedor,
                        'PRCN_TIPO' => $conditions['TIPO_CONDICION'],
                        'PRCN_INFO' => $conditions['INFORMACION'],
                        'PRCN_NULI' => $line,
                        'PRCN_USRE' => $user,
                        'PRCN_FERE' => $currentDate,
                        'PRCN_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                    ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD021: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateInsertCondition) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD020: Ocurrió un error al obtener el contenido.", [], 500);
                }
            } else if ($conditions['ESTADO'] == 'Eliminado'){
                try {
                    $validateRegister = DB::table('S002V01TPRCN')
                        ->where('PRCN_IDCM', '=', $conditions['NUMERO_CONDICION'])
                        ->where('PRCN_NUPR', '=', $numeroProveedor)
                        ->where('PRCN_NULI', '=', $line)
                        ->exists();
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD023: Ocurrió un error al validar el registro.", $th->getMessage(), 500);
                }

                if ($validateRegister) {
                    try {
                        $validateUpdateConditions = DB::table('S002V01TPRCN')
                            ->where('PRCN_IDCM', '=', $conditions['NUMERO_CONDICION'])
                            ->where('PRCN_NUPR', '=', $numeroProveedor)
                            ->where('PRCN_NULI', '=', $line)
                            ->update([
                                'PRCN_ESTA' => 'Eliminado',
                                'PRCN_USMO' => $user,
                                'PRCN_FEMO' => $currentDate,
                                'PRCN_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                            ]);
                        
                    } catch (\Throwable $th) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD023: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                    }
                    if (!$validateUpdateConditions) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD022: Ocurrió un error al obtener el contenido.", [], 500);
                    }
                }
            }
        }

        foreach ($arrCatalogs as $catalogs) {
            if ($catalogs['ESTADO'] == 'Activo' || $catalogs['ESTADO'] == 'Modificado') {
                try {
                    $validateUpdateCatalog = DB::table('S002V01TPRCE')
                        ->where('PRCE_IDCE', '=', $catalogs['NUMERO_CATALAGO'])
                        ->where('PRCE_NUPR', '=', $numeroProveedor)
                        ->where('PRCE_NULI', '=', $line)
                        ->update([
                            'PRCE_CATA' => $catalogs['CATALAGO'],
                            'PRCE_DESC' => $catalogs['DESCRIPCION'],
                            'PRCE_XURL' => $catalogs['URL_CATALAGO'],
                            'PRCE_USMO' => $user,
                            'PRCE_FEMO' => $currentDate,
                            'PRCE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                        ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD025: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateUpdateCatalog) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD024: Ocurrió un error al obtener el contenido.", [], 500);
                }
            } else if ($catalogs['ESTADO'] == 'Nuevo'){
                try {
                    $validateInsertCatalog = DB::table('S002V01TPRCE')->insert([
                        'PRCE_NUPR' => $numeroProveedor,
                        'PRCE_CATA' => $catalogs['CATALAGO'],
                        'PRCE_DESC' => $catalogs['DESCRIPCION'],
                        'PRCE_XURL' => $catalogs['URL_CATALAGO'],
                        'PRCE_NULI' => $line,
                        'PRCE_USRE' => $user,
                        'PRCE_FERE' => $currentDate,
                        'PRCE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                    ]);
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD027: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
                if (!$validateInsertCatalog) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD026: Ocurrió un error al obtener el contenido.", [], 500);
                }
            } else if ($catalogs['ESTADO'] == 'Eliminado'){
                try {
                    $validateExists = DB::table('S002V01TPRCE')
                        ->where('PRCE_IDCE', '=', $catalogs['NUMERO_CATALAGO'])
                        ->where('PRCE_NUPR', '=', $numeroProveedor)
                        ->where('PRCE_NULI', '=', $line)
                        ->exists();
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD029: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }

                if ($validateExists) {
                    try {
                        $validateDelete = DB::table('S002V01TPRCE')
                            ->where('PRCE_IDCE', '=', $catalogs['NUMERO_CATALAGO'])
                            ->where('PRCE_NUPR', '=', $numeroProveedor)
                            ->where('PRCE_NULI', '=', $line)
                            ->update([
                                'PRCE_ESTA' => 'Eliminado',
                                'PRCE_USMO' => $user,
                                'PRCE_FEMO' => $currentDate,
                                'PRCE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                            ]);
                        
                    } catch (\Throwable $th) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD029: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                    }
                    if (!$validateDelete) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_MOD028: Ocurrió un error al obtener el contenido.", [], 500);
                    }
                }
            }
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "EXITO: Modificación Exitosa");
    }

    public function registerProvider(Request $request) {
        $validator = Validator::make($request->all(), [
            'line' => 'required|string',
            'user' => 'required|string',
            'obj_response' => 'required',
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_PROVIDER_REG000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        DB::beginTransaction();
        $requestData = $request->all();
        $line = $requestData['line'];

        try {
            $user = $this->encController->decrypt($requestData['user']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG001: Ocurrió un error al obtener el usuario.", $th->getMessage(), 500);
        }

        $arrInformationPersonal = (array) $requestData['obj_response']['INFORMACION'];
        $arrReferences = (array) $requestData['obj_response']['REFERENCIAS'];
        $arrContacts = (array) $requestData['obj_response']['CONTACTOS'];
        $arrConditions = (array) $requestData['obj_response']['CONDICIONES'];
        $arrPaymentMedia = (array) $requestData['obj_response']['METODOS_PAGO'];
        $arrCatalogs = (array) $requestData['obj_response']['CATALAGOS'];

        $currentDate = Carbon::now()->timezone('America/Mazatlan')->toDateTimeString();

        $arrPaymentTemp = array();
        foreach ($arrPaymentMedia as $payment) {
            $arrPaymentTemp[$payment['MEPA_IDME']] = $payment['MEPA_NOMB'];
        }

        try {
            $strPayment = json_encode($arrPaymentTemp);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG003: Ocurrió un error al obtener los métodos de pago del proveedor.", $th->getMessage(), 500);
        }
        
        $insertPersonal = [
            'PROV_NOCO' => $arrInformationPersonal['RAZON_SOCIAL'],
            'PROV_NOMB' => $arrInformationPersonal['NOMBRE'],
            'PROV_APPA' => $arrInformationPersonal['PRIMER_APELLIDO'],
            'PROV_APMA' => $arrInformationPersonal['SEGUNDO_APELLIDO'] != '' ? $arrInformationPersonal['SEGUNDO_APELLIDO'] : null,
            'PROV_CORR' => $arrInformationPersonal['CORREO'],
            'PROV_LAD1' => $arrInformationPersonal['LADA1'],
            'PROV_TEL1' => $arrInformationPersonal['TELEFONO1'],
            'PROV_LAD2' => $arrInformationPersonal['LADA2'],
            'PROV_TEL2' => $arrInformationPersonal['TELEFONO2'] != '' ? $arrInformationPersonal['TELEFONO2'] : null,
            'PROV_TICO' => $arrInformationPersonal['TIPO_CONTRIBUYENTE'],
            'PROV_XRFC' => $arrInformationPersonal['RFC'],
            'PROV_XTAX' => $arrInformationPersonal['TAXID'] != '' ? $arrInformationPersonal['TAXID'] : null,
            'PROV_CRFI' => $arrInformationPersonal['REGIMEN_FISCAL'],
            'PROV_TIPO' => $arrInformationPersonal['TIPO'],
            'PROV_SIWE' => $arrInformationPersonal['SITIOWEB'],
            'PROV_CALL' => $arrInformationPersonal['CALLE'],
            'PROV_NUEX' => $arrInformationPersonal['EXTERIOR'],
            'PROV_NUIN' => $arrInformationPersonal['INTERIOR'] != '' ? $arrInformationPersonal['INTERIOR'] : null,
            'PROV_COPO' => $arrInformationPersonal['CODIGO_POSTAL'],
            'PROV_COLO' => $arrInformationPersonal['COLONIA'],
            'PROV_LOCA' => $arrInformationPersonal['LOCALIDAD'],
            'PROV_MUNI' => $arrInformationPersonal['MUNICIPIO'],
            'PROV_ENTI' => $arrInformationPersonal['ENTIDAD'],
            'PROV_PAIS' => $arrInformationPersonal['PAIS'],
            'PROV_MEPA' => $strPayment,
            'PROV_NULI' => $line,
            'PROV_USRE' => $user,
            'PROV_FERE' => $currentDate,
            'PROV_FEAR' => DB::raw('CURRENT_TIMESTAMP')
        ];
        try {
            $idProdiver = DB::table('S002V01TPROV')->insertGetId($insertPersonal);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG004: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }
        foreach ($arrReferences as $references) {
            if ($references['ESTADO'] == 'Activo' ||  $references['ESTADO'] == 'Nuevo') {
                $insertReferences = [
                    'PRRE_NUPR' => $idProdiver,
                    'PRRE_EMPR' => $references['RAZON_SOCIAL'],
                    'PRRE_CORR' => $references['CORREO'],
                    'PRRE_LADA' => $references['LADA'],
                    'PRRE_TELE' => $references['TELEFONO'],
                    'PRRE_XRFC' => $references['RFC'],
                    'PRRE_DIRE' => $references['DIRECCION'],
                    'PRRE_NULI' => $line,
                    'PRRE_USRE' => $user,
                    'PRRE_FERE' => $currentDate,
                    'PRRE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                ];
                try {
                    $resp = DB::table('S002V01TPRRE')->insert($insertReferences);
                    if (!$resp) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG005: Ocurrió un error al obtener el contenido.", [], 500);
                    }
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG006: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
            }
        }

        foreach ($arrContacts as $contacts) {
            if ($contacts['ESTADO'] == 'Activo' || $contacts['ESTADO'] == 'Nuevo') {
                $insertContacts = [
                    'PRCO_NUPR' => $idProdiver,
                    'PRCO_NOMB' => $contacts['NOMBRE_CONTACTO'],
                    'PRCO_TIPO' => $contacts['TIPO_CONTACTO'],
                    'PRCO_CALL' => $contacts['CALLE'],
                    'PRCO_NUEX' => $contacts['NUMERO_EXTERIOR'],
                    'PRCO_NUIN' => $contacts['NUMERO_INTERIOR'] != '' ? $contacts['NUMERO_INTERIOR'] : null,
                    'PRCO_COPO' => $contacts['CODIGO_POSTAL'],
                    'PRCO_LOCA' => $contacts['LOCALIDAD'],
                    'PRCO_COLO' => $contacts['COLONIA'],
                    'PRCO_MUNI' => $contacts['MUNICIPIO'],
                    'PRCO_ENTI' => $contacts['ENTIDAD'],
                    'PRCO_PAIS' => $contacts['PAIS'],
                    'PRCO_LAD1' => $contacts['LADA1'],
                    'PRCO_TEL1' => $contacts['TELEFONO1'],
                    'PRCO_LAD2' => $contacts['LADA2'] != '' ? $contacts['LADA2'] : null,
                    'PRCO_TEL2' => $contacts['TELEFONO2'] != '' ? $contacts['TELEFONO2'] : null,
                    'PRCO_COR1' => $contacts['CORREO1'],
                    'PRCO_COR2' => $contacts['CORREO2'] != '' ? $contacts['CORREO2'] : null,
                    'PRCO_OBSE' => $contacts['OBSERVACIONES'],
                    'PRCO_NULI' => $line,
                    'PRCO_USRE' => $user,
                    'PRCO_FERE' => $currentDate,
                    'PRCO_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                ];
                try {
                    $resp = DB::table('S002V01TPRCO')->insert($insertContacts);
                    
                    if (!$resp) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG007: Ocurrió un error al obtener el contenido.", [], 500);
                    }
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG008: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
            }
        }

        foreach ($arrConditions as $conditions) {
            if ($conditions['ESTADO'] == 'Activo') {
                $insertConditions = [
                    'PRCN_NUPR' => $idProdiver,
                    'PRCN_TIPO' => $conditions['TIPO_CONDICION'],
                    'PRCN_INFO' => $conditions['INFORMACION'],
                    'PRCN_NULI' => $line,
                    'PRCN_USRE' => $user,
                    'PRCN_FERE' => $currentDate,
                    'PRCN_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                ];
                try {
                    $resp = DB::table('S002V01TPRCN')->insert($insertConditions);
                    if (!$resp) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG009: Ocurrió un error al obtener el contenido.", [], 500);
                    }
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG010: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
            }
        }

        foreach ($arrCatalogs as $catalogs) {
            if ($catalogs['ESTADO'] == 'Activo' || $catalogs['ESTADO'] == 'Nuevo') {
                $insertCatalogs = [
                    'PRCE_NUPR' => $idProdiver,
                    'PRCE_CATA' => $catalogs['CATALAGO'],
                    'PRCE_DESC' => $catalogs['DESCRIPCION'],
                    'PRCE_XURL' => $catalogs['URL_CATALAGO'],
                    'PRCE_NULI' => $line,
                    'PRCE_USRE' => $user,
                    'PRCE_FERE' => $currentDate,
                    'PRCE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                ];
                try {
                    $resp = DB::table('S002V01TPRCE')->insert($insertCatalogs);
                    if (!$resp) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG011: Ocurrió un error al obtener el contenido.", [], 500);
                    }
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_PROVIDER_REG012: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
                }
            }
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "EXITO: Registro Exitoso");
    }

    public function deleteProvider(Request $request) {
        $validator = Validator::make($request->all(), [
            'line' => 'required|string',
            'user' => 'required|string',
            'numero_proveedor' => 'required|string'
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_PROVIDER_DEL000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        DB::beginTransaction();
        $requestData = $request->all();
        $currentDate = Carbon::now()->timezone('America/Mazatlan')->toDateTimeString();
        $line = $requestData['line'];

        try {
            $numeroProveedor = $this->encController->decrypt($requestData['numero_proveedor']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL001: Ocurrió un error al obtener el número del proveedor.", $th->getMessage(), 500);
        }
        try {
            $user = $this->encController->decrypt($requestData['user']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL002: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }

        $update = [
            'PROV_ESTA' => 'Eliminado',
            'PROV_USMO' => $user,
            'PROV_FEMO' => $currentDate,
            'PROV_FEAR' => DB::raw('CURRENT_TIMESTAMP')
        ];
        try {
            $resp = DB::table('S002V01TPROV')->where('PROV_NUPR', '=', $numeroProveedor)->where('PROV_NULI', '=', $line)->update($update);
            if (!$resp) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL003: Ocurrió un error al obtener el contenido. ", [], 500);
            }
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL004: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }

        $update = [
            'PRRE_ESTA' => 'Eliminado',
            'PRRE_USMO' => $user,
            'PRRE_FEMO' => $currentDate,
            'PRRE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
        ];
        try {
            $resp = DB::table('S002V01TPRRE')->where('PRRE_NUPR', '=', $numeroProveedor)->where('PRRE_NULI', '=', $line)->update($update);
            /* if (!$resp) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL005: Ocurrió un error al obtener el contenido. ", [], 500);
            } */
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL006: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }

        $update = [
            'PRCO_ESTA' => 'Eliminado',
            'PRCO_USMO' => $user,
            'PRCO_FEMO' => $currentDate,
            'PRCO_FEAR' => DB::raw('CURRENT_TIMESTAMP')
        ];
        try {
            $resp = DB::table('S002V01TPRCO')->where('PRCO_NUPR', '=', $numeroProveedor)->where('PRCO_NULI', '=', $line)->update($update);
            /* if (!$resp) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL007: Ocurrió un error al obtener el contenido. ", [], 500);
            } */
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL008: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }

        $update = [
            'PRCN_ESTA' => 'Eliminado',
            'PRCN_USMO' => $user,
            'PRCN_FEMO' => $currentDate,
            'PRCN_FEAR' => DB::raw('CURRENT_TIMESTAMP')
        ];
        try {
            $resp = DB::table('S002V01TPRCN')->where('PRCN_NUPR', '=', $numeroProveedor)->where('PRCN_NULI', '=', $line)->update($update);
            /* if (!$resp) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL009: Ocurrió un error al obtener el contenido. ", [], 500);
            } */
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL010: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }

        $update = [
            'PRCE_ESTA' => 'Eliminado',
            'PRCE_USMO' => $user,
            'PRCE_FEMO' => $currentDate,
            'PRCE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
        ];
        try {
            $resp = DB::table('S002V01TPRCE')->where('PRCE_NUPR', '=', $numeroProveedor)->where('PRCE_NULI', '=', $line)->update($update);
            /* if (!$resp) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL011: Ocurrió un error al obtener el contenido. ", [], 500);
            } */
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_DEL012: Ocurrió un error al obtener el contenido.", $th->getMessage(), 500);
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "EXITO: Eliminación correcta",);

    }

    public function getProviderByArtitle(Request $request) {
        $validator = Validator::make($request->all(), [
            'NUMERO_ARTICULO' => 'required|string',
            'NUMERO_LINEA' => 'required|string',
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_PROVIDER_MOD000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        $response = $request->all();
        $numeroArticulo = $this->encController->decrypt($response['NUMERO_ARTICULO']);
        try {
            $arrDescription = DB::table('S002V01TDEAR')
                ->where('DEAR_ESTA', '=', 'Activo')
                ->where('DEAR_IDAR', '=', $numeroArticulo)
                ->join('S002V01TPROV', 'DEAR_NUPR', '=', 'PROV_NUPR')
                ->get([
                    'DEAR_IDDE AS NUMERO_DESCRIPTION',
                    'PROV_NUPR AS NUMERO_PROVEEDOR',
                    'PROV_NOCO AS RAZON_SOCIAL',
                    'PROV_NOMB AS NOMBRE',
                    'PROV_APPA AS PRIMER_APELLIDO',
                    'PROV_APMA AS SEGUNDO_APELLIDO',
                    'PROV_CORR AS CORREO',
                    'PROV_LAD1 AS LADA1',
                    'PROV_TEL1 AS TELEFONO1',
                    'PROV_LAD2 AS LADA2',
                    'PROV_TEL2 AS TELEFONO2',
                    'PROV_TICO AS TIPO_CONTRIBUYENTE',
                    'PROV_XRFC AS RFC',
                    'PROV_XTAX AS TAXID',
                    'PROV_CRFI AS REGIMEN_FISCAL',
                    'PROV_TIPO AS TIPO',
                    'PROV_SIWE AS SITIOWEB',
                    'PROV_MEPA AS METODO_PAGO',
                    'PROV_ESTA AS ESTADO',
                    'PROV_USRE AS USUARIO_REGISTRA',
                    'PROV_FERE AS FECHA_REGISTRA',
                    'PROV_USMO AS USUARIO_MODIFICA',
                    'PROV_FEMO AS FECHA_MODIFICA',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_PROVIDER_GETBYARTITLE000: No se pudo realizar la consulta a la base.", $th->getMessage(), 500);
        }

        return $this->responseController->makeResponse(false, "ÉXITO", $arrDescription);

    }

    public function generateSheetProvider($encProvider, $encUser, $line) {
        try {
            $provider = $this->encController->decrypt($encProvider);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG000: Ocurrió un error al obtener la ordens.", $th->getMessage(), 500);
        }
        try {
            $user = $this->encController->decrypt($encUser);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG001: Ocurrió un error al obtener la ordens.", $th->getMessage(), 500);
        }

        try {
            $getProvider = (array) DB::table('S002V01TPROV')
                ->where('PROV_NUPR', '=', $provider)
                ->first([
                    'PROV_NOCO',
                    'PROV_NOMB', 
                    'PROV_APPA', 
                    'PROV_APMA', 
                    'PROV_CORR', 
                    'PROV_LAD1', 
                    'PROV_TEL1', 
                    'PROV_LAD2', 
                    'PROV_TEL2', 
                    'PROV_TICO',
                    'PROV_XRFC', 
                    'PROV_XTAX', 
                    'PROV_CRFI', 
                    'PROV_TIPO', 
                    'PROV_SIWE', 
                    'PROV_MEPA', 
                    'PROV_USRE', 
                    'PROV_FERE', 
                    'PROV_USMO', 
                    'PROV_FEMO', 
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG002: Ocurrió un error al obtener la ordens.", $th->getMessage(), 500);
        }

        try {
            $getProviderReferences = DB::table('S002V01TPRRE')
                ->where('PRRE_NUPR', '=', $provider)
                ->where('PRRE_ESTA', '=', 'Activo')
                ->where('PRRE_NULI', '=', $line)
                ->get([
                    'PRRE_IDRE',
                    'PRRE_EMPR',
                    'PRRE_CORR',
                    'PRRE_LADA',
                    'PRRE_TELE',
                    'PRRE_XRFC',
                    'PRRE_DIRE',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG003: Ocurrió un error al obtener la ordens.", $th->getMessage(), 500);
        }
        $getProviderReferences = json_decode(json_encode($getProviderReferences), true);

        try {
            $getProviderCondiciones = DB::table('S002V01TPRCN')
                ->where('PRCN_NUPR', '=', $provider)
                ->where('PRCN_ESTA', '=', 'Activo')
                ->where('PRCN_NULI', '=', $line)
                ->get([
                    'PRCN_IDCM',
                    'PRCN_TIPO',
                    'PRCN_INFO',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG004: Ocurrió un error al obtener la ordens.", $th->getMessage(), 500);
        }
        $getProviderCondiciones = json_decode(json_encode($getProviderCondiciones), true);

        try {
            $getProviderCatalog = DB::table('S002V01TPRCE')
                ->where('PRCE_NUPR', '=', $provider)
                ->where('PRCE_ESTA', '=', 'Activo')
                ->where('PRCE_NULI', '=', $line)
                ->get([
                    'PRCE_IDCE',
                    'PRCE_CATA',
                    'PRCE_DESC',
                    'PRCE_XURL',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG005: Ocurrió un error al obtener la ordens.", $th->getMessage(), 500);
        }
        $getProviderCatalog = json_decode(json_encode($getProviderCatalog), true);

        try {
            $getProviderContacto = DB::table('S002V01TPRCO')
                ->where('PRCO_NUPR', '=', $provider)
                ->where('PRCO_ESTA', '=', 'Activo')
                ->where('PRCO_NULI', '=', $line)
                ->get([
                    'PRCO_IDCP',
                    'PRCO_NOMB',
                    'PRCO_TIPO',
                    'PRCO_CALL',
                    'PRCO_NUEX',
                    'PRCO_NUIN',
                    'PRCO_COPO',
                    'PRCO_COLO',
                    'PRCO_MUNI',
                    'PRCO_ENTI',
                    'PRCO_PAIS',
                    'PRCO_LAD1',
                    'PRCO_TEL1',
                    'PRCO_LAD2',
                    'PRCO_TEL2',
                    'PRCO_COR1',
                    'PRCO_COR2',
                    'PRCO_OBSE',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG006: Ocurrió un error al obtener la ordens.", $th->getMessage(), 500);
        }
        $getProviderContacto = json_decode(json_encode($getProviderContacto), true);


        $mpdf = new PDF( [
            'mode' => 'utf-8',
            'format' => 'A4',
            'margin_header' => '3',
            'margin_top' => '20',
            'margin_bottom' => '20',
            'margin_footer' => '2',
        ]);

        $mpdf->SetHTMLHeader('
            <div style="display:flex; align-items: center; text-align: right;">
                <img src="data:image/png;base64,[encoded data, 53204 characters]" width="100">
            </div>
        ');
        
        $mpdf->WriteHTML('<b>Número de Proveedor:</b> '.$provider);
        $mpdf->WriteHTML('<b>Nombre Comercial:</b> '.$getProvider['PROV_NOCO']);
        $mpdf->WriteHTML('<b>Encargado:</b> '.$getProvider['PROV_NOMB'].' '.$getProvider['PROV_APPA'].' '.$getProvider['PROV_APMA']);
        $mpdf->WriteHTML('<b>Correo Electrónico:</b> '.$getProvider['PROV_CORR']);
        $mpdf->WriteHTML('<b>Teléfono Principal:</b> +'.$getProvider['PROV_LAD1'].' '.$getProvider['PROV_TEL1']);
        if ($getProvider['PROV_LAD2'] != null) {
            $mpdf->WriteHTML('<b>Teléfono Secundario:</b> +'.$getProvider['PROV_LAD2'].' '.$getProvider['PROV_TEL2']);
        }
        if ($getProvider['PROV_XRFC'] != null) {
            $mpdf->WriteHTML('<b>R.F.C.:</b> '.$getProvider['PROV_XRFC']);
        }
        if ($getProvider['PROV_XTAX'] != null) {
            $mpdf->WriteHTML('<b>TAX ID:</b> '.$getProvider['PROV_XTAX']);
        }
        $mpdf->WriteHTML('<b>Regimen Fiscal:</b> '.$getProvider['PROV_CRFI']);
        $mpdf->WriteHTML('<b>Tipo de Proveedor:</b> '.$getProvider['PROV_TIPO']);
        $mpdf->WriteHTML('<b>Sitio Web:</b> '.$getProvider['PROV_SIWE']);

        
        $mpdf->WriteHTML('<hr>');

        $mpdf->WriteHTML('<b>Métodos de Pago Aceptados:</b>');
        $arrMethod = json_decode($getProvider['PROV_MEPA'], true);
        $htmlList = '<ul style="margin: 0;">';
        foreach ($arrMethod as $keyMethod => $isHabilited) {
            if ($isHabilited) {
                $htmlList .= '<li>';
                $htmlList .= $keyMethod;
                $htmlList .= '</li>';
            }   
        }
        $htmlList .= '</ul>';
        $mpdf->WriteHTML($htmlList);

        $mpdf->WriteHTML('<hr>');

        $htmlReferences = '<b>Contactos del Proveedor</b><br>
            <table border="1" style="margin-top: 12px;">
                <thead>
                    <tr>
                        <th style="font-size: 8pt;">No</th>
                        <th style="font-size: 8pt;">Nombre Empleado</th>
                        <th style="font-size: 8pt;">Dirección</th>
                        <th style="font-size: 8pt;">Teléfono 1</th>
                        <th style="font-size: 8pt;">Teléfono 2</th>
                        <th style="font-size: 8pt;">Correo Electrónico 1</th>
                        <th style="font-size: 8pt;">Correo Electrónico 2</th>
                        <th style="font-size: 8pt;">Observaciones</th>
                    </tr>
                </thead>
                <tbody>';
        foreach ($getProviderContacto as $key => $providerContacto) {
            $htmlReferences .= '<tr>';
            // No
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerContacto['PRCO_IDCP'].'</td>';
            // Nombre Empleado
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerContacto['PRCO_NOMB'].'</td>';
            // Direccion
            $direction = $providerContacto['PRCO_CALL'].' '.$providerContacto['PRCO_NUEX'].' '.$providerContacto['PRCO_NUIN'].' '.$providerContacto['PRCO_COPO'].' '.
                $providerContacto['PRCO_MUNI'].' '.$providerContacto['PRCO_ENTI'].' '.$providerContacto['PRCO_PAIS'];
            $htmlReferences .='<td style="font-size: 8pt;">'.$direction.'</td>';
            // Teléfono 1
            $htmlReferences .='<td style="font-size: 8pt;">+'.$providerContacto['PRCO_LAD1'].' '.$providerContacto['PRCO_TEL1'].'</td>';
            // Teléfono 2
            if ($providerContacto['PRCO_LAD2'] != null) {
                $htmlReferences .='<td style="font-size: 8pt;">+'.$providerContacto['PRCO_LAD2'].' '.$providerContacto['PRCO_TEL2'].'</td>';
            } else {
                $htmlReferences .= '<td>-</td>';
            }
            // Correo 1
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerContacto['PRCO_COR1'].'</td>';
            // Correo 2
            if ($providerContacto['PRCO_COR2'] != null) {
                $htmlReferences .='<td style="font-size: 8pt;">'.$providerContacto['PRCO_COR2'].'</td>';
            } else {
                $htmlReferences .= '<td>-</td>';
            }
            // Observaciones
            if ($providerContacto['PRCO_OBSE'] != null) {
                $htmlReferences .='<td style="font-size: 8pt;">'.$providerContacto['PRCO_OBSE'].'</td>';
            } else {
                $htmlReferences .= '<td>-</td>';
            }
            $htmlReferences .= '</tr>';
        }
        $htmlReferences .= '</tbody></table>';
        $mpdf->WriteHTML($htmlReferences);
        $mpdf->WriteHTML('<hr>');
        $htmlReferences = '<b>Referencias del Proveedor</b><br>
            <table border="1" style="margin-top: 12px;">
                <thead>
                    <tr>
                        <th style="font-size: 8pt;">No</th>
                        <th style="font-size: 8pt;">Empresa</th>
                        <th style="font-size: 8pt;">Correo Electrónico</th>
                        <th style="font-size: 8pt;">Teléfono</th>
                        <th style="font-size: 8pt;">R.F.C.</th>
                        <th style="font-size: 8pt;">Dirección</th>
                    </tr>
                </thead>
                <tbody>';
        foreach ($getProviderReferences as $key => $providerReferences) {
            $htmlReferences .= '<tr>';
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerReferences['PRRE_IDRE'].'</td>';
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerReferences['PRRE_EMPR'].'</td>';
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerReferences['PRRE_CORR'].'</td>';
            $htmlReferences .='<td style="font-size: 8pt;">+'.$providerReferences['PRRE_LADA'].' '.$providerReferences['PRRE_TELE'].'</td>';
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerReferences['PRRE_XRFC'].'</td>';
            $htmlReferences .='<td style="font-size: 8pt;">'.$providerReferences['PRRE_DIRE'].'</td>';
            $htmlReferences .= '</tr>';
        }
        $htmlReferences .= '</tbody></table>';
        $mpdf->WriteHTML($htmlReferences);
        $mpdf->WriteHTML('<hr>');

        $htmlCondition = '<b>Condiciones del Proveedor</b><br>';
        foreach ($getProviderCondiciones as $key => $providerCondiciones) {
            $htmlCondition .= '<b>Tipo de Condición</b>: '.$providerCondiciones['PRCN_TIPO'];
            $htmlCondition .= '<p>'.$providerCondiciones['PRCN_INFO'].'</p>';
        }
        $mpdf->WriteHTML($htmlCondition);

        $contentFile = $mpdf->Output('', "S");
        $base64File = base64_encode($contentFile);

        try {
            $arrResponse = $this->resourcesController->saveDocument($base64File, 'GEAD','FICHA_PROVEEDOR_'.$provider.'.pdf','IN',$line);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG008: Ocurrió un error al obtener la información.", $th->getMessage(), 500);
        }

        if ($arrResponse['error']) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG009: Ocurrió un error al obtener la información.", [], 500);
        }

        try {
            $validateInsert = DB::table('S002V01TPRDO')->insert([
                'PRDO_NUPR' => $provider,
                'PRDO_CODU' => $arrResponse['response'],
                'PRDO_DESC' => 'Ficha',
                'PRDO_TIPO' => 'IN',
                'PRDO_NULI' => $line,
                'PRDO_USRE' => $user,
                'PRDO_FERE' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                'PRDO_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
            ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG010: Ocurrió un error al ingresar la ficha.", $th->getMessage(), 500);
        }

        if (!$validateInsert) {
            return $this->responseController->makeResponse(true, "ERR_GENERATE_SHEET_REG011: No se pudo ingresar la ficha.", [], 500);
        }

        return $this->responseController->makeResponse(false, "ÉXITO: Ficha Exitosa", $arrResponse['response']);
    }

    public function getArtitlesByProvider($encProvider, $line) {
        DB::beginTransaction();

        // Se obtiene el número del proveedor
        try {
            $provider = $this->encController->decrypt($encProvider);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ARTITLES_PROVIDER_GET000: Ocurrió un error al obtener el número del proveedor.", $th->getMessage(), 500);
        }
        
        // Verifica su existe el proveedor
        try {
            $validateExist = DB::table('S002V01TPROV')
                ->where('PROV_NUPR', '=', $provider)
                ->where('PROV_NULI', '=', $line)
                ->exists();
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ARTITLES_PROVIDER_GET001: Ocurrió un error al identificar el proveedor.", $th->getMessage(), 500);
        }

        // Valida si existe el proveedor
        if (!$validateExist) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ARTITLES_PROVIDER_GET002: El proveedor no existe", [], 500);
        }

        // Obtiene todos las descripciones de los artículos del proveedor
        try {
            $getDescriptionArtitles = DB::table('S002V01TDEAR')
                ->where('DEAR_NUPR', '=', $provider)
                ->where('DEAR_NULI', '=', $line)
                ->where('DEAR_ESTA', '=', 'Activo')
                ->get([
                    'DEAR_IDDE', # Identificador de la descripción
                    'DEAR_IMAG', # Imagenes de los artículos
                    'DEAR_DESC', # Descripción del artículo
                    'DEAR_CARA', # Características del artículo
                    'DEAR_COWE', # Compra web
                    'DEAR_IDUN', # Identificador del tipo de unidad
                    'DEAR_IDAR', # Identificador del artículo principal
                    'DEAR_USRE', # Usuario de registro
                    'DEAR_FERE', # Fecha de registro
                    'DEAR_USMO', # Usuario de modificación
                    'DEAR_FEMO', # Fecha de modificación
                ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ARTITLES_PROVIDER_GET003: El proveedor no existe", $th->getMessage(), 500);
        }

        // El resultado pasa a ser un arreglo
        $arrDescriptionArtitles = json_decode(json_encode($getDescriptionArtitles), true);

        $arrDescription = array();
        foreach ($arrDescriptionArtitles as $keyDescription => $descriptionArtitle) {
            // Obtiene las imagenes y las pasa a un arreglo
            $descriptionArtitle['DEAR_IMAG'] = json_decode($descriptionArtitle['DEAR_IMAG']);
            $descriptionArtitle['DEAR_IMAG'] = json_decode($descriptionArtitle['DEAR_IMAG']);

            // Obtiene la información principal del artículo
            try {
                $objArtitle = DB::table('S002V01TARTI')
                    ->where('ARTI_IDAR', '=', $descriptionArtitle['DEAR_IDAR'])
                    ->where('ARTI_NULI', '=', $line)
                    ->where('ARTI_ESTA', '=', 'Activo')
                    ->join('S002V01TFAMI', 'ARTI_IDFA', '=', 'FAMI_IDFA')
                    ->join('S002V01TSUBF', 'ARTI_IDSU', '=', 'SUBF_IDSU')
                    ->first([
                        'ARTI_IDAR', # Identificador del artículo
                        'ARTI_IDFA', # Identificador de la familia del artículo
                        'FAMI_NOMB', # Nombre de la familia del artículo
                        'ARTI_IDSU', # Identificador de la subfamilia del artículo
                        'SUBF_NOMB', # Nombre de la subfamilia del artículo
                        'ARTI_CODI', # Código de barras del artículo
                        'ARTI_NOMB', # Nombre principal del artículo
                        // 'ARTI_USRE', # Usuario de registro
                        // 'ARTI_FERE', # Fecha de registro
                        // 'ARTI_USMO', # Usuario de modificación
                        // 'ARTI_FEMO', # Fecha de modificación
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ARTITLES_PROVIDER_GET004: Ocurrió un error al obtener la información del artículo.", $th->getMessage(), 500);
            }
            // La información es guardada en el arreglo de respuesta
            foreach ($objArtitle as $keyArtitle => $artitle) {
                $descriptionArtitle[$keyArtitle] = $artitle;
            }

            // Se obtiene la unidad del artículo
            try {
                $objUnit = DB::table('S002V01TUNID')
                    ->where('UNID_IDUN', '=', $descriptionArtitle['DEAR_IDUN'])
                    ->where('UNID_NULI', '=', $line)
                    ->where('UNID_ESTA', '=', 'Activo')
                    ->first([
                        'UNID_IDUN', # Identificador de la unidad
                        'UNID_NOMB', # Nombre de la unidad
                        'UNID_ACRO', # Acrónimo de la unidad
                        'UNID_USRE', # Usuario de registro
                        'UNID_FERE', # Fecha de registro
                        'UNID_USMO', # Usuario de modificación
                        'UNID_FEMO', # Fecha de modificación
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ARTITLES_PROVIDER_GET005: Ocurrió un error al obtener el tipo de unidad.", $th->getMessage(), 500);
            }

            // La información es guardada en el arreglo de respuesta
            $descriptionArtitle['DEAR_IDUN'] = $objUnit;
            
            // Se obtienen los detalles de la descripción
            try {
                $getDetailsDescription = DB::table('S002V01TINAR')
                    ->where('INAR_IDDE', '=', $descriptionArtitle['DEAR_IDDE'])
                    ->where('INAR_NULI', '=', $line)
                    ->where('INAR_ESTA', '=', 'Activo')
                    ->get([
                        'INAR_IDIN', # Identificador de los detalles
                        'INAR_CODI', # Código del artículo
                        'INAR_MODE', # Módelo del artículo
                        'INAR_MONE', # Tipo de moneda
                        'INAR_PREC', # Precio unitario del artículo
                        'INAR_MOMI', # Mónto mínimo
                        'INAR_CARA', # Características
                        'INAR_USRE', # Usuario de registro
                        'INAR_FERE', # Fecha de registro
                        'INAR_USMO', # Usuario de modificación
                        'INAR_FEMO', # Fecha de modificación
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ARTITLES_PROVIDER_GET007: Ocurrió un error al obtener los detalles de la descripción del artículo.", $th->getMessage(), 500);
            }
            
            // La información es guardada en el arreglo de respuesta
            $descriptionArtitle['DETAILS'] = $getDetailsDescription;

            // Se almacen el arreglo de respuesta en el arreglo principal
            $arrDescription[] = $descriptionArtitle;
        }

        DB::commit(); # Para guardar los cambios en la base de datos
        return $this->responseController->makeResponse(false, "ÉXITO: Consulta exitosa", $arrDescription);
    }

    public function downloadArtitlesByProvider(Request $request) {
        $validator = Validator::make($request->all(), [
            'PROVIDER' => 'required|string',
            'USER' => 'required|string',
            'LINE_NUMBER' => 'required|string',
            'DOWNLOAD' => 'required|array',
        ]);

        
        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_DOWNLOAD_ARTITLE_DOW000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }
        
        $responseData = $request->all();

        try {
            $user = $this->encController->decrypt($responseData['USER']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW001: No se pudo obtener los datos del usuario", $th->getMessage(), 500);
        }
        
        // Verifica su existe el proveedor
        try {
            $validateExist = DB::table('S002V01TPROV')->where('PROV_NUPR', '=', $responseData['PROVIDER'])->where('PROV_NULI', '=', $responseData['LINE_NUMBER'])->exists();
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW002: Ocurrió un error al identificar el proveedor.", $th->getMessage(), 500);
        }

        // Valida si existe el proveedor
        if (!$validateExist) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW003: El proveedor no existe", [], 500);
        }

        $arrDescriptionId = $responseData['DOWNLOAD'];
        $arrDataArtitles = array();
        foreach ($arrDescriptionId as $keyId => $idDescription) {
            // Obtiene todos las descripciones de los artículos del proveedor
            try {
                $getDescriptionArtitles = DB::table('S002V01TDEAR')
                    ->where('DEAR_IDDE', '=', $idDescription)
                    ->where('DEAR_NUPR', '=', $responseData['PROVIDER'])
                    ->where('DEAR_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('DEAR_ESTA', '=', 'Activo')
                    ->first([
                        'DEAR_IDDE', # Identificador de la descripción
                        'DEAR_IMAG', # Imagenes de los artículos
                        'DEAR_DESC', # Descripción del artículo
                        'DEAR_CARA', # Características del artículo
                        'DEAR_COWE', # Compra web
                        'DEAR_IDUN', # Identificador del tipo de unidad
                        'DEAR_IDAR', # Identificador del artículo principal
                        'DEAR_USRE', # Usuario de registro
                        'DEAR_FERE', # Fecha de registro
                        'DEAR_USMO', # Usuario de modificación
                        'DEAR_FEMO', # Fecha de modificación
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW004: El proveedor no existe", $th->getMessage(), 500);
            }
            $arrDescriptionArtitles = (array) $getDescriptionArtitles;


            // Obtiene la información principal del artículo
            try {
                $objArtitle = DB::table('S002V01TARTI')
                    ->where('ARTI_IDAR', '=', $arrDescriptionArtitles['DEAR_IDAR'])
                    ->where('ARTI_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('ARTI_ESTA', '=', 'Activo')
                    ->join('S002V01TFAMI', 'ARTI_IDFA', '=', 'FAMI_IDFA')
                    ->join('S002V01TSUBF', 'ARTI_IDSU', '=', 'SUBF_IDSU')
                    ->first([
                        'ARTI_IDAR', # Identificador del artículo
                        'ARTI_IDFA', # Identificador de la familia del artículo
                        'FAMI_NOMB', # Nombre de la familia del artículo
                        'ARTI_IDSU', # Identificador de la subfamilia del artículo
                        'SUBF_NOMB', # Nombre de la subfamilia del artículo
                        'ARTI_CODI', # Código de barras del artículo
                        'ARTI_NOMB', # Nombre principal del artículo
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW005: Ocurrió un error al obtener la información del artículo.", $th->getMessage(), 500);
            }
            $objArtitle = (array) $objArtitle;
            // La información es guardada en el arreglo de respuesta
            foreach ($objArtitle as $keyArtitle => $artitle) {
                $arrDescriptionArtitles[$keyArtitle] = $artitle;
            }

            // Se obtiene la unidad del artículo
            try {
                $objUnit = DB::table('S002V01TUNID')
                    ->where('UNID_IDUN', '=', $arrDescriptionArtitles['DEAR_IDUN'])
                    ->where('UNID_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('UNID_ESTA', '=', 'Activo')
                    ->first([
                        'UNID_IDUN', # Identificador de la unidad
                        'UNID_NOMB', # Nombre de la unidad
                        'UNID_ACRO', # Acrónimo de la unidad
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW006: Ocurrió un error al obtener el tipo de unidad.", $th->getMessage(), 500);
            }

            // La información es guardada en el arreglo de respuesta
            $arrDescriptionArtitles['DEAR_IDUN'] = $objUnit;

            // Se obtienen los detalles de la descripción
            try {
                $getDetailsDescription = DB::table('S002V01TINAR')
                    ->where('INAR_IDDE', '=', $idDescription)
                    ->where('INAR_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('INAR_ESTA', '=', 'Activo')
                    ->get([
                        'INAR_IDIN', # Identificador de los detalles
                        'INAR_CODI', # Código del artículo
                        'INAR_MODE', # Módelo del artículo
                        'INAR_MONE', # Tipo de moneda
                        'INAR_PREC', # Precio unitario del artículo
                        'INAR_MOMI', # Mónto mínimo
                        'INAR_CARA', # Características
                        'INAR_USRE', # Usuario de registro
                        'INAR_FERE', # Fecha de registro
                        'INAR_USMO', # Usuario de modificación
                        'INAR_FEMO', # Fecha de modificación
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW007: Ocurrió un error al obtener los detalles de la descripción del artículo.", $th->getMessage(), 500);
            }
            $arrDetailsDescription = json_decode(json_encode($getDetailsDescription), true);
            $arrDescriptionArtitles['DETAILS'] = $arrDetailsDescription;

            $arrDataArtitles[] = $arrDescriptionArtitles;
        }

        // Se inicializa el nombre del documento
        $nameDocument = "CONTENT_ARTITLE_BY_".$responseData['PROVIDER'].".xlsx";
        // Se crea el documento y se obtiene el base64 del documento
        $base64Document = $this->createDocument($arrDataArtitles);

        // Se guarda el documento y se genera el código del documento
        $arrResponseDocument = $this->resourcesController->saveDocument($base64Document, 'GEAD', $nameDocument, 'IN', $responseData['LINE_NUMBER']);
        if ( $arrResponseDocument['error'] ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, 'ERR_DOWNLOAD_ARTITLE_DOW008:'.$arrResponseDocument['msg'], $arrResponseDocument['response'], 500);
        }
        // Se obtiene el código del documento
        $codeDocument = $arrResponseDocument['response'];

        try {
            $validaeInsert = DB::table('S002V01TPRDO')->insert([
                'PRDO_NUPR' => $responseData['PROVIDER'],
                'PRDO_CODU' => $codeDocument,
                'PRDO_TIPO' => 'IN',
                'PRDO_DESC' => 'GENERACIÓN DE DOCUMENTO DE ARTÍCULOS POR PROVEEDOR',
                'PRDO_NULI' => $responseData['LINE_NUMBER'],
                'PRDO_USRE' => $user,
                'PRDO_FERE' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                'PRDO_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
            ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW009: Ocurrió un error al registrar el documento.", $th->getMessage(), 500);
        }

        if (!$validaeInsert) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_DOWNLOAD_ARTITLE_DOW010: No se pudo registrar el documento en la base de datos", [], 500);
        }

        DB::commit(); # Para guardar los cambios en la base de datos
        return $this->responseController->makeResponse(false, "ÉXITO: Se genero correctamente.", $codeDocument);

    }

    public function uploadArtitlesByProvider(Request $request) {
        $validator = Validator::make($request->all(), [
            'PROVIDER' => 'required|string',
            'USER' => 'required|string',
            'LINE_NUMBER' => 'required|string',
            'DOCUMENT' => 'required|string',
        ]);
        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_UPLOAD_ARTITLE_UPL000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        DB::beginTransaction();
        $responseData = $request->all();

        try {
            $user = $this->encController->decrypt($responseData['USER']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_UPLOAD_ARTITLE_UPL001: No se pudo obtener los datos del usuario", $th->getMessage(), 500);
        }

        $nameDocument = "UPLOAD_".$responseData['PROVIDER']."_".date('YmdHms').".xlsx";
        // Se guarda el documento y se genera el código del documento
        $arrResponseDocument = $this->resourcesController->saveDocument($responseData['DOCUMENT'], 'GEAD', $nameDocument, 'IN', $responseData['LINE_NUMBER']);
        if ( $arrResponseDocument['error'] ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL002:'.$arrResponseDocument['msg'], $arrResponseDocument['response'], 500);
        }
        // Se obtiene el código del documento
        $codeDocument = $arrResponseDocument['response'];

        // Se obtiene la ruta en donde se guardará el archivo
        $routeSaveDocument = "/app/public/GEAD/";
        // Se obtiene la ruta completa del archivo a guardar
        $pathRoute = storage_path().$routeSaveDocument.$codeDocument;

        if(!file_exists($pathRoute)){
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_UPLOAD_ARTITLE_UPL003: No se pudo obtener el documento.", [], 500);
        }

        $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx;
        $spreadsheet = $reader->load($pathRoute);
        $sheet = $spreadsheet->getSheetByName('ART');
        $maxRow = $sheet->getHighestRow();
        $maxColumn = $sheet->getHighestColumn();
        try {
            $arrDataArtitle = array();
            for ($positionRow=2; $positionRow <= $maxRow; $positionRow++) { 
                $arrContentRow = array();
                for ($positionColumn = 0; $positionColumn <= array_search($maxColumn, $this->arrAlphabet); $positionColumn++) { 
                    $data = $sheet->getCell($this->arrAlphabet[$positionColumn].$positionRow)->getValue();
                    // $code = $this->arrHeader[array_search($this->arrAlphabet[$positionColumn], $this->arrAlphabet)]['CODE'];
                    $infoHeader = $this->arrHeader[array_search($this->arrAlphabet[$positionColumn], $this->arrAlphabet)];
                    $data = trim($data);
                    if ($data == '' && $infoHeader['OBLIGATORY']) {
                        $position = $this->arrAlphabet[$positionColumn].$positionRow;
                        return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL004: El campo "'.$position.'" de la hoja ART es obligatorio.', [], 500);
                    } else if ($data == '') {
                        $data = null;
                    }
                    $arrContentRow[$infoHeader['CODE']] = $data;
                }
                $arrDataArtitle[] = $arrContentRow;
            }
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_UPLOAD_ARTITLE_UPL005: No se pudieron obtener los datos. Verifique que el formato de su documento sea correcto.", $th->getMessage(), 500);
        }
        $arrIdDetails = array();
        foreach ($arrDataArtitle as $keyArtitle => $artitle) {

            foreach ($this->arrHeader as $keyHeader => $header) {
                if (!array_key_exists($header['CODE'], $artitle)) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL006: El campo "'.$header['COLUMN'].'" no existe en los encabezados.', [], 500);
                }
            }

            try {
                $validateExistArtitle = DB::table('S002V01TARTI')
                    ->where('ARTI_IDAR', '=', $artitle['ARTI_IDAR'])
                    ->where('ARTI_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('ARTI_ESTA', '=', 'Activo')
                    ->exists();
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL007: Ocurrió un error al validar los artículos', $th->getMessage(), 500);
            }
            if (!$validateExistArtitle) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL008: El artículo con el número '.$artitle['ARTI_IDAR'].' no existe.', [], 500);
            }
            
            try {
                $validateExistDetails = (array) DB::table('S002V01TDEAR')
                    ->where('DEAR_IDAR', '=', $artitle['ARTI_IDAR'])
                    ->where('DEAR_NUPR', '=', $responseData['PROVIDER'])
                    ->where('DEAR_ESTA', '=', 'Activo')
                    ->exists();
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL009: Ocurrió un error al validar la descripción', $th->getMessage(), 500);
            }
            if (!$validateExistDetails) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL010: La descripción del artículo no pudo ser encontrada.', [], 500);
            }
            // $arrIdDetails[] = $arrDescription['DEAR_IDDE'];
            try {
                $arrFamily = (array) DB::table('S002V01TFAMI')
                    ->where('FAMI_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('FAMI_ESTA', '=', 'Activo')
                    ->where('FAMI_NOMB', '=', $artitle['FAMI_NOMB'])
                    ->first();
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL011: Ocurrió un error al validar la descripción.', $th->getMessage(), 500);
            }

            if (count($arrFamily) == 0) {
                DB::rollBack();
                $indexHeader = array_search('FAMI_NOMB', array_column($this->arrHeader, 'CODE'));
                $header = $this->arrHeader[$indexHeader]['COLUMN'];
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL012: El valor del campo "'.$header.'" no es válido.', [], 500);
            }
            
            try {
                $arrSubfamily = (array) DB::table('S002V01TSUBF')
                    ->where('SUBF_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('SUBF_ESTA', '=', 'Activo')
                    ->where('SUBF_NOMB', '=', $artitle['SUBF_NOMB'])
                    ->first();
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL013: Ocurrió un error al validar la descripción.', $th->getMessage(), 500);
            }
            if (count($arrSubfamily) == 0) {
                DB::rollBack();
                $indexHeader = array_search('SUBF_NOMB', array_column($this->arrHeader, 'CODE'));
                $header = $this->arrHeader[$indexHeader]['COLUMN'];
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL014: El valor del campo "'.$header.'" no es válido.', [], 500);
            }

            try {
                $validateUpdate = DB::table('S002V01TARTI')
                    ->where('ARTI_IDAR', '=', $artitle['ARTI_IDAR'])
                    ->where('ARTI_NULI', '=', $responseData['LINE_NUMBER'])
                    ->update([
                        'ARTI_IDFA' => $arrFamily['FAMI_IDFA'],
                        'ARTI_IDSU' => $arrSubfamily['SUBF_IDSU'],
                        'ARTI_CODI' => $artitle['ARTI_CODI'],
                        'ARTI_NOMB' => $artitle['ARTI_NOMB'],
                        'ARTI_USMO' => $user,
                        'ARTI_FEMO' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL015: Ocurrió un error al actualizar los artículos.', $th->getMessage(), 500);
            }
            if (!$validateUpdate) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL016: No se pudieron actualizar los artículos.', [], 500);
            }

            if ($artitle['DEAR_COWE'] == 'Si') {
                $webPurchase = 1;
            }else if ($artitle['DEAR_COWE'] == 'No') {
                $webPurchase = 0;
            } else {
                DB::rollBack();
                $indexHeader = array_search('DEAR_COWE', array_column($this->arrHeader, 'CODE'));
                $header = $this->arrHeader[$indexHeader]['COLUMN'];
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL017: El valor del campo "'.$header.'" no es válido.', [], 500);
            }

            try {
                $arrUnid = (array) DB::table('S002V01TUNID')
                    ->where('UNID_NULI', '=', $responseData['LINE_NUMBER'])
                    ->where('UNID_ESTA', '=', 'Activo')
                    ->where('UNID_NOMB', '=', $artitle['DEAR_IDUN'])
                    ->first();
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL018: Ocurrió un error al obtener las unidades.', $th->getMessage(), 500);
            }
            if (count($arrUnid) == 0) {
                DB::rollBack();
                $indexHeader = array_search('DEAR_IDUN', array_column($this->arrHeader, 'CODE'));
                $header = $this->arrHeader[$indexHeader]['COLUMN'];
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL019: El valor del campo "'.$header.'" no es válido.', [], 500);
            }
            try {
                $validateUpdate = DB::table('S002V01TDEAR')
                    ->where('DEAR_NUPR', '=', $responseData['PROVIDER'])
                    ->where('DEAR_IDAR', '=', $artitle['ARTI_IDAR'])
                    ->where('DEAR_ESTA', '=', 'Activo')
                    ->where('DEAR_NULI', '=', $responseData['LINE_NUMBER'])
                    ->update([
                        'DEAR_DESC' => $artitle['DEAR_DESC'],
                        'DEAR_CARA' => $artitle['DEAR_CARA'],
                        'DEAR_COWE' => $webPurchase,
                        'DEAR_IDUN' => $arrUnid['UNID_IDUN'],
                        'DEAR_USMO' => $user,
                        'DEAR_FEMO' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                        'DEAR_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
                    ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL020: Ocurrió un error al actualizar las descripciones de los artículos.', $th->getMessage(), 500);
            }
            if (!$validateUpdate) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL021: No se pudieron actualizar las descripciones de los.', [], 500);
            }
            
            $arrIdDetails[] = $artitle['ARTI_IDAR'];
        }

        foreach ($arrIdDetails as $idDetails) {
            $readerDetails = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx;
            $spreadsheet = $readerDetails->load($pathRoute);
            $sheet = $spreadsheet->getSheetByName('ARTDET-'.$idDetails);
            $maxRow = $sheet->getHighestRow();
            $maxColumn = $sheet->getHighestColumn();
            try {
                $arrDataDetails = array();
                for ($positionRow=2; $positionRow <= $maxRow; $positionRow++) { 
                    $arrContentRow = array();
                    for ($positionColumn = 0; $positionColumn <= array_search($maxColumn, $this->arrAlphabet); $positionColumn++) { 
                        $data = $sheet->getCell($this->arrAlphabet[$positionColumn].$positionRow)->getValue();
                        $infoHeader = $this->arrHeaderDetails[array_search($this->arrAlphabet[$positionColumn], $this->arrAlphabet)];
                        $data = trim($data);
                        if ($data == '' && $infoHeader['OBLIGATORY']) {
                            $position = $this->arrAlphabet[$positionColumn].$positionRow;
                            return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL022: El campo "'.$position.'" de la hoja ARTDET-'.$idDetails.' es obligatorio.', [], 500);
                        } else if ($data == '') {
                            $data = null;
                        }
                        $arrContentRow[$infoHeader['CODE']] = $data;
                    }
                    $arrDataDetails[] = $arrContentRow;
                }
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_UPLOAD_ARTITLE_UPL023: No se pudieron obtener los datos. Verifique que el formato de su documento sea correcto.", $th->getMessage(), 500);
            }

            foreach ($arrDataDetails as $keyDetails => $details) {

                foreach ($this->arrHeaderDetails as $keyHeader => $header) {
                    if (!array_key_exists($header['CODE'], $details)) {
                        DB::rollBack();
                        return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL024: El campo "'.$header['COLUMN'].'" no existe en los encabezados.', [], 500);
                    }
                }
                try {
                    $validateDetails = DB::table('S002V01TINAR')
                        ->where('INAR_IDIN', '=', $details['INAR_IDIN'])
                        ->where('INAR_ESTA', '=', 'Activo')
                        ->where('INAR_NULI', '=', $responseData['LINE_NUMBER'])
                        ->exists();
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_UPLOAD_ARTITLE_UPL025: No se pudieron obtener los datos. Verifique que el formato de su documento sea correcto.", $th->getMessage(), 500);
                }
                if (!$validateDetails) {
                    DB::rollBack();
                    $indexHeader = array_search('INAR_IDIN', array_column($this->arrHeaderDetails, 'CODE'));
                    $header = $this->arrHeaderDetails[$indexHeader]['COLUMN'];
                    $position = $this->arrHeaderDetails[$indexHeader]['POSITION'];
                    $errorPosition = $position.$keyDetails+1;
                    return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL026: El valor del campo "'.$header.'" no es válido.', [], 500);
                }


                try {
                    $validateUpdate = DB::table('S002V01TINAR')
                        ->where('INAR_IDIN', '=', $details['INAR_IDIN'])
                        ->where('INAR_NULI', '=', $responseData['LINE_NUMBER'])
                        ->where('INAR_ESTA', '=', 'Activo')
                        ->update([
                            'INAR_CODI' => $details['INAR_CODI'],
                            'INAR_MODE' => $details['INAR_MODE'],
                            'INAR_MONE' => $details['INAR_MONE'],
                            'INAR_PREC' => $details['INAR_PREC'],
                            'INAR_MOMI' => $details['INAR_MOMI'],
                            'INAR_CARA' => $details['INAR_CARA'],
                            'INAR_USMO' => $user,
                            'INAR_FEMO' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                            'INAR_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
                        ]
                    );
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, "ERR_UPLOAD_ARTITLE_UPL027: Ocurrió un error al actualizar los detalles del artículo.", $th->getMessage(), 500);
                }

                if (!$validateUpdate) {
                    DB::rollBack();
                    return $this->responseController->makeResponse(true, 'ERR_UPLOAD_ARTITLE_UPL028: No se pudo actualizar los detalles del artículo.', [], 500);
                }
            }
        }
        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Actualización Exitosa");
    }

    private function createDocument($arrDescription) {

        // Se inicializa el archivo xlsx
        $spreadsheet = new Spreadsheet();
        // Se crea la primera hoja donde se encontraran todos los artículos del proveedor
        $activeWorksheet = $spreadsheet->getActiveSheet()->setTitle("ART");
        
        // Se colocan los encabezados de la tabla
        $positionColumn = 0; # Posición de la columna (Empieza en 0 debído al arreglo del abecedario el cual corresponde a la letra A)
        // Se itean la información del encabezado
        foreach ($this->arrHeader as $keyArtitle => $header) {
            // Se ingresa el encabezado en la hoja
            $activeWorksheet->setCellValue($this->arrAlphabet[$positionColumn]."1", $header['COLUMN']);
            // Se incrementa la posición para la siguiente columna
            $positionColumn++;
        }

        // Se ingresa la información de los artículos
        $positionRow = 2; # Posición de la fila (Empieza en 2 debído a que la posición 1 ya la tomó la información del encabezado)
        // Se iteran los artículos del proveedor
        foreach ($arrDescription as $keyDescription => $arrArtitle) {
            $positionColumn = 0; # Siempre se inicializa en 0 por cada información de los artículos para que vuelva a comenzar en la columna A
            // Se itera el objeto que tiene la información del artículo
            foreach ($this->arrHeader as $keyHeader => $header) {
                // Se verifica que el campo obtenido se encuentre en la lista del encabezado
                // Se hace de esta manera para que se ordenen los campos de acuerdo al ordenamiento de los encabezados
                if(array_key_exists($header['CODE'], $arrArtitle)){

                    if ($header['CODE'] == 'DEAR_COWE') {
                        $arrArtitle[$header['CODE']] = $arrArtitle[$header['CODE']] == 0 ? 'No':'Si';
                    }
                    if ($header['CODE'] == 'DEAR_IDUN') {
                        $arrArtitle[$header['CODE']] = $arrArtitle[$header['CODE']]->UNID_NOMB;
                    }

                    // Se ingresa la información
                    $activeWorksheet->setCellValue($this->arrAlphabet[$positionColumn].$positionRow, $arrArtitle[$header['CODE']]);
                    // Se incrementa la posición para la siguiente columna
                    $positionColumn++;
                }
            }
            // Al terminar de procesar toda la información, la posición de la fila se incrementa para que pase a la siguiente fila
            $positionRow++;

            // Se verifica que la información obtenida tenga detalles
            if (count($arrArtitle['DETAILS']) > 0) {
                // En caso de ser verdadero, se crea una nueva hoja
                $spreadsheet->createSheet();
                // Se selecciona para trabajar ahora en esa hoja nueva
                $spreadsheet->setActiveSheetIndex($keyDescription + 1);

                // Se ingresa el nombre de la hoja, que es referente a su información perteneciente
                $activeWorksheetDetails = $spreadsheet->getActiveSheet()->setTitle('ARTDET-'.$arrArtitle['ARTI_IDAR']);

                // Se ingresan los encabezados en la nueva hoja
                $positionColumnDetails = 0; # Posición de la columna de los detalles (Empieza en 0 debído al arreglo del abecedario el cual corresponde a la letra A)
                // Se itean la información del encabezado de los detalles
                foreach ($this->arrHeaderDetails as $keyHeaderDetails => $headerDetails) {
                    // Se ingresa el encabezado en la hoja de los detalles
                    $activeWorksheetDetails->setCellValue($this->arrAlphabet[$positionColumnDetails]."1", $headerDetails['COLUMN']);
                    // Se incrementa la posición para la siguiente columna de los detalles
                    $positionColumnDetails++;
                }

                // Se ingresa la información de los artículos
                $positionRowDetails = 2; # Posición de la fila de los detalles (Empieza en 2 debído a que la posición 1 ya la tomó la información del encabezado de los detalles)
                // Se itera el objeto que tiene la información del artículo
                foreach ($arrArtitle['DETAILS'] as $key => $details) {
                    $positionColumnDetails = 0; # Siempre se inicializa en 0 por cada información de los detalles para que vuelva a comenzar en la columna A
                    // Se itera el objeto que tiene la información de los detalles
                    foreach ($this->arrHeaderDetails as $keyHeaderDetails => $headerDetails) {
                        // Se verifica que el campo obtenido se encuentre en la lista del encabezado de los detalles
                        // Se hace de esta manera para que se ordenen los campos de acuerdo al ordenamiento de los encabezados
                        if(array_key_exists($headerDetails['CODE'], $details)){
                            // Se ingresan los detalles
                            $activeWorksheetDetails->setCellValue($this->arrAlphabet[$positionColumnDetails].$positionRowDetails, $details[$headerDetails['CODE']]);
                            // Se incrementa la posición para la siguiente columna
                            $positionColumnDetails++;
                        }
                    }
                    // Al terminar de procesar toda la información, la posición de la fila se incrementa para que pase a la siguiente fila
                    $positionRowDetails++;
                }

                // Se inicializan las posiciones iniciales y finales
                $inicialPositionDetails = "A1";
                $finalPositionDetails = $this->arrAlphabet[$positionColumnDetails-1].$positionRowDetails-1;

                // Se inicializa el formato de la tabla
                $table = new Table("$inicialPositionDetails:$finalPositionDetails", 'Table'.$arrArtitle['ARTI_IDAR']);

                // Se inicializa los estilos de la tabla
                $tableStyle = new TableStyle();
                // Se ingresa el tipo de tabla
                $tableStyle->setTheme(TableStyle::TABLE_STYLE_MEDIUM10);
                // Se ingresa el estilo en la tabla
                $tableStyle->setShowRowStripes(true);
                $table->setStyle($tableStyle);
                $activeWorksheetDetails->addTable($table);

                // Se ajustan las dimensiones de la hoja de detalles
                $positionColumnDetails = 0; # Posición de la columna (Empieza en 0 debído al arreglo del abecedario el cual corresponde a la letra A)
                // Se iteran la información del encabezado de los detalles
                foreach ($this->arrHeaderDetails as $keyHeaderDetails => $headerDetails) {

                    if ($headerDetails['CODE'] == 'INAR_CARA') {
                        $activeWorksheetDetails->getColumnDimension($this->arrAlphabet[$positionColumnDetails])->setAutoSize(true);
                        $activeWorksheetDetails->getStyle($this->arrAlphabet[$positionColumnDetails])->getAlignment()->setWrapText(true); 

                    } else {
                        $activeWorksheetDetails->getColumnDimension($this->arrAlphabet[$positionColumnDetails])->setAutoSize(true);
                    }

                    // Las columnas son auto ajustadas
                    // Se incrementa la posición para la siguiente columna
                    $positionColumnDetails++;
                }
            }
        }
        // Se inicializan las posiciones iniciales y finales
        $inicialPosition = "A1";
        $finalPosition = $this->arrAlphabet[$positionColumn-1].$positionRow-1;

        // Se inicializa el formato de la tabla
        $table = new Table("$inicialPosition:$finalPosition", 'Table1');

        // Se inicializa los estilos de la tabla
        $tableStyle = new TableStyle();
        // Se ingresa el tipo de tabla
        $tableStyle->setTheme(TableStyle::TABLE_STYLE_MEDIUM8);
        // Se ingresa el estilo en la tabla
        $tableStyle->setShowRowStripes(true);
        $table->setStyle($tableStyle);
        $activeWorksheet->addTable($table);

        // Se ajustan las dimensiones de la hoja de los artículos
        $positionColumn = 0; # Posición de la columna (Empieza en 0 debído al arreglo del abecedario el cual corresponde a la letra A)
        // Se iteran la información del encabezado
        foreach ($this->arrHeader as $keyHeader => $header) {
            if ($header['CODE'] == 'DEAR_DESC' || $header['CODE'] == 'DEAR_CARA') {
                // Si se obtienen las siguientes columnas, entonces tendrá 40 de dimensión
                $activeWorksheet->getColumnDimension($this->arrAlphabet[$positionColumn])->setWidth(40);
                $activeWorksheet->getStyle($this->arrAlphabet[$positionColumn])->getAlignment()->setWrapText(true); 
            } else {
                // Las columnas son auto ajustadas
                $activeWorksheet->getColumnDimension($this->arrAlphabet[$positionColumn])->setAutoSize(true);
            }
            // Se incrementa la posición para la siguiente columna
            $positionColumn++;
        }


        $writer = new Xlsx($spreadsheet);
        ob_start();
        $writer->save('php://output');
        $base64 = base64_encode(ob_get_clean());
        return $base64;
        // $validate = \File::put( storage_path() . '/test.xlsx',  base64_decode($base64) );
    }
}
