<?php
class faelActions extends wtActions
{
    public $id_request;

    public function executeIndex()
    {
        $o_VTA_FacturacionElectronicaBN = new VTA_FacturacionElectronicaBN();
        $o_VTA_FacturacionElectronicaBN->setIdCompania( "1" );
        $o_VTA_FacturacionElectronicaBN->setFactElecId( "30884" );
        $o_VTA_FacturacionElectronicaBN->setTipo( "BV" );

        $o_FacturacionElectronicaBL = new FacturacionElectronicaBL();
        //$o_FacturacionElectronicaBL->registrarBandeja( $o_VTA_FacturacionElectronicaBN );

        return ViewResponse::NONE;
    }

    public function executeList()
    {
        LayoutTemplate::getInstance()->setUseBootstrap();

        $this->Titulo = "Facturacion Electonica";

        if( !myUser::getUser()->getIdBusiness() )
        {
            pr( "Por favor iniciar Sesion" );
        }

        $this->a_Estados = VTA_FacturacionElectronicaBN::getArrayEstados();
        $this->a_EstadosWeb = VTA_DocumentoBN::getArrayEstados();
        unset( $this->a_EstadosWeb['PR'] );

        //TIPO DE DOCUMENTO
        $o_GSS_SucursalDocumentoFN = new GSS_SucursalDocumentoFN();
        $o_GSS_SucursalDocumentoFN->setIdCompania( myUser::getUser()->getIdBusiness() );
        $o_GSS_SucursalDocumentoFN->setIdSucursal( myUser::getUser()->getIdSucursal() );
        $this->a_VTA_TipoDocumento = $o_GSS_SucursalDocumentoFN->recuperarTipoDocumento();
        //unset( $this->a_VTA_TipoDocumento[3] );
        ///////////////////
    }

    private function initialGridAction()
    {
        $o_GridAction = new GridAction();
        $o_GridAction->setClassFind( new VTA_FacturacionElectronicaFN() );

        $o_GridAction->addAssignFilter( "Estado" );
        $o_GridAction->addAssignFilter( "EstadoWeb" );
        $o_GridAction->addAssignFilter( "Serie" );
        //$o_GridAction->addAssignFilter( "Numero" );
        $o_GridAction->addAssignFilter( "Tipo" );
        $o_GridAction->addAssignFilter( "AceptadaxSunat" );
        $o_GridAction->addAssignFilter( "AnuAceptadaPorSunat" );

        if( !myUser::getUser()->hasGlobalAccess() )
        {
            $o_GridAction->addMethodDefault( "IdCompania", myUser::getUser()->getIdBusiness() );
            $o_GridAction->addAssignFilter( "IdCompania" );
        }
        else
        {
            $o_GridAction->addAssignFilter( "IdCompania" );
        }

        $o_GridAction->addConditionFilter( "FechaDocumento1", VTA_FacturacionElectronicaFN::FechaEmision,  ">=", '00:00:00' );
        $o_GridAction->addConditionFilter( "FechaDocumento2", VTA_FacturacionElectronicaFN::FechaEmision,  "<=", '23:59:59' );

        $o_GridAction->addConditionFilter( "Numero", VTA_FacturacionElectronicaFN::Numero, "LIKE", "%%s%" );

        $o_GridAction->addOrderDefault( VTA_FacturacionElectronicaFN::FactElecId, true );

        return $o_GridAction;
    }

    public function executeGrid()
    {
        $o_GridAction = $this->initialGridAction();

        $o_GridAction->addRowsToShow
        (
            "FactElecId", "TipoComprobanteDesc", "SerieNumero", "FechaDocumentoRec", "ClienteNom", "MonedaDesc", "MontoTotal", "EstadoDesc", "EstadoWebDesc",
            "AceptadaxSunat", "PDFResult", "XMLResult", "CDRResult", "AnuAceptadaPorSunat", "IdCompania", "Tipo"
        );

        $o_GridAction->setNumberRecordsShow( 100 );

        $o_GridAction->initialize();
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        $a_ResultJson            = array();
        $a_ResultJson['page']    = $o_GridAction->getPage();
        $a_ResultJson['total']   = $o_GridAction->getTotalPage();
        $a_ResultJson['records'] = $o_GridAction->getTotalRecords();
        $a_ResultJson['rows']    = $o_GridAction->getResultArray();

        echo json_encode( $a_ResultJson );

        return ViewResponse::NONE;
    }

    public function executeProcesoMasivo()
    {
        $a_ResultJson = array( "error" => 0 );

        $o_GridAction = $this->initialGridAction();
        $o_GridAction->setControlArray( false );
        $o_GridAction->setNumberRecordsShow( 99999 );
        $o_GridAction->initialize();
        $a_VTA_FacturacionElectronica = $o_GridAction->getResultSelect();

        if( $a_VTA_FacturacionElectronica )
        {
            //se inicial el proceso masivo
            echo "<h2>PROCESO MASIVO - RESPUESTA DE SUNAT</h2>";
            foreach ( $a_VTA_FacturacionElectronica as $key => $o_VTA_FacturacionElectronicaBN )
            {
                $i_Cnt = $key + 1;
                $s_NumDocumento   = $o_VTA_FacturacionElectronicaBN->getSerieNum();
                $this->id_request = $o_VTA_FacturacionElectronicaBN->getFactElecId();

                $s_Result = $this->executeProcAPI();

                if( $s_Result == "Success" )
                {
                    //echo "$i_Cnt - $s_NumDocumento - [$s_Result] <br>";
                    //continue;
                }

                if( $this->mensaje_error )
                {
                    echo "$i_Cnt - $s_NumDocumento - El Comprobante [{$this->id_request}][".$o_VTA_FacturacionElectronicaBN->getSerieNum()."] tiene el siguiente mensaje de error: ".$this->mensaje_error."<br>";
                    //$a_ResultJson['error'] = 1;
                    //$a_ResultJson['mensaje_error'] = "El Comprobante [{$this->id_request}][".$o_VTA_FacturacionElectronicaBN->getSerieNum()."] tiene el siguiente mensaje de error: ".$this->mensaje_error;
                }
                else
                {
                    echo "$i_Cnt - $s_NumDocumento - [$s_Result][OK] <br>";
                }
            }
            echo '<script type="text/javascript">parent.findControl();</script>';
        }

        //echo json_encode( $a_ResultJson );

        return ViewResponse::NONE;
    }

