// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Reporte:     RELACION DE CFDi CON REP
//
// Sistema:     ADMINPAQ  Versión v10.0 Windows
//
// Descripcion:  Reporte que imprime una relación de CFDi timbrados (facturas) con sus pagos electrónicos
//		 en resumen
// Consideraciones :  La información se obtiene de datos almacenados en tablas, no lee los xml
// Creación  :  Agosto 2017
// Revisiones : 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

//******************************************************************************
//Funciones de librería.

  Incluye LibAdminPaq.rpt
  Incluye LibDigitales.rpt
//******************************************************************************
//Parámetros.
    
  Parametro pDeLaFecha      = '20170101'
  Parametro pAlaFecha       = '20171231'
  Parametro pDelCliente     = ' '      // Espacio en blanco, clave del primer cliente en el rango
  Parametro pAlCliente     = ' '      // Espacio en blanco, clave del primer cliente en el rango 
  Parametro pConcepto       = ' '      // Código del Concepto de Facturación
  Parametro pEstado         = 0	       // 0 - Todos
					// 1 - Timbradas
					// 2 - Parcialmente timbrada
					// 3 - Pendiente de timbrado
					// 4 - Opcional ????
  Parametro pIdMoneda       = 1        // 1 = ID moneda Peso mexicano 

//******************************************************************************
//Apertura de tablas.

//Nombres terminados en Lib, indican que la tabla fue abierta explícitamente 
//para alguna Fx de librería

  UsaEmpresa tEmpresa;'AdminpaqW'               

  //Parametros de la empresa. 
  //Índice: primario.
  UsaTabla tParametros = tEmpresa['mgw10000']                        

  //Documentos. 
  UsaTabla tDocumentos = tEmpresa['mgw10008'] Alias 'tDoctos1'  
  tDocumentos.Usaindice['IDOCUMEN01']   //
  //cIdDocumentoDe + cFecha + cSerie + cFolio
  
  UsaTabla tPago = tEmpresa['mgw10008'] Alias 'tDoctos2'  
  tPago.Usaindice['']   //

  UsaTabla tDigitales = tEmpresa['mgw10045'] Alias 'tDigital1'
  tDigitales.Usaindice['CIDDOCTO']


  //Clientes y Provedores. 
  //Índice: cCodigoCliente + cTipoCliente.
  UsaTabla tClientes = tEmpresa['mgw10002'] Alias 'tCliente1'
  tClientes.Usaindice['']                            

  UsaTabla tClientesFiltro = tEmpresa['mgw10002'] Alias 'tCliente2'
  tClientesFiltro.Usaindice['ICODIGOT01']                            

  //Cargos y Abonos. 
  //Índice: IDDoctoCargo + IDDoctoAbono.
  UsaTabla tCargosAbonos = tEmpresa['mgw10009']   
  tCargosAbonos.UsaIndice['IDOCTOCA01']

  //Conceptos de documento. 
  //Índice: cIdConceptoDocumento.
  UsaTabla tConceptos = tEmpresa['mgw10006'] Alias 'tConcepto1'     
  tConceptos.UsaIndice['cIdConceptoDocumento'] 

  //Monedas. 
  //Índice: primario.
  UsaTabla tMonedas = tEmpresa['mgw10034']          
  tMonedas.Usaindice['']                        

  pIdMoneda = 1
  tMonedas.Busca[@Str(pIdMoneda;0)] 
  gDecimales = tMonedas(cDecimalesMoneda)


//******************************************************************************
//Declaración de variables globales.
  
  Columnas 1; 5  
  
  gHoy = fFormateaFecha(@Hoy();0)
  gNombreMoneda = tMonedas(cNombreMoneda)

// *************************************
// Definicion de constantes de EXCEL
// *************************************
constante xlCentrarEnSeleccion  7
constante xlAutomatico          -4105
constante xlManual              -4135
constante xlInferior            -4107
constante xlSubrayadoDoble      -4119
constante xlIzquierda           -4131
constante xlMediano             -4138
constante xlNinguno             -4142
constante xlDerecha             -4152
constante xlSuperior            -4160
constante xlHojaCalculo         -4167
constante xlLineaSimple		1
constante xlBordeSuperior	8
constante xlBordeInferior	9
constante xlBordeIzquierda	7
constante xlBordeDerecha	10
constante xlCentro		-4108
constante xlSaltoPagina -4135

