// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Reporte:     REPORTE DE RELACION DE COBRANZA POR CLIENTE    ReviCobranza.rpt 
//
// Sistema:     ADMINPAQ  Versión v1.0 Windows
//
// Descripcion: Este reporte despliega todos los documentos pendientes de pago de cada cliente
//         El Saldo del documento se calcula en base a la fecha de corte.
//         Este reporte es exclusivo para Clientes.
// Consideraciones :
// Creación  :  Felix de la Cruz S.   11/Sept/2001
// Revisiones : Félix 14/Feb/2002;
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus     Descripcion
//  15/11/2002  DRdA    N.D.1568    Si no se selecciona ningún día en cualquiera de los filtros
//                                  de días de pago o de revisión se debe asumir que se desean 
//                                  ver todos los días como si se hubieran seleccionado.
//                                  - Variables globales
//  10/12/2002  LAP     N.D.1678    Cuando el cliente no tenga dias de pago o dias de revisión
//                                  capturados se deberá considerar como si se han capturado 
//                                  todos los días.  
//                                  - fCoincideDias
// 28/07/2003   CILA    N.D.2335    Se cambio el numero de decimales de 2 a 4
//                                  para la columna de tipo de cambio.
// 29/07/2003   HVA     N.D.2352    No mostraba los totales cuando se encontraba con dos documentos del cliente, el
//                                  primero pasaba la condicion el segundo ya no por lo que ya no mostraba el total por cliente
// 08/03/2005   HVA     N.D.2962     
// 19/04/2005   LAP     N.D.3219    Expresar los importes de los documentos en la moneda del reporte
//                                  Considerando que los documentos en moneda base tienen el 
//                                  tipo de cambio de la moneda del cliente a la moneda base.
//                                  - Cuerpo del reporte
//                                  - fImprimirDocto
//                                  - fCambioMonedaDocto pasa a LibAdminPAQ.rpt como fCambiarMonedaDoctoAReporte
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// INCLUSION DE ARCHIVOS
Incluye LibAdminPaq.rpt
Incluye LibCliProv.rpt

// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// INICIO PARAMETROS
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    Parametro pFechaCorte   = '20020215'
    Parametro pDelCliente   = ' '             // clave del primer cliente en el rango
    Parametro pAlCliente    = ' '             // clave del ultimo cliente en el rango
    Parametro pDiasPago     = 'L,M,Mi,J,V,S,D'// L= Lunes, M= Martes.... D = Domingo 
    Parametro pDiasRevision = 'L,M,Mi,J,V,S,D'// por omisión son todos los días, pero puede ser 
                                              // cualquier subconjunto, '1,2';'2,4,6' etc.
    Parametro pImprimirDoctos =  0            // 0 = Todos Doctos con saldo
                                              // 1 = Solo Doctos Vencidos a Fecha de Corte
    Parametro pCualesClientes =  0            // 0 =todos, 1= Activos, 2= InActivos
    Parametro pIdMoneda       =  1            // 1 = ID moneda Peso mexicano
    
    Parametro pIdClase1   = 0    // por omisión deben recibir 0 =  ninguna
    Parametro pIdClase2   = 0    // se pueden seleccionar varias clases por clasificación.    
    Parametro pIdClase3   = 0    
    Parametro pIdClase4   = 0    // por los pueden recibir una lista con los Id´s de las clases
    Parametro pIdClase5   = 0
    Parametro pIdClase6   = 0    // seleccionadas.

// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// INICIO APERTURA TABLAS
// Nombres terminados en Lib, indican: la tabla fue abierta explicitamente para alguna Fx de libreria
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  UsaEmpresa tEmpresa;'AdminpaqW'               

   // Parametros de la empresa
  UsaTabla tParametros = tEmpresa['mgw10000']         // Usa el indice primario

  // Clientes y Provedores
  UsaTabla tClientes = tEmpresa['mgw10002']
  tClientes.Usaindice['iCodigoTipo']                  // cCodigoCliente + cTipoCliente

  // Conceptos de los documentos
  UsaTabla tConceptos = tEmpresa['mgw10006']     
  tConceptos.UsaIndice['cIdConceptoDocumento']

  // Documentos
  UsaTabla tDocumentos = tEmpresa['mgw10008'] Alias 'tDoctos1'
  tDocumentos.Usaindice['iClienteProveedorFecha']   //IdClienteProveedor+cFecha+cSerie+cFolio
  UsaTabla tDoctoslib = tEmpresa['mgw10008']  Alias 'tDoctos2'               
  tDoctosLib.UsaIndice['']      //IdClienteProveedor+cFecha+cSerie+cFolio

  UsaTabla tCargosAbonosLib = tEmpresa['mgw10009']   
  tCargosAbonosLib.UsaIndice['iDoctoCargoAbono']                  // IDDoctoCargo + IDDoctoAbono

  UsaTabla tValoresDeClasif = tEmpresa['mgw10020']
  tValoresDeClasif.UsaIndice['']

  UsaTabla tMonedas = tEmpresa['mgw10034']          
  tMonedas.Usaindice['']                              // Usa el índice primario, por cIdMoneda

  // TiposCambio 
  Usatabla tTiposCambioLib = tEmpresa['mgw10035']
  tTiposCambioLib.Usaindice['iMonedaFecha']                                  //  cIdMoneda + cFecha

   // Periodos
  UsaTabla tPeriodos = tEmpresa['mgw10031']            // Usa el indice primario, cIDEjercicio
  tPeriodos.UsaIndice['cNumeroEjercicio']

  UsaTabla tAgentes = tEmpresa['mgw10001']             // Usa el indice primario
  tAgentes.UsaIndice['']


// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// DEFINICION DE COLUMNAS 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
             // C0      C2        C4        C6        C8      C10       C12      C14       C16       C18
  Columnas 19; 2.1,0.15,0.75,0.15,1.2,0.15,3.75,0.15,2.1,0.15,1.95,0.15,2.1,0.15,1.95,0.15,1.35,0.15,1.2 
  UsaLetra 'Arial'
  Altura 9
  [C0..C10,C16].Decimales 0
  
  [C0..C8].Blanco ' '
  [C10,C12].Coma
  [C10,C12].Corchete True
  tMonedas.Busca[@Str(pIdMoneda;0)]
  gDecimales = tMonedas(cDecimalesMoneda)
  // N.D.2335 Inicio -----------------------
  //[C12,C14,C18].Decimales gDecimales
  [C12,C14].Decimales gDecimales
  [C18].Decimales 4
  // N.D.2335 Fin --------------------------
  [C10,C12].Blanco '0.00'

// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// VARIABLES GLOBALES 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  
  gHoy = fFormateaFecha(@Hoy();0)
  gNombreMoneda = tMonedas(cNombreMoneda)

  gTotalGralSaldo = 0.0
  gTotalGral  = 0.0
  gNumDiasRev  = -1       // guardaran el numero de días que se recibieron como parámetro
  gNumDiasPago = -1
  gDiasPagoCliente = ''  // guardaran una lista con los días de pago y revisión del cliente
  gDiasRevCliente = ''   // en proceso

  // Inicia N.D.1578
  Si @Pos('L,M,Mi,J,V,S,D';@Escoge(pDiasPago;0)) < 0
    pDiasPago = 'L,M,Mi,J,V,S,D' // L= Lunes, M= Martes.... D = Domingo 
  FinSi

  Si @Pos('L,M,Mi,J,V,S,D';@Escoge(pDiasRevision;0)) < 0
    pDiasRevision = 'L,M,Mi,J,V,S,D' // L= Lunes, M= Martes.... D = Domingo 
  FinSi
  // Fin N.D.1578

// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// FUNCIONES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// ==========================================================================================
// fMascaraDias()
//    Esta función recibe un campo numérico, que en una representación binaria de siete digitos
//    indica ciertos días de la semana, según el digito que esté prendido, estos pueden ser
//    1111111 - Dom Sab Vie Jue Mie Mar Lun
// ==========================================================================================
Deffunc fMascaraDias(aValor)
Local lDias,lGuion

  // solo nos interesan los 7 bits mas a la derecha  
  lComa = ''    
  lDias = ''
  Si aValor%2 = 1       // Un numero non = bit menos significativo encendido
    lDias = lComa&'L'
    lComa = ','
  Finsi
  Si aValor%4 >= 2      // Valor Entre 1y4 = Segundo bit menos significativo encendido
    lDias = lDias & lComa & 'M'
    lComa = ','
  Finsi
  Si aValor%8 >= 4      // Valor Entre 8y4 = Tercer bit menos significativo encendido
    lDias = lDias & lComa & 'Mi'
    lComa = ','
  Finsi
  Si aValor%16 >= 8     // Valor Entre 16y8 = Cuarto bit menos significativo encendido
    lDias = lDias & lComa & 'J'
    lComa = ','
  Finsi
  Si aValor%32 >= 16
    lDias = lDias & lComa & 'V'
    lComa = ','
  Finsi  
  Si aValor%64 >= 32
    lDias = lDias & lComa & 'S'
    lComa = ','
  Finsi  
  Si aValor%128>= 64
    lDias = lDias & lComa & 'D'
    lComa = ','
  Finsi  

  Retorna lDias
FinFunc

// ==========================================================================================
// fComparaElem(ListaA;ListaB)
// Salida : 1=  Existe al menos un elemento en la conjunción de ListaA y ListaB
//          0=  No existe ni un elemento en la conjunción de ListaA y ListaB
// ==========================================================================================
Deffunc fInterseccion(aListaA;aListaB)
Local lCont1,lCont2,lRegresa

  lRegresa = 0  
  lCont1 = 0
  Mientras @Escoge(aListaA;lCont1)!= '' Y (lRegresa = 0)
    lCont2 = 0
    Mientras @Escoge(aListaB;lCont2)!=''
      Si @Escoge(aListaA;lCont1) = @Escoge(aListaB;lCont2)
        lRegresa = 1
        Finciclo
      Finsi
      lCont2 = lCont2 +1
    FinMientras 
    lCont1 = lCont1 + 1
  FinMientras  
  Retorna lRegresa 
FinFunc

// ==========================================================================================
// fCoincideDias
// Salida: 1 = Alguno de los Dias de pago y revisión SI coincide con los días del cliente
//         0 = Alguno de los Dias de pago y revisión NO coinciden con los días del cliente
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus     Descripcion
//  10/12/2002  LAP     N.D.1678    Cuando el cliente no tenga dias de pago o dias de revisión
//                                  capturados se deberá considerar como si se han capturado 
//                                  todos los días.  
// ==========================================================================================
Deffunc fCoincideDias(atCliente:TABLA;aDiasPagoCliente;aDiasRevCliente)
Local lRegresa

  lRegresa = 0 // por omisión se considera que no hay coincidencia

  // Se obtiene la lista de dias de cada tipo, de revision y de pago
  aDiasPagoCliente = fMascaraDias(atCliente(cDiaPago))
  aDiasRevCliente =  fMascaraDias(atCliente(cDiasRevision))

  // N.D.1678 Inicio
  // Se busca la interseccion con los parametros respectivos. Debe haber interseccion tanto en 
  // días de pago, como en días de revisión.
  Si aDiasPagoCliente = '' o (fInterseccion(aDiasPagoCliente;pDiasPago) = 1)
     Si aDiasRevCliente = '' o (fInterseccion(aDiasRevCliente;pDiasRevision) = 1)
        lRegresa = 1
     Finsi
  Finsi
  // N.D.1678 Fin  
  Retorna lRegresa
FinFunc

