// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
//	Capas.rpt
//	Nombre del reporte en el sistema: Análisis de capas
//
//  Sistema: AdminPAQ v1.1
// 
//	Este reporte perteneciente al módulo de inventarios, despliega los 
//  movimientos de entrada y salida de capas cuando el producto se costea
//  UEPS o PEPS.
//
//	Consideraciones especiales:
//  Este reporte aunque está programado como uno solo, representa en realidad
//  dos reportes en el ámbito del sistema:
//    Análisis de capas en unidades
//    Análisis de capas en importes
//  
//	Elaboró:    Eduardo Pérez Figueroa
//	Fecha: 	    18 de Octubre del 2001
//
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//  17/10/2002 LAP      N.D.1316    
//                                  - fObtenerIdsEntradaCapa
//  09/03/2005 HVA      N.D.3103    
//  28/04/2005 LAP      N.D.3240    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. Utilizar fCambiarMonedaDoctoAReporte y
//                                  fCambiarMonedaImporteAReporte de LibAdminPAQ.rpt
//  12/11/2008 ELVS     N.C.224     Se deben considerar los movimientos que están con el 
//                                  campo cAfectadoInventario = 2, se agrega marca y leyenda
//                                  de que esos movimientos están en captura.
//  16/12/2008 ELVS     N.D.5585    REPORTES DE INVENTARIO - CUANDO EL PRODUCTO ESTA EN 
//                                  CAPTURA. En los reportes de capa el texto de explicación
//                                  aparece incompleto y en otros reportes aparece el error
//                                  pero no que se puede hacer. 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

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

Incluye LibAdminPAQ.Rpt
Incluye LibInventarios.Rpt


// *****************************************************************************
//	Parámetros del reporte:

Parametro pFechaInicial = '20010901'    // Fecha inicial del rango
Parametro pFechaFinal = '20011130'      // Fecha final del rango
Parametro pProductoInicial = ' '        // Código del producto inicial del rango (' ' = Todos)
Parametro pProductoFinal = ' '          // Código del producto final del rango (' ' = Todos)
Parametro pImprimirProductos = 0        // Productos a imprimir:
                                        // 0 = Todos
                                        // 1 = Solo productos con movimientos 
Parametro pEstadoProducto = 0           // Incluir productos con estado:
                                        // 0 = Todos
                                        // 1 = Activos
                                        // 2 = Inactivos
Parametro pIdClase1 = 0                 // Clasificaciones del produto (0 = Ninguna)
Parametro pIdClase2 = 0                 // Estos seis parámetros corresponden a las seis clasificaciones
Parametro pIdClase3 = 0                 // del producto, y pueden contener una lista de IDs
Parametro pIdClase4 = 0                 // de clasificaciones separados por coma.
Parametro pIdClase5 = 0               
Parametro pIdClase6 = 0               
Parametro pIdMoneda = 1                 // Id de la moneda a expresar el reporte
Parametro pTipoReporte = 1              // Tipo de Reporte (este parámetro es interno a AdminPAQ)
                                        // 0 = Unidades
                                        // 1 = Importes

// *****************************************************************************
//	Tablas a utilizar e Indices de búsqueda por omisión

UsaEmpresa tEmpresa;'ADMINPAQW'                   // Parámetros

UsaTabla tProducto = tEmpresa['MGW10005']         // Productos
tProducto.Usaindice['iCodigoTipo']                // cCodigoProducto+cTipoProducto

UsaTabla tDocumento = tEmpresa['MGW10008']        // Documentos
tDocumento.Usaindice['']                          // Indice primario: cIdDocumento

UsaTabla tConcepto = tEmpresa['MGW10006']         // Conceptos de documentos
tConcepto.Usaindice['']                           // Indice primario: cIdConceptoDocumento

UsaTabla tMovimiento = tEmpresa['MGW10010'] Alias 'Movto'   // Movimientos
tMovimiento.Usaindice['iProductoFechaAfecta']     // cIdProducto+cFecha+cAfectaExistencia

UsaTabla tMovimiento2 = tEmpresa['MGW10010'] Alias 'Movto2' // Movimientos (para recorrer las salidas de las entradas de capas)
tMovimiento2.Usaindice['']                        // Indice primario: cIdMovimiento

UsaTabla tMovtoOwner = tEmpresa['MGW10010'] Alias 'MovtoOwner'  // Movimientos
tMovtoOwner.Usaindice['']                         // Indice primario: cIdMovimiento

UsaTabla tAlmacen = tEmpresa['MGW10003']          // Almacenes
tAlmacen.Usaindice['']                            // Indice primario: cIdAlmacen

UsaTabla tCapa = tEmpresa['MGW10025']             // Capas
tCapa.Usaindice['']                               // Indice primario: cIdCapa

