// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
// Kardex.rpt
// Nombre del reporte en el sistema: Kardex
//
//  Sistema: AdminPAQ v1.1
// 
//  Este reporte perteneciente al módulo de inventarios, despliega los 
//  movimientos de entrada y salida de productos. Por cada movimiento,
//  se presenta las unidades o el costo según el tipo de reporte elegido.
//
//  Consideraciones especiales:
//  Este reporte aunque está programado como uno solo, representa en realidad
//  dos reportes en el ámbito del sistema, el kardex en unidades y el kardex
//  en importes.
//  
// Elaboró:    Eduardo Pérez Figueroa
// Fecha:      20 de Junio del 2001
//
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 24/01/2002   MOFM    SC 24       Se agregó el parámetro pAlmacen y se modifi-
//                                  caron los métodos: fProcesaSinCapas y el 
//                                  cuerpo del reporte
//                                  Se le agregaron más valores a pTipoKardex.
// 15/02/2002   MOFM    SC 24       Se modifica el parámetro pAlmacen para recibir
//                                  un rango de códigos de almacén.
// 19/02/2002   RPC     ND 141      Se agregaron totales en los kárdex globales
//                                  En los kárdex por almacén fallaba el cálculo   
//                                  de la existencia y costo inicial
//                                  En los kárdex por almacén ponía los datos del 
//                                  almacén antes de los datos del producto
//                                  En los kárdex por almacén el total por 
//                                  producto debe incluir la existencia o costo
//                                  final
// 19/03/2002   CILA    SC 35       Se agrego el parametro para saber si se con-
//                                  sideran todos los movimientos, o solo los que
//                                  que estan afectados o que estan sin afectar.
// 16/05/2002   EGV     ND 390      Se modificaron las funciones:
//                                  - fProcesaPorAlmacen,
//                                  - fImprimeMovimiento,
//                                  - Cuerpo del reporte. (EGV)
// 21/06/2002   LAP     ND 585      Adición de fExistenciaProductoSinAfectar y
//                                  fCostoProductoSinAfectar para obtener las
//                                  unidades y costo de los movimientos sin
//                                  afectar. Y dependiendo de si el usuario  
//                                  desea ver todos los movimientos, los 
//                                  movimientos afectados o los movimientos sin
//                                  afectar, poder desplegar correctamente la
//                                  existencia o el costo inicial.
//                                  - Cuerpo del reporte
//                                  - fProcesaPorAlmacen
// NOTA: Temporalmente se definen las funciones fExistenciaProductoSinAfectar y
//       fCostoProductoSinAfectar y no en LibInventarios.Rpt ya que algunos
//       reportes no se pueden compilar por que se excede el límite máximo de
//       instrucciones del reporteador.
// 16/07/2002   LAP     ND 884      Al calcular el inventario inicial se deben
//                                  de considerar exclusivamente los movimientos 
//                                  del primer periodo hasta antes de la fecha
//                                  indicada ya que los movimientos a partir de 
//                                  la fecha inicial ya se consideran parte del
//                                  reporte.
//                                  - fExistenciaProductoSinAfectar
//                                  - fCostoProductoSinAfectar
// 26/07/2002   RPC     SC 150      Debido a la SC 150 todos los movtos ahora se
//                                  afectan en línea y se permiten existencias 
//                                  negativas protegiendo al costo. Los movtos 
//                                  sin afectar se consideran erroneos y se 
//                                  siguen imprimiendo con asterisco pero con 
//                                  totales separados. Esta modificación  
//                                  incluye quitar todas las modificaciones  
//                                  efectuadas la ND 585 y una parte de la SC 35
//  27/01/2003  LAP     N.D.1377    Los movimientos incompletos de detalles de
//                                  características no se deben de imprimir
//                                  - fProcesaSinCapas
//                                  - fProcesaPorAlmacen
// 08/09/2003   EGV     N.D.2410    Se modificó: fProcesaPorAlmacen. (EGV)
// 29/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
// 14/11/2005   HVA     N.D.3484    Al utilizar el filtro "Solo con Movimientos" aparecen los que tienen existencia inicial
// 23/02/2006   HVA     N.D.3868    Se duplican los costos cuando el producto tiene unidadades no convertibles.
// 27/11/2006   LAP     N.D.4355    Totalizar el Inventario Inicial al imprimir por con la opción
//                                  "Solo con Movimientos" (LAP)
//                                  - fProcesaPorAlmacen  
// 21/05/2007   JAAM    N.C.147     Esquema de adicion de unidades de compra y venta 
// 05/02/2008   JENL    N.D.5062    ERROR TARDA 6 MINUTOS AL MOMENTO DE CONVERTIR UN PEDIDO EN FACTURA 
//                                  Se modifica:
//                                  -fProcesaPorAlmacen
//                                  -Cuerpo del reporte 
// 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.
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

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

Incluye LibAdminPAQ.Rpt
Incluye LibInventarios.Rpt


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

Parametro pFechaInicial = '20020101'    // Fecha inicial del rango
Parametro pFechaFinal = '20021231'      // 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 pAlmacenInicial = ' '         // Código inicial del almacen
Parametro pAlmacenFinal = ' '           // Código final del almacén
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 pUnidad = 0                   // Unidad de medida y peso para expresar el reporte
                                        // 0 = Unidad base del producto
                                        // 1 = Unidad no equivalente del producto
                                        // 2 = Unidad equivalente (ver parámetro pIdUnidad)
                                        // 3 = Unidad de Compra
                                        // 4 = Unidad de Venta
Parametro pIdUnidad = 2                 // Id de la unidad equivalente
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 pTipoKardex = 0               // Tipo de Kardex (este parámetro es interno a AdminPAQ)
                                        // 0 = Kardex en unidades
                                        // 1 = Kardex en importes
                                        // 2 = Kardex en unidades por almacén
                                        // 3 = Kardex en importes por almacén  

// *****************************************************************************
//  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

// N.D.1377 Inicio
// Productos identificadores a fin de saber si el producto es un detalle de
//  caracteristicas o no
UsaTabla tDetalleProducto = tEmpresa['MGW10004']  // Productos
tDetalleProducto.Usaindice['']                    // Indice primario: cIdProducto
// N.D.1377 Fin

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

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

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

UsaTabla tMovtoSinAfectar = tEmpresa['MGW10010'] Alias 'MovtoSinAfectar'  // Movimientos sin afectar
tMovtoSinAfectar.Usaindice['iProductoDoctoDeAfecFecha']    // cIdProducto+cIdDocumentoDe+cAfectadoInventario+cFecha

UsaTabla tEjercicio = tEmpresa['MGW10031']        // Ejercicios
tEjercicio.Usaindice['cNumeroEjercicio']          // cNumeroEjercicio

