// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Reporte:     Reporte de ventas por cliente
//              Reporte de compras por proveedor
//
//
// Sistema:     ADMINPAQ  Versión v1.0 Windows
// 
// Descripcion: 
//
// Consideraciones :
// Creación  :  Luis Palau Castañeda.  12/Agosto/2001
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 18/05/2007   JAAM    N.C.147     Esquema de adicion de unidades de compra y venta  
//  22/04/2009  JENL    N.D.5708    NO MUESTRA EL REPORTE DE SEGUIMIENTO DE OPERACIONES DE VENTA CUANDO SE MANDA LLAMAR POR REPORTE SENSIBLE A CONTEXTO DESDE REPORTE DE VENTAS POR PRODUCTO (ES EL 3ER NIVEL)
//                                  Se modifico:
//                                  -ContextoDetalleClienteProd
//                                  -fRenglon
//                                  -fAcumulaProducto
//                                  -fProcesaMovto
//                                  Se agrego:
//                                  -fObtieneCodigo
//                                  -fRellena
//                                  -Una columna
//  24/04/2009  JENL    N.D.5767    EL REPORTE DE VENTAS POR CLIENTE NO MUESTRA EL TOTAL DE LA COLUMNA
//                                  CANTIDAD
//                                  Se modifico: fRenglon
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// *************************************************************************************************
// INCLUSION DE ARCHIVOS
// *************************************************************************************************
    Incluye LibAdminPaq.rpt


// *************************************************************************************************
// INICIO PARAMETROS
// *************************************************************************************************
    Parametro pFechaIni         = '20050101'
    Parametro pFechaFin         = '20051231'
    Parametro pClienteInicial   = ' ' 
    Parametro pClienteFinal     = ' '
    Parametro pProductoInicial  = ' '
    Parametro pProductoFinal    = ' '
    Parametro pUnidad           = 0	  // 0 = Unidad Base ·	1 = Unidad No Equivalente ·	2 = Seleccionar Unidad
    Parametro pIdUnidad         = 1   // Base de datos de unidades (id)   
    Parametro pIdMoneda         = 1   // 1 = ID moneda Peso mexicano
    Parametro pTipoReporte      = 1   // 1   ventas, 
                                      // 2   compras, 
                                      // 3   notas de venta


// *************************************************************************************************
// INICIO APERTURA TABLAS
// *************************************************************************************************
  UsaEmpresa tEmpresa;'AdminpaqW'

  UsaTabla tParametros = tEmpresa['mgw10000']

  UsaTabla tClientes = tEmpresa['mgw10002']
  tClientes.Usaindice['iCodigoTipo']

  UsaTabla tProductos = tEmpresa['mgw10005']
  tProductos.Usaindice['cIdProducto']

  UsaTabla tDocumentos = tEmpresa['mgw10008']
  tDocumentos.Usaindice['iClienteProveedorFecha']

  UsaTabla tMovimientos = tEmpresa['mgw10010'] Alias 'Movimientos'
  tMovimientos.Usaindice['iDoctoNumeroMovto']

  UsaTabla tMovimientosOcultos = tEmpresa['mgw10010'] Alias 'tMovtosOcultos' 
  tMovimientosOcultos.Usaindice['iMovtoOwnerMovto']

  UsaTabla tUnidadesPM = tEmpresa['mgw10026']
  tUnidadesPM.Usaindice['']

  UsaTabla tEquivaleUnidadesPM = tEmpresa['mgw10027']
  tEquivaleUnidadesPM.Usaindice['']

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

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

  tParametros.Busca Primero   

// *************************************************************************************************
//DEFINICION DE COLUMNAS 
// *************************************************************************************************
  //Columnas 20;2.7,0.15,5.55,0.15, 2.25,0.15,0.9,0.15, 0,0 ,2.25,0.15,2.25,0.15,2.25,0,0,0.15,0
  //          Código   Nom(Prod) Cantidad  Unidad    Neto      Descuento Neto-Desc Impuesto  Total
  //          C0       C2        C4        C6        C8        C10       C12       C14       C16
  //Columnas 18;2.7,0.15,4.05,0.15,1.95,0.15,0.90,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0 N.D.5708
  Columnas 19;2.7,0.15,4.05,0.15,1.95,0.15,0.90,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0//N.D.5708

  UsaLetra 'Arial'
  Altura 9 
  [C0..C3,C6].Decimales 0
  [C0..C3,C6].Blanco ' '
  tMonedas.Busca[@Str(pIdMoneda;0)]
  gDecimales = tMonedas(cDecimalesMoneda)
  [C8..C16].Coma
  [C4].Decimales tParametros(cDecimalesUnidades) // Decimales para unidades
  [C8..C16].Decimales gDecimales
  [C4, C8..C16].Blanco '0.00'
  [C5,C7,C9,C11,C13,C15,C17].Blanco ' '