UsaTabla tMovimientoCapa = tEmpresa['MGW10028']   // Movimientos de capas
tMovimientoCapa.Usaindice['']                     // Indice primario: cIdMovimiento+cIdCapa

UsaTabla tMovtoCapa1 = tEmpresa['MGW10028'] Alias 'MovtoCapa1'  // Movimientos de capas
tMovtoCapa1.Usaindice['']                     // Indice primario: cIdMovimiento+cIdCapa


UsaTabla tCapaMovto = tEmpresa['MGW10028'] Alias 'CapaMovto'   // Movimientos de capas
tCapaMovto.Usaindice['ICAPAFECHA']                     // Indice primario: cIdMovimiento+cIdCapa


UsaTabla tMoneda = tEmpresa['MGW10034']           // Monedas
tMoneda.Usaindice['']                             // Indice primario: cIdMoneda

UsaTabla tTipoCambioLib = tEmpresa['MGW10035']       // Tipo de cambio
tTipoCambioLib.Usaindice['iMonedaFecha']             // cIdMoneda+cFecha

UsaTabla tValoresDeClasif = tEmpresa['MGW10020']
tValoresDeClasif.UsaIndice['']                    // Indice primario: cIdValorClasificacion

UsaTabla tParametros = tEmpresa['MGW10000']       // Parámetros de la empresa
tParametros.Usaindice['']                         // Indice primario: cIdEmpresa

// N.D.3240 A fin de obtener la moneda del cliente / proveedor del documento
UsaTabla tClienteProveedor = tEmpresa['MGW10002'] // Clientes/Proveedores
tClienteProveedor.Usaindice['']                   // Indice primario: cIdClienteProveedor


// *****************************************************************************
// Definiciones y asumidos globales para el reporte

// Ancho de columnas = caracteres / 17 * 2.54
// Se consideran columnas intermedias de un espacio
// C0 (Fecha) = 11 caracteres
// C2 (Serie) = 5 caracteres
// C4 (Folio) = 8 caracteres
// C6 (Concepto) = 15 caracteres
// C8 (Almacén) = 3 caracteres
// C10 (Cantidad) = 14 caracteres
// C12 (Fecha) = 11 caracteres
// C14 (Serie) = 5 caracteres
// C16 (Folio) = 8 caracteres
// C18 (Concepto) = 15 caracteres
// C20 (Almacén) = 3 caracteres
// C22 (Cantidad) = 14 caracteres
//N.C.224
//    				      1	   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22    
Columnas 25;1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.45,1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.00	  
//Columnas 24;1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.45,1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,0
[C2,C4,C14,C16].Decimales 0
[C2,C4,C14,C16].Blanco ''

Usaletra 'Arial'
Altura 9


// *****************************************************************************
//	Variables de ámbito global:

gIdioma = 0               // Idioma del reporte
                          // 0 = Español
                          // 1 = Inglés
gMascarillaProducto = ''  // Mascarilla para el código del producto


// *****************************************************************************
//  fConfiguraDecimales
//
//	Configura el número de decimales de las columnas de importes, basado en
//  los parámetros de la empresa.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fConfiguraDecimales()

  // Busca el registro de la empresa
  tParametros.Busca Primero
  Si tParametros->Encontro // Si lo encontró
    Si pTipoReporte
      [C10,C22].Decimales tParametros(cDecimalesCostos)
    Sino // entonces el reporte es en unidades
      [C10,C22].Decimales tParametros(cDecimalesUnidades)
    FinSi
    gMascarillaProducto = tParametros(cMascarillaProducto) // mascarilla para el código del producto
  Sino // Si no encontró el registro de la empresa
    [C10,C22].Decimales 2
  FinSi
FinFunc