// *************************************
// Inicializa EXCEL
// *************************************
// Accesa objetos de excel. Crea un objeto de Excel con la funcion @CreaObjeto(). A esta funcion
// se le pasa un identificador de OLE de la aplicacion que se desea crear. En este caso el identificador
// es Excel.Application.5
Objeto Excel = @CreaObjeto('Excel.Application')

// Invoca el metodo de EXCEL Libros y luego el metodo Agregar para crear un libro de hoja de calculo
// representado por la constante de EXCEL (xlHojaCalculo).
// Es importante notar que estos metodos NO LOS EJECUTA EL REPORTEADOR sino que los hace EXCEL
// y estan documentados en el Help de EXCEL
Objeto wb = Excel.WorkBooks.Add(xlHojaCalculo)

// Accesa la hoja de calculo (HojasCalculo) numero 1 del Libro creado anteriormente
// y representado por la variable wb, de la instruccion anterior
Objeto ws = wb.Worksheets(1)

// Hace visible a EXCEL. Para Excel, TRUE o VERDADERO es -1, FALSE o FALSO es 0
Excel.ActiveWindow.DisplayGridlines = FALSE[C0]
Excel.Visible = -1[C0]

RenActual = 1

// Pone la longitud de cada columna
ws.Columns(1).ColumnWidth = 15[C0]  //A
ws.Columns(2).ColumnWidth = 10[C0] // B
ws.Columns(3).ColumnWidth = 20[C0] // C
ws.Columns(4).ColumnWidth = 25[C0] // D
ws.Columns(5).ColumnWidth = 40[C0]   //E
ws.Columns(6).ColumnWidth = 33[C0]  //F
ws.Columns(7).ColumnWidth = 15[C0]  //G
ws.Columns(8).ColumnWidth = 15[C0]  //H
ws.Columns(9).ColumnWidth = 12[C0]  //I
ws.Columns(10).ColumnWidth = 23[C0]  //J


lDigsDecimales = '0000000000'
lDecs = @SUBSTR(lDigsDecimales;1;gDecimales)

lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
ws.Columns(7).NumberFormat = lFormato[C0]
ws.Columns(8).NumberFormat = lFormato[C0]


//******************************************************************************
//Funciones.
// ==========================================================================================
// fImprimeNota (Procedimiento)
// Descripcion: Imprime nota explicando el estado del documento
// ==========================================================================================
Deffunc fImprimeNota()

  RenActual = RenActual +1  
  ws.Range('C' & RenActual).Value = '* Estado del REP'  
  RenActual = RenActual +1
  ws.Range('C' & RenActual).Value = 'Complemento Opcional:'
  ws.Range('D' & RenActual).Value = 'Complemento de Recepción de Pago opcional, lo que significa que la forma de pago asignada al documento CFD es distinta a 99 (Por Definir)'
  RenActual = RenActual +1
  ws.Range('C' & RenActual).Value = 'Complemento Pendiente:'
  ws.Range('D' & RenActual).Value = 'Complemento obligatorio, el documento CFDI tiene asignada la forma de pago 99 (Por Definir), o no se han timbrado todavía los cobros'  
  RenActual = RenActual +1
  ws.Range('C' & RenActual).Value = 'Complemento Parcial:'
  ws.Range('D' & RenActual).Value = 'Complemento es solo Parcial, no se han timbrado todos los cobros asociados al documento o falta asignar un cobro'  
  RenActual = RenActual +1
  ws.Range('C' & RenActual).Value = 'Complemento Timbrado:'
  ws.Range('D' & RenActual).Value = 'Complemento Recepción de Pago asociado al documento CFDI se encuentra timbrado'  
  RenActual = RenActual +1

Finfunc