// *************************************************************************************************
//VARIABLES GLOBALES 
// *************************************************************************************************
  gUnidad = pUnidad
  gIdUnidad = pIdUnidad
  gIdRenIni = 5  // Inicio de la hoja
  gIdRenFin = 5  // Fin de la hoja (inicializacion)
  gDelaFecha = pFechaIni
  gAlaFecha  = pFechaFin
  gRenglon = '' 
  gTotalCliente = ''
  gTotalGral = ''
  // N.D.3011 Inicio
  // Total de unidades de paquetes
  gTotalPaquetes = ''
  gTotalClientePaquetes = ''
  // N.D.3011 Fin
  gNombreMoneda = tMonedas(cNombreMoneda)
  gEncabezadoCliente = 0
  gImpTotalGral = 0
 
  kMeses = 'Ene,Feb,Mar,Abr,May,Jun,Jul,Ago,Sep,Oct,Nov,Dic'[C0]


// *************************************************************************************************
//FUNCIONES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// *************************************************************************************************

//--------------------------------------------------------------------------------------------------
//  Nombre: fObtieneCodigo
//  Proceso: Obtiene el código que corresponde al id que recibe en la tabla que recibe
//  Entradas: aId, el id del que queremos obtener el código
//            aTabla, la tabla en la que buscaremos el codigo de aId (1 = Clientes, 2 = Productos)
//  Salidas: lCodigo, el código encontrado
//  Consideraciones:
//
//  Historial de revisiones
//    Fecha     ID_SitePruebas              Descripción
//--------------------------------------------------------------------------------------------------
//  22/04/2009    N.D.5708        Implementación inicial (JENL).
//--------------------------------------------------------------------------------------------------
DefFunc fObtieneCodigo(aId;aTabla)
  Si aTabla = 1
    tClientes.Usaindice['PRIMARYKEY']
    tClientes.Busca[@Str(aId;0)]
    Si tClientes->Encontro
      Retorna tClientes(cCodigoCliente)
    Finsi
  Sino
    tProductos.Busca[@Str(aId;0)]
    Si tProductos->Encontro
      Retorna tProductos(cCodigoProducto)
    Finsi
  FinSi
FinFunc//fObtieneCodigo

//--------------------------------------------------------------------------------------------------
//  Nombre: ContextoDetalleClienteProd
//  Proceso: Función área sensible al contexto
//  Entradas: 
//  Salidas: 
//  Consideraciones:
//
//  Historial de revisiones
//    Fecha     ID_SitePruebas              Descripción
//--------------------------------------------------------------------------------------------------
//  22/04/2009    N.D.5708        Se cambia lo que recibe en aValor, ahora recibe el id del cliente
//                                y el del producto rellenados a la izq. con ceros y los manda a
//                                fObtieneCodigo para obtener los códigos correpondientes y ejecutar
//                                el reporte como siempre (JENL).
//--------------------------------------------------------------------------------------------------
DefFunc ContextoDetalleClienteProd(aNumeroColumna; aValor)
  //N.D.5708 Inicio
  Local lP1, lP2
  lP1 = fObtieneCodigo(@INT(@SubStr(aValor;0;10));1)//tClientes
  lP2 = fObtieneCodigo(@INT(@SubStr(aValor;10;10));2)//tProductos
  //EJECUTA tEmpresa->SysDirDatos & '\Reportes\AdminPAQ\ResProv.rtw';0,0,@Trim(2;@Escoge(aValor;0)),@Trim(2;@Escoge(aValor;0)),@Escoge(aValor;1),@Escoge(aValor;1),pUnidad,pIdUnidad,pIdMoneda,pTipoReporte,pFechaIni,pFechaFin;tEmpresa->Directorio
  EJECUTA tEmpresa->SysDirDatos & '\Reportes\AdminPAQ\ResProv.rtw';0,0,lP1,lP1,lP2,lP2,pUnidad,pIdUnidad,pIdMoneda,pTipoReporte,pFechaIni,pFechaFin;tEmpresa->Directorio
  //N.D.5708 Fin
FinFunc