// *****************************************************************************
//  fGuardaMovimiento
//
//	Esta función almacena en el buffer de impresión, los datos del
//  movimiento para ser impresos por pares.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fGuardaMovimiento(atMovimiento: Tabla; aCantidad; aImprime)
Local lFechaEditada, lIdDocumento

  // Si el movimiento es de entrada
  Si atMovimiento(cAfectaExistencia) = 1
    // Fecha del movimiento
    lFechaEditada = fFormateaFecha(atMovimiento(cFecha); gIdioma)
    aImprime = @Col(lFechaEditada;0)[C0]

    // lee el documento del movimiento
    Si atMovimiento(cIdDocumento)
      tDocumento.Busca[@Str(atMovimiento(cIdDocumento);0)]
    Sino // es un movimiento oculto
      // Busca el ID del documento en el movimiento owner
      lIdDocumento = fIdDocumentoMovtoOwner(atMovimiento; tMovtoOwner) 
      tDocumento.Busca[@Str(lIdDocumento;0)]
    FinSi
    Si tDocumento->Encontro
      // Serie
      aImprime = tDocumento(cSerieDocumento)[C2]
      // Folio
      aImprime = tDocumento(cFolio)[C4]
      // lee el concepto del documento
      tConcepto.Busca[@Str(tDocumento(cIdConceptoDocumento);0)]
      Si tConcepto->Encontro
        aImprime = tConcepto(cNombreConcepto)[C6]
      FinSi
    FinSi
  
    // Almacén  
    tAlmacen.Busca[@Str(atMovimiento(cIdAlmacen);0)]
    Si tAlmacen->Encontro
      aImprime = tAlmacen(cCodigoAlmacen)[C8]
    FinSi

    // Unidades del movimiento
    aImprime = @Col(aCantidad;0)[C10]
  Sino // Movimiento de salida
    // Fecha del movimiento
    lFechaEditada = fFormateaFecha(atMovimiento(cFecha); gIdioma)
    aImprime = @Col(lFechaEditada;0)[C12]

    // lee el documento del movimiento
    Si atMovimiento(cIdDocumento)
      tDocumento.Busca[@Str(atMovimiento(cIdDocumento);0)]
    Sino // es un movimiento oculto
      // Busca el ID del documento en el movimiento owner
      lIdDocumento = fIdDocumentoMovtoOwner(atMovimiento; tMovtoOwner) 
      tDocumento.Busca[@Str(lIdDocumento;0)]
    FinSi
    Si tDocumento->Encontro
      // Serie
      aImprime = tDocumento(cSerieDocumento)[C14]
      // Folio
      aImprime = tDocumento(cFolio)[C16]
      // lee el concepto del documento
      tConcepto.Busca[@Str(tDocumento(cIdConceptoDocumento);0)]
      Si tConcepto->Encontro
        aImprime = tConcepto(cNombreConcepto)[C18]
      FinSi
    FinSi

    // Almacén  
    tAlmacen.Busca[@Str(atMovimiento(cIdAlmacen);0)]
    Si tAlmacen->Encontro
      aImprime = tAlmacen(cCodigoAlmacen)[C20]
    FinSi

    // Unidades del movimiento
    aImprime = @Col(aCantidad;0)[C22]
  FinSi
FinFunc


// *****************************************************************************
//  fImprimeDatosProducto
//
//	Esta función imprime los datos del producto (código, nombre)
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeDatosProducto(atProducto: Tabla)
Local vImprime, lCodigoEditado, lFechaEditada

  // Redefine el ancho de las columnas
  // C0 20 caracteres
  // C2 70 caracteres
  Columnas 24; 2.99,0.15,10.46,0

  vImprime = ' '[C0..C23]

  NEGRITAS TRUE

  vImprime = 'Producto: '[C0]
  lCodigoEditado = fMascarilla(atProducto(cCodigoProducto); gMascarillaProducto)
  vImprime = @Col(lCodigoEditado;0)[C2]
  Lista vImprime
  
  vImprime = 'Nombre: '[C0]
  vImprime = atProducto(cNombreProducto)[C2]
  Lista vImprime

  vImprime = 'Método de costeo: '[C0]
  Si atProducto(cMetodoCosteo) = 4
    vImprime = 'UEPS'[C2]
  Sino
    vImprime = 'PEPS'[C2]
  Finsi
  Lista vImprime

  SaltaLin

  Si pTipoReporte // Si el reporte es en importes
    // Verifica si el producto tiene errores en costos
    Si atProducto(cErrorCosto)
      vImprime = 'Error en costos:'[C0]
      Escoge atProducto(cErrorCosto)
        Caso 1
          vImprime = '*** Captura en desorden de entradas'[C2]
        FinCaso
        Caso 2
          vImprime = '*** Captura en desorden de salidas'[C2]
        FinCaso
        Caso 3
          vImprime = '*** Existencias negativas'[C2]
        FinCaso
        Caso 4
          vImprime = '*** Series huérfanas'[C2]
        FinCaso
        Caso 5
          vImprime = '*** Series sin costo'[C2]
        FinCaso
      FinEscoge
      lFechaEditada = fFormateaFecha(atProducto(cFechaErrorCosto); gIdioma)
      vImprime = @Col(vImprime;2) & ' a partir del ' & @Col(lFechaEditada;0)[C2]
      Lista vImprime
      vImprime = ' '[C0]      
      vImprime = '*** Se recomienda ejecutar el proceso "Recosteo" para éste producto'[C2]
      Lista vImprime
      SaltaLin
    FinSi
  FinSi

  NEGRITAS FALSE

  // Regresa las columnas a su ancho original    
  //Columnas 24;1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,0.45,1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,0	
  //N.C.224 		      1	   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22    
  Columnas 25;1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.45,1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,0.45	  