UsaTabla tExistencia = tEmpresa['MGW10030']       // Existencia
tExistencia.Usaindice['iProdEjerAlmacenTipo']     // cIdProducto+cIdEjercicio+cIdAlmacen+cTipoExistencia

UsaTabla tCostoHistorico = tEmpresa['MGW10017']   // Costo histórico
tCostoHistorico.Usaindice['iProdAlmacenFecha']    // cIdProducto+cIdAlmacen+cFechaCostoH+cTipoCosto

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

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

UsaTabla tUnidad = tEmpresa['MGW10026']           // Unidades de peso y medida
tUnidad.Usaindice['']                             // Indice primario: cIdUnidad

UsaTabla tEquivalencia = tEmpresa['MGW10027']     // Equivalencia de unidades de peso y medida
tEquivalencia.Usaindice['']                       // Indice primario: cIdUnidad1+cIdUnidad2

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

UsaTabla tAlmacenRecorrido = tEmpresa['MGW10003'] Alias 'AlmacenRecorrido' //Almacenes
tAlmacenRecorrido.Usaindice['cCodigoAlmacen']     // Indice primario: cIdAlmacen

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

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
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) = 25 caracteres
// C8 (Almacen) = 15 caracteres
// C10 (Entradas) = 15 caracteres
// C12 (Salidas) = 15 caracteres
// C14 (Existencia/Costo Total) = 15 caracteres						    10     11   12   13
//N.C.224
Columnas 16;1.64,0.15,0.75,0.15,1.20,0.15,3.74,0.15,2.24,0.15,2.24,1.24,2.24,1.24,2.24,1.24 

Usaletra 'Arial'
Altura 9
[C10,C12,C14].Coma
[C2,C4].Decimales 0
[C2,C4].Blanco ''


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

gIdioma = 0                       // Idioma del reporte
                                  // 0 = Español
                                  // 1 = Inglés
// Las siguientes variables se utilizan en el cuerpo principal del reporte
gPeriodo = 0                      // Numero de período que corresponde a la fecha de inicio del reporte
gIdEjercicio = 0                  // ID del ejercicio que contiene la fecha de inicio del reporte
gUnidad = pUnidad                 // Almacenamiento del parámetro pUnidad
gIdUnidad = pIdUnidad             // Almacenamiento del parámetro pIdUnidad
gDescUnidad = ''                  // Descripción de la unidad de medida o peso
gInventarioInicial = 0            // Inventario final
gDatosProducto = 0                // Bandera que indica si los datos del producto ya fueron impresos
gMascarillaProducto = ''          // Mascarilla para el código del producto
gTotalEntradasAlmacen = 0.0       // Total de entradas del producto en un almacén
gTotalSalidasAlmacen = 0.0        // Total de salidas del producto en un almacén
gTotalEntradasProducto = 0.0      // Total de entradas del producto
gTotalSalidasProducto = 0.0       // Total de salidas del producto
gTotalEntradas = 0.0              // Total de entradas de todos los productos en todos los almacenes
gTotalSalidas = 0.0               // Total de salidas de todos los productos en todos los almacenes
gTotal = 0.0                      // Total de existencia o costo total de todos los productos
gInventarioInicialAlmacen = 0     // Inventario incial de una Almacén en específico.
// RPC - SC 150 Nuevas variables globales para totales sin afectar
gTotalEntradasProdSinAfectar = 0  // Total de entradas sin afectar del producto 
gTotalSalidasProdSinAfectar = 0   // Total de salidas sin afectar del producto   
gTotalEntradasAlmSinAfectar = 0   // Total de entradas sin afectar del almacén  
gTotalSalidasAlmSinAfectar = 0    // Total de salidas sin afectar del almacén  
gTotalEntradasSinAfectar = 0      // Total de entradas sin afectar 
gTotalSalidasAfectar = 0          // Total de salidas sin afectar 
// FIN RPC - SC 150 


// *****************************************************************************
//  fConfiguraDecimales
//
//  Configura el número de decimales de las columnas de importes, basado en
//  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 pTipoKardex = 1 o pTipoKardex = 3 // Si el kardex es en importes
      [C10,C12,C14].Decimales tParametros(cDecimalesCostos)
    Sino // entonces el kardex es en unidades
      [C10,C12,C14].Decimales tParametros(cDecimalesUnidades)
    FinSi
    gMascarillaProducto = tParametros(cMascarillaProducto)  // mascarilla para el código del producto
  Sino // Si no encontró el registro de la empresa
    [C10,C12,C14].Decimales 2
  FinSi
FinFunc