    public function executeProcAPI()
    {

        $i_IdFact = null;
        if( $this->getRequestParameter( 'id' ) )
        {
            $i_IdFact = intval( $this->getRequestParameter( 'id' ) );
        }

        if( $this->id_request )
        {
            $i_IdFact = intval( $this->id_request );
        }

        $this->externo          = $this->getRequestParameter( 'externo' );
        $this->recargarExterno  = true;

        $b_ControlAnulado = false;
        $this->mensaje_error = "";
        $this->o_VTA_FacturacionElectronicaBN = new VTA_FacturacionElectronicaBN();

        try
        {
            myUser::getUser()->validar_session();

            if( !$i_IdFact )
            {
                throw new Exception( "El Id de Comprobante es importante." );
            }

            //buscamos en la bandeja
            $o_VTA_FacturacionElectronicaFN = new VTA_FacturacionElectronicaFN();
            $o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaFN->selectByPK( $i_IdFact );

            //ahora buscamos el documento
            $o_VTA_DocumentoFN = new VTA_DocumentoFN();
            $o_VTA_DocumentoBN = $o_VTA_DocumentoFN->selectByPK( $o_VTA_FacturacionElectronicaBN->getTipo(), $o_VTA_FacturacionElectronicaBN->getIdCompania(), $o_VTA_FacturacionElectronicaBN->getFactElecId() );

            //se pregunta si esta anulado, si es true, tiene un procedimiento diferente
            //pr( "if( {$o_VTA_DocumentoBN->getEstado()} == ".VTA_DocumentoBN::ESTADO_ANULADO." )" ); exit;
            if( $o_VTA_DocumentoBN->getEstado() == VTA_DocumentoBN::ESTADO_ANULADO )
            {
                $b_ControlAnulado = true;

                //aqui se agrega una validacion mas, si esta anulado en documentos, pero paso algo, y no se actualizo en fael
                //pr( "if( {$o_VTA_FacturacionElectronicaBN->getEstadoWeb()} != {$o_VTA_DocumentoBN->getEstado()} )" ); exit;
                if( $o_VTA_FacturacionElectronicaBN->getEstadoWeb() != $o_VTA_DocumentoBN->getEstado() )
                {
                    //se debe de actualiza a anulado
                    $o_VTA_FacturacionElectronicaBN->setEstadoWeb( VTA_DocumentoBN::ESTADO_ANULADO );
                    $o_VTA_FacturacionElectronicaBN->setAnuMotivo( $o_VTA_DocumentoBN->getAnulacionComentario() );
                    $o_VTA_FacturacionElectronicaBN->setAnuAceptadaPorSunat( "NO" );
                    //
                    $o_FacturacionElectronicaBL = new FacturacionElectronicaBL();
                    $o_FacturacionElectronicaBL->anularComprobante( $o_VTA_FacturacionElectronicaBN );
                }

                //aqui la factura o boleta tiene que estar en el proveedor para la baja del comprobante
                //pr( "if( {$o_VTA_FacturacionElectronicaBN->getAceptadaxSunat()} == 'SI' )" ); exit;
                if( $o_VTA_FacturacionElectronicaBN->getAceptadaxSunat() == "SI" )
                {
                    //se valida que si ya tiene un proceso de anulacion, se hace diferentes proceso
                    //pr( "if( {$o_VTA_FacturacionElectronicaBN->getAnuSunatTicketNumero()} )" ); exit;
                    if( $o_VTA_FacturacionElectronicaBN->getAnuSunatTicketNumero() )
                    {
                        //pr( "if( {$o_VTA_FacturacionElectronicaBN->getAnuAceptadaPorSunat()} == 'NO' )" ); exit;
                        if( $o_VTA_FacturacionElectronicaBN->getAnuAceptadaPorSunat() == "NO" )
                        {
                            //aqui se procede a realizar la consulta de la anulacion del documento
                            $a_data = array
                            (
                                "operacion"           => "consultar_anulacion",
                                "tipo_de_comprobante" => $o_VTA_FacturacionElectronicaBN->getTipoComprobante(),
                                "serie"               => $o_VTA_FacturacionElectronicaBN->getSerie(),
                                "numero"              => intval( $o_VTA_FacturacionElectronicaBN->getNumero() )
                            );

                            $s_data_json = json_encode( $a_data );

                            $a_respuesta = $this->executeCurl( $s_data_json, $o_VTA_FacturacionElectronicaBN );
                            //pr( $a_respuesta ); exit;

                            $this->updateDocumentxAnull( $a_respuesta, $o_VTA_FacturacionElectronicaBN );
                        }

                        $o_VTA_FacturacionElectronicaFN = new VTA_FacturacionElectronicaFN();
                        $o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaFN->selectByPK( $i_IdFact );

                        $this->o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaBN;
                        return ViewResponse::SUCCESS;
                    }

                    //ahora se realiza le procedimiento de baja de los comprobantes
                    $a_data = array
                    (
                        "operacion"           => "generar_anulacion",
                        "tipo_de_comprobante" => $o_VTA_FacturacionElectronicaBN->getTipoComprobante(),
                        "serie"               => $o_VTA_FacturacionElectronicaBN->getSerie(),
                        "numero"              => intval( $o_VTA_FacturacionElectronicaBN->getNumero() ),
                        "motivo"              => "ERROR DE SISTEMA",
                        "codigo_unico"        => ""
                    );

                    $s_data_json = json_encode( $a_data );

                    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    //Invocamos el servicio de NUBEFACT - para la anulacion del documento
                    $a_respuesta = $this->executeCurl( $s_data_json, $o_VTA_FacturacionElectronicaBN );
                    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    //se actualiza en la tabla bandeja
                    if( $a_respuesta )
                    {
                        $this->updateDocumentxAnull( $a_respuesta, $o_VTA_FacturacionElectronicaBN );

                        $o_VTA_FacturacionElectronicaFN = new VTA_FacturacionElectronicaFN();
                        $o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaFN->selectByPK( $i_IdFact );

                        $this->o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaBN;
                        return ViewResponse::SUCCESS;
                    }
                    else
                    {
                        throw new Exception( "No hay respuesta del Servidor de Facturacion Electronica." );
                    }
                }
                else
                {
                    //por ahora se comenta si aun no se ha enviado a la sunat
                    //throw new Exception( "El Comprobante esta Anulado, pero tiene que estar aceptado por Sunat para dar su baja." );
                }
            }

            if( $o_VTA_FacturacionElectronicaBN->getAceptadaxSunat() == "SI" )
            {

                if( !$o_VTA_FacturacionElectronicaBN->getCDRResult() )
                {
                    //para boletas no es muy importante, ademas es por lote, varias boletas
                    //puede estar en un cdr
                    //facturas es de uno a uno en cdr
                    if( $o_VTA_FacturacionElectronicaBN->getTipo() != "BV" )
                    {
                        $this->mensaje_error = "";
                        $this->findDocument( $o_VTA_FacturacionElectronicaBN );
                    }
                }
                $this->recargarExterno  = false;
                $this->o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaBN;
                return ViewResponse::SUCCESS;
            }

            if( $o_VTA_FacturacionElectronicaBN->getEnlace() && $o_VTA_FacturacionElectronicaBN->getCodigoHashQR() )
            {
                //en este procedimiento indica que ya se envio al proveedor y que falta preguntar si la sunat ua acepto
                $this->mensaje_error = "";
                $this->findDocument( $o_VTA_FacturacionElectronicaBN );
                $this->o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaBN;
                return ViewResponse::SUCCESS;
            }

            //pr( "FIN" );            exit;
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //parametros por defecto
            $a_errors = array();
            $a_errors[10] = "No se pudo autenticar, token incorrecto o eliminado";
            $a_errors[11] = "La ruta o URL que estás usando no es correcta o no existe. Ingresa a tu cuenta en www.nubefact.com en la opción Api-Integración para verificar este dato";
            $a_errors[12] = "Solicitud incorrecta, la cabecera (Header) no contiene un Content-Type correcto";
            $a_errors[20] = "El archivo enviado no cumple con el formato establecido";
            $a_errors[21] = "No se pudo completar la operación, se acompaña el problema con un mensaje";
            $a_errors[22] = "Documento enviado fuera del plazo permitido";
            $a_errors[23] = "Este documento ya existe en NubeFacT";
            $a_errors[24] = "El documento indicado no existe o no fue enviado a NubeFacT";
            $a_errors[40] = "Error interno desconocido";
            $a_errors[50] = "Su cuenta ha sido suspendida";
            $a_errors[51] = "Su cuenta ha sido suspendida por falta de pago";

            $a_SunatTpDoc = array( "RUC" => 6, "DNI" => 1, "" => "-", "OTRO" => "-", "EXP" => 0 );
            $a_Moneda     = array( "LO" => 1, "EX" => 2, "EU" => 3 );
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            $s_MontoEntero = explode( ".", number_format( $o_VTA_FacturacionElectronicaBN->getMontoTotal(), 2, ".", "" ) );
            $o_NumberToLetter   = new NumberToLetterConverter();
            $s_MontoTotalLetras = $o_NumberToLetter->to_word( $s_MontoEntero[0] );

            $s_MonedaDocumento  = $o_VTA_FacturacionElectronicaBN->getTipoMoneda();
            if( $s_MonedaDocumento == "LO" )
            {
                $s_MontoTotalLetras .= " CON ".$s_MontoEntero[1]." / 100 SOLES";
            }
            else
            {
                $s_MontoTotalLetras .= " CON ".$s_MontoEntero[1]." / 100 DOLARES";
            }

            $s_ClienteTipoDocumento = $o_VTA_FacturacionElectronicaBN->getClienteTipoDoc();

            $s_SunatTransaction = "";
            switch ( $o_VTA_DocumentoBN->getTipoVenta() )
            {
                case "MER": //para el caso de -> VENTA INTERNA
                    $s_SunatTransaction = "1";
                    break;
                case "EXP": //EXPORTACIÓN
                    $s_SunatTransaction     = "2";
                    $s_ClienteTipoDocumento = "EXP";
                    break;
                case "ANT": //VENTA INTERNA – ANTICIPOS
                    $s_SunatTransaction     = "4";
                    //$s_ClienteTipoDocumento = "EXP";
                    break;
                case "DET": //DETRACCIONES
                    $s_SunatTransaction     = "30";
                    break;

            }

            //SE AGREGA UNA CONDICIONAL, SI TIENE MONTO ANTICIPO, SE CONSIDERA ANTICIPO REGULARIZACION
            if( $o_VTA_FacturacionElectronicaBN->getMontoAnticipo() > 0 )
            {
                $s_SunatTransaction     = "4";
            }

            if( $s_SunatTransaction == "" )
            {
                throw new Exception( "No se identifico el tipo de transaccion para la sunat." );
            }

            $s_ComentarioDocumento = trim( $o_VTA_DocumentoBN->getComentario() );
            $s_ComentarioDocumento .= "\n Vend: ".$o_VTA_DocumentoBN->getVendedor();

            $a_data = array
            (
                "operacion"                         => "generar_comprobante",

                "tipo_de_comprobante"               => $o_VTA_DocumentoBN->getObjectTipoDocumento()->getCodigoFiscalPrs(),
                "serie"                             => $o_VTA_FacturacionElectronicaBN->getSerie(),
                "numero"                            => intval( $o_VTA_FacturacionElectronicaBN->getNumero() ),
                "sunat_transaction"                 => $s_SunatTransaction,
                "cliente_tipo_de_documento"         => $a_SunatTpDoc[$s_ClienteTipoDocumento],
                "cliente_numero_de_documento"       => $o_VTA_FacturacionElectronicaBN->getClienteDocNum(),
                "cliente_denominacion"              => $o_VTA_FacturacionElectronicaBN->getClienteNom(), //razon social, nombre del cliente
                "cliente_direccion"                 => $o_VTA_FacturacionElectronicaBN->getClienteDireccion(),
                "cliente_email"                     => $o_VTA_FacturacionElectronicaBN->getClienteEmail(),
                "cliente_email_1"                   => "",
                "cliente_email_2"                   => "",
                "fecha_de_emision"                  => UtilDate::getFormatDate( $o_VTA_FacturacionElectronicaBN->getFechaEmision(), "d-m-Y" ),
                "fecha_de_vencimiento"              => "", //$o_VTA_FacturacionElectronicaBN->getFechaVencimiento() ? $o_VTA_FacturacionElectronicaBN->getFechaVencimiento() : "",
                "moneda"                            => $a_Moneda[$o_VTA_FacturacionElectronicaBN->getTipoMoneda()],
                "tipo_de_cambio"                    => $o_VTA_FacturacionElectronicaBN->getTipoMoneda()=="EX" ? $o_VTA_FacturacionElectronicaBN->getTipoCambio() : "",
                "porcentaje_de_igv"                 => $o_VTA_FacturacionElectronicaBN->getPorcentajeIGV(),

                "descuento_global"                  => $o_VTA_FacturacionElectronicaBN->getMontoDescuento(), //DESCUENTO SOBRE EL GRAVADO
                "total_descuento"                   => "", //DESCUENTO POR ITEM
                "total_anticipo"                    => $o_VTA_FacturacionElectronicaBN->getMontoAnticipo(),

                "total_gravada"                     => $o_VTA_FacturacionElectronicaBN->getMontoAfecto(),
                "total_inafecta"                    => $o_VTA_FacturacionElectronicaBN->getMontoInafecto(),
                "total_exonerada"                   => $o_VTA_FacturacionElectronicaBN->getMontoExonerado(),

                "total_igv"                         => $o_VTA_FacturacionElectronicaBN->getImpuesto(),
                "total_gratuita"                    => "",
                "total_otros_cargos"                => "",
                "total"                             => $o_VTA_FacturacionElectronicaBN->getMontoTotal(),
                "percepcion_tipo"                   => "",
                "percepcion_base_imponible"         => "",
                "total_percepcion"                  => "",
                "total_incluido_percepcion"         => "",
                "total_impuestos_bolsas"            => "",
                "detraccion"                        => false,
                "observaciones"                     => $s_ComentarioDocumento,
                "documento_que_se_modifica_tipo"    => "", //para nota de credito
                "documento_que_se_modifica_serie"   => "", //para nota de credito
                "documento_que_se_modifica_numero"  => "", //para nota de credito
                "tipo_de_nota_de_credito"           => "", //para nota de credito
                "tipo_de_nota_de_debito"            => "",
                "enviar_automaticamente_a_la_sunat" => true,
                "enviar_automaticamente_al_cliente" => true,
                "codigo_unico"                      => "",
                "condiciones_de_pago"               => "",
                "medio_de_pago"                     => "",
                "placa_vehiculo"                    => "",
                "orden_compra_servicio"             => "",
                "tabla_personalizada_codigo"        => "",
                "formato_de_pdf"                    => "", //Formato de PDF que se desea generar para la representación, si se deja en blanco se genera el formato definido por defecto en NUBEFACT. Se puede elegir entre A4, A5 o TICKET.
                "generado_por_contingencia"         => "",
                //"items"                             => array()
            );

            ///////////////////////////////////////////////////////////////////////////
            /////AHORA SE VALIDA LA DETRACCION - 2021-10-10
            if( $o_VTA_DocumentoBN->getDetraccionTipoId() )
            {
                $a_DataDetMedPago = VTA_DocumentoBN::getArrayDetraccionMediosPago( $o_VTA_DocumentoBN->getDetraccionMedPagoId() );
                $o_GSS_Detraccion = $o_VTA_DocumentoBN->getObjectDetraccion();

                $a_data['detraccion'] = true;
                $a_data['detraccion_tipo'] = $o_GSS_Detraccion->getCodigoSunatPr();
                $a_data['detraccion_total'] = $o_VTA_DocumentoBN->getDetraccionTotal();
                $a_data['medio_de_pago_detraccion'] = $a_DataDetMedPago['CodigoSunatPr'];
            }
            ///////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////
            ///AHORA SE VALIDA PARA LA RETENCION
            if( $o_VTA_DocumentoBN->getEsAgenteRetenedor() )
            {
                $a_DataRetencion = MST_PersonaMastBN::getArrayRetenciones( $o_VTA_DocumentoBN->getRetencionTipoId() );

                $a_data['retencion_tipo'] = $a_DataRetencion['CodigoSunatPr'];
                $a_data['retencion_base_imponible'] = $o_VTA_DocumentoBN->getRetencionBaseImponible();
                $a_data['total_retencion'] = $o_VTA_DocumentoBN->getRetencionTotal();
            }
            ///////////////////////////////////////////////////////////////////////////

            ///////////////////////////////////////////////////////////////////////////
            //AHORA SE MUESTRA EL MEDIO DE PAGO - 2021-09-20
            $o_FCO_AplicacionFN = new FCO_AplicacionFN();
            $o_FCO_AplicacionFN->setIdDocNumRef( $o_VTA_DocumentoBN->getNumeroDocumento() );
            $o_FCO_AplicacionFN->setEstado( FCO_AplicacionBN::ESTADO_APLICADO );
            $a_FCO_Aplicacion = $o_FCO_AplicacionFN->select();
            $s_MedioPago      = "";
            if( $a_FCO_Aplicacion )
            {
                foreach( $a_FCO_Aplicacion as $o_FCO_AplicacionBN )
                {
                    $s_Descripcion = $o_FCO_AplicacionBN->getTipoPagoNombre();
                    if( $o_FCO_AplicacionBN->getIdTipoPago() != 1 )
                    {
                        $s_Descripcion .= " OP: ".$o_FCO_AplicacionBN->getReciboNumero();
                    }

                    $a_DataMedioPago[] = $s_Descripcion;
                }
                $s_MedioPago = implode( " | ", $a_DataMedioPago );
            }
            $a_data['medio_de_pago'] = $s_MedioPago;
            ///////////////////////////////////////////////////////////////////////////

            ///////////////////////////////////////////////////////////////////////////
            ///
            $a_SR_GuiaRemisionH = $o_VTA_DocumentoBN->getArrayGuiaRemision();
            if( $a_SR_GuiaRemisionH )
            {
                $a_data['guias'] = array();
                $data_guias = array();
                foreach( $a_SR_GuiaRemisionH as $o_SR_GuiaRemisionHBN )
                {
                    $data_guias[] = array
                    (
                        "guia_tipo"         => 1,
                        "guia_serie_numero" => $o_SR_GuiaRemisionHBN->getGuiaSerie()."-".intval( $o_SR_GuiaRemisionHBN->getGuiaNumero() )
                    );
                }

                $a_data['guias'] = $data_guias;
            }
            ///////////////////////////////////////////////////////////////////////////

            ///////////////////////////////////////////////////////////////////////////
            //AHORA SE AGREGA EL PROCEDIMIENTO PARA FACTURAS AL CREDITO
            $o_VTA_FormaPagoFN = new VTA_FormaPagoFN();
            $o_VTA_FormaPagoBN = $o_VTA_FormaPagoFN->selectByPK( $o_VTA_DocumentoBN->getIdFormaPago() );

            $a_data['condiciones_de_pago'] = $o_VTA_FormaPagoBN->getDescripcionLocal();
            if( $o_VTA_FormaPagoBN->getDias() > 0 )
            {
                //ES CREDITO
                $a_data['condiciones_de_pago'] = $o_VTA_FormaPagoBN->getDescripcionLocal();
                $a_data['medio_de_pago'] = "credito";
                $a_data['venta_al_credito'] = array();

                $data_credito[] = array
                (
                    "cuota"         => 1,
                    "fecha_de_pago" => $o_VTA_DocumentoBN->getFechaVencimiento(),
                    "importe"       => $o_VTA_FacturacionElectronicaBN->getMontoTotal()
                );

                $a_data['venta_al_credito'] = $data_credito;
            }
            ///////////////////////////////////////////////////////////////////////////

            if( $o_VTA_DocumentoBN->getIdTipoDocumento() == "NC" )
            {
                $o_REF_VTA_DocumentoBN = VTA_DocumentoFN::selectByDocumentNumber( $o_VTA_DocumentoBN->getDocumentoParentId() );

                $a_data['tipo_de_nota_de_credito'] = 1;
                $a_data['documento_que_se_modifica_tipo'] = $o_REF_VTA_DocumentoBN->getObjectTipoDocumento()->getCodigoFiscal();
                $a_data['documento_que_se_modifica_serie'] = $o_REF_VTA_DocumentoBN->getDocumentoSerie();
                $a_data['documento_que_se_modifica_numero'] = intval( $o_REF_VTA_DocumentoBN->getDocumentoNumero() );
            }

            $a_VTA_DocumentoDet = $o_VTA_DocumentoBN->getArrayObjectDetalles();

            $f_TotalGratuito = 0;
            $data_det = array();

            foreach ( $a_VTA_DocumentoDet as $key => $o_VTA_DocumentoDetalleBN )
            {
                $f_PrecioUnitario = $o_VTA_DocumentoDetalleBN->getPrecioUnitario();
                if( $o_VTA_DocumentoDetalleBN->getTipoIGV() )
                {
                    $o_MST_TipoAfectacionIGVFN = new MST_TipoAfectacionIGVFN();
                    $o_MST_TipoAfectacionIGVBN = $o_MST_TipoAfectacionIGVFN->selectByPK( $o_VTA_DocumentoDetalleBN->getTipoIGV() );
                    if( $o_MST_TipoAfectacionIGVBN )
                    {
                        $s_tipo_igv = $o_MST_TipoAfectacionIGVBN->getCodigoProv();
                    }
                }

                if( $o_VTA_DocumentoBN->getTipoVenta() == "EXP" )
                {
                    $s_tipo_igv = "16";
                }

                $o_ALM_ItemMastFN = new ALM_ItemMastFN();
                $o_ALM_ItemMastBN = $o_ALM_ItemMastFN->selectByPK( $o_VTA_DocumentoDetalleBN->getItemCodigo() );

                //buscamos si bonificaciones
                if( $o_VTA_DocumentoDetalleBN->getPrecioUnitario() <= 0 )
                {
                    //ahora se recupera el valor por referencia
                    $o_ALM_ItemMastBN = is_null( $o_ALM_ItemMastBN ) ? new ALM_ItemMastBN() : $o_ALM_ItemMastBN;
                    $f_PrecioUnitario = !$o_ALM_ItemMastBN->getPrecioCosto() ? 0 : $o_ALM_ItemMastBN->getPrecioCosto();

                    $f_TotalGratuito += $f_PrecioUnitario * $o_VTA_DocumentoDetalleBN->getCantidadPedida();

                    //$s_tipo_igv = "10";
                }

                $data_det[] = array
                (
                    //"unidad_de_medida"          => "NIU", por la unidad de medida oficial cambia,
                    "unidad_de_medida"          => $o_VTA_DocumentoDetalleBN->getObjectUnidad()->getCodigoSunat(),
                    //"unidad_de_medida"          => "ZZ",  LA DETRACCION SE EFECTUA CUANDO SE ENCUENTRA UN DETALLE COMO TIPO SERVICIO
                    "codigo"                    => $o_VTA_DocumentoDetalleBN->getItemCodigo(),
                    "codigo_producto_sunat"     => $o_ALM_ItemMastBN->getCodigoSunat(),
                    //"descripcion"               => $o_VTA_DocumentoDetalleBN->getDescripcion()." | ".$o_VTA_DocumentoDetalleBN->getObjectItem()->getIdMarca()." | ".$o_VTA_DocumentoDetalleBN->getLoteAliasPr()." | ".UtilDate::getFormatDate( substr($o_VTA_DocumentoDetalleBN->getObjectItemAlmacen()->getFechaVencimiento(), 0, 10 ), "m/Y"),
                    "descripcion"               => $o_VTA_DocumentoDetalleBN->getDescripcion(),

                    "cantidad"                  => $o_VTA_DocumentoDetalleBN->getCantidadPedida(),
                    "valor_unitario"            => $f_PrecioUnitario,
                    "precio_unitario"           => $o_VTA_DocumentoDetalleBN->getMontoIncImpuestoUnidad(),
                    "descuento"                 => "",
                    "subtotal"                  => $o_VTA_DocumentoDetalleBN->getMontoSubTotal(),
                    "tipo_de_igv"               => $s_tipo_igv,
                    "igv"                       => $o_VTA_DocumentoDetalleBN->getMontoSubTotalImpuesto(),
                    "total"                     => $o_VTA_DocumentoDetalleBN->getMontoTotalNeto(),
                    "anticipo_regularizacion"   => "false",
                    "anticipo_documento_serie"  => "",
                    "anticipo_documento_numero" => ""
                );
            }

            if( $o_VTA_DocumentoBN->getTipoVenta() == "ANT" )
            {
                //SE AGREGA PROCEDIMIENTO PARA ANTICIPOS:
                $o_VTA_DocumentoFN = new VTA_DocumentoFN();
                $o_VTA_DocumentoFN->setDocumentoParentId( $o_VTA_DocumentoBN->getDocumentoParentId() );
                $o_VTA_DocumentoFN->setTipoVenta( "ANT" ); //TIPO ANTICIPO
                $o_VTA_DocumentoFN->setEstado( VTA_DocumentoBN::ESTADO_CERRADO );
                $a_VTA_Documento = $o_VTA_DocumentoFN->select();

                if ( $a_VTA_Documento )
                {
                    foreach ( $a_VTA_Documento as $key => $o_TMP_VTA_DocumentoBN )
                    {
                        $f_ValorUnitario = 0;
                        $f_PrecioUnitario = 0;
                        $f_SubTotal = 0;
                        $f_IGV = 0;
                        $f_Total = 0;

                        if ( $o_VTA_FacturacionElectronicaBN->getTipoMoneda() == "EX" )
                        {
                            if ( $o_TMP_VTA_DocumentoBN->getMonedaDocumento() == "EX" )
                            {
                                $f_ValorUnitario = $o_TMP_VTA_DocumentoBN->getMontoSubTotal();
                                $f_PrecioUnitario = $o_TMP_VTA_DocumentoBN->getMontoTotal();
                                $f_SubTotal = $o_TMP_VTA_DocumentoBN->getMontoSubTotal();
                                $f_IGV = $o_TMP_VTA_DocumentoBN->getMontoImpuestos();
                                $f_Total = $o_TMP_VTA_DocumentoBN->getMontoTotal();
                            }
                            else
                            {
                                //SE RECIMIENDA EVITAR REALIZAR LA MONEDA CRUZADA EN ESTE CADO, POR Q SE TIENE Q CONVERTIR Y SE PUEDE PRODUCIR CALCULOS INESPERADOS
                            }
                        }
                        else
                        {
                            if ( $o_TMP_VTA_DocumentoBN->getMonedaDocumento() == "EX" )
                            {
                                $f_ValorUnitario = $o_TMP_VTA_DocumentoBN->getMontoSubTotalMN();
                                $f_PrecioUnitario = $o_TMP_VTA_DocumentoBN->getMontoTotalMN();
                                $f_SubTotal = $o_TMP_VTA_DocumentoBN->getMontoSubTotalMN();
                                $f_IGV = $o_TMP_VTA_DocumentoBN->getMontoImpuestoMN();
                                $f_Total = $o_TMP_VTA_DocumentoBN->getMontoTotalMN();
                            }
                            else
                            {
                                $f_ValorUnitario = $o_TMP_VTA_DocumentoBN->getMontoSubTotal();
                                $f_PrecioUnitario = $o_TMP_VTA_DocumentoBN->getMontoTotal();
                                $f_SubTotal = $o_TMP_VTA_DocumentoBN->getMontoSubTotal();
                                $f_IGV = $o_TMP_VTA_DocumentoBN->getMontoImpuestos();
                                $f_Total = $o_TMP_VTA_DocumentoBN->getMontoTotal();
                            }
                        }
                        $data_det[] = array
                        (
                            //"unidad_de_medida"          => "NIU", por la unidad de medida oficial cambia,
                            "unidad_de_medida" => "ZZ",
                            "codigo" => $o_TMP_VTA_DocumentoBN->getNumeroDocumento(),
                            "codigo_producto_sunat" => "10000000",
                            //"descripcion"               => $o_VTA_DocumentoDetalleBN->getDescripcion()." | ".$o_VTA_DocumentoDetalleBN->getObjectItem()->getIdMarca()." | ".$o_VTA_DocumentoDetalleBN->getLoteAliasPr()." | ".UtilDate::getFormatDate( substr($o_VTA_DocumentoDetalleBN->getObjectItemAlmacen()->getFechaVencimiento(), 0, 10 ), "m/Y"),
                            "descripcion" => "ANTICIPO: " . $o_TMP_VTA_DocumentoBN->getTipoDocumentoDesc() . " NRO. " . $o_TMP_VTA_DocumentoBN->getDocumentoSerie() . "-" . intval( $o_TMP_VTA_DocumentoBN->getDocumentoNumero() ),

                            "cantidad" => 1,
                            "valor_unitario" => $f_ValorUnitario,
                            "precio_unitario" => $f_PrecioUnitario,
                            "descuento" => "",
                            "subtotal" => $f_SubTotal,
                            "tipo_de_igv" => 1,
                            "igv" => $f_IGV,
                            "total" => $f_Total,
                            "anticipo_regularizacion" => "true",
                            "anticipo_documento_serie" => $o_TMP_VTA_DocumentoBN->getDocumentoSerie(),
                            "anticipo_documento_numero" => intval( $o_TMP_VTA_DocumentoBN->getDocumentoNumero() )
                        );
                    }
                }
            }


            if( $f_TotalGratuito )
            {
                $a_data['total_gratuita'] = $f_TotalGratuito;
            }
            $a_data['items'] = $data_det;

            //pr( $a_data ); exit;

            $s_data_json = json_encode( $a_data );

            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //Invocamos el servicio de NUBEFACT
            $a_respuesta = $this->executeCurl( $s_data_json, $o_VTA_FacturacionElectronicaBN );
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            if( $a_respuesta )
            {
                $a_respuesta['es_anulado'] = false;
                if( $b_ControlAnulado )
                {
                    $a_respuesta['es_anulado'] = true;
                }
                $this->updateDocument( $a_respuesta, $o_VTA_FacturacionElectronicaBN );
            }
            else
            {
                throw new Exception( "No hay respuesta del Servidor de Facturacion Electronica." );
            }

            $this->o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaFN->selectByPK( $i_IdFact );
        }
        catch ( Exception $o_Exception )
        {
            $this->mensaje_error = $o_Exception->getMessage();
        }
    }