FinFunc


// *****************************************************************************
//  fImprimeMarcaHuerfanos
//
//	Esta función imprime una marca de inicio de los movimientos huérfanos,
//  motivado por el manejo de existencias negativas.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeMarcaHuerfanos()

  Columnas 24;9.11,0,0,0,0,0,0,0,0,0,0,0.45,9.11,0,0,0,0,0,0,0,0,0,0
  Texto C12;'*** Salidas sin capa ***'
  Imprime
  //N.C.224
  //    				      1	   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22    
  Columnas 25;1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.45,1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.00 
	
FinFunc


// *****************************************************************************
//  fImprimeMovimiento
//
//	Esta función imprime los datos del movimiento.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeMovimiento(atMovimiento: Tabla; aCantidad; aImprime)

  // Si el movimiento es de entrada
  Si atMovimiento(cAfectaExistencia) = 1
    // Si los datos de entrada están llenos, imprime el renglón y limpia el buffer
    Si @Col(aImprime;0) != ' ' 
      Lista aImprime
      aImprime = ' '[C0..C23]
    FinSi
    fGuardaMovimiento(atMovimiento; aCantidad; &aImprime)
  Sino // El movimiento es de salida    
    // Si los datos de salida están llenos, imprime el renglón y limpia el buffer
    Si @Col(aImprime;12) != ' ' 
      Lista aImprime
      aImprime = ' '[C0..C23]
    FinSi
    fGuardaMovimiento(atMovimiento; aCantidad; &aImprime)
  FinSi  
FinFunc


// *****************************************************************************
//  fImprimeUltimoRenglon
//
//	Esta función imprime el ultimo renglón de movimentos pares, si es que no 
//  ha sido impreso
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeUltimoRenglon(aImprime)
  
  Si @Col(aImprime;0) != ' ' o @Col(aImprime;12) != ' ' 
    Lista aImprime
  FinSi
  aImprime = ' '[C0..C23]
FinFunc


// *****************************************************************************
//  fImprimeTotales
//
//	Esta función imprime los totales por capas.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeTotales(aTotal)
Local vImprime

  vImprime = ' '[C0..C23]
	Texto C22;'@L{22}'
	Imprime
  Si pTipoReporte
    vImprime = '"Saldo:'[C18]
  Sino
    vImprime = '"Existencia:'[C18]
  FinSi
  vImprime = @Col(aTotal;0)[C22]
  Lista vImprime
  Saltalin

FinFunc


// *****************************************************************************
//  fProcesaSalidasHuerfanas
//
//	Esta función lee y procesa los movimientos de salida que no tienen una capa
//  asociada (debido al manejo de existencias negativas), pero que sin embargo
//  pertenecen a productos costeados por UEPS o PEPS.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fProcesaSalidasHuerfanas(atProducto: Tabla)
Local lFecha, lCostoExistencia, lUnidadesCapa, lImprime, lAlMenosUno

  lImprime = ' '[C0..C23]
  lAlMenosUno = 0
  // Busca movimientos de salida en el rango de fechas
  lFecha = pFechaInicial
  Mientras lFecha <= pFechaFinal    
    // Todos los movimientos de salida en una misma fecha
    Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lFecha & ':2']; tMovimiento->Encontro; tMovimiento.Busca Siguiente[3] ]
      // Discrimina los movimientos sin afectar
      SI tMovimiento(cAfectadoInventario) = 0
        Continua
      FinSi
      
      // Inicializa la variable que lleva el acumulado de unidades de los movimientos de capa
      lUnidadesCapa = 0
      // Busca el movimiento de capa que corresponde a la salida  
      // Puede encontrarse más de uno, pero hay que discriminar los lotes y pedimentos
      Mientras [ tMovtoCapa1.Busca[@Str(tMovimiento(cIdMovimiento);0)]; tMovtoCapa1->Encontro; tMovtoCapa1.Busca Siguiente[1] ]
        // ahora recupera la capa a partir del movimiento de capa
        tCapa.Busca[@Str(tMovtoCapa1(cIdCapa);0)]
        Si tCapa->Encontro
          // Discrimina lotes y pedimentos
          Si tCapa(cTipoCapa) != 5 // la capa no es de costeo UEPS o PEPS
            Continua
          FinSi
        FinSi
        // acumula las unidades de la capa
        lUnidadesCapa = lUnidadesCapa + tMovtoCapa1(cUnidades)        
      FinMientras

      // Si las unidades de la capa coinciden con las unidades del movimiento, entonces la salida ya fue impresa junto con su entrada
      // de otra forma, es una salida que no fue cubierta en su totalidad con las capas de entrada que existían (debido al manejo de existencias negativas)
      Si (lUnidadesCapa - tMovimiento(cUnidades)) != 0
        Si pTipoReporte // Si el reporte es en importes
          // el costo de la salida es cero
          lCostoExistencia = 0.0
        Sino
          lCostoExistencia = tMovimiento(cUnidades) - lUnidadesCapa
        FinSi
        //N.C.224
        //Cuando se da una salida que genera existencia negativa, mientras se está 
        //capturando el estatus del movimiento en cAfectadoInventario es igual a dos,
        //también este movimiento se debe reflejar en el reporte
  	    Si tMovimiento(cAfectadoInventario) = 2
    	   lImprime = '(*)' [C23]			
      	FinSi         
        
        lAlMenosUno = 1 // Al menos se imprimió una salida huérfana
        // Marca el inicio de movimientos huerfanos
        fImprimeMarcaHuerfanos()
        // Imprime el movimiento de salida
        fImprimeMovimiento(tMovimiento; lCostoExistencia; &lImprime)
        fImprimeUltimoRenglon(&lImprime)
      FinSi      
    FinMientras // tMovimiento->Encontro

    lFecha = fFechaSiguiente(lFecha)
  FinMientras // lFecha <= pFechaFinal

  Si lAlMenosUno // AL menos se imprimió una salida huérfana?
    Saltalin
  FinSi