// *****************************************************************************
//  fImprimeDatosProducto
//
//  Esta función imprime los datos del producto (código, nombre, método de 
//  costeo y unidad de medida y peso)
//
//  Parámetros 
//
//  Salidas 
//
//  Historia de Revisiones
// Fecha       Nombre   IDLotus                     Descripcion
// 26/07/2002  RPC      SC 150     Incluir la detección y manejo de los errores
//                                 de existencias negativas y movtos sin afectar
// *****************************************************************************
DefFunc fImprimeDatosProducto(atProducto: Tabla)
Local vImprime, vImprime2, vImprime3, lCodigoEditado, lFechaEditada
Local lFechaSinAfectar, lExistenciaCongelada

  // Redefine el ancho de las columnas
  // C0  11 caracteres
  // C1 100 caracteres
  Columnas 16; 2.99,14.94,0.15
  
  vImprime = ' '[C0..C15]

  NEGRITAS TRUE

  vImprime = 'Producto: '[C0]
  lCodigoEditado = fMascarilla(atProducto(cCodigoProducto); gMascarillaProducto)
  vImprime = @Col(lCodigoEditado;0)[C1]
  Lista vImprime
  
  vImprime = 'Nombre: '[C0]
  vImprime = atProducto(cNombreProducto)[C1]
  Lista vImprime
  
  vImprime = 'Método de costeo: '[C0]
  Escoge atProducto(cMetodoCosteo)
    Caso 1
      vImprime = 'Costo Promedio'[C1]
    FinCaso
    Caso 2
      vImprime = 'Costo Promedio por Almacén'[C1]
    FinCaso
    Caso 3
      vImprime = 'Ultimo Costo'[C1]
    FinCaso
    Caso 4
      vImprime = 'UEPS'[C1]
    FinCaso
    Caso 5
      vImprime = 'PEPS'[C1]
    FinCaso
    Caso 6
      vImprime = 'Costo Específico'[C1]
    FinCaso
    Caso 7
      vImprime = 'Costo Estándar'[C1]
    FinCaso
  FinEscoge
  Lista vImprime

  // Imprime unidad de medida y peso
  Si pTipoKardex = 0 o pTipoKardex = 2 // Solo si el kardex es en unidades
    fVerificaUnidad(tProducto)
    Escoge pUnidad
      Caso 0 // Unidad base
        tUnidad.Busca[@Str(atProducto(cIdUnidadBase);0)]      
      FinCaso
      Caso 1 // Unidad no equivalente
        tUnidad.Busca[@Str(atProducto(cIdUnidadNoConvertible);0)]        
      FinCaso
      Caso 2 // Unidad equivalente
        tEquivalencia.Busca[atProducto(cIdUnidadBase) & ':' & pIdUnidad]
        Si tEquivalencia->Encontro // Si encontró una equivalencia con la unidad base
          tUnidad.Busca[@Str(pIdUnidad;0)] // Busca la unidad equivalente
        Sino // Si no encontró la unidad equialente, Busca la unidad base
          tUnidad.Busca[@Str(atProducto(cIdUnidadBase);0)]
        FinSi
      FInCaso
    FinEscoge
    Si tUnidad->Encontro y tUnidad(cIdUnidad) != 0 // Encontró el registro de la unidad de medida y peso
      // Guarda la descripción de la unidad en una variable global
      // Así se evita tener que leerla nuevamente al desplegar los totales
      gDescUnidad = tUnidad(cDespliegue) 
      Si gDescUnidad != ''
        vImprime = 'Unidad:'[C0]
        vImprime = @Col(gDescUnidad;0)[C1]
        Lista vImprime
      FinSi
    Sino
      gDescUnidad = ''
    FinSi
  FinSi  // Si el kardex es en unidades

  // RPC - SC 150 Verificar si el producto tiene algún error y sí es así 
  // desplegar el error.
  vImprime = ''

  // Verificar si hay existencias congeladas
  lExistenciaCongelada = fVerificarExistenciaCongelada(atProducto(cIdProducto); 0; tParametros(cIdEjercicioActual); tExistencia)

  // Si no hay existencias congeladas verificar si hay movimientos sin afectar.
  // Cuando hay existencias congeladas no se revisan movimientos sin afectar 
  // porque pueden deberse a dicha existencia congelada
  Si !lExistenciaCongelada
    // Verificar si hay movimientos sin afectar y en que fecha
    lFechaSinAfectar = fVerificarMovtosSinAfectar(atProducto(cIdProducto); tMovtoSinAfectar; tMovtoOwner; tDocumento)
  SiNo  
    vImprime = 'Advertencia:'[C0]
    vImprime =  '*** En proceso de levantamiento de inventario físico'[C1]
    vImprime2 = '*** Se recomienda aplicar el inventario físico'[C1]
    Lista vImprime
    Lista vImprime2
    lFechaSinAfectar = ''
  FinSi

  // Si hay error de costos y no hay movtos sin afectar O
  // el error de costos ocurrió antes de los movtos sin afectar
  // entonces se despliega el error de costos
  Si ( atProducto(cErrorCosto) Y !lFechaSinAfectar) O ( lFechaSinAfectar Y atProducto(cErrorCosto) Y atProducto(cFechaErrorCosto) < lFechaSinAfectar )
    vImprime = 'Error en costos:'[C0]
    Escoge atProducto(cErrorCosto) 
      Caso 1
        vImprime =  '*** Captura en desorden de entradas'[C1]
        vImprime2 = '*** Se recomienda ejecutar el proceso "Recosteo" para éste producto'[C1]
        vImprime3 = ''
      FinCaso
      Caso 2
        vImprime =  '*** Captura en desorden de salidas'[C1]
        vImprime2 = '*** Se recomienda ejecutar el proceso "Recosteo" para éste producto'[C1]
        vImprime3 = ''
      FinCaso
      Caso 3
        vImprime =  '*** Existencias negativas'[C1]
        vImprime2 = '*** Se recomienda registrar las entradas necesarias'[C1]
        vImprime3 = '*** y ejecutar el proceso "Recosteo" para éste producto'[C1]
      FinCaso
      Caso 4
        vImprime =  '*** Series sin movimiento de entrada'[C1]
        vImprime2 = '*** Se recomienda registrar la entrada de las series pendientes'[C1]
        vImprime3 = '*** y ejecutar el proceso "Recosteo" para éste producto'[C1]
      FinCaso
      Caso 5
        vImprime =  '*** Series sin costo'[C1]
        vImprime2 = '*** Se recomienda ejecutar el proceso "Recosteo" para éste producto'[C1]
        vImprime3 = ''
      FinCaso
    FinEscoge
    lFechaEditada = fFormateaFecha(atProducto(cFechaErrorCosto); gIdioma)
    vImprime = @Col(vImprime;1) & ' a partir del ' & @Col(lFechaEditada;0)[C1]
    Lista vImprime
    Lista vImprime2
    Si vImprime3 
      Lista vImprime3
    FinSi
  FinSi  // Si hay error de costos

  // Si hay movtos sin afectar y no hay errores de costos O
  // los movtos sin afectar ocurrieron antes del error de costos
  // entonces se despliega el error de movtos sin afectar
  Si ( lFechaSinAfectar Y !atProducto(cErrorCosto) ) O ( lFechaSinAfectar Y atProducto(cErrorCosto) Y lFechaSinAfectar <= atProducto(cFechaErrorCosto) )
    vImprime = 'Error en costos:'[C0]
    vImprime = '*** Movimientos sin afectar'[C1]
    lFechaEditada = fFormateaFecha(lFechaSinAfectar; gIdioma)
    vImprime = @Col(vImprime;1) & ' a partir del ' & @Col(lFechaEditada;0)[C1]
    vImprime2 = '*** Se recomienda consultar el reporte "Movimientos sin Afectar"'[C1]
    vImprime3 = '*** y ejecutar el proceso "Recosteo" para éste producto'[C1]
    Lista vImprime
    Lista vImprime2
    Lista vImprime3
  FinSi  // Hay error de movimientos sin afectar
  // FIN RPC - SC 150

  SaltaLin
  NEGRITAS FALSE

  // Regresa las columnas a su ancho original    
  //N.C.224	
	Columnas 16;1.64,0.15,0.75,0.15,1.20,0.15,3.74,0.15,2.24,0.15,2.24,1.24,2.24,1.24,2.24,1.24  

  // Modifica la variable global que indica que los datos del producto ya fueron impresos
  gDatosProducto = 1
FinFunc

// *****************************************************************************
//  fImprimeDatosAlmacen
//
//  Esta función imprime los datos del almacén
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeDatosAlmacen( )
  Local lIdAlmacen

  lIdAlmacen = tAlmacenRecorrido(cIdAlmacen)  
  Si lIdAlmacen != 0
    Imprime  
    //Solo si es el primer producto del alamacen y no es global
    Texto 'Almacén : '& fMascarilla(tAlmacenRecorrido(cCodigoAlmacen); tParametros(cMascarillaAlmacen))
    Imprime
    Texto 'Nombre  : '& tAlmacenRecorrido(cNombreAlmacen)
    Imprime 2
  FinSi