// *************************************************************************************************
// Descripcion: Esta función recibe una fecha con formato ddmmaaaa y la convierte a formato dd/mmm/aaaa
// Entradas :  Fecha : contiene la fecha AAAAMMDD
// Salida :    regresa una cadena con la fecha en formato DD/MMM/AAAA
// *************************************************************************************************
DefFunc fEditaFecha(aFecha)
Local lMes
Local lRegreso

	lMes = @INT(@SubStr(aFecha;4;2))
	lRegreso[0] = @SubStr(aFecha;6;2) & '/' & @Escoge(kMeses;lMes-1) & '/' & @SubStr(aFecha;0;4)
  Retorna lRegreso
FinFunc

//--------------------------------------------------------------------------------------------------
//  Nombre: fRellena
//  Proceso: Rellena el id que recibio con ceros a la izquierda hasta que tenga una longitud de 10
//  Entradas: aId, el id que queremos rellenar
//  Salidas: el id rellenado
//  Consideraciones:
//
//  Historial de revisiones
//    Fecha     ID_SitePruebas              Descripción
//--------------------------------------------------------------------------------------------------
//  22/04/2009    N.D.5708        Implementación inicial (JENL).
//--------------------------------------------------------------------------------------------------
DefFunc fRellena(aId)
  Local lRetorno
  lRetorno = ''
  MIENTRAS @LEN(lRetorno & aId) < 10
    lRetorno = lRetorno & '0'
  FINMIENTRAS
  Retorna lRetorno & aId
FinFunc//fRellena

//--------------------------------------------------------------------------------------------------
//  Nombre: fRenglon
//  Proceso: imprime los acumulados de un producto
//  Entradas: 
//  Salidas: 
//  Consideraciones:
//
//  Historial de revisiones
//    Fecha     ID_SitePruebas              Descripción
//--------------------------------------------------------------------------------------------------
//  22/04/2009    N.D.5708        Lo que se almacena en [C4].REGIONINFO combia de formato, ahora se
//                                guardan los ids rellenados con ceros a la izq, y contiguos (JENL).
//  24/04/2009    N.D.5767        Faltaba sumar la columna de cantidad (JENL)
//--------------------------------------------------------------------------------------------------
DefFunc fRenglon(aIdRenglon)

  // Código   Nom(Prod) Cantidad  Unidad    Neto    Descuento Neto-Desc Impuesto  Total
  // C0       C2        C4        C6        C8      C10       C12       C14       C16
  gRenglon[0] = @Col({aIdRenglon};1)
  gRenglon[2] = @Col({aIdRenglon};2)
  gRenglon[4] = @Col({aIdRenglon};3)
  gRenglon[6] = '^' & @Col({aIdRenglon};4)
  gRenglon[8] = @Col({aIdRenglon};5)
  gRenglon[10] = @Col({aIdRenglon};6)
  gRenglon[12] = @Col({aIdRenglon};7)
  gRenglon[14] = @Col({aIdRenglon};8)
  gRenglon[16] = @Col({aIdRenglon};9)

  // Solo si la cantidad del producto es mayor a cero se imprime y se acumula
  Si @Col(gRenglon;4) > 0
    DEFREGION ContextoDetalleClienteProd
    //[C4].REGIONINFO tClientes(cCodigoCliente) & ' ,' & @Col({aIdRenglon};11) N.D.5708
    [C4].REGIONINFO fRellena(tClientes(cIdClien01)) & fRellena(@Col({aIdRenglon};18))//N.D.5708
    Imprime gRenglon

    // Acumular Totales Generales y por Cliente
    Si @Col({aIdRenglon};10) = 2
      // En caso de paquetes acumular las unidades al total de paquetes
      gTotalPaquetes = gTotalPaquetes + gRenglon[C4]
      // En caso de paquetes acumular las unidades al total de paquetes
      gTotalClientePaquetes = gTotalClientePaquetes + gRenglon[C4]
      //N.D.5767 Inicio
      // Acumular los restantes importes
      //gTotalCliente = gTotalCliente + gRenglon[C6, C8, C10, C12, C14, C16]
      //gTotalGral = gTotalGral + gRenglon[C6, C8, C10, C12, C14, C16]  
    //Sino
    FinSi
    //N.D.5767 Fin
      // Acumular las cantidades
      //gTotalCliente = gTotalCliente + gRenglon
      //gTotalGral = gTotalGral + gRenglon //RCVG ND: 5557
      //N.D.5767 Inicio
      //gTotalCliente = gTotalCliente + gRenglon[C6, C8, C10, C12, C14, C16]
      //gTotalGral = gTotalGral + gRenglon[C6, C8, C10, C12, C14, C16]  
      gTotalCliente = gTotalCliente + gRenglon[C4, C6, C8, C10, C12, C14, C16]
      gTotalGral = gTotalGral + gRenglon[C4, C6, C8, C10, C12, C14, C16]  
    //FinSi
      //N.D.5767 Fin
  FinSi
  gRenglon = '' 