FinFunc

// ==========================================================================================
// Nombre   :   fObtenerIdsEntradaCapa
// Descripcion: Dado un movimiento obtiene una lista de los Ids de sus capas.
// Entrada  : 	aListaIdsCapas      Regresa la lista de Ids de capas del movimiento
//              atMovimiento        Tabla de movimientos, posicionada en el registro
//                                    del movimiento de cual se van a obtener sus
//                                    capas
//              atMovimientoCapa    Tabla de los movimientos de capas
//              atCapa              Tabla de las capas
// Salida   :		
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus       Descripcion
//  17/10/2002 LAP      N.D.1316      Implementación inicial
// ==========================================================================================
DefFunc fObtenerIdsEntradaCapa(aListaIdsCapas; atMovimiento:Tabla; atMovimientoCapa:Tabla; atCapa:Tabla)

  aListaIdsCapas = ''

  // Busca el movimiento de capa que corresponde a la entrada  
  // Puede encontrarse más de uno, pero hay que discriminar los lotes y pedimentos
  Mientras[tMovtoCapa1.Busca[@Str(atMovimiento(cIdMovimiento);0)]; tMovtoCapa1->Encontro; tMovtoCapa1.Busca Siguiente[1]]

    // ahora recupera la capa a partir del movimiento de capa
    atCapa.Busca[@Str(tMovtoCapa1(cIdCapa);0)]
    Si atCapa->Encontro

      // Discrimina lotes y pedimentos
      Si atCapa(cTipoCapa) != 5 // la capa no es de costeo UEPS o PEPS
        Continua
      FinSi

      // Forma la lista de Ids de las capas involucradas y la lista de sus costos en moneda base
      Si aListaIdsCapas = ''
        aListaIdsCapas = @Str(tMovtoCapa1(cIdCapa);0)
      Sino
        aListaIdsCapas = aListaIdsCapas & ',' & @Str(tMovtoCapa1(cIdCapa);0)
      FinSi
    FinSi   
    
  FinMientras
  // Fin recorrido de los movimientos de las capas

FinFunc
// Fin función: fObtenerIdsEntradaCapa