// ==========================================================================================
// fEstadoREP 
// Descripcion : De acuerdo al historial de Pagos, establece el ESTADO REP del documento
// Entrada :
//
// ==========================================================================================
DefFunc fEstadoREP(aTblDocumento:TABLA; aTblPago:TABLA; aTblDigitales:TABLA; aTblCargosAbonos:TABLA; aFecha)
Local lRegresa, lImporte, lRegresa, lTotalFactura

lImporte = 0
lRegresa = 0
lTimbrado = 0
lPagos    = 0

    Si aTblDocumento(cIdMoneda) = 1  //si la moneda es distinta a Pesos, tenemos que cambiar el documento a Pesos para comparar vs Limite
        lTotalFactura = aTblDocumento(cTotal)
    SiNo
        lTotalFactura = aTblDocumento(cTotal) * aTblDocumento(cTipoCambio)
    FinSi

    Si aTblDocumento(cMetodoPag) != 99 
        lRegresa = 4  // Opcional
    SiNo
        Mientras[aTblCargosAbonos.Busca[@STR(aTblDocumento(cIdDocumento);0)]; aTblCargosAbonos->Encontro; aTblCargosAbonos.Busca Siguiente[1]]    

            aTblPago.BUSCA[@STR(aTblCargosAbonos(cIdDocum01);0)]

            Si !aTblPago->ENCONTRO O aTblPago(cFecha) > aFecha  // Si no hay cuenta bancaria o no encontro el pago no imprime nada
                Continua
            FinSi
            lPagos = lPagos + 1[C0]
            lImporte = lImporte + aTblCargosAbonos(cImporte02)
            
            aTblDigitales.BUSCA[@STR(aTblPago(cIdDocumento);0)]
            SI aTblDigitales->ENCONTRO Y aTblDigitales(cEstado) = 2
                lTimbrado = lTimbrado + 1[C0]
            FINSI
        FinMientras
        Si (aTblDocumento(cTotal)-lImporte < 0.01 Y (lTimbrado = lPagos))
           lRegresa = 1  //Timbrada
        SiNo
            Si lTimbrado >= 1
                lRegresa = 2 //Parcialmente 
            SiNo
                lRegresa = 3 //'Pendiente de Timbrado'
            FinSi
         FinSi
    FinSi

    RETORNA lRegresa
Finfunc