Finfunc


// *************************************************************************************************
// Descripcion: imprime los datos del cliente o proveedor
// Entradas :  
// Salida :    
// *************************************************************************************************
Deffunc ImprimeCP()
Local lImprime, lIdRenglon

  Si gIdRenIni < gIdRenFin
    gEncabezadoCliente = 1
    gImpTotalGral = 1

    //          C0       C2
    //Columnas 18;1.5,0.15,6.6,0.15,0 N.D.5708
    Columnas 19;1.5,0.15,6.6,0.15,0//N.D.5708
    Negritas True

    Si pTipoReporte = 1 o  pTipoReporte = 3
      lImprime = 'Cliente:' [c0]
    Sino
      lImprime = 'Proveedor:' [c0]
    Finsi
    lImprime = fMascarilla(tClientes(cCodigoCliente);tParametros(cMascarillaClientes))[C2]
    Imprime lImprime

    lImprime = 'Nombre:' [c0]
    lImprime = tClientes(cRazonSocial) [c2]
    Imprime lImprime
    Negritas False
  
    //          Código   Nom(Prod) Cantidad  Unidad    Neto      Descuento Neto-Desc Impuesto  Total
    //          C0       C2        C4        C6        C8        C10       C12       C14       C16
    //Columnas 18;2.7,0.15,4.05,0.15,1.95,0.15,0.90,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0 N.D.5708
    Columnas 19;2.7,0.15,4.05,0.15,1.95,0.15,0.90,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0//N.D.5708
    // Imprime el detalle   
    Mientras [lIdRenglon = gIdRenIni; lIdRenglon < gIdRenFin; lIdRenglon = lIdRenglon + 1]
      fRenglon(lIdRenglon)
    FinMientras
  FinSi
Finfunc

// *************************************************************************************************
// Descripcion: imprime los totales generales de las variables gTotalGral
// Entradas :  
// Salida :    
// *************************************************************************************************
DefFunc fTotalGeneral()
Local LTotalLinea
  // Código   Nom(Prod) Cantidad  Unidad    Neto    Descuento Neto-Desc Impuesto  Total
  // C0       C2        C4        C6        C8      C10       C12       C14       C16

  // Si hubo datos
  Si gImpTotalGral = 1
    LTotalLinea = '==========================='[C0]
    //Texto '@L{4,8,10,12,14,16}'
    Texto C4; @Col(LTotalLinea;0)
    Texto C8; @Col(LTotalLinea;0)
    Texto C10; @Col(LTotalLinea;0)
    Texto C12; @Col(LTotalLinea;0)
    Texto C14; @Col(LTotalLinea;0)
    Texto C16; @Col(LTotalLinea;0)

    Imprime
    gTotalGral = ''[C0..C3]
    gTotalGral[2] = 'Total General'
    gTotalGral = ''[C5..C7]
    Imprime gTotalGral
    gTotalGral = ''

    // Total de paquetes
    Si @Col(gTotalPaquetes; 4) > 0
      gTotalPaquetes = ''[c0..c3]
      gTotalPaquetes[2] = 'Total Cantidad de Paquetes'
      Imprime gTotalPaquetes
    FinSi
  FinSi
Finfunc

// *************************************************************************************************
// Descripcion: imprime los totales del cliente de las variables gTotalCliente
// Entradas :  
// Salida :    
// *************************************************************************************************
DefFunc  fTotalCliente()
  // Código   Nom(Prod) Cantidad  Unidad    Neto    Descuento Neto-Desc Impuesto  Total
  // C0       C2        C4        C6        C8      C10       C12       C14       C16

  //si hubo encabezado del cliente 
  Si gEncabezadoCliente = 1
    Texto '@L{4,8,10,12,14,16}'
    Imprime
    gTotalCliente = ''[C0..C3]
    Si pTipoReporte = 1
      gTotalCliente[2] = 'Total Cliente'
    Sino
      gTotalCliente[2] = 'Total Proveedor'
    FinSi    
    gTotalCliente = ''[C5..C7]
    Imprime gTotalCliente
    gTotalCliente  = ''
    gEncabezadoCliente = 0
    
    // Total de paquetes
    Si @Col(gTotalClientePaquetes; 4) > 0
      gTotalClientePaquetes = ''[c0..c3]
      gTotalClientePaquetes[2] = 'Total Cantidad de Paquetes'
      Imprime gTotalClientePaquetes
    FinSi
    gTotalClientePaquetes = ''
  FinSi