// ==========================================================================================
// Nombre   :   fProcesaMovtosCapas
// Descripcion: 
// Entrada  : 	aTipoMovtos         Tipo de afectación de los movimientos al inventario.
//                                    1 - Entradas
//                                    2 - Salidas
//              aListaIdsCapas      Lista de los Ids de las capas, separadas por comas.
//              aAcumulado          [Por referencia] Acumulado de los costos/unidades
//                                    procesados del movimiento.
//              aAlMenosUnMovto     [Por referencia] Bandera para saber si se proceso un 
//                                    movimiento.
//                                    1 si se proceso al menos un movimiento
//                                    0 si no se proceso al menos un movimiento
//              aImprimirMovto      Bandera que indica si el movimiento procesado se 
//                                    imprime o no.
//                                    1 si se imprime el movimiento
//                                    0 no se imprime el movimiento
//              aDatosMovto         Variable que almacena los datos del movimiento que 
//                                    se va a imprimir
// Salida   :		
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus       Descripcion
//  17/10/2002 LAP      N.D.1316      Implementación inicial
// ==========================================================================================
DefFunc fProcesaMovtosCapas(aTipoMovtos; aListaIdsCapas; aAcumulado; aAlMenosUnMovto; aImprimirMovto; aDatosMovto)
Local lNumeroCapas
Local lCostoExistencia
Local lIdDocumento, lIdMonedaCliente

  aAcumulado = 0
  aAlMenosUnMovto = 0

  // Activa el indice para la busquéda de la capa
  tMovimientoCapa.Usaindice['iCapaFecha']

  // Procesa las capas
  lNumeroCapas = 0

  

  Mientras @Escoge(aListaIdsCapas; lNumeroCapas)
    // Validación de la existencia de la capa
    tCapa.Busca[@Escoge(aListaIdsCapas; lNumeroCapas)]
    Si !tCapa->Encontro
      Continua
    FinSi


    lIdCapa = @Str(tCapa(cIdCapa);0)

    // Procesa los movimientos de la capa
    Mientras[tCapaMovto.Busca[lIdCapa]; tCapaMovto->Encontro; tCapaMovto.Busca Siguiente[1]]
      // Lee el movimiento asociado al movimiento de capa
      tMovimiento2.Busca[@Str(tCapaMovto(cIdMovimiento);0)]
      Si !tMovimiento2->Encontro
        Continua
      FinSi

      // Discrimina los movimientos sin afectar
      Si tMovimiento2(cAfectadoInventario) = 0
        Continua
      FinSi
      
      // Discrimina los movimientos que no sean salidas/entradas
      Si tMovimiento2(cAfectaExistencia) != aTipoMovtos
        Continua
      FinSi     

      // Obtiene el costo o las unidades del movimiento de capa
      Si pTipoReporte = 0  // El reporte es en unidades ?
        lCostoExistencia = tCapaMovto(cUnidades)
      Sino                // El reporte es en importes
        // Calcula el costo a partir del costo de la capa multiplicado por las unidades del movimiento de capa
        lCostoExistencia = tCapaMovto(cUnidades) * tCapa(cCosto)
        
        //N.C.224
        //Si es un movimiento afectado solo en inventario y el costoexistencia está en cero,
        //(está en cero porque aún no se ha creado la capa o no ha sido afectada)
      	Si lCostoExistencia = 0 Y tMovimiento(cAfectadoInventario) = 2 
       		aDatosMovto = '(*)' [C11]			
       		lCostoExistencia = tMovimiento2(cUnidades)
      	FinSi   
        
        // Convierte el costo a la moneda del reporte. 
        //  Nota: El costo SIEMPRE está expresado en la moneda base (ID = 1)
        //! N.D.3240 lCostoExistencia = fConvierteTipoCambio(lCostoExistencia; 1; pIdMoneda; tMovimiento2(cFecha); tTipoCambio)
        // N.D.3240 Obtención del documento del movimiento
        Si tMovimiento2(cIdDocumento)
          tDocumento.Busca[@Str(tMovimiento2(cIdDocumento);0)]
        Sino 
          // Movimiento oculto
          lIdDocumento = fIdDocumentoMovtoOwner(tMovimiento2; tMovtoOwner) 
          tDocumento.Busca[@Str(lIdDocumento;0)]          
        FinSi
        // N.D.3240 Obtención de la moneda del cliente / proveedor
        tClienteProveedor.Busca[@Str(tDocumento(cIdClienteProveedor);0)]

        // N.D.3240 Id de la moneda del cliente / proveedor
        Si tClienteProveedor->Encontro
          lIdMonedaCliente = tClienteProveedor(cIdMoneda)
        Sino
          lIdMonedaCliente = tDocumento(cIdMoneda)
        FinSi

        // N.D.3240 Costo en la moneda del reporte
        lCostoExistencia = fCambiarMonedaImporteAReporte(tDocumento; tTipoCambioLib; lCostoExistencia; 1; pIdMoneda; lIdMonedaCliente)
      FinSi

      // Acumula al total
      aAcumulado = aAcumulado + lCostoExistencia
      
      // Imprime el movimiento de salida
      aAlMenosUnMovto = 1
      Si aImprimirMovto
        fImprimeMovimiento(tMovimiento2; lCostoExistencia; &aDatosMovto)
      FinSi

    FinMientras 
    // Fin recorrido de los movimientos de la capa
    lNumeroCapas = lNumeroCapas +1

  FinMientras
  // Fin recorrido de las capas

FinFunc
// Fin Función: fProcesaMovtosCapas