FinFunc


// *****************************************************************************
//  fImprimeInventarioInicial
//
//  Esta función imprime los datos del inventario inicial del reporte.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeInventarioInicial(aInventarioInicial)
Local vImprime

  vImprime = ' '[C0..C15]
  vImprime = '^Inventario Inicial:'[C6]
  vImprime = @Col(aInventarioInicial;0)[C14]
  Lista vImprime
FinFunc


// *****************************************************************************
//  fImprimeMovimiento
//
//  Esta función imprime los datos de cada movimiento de entrada o salida
//  que se incluye en el reporte.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 19/03/2002   CILA    SC 35       Se agrego a la fecha del movimiento el * si
//                                  si este no esta afectado.
// 13/05/2002   EGV     ND 390      Cuando se imprime la existencia, ésta se
//                                  hace en base al atributo global
//                                  gInventarioInicialAlmacen y no en base al
//                                  atributo gInventarioInicial.
// 26/07/20002  RPC     SC 150      No sumar los movimientos sin afectar a los
//                                  totales
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeMovimiento(atProducto: Tabla; atMovimiento: Tabla; aCostoExistencia)
Local vImprime, lFechaEditada, lIdDocumento

  // FBCS antes de continuar verifica que el docto no este cancelado
  // 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
    Si tDocumento(cCancelado) = 1   // Esta cancelado??? 
      Retorna                     // No se imprime
    Finsi
  Finsi
  // Fin FBCS 

  // Antes de imprimir el movimento, verifica si ya se imprimieron los datos del producto
  Si !gDatosProducto // Si no se han impreso
    // Imprime los datos del producto
    fImprimeDatosProducto(atProducto)
    // y el inventario inicial
    fImprimeInventarioInicial(gInventarioInicial)
  FinSi

  vImprime = ' '[C0..C15]

  // Fecha del movimiento
  lFechaEditada = fFormateaFecha(atMovimiento(cFecha); gIdioma)
  // CILA - SC 35
  Si atMovimiento(cAfectadoInventario) = 0
    lFechaEditada = '*' & lFechaEditada
  SiNo
    lFechaEditada = ' ' & lFechaEditada
  FinSi 
  // Fin CILA - SC 35
  vImprime = lFechaEditada[C0]

  Si tDocumento->Encontro
    // Serie
    vImprime = tDocumento(cSerieDocumento)[C2]
    // Folio
    vImprime = tDocumento(cFolio)[C4]
    // lee el concepto del documento
    tConcepto.Busca[@Str(tDocumento(cIdConceptoDocumento);0)]
    Si tConcepto->Encontro
      vImprime = tConcepto(cNombreConcepto)[C6]
    FinSi
  FinSi

  // Almacen
  tAlmacen.Busca[@Str(atMovimiento(cIdAlmacen);0)]
  Si tAlmacen->Encontro
    vImprime = tAlmacen(cNombreAlmacen)[C8]
  FinSI

  Si atMovimiento(cAfectaExistencia) = 1 // Entradas
    vImprime = @Col(aCostoExistencia;0)[C10]
    // RPC - SC 150 Si el movimiento esta afectado sumarlo a los totales
    //N.C.224 
    //Se deben considerar las unidades que afectaron el inventario 
    //aunque todavía no se afecte el costo, esto sucede cuando todavía se tienen 
    //movimientos en captura.
    Si atMovimiento(cAfectadoInventario) = 1 o atMovimiento(cAfectadoInventario) = 2
      // acumula en el total de entradas del producto en el almacén
      gTotalEntradasAlmacen = gTotalEntradasAlmacen + aCostoExistencia 
      // acumula en el total de entradas del producto
      gTotalEntradasProducto = gTotalEntradasProducto + aCostoExistencia
      //N.C.224 Debe marcar con una leyenda el movimiento que está siendo capturado en el momento
      vImprime = '' [C11]
      Si atMovimiento(cAfectadoInventario) = 2
      	vImprime = '(*)' [C11]
      FinSi	
    SiNo  //Si el movto no esta afectado sumarlo a los totales sin afectar
      //Acumula en el total de entradas sin afectar del producto en el almacén
      gTotalEntradasAlmSinAfectar = gTotalEntradasAlmSinAfectar + aCostoExistencia 
      //Acumula en el total de entradas sin afectar del producto
      gTotalEntradasProdSinAfectar = gTotalEntradasProdSinAfectar + aCostoExistencia 
    FinSi  // Si el movimiento esta afectado
  Sino // Salidas
    vImprime = @Col(aCostoExistencia;0)[C12]
    //RPC - SC 150 Si el movimiento esta afectado sumarlo a los totales
    //N.C.224
    Si atMovimiento(cAfectadoInventario) = 1 o atMovimiento(cAfectadoInventario) = 2
      // acumula en el total de salidas del producto en el almacén
      gTotalSalidasAlmacen = gTotalSalidasAlmacen + aCostoExistencia
      // acumula en el total de salidas del producto
      gTotalSalidasProducto = gTotalSalidasProducto + aCostoExistencia 
      //N.C.224 Debe marcar con una leyenda el movimiento que está siendo capturado en el momento
      vImprime = '' [C11]
      Si atMovimiento(cAfectadoInventario) = 2
				vImprime = '(*)' [C15]
      FinSi	
    Sino  // Si el movto no esta afectado sumarlo a los totales sin afectar
      // acumula en el total de salidas sin afectar del producto en el almacén
      gTotalSalidasAlmSinAfectar = gTotalSalidasAlmSinAfectar + aCostoExistencia 
      // acumula en el total de salidas sin afectar del producto
      gTotalSalidasProdSinAfectar = gTotalSalidasProdSinAfectar + aCostoExistencia 
    FinSi  // Si el movimiento esta afectado
  FinSi  // Si el movimiento es entrada o salida
  // FIN RPC - SC 150

  // Total
  Si pTipoKardex = 0 o pTipoKardex = 1  // Si es kárdex global
    vImprime = @Col(gInventarioInicialAlmacen;0)+@Col(gTotalEntradasProducto;0)-@Col(gTotalSalidasProducto;0)[C14]
  SiNo  // Si es kárdex por almacén
    vImprime = @Col(gInventarioInicialAlmacen;0)+@Col(gTotalEntradasAlmacen;0)-@Col(gTotalSalidasAlmacen;0)[C14]
  FinSi

  // RPC - SC 150 si el movimiento no esta afectado imprimirlo en itálica
  Si atMovimiento(cAfectadoInventario) = 0
//    Italico True 
    Lista vImprime
//    Italico False 
  SiNo
    Lista vImprime
  FinSi
  // FIN RPC - SC 150
FinFunc