Finfunc
//--------------------------------------------------------------------------------------------------
//  Nombre: fAcumulaProducto
//  Proceso: Agrega el producto si no existe y deposita o acumula los datos del movimiento
//  Entradas: el producto
//  Salidas: id del renglon
//  Consideraciones:
//
//  Historial de revisiones
//    Fecha     ID_SitePruebas              Descripción
//--------------------------------------------------------------------------------------------------
//  22/04/2009    N.D.5708        Se agrega el id del producto como parametro para almacenarse (JENL).
//--------------------------------------------------------------------------------------------------
//DefFunc fAcumulaProducto(aCodigo;aCodigoMascara;aNombreProd;aCantidad;aUnidad;aNeto;aDescuentos;aImpuestos;aTotal;aTipoProducto) N.D.5708
DefFunc fAcumulaProducto(aCodigo;aCodigoMascara;aNombreProd;aCantidad;aUnidad;aNeto;aDescuentos;aImpuestos;aTotal;aTipoProducto; aIdProducto)//N.D.5708
Local lIdTemp

  lIdTemp = gIdRenIni

  Mientras  lIdTemp < gIdRenFin
    Si @Col(aCodigoMascara;0) = @Col({lIdTemp};1)
      FinCiclo
    Finsi
    lIdTemp = lIdTemp + 1
  FinMientras

  // Si no se encontro el producto lo agrega a la lista
  Si lIdTemp = gIdRenFin
    {lIdTemp}[1] = aCodigoMascara
    {lIdTemp}[2] = aNombreProd
    {lIdTemp}[3] = 0
    {lIdTemp}[4] = aUnidad
    {lIdTemp}[5] = 0
    {lIdTemp}[6] = 0
    {lIdTemp}[7] = 0
    {lIdTemp}[8] = 0
    {lIdTemp}[9] = 0
    // Indica el tipo de Producto: Producto, servicio o paquete
    {lIdTemp}[10] = 0
    {lIdTemp}[18] = @Col(aIdProducto;0)//N.D.5708
    gIdRenFin = lIdTemp + 1
    {lIdTemp}[11] = aCodigo
  Finsi

  // Agrega los datos
  {lIdTemp}[3] = @Col({lIdTemp};3) + @Col(aCantidad;0)
  {lIdTemp}[5] = @Col({lIdTemp};5) + @Col(aNeto;0)
  {lIdTemp}[6] = @Col({lIdTemp};6) + @Col(aDescuentos;0)
  {lIdTemp}[7] = @Col({lIdTemp};7) + @Col(aNeto;0) - @Col(aDescuentos;0)
  {lIdTemp}[8] = @Col({lIdTemp};8) + @Col(aImpuestos;0)
  {lIdTemp}[9] = @Col({lIdTemp};9) + @Col(aTotal;0)
  {lIdTemp}[10] = aTipoProducto
FinFunc