// *****************************************************************************
//  fProcesaProducto
//
//  Esta función obtiene los lotes y pedimentos del producto conforme al rango
//  de fechas del reporte.
//
//  Parámetros 
//
//  Salidas 
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//  17/10/2002 LAP      N.D.1316    
//                                  - fProcesaProducto
// *****************************************************************************
DefFunc fProcesaProducto(atProducto: Tabla)
Local lFecha, lImprime, lDatosProducto, lAlMenosUno, lAlMenosUnaSalida
Local lCostoExistenciaEntrada
// N.D.1316 Inicio
Local lCostoExistenciaSalida
Local lListaIdsCapa, lNumeroCapas
Local lListaCostosUnitariosCapas
// N.D.1316 Fin

  Si !pImprimirProductos // Imprimir productos sin importar si tiene o no movimientos?
    fImprimeDatosProducto(atProducto)
    lDatosProducto = 1
  Sino
    // No se han impreso los datos del producto
    lDatosProducto = 0
  FinSi

  // No se ha impreso alguna capa
  lAlMenosUno = 0
  lImprime = ' '[C0..C23]

  // Busca movimientos de entrada en el rango de fechas
  lFecha = pFechaInicial
  Mientras lFecha <= pFechaFinal    
    // Todos los movimientos de entrada en una misma fecha
    Mientras[tMovimiento.Busca[atProducto(cIdProducto) & ':' & lFecha & ':1']; tMovimiento->Encontro; tMovimiento.Busca Siguiente[3]]
      // Discrimina los movimientos sin afectar
      SI tMovimiento(cAfectadoInventario) = 0
        Continua        
      FinSi     
			
      // N.D.1316 Inicio
      // Obtiene la lista de los Ids de las capas 
      fObtenerIdsEntradaCapa(&lListaIdsCapa; tMovimiento; tMovimientoCapa; tCapa)
      
      // Procesa las unidades o importes de la capa de entrada
      fProcesaMovtosCapas(1; lListaIdsCapa; &lCostoExistenciaEntrada; 0; 0; 0)
      
      //N.C.224
      //En este momento se está capturando el movimiento, aún no se tiene la capa creada por tal 
      //motivo no aparece la afectación del movimiento en el reporte
      Si lCostoExistenciaEntrada = 0 Y tMovimiento(cAfectadoInventario) = 2
        lImprime = '(*)' [C11]			
        Si pTipoReporte = 0
          lCostoExistenciaEntrada = tMovimiento(cUnidades)       
        Sino
          lCostoExistenciaEntrada = 0.0
        FinSi	
      FinSi         
      // N.D.1316 Fin

      // Si el producto no ha sido impreso, se imprime
      Si !lDatosProducto
        fImprimeDatosProducto(atProducto)
        lDatosProducto = 1
      FinSi

      // Al menos se imprime una capa
      lAlMenosUno = 1

      // Imprime el movimiento de entrada        
      fImprimeMovimiento(tMovimiento; lCostoExistenciaEntrada; &lImprime)

      // N.D.1316 Inicio
      // *** Ahora busca las salidas asociadas a la capa de entrada ***
      // Procesa los movimientos de salida de las capas
      fProcesaMovtosCapas(2; lListaIdsCapa; &lCostoExistenciaSalida; &lAlMenosUnaSalida; 1; &lImprime)
      // N.D.1316 Fin

      // Si el último renglón no ha sido impreso, lo imprime
      fImprimeUltimoRenglon(&lImprime)

      // Si al menos se imprimio una salida
      Si lAlMenosUnaSalida
        // Imprime totales de la capa
        fImprimeTotales(lCostoExistenciaEntrada - lCostoExistenciaSalida) 
      Sino
        // Brinca un renglón para separarlo de la siguiente capa.
        Saltalin 
      FinSi

      tMovimientoCapa.Usaindice[' '] // Indice primario: cIdMovimiento+cIdCapa
    FinMientras 
    // Fin recorrido de los movimientos
    
    lFecha = fFechaSiguiente(lFecha)
  FinMientras 
  // Fin recorrido de las fechas

  // Rastrea las salidas que no tienen ninguna capa asociada 
  //  (en el caso de que se manejen existencias negativas)
  fProcesaSalidasHuerfanas(atProducto)  

  // Si al menos se imprimió una capa salta un renglón
  Si lAlMenosUno
    Saltalin 1
  FinSi

FinFunc


// *****************************************************************************
//  fVerificaParametros
//
//  Esta función verifica los parámetros pProductoInicial y pProductoFinal.
//  Si están vacíos toma el primer y último producto de la tabla.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fVerificaParametros()

  // Si el rango inicial es el primer producto, recupera el código del primero
  Si pProductoInicial = ' '
    tProducto.Busca Primero
    Si tProducto->Encontro
      pProductoInicial = tProducto(cCodigoProducto)
    FinSi
  FinSi

  // Si el rango final es el último producto, recupera el código del último
  Si pProductoFinal = ' '
    tProducto.Busca Ultimo
    Si tProducto->Encontro
      pProductoFinal = tProducto(cCodigoProducto)
    FinSi
  FinSi