    public function executeProcDemo()
    {
        error_reporting( E_ALL ^ E_NOTICE );
        $bodyRequest = file_get_contents( "php://input" );
        //pr( $bodyRequest );
        $cab = json_decode( $bodyRequest, true );
        //pr( $cab );

        return ViewResponse::NONE;
    }

    private function executeCurl( $s_data_json, VTA_FacturacionElectronicaBN $o_VTA_FacturacionElectronicaBN )
    {
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ///recuperamos los parametros
        /*$a_Param = Constantes::getTokenRutaPorCompania( $id_compania );
        if( !$a_Param )
        {
            throw new Exception( "No se encontro la RUTA y el TOKEN para realizar la Facturacion Electronica - Compania [ $id_compania ]." );
        }*/

        if( $o_VTA_FacturacionElectronicaBN->getIdSucursal() )
        {
            $o_GSS_SucursalFN = new GSS_SucursalFN();
            $o_GSS_SucursalBN = $o_GSS_SucursalFN->selectByPK( $o_VTA_FacturacionElectronicaBN->getIdSucursal() );
            //pr( $o_GSS_SucursalBN );

            $RUTA_API  = $o_GSS_SucursalBN->getRutaProveedorExt();
            $TOKEN_API = $o_GSS_SucursalBN->getTokenProveedorExt();
        }
        else
        {
            throw new Exception( "La Sucursal no esta seleccionada." );
        }

        if( empty( $RUTA_API ) )
        {
            throw new Exception( "No tiene RUTA para registrar al Proveedor." );
        }

        if( empty( $TOKEN_API ) )
        {
            throw new Exception( "No tiene TOKEN para registrar al Proveedor." );
        }

        //pr( json_decode( $s_data_json ) );
        //pr( $a_Param );

        //exit;

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //Invocamos el servicio de NUBEFACT
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, $RUTA_API );
        curl_setopt
        (
            $ch,
            CURLOPT_HTTPHEADER,
            array
            (
                'Authorization: Token token="'.$TOKEN_API.'"',
                'Content-Type: application/json',
            )
        );
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, $s_data_json );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
        $respuesta  = curl_exec( $ch );
        curl_close( $ch );
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        $a_respuesta = json_decode( $respuesta, true );
        //pr( $respuesta );
        //pr( $a_respuesta );
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        return $a_respuesta;
    }

    private function updateDocumentxAnull( $a_respuesta, $o_VTA_FacturacionElectronicaBN )
    {
        $o_VTA_FacturacionElectronicaDP = new VTA_FacturacionElectronicaDP();
        $o_VTA_FacturacionElectronicaDP->setFactElecId( $o_VTA_FacturacionElectronicaBN->getFactElecId() );

        if( isset( $a_respuesta['errors'] ) )
        {
            $o_VTA_FacturacionElectronicaDP->setAnuSunatTicketNumero( "000000" );
            $o_VTA_FacturacionElectronicaDP->setAnuSunatSoapError( str_replace( array( "'", "`" ), array( "", "" ), $a_respuesta['errors'] ) );
            $o_VTA_FacturacionElectronicaDP->setCodigoError( $a_respuesta['codigo']."" );
        }
        else
        {
            $o_VTA_FacturacionElectronicaDP->setEstado( VTA_FacturacionElectronicaBN::ESTADO_ANULADO );
            $o_VTA_FacturacionElectronicaDP->setAnuNumero( intval( $a_respuesta['numero'] ) );
            $o_VTA_FacturacionElectronicaDP->setAnuEnlace( $a_respuesta['enlace'] );
            $o_VTA_FacturacionElectronicaDP->setAnuSunatTicketNumero( $a_respuesta['sunat_ticket_numero'] );
            $o_VTA_FacturacionElectronicaDP->setAnuAceptadaPorSunat( $a_respuesta['aceptada_por_sunat'] ? "SI" : "NO" );
            $o_VTA_FacturacionElectronicaDP->setAnuSunatDescripcion( $a_respuesta['sunat_description'] );
            $o_VTA_FacturacionElectronicaDP->setAnuSunatNote( $a_respuesta['sunat_note'] );
            $o_VTA_FacturacionElectronicaDP->setAnuSunatResponseCode( $a_respuesta['sunat_responsecode'] );
            $o_VTA_FacturacionElectronicaDP->setAnuSunatSoapError( $a_respuesta['sunat_soap_error'] );
            $o_VTA_FacturacionElectronicaDP->setAnuPDFResult( $a_respuesta['enlace_del_pdf'] );
            $o_VTA_FacturacionElectronicaDP->setAnuXMLResult( $a_respuesta['enlace_del_xml'] );
            $o_VTA_FacturacionElectronicaDP->setAnuCDRResult( $a_respuesta['enlace_del_cdr'] );
            $o_VTA_FacturacionElectronicaDP->setAnuKey( $a_respuesta['key'] );
        }

        $o_VTA_FacturacionElectronicaDP->setUsuarioModificacion( myUser::getUser()->getUserId() );
        $o_VTA_FacturacionElectronicaDP->setFechaModificacion( date( "Y-m-d H:i:s" ) );
        $o_VTA_FacturacionElectronicaDP->update();

        return true;
    }

    private function updateDocument( $a_respuesta, $o_VTA_FacturacionElectronicaBN )
    {
        $o_VTA_FacturacionElectronicaDP = new VTA_FacturacionElectronicaDP();
        $o_VTA_FacturacionElectronicaDP->setFactElecId( $o_VTA_FacturacionElectronicaBN->getFactElecId() );
        $o_VTA_FacturacionElectronicaDP->setEstado( "E" );

        if( isset( $a_respuesta['es_anulado'] ) )
        {
            if( $a_respuesta['es_anulado'] )
            {
                $o_VTA_FacturacionElectronicaDP->setAnuAceptadaPorSunat( "NO" );
                $o_VTA_FacturacionElectronicaDP->setEstadoWeb( VTA_DocumentoBN::ESTADO_ANULADO );
            }
        }

        if( isset( $a_respuesta['errors'] ) )
        {
            $o_VTA_FacturacionElectronicaDP->setEstado( "X" );
            $o_VTA_FacturacionElectronicaDP->setErrors( addslashes( $a_respuesta['errors'] ) );
            $o_VTA_FacturacionElectronicaDP->setCodigoError( $a_respuesta['codigo']."" );
            $o_VTA_FacturacionElectronicaDP->setAceptadaxSunat( "NO" );
            $this->mensaje_error = "[ ".addslashes( $a_respuesta['errors'] )." ]";
            if( isset( $a_errors[$a_respuesta['codigo']] ) )
            {
                $o_VTA_FacturacionElectronicaDP->setCodigoErrorDesc( $a_errors[$a_respuesta['codigo']] );
                $this->mensaje_error .= "<br>[ ".addslashes( $a_errors[$a_respuesta['codigo']] )." ]";
            }
            //aqui se hace una excepcion, para cueando el documento ya existe, solo se tiene que actualizar
            if( $a_respuesta['codigo'] == 23 )
            {
                $this->mensaje_error = "";
                $this->findDocument( $o_VTA_FacturacionElectronicaBN );
                return true;
            }
        }
        else
        {
            $o_VTA_FacturacionElectronicaDP->setErrors( "" );
            $o_VTA_FacturacionElectronicaDP->setCodigoError( "" );
            $o_VTA_FacturacionElectronicaDP->setCodigoErrorDesc( "" );
            $o_VTA_FacturacionElectronicaDP->setEnlace( $a_respuesta['enlace'] );
            $o_VTA_FacturacionElectronicaDP->setAceptadaxSunat( $a_respuesta['aceptada_por_sunat'] ? "SI" : "NO" );
            $o_VTA_FacturacionElectronicaDP->setSunatDescripcion( addslashes( $a_respuesta['sunat_description'] ) );
            $o_VTA_FacturacionElectronicaDP->setSunatNote( addslashes( $a_respuesta['sunat_note'] ) );
            $o_VTA_FacturacionElectronicaDP->setSunatResponseCode( is_null( $a_respuesta['sunat_responsecode'] ) ? "" : $a_respuesta['sunat_responsecode'] );
            $o_VTA_FacturacionElectronicaDP->setSunatSoapError( is_null( $a_respuesta['sunat_soap_error'] ) ? "" : $a_respuesta['sunat_soap_error'] );
            $o_VTA_FacturacionElectronicaDP->setPDFResult( $a_respuesta['enlace_del_pdf'] );
            $o_VTA_FacturacionElectronicaDP->setXMLResult( $a_respuesta['enlace_del_xml'] );
            $o_VTA_FacturacionElectronicaDP->setCDRResult( $a_respuesta['enlace_del_cdr'] );
            $o_VTA_FacturacionElectronicaDP->setCodigoHashQR( $a_respuesta['cadena_para_codigo_qr'] );
            $o_VTA_FacturacionElectronicaDP->setCodigoHash( $a_respuesta['codigo_hash'] );
        }

        $o_VTA_FacturacionElectronicaDP->setUsuarioModificacion( myUser::getUser()->getUserId() );
        $o_VTA_FacturacionElectronicaDP->setFechaModificacion( date( "Y-m-d H:i:s" ) );
        $o_VTA_FacturacionElectronicaDP->update();

        return true;
    }

    private function findDocument( &$o_VTA_FacturacionElectronicaBN )
    {
        $a_data = array
        (
            "operacion"                         => "consultar_comprobante",
            "tipo_de_comprobante"               => $o_VTA_FacturacionElectronicaBN->getTipoComprobante(),
            "serie"                             => $o_VTA_FacturacionElectronicaBN->getSerie(),
            "numero"                            => intval( $o_VTA_FacturacionElectronicaBN->getNumero() )
        );

        $data_json = json_encode( $a_data );

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //Invocamos el servicio de NUBEFACT
        $a_respuesta = $this->executeCurl( $data_json, $o_VTA_FacturacionElectronicaBN );

        //pr( $a_respuesta ); exit;

        $this->updateDocument( $a_respuesta, $o_VTA_FacturacionElectronicaBN );

        //buscamos en la bandeja
        $o_VTA_FacturacionElectronicaFN = new VTA_FacturacionElectronicaFN();
        $o_VTA_FacturacionElectronicaBN = $o_VTA_FacturacionElectronicaFN->selectByPK( $o_VTA_FacturacionElectronicaBN->getFactElecId() );
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        return true;
    }
}