//--------------------------------------------------------------------------------------------------
//  Nombre: fProcesaMovto
//  Proceso: Agrega el producto si no existe y deposita o acumula los datos del movimiento
//  Entradas: aTblDocto : Documento del que se tomarán la fecha y el tipo de cambio
//            aTblMovto : Movimiento del que se tomarán los datos
//  Salidas: Importe del documento reflejado en la moneda que recibe
//  Consideraciones:
//
//  Historial de revisiones
//    Fecha     ID_SitePruebas              Descripción
//--------------------------------------------------------------------------------------------------
//  22/04/2009    N.D.5708        Se agrega el id del producto como argumento en la llamda a
//                                fAcumulaProducto (JENL).
//--------------------------------------------------------------------------------------------------
Deffunc fProcesaMovto(aTblDocto:TABLA; aTblMovto:TABLA)
  Local lCantidad, lUnidad, lNeto, lDescuentos, lImpuestos, lTotal
  Local lRegresa, lIdUnidad
  Local lIdMonedaCte

  lRegresa = 0
  Si aTblMovto(cIdProducto) = 0
    lRegresa = 1
  SiNo
    tProductos.Busca[@Str(aTblMovto(cIdProducto);0)]
    Si pTipoReporte = 2
      Si tProductos(cTipoProducto) = 2
        //si es compra y es paquete, se brinca el registro
        lRegresa = 1
      Finsi
    Finsi
  FinSi

  Si lRegresa = 0 Y tProductos->Encontro Y (tProductos(cCodigoProducto) >= pProductoInicial O pProductoInicial = ' ') Y (tProductos(cCodigoProducto) <= pProductoFinal O pProductoFinal = ' ')
    // Si es uno de los servicios para facturar notas de venta no incluirlo
    Si tProductos(cIdProducto) != tParametros(cIdProdu01) Y tProductos(cIdProducto) != tParametros(cIdProdu02) Y tProductos(cIdProducto) != tParametros(cIdProdu03) Y tProductos(cIdProducto) != tParametros(cIdProdu04) Y tProductos(cIdProducto) != tParametros(cIdProdu05)
      // Calcula datos (Cantidad en sus unidades, neto, suma de descuentos, suma de impuestos y total)
      lIdUnidad = tProductos(cIdUnidadBase)

      fVerificaUnidad(tProductos)

      // En este método no se utiliza tMovimientos sino aTblMovto
      // SI el Producto tiene Unidad de Medida NO Equivalente  "Y" pUnidad = 1
      Si pUnidad = 1 Y tProductos(cIdUnidadNoConvertible) != 0 Y tMovimientos(cUnidadesNC) > 0        
        lCantidad = aTblMovto(cUnidadesNC) //tMovimientos(cUnidadesNC)
        lIdUnidad = tProductos(cIdUnidadNoConvertible)
      Sino 
        lCantidad = aTblMovto(cUnidades) //tMovimientos(cUnidades)
      FinSi

      // Convertir cantidad de unidades a la unidad solicitada
      Si pUnidad = 2 Y tProductos(cIdUnidadBase) != 0
        // El Producto tiene Unidad de Medida y Peso, por lo que hay que
        //	unificar vCantidad de acuerdo a la unidad deseada en el reporte.
        //	EquivalenciaUnidadMedidayPeso.BUSCA[Productos(cIdUnidadBase)+cIdUnidad]	
        tEquivaleUnidadesPM.Busca[@Str(tProductos(cIdUnidadBase);0) &':'& @Str(pIdUnidad;0)]
        Si tEquivaleUnidadesPM->Encontro
          lCantidad = lCantidad * tEquivaleUnidadesPM(cFactorConversion)
          lIdUnidad = pIdUnidad
        Finsi
      Finsi

      // Se busca el nombre de la unidad del producto
      lUnidad = ''
      Si lIdUnidad != 0
        tUnidadesPM.Busca[@Str(lIdUnidad;0)]
        Si tUnidadesPM->Encontro
          lUnidad = tUnidadesPM(cDespliegue)
        FinSi
      FinSi

      lIdMonedaCte = tClientes(cIdMoneda)
      lNeto = fCambiarMonedaDoctoAReporte(aTblDocto; tTiposCambio; aTblMovto(cNeto); pIdMoneda; lIdMonedaCte)
      lDescuentos = aTblMovto(cDescuento1) + aTblMovto(cDescuento2) + aTblMovto(cDescuento3) + aTblMovto(cDescuento4) + aTblMovto(cDescuento5)
      lDescuentos = fCambiarMonedaDoctoAReporte(aTblDocto; tTiposCambio; lDescuentos; pIdMoneda; lIdMonedaCte)
      lImpuestos = aTblMovto(cImpuesto1) + aTblMovto(cImpuesto2) + aTblMovto(cImpuesto3)
      lImpuestos = fCambiarMonedaDoctoAReporte(aTblDocto; tTiposCambio; lImpuestos; pIdMoneda; lIdMonedaCte)
      lTotal = fCambiarMonedaDoctoAReporte(aTblDocto; tTiposCambio; aTblMovto(cTotal); pIdMoneda; lIdMonedaCte)

      // Enviar el tipo de producto
      // Acumula los saldos en memoria
      //fAcumulaProducto(tProductos(cCodigoProducto);fMascarilla(tProductos(cCodigoProducto);tParametros(cMascarillaProducto));tProductos(cNombreProducto);lCantidad;lUnidad;lNeto;lDescuentos;lImpuestos;lTotal;tProductos(cTipoProducto)) N.D.5708
      fAcumulaProducto(tProductos(cCodigoProducto);fMascarilla(tProductos(cCodigoProducto);tParametros(cMascarillaProducto));tProductos(cNombreProducto);lCantidad;lUnidad;lNeto;lDescuentos;lImpuestos;lTotal;tProductos(cTipoProducto);tProductos(cIdProducto))//N.D.5708
    FinSi
  FinSi
FinFunc