FinFunc


// *****************************************************************************
// Encabezado del reporte

Encab
	Texto '@TC{255,0,0}@S{8}AdminPAQ'
	Hoja '"@TC{0,0,0}@S{8}Hoja: '
	Imprime
  // lee la moneda del reporte
  Si pTipoReporte = 1
    tMoneda.Busca[@Str(pIdMoneda;0)]
    Si tMoneda->Encontro
      Texto '@TC{0,0,0}@S{8}Moneda: ' & tMoneda(cNombreMoneda)
    FinSi
  FinSi
	Texto '"@TC{0,0,0}@S{8}Fecha: ' & fFormateaFecha(@Hoy();gIdioma)
  Imprime

	Texto '^@TC{0,0,0}@S{22}' & tEmpresa->Nombre
	Imprime

	Texto '^@TC{0,0,0}@S{16}ANALISIS DE CAPAS (UEPS Y PEPS)' // N.D.4458 - IYPZ
  Imprime
  Si pTipoReporte = 1 // Importes
  	Texto '^@TC{0,0,0}@S{16}EN IMPORTES'
  Sino // Unidades
  	Texto '^@TC{0,0,0}@S{16}EN UNIDADES'
  FinSi
	Imprime
	Texto '^@TC{0,0,0}@S{16}Del: ' & fFormateaFecha(pFechaInicial;gIdioma) & ' Al: ' & fFormateaFecha(pFechaFinal;gIdioma)
	Imprime

  // Se Revisan las clasificaciones, para recuperarlas e imprimirlas en el encabezado
  fRevisaClases(tValoresDeClasif)

  Saltalin

	NEGRITAS TRUE
	Texto '@TC{0,0,0}@L{-1}'
  Imprime

  // Modifica el ancho de las columnas
  Columnas 24;9.11,0,0,0,0,0,0,0,0,0,0,0.45,9.11,0,0,0,0,0,0,0,0,0,0,0
  Texto C0;'E N T R A D A S'
  Texto C12;'S A L I D A S'
  Imprime
	//N.C.224
	//    				      1	   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22    
	Columnas 25;1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.45,1.64,0.15,0.75,0.15,1.20,0.15,2.24,0.15,0.45,0.15,2.09,1.00  

	Texto C0;'Fecha'
	Texto C2;'Serie'
	Texto C4;'^Folio'
	Texto C6;'Concepto'
  Texto C8;'Alm'
  Texto C10;'^Entrada'
	Texto C12;'Fecha'
	Texto C14;'Serie'
	Texto C16;'^Folio'
	Texto C18;'Concepto'
  Texto C20;'Alm'
  Texto C22;'^Salida'
	Imprime

	Texto '@TC{0,0,0}@L{-1}'
	Imprime 1

	NEGRITAS FALSE
	Color @RGB(0;0;0)
	Altura 9
FinEncab


// *****************************************************************************
// Cuerpo del reporte

// Configura los decimales del reporte
fConfiguraDecimales()

// Verifica el rango de productos del reporte
fVerificaParametros()

// Obtiene los productos en el rango especificado en los parámetros del reporte
Mientras [ tProducto.Busca[pProductoInicial & '..' & pProductoFinal]; tProducto->Encontro; tProducto.Busca Siguiente[1] ]

  // Solo busca productos, descarta paquetes y servicios
  Si tProducto(cTipoProducto) != 1
    Continua
  FinSi

  // Verifica si el producto es candidato a imprimirse en función de su estado
  // tProducto(cStatusProducto) = 0 (Inactivo)
  // tProducto(cStatusProducto) = 1 (Activo)
  Si pEstadoProducto y pEstadoProducto != @Abs(tProducto(cStatusProducto) - 2)
    Continua
  FinSi

  // Verifica si el producto cumple con las clasificaciones especificadas 
  Si gNumDeClases > 0
    Si !fMiembroDeUnaClase(tProducto; gNumDeClases; gListIdDeClases; 2)
      // Discrimina el producto por no pertenecer a alguna de las clasificaciones
      Continua
    FinSi
  FinSi

  // Discrimina productos que no tengan costo UEPS o PEPS
  Si tProducto(cMetodoCosteo) = 4 o tProducto(cMetodoCosteo) = 5
    fProcesaProducto(tProducto)
  FinSi

FinMientras

//N.C.224, N.D.5585
Columnas 4;0.10,100,0.0
vImprime = '(*) Este movimiento está actualmente en captura, por tal motivo solo está afectado en existencia y no en costo' [C1]
Lista vImprime