// =========================================================================================
// fImprimeDocumento (Procedimiento)
// ==========================================================================================
Deffunc  fImprimeCliente(atCliente:TABLA;aDiasPago;aDiasRev)
Local  lRenglon, lCont,lGuion

  NEGRITAS True
  Texto 'Cliente: ' & fMascarilla(atCliente(cCodigoCliente);tParametros(cMascarillaClientes))
  Imprime
  Texto 'Nombre:  ' & atCliente(cRazonSocial)
  Imprime

  // Se arma una cadena con separadores '-' en lugar de ',' para dias de pago
  lCont = 0
  lCadena = ''
  lGuion = ''
  Mientras @Escoge(aDiasRev;lCont)!= ''
    lCadena = lCadena & lGuion & @Escoge(aDiasRev;lCont)
    lCont = lCont + 1
    lGuion = '-'
  FinMientras
  Texto 'Días de Revisión:  '& lCadena
  Imprime

   // Se arma una cadena con separadores '-' en lugar de ',' para dias de revision
  lCont = 0
  lCadena = ''
  lGuion = ''
  Mientras @Escoge(aDiasPago;lCont) != ''
    lCadena = lCadena & lGuion & @Escoge(aDiasPago;lCont)
    lCont = lCont + 1
    lGuion = '-'
  FinMientras
  Texto 'Días de Pago:       '& lCadena
  Imprime
  NEGRITAS False
FinFunc

// ==========================================================================================
// fImprimirDocto()
// Descripcion : 
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
// Fecha       Nombre   IDLotus     Descripcion
// 19/04/2005  LAP      N.D.3219    Ahora esta función recibe el total y el saldo del documento
//                                  expresados en la moneda del reporte.
// ==========================================================================================
Deffunc fImprimirDocto(atDocto:TABLA; aTotal; aSaldo)
Local lRenglon

  lRenglon = ''

  // Se busca el agente asociado
  tAgentes.Busca[@Str(atDocto(cIdAgente);0)]

  Si atDocto(cFechaVencimiento) < pFechaCorte
    lRenglon[ 0] = '*'& fFormateaFecha(atDocto(cFecha);0)
    lRenglon[16] = (fConvJul(pFechaCorte)-fConvJul(atDocto(cFechaVencimiento)))
  Sino
    lRenglon[ 0] = ' '& fFormateaFecha(atDocto(cFecha);0)
  Finsi
  lRenglon[ 2] = atDocto(cSerieDocumento)
  lRenglon[ 4] = atDocto(cFolio)
  
  tConceptos.Busca[@Str(atDocto(cIdConceptoDocumento);0)]
  Si tConceptos->Encontro
    lRenglon[ 6] = tConceptos(cNombreConcepto)
  Finsi

  lRenglon[ 8] = fMascarilla(tAgentes(cCodigoAgente);tParametros(cMascarillaAgente))
  lRenglon[10] = fFormateaFecha(atDocto(cFechaVencimiento);0)
  lRenglon[12] = aTotal
  lRenglon[14] = aSaldo  
  lRenglon[18] = atDocto(cTipoCambio)
  Imprime lRenglon

  // Acumula el total por cliente
  gTotalSaldoCliente = gTotalSaldoCliente + aSaldo
  gTotalCliente = gTotalCliente + aTotal
FinFunc

// ==========================================================================================
// fImprimeTotal() 
//    Imprime el total por cliente o el total genera, depende del parametro aCual
// ==========================================================================================
Deffunc fImprimeTotal(aTotal;aTotalSaldo;aCual)
Local lRenglon, lSubRaya

  lRenglon = ''

  Si aCual = 'C'  // es un total del cliente
    [C12,C14].SubrayaCol '-'
    Imprime 
    // Entonces acumula los totales generales
    gTotalGralSaldo = gTotalGralSaldo + aTotalSaldo
    gTotalGral = gTotalGral + aTotal
  Sino            // Es un total general, subraya las columnas 
    lSubraya = '==============='[C12,C14]
    Saltalin 1
    Imprime lSubRaya
  Finsi

  lRenglon[12] = aTotal
  lRenglon[14] = aTotalSaldo
  Imprime lRenglon
FinFunc