// *****************************************************************************
//  fImprimeTotales
//
//  Esta función imprime los totales por producto.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeTotales(aEntradas; aSalidas; aTotal; aDescUnidad; aMensaje)
Local vImprime, lMensajeSinAfectar

  // RPC - SC 150 Si se despliega el total sin afectar cambia el mensaje
  Si aMensaje 
    lMensajeSinAfectar = ''
  SiNo
    lMensajeSinAfectar = ' Sin Afectar'
  FinSi
  // FIN RPC - SC 150 

  // Si el kardex es global
  Si pTipoKardex = 0 o ptipoKardex = 1
     Texto C10;'@L{10}'
   Texto C12;'@L{12}'
   // Texto C14;'@L{14}'
    Imprime
 
    vImprime = ' '[C0..C15]
    Si (pTipoKardex = 0 o pTipoKardex = 2) y aDescUnidad != '' // Si el Kardex es en unidades y la descripción de la unidad no está vacía
      vImprime = '^Total' & lMensajeSinAfectar & ' en ' & @Col(aDescUnidad;0) & ':'[C6] // imprime la descripción de la unidad
    Sino
      vImprime = '^Total' & lMensajeSinAfectar & ':'[C6]
    FinSi
    vImprime = @Col(aEntradas;0)[C10]
    vImprime = @Col(aSalidas;0)[C12]
    // vImprime = @Col(aTotal;0)[C14]
    Lista vImprime
    // Saltalin 2
  Sino
    vSubraya = '=================='[C10,C12]
    Imprime vSubraya
    vImprime = ' '[C0..C15]
    vImprime = '^Total' & lMensajeSinAfectar & ' del Producto:'[C6] // imprime la descripción de la unidad
    vImprime = @Col(aEntradas;0)[C10]
    vImprime = @Col(aSalidas;0)[C12]
    vImprime = @Col(aTotal;0)[C14]
    Lista vImprime
    // Saltalin 2
  FinSi  

FinFunc

// *****************************************************************************
//  fImprimeTotalesPorAlmacen
//
//  Esta función imprime los totales por almacen
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeTotalesPorAlmacen(aEntradas; aSalidas; aMensaje)
Local vImprime, lMensajeSinAfectar

  // RPC - SC 150 Si se despliega el total sin afectar cambia el mensaje
  Si aMensaje 
    lMensajeSinAfectar = ''
  SiNo
    lMensajeSinAfectar = ' Sin Afectar'
  FinSi
  // FIN RPC - SC 150 

  Texto C10;'@L{10}'
  Texto C12;'@L{12}'
  Imprime
  
  vImprime = ' '[C0..C15]
  vImprime = '^Total' & lMensajeSinAfectar & ' del Almacén :'[C6]

  vImprime = @Col(aEntradas;0)[C10]
  vImprime = @Col(aSalidas;0)[C12]
  // vImprime = @Col(aTotal;0)[C14]
  Lista vImprime
  // Saltalin 1
FinFunc

// *****************************************************************************
//  fImprimeTotalesGenerales
//
//  Esta función imprime los totales generales cuando se trata de los reportes
// por almacén
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeTotalesGenerales(aEntradas; aSalidas; aTotal; aMensaje)
Local vImprime, lMensajeSinAfectar

  // RPC - SC 150 Si se despliega el total sin afectar cambia el mensaje
  Si aMensaje 
    lMensajeSinAfectar = ''
  SiNo
    lMensajeSinAfectar = ' Sin Afectar'
  FinSi
  // FIN RPC - SC 150 

  vSubraya = '=================='[C10,C12]
  Imprime vSubraya
  vImprime = ' '[C0..C15]
  vImprime = '^Total General' & lMensajeSinAfectar & ':'[C6]
  vImprime = @Col(aEntradas;0)[C10]
  vImprime = @Col(aSalidas;0)[C12]
  vImprime = @Col(aTotal;0)[C14]
  Lista vImprime
  // Saltalin 2
FinFunc

// *****************************************************************************
//  fProcesaSinCapas
//
//  Esta función lee y procesa los movimientos de entrada y salida cuando el
//  método de costeo es diferente de UEPS o PEPS, es decir, sin capas.  Sólo 
// aplica para reportes globales
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 24/01/2002   MOFM    SC 24       La búsqueda sobre tMovimiento  cambia depen-
//                                  diendo del almacén seleccionado.               
// 15/02/2002   MOFM    SC 24       Se modifica para realizar la búsqueda en base
//                                  al rango de almacenes
// 19/03/2002   CILA    SC 35       Se modifica para mostrar todos los movimientos 
//                                  solo los movimientos afectado o solo los 
//                                  movimientos sin afectar.   
// 26/07/20002  RPC     SC 150      Discriminar todos los movtos sin afectar
//  27/01/2003  LAP     N.D.1377    Los movimientos incompletos de detalles de
//                                  características no se deben de imprimir
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fProcesaSinCapas(atProducto: Tabla)
Local lCostoExistencia, lFecha
Local lAlmacen
Local lIdDocumento, lIdMonedaCliente, lTipoCambioDocumento

  // Inicializa la Fecha de inicio del rango de fechas del reporte
  lFecha = pFechaInicial 

  // Si se obtiene el kardex en forma global 
  Si pTipoKardex = 0 o pTipoKardex = 1 
    // Recorre todas las fechas en el rango de fechas del reporte
    Mientras lFecha <= pFechaFinal
      // Busca el primer movimiento en esa fecha
      // Si encontro al menos un movimiento, sigue buscando otros movimientos en esa misma fecha
      Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[2] ]
        // Discrimina los movimientos que no son entradas ni salidas
        Si tMovimiento(cAfectaExistencia) != 1 y tMovimiento(cAfectaExistencia) != 2
          Continua
        FinSi

        // N.D.1377 Inicio
        // Discrimina movimientos incompletos de características
        // Revisa si el movimiento corresponde a un detalle de características
        Si tMovimiento(cTipoTraspaso) = 4
          // Busca el producto identificador
          tDetalleProducto.Busca[@Str(tMovimiento(cIdProducto);0)]
          Si tDetalleProducto->Encontro
  	        // Si el producto corresponde a un padre de características, entonces
            //  no hay que procesar este movimiento ya que es un movto
            //  incompleto de características
            Si tDetalleProducto(cTipoProducto) = 0
              Continua
            FinSi
          FinSi
        FinSi
        // N.D.1377 Fin

        Si pTipoKardex = 1 o pTipoKardex = 3 // Si el kardex es en importes, obtiene el costo del movimiento
          // N.D.3240 Localización de la moneda del cliente / proveedor
          lTipoCambioDocumento = 1.00
          Si tMovimiento(cIdDocumento)
            tDocumento.Busca[@Str(tMovimiento(cIdDocumento);0)]
          Sino 
            lIdDocumento = fIdDocumentoMovtoOwner(tMovimiento; tMovtoOwner) 
            tDocumento.Busca[@Str(lIdDocumento;0)]
          FinSi
          lIdMonedaCliente = 1
          Si tDocumento->Encontro
            lTipoCambioDocumento = tDocumento(cTipoCambio)
            tClienteProveedor.Busca[@Str(tDocumento(cIdClienteProveedor);0)]
            Si tClienteProveedor->Encontro
              lIdMonedaCliente = tClienteProveedor(cIdMoneda)
            Sino
              lIdMonedaCliente = tDocumento(cIdMoneda)
            FinSi
          Finsi
          //! N.D.3240 lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; pIdMoneda)
          // Costo del movimiento en moneda base
          lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; 1)
          lCostoExistencia = fCambiarMonedaImporteLib(tTipoCambioLib; lCostoExistencia; 1; pIdMoneda; lTipoCambioDocumento; tMovimiento(cFecha); lIdMonedaCliente)
        Sino // Si el kardex es en unidades
          lCostoExistencia = fUnidades(pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tEquivalencia)
        FinSi
        // Imprime el movimiento
        fImprimeMovimiento(atProducto; tMovimiento; lCostoExistencia)
      FinMientras
      // Incrementa un día a la fecha
      lFecha = fFechaSiguiente(lFecha)
    FinMientras
  FinSi