// *************************************************************************************************
//ENCABEZADO 
// *************************************************************************************************
  Encab
    Texto '@TC{255,0,0}@S{8}AdminPAQ' 
    Hoja '"@TC{0,0,0}@S{8}Página: '
    Imprime

    Texto '@TC{0,0,0}@S{8}Moneda: '& gNombreMoneda
    Texto '^@TC{0,0,0}@S{22}' & tEmpresa->Nombre
    Texto '"@TC{0,0,0}@S{8}Fecha: ' & fEditaFecha(@Hoy())
    Imprime
    Si pTipoReporte = 1
      Texto '^@TC{0,0,0}@S{16}' & ' Reporte de Ventas por Cliente'
    Sino
      Si pTipoReporte = 2
        Texto '^@TC{0,0,0}@S{16}' & ' Reporte de Compras por Proveedor'
      Sino
        Si pTipoReporte = 3
          Texto '^@TC{0,0,0}@S{16}' & ' Reporte de Devoluciones Sobre Venta por Cliente'
        Sino 
          Texto '^@TC{0,0,0}@S{16}' & ' Reporte de Devoluciones Sobre Compra por Proveedor'
        Finsi
      Finsi
    Finsi

    Texto '"@TC{0,0,0}@S{8}Hora: ' & @Hora()
    Imprime

    Texto '^@TC{0,0,0}@S{16}'& 'Del ' & fEditaFecha(gDelaFecha) & ' al ' & fEditaFecha(gAlaFecha)
    Imprime 
    NEGRITAS TRUE
    Altura 10

    //Código         Nombre(Cliente)                       Cantidad       Precio     Neto       Descuento Impuesto  Total         
    //          Código   Nom(Prod) Cantidad  Unidad    Neto      Descuento Neto-Desc Impuesto  Total
    //          C0       C2        C4        C6        C8        C10       C12       C14       C16
    //Columnas 18;2.7,0.15,4.05,0.15,1.95,0.15,0.90,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0 N.D.5708
    Columnas 19;2.7,0.15,4.05,0.15,1.95,0.15,0.90,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0.15,1.95,0//N.D.5708

    Texto '@TC{0,0,0}@L{-1}'
	  Imprime 
  
    Texto C0;'Código'
    Texto C2;'Nombre (Producto,Servicio,Paquete)'
    Texto C4;'^Cantidad' 
    Texto C6;'^Unidad' 
    Texto C8;'^Neto' 
    Texto C10;'^Descuento' 
    Texto C12;'^Neto-Desc.' 
    Texto C14;'^Impuesto'
    Texto C16;'^Total'
    Imprime   

    Texto '@TC{0,0,0}@L{-1}'
    Imprime 
    NEGRITAS FALSE
    Altura 10
  FinEncab