// ==========================================================================================
// fEncabColumnas
// ==========================================================================================
Deffunc fEncabColumnas()

  NEGRITAS True
  Altura 9
  Texto '@TC{0,0,0}@L{-1}'
  Imprime 
  Texto C0; 'Fecha'
  TExto C2; 'Serie'
  TExto C4; 'Folio'
  Texto C6; 'Concepto'
  Texto C8; 'Agente'
  Texto C10;'Vencimiento'
  Texto C12;'^Total'
  Texto C14;'^Saldo'
  Texto C16;'^Días'
  Texto C18;'^Tipo'
  Imprime 
  Texto C16;'^Vencidos'
  Texto C18;'^Cambio'
  Imprime 
  Texto '@TC{0,0,0}@L{-1}'
  Imprime 
  NEGRITAS False
FinFunc

// ==========================================================================================
// fDiscriminaCliente()
// Salidas:  1 = indica que el cliente no aplica, debe descartarse
//           0 = indica que el cliente no debe descartarse.
// ==========================================================================================
DefFunc fDiscriminaCliente(atCliente:TABLA)
Local lRegresa
    
  lRegresa = 0

  // Se salta el Cliente NINGUNO
  Si atCliente(cIdClienteProveedor) = 0
    lRegresa = 1
  Finsi

  // Si no se trata de un cliente, lo discrimina :(1=cliente,2=cliente/provedor,3= proveedor)
  Si atCliente(cTipoCliente) > 2
    lRegresa = 1
  Finsi

  // Si Estado solicitado no es Todos y No Coincide el tipo de cliente con el parametro 
  // pCualesClientes = 2(inactivos) aplicando %2 = 0, 0 = inactivos en la tabla de clientes
  Si (pCualesClientes != 0) Y (atCliente(cEstatus) != pCualesClientes%2)
    lRegresa = 1
  Finsi

  // Se Revisan las CLASIFICACIONES, solo en el caso de haber seleccionado al menos una 
  Si gNumDeClases > 0
    Si !fMiembroDeUnaClase(atCliente;gNumDeClases;gListIdDeClases;0)
     // Sa salta el cliente actual, por no pertenecer a alguna de las clasificaciones
      lRegresa = 1
    Finsi
  Finsi
  Retorna lRegresa
FinFunc

// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// ENCABEZADO 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Encab   
    Texto '@TC{0,0,0}@S{8}AdminPAQ' 
 	  Hoja '"@TC{0,0,0}@S{8}Hoja: ' 
    Imprime 
    Texto '@TC{0,0,0}@S{8}Moneda: ' & gNombreMoneda
    Texto '"@TC{0,0,0}@S{8}Fecha: ' & gHoy
    Imprime
    Texto '^@TC{0,0,0}@S{22}' & tEmpresa->Nombre
    Imprime
    Texto '^@TC{0,0,0}@S{16}' & 'Relación de Cobranza por Cliente'
    Imprime
    gFechaCorte = fFormateaFecha(pFechaCorte;0)
    Texto '^@TC{0,0,0}@S{16}'& 'Fecha de Corte : ' & gFechaCorte
    Imprime 

    // ===== Se Revisan las clasificaciones, para recuperarlas e imprimirlas en el encabezado
    fRevisaClases(tValoresDeClasif)  
    // ===== Fin de la revision de clasificaciones

    fEncabColumnas()
 FinEncab

// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// PRINCIPAL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Si pDelCliente = ' '
  tClientes.Busca Primero
  pDelCliente = tClientes(cCodigoCliente)
Finsi
  
Si pAlCliente = ' '
  tClientes.Busca Ultimo
  pAlCliente =  tClientes(cCodigoCliente)  
Finsi

tParametros.Busca Primero   

// Esta función se debe ejecutar antes del cuerpo del reporte, para inicializar algunas valores
// Globales para la biblioteca LibAdminPAQ.rpt
fIniFechasHistoria(tPeriodos)

fEjercicioPeriodo(pFechaCorte;&gPeriodo;&gIdEjercicio;tPeriodos)  
// Esta función se debe ejecutar antes del cuerpo del reporte, para inicializar algunas valores
// Globales para la biblioteca LibAdminPAQ.rpt