FinFunc

// *****************************************************************************
//  fProcesaPorAlmacen
//
//  Esta función lee y procesa los movimientos de entrada y salida cuando el
//  método de costeo es diferente de UEPS o PEPS, es decir, sin capas. Sólo aplica
// para reportes por almacén
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 18/02/2002   MOFM              Implementación inicial
// 19/02/2002   RPC     ND 141    Se corrige existencia y costo inicial
//                                Se corrigen impresión de datos del almacén 
//                                antes de datos del producto
// 19/03/2002   CILA    SC 35     Se modifica para mostrar todos los movimientos 
//                                solo los movimientos afectado o solo los 
//                                movimientos sin afectar.
// 16/05/2002   EGV     ND 390    Cuando se obtiene la existencia inicial del
//                                Almacén, ésta es copiada a la variable global
//                                gInventarioInicialAlmacen a fin de que los
//                                movimientos sumen o resten existencia o importe
//                                de dicha existencia inicial y no de la
//                                existencia inicial acumulada de todos los 
//                                almacenes para ese Producto. (EGV)
// 21/06/2002   LA      ND 585    Adición de fExistenciaProductoSinAfectar y
//                                fCostoProductoSinAfectar para obtener las
//                                unidades y costo de los movimientos sin
//                                afectar. Y dependiendo de si el usuario  
//                                desea ver todos los movimientos, los 
//                                movimientos afectados o los movimientos sin
//                                afectar, poder desplegar correctamente la
//                                existencia o el costo inicial.
// 26/07/20002  RPC     SC 150    Ya no se calcula la existencia y costo sin 
//                                afectar porque sólo se imprime lo afectado y 
//                                los movtos sin afectar son un error
//  27/01/2003  LAP     N.D.1377    Los movimientos incompletos de detalles de
//                                  características no se deben de imprimir
// 08/09/2003   EGV     N.D.2410  Se checa que se cumpla el filtro Imprimir 
//                                Productos: Sólo con movimientos. (EGV) 
//  05/02/2008  JENL    N.D.5062  Se cambia el indice iProductoAlmacenFechaAfec por iProductoAlmacenAfecFecha
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fProcesaPorAlmacen(atProducto: Tabla)
Local lCostoExistencia, lFecha
Local lAlmacen, lInventario
Local lAlmacenImpreso
Local lIdMonedaCliente, lIdDocumento, lTipoCambioDocumento

  // Inicializa la Fecha de inicio del rango de fechas del reporte
  lFecha = pFechaInicial
  lAlmacenImpreso = 0 

 
  Mientras [ tAlmacenRecorrido.Busca[pAlmacenInicial & '..' & pAlmacenFinal]; tAlmacenRecorrido->Encontro; tAlmacenRecorrido.Busca Siguiente[1] ]
    lAlmacen = tAlmacenRecorrido(cIdAlmacen) 
    lFecha = pFechaInicial
    lAlmacenImpreso = 0
    gTotalEntradasAlmacen = 0.0
    gTotalSalidasAlmacen = 0.0
    gInventarioInicialAlmacen = 0
    gTotalEntradasAlmSinAfectar = 0 
    gTotalSalidasAlmSinAfectar = 0

    // Establecer el índice usado por el calculo de costo y existencia inicial
    tMovimiento.Usaindice['iProductoFechaAfecta']    // cIdProducto+cFecha+cAfectaExistencia

    // N.D.585 Inicio
    // calcula el inventario inicial
    Si pTipoKardex = 2 // Kardex por almacén en unidades?
      lInventario = fExistenciaInicialProducto(atProducto(cIdProducto); lAlmacen; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
   FINSI

    Si pTipoKardex = 3 // Kardex por almacén en importes?
      lInventario = fCostoInicialProducto(tProducto(cIdProducto); lAlmacen; pFechaInicial; gIdEjercicio; gPeriodo; tProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambioLib; pIdMoneda)
    FINSI
    // N.D.585 Fin

    // Imprime los datos del almacén. Se checa que se cumpla el filtro Imprimir Productos: Todos o sólo con movimientos.
//    Si (lInventario != 0 Y pImprimirProductos = 1) O (pImprimirProductos = 0)

    Si !pImprimirProductos 
      // Imprime los datos del producto
      Si !gDatosProducto // Si no se han impreso
        // Imprime los datos del producto
        fImprimeDatosProducto(atProducto)
      FinSi
      fImprimeDatosAlmacen()  
      // y el inventario inicial
      fImprimeInventarioInicial(lInventario)
      gInventarioInicial = gInventarioInicial + lInventario
      gInventarioInicialAlmacen = lInventario
      lAlmacenImpreso = 1    
    FinSi  

    // Regresar al índice usado por el reporte 
    tMovimiento.Usaindice['iProductoAlmacenFechaAfec']    // cIdProducto+cIdAlmacen+cFecha+cAfectaExistencia //RCVG 5266
    //tMovimiento.Usaindice['iProductoAlmacenAfecFecha'] // cIdProducto+cIdAlmacen+CAFECTADOINVENTARIO+cFecha N.D.5062

    // Recorre todas las fechas en el rango de fechas del reporte
    Mientras lFecha <= pFechaFinal
      // Busca el primer movimiento en esa fecha
      // Si encontro al menos un movimiento, sigue buscando otros movimientos en esa misma fecha
      Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lAlmacen & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[3] ]
      //Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lAlmacen & ':' & '1' & ':' &  lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[4] ]//N.D.5062
        // Discrimina los movimientos que no son entradas ni salidas
        Si tMovimiento(cAfectaExistencia) != 1 y tMovimiento(cAfectaExistencia) != 2
          Continua
        FinSi

        // N.D.1377 Inicio
        // Discrimina movimientos incompletos de características
        // Revisa si el movimiento corresponde a un detalle de características
        Si tMovimiento(cTipoTraspaso) = 4
          // Busca el producto identificador
          tDetalleProducto.Busca[@Str(tMovimiento(cIdProducto);0)]
          Si tDetalleProducto->Encontro
  	        // Si el producto corresponde a un padre de características, entonces
            //  no hay que procesar este movimiento ya que es un movto
            //  incompleto de características
            Si tDetalleProducto(cTipoProducto) = 0
              Continua
            FinSi
          FinSi
        FinSi
        // N.D.1377 Fin

        Si pTipoKardex = 1 o pTipoKardex = 3 // Si el kardex es en importes, obtiene el costo del movimiento
          // N.D.3240 Localización de la moneda del cliente / proveedor
          lTipoCambioDocumento = 1.00
          Si tMovimiento(cIdDocumento)
            tDocumento.Busca[@Str(tMovimiento(cIdDocumento);0)]
          Sino 
            lIdDocumento = fIdDocumentoMovtoOwner(tMovimiento; tMovtoOwner) 
            tDocumento.Busca[@Str(lIdDocumento;0)]
          FinSi
          lIdMonedaCliente = 1
          Si tDocumento->Encontro
            lTipoCambioDocumento = tDocumento(cTipoCambio)
            tClienteProveedor.Busca[@Str(tDocumento(cIdClienteProveedor);0)]
            Si tClienteProveedor->Encontro
              lIdMonedaCliente = tClienteProveedor(cIdMoneda)
            Sino
              lIdMonedaCliente = tDocumento(cIdMoneda)
            FinSi
          Finsi
          //! N.D.3240 lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; pIdMoneda)
          lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; 1)
          lCostoExistencia = fCambiarMonedaImporteLib(tTipoCambioLib; lCostoExistencia; 1; pIdMoneda; lTipoCambioDocumento; tMovimiento(cFecha); lIdMonedaCliente)
        Sino // Si el kardex es en unidades
          lCostoExistencia = fUnidades(pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tEquivalencia)
        FinSi

        // Imprime los datos del producto
        Si !gDatosProducto // Si no se han impreso
          // Imprime los datos del producto
          fImprimeDatosProducto(atProducto)
        FinSi

        // Imprime el movimiento
        Si lAlmacenImpreso = 0
          fImprimeDatosAlmacen()  
          // y el inventario inicial
          fImprimeInventarioInicial(lInventario)
          // N.D.4355 Acumular el inventario inicial
          gInventarioInicial = gInventarioInicial + lInventario
          gInventarioInicialAlmacen = lInventario
          lAlmacenImpreso = 1
        FinSi  
        fImprimeMovimiento(atProducto; tMovimiento; lCostoExistencia)
      FinMientras
      // Incrementa un día a la fecha
      lFecha = fFechaSiguiente(lFecha)
    FinMientras
    Si lAlmacenImpreso = 1
      fImprimeTotalesPorAlmacen(gTotalEntradasAlmacen; gTotalSalidasAlmacen; True)
      Si gTotalEntradasAlmSinAfectar != 0 O gTotalSalidasAlmSinAfectar != 0
        fImprimeTotalesPorAlmacen(gTotalEntradasAlmSinAfectar; gTotalSalidasAlmSinAfectar; False)
      FinSi
      Saltalin 1
    FinSi  // Si se imprimió el almacén
  FinMientras