//******************************************************************************
//Encabezado.
Encab
    // Valida el rango de fechas
    pALaFecha = pALaFecha < pDeLaFecha ? pDeLaFecha : pAlaFecha

    // Pone el nombre del sistema
    gFinReporte = 'J'[C0]
    gEmpresa = 'I'[C0]
    ws.Range('A' & RenActual).Font.Color = @RGB(255;0;0)[C0]
    ws.Range('A' & RenActual).Font.Size = 10[C0]
    ws.Range('A' & RenActual).Value = 'AdminPAQ'[C0]
    RenActual = RenActual + 1[C0]

    ws.Range(gFinReporte & RenActual).HorizontalAlignment = xlDerecha[C0]
    ws.Range(gFinReporte & RenActual).Value = gHoy
    RenActual = RenActual + 1[C0]

    // Pone el nombre de la empresa
    ws.Range('A' & RenActual).Font.Size = 14[C0]
    ws.Range('A' & RenActual).Font.Bold = true[C0]
    ws.Range('A' & RenActual & ':' & gEmpresa & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range('A' & RenActual ).Value = tEmpresa->Nombre

    RenActual = RenActual + 1[C0]

    ws.Range('A' & RenActual).Font.Size = 12[C0]
    ws.Range('A' & RenActual).Font.Bold = true[C0]
    ws.Range('A' & RenActual & ':' & gEmpresa & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range('A' & RenActual ).Value = 'Relación de CFDi con Recibos Electrónicos de Pago'[C0]
  
    RenActual = RenActual + 1[C0]
    
    ws.Range('A' & RenActual).Font.Size = 12[C0]
    ws.Range('A' & RenActual).Font.Bold = true[C0]    
    ws.Range('A' & RenActual & ':' & gEmpresa & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    gDelaFecha = fFormateaFecha(pDelaFecha;0)
    gAlaFecha  = fFormateaFecha(pAlaFecha;0)
    ws.Range('A' & RenActual ).Value = 'Del: ' & gDelaFecha & ' Al: ' & gAlaFecha[C0]

    RenActual = RenActual + 2[C0]

    ws.Range('A' & RenActual & ':H' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion
    ws.Range('A' & RenActual & ':H' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple
    ws.Range('A' & RenActual & ':H' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple
    ws.Range('A' & RenActual & ':H' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple
    ws.Range('A' & RenActual & ':H' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple
    ws.Range('A' & RenActual & ':H' & RenActual).Interior.Color = @RGB(255;0;0) 
    ws.Range('A' & RenActual).Font.Color = @RGB(255;255;255)
    ws.Range('A' & RenActual).Font.Bold = true
    ws.Range('A' & RenActual ).Value = 'CFDI'

    ws.Range('I' & RenActual & ':J' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion
    ws.Range('I' & RenActual & ':J' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple
    ws.Range('I' & RenActual & ':J' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple
    ws.Range('I' & RenActual & ':J' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple
    ws.Range('I' & RenActual & ':J' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple
    ws.Range('I' & RenActual & ':J' & RenActual).Interior.Color = @RGB(255;0;0) 
    ws.Range('I' & RenActual).Font.Color = @RGB(255;255;255)
    ws.Range('I' & RenActual).Font.Bold = true
    ws.Range('I' & RenActual ).Value = 'RECIBO ELECTRONICO DE PAGO'

    RenActual = RenActual + 1[C0]

    // Pone el titulo de cada columna en EXCEL
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Interior.ColorIndex = 55[C0]    
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Font.Bold = true[C0]    
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Font.Color = @RGB(255;255;255)[C0]
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).WrapText = True
    ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).HorizontalAlignment = xlCentro[C0]	
    
    ws.Range('A' & RenActual).Value = 'Fecha Documento'	
    ws.Range('B' & RenActual).Value = 'Serie'
    ws.Range('C' & RenActual).Value = 'Folio'
    ws.Range('D' & RenActual).Value = 'Documento'
    ws.Range('E' & RenActual).Value = 'Cliente'
    ws.Range('F' & RenActual).Value = 'Forma Pago'
    ws.Range('G' & RenActual).Value = 'Moneda Documento'
    ws.Range('H' & RenActual).Value = 'Total Documento'
	ws.Range('I' & RenActual).Value = 'Importe Pagado'
    ws.Range('J' & RenActual).Value = 'Estado del REP(*)'

    RenActual = RenActual + 1

  FinEncab


//******************************************************************************
//Cuerpo principal.
//******************************************************************************


    tParametros.Busca Primero   

    Si pDelCliente = ' '
        tClientesFiltro.Busca Primero
        pDelCliente = tClientesFiltro(cCodigoCliente)
    Finsi
  
    Si pAlCliente = ' '
        tClientesFiltro.Busca Ultimo
        pAlCliente =  tClientesFiltro(cCodigoCliente)  
    Finsi

    // Se inicializa la fecha con la que se realizaran las busquedas en el rango de fechas
    gFechaBusqueda = pDeLaFecha  

    // NOTA: Es obligatorio volver a fijar el índice a fin de que las búsquedas parciales funcionen correctamente
    tDocumentos.Usaindice['IDOCUMEN01']
    tDocumentos.Busca[@STR(4;0) & ':' & gFechaBusqueda]
    Si !tDocumentos->ENCONTRO
      Si @Val(@SUBSTR(tDocumentos->Llave;0;11)) = 4
        Si @SUBSTR(tDocumentos->Llave;11;8) >= pDeLaFecha Y @SUBSTR(tDocumentos->Llave;11;8) <= pAlaFecha
          gFechaBusqueda = @SUBSTR(tDocumentos->Llave;11;8)
          tDocumentos.Busca[@STR(4;0) & ':' & gFechaBusqueda]
        FinSi
      FinSi        
    FinSi

    
    Mientras tDocumentos->Encontro Y (tDocumentos(cFecha) <= pAlaFecha)

        tConceptos.BUSCA[@STR(tDocumentos(CIDCONCE01);0)]

        Si !tConceptos->ENCONTRO
            tDocumentos.BUSCA SIGUIENTE[1]
            Continua
        FinSi

        // Filtro de Conceptos
        Si pConcepto != ' ' Y pConcepto != ''
          lConceptoIncluido = False
          lNum = 0
          Mientras (!lConceptoIncluido) Y @Escoge(pConcepto;lNum)
            Si @Val(@Escoge(pConcepto;lNum)) > 0 Y @Val(@Escoge(pConcepto;lNum)) = tDocumentos(cIdConceptoDocumento)
                lConceptoIncluido = true  
            FinSi
            lNum = lNum +1
          FinMientras

          Si !lConceptoIncluido
            tDocumentos.BUSCA SIGUIENTE[1]
            Continua
          FinSi
        FinSi

               
	    tClientes.BUSCA[@STR(tDocumentos(cIdClien01);0)]
        
        Si !tClientes->ENCONTRO O tClientes(cCodigoC01) < pDelCliente O tClientes(cCodigoC01) > pAlCliente
            tDocumentos.BUSCA SIGUIENTE[1]
            Continua
        FinSi

        tMonedas.BUSCA[@STR(tDocumentos(cIdMoneda);0)]

        // Busca el estado REP de la Factura que se va a imprimir
        lEstado = fEstadoREP(tDocumentos; tPago; tDigitales; tCargosAbonos; pAlaFecha)

        Si pEstado != 0 Y pEstado != lEstado O tDocumentos(cCancelado) = 1
            tDocumentos.BUSCA SIGUIENTE[1]
            Continua
        FinSi        
        
        //Mientras[tCargosAbonos.Busca[@STR(tDocumentos(cIdDocumento);0)]; tCargosAbonos->Encontro; tCargosAbonos.Busca Siguiente[1]]    
            
			tCargosAbonos.Busca[@STR(tDocumentos(cIdDocumento);0)]
            tPago.BUSCA[@STR(tCargosAbonos(cIdDocum01);0)]

            //Si !tPago->ENCONTRO O tPago(cEsCFD) = 0 O tPago(cFecha) > pAlaFecha  // Si no hay cuenta bancaria o no encontro el pago no imprime nada
                //Continua
            //FinSi
			ws.Range('A' & RenActual ).Value = @chr(39) & fFormateaFecha(tDocumentos(cFecha);0)[C0]
            ws.Range('B' & RenActual ).Value = tDocumentos(cSerieDo01)[C0]         
            ws.Range('C' & RenActual ).Value = tDocumentos(cFolio)[C0]
            ws.Range('D' & RenActual ).Value = tConceptos(cNombreC01)[C0]     
            ws.Range('E' & RenActual ).Value = tClientes(CRAZONSO01)[C0]    
            ws.Range('F' & RenActual ).Value = fBuscaFormaPago(tDocumentos(cMetodoPag))[C0] 
            Si tMonedas->ENCONTRO
                ws.Range('G' & RenActual ).Value = tMonedas(cClaveSAT)[C0]        
            FinSi
			ws.Range('H' & RenActual ).Value = tDocumentos(cTotal)[C0]			
			ws.Range('I' & RenActual ).Value = tCargosAbonos(cImporte02)[C0]  // Importe pagado en la moneda de la factura
            ws.Range('J' & RenActual ).Value = fBuscaEstadoREP(lEstado)[C0]                         
            ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
            ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
            ws.Range('A' & RenActual & ':' & gFinReporte & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
            
            RenActual = RenActual + 1[C0]
        
        //FinMientras
                
         // Búsqueda del siguiente registro que cumpla con la cuenta
        tDocumentos.BUSCA SIGUIENTE[1]


    FinMientras

  fImprimeNota()  
  //  FIN DEL REPORTE