Mientras[tClientes.Busca[pDelCliente&'..'&pAlCliente]; tClientes->Encontro; tClientes.Busca Siguiente[1]]  
  Si fDiscriminaCliente(tClientes) = 1
    Continua
  Finsi

  // Revisa que los días de pago y revisión del cliente coincidan con los que se pidieron
  Si !fCoincideDias(tClientes;&gDiasPagoCliente;&gDiasRevCliente)
    Continua
  Finsi

  gTotalSaldoCliente = 0.0  // acumula el saldo de los doctos que se imprimen para el cliente
  gTotalCliente = 0.0
  gImprimirCliente = 0      // Por omisión no se imprime el cliente hasta encontrar un docto con saldo
  gDatosCliente = 0         // Controla la impresión de los datos del cliente, solo una vez por cliente
  gImprimeTotalCliente = 0 

  Mientras[tDocumentos.BUSCA[@Str(tClientes(cIdClienteProveedor);0)]; tDocumentos->ENCONTRO; tDocumentos.BUSCA SIGUIENTE[1]]  
    Si tDocumentos(cFecha) > pFechaCorte
      FinCiclo
    FinSi

    // Si el docuemento no esta afectado, o no es de clientes o no es cargo; se lo salta
    Si (tDocumentos(cAfectado)!= 1) O (tDocumentos(cUsaCliente)!= 1)O (tDocumentos(cNaturaleza)!=0)
      Continua
    Finsi

    // Excluye los documentos de utilidad o perdida cambiaria
    Si ( tDocumentos(cIdDocumentoDe)>=28 Y tDocumentos(cIdDocumentoDe)<=31 )
      Continua
    Finsi

    // Calcula el Saldo del Documento es igual tanto para cargos, como para abonos
    gSaldoDocumento = fSaldoDocumento('';pFechaCorte;tCargosAbonosLib;tDocumentos;tDoctosLib)

    // Si al menos un docto tiene saldo, entonces se imprime el cliente
    Si (gSaldoDocumento > 0.001) 
      gImprimirCliente = 1
    Finsi

    // Si no tiene saldo, siempre se excluye
    Si (gImprimirCliente = 0 )
      Continua                        
    FinSi
    // Si llegó hasta aquí, el cliente tiene al menos un docto con saldo a la fecha de corte
    // Si el saldo no esta vencido y se elijió solo doctos vencidos, lo excluye
    Si  (tDocumentos(cFechaVencimiento) >= pFechaCorte) Y (pImprimirDoctos = 1)
      gImprimirCliente = 0  // Siempre no se va a imprimir el cliente.
      Continua
    Finsi

    // Si no se han impreso los datos, se imprimen y se levanta la bandera para no imprimirlos nuevamente
    Si gDatosCliente = 0
      fImprimeCliente(tClientes;gDiasPagoCliente;gDiasRevCliente)
      gDatosCliente = 1   // Solo se imprime una vez el encabezado del cliente
    FinSi

    // Solo se imprimen los documento que tienen un saldo realmente, a la fecha de corte
    Si gSaldoDocumento > 0.001
      // N.D.3219 Inicio
      // Expresar el total y el saldo en la moneda del reporte
      gSaldoDocumento = fCambiarMonedaDoctoAReporte(tDocumentos; tTiposCambioLib; gSaldoDocumento; pIdMoneda; tClientes(cIdMoneda))
      gTotalDocumento = fCambiarMonedaDoctoAReporte(tDocumentos; tTiposCambioLib; tDocumentos(cTotal); pIdMoneda; tClientes(cIdMoneda))
      // Enviar el total y el saldo a la función que imprime el documento
      fImprimirDocto(tDocumentos; gTotalDocumento; gSaldoDocumento)
      // N.D.3219 Fin
      gImprimeTotalCliente = 1
    Finsi

  FinMientras
  Si (gImprimeTotalCliente = 1)
    fImprimetotal(gTotalCliente;gTotalSaldoCliente;'C')
  Finsi
FinMientras   

fImprimeTotal(gTotalGral;gTotalGralSaldo;'G')

Saltalin 1
Texto '      *  Documentos Vencidos con respecto a la Fecha de Corte'
Imprime

//  FIN DEL REPORTE