FinFunc



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

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 19/03/2002   CILA    SC 35     Se agregaron los textos que incluye los movtos
//                                afectados, sin afectar o todos.
// 26/07/20002  RPC     SC 150    Ya no se imprimen el texto y el asterisco de 
//                                movimientos sin afectar
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Encab
  Texto '@TC{255,0,0}@S{8}AdminPAQ'
  Hoja '"@TC{0,0,0}@S{8}Hoja: '
  Imprime
  // lee la moneda del reporte
  Si pTipoKardex = 1 o pTipoKardex = 3
    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}KARDEX'
  Imprime
  Si pTipoKardex = 0 // Kardex en unidades?
    Texto '^@TC{0,0,0}@S{16}GLOBAL EN UNIDADES'
  FinSi
  Si pTipoKardex = 1 // Kardex en importes
    Texto '^@TC{0,0,0}@S{16}GLOBAL EN IMPORTES'
  Finsi  
  Si pTipoKardex = 2 // Kardex en unidades por almacén
    Texto '^@TC{0,0,0}@S{16}DEL ALMACEN EN UNIDADES'
  FinSi
  Si pTipoKardex = 3 // Kardex en importes por almacén
    Texto '^@TC{0,0,0}@S{16}DEL ALMACEN EN IMPORTES'
  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
  // CILA - SC 35
  Texto '@TC{0,0,0}@S{10}* - Movimiento que no ha sido afectado en Inventarios'
  Imprime  
  // FIN CILA - SC 35
  Texto '@TC{0,0,0}@L{-1}'
  Imprime
  Texto C0;'Fecha'
  Texto C2;'Serie'
  Texto C4;'^Folio'
  Texto C6;'Concepto'
  Texto C8;'Almacén'
  Texto C10;'^Entradas'
  Texto C12;'^Salidas'
  Si pTipoKardex = 0 o pTipoKardex = 2 // Kardex en unidades?
    Texto C14;'^Existencia'
  Sino // Kardex en importes
    Texto C14;'^Costo Total'
  Finsi
  Imprime
  Texto '@TC{0,0,0}@L{-1}'
  Imprime 1

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


// *****************************************************************************
// Cuerpo del reporte
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 24/01/2002   MOFM    SC 24       Se cambia el índice de tMovimiento depen-
//                                  diendo del almacén seleccionado.               
// 15/02/2002   MOFM    SC 24       Se modifica para realizar la búsqueda en base
//                                  al rango de almacenes
// 19/02/2002   RPC     ND 141      Se agrega total para kárdex globales
// 13/05/2002   EGV     ND 390      Cuando se obtiene la existencia inicial del
//                                  producto, se copia el valor de
//                                  gInventarioInicial a la variable
//                                  gInventarioInicialAlmacen para que la
//                                  función fImprimeMovimiento haga los cálculos
//                                  correctamente. Además, cuando el usuario
//                                  especifica que desea imprimir todos los
//                                  almacenes, se omite por código el Almacén 0. 
// 21/06/2002   LAP     ND 585      Adición de fExistenciaProductoSinAfectar y
//                                  fCostoProductoSinAfectar para obtener las
//                                  unidades y costo de los movimientos sin
//                                  afectar. Y dependiendo de si el usuario  
//                                  desea ver todos los movimientos, los 
//                                  movimientos afectados o los movimientos sin
//                                  afectar, poder desplegar correctamente la
//                                  existencia o el costo inicial.
// 26/07/20002  RPC     SC 150      Ya no se calcula la existencia y costo sin 
//                                  afectar porque sólo se imprime lo afectado y
//                                  los movtos sin afectar son unerror
//  05/02/2008  JENL    N.D.5062  Se cambia el indice iProductoAlmacenFechaAfec por iProductoAlmacenAfecFecha
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// Inicializa valores globales para la biblioteca LibAdminPAQ.rpt
fIniFechasHistoria(tEjercicio)