// *************************************************************************************************
// PRINCIPAL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// *************************************************************************************************
  gRenglon = '' 
  gTotalGral = ''

  Si pClienteInicial = ' '
    tClientes.Busca Primero
  Sino
    tClientes.Busca[pClienteInicial & ':'] 
  Finsi

  // Ciclo principal de clientes
  Mientras tClientes->Encontro
    Si pClienteInicial != ' '
      Si tClientes(cCodigoCliente) < pClienteInicial
        tClientes.Saltareg[1]
        Continua  
      Finsi 
    Finsi

    Si pClienteFinal != ' '
      Si tClientes(cCodigoCliente) > pClienteFinal
        Finciclo
      Finsi 
    Finsi

    // Se salta el Cliente NINGUNO
    Si tClientes(cIdClienteProveedor) = 0
      tClientes.Saltareg[1]
      Continua  
    Finsi

    // Si se requieren los clientes y no se trata de un cliente:(1=cliente,2=cliente/provedor,3= proveedor)
    Si (pTipoReporte = 1 O pTipoReporte = 3) Y (tClientes(cTipoCliente) > 2) 
      tClientes.Saltareg[1]
      Continua
    Finsi

    // Si se requieren los Proveedores y no se trata de un Proveedor
    Si (pTipoReporte = 2 O pTipoReporte = 4)  Y (tClientes(cTipoCliente) < 2) 
      tClientes.Saltareg[1]
      Continua
    Finsi

    gIdRenFin = 5  // Reinicia la hoja con el cliente

    // N.D.4048 Búsqueda de un movimiento del producto a la fecha inicial del reporte
    gFechaBusqueda = pFechaIni
    // NOTA: Es obligatorio volver a fijar el índice a fin de que las búsquedas parciales funcionen correctamente
    tDocumentos.Usaindice['iClienteProveedorFecha']
    tDocumentos.Busca[tClientes(cIdClienteProveedor) & ':' & gFechaBusqueda]
    Si !tDocumentos->ENCONTRO
      // Busquedas parciales: Cursor en el registro más cercano que cumple con la llave
      // NOTA: La propiedad Llave de la tabla nos regresa la llave más cercana que cumple con el criterio de la búsqueda
      //       La llave está en formato cadena y no tiene ningún separador entre los campos, por lo que es necesario revisar
      //      en FoxPro la definición del índice para descomponer los elementos de la Llave
      // Revisar si la llave actual corresponde al Producto / Almacén y al Rango de Fechas.
      Si tClientes(cIdClienteProveedor) = @Val(@SUBSTR(tDocumentos->Llave;0;11))
        Si @SUBSTR(tDocumentos->Llave;11;8) >= pFechaIni Y @SUBSTR(tDocumentos->Llave;11;8) <= pFechaFin
          // Realizar nuevamente la búsqueda a fin de posicionarnos en el registro y activar la propiedad Encontro
          gFechaBusqueda = @SUBSTR(tDocumentos->Llave;11;8)
          tDocumentos.Busca[tClientes(cIdClienteProveedor) & ':' & gFechaBusqueda]
        FinSi
      FinSi        
    FinSi

    Mientras tDocumentos->Encontro Y (tDocumentos(cFecha) <= pFechaFin)
      Si tDocumentos(cAfectado) != 1
        tDocumentos.BUSCA SIGUIENTE[1]
        Continua
      FinSi

      // El reporte es de Ventas No considerar documentos que no correspondan a facturas
      // El reporte es de Compras No considerar documentos que no correspondan a compras
      Si pTipoReporte = 1  Y (tDocumentos(cIdDocumentoDe) != 4 Y tDocumentos(cIdDocumentoDe) != 35)
        tDocumentos.BUSCA SIGUIENTE[1]
        Continua
      FinSi
      Si pTipoReporte = 2 Y (tDocumentos(cIdDocumentoDe) != 19)
        tDocumentos.BUSCA SIGUIENTE[1]
        Continua
      FinSi
      Si pTipoReporte = 3 Y (tDocumentos(cIdDocumentoDe) != 35)
        tDocumentos.BUSCA SIGUIENTE[1]
        Continua
      FinSi

      // Ciclo de los movimientos visibles del documento
      tMovimientos.Busca[@str(tDocumentos(cIdDocumento);0)]
      Mientras tMovimientos->Encontro
        Si tMovimientos(cIdDocumento) != tDocumentos(cIdDocumento)
          Finciclo
        FinSi

        // Acumula datos del movto a su producto asignado
        fProcesaMovto(tDocumentos;tMovimientos)

        // Recorre los movtos hijos del movto origen
        tMovimientosOcultos.Busca[@Str(tMovimientos(cIdMovimiento);0)]
        Mientras tMovimientosOcultos->Encontro
          Si tMovimientosOcultos(cIdMovtoOwner) != tMovimientos(cIdMovimiento)
            Finciclo
          Finsi 
            
          //ped. cot
          Si (tMovimientosOcultos(cIdDocumentoDe) = 1 O tMovimientosOcultos(cIdDocumentoDe) = 2) Y (tMovimientosOcultos(cTipoTraspaso)=4)
            tMovimientosOcultos.Saltareg[1]  
            Continua                 
          Finsi                                 
          //remisiones
          Si (tMovimientosOcultos(cIdDocumentoDe) = 3 ) Y (tMovimientosOcultos(cTipoTraspaso)!=2)
            tMovimientosOcultos.Saltareg[1]  
            Continua                 
          Finsi                                    
          //ord. compra ,consig
          Si (tMovimientosOcultos(cIdDocumentoDe) = 17 O tMovimientosOcultos(cIdDocumentoDe) = 18) Y (tMovimientosOcultos(cTipoTraspaso)=4)
            tMovimientosOcultos.Saltareg[1]  
            Continua                 
          FinSi

          // Acumula datos del movto a su producto asignado
          fProcesaMovto(tDocumentos;tMovimientosOcultos)

          tMovimientosOcultos.saltareg[1]           
        FinMientras

        tMovimientos.saltareg[1]
      FinMientras

      tDocumentos.BUSCA SIGUIENTE[1]
    FinMientras

    ImprimeCP()

    //Imprime Totales del cliente
    fTotalCliente()

    tClientes.Saltareg[1]
  FinMientras 

  // Imprime Totales Generales
  fTotalGeneral()