// Configura los decimales del reporte
fConfiguraDecimales()

// A partir de la fecha de inicio del reporte, obtiene el ejercicio y periodo correspondiente
// esto es util para el cálculo del inventario inicial del reporte
fEjercicioPeriodo(pFechaInicial; &gPeriodo; &gIdEjercicio; tEjercicio) 

// Obtiene los productos en el rango especificado en los parámetros del reporte

// 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

// Si el rango inicial es el primer almacén, recupera el código del primero
Si pAlmacenInicial = ' '
  tAlmacenRecorrido.Busca Primero
  Si tAlmacenRecorrido->Encontro
    Si tAlmacenRecorrido(cIdAlmacen) = 0
      tAlmacenRecorrido.Saltareg[1]
    FinSi
    Si tAlmacenRecorrido->Encontro
      pAlmacenInicial = tAlmacenRecorrido(cCodigoAlmacen)
    FinSi
  FinSi
FinSi

// Si el rango final es el último almacén, recupera el código del último
Si pAlmacenFinal = ' '
  tAlmacenRecorrido.Busca Ultimo
  Si tAlmacenRecorrido->Encontro
    pAlmacenFinal = tAlmacenRecorrido(cCodigoAlmacen)
  FinSi
FinSi

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

  // Inicializa variable para impresión de los datos del producto
  gDatosProducto = 0 // No se han impreso los datos del producto

  // Inicializa variables de totales del producto
  gTotalEntradasProducto = 0.0
  gTotalSalidasProducto = 0.0
  gInventarioInicial = 0
  gTotalEntradasProdSinAfectar = 0
  gTotalSalidasProdSinAfectar = 0

  // Se pidó el Kardex en unidades? Verifica parámetro pUnidad
  //Si pTipoKardex = 0 o pTipoKardex = 2
  //  pUnidad = fVerificaUnidad(tProducto)
  //FinSi

  // Si los kárdex son generales
  Si pTipoKardex = 0 o pTipoKardex = 1
    // RPC - SC 150 Ya no se imprime existencia o costo sin afectar
    gInventarioInicial = fExistenciaInicialProducto(tProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
    Si pTipoKardex = 1 // Kardex global en importes?
      Si tProducto(cMetodoCosteo) = 7
        gInventarioInicial = gInventarioInicial * tProducto(cCostoEstandar)
      SiNo
        gInventarioInicial = fCostoInicialProducto(tProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; tProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambioLib; pIdMoneda)
      FinSi
    FinSi
    gInventarioInicialAlmacen = gInventarioInicial

    Si !pImprimirProductos // No discriminar productos sin movimientos?
      // Imprime los datos del producto
      fImprimeDatosProducto(tProducto)
        // y el inventario inicial
      fImprimeInventarioInicial(gInventarioInicial)
    FinSi
 
    tMovimiento.Usaindice['iProductoFechaAfecta']     // cIdProducto+cFecha+cAfectaExistencia
    fProcesaSinCapas(tProducto)

    // Se imprimieron los datos del producto?
    Si gDatosProducto
      // Imprime los totales por producto
      fImprimeTotales(gTotalEntradasProducto; gTotalSalidasProducto; gInventarioInicial + gTotalEntradasProducto - gTotalSalidasProducto; gDescUnidad; True)
      // Acumula en los totales globales
      gTotalEntradas = gTotalEntradas + gTotalEntradasProducto
      gTotalSalidas = gTotalSalidas + gTotalSalidasProducto
      gTotal = gTotal + gInventarioInicial + gTotalEntradasProducto - gTotalSalidasProducto
      Si gTotalEntradasProdSinAfectar != 0 O gTotalSalidasProdSinAfectar != 0 
        fImprimeTotales(gTotalEntradasProdSinAfectar; gTotalSalidasProdSinAfectar; 0; gDescUnidad; False)
        gTotalEntradasSinAfectar = gTotalEntradasSinAfectar + gTotalEntradasProdSinAfectar
        gTotalSalidasSinAfectar = gTotalSalidasSinAfectar + gTotalSalidasProdSinAfectar
      FinSi
      Saltalin 2
    FinSi

  // Si los kardex son por almacen
  Sino   
    tMovimiento.Usaindice['iProductoAlmacenFechaAfec']     // cIdProducto+cIdAlmacen+cFecha+cAfectaExistencia //RCVG 5266
    //tMovimiento.Usaindice['iProductoAlmacenAfecFecha'] // cIdProducto+cIdAlmacen+CAFECTADOINVENTARIO+cFecha N.D.5062
    
    fProcesaPorAlmacen(tProducto) 
    // Se imprimieron los datos del producto?
    Si gDatosProducto
      // Imprime los totales por producto
      fImprimeTotales(gTotalEntradasProducto; gTotalSalidasProducto; gInventarioInicial + gTotalEntradasProducto - gTotalSalidasProducto; gDescUnidad; True)
      // Acumula en los totales globales
      gTotalEntradas = gTotalEntradas + gTotalEntradasProducto
      gTotalSalidas = gTotalSalidas + gTotalSalidasProducto
      gTotal = gTotal + gInventarioInicial + gTotalEntradasProducto - gTotalSalidasProducto
      Si gTotalEntradasProdSinAfectar != 0 O gTotalSalidasProdSinAfectar != 0 
        fImprimeTotales(gTotalEntradasProdSinAfectar; gTotalSalidasProdSinAfectar ; 0; gDescUnidad; False)
        gTotalEntradasSinAfectar = gTotalEntradasSinAfectar + gTotalEntradasProdSinAfectar
        gTotalSalidasSinAfectar = gTotalSalidasSinAfectar + gTotalSalidasProdSinAfectar
      FinSi
      Saltalin 2
    FinSi
  FinSi // Si son kárdex globales o por almacén 

  // Regresa el valor original de pUnidad guardado en la variable global gUnidad
  //pUnidad = gUnidad

FinMientras

// Imprimir los totales del reporte
fImprimeTotalesGenerales(gTotalEntradas; gTotalSalidas; gTotal; True)

Si gTotalEntradasSinAfectar != 0 O gTotalSalidasSinAfectar != 0 
  fImprimeTotalesGenerales(gTotalEntradasSinAfectar; gTotalSalidasSinAfectar; ''; False)
FinSi

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