// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
//  RelEntSalExcel.rpt
//  Nombre del reporte en el sistema: Relación de entradas y salidas
//
//  Sistema: AdminPAQ v1.1
// 
//  Este reporte perteneciente al módulo de inventarios, despliega el 
//  inventario inicial, movimientos de entrada y salida, así como el 
//  inventario final de productos tanto en unidades como en importes.
//
//  Consideraciones especiales:
//  Este reporte aunque está programado como uno solo, representa en realidad
//  dos reportes en el ámbito del sistema:
//    Relación de entradas y salidas global en Excel
//    Relación de entradas y salidas por almacén en Excel
//  
//  Elaboró:    María Olivia Fernández Madinaveitia
//  Fecha:      01 de Febrero del 2002
//
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 15/02/2002   MOFM    SC 23       Se le agregaron más opciones al parámetro
//                                  pImprimirProducto y se agregó pCosto
//                                  Se modificaron los métodos fProcesaGlobal y
//                                  fProcesaPorAlmacen (MOFM)   
// 15/02/2002   MOFM                Se cambia el nombre del reporte de Relacion
//                                  de Entradas y Salidas a Inventario Actual 
// 20/02/2002   CILA    SC 35       Se agrego el parametro para saber si el reporte
//                                  incluye todos los movimientos, o solo los
//                                  movimientos afectados o solo los movimientos
//                                  sin afectar, mostrando en el encabezado del
//                                  reporte información que indica lo anterior.
// 29/04/2002   EGV     N.D.364     Se modificaron las funciones:
//                                  fProcesaGlobal y fProcesaPorAlmacen.    
// 21/06/2002   DRdA    N.D.0652    Se modificó:
//                                  - fImprimeDatosProducto.
//                                  - fImprimeProducto.
// 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. Por lo tanto
//                                  ya no se imprimen movtos sin afectar, de hoy
//                                  en adelante se afectan en línea todos los 
//                                  movimientos y los movimientos no afectados 
//                                  son erroneos. Esta modificación incluye 
//                                  quitar las modificaciones de la SC 35
// 26/07/2002   RPC     ND 955      Cuando se ejecuta el reporte con rangos de 
//                                  fechas que terminana el mismo día pero 
//                                  inician en días diferentes se producen 
//                                  diferencias en el costo final debido a que 
//                                  el cálculo del costo inicial se hace con un
//                                  día de más 
// 29/07/2002		LAP		  N.D.799		  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.
//																	- fProcesaGlobal
//																	- fProcesaPorAlmacen
// NOTA: Temporalmente se definen las funciones fExistenciaProductoSinAfectar y
//				fCostoProductoSinAfectar y no en LibInventarios.Rpt ya que este
//				reporte se va a rediseñar por parte de Arquitectura.
// 31/07/2002		LAP			N.D.956			Corrección en la obtención del inventario
//																	inicial.	
//																	- fProcesaGlobal
//																	- fProcesaPorAlmacen
// NOTA: Se quitan las modificaciones de la N.D. 799 y 956 ya que ya no aplica
//       el manejo de movimientos no afectados para el cambio de existencias
//       (N.C. 150)
// 26/12/2002   EGV     N.D.1697    Se modificaron las funciones:
//                                  - fProcesaGlobal,
//                                  - fProcesaPorAlmacen.(EGV)
// 16/05/2005   HVA     N.D.3257    Cuando se seleccionaban productos solo con existencias mostraba aun los que no tenian
// 23/02/2006   HVA     N.D.3868    Se duplican los costos cuando el producto tiene unidadades no convertibles.
//  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
//  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. 
//  03/04/2009 ELVS     N.D.5724    REPORTES DE INVENTARIO En Excel - CUANDO EL PRODUCTO ESTA EN CAPTURA
//                                  Hace falta el nombre de la columna "Error"  Rep de Diario de ventas
//                                  detallado /compras detallado,  inventario actual por alm/ global en importes.
//	01/07/2009  MAJU		N.D.4538		ERROR SE MUESTRAN CANTIDADES INCORRECTAS A PARTIR DE UN PRODUCTO QUE NO TIENE 
//  																LA MISMA UNIDAD NO EQUIVALENTE  QUE EL RESTO CUANDO SE PIDE EL REPORTE POR 
//																	UNIDAD NO EQUIVALENTE  AL GENERAR EL REPORTE INVENTARIO ACTUAL DEL ALMACEN 
//																	POR PRODUCTO (EXCEL). Se modifica: Cuerpo del reporte.
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// *****************************************************************************
// Funciones de librería

Incluye LibAdminPAQ.Rpt
Incluye LibInventarios.Rpt


// *****************************************************************************
// Nombre:			fExistenciaProductoSinAfectar
// Descripcion:	Calcula la existencia no afectada de un producto antes de una 
//							fecha
//
// Entradas:
// Salidas: 	
// Consideraciones:
//		Requiere que la tabla de movimientos use el índice iProductoDoctoDeAfecFecha
//
// Historia de Revisiones
//
// 29/07/2002		LAP		N.D.799			Implementación inicial
// *****************************************************************************
//!DEFFUNC fExistenciaProductoSinAfectar(acIdProducto; acIdAlmacen; aFecha; aUnidad; aIdUnidadBase; aIdUnidadEquivalente; atParametros: Tabla; atDocumento: Tabla; atMovimiento: Tabla; atMovtoOwner: Tabla; atEquivalencia: Tabla)
//!LOCAL lUnidad
//!LOCAL lFecha
//!LOCAL lListaDoctoDe, lDoctoModelo, lIdDocumento, lLlave
//!LOCAL lUnidadesMovto, lExistenciaSinAfectar
//!
//!  atMovimiento.Usaindice['iProductoDoctoDeAfecFecha']
//!
//!	lExistenciaSinAfectar = 0
//!
//!	SI aUnidad = 2
//!		lUnidad = aUnidad
//!		aUnidad = 0 // asume unidades base
//!	FINSI
//!
//!	lListaDoctoDe = ' 4, 5, 6, 7,18,19,20,21,32,33,34'[C0]
//!	lFecha = atParametros(cFechaCierre) 
//!	lFecha = fFechaSiguiente(lFecha)
//!	MIENTRAS lFecha < aFecha
//!		lDoctoModelo = 0
//!		MIENTRAS lDoctoModelo < 11
//!			lLlave = acIdProducto &':'&  @Escoge(lListaDoctoDe;lDoctoModelo) &':'& '0' &':'& lFecha
//!			MIENTRAS [atMovimiento.Busca[@Str(lLlave;0)]; atMovimiento->Encontro; atMovimiento.Busca Siguiente[4]]
//!				// Discrimina movimientos cuyo almacén no corresponde al solicitado
//!				SI acIdAlmacen != 0 y atMovimiento(cIdAlmacen) != acIdAlmacen
//!					CONTINUA
//!				FINSI
//!				// Discrimina los movimientos de documentos cancelados
//!				SI atMovimiento(cIdDocumento)
//!					atDocumento.Busca[@Str(atMovimiento(cIdDocumento);0)]
//!				SINO // es un movimiento oculto
//!					// Busca el ID del documento en el movimiento owner
//!					lIdDocumento = fIdDocumentoMovtoOwner(atMovimiento; atMovtoOwner) 
//!					atDocumento.Busca[@Str(lIdDocumento;0)]
//!				FINSI
//!				SI !atDocumento->Encontro
//!					CONTINUA  // Si no se encontró el docto se asume como cancelado   
//!				FINSI
//!				SI atDocumento->Encontro Y atDocumento(cCancelado) = 1   
//!					CONTINUA   // El docto esta cancelado
//!				FINSI
//!				// Recuperar las unidades del movimiento
//!				lUnidadesMovto = fUnidades(aUnidad; aIdUnidadBase; aIdUnidadEquivalente; atMovimiento; atEquivalencia)
//!				SI atMovimiento(cAfectaExistencia) = 1 // es una entrada?
//!					lExistenciaSinAfectar = lExistenciaSinAfectar + lUnidadesMovto
//!				SINO // es una salida
//!					lExistenciaSinAfectar = lExistenciaSinAfectar - lUnidadesMovto
//!				FINSI
//!			FINMIENTRAS  // Hay movimientos sin afectar del documento modelo
//!			lDoctoModelo = lDoctoModelo + 1
//!		FINMIENTRAS  // Hay documentos modelo que afectan existencias
//!		lFecha = fFechaSiguiente(lFecha)
//!	FINMIENTRAS  // Hay días que recorrer
//!
//!	SI lUnidad = 2 // Se solicitó el reporte en unidades equivalentes?
//!		lExistenciaSinAfectar = fUnidadesEquivalentes(lExistenciaSinAfectar; aIdUnidadBase; aIdUnidadEquivalente; atEquivalencia)
//!	FINSI
//!
//!	RETORNA lExistenciaSinAfectar
//!FINFUNC

// *****************************************************************************
// Nombre:			fCostoProductoSinAfectar
// Descripcion:	Calcula un aproximado del costo de los movimientos no afectados 
//								de un producto antes de una fecha
//
// Entradas:
// Salidas: 	
// Consideraciones:
//		Requiere que la tabla de movimientos use el índice iProductoDoctoDeAfecFecha
//
// Historia de Revisiones
//
// 29/07/2002		LAP		N.D.799			Implementación inicial
// *****************************************************************************
//!DEFFUNC fCostoProductoSinAfectar(acIdProducto; acIdAlmacen; aFecha; aIdMoneda; atParametros: Tabla; atDocumento: Tabla; atMovimiento: Tabla; atMovtoOwner: Tabla; atCostoHistorico: Tabla; atTipoCambio: Tabla)
//!LOCAL	lIndiceAnterior
//!LOCAL lUnidad
//!LOCAL lFecha
//!LOCAL lListaDoctoDe, lDoctoModelo, lIdDocumento
//!LOCAL lNetoMovto, lGastosMovto
//!LOCAL lNetoDocto, lGastosDocto
//!LOCAL lCostoMovto, lCostoSinAfectar
//!
//!	// Respalda el indice anterior
//!	lIndiceAnterior = atMovimiento->Indice
//!
//!  atMovimiento.Usaindice['iProductoDoctoDeAfecFecha']
//!
//!	lCostoSinAfectar = 0
//!
//!	// Formar una lista con los documentos modelo que afectan existencias
//!	lListaDoctoDe = ' 4, 5, 6, 7,18,19,20,21,32,33,34'[C0]
//!	lFecha = atParametros(cFechaCierre)
//!	lFecha = fFechaSiguiente(lFecha)
//!	MIENTRAS lFecha < aFecha
//!		lDoctoModelo = 0
//!		MIENTRAS lDoctoModelo < 11
//!			lLlave = acIdProducto &':'& @Escoge(lListaDoctoDe;lDoctoModelo) &':'& '0' &':'& lFecha
//!			MIENTRAS [atMovimiento.Busca[@Str(lLlave;0)]; atMovimiento->Encontro; atMovimiento.Busca Siguiente[4]]
//!				// Discrimina movimientos cuyo almacén no corresponde al solicitado
//!				SI acIdAlmacen != 0 y atMovimiento(cIdAlmacen) != acIdAlmacen
//!					CONTINUA
//!				FINSI
//!				// Discrimina los movimientos de documentos cancelados
//!				SI atMovimiento(cIdDocumento)
//!					atDocumento.Busca[@Str(atMovimiento(cIdDocumento);0)]
//!				SINO // es un movimiento oculto
//!					// Busca el ID del documento en el movimiento owner
//!					lIdDocumento = fIdDocumentoMovtoOwner(atMovimiento; atMovtoOwner) 
//!					atDocumento.Busca[@Str(lIdDocumento;0)]
//!				FINSI
//!				SI !atDocumento->Encontro
//!					CONTINUA  // Si no se encontró el docto se asume como cancelado   
//!				FINSI
//!				SI atDocumento->Encontro Y atDocumento(cCancelado) = 1   
//!					CONTINUA  // El docto esta cancelado
//!				FINSI
//!				SI atMovimiento(cAfectaExistencia) = 1 // es una entrada?
//!					// Calcula el neto del movimiento
//!					lNetoMovto   = atMovimiento(cNeto) - atMovimiento(cDescuento1) - atMovimiento(cDescuento2) - atMovimiento(cDescuento3) - atMovimiento(cDescuento4) - atMovimiento(cDescuento5) 
//!					// Calcular el gasto del movimiento, a través de un aregla de tres con respecto al
//!					// neto y gastos del documento
//!					lGastosDocto = atDocumento(cGasto1) + atDocumento(cGasto2) + atDocumento(cGasto3)
//!					lNetoDocto   = atDocumento(cNeto) - atDocumento(cDescuentoMov) 
//!					lGastosMovto = lNetoMovto * lGastosDocto / lNetoDocto 
//!					// Calcula el costo del movimiento incluyendo gastos sobre compra
//!					lNetoMovto   = lNetoMovto * atDocumento(cTipoCambio)	// Neto en moneda base
//!					lCostoMovto  = lNetoMovto + lGastosMovto
//!					// Convierte el costo a la moneda del reporte
//!					lCostoMovto  = fConvierteTipoCambio(lCostoMovto; 1; aIdMoneda; aFecha; atTipoCambio)
//!					lCostoSinAfectar = lCostoSinAfectar + lCostoMovto
//!				SINO  // Es un salida
//!					// Tomar como costo del movimiento el costo promedio
//!					lCostoMovto = fCostoHistorico(acIdProducto; acIdAlmacen; aFecha; 1; atCostoHistorico; atTipoCambio; aIdMoneda)
//!					lCostoMovto = lCostoMovto * atMovimiento(cUnidades)
//!					lCostoSinAfectar = lCostoSinAfectar - lCostoMovto
//!				FINSI
//!			FINMIENTRAS  // Hay movimientos sin afectar del documento modelo
//!			lDoctoModelo = lDoctoModelo + 1
//!		FINMIENTRAS  // Hay documentos modelo que afectan existencias
//!		lFecha = fFechaSiguiente(lFecha)
//!	FINMIENTRAS  // Hay días que recorrer 
//!
//!	// Restaura el indice original
//!  atMovimiento.Usaindice[lIndiceAnterior]
//!
//!	RETORNA lCostoSinAfectar
//!FINFUNC


// *****************************************************************************
//  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 del almacén inicial del rango (' ' = Todos)
Parametro pAlmacenFinal = ' '           // Código del almacén final del rango (' ' = Todos)
Parametro pImprimirProductos = 0        // Productos a imprimir:
                                        // 0 = Todos
                                        // 1 = Solo productos con movimientos 
                                        // 2 = Sólo con existencias  
                                        // 3 = Con Movimientos o existencias
// RPC - SC 150 Ahora siempre se imprimen sólo los movimientos afectados y si
// hay no afectados se consideran error
//!Parametro pAfectado = 0                 // Movimientos a imprimir
//!                                        // 0 = Todos
//!                                        // 1 = Afectados
//!                                        // 2 = Sin Afectar  
// FIN RPC - SC 150
Parametro pCosto = 0                    // Método de Costeo:
                                        // 0 = Definido por el producto
                                        // 1 = Costo Promedio (Global)
                                        // 2 = Costo Promedio (Por Almacén)
                                        // 3 = Ultimo Costo (Global)
                                        // 4 = Ultimo Costo (Por Almacén)      
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 pTipoReporte = 0              // Tipo de reporte:
                                        // 0 - Relación de Entradas y Salidas Global
                                        // 1 - Relación de Entradas y Salidas Por Almacen

// *****************************************************************************
//  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 tAlmacen = tEmpresa['MGW10003']          // Almacenes
tAlmacen.Usaindice['cCodigoAlmacen']              // cCodigoAlmacen

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

UsaTabla tMovimiento = tEmpresa['MGW10010'] Alias 'Movtos'      // 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 tTipoCambio = tEmpresa['MGW10035']       // Tipo de cambio
tTipoCambio.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 tValoresDeClasif = tEmpresa['MGW10020']
tValoresDeClasif.UsaIndice['']                    // Indice primario: cIdValorClasificacion

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


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

Columnas 25;1

Usaletra 'Arial'
Altura 9
[C6,C8,C10,C12,C14].Coma

gTieneMovtosEnCaptura = 0 //N.C.224


// *****************************************************************************
//  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 corte del reporte
gIdEjercicio = 0          // ID del ejercicio que contiene la fecha de corte del reporte
gUnidad = pUnidad         // Almacenamiento del parámetro pUnidad
gIdUnidad = pIdUnidad     // Almacenamiento del parámetro pIdUnidad
gMascarillaProducto = ''  // Mascarilla para el código del producto
gMascarillaAlmacen = ''   // Mascarilla para el código del almacén
  // Inicia acumulados por producto
gTotalInvInicial = 0.0
gTotalEntradas = 0.0
gTotalSalidas = 0.0
gTotalImporteInicial = 0.0
gTotalImporteEntradas = 0.0
gTotalImporteSalidas = 0.0   
// RPC - SC 150 Ahora se maneja un número que indica si el producto tiene error
//!gAsterisco = ' '           

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

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

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

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

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

RenActual = 1

// Pone la longitud de cada columna
Si pTipoReporte = 1
  ws.Columns(1).ColumnWidth = 1[C0]
  ws.Columns(2).ColumnWidth = 17[C0]
  ws.Columns(3).ColumnWidth = 32[C0]
  ws.Columns(4).ColumnWidth = 12[C0]
  ws.Columns(5).ColumnWidth = 15[C0]
  ws.Columns(6).ColumnWidth = 15[C0]
  ws.Columns(7).ColumnWidth = 15[C0]
  ws.Columns(8).ColumnWidth = 15[C0]
  ws.Columns(9).ColumnWidth = 15[C0]
  ws.Columns(10).ColumnWidth = 15[C0]
  ws.Columns(11).ColumnWidth = 15[C0]
  ws.Columns(12).ColumnWidth = 15[C0]
  //N.C.224
  ws.Columns(13).ColumnWidth = 5[C0]
  ws.Columns(14).ColumnWidth = 5[C0]
Sino
  ws.Columns(1).ColumnWidth = 1[C0] 
  ws.Columns(2).ColumnWidth = 12[C0]
  ws.Columns(3).ColumnWidth = 32[C0]
  ws.Columns(4).ColumnWidth = 15[C0]
  ws.Columns(5).ColumnWidth = 3[C0]
  ws.Columns(6).ColumnWidth = 15[C0]
  ws.Columns(7).ColumnWidth = 15[C0]
  ws.Columns(8).ColumnWidth = 15[C0]
  ws.Columns(9).ColumnWidth = 15[C0]
  ws.Columns(10).ColumnWidth = 15[C0]
  ws.Columns(11).ColumnWidth = 15[C0]
  ws.Columns(12).ColumnWidth = 15[C0]
  ws.Columns(13).ColumnWidth = 15[C0]
  ws.Columns(14).ColumnWidth = 5[C0]
  ws.Columns(15).ColumnWidth = 5[C0] //N.C.224
FinSi

// *****************************************************************************
//  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()
  LOCAL lDigDecimales, lDecs, lFormato

  lDigsDecimales = '0000000000'


  Si pTipoReporte = 1 
    // Busca el registro de la empresa
    tParametros.Busca Primero
    Si tParametros->Encontro // Si lo encontró
      lDecs = @SUBSTR(lDigsDecimales;1;tParametros(cDecimalesUnidades))
      lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
      ws.Columns(5).NumberFormat = lFormato[C0]
      ws.Columns(6).NumberFormat = lFormato[C0]
      ws.Columns(7).NumberFormat = lFormato[C0]
      ws.Columns(8).NumberFormat = lFormato[C0]

      lDecs = @SUBSTR(lDigsDecimales;1;tParametros(cDecimalesCostos))
      lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
      ws.Columns(9).NumberFormat = lFormato[C0]
      ws.Columns(10).NumberFormat = lFormato[C0]
      ws.Columns(11).NumberFormat = lFormato[C0]
      ws.Columns(12).NumberFormat = lFormato[C0]

      gMascarillaAlmacen = tParametros(cMascarillaAlmacen) // mascarilla para el código del almacen
      gMascarillaClientes = tParametros(cMascarillaClientes) // mascarilla para el código del cliente/proveedor
    Sino // Si no encontró el registro de la empresa
      [C7,C9,C11,C13].Decimales 2
      ws.Columns(5).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(6).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(7).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(8).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(9).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(10).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(11).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(12).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    FinSi
  Sino 
    // Busca el registro de la empresa
    tParametros.Busca Primero
    Si tParametros->Encontro // Si lo encontró
      lDecs = @SUBSTR(lDigsDecimales;1;tParametros(cDecimalesUnidades))
      lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
      ws.Columns(6).NumberFormat = lFormato[C0]
      ws.Columns(7).NumberFormat = lFormato[C0]
      ws.Columns(8).NumberFormat = lFormato[C0]
      ws.Columns(9).NumberFormat = lFormato[C0]

      lDecs = @SUBSTR(lDigsDecimales;1;tParametros(cDecimalesCostos))
      lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
      ws.Columns(10).NumberFormat = lFormato[C0]
      ws.Columns(11).NumberFormat = lFormato[C0]
      ws.Columns(12).NumberFormat = lFormato[C0]
      ws.Columns(13).NumberFormat = lFormato[C0]

//      gMascarillaAlmacen = tParametros(cMascarillaAlmacen) // mascarilla para el código del almacen
      gMascarillaClientes = tParametros(cMascarillaClientes) // mascarilla para el código del cliente/proveedor
    Sino // Si no encontró el registro de la empresa
      [C7,C9,C11,C13].Decimales 2
      ws.Columns(6).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(7).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(8).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(9).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(10).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(11).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(12).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
      ws.Columns(13).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    FinSi
  FinSi

  [C15].Decimales 2
FinFunc

// *****************************************************************************
// fCancelado  :  Verifca si el movto es de un docto cancelado, 
// salidas 1 = cancelado, 0 = no cancelado
// *****************************************************************************
Deffunc fCancelado(atMovimiento:Tabla)
  local lvalorregreso,lIdDocumento

  // 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
  lvalorregreso = 1 // cancelado en caso de no encontrar el docto.
  Si tDocumento->Encontro
    lvalorregreso =  tDocumento(cCancelado)    // Regresa el estado del campo
  Finsi

  Retorna lvalorregreso

FinFunc

// *****************************************************************************
//  fImprimeAlmacen
//
//  Esta función imprime los datos del almacén para el reporte por almacén.
//  Además configura los renglones para que aparezcan con el formato correcto.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 20/02/2002   CILA    SC 35       Se agrego al código del producto la concate-
//                                  nación del asterisco, cuando el producto tiene
//                                  movimientos sin afectar.
// 26/07/2002   RPC     SC 150      Se quito el asterísco que indicaba movtos 
//                                  sin afectar porque el error ahora se indica 
//                                  junto con los datos del producto
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeAlmacen(atAlmacen: Tabla; aInvInicial; aEntradas; aSalidas)
Local vImprime, lInvFinal, lRotacion, lPromedio, lCodigoEditado

  // Avanza de renglon
  RenActual = RenActual + 1[C0]  
  //N.D.5724 Junta la columna M y N para poner los Errores.  
  ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':L' & RenActual).Font.FontStyle = 'Negrita'[C0]    

  //N.D.5724 Junta la columna M y N para poner los Errores.
  // Pone el titulo de cada columna en EXCEL
  ws.Range('M' & RenActual & ':N' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('M' & RenActual & ':N' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]     
  ws.Range('M' & RenActual & ':N' & RenActual).Font.FontStyle = 'Negrita'[C0]      
  ws.Range('M' & RenActual & ':N' & RenActual).HorizontalAlignment = xlDerecha[C0]
  ws.Range('M' & RenActual & ':N' & RenActual).HorizontalAlignment = xlCentro[C0]
  ws.Range('N' & RenActual & ':N' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]

  vImprime = ' '[C0..C15]

// RPC - SC 150 Ahora se maneja un número que indica si el producto tiene <p align="right">error</p>
//!  // CILA - SC 35
//!  ws.Range('A' & RenActual ).Value = gAsterisco[C0]    
//!  // Fin CILA - SC 35  
// FIN RPC - SC 150

  // Codigo y nombre del almacén
  lCodigoEditado = fMascarilla(atAlmacen(cCodigoAlmacen); gMascarillaAlmacen)
  ws.Range('B' & RenActual).HorizontalAlignment = xlIzquierda[C0]
  ws.Range('B' & RenActual ).Value = @Col(lCodigoEditado;0)[C0]
  ws.Range('C' & RenActual ).Value = atAlmacen(cNombreAlmacen)[C0]
    
  vImprime = @Col(aInvInicial;0)[C6]
  vImprime = @Col(aEntradas;0)[C8]
  vImprime = @Col(aSalidas;0)[C10]
  // calcula el inventario final
  lInvFinal = aInvInicial + aEntradas - aSalidas
  vImprime = @Col(lInvFinal;0)[C12]

  ws.Range('E' & RenActual ).Value = @COL(vImprime;6)[C0]
  ws.Range('F' & RenActual ).Value = @COL(vImprime;8)[C0]
  ws.Range('G' & RenActual ).Value = @COL(vImprime;10)[C0]
  ws.Range('H' & RenActual ).Value = @COL(vImprime;12)[C0]
  
  //N.C.224 Debe marcar con una leyenda el movimiento que está siendo capturado en el momento
  Si gTieneMovtosEnCaptura = 1
  	ws.Range('N' & RenActual ).Value = '(*)'[C0]  	
  FinSi	
FinFunc


// *****************************************************************************
//  fImprimeDatosProducto
//
//  Esta función imprime los datos del producto para el reporte por Almacén.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 26/07/2002   RPC     SC 150      Se agrearon mensajes de error de existencias 
//                                  negativas, costos y movtos sin afectar
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeDatosProducto(atProducto: Tabla)
Local vImprime, vImprime2, vImprime3, lCodigoEditado
Local lFechaSinAfectar, lExistenciaCongelada

  lCodigoEditado = fMascarilla(atProducto(cCodigoProducto); gMascarillaProducto)

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
  ws.Range('B' & RenActual ).Value = 'Producto:'[C0]
  // N.D.0652 Se agregó un apostrofe al inicio del código por si viene iniciado
  // por ceros no los quite excel, sino que lo tome como una cadena y no como 
  // un número. (DRdA)
  ws.Range('C' & RenActual ).Value = @Chr(39) & @Col(lCodigoEditado;0)[C0]
  
  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
  ws.Range('B' & RenActual ).Value = 'Nombre:'[C0]
  ws.Range('C' & RenActual ).Value = @Chr(39) & atProducto(cNombreProducto)[C0]

  
  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

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
  ws.Range('B' & RenActual ).Value = @COL(vImprime;0)[C0]
  ws.Range('C' & RenActual ).Value = @COL(vImprime;1)[C0]


  // Imprime unidad de medida y peso
  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
    Si tUnidad(cIdUnidad) y tUnidad(cDespliegue) != ''
      vImprime = tUnidad(cDespliegue)[C0]
      // Avanza de renglon
      RenActual = RenActual + 1[C0]
      ws.Range('D' & RenActual ).Value = @COL(vImprime;0)[C0]
    FinSi
  FinSi

  // RPC - SC 150 Verificar si el producto tiene algún error y sí es así 
  // desplegar en la última columna el número de 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]
    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('B' & RenActual ).Value = @COL(vImprime;0)[C0] 
    ws.Range('C' & RenActual ).Value = @COL(vImprime;1)[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('C' & RenActual ).Value = @COL(vImprime2;1)[C0]
    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'[C2]
        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]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('B' & RenActual ).Value = @COL(vImprime;0)[C0] 
    ws.Range('C' & RenActual ).Value = @COL(vImprime;1)[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('C' & RenActual ).Value = @COL(vImprime2;1)[C0]

    // Avanza de renglon
    Si vImprime3 
      RenActual = RenActual + 1[C0]
      ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
      ws.Range('C' & RenActual ).Value = @COL(vImprime3;1)[C0]
    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]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('B' & RenActual ).Value = @COL(vImprime;0)[C0] 
    ws.Range('C' & RenActual ).Value = @COL(vImprime;1)[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('C' & RenActual ).Value = @COL(vImprime2;1)[C0]
 
    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('B' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('C' & RenActual ).Value = @COL(vImprime3;1)[C0]
  FinSi  // Hay error de movimientos sin afectar
  // FIN RPC - SC 150

  // Avanza de renglon
  RenActual = RenActual + 1[C0]

FinFunc


// *****************************************************************************
//  fImprimeImportes
//
//  Esta función imprime los datos del producto para el reporte global.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeImportes(atProducto: Tabla; aInvInicial; aEntradas; aSalidas)
Local vImprime, lInvFinal, lRotacion, lPromedio, lCodigoEditado

  vImprime = ' '[C0..C15]

  vImprime = @Col(aInvInicial;0)[C14]
  vImprime = @Col(aEntradas;0)[C16]
  vImprime = @Col(aSalidas;0)[C18]
  // calcula el inventario final
  lInvFinal = aInvInicial + aEntradas - aSalidas
  vImprime = @Col(lInvFinal;0)[C20]

  ws.Range('I' & RenActual ).Value = @COL(vImprime;14)[C0]
  ws.Range('J' & RenActual ).Value = @COL(vImprime;16)[C0]
  ws.Range('K' & RenActual ).Value = @COL(vImprime;18)[C0]
  ws.Range('L' & RenActual ).Value = @COL(vImprime;20)[C0]

FinFunc

// *****************************************************************************
//  fImprimeProducto
//
//  Esta función imprime los datos del producto para el reporte global.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 20/02/2002   CILA    SC 35       Se agrego al código del producto la concate-
//                                  nación del asterisco, cuando el producto tiene
//                                  movimientos sin afectar.
// 26/07/2002   RPC     SC 150      Se quito el asterísco y se sustituyó por una
//                                  columna con el número de error
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeProducto(atProducto:Tabla; aInvInicial; aEntradas; aSalidas; aImporteInicial; aImporteEntradas; aImporteSalidas)
Local vImprime, lInvFinal, lImporteFinal, lFechaSinAfectar, lExistenciaCongelada

  // Avanza de renglon
  RenActual = RenActual + 1[C0]  
  ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & RenActual & ':M' & RenActual).Font.FontStyle = 'Negrita'[C0]    
  ws.Range('N' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentro[C0]
  
  //N.D.5724 Junta la columna M y N para poner los Errores.
  // Pone el titulo de cada columna en EXCEL
  ws.Range('N' & RenActual & ':O' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('N' & RenActual & ':O' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]     
  ws.Range('N' & RenActual & ':O' & RenActual).Font.FontStyle = 'Negrita'[C0]      
  ws.Range('N' & RenActual & ':O' & RenActual).HorizontalAlignment = xlDerecha[C0]
  ws.Range('N' & RenActual & ':O' & RenActual).HorizontalAlignment = xlCentro[C0]
  ws.Range('O' & RenActual & ':O' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]


  vImprime = ' '[C0..C20]

// RPC - SC 150 No imprimir el asterísco, en su lugar usar un número que indica
// si el producto tiene error y cual es 
//!  // CILA - SC 35
//!  ws.Range('A' & RenActual ).Value = gAsterisco[C0]
//!  // Fin CILA - SC 35  
// FIN RPC - SC 150

  lCodigoEditado = fMascarilla(atProducto(cCodigoProducto); gMascarillaProducto)
  // N.D.0652 Se agregó un apostrofe al inicio del código por si viene iniciado
  // por ceros no los quite excel, sino que lo tome como una cadena y no como 
  // un número. (DRdA)
  ws.Range('B' & RenActual ).Value = @Chr(39) & @Col(lCodigoEditado;0)[C0]
  ws.Range('C' & RenActual ).Value = @Chr(39) & atProducto(cNombreProducto)[C0]
  
  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
  ws.Range('D' & RenActual ).Value = @COL(vImprime;1)[C0]

  // Imprime unidad de medida y peso
  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
    Si tUnidad(cIdUnidad) y tUnidad(cDespliegue) != ''
      vImprime = tUnidad(cDespliegue)[C0]
      ws.Range('E' & RenActual ).Value = @COL(vImprime;0)[C0]
    FinSi
  FinSi

  vImprime = @Col(aInvInicial;0)[C6]
  vImprime = @Col(aEntradas;0)[C8]
  vImprime = @Col(aSalidas;0)[C10]
  // calcula el inventario final
  lInvFinal = aInvInicial + aEntradas - aSalidas
  vImprime = @Col(lInvFinal;0)[C12]

  ws.Range('F' & RenActual ).Value = @COL(vImprime;6)[C0]
  ws.Range('G' & RenActual ).Value = @COL(vImprime;8)[C0]
  ws.Range('H' & RenActual ).Value = @COL(vImprime;10)[C0]
  ws.Range('I' & RenActual ).Value = @COL(vImprime;12)[C0]


  vImprime = @Col(aImporteInicial;0)[C14]
  vImprime = @Col(aImporteEntradas;0)[C16]
  vImprime = @Col(aImporteSalidas;0)[C18]
  // calcula el inventario final
  lImporteFinal = aImporteInicial + aImporteEntradas - aImporteSalidas
  vImprime = @Col(lImporteFinal;0)[C20]

  // RPC - SC 150 Verificar si el producto tiene algún error y sí es así 
  // desplegar en la última columna el número de error
  vImprime = ''[C22]

  // 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 = '(7)'[C22]
    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 = '(' & atProducto(cErrorCosto)& ')' [C22] 
  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 = '(6)'[C22]
  FinSi
  // FIN RPC - SC 150

  ws.Range('J' & RenActual ).Value = @COL(vImprime;14)[C0]
  ws.Range('K' & RenActual ).Value = @COL(vImprime;16)[C0]
  ws.Range('L' & RenActual ).Value = @COL(vImprime;18)[C0]
  ws.Range('M' & RenActual ).Value = @COL(vImprime;20)[C0]
  ws.Range('N' & RenActual ).Value = @Chr(39) & @COL(vImprime;22)[C0]
  //N.C.224 Debe marcar con una leyenda el movimiento que está siendo capturado en el momento
  Si gTieneMovtosEnCaptura = 1 
    vImprime = '(8)'[C22] 	
  	ws.Range('O' & RenActual ).Value = @Chr(39) & @COL(vImprime;22)[C0]
  FinSi  	
FinFunc

// *****************************************************************************
//  fImprimeTotales
//
//  Esta función imprime los totales por producto.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeTotales(aInvInicial; aEntradas; aSalidas; aImporteInicial; aImporteEntradas; aImporteSalidas)
Local vImprime, lInvFinal, lRotacion, lPromedio

  // Si el reporte es por almacén 
  Si pTipoReporte = 1 
    // Avanza de renglon
    RenActual = RenActual + 1[C0]    
    ws.Range('E' & RenActual & ':L' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
    ws.Range('E' & RenActual & ':L' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('E' & RenActual & ':L' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('E' & RenActual & ':L' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('D' & RenActual & ':L' & RenActual).Font.FontStyle = 'Negrita'[C0]

    ws.Range('D' & RenActual).Value = 'Total:'[C0]

    ws.Range('E' & RenActual).Value = @Col(aInvInicial;0)[C0]
    ws.Range('F' & RenActual).Value = @Col(aEntradas;0)[C0]
    ws.Range('G' & RenActual).Value = @Col(aSalidas;0)[C0]
    ws.Range('H' & RenActual).Value = @Col(aInvInicial;0) + @Col(aEntradas;0) - @Col(aSalidas;0)[C0]

    ws.Range('I' & RenActual).Value = @Col(aImporteInicial;0)[C0]
    ws.Range('J' & RenActual).Value = @Col(aImporteEntradas;0)[C0]
    ws.Range('K' & RenActual).Value = @Col(aImporteSalidas;0)[C0]
    ws.Range('L' & RenActual).Value = @Col(aImporteInicial;0) + @Col(aImporteEntradas;0) - @Col(aImporteSalidas;0)[C0]
  Sino   // Si el reporte es global
    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('F' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
    ws.Range('F' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('F' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('F' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('D' & RenActual & ':M' & RenActual).Font.FontStyle = 'Negrita'[C0]

    ws.Range('D' & RenActual).Value = 'Total:'[C0]

    ws.Range('F' & RenActual).Value = @Col(aInvInicial;0)[C0]
    ws.Range('G' & RenActual).Value = @Col(aEntradas;0)[C0]
    ws.Range('H' & RenActual).Value = @Col(aSalidas;0)[C0]
    ws.Range('I' & RenActual).Value = @Col(aInvInicial;0) + @Col(aEntradas;0) - @Col(aSalidas;0)[C0]

    ws.Range('J' & RenActual).Value = @Col(aImporteInicial;0)[C0]
    ws.Range('K' & RenActual).Value = @Col(aImporteEntradas;0)[C0]
    ws.Range('L' & RenActual).Value = @Col(aImporteSalidas;0)[C0]
    ws.Range('M' & RenActual).Value = @Col(aImporteInicial;0) + @Col(aImporteEntradas;0) - @Col(aImporteSalidas;0)[C0]
  FinSi 

  RenActual = RenActual + 1[C0]
FinFunc


// *****************************************************************************
//  fProcesaGlobal
//
//  Esta función procesa el reporte de stock máximo global.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 15/02/2002   MOFM    SC 23       Se le agregaron las validaciones para le manejo
//                                  de las nuevas opciones de pImprimirProducto 
//                                  y del parámetro pCosto (MOFM)   
// 20/03/2002   CILA    SC 35       Se modifica para mostrar todos los movimientos 
//                                  solo los movimientos afectado o solo los 
//                                  movimientos sin afectar.   
//                                  Se agrego la inicialización de la variable global
//                                  gAsterisco para imprimir en el producto que
//                                  tiene movimientos pendientes de afectar.
// 19/04/2002   EGV     N.D.364     Se imprime el asterisco '*' sí y solo sí el
//                                  movimiento no está afectado y el Documento
//                                  padre no está cancelado.
// 26/07/20002  RPC     SC 150      Ya no se imprimen movtos sin afectar
// 29/07/2002		LAP		  N.D.799		  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.
// 31/07/2002		LAP			N.D.956			Corrección en la obtención del inventario
//																	inicial.	
//                                  NOTA: Las N.D. 799 y 956 ya no son validos
//                                  con el cambio a existencias de la N.C. 150
//                                  por eso se eliminan dichos cambios ademas 
//                                  de que fueron programados despues dicha
//                                  notificación. (CILA)
// 26/12/2002   EGV     N.D.1697    Evitar que se imprima por segunda vez un
//                                  producto validando el valor de la variable
//                                  lImpreso. (EGV) 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fProcesaGlobal(atProducto: Tabla)
Local lFecha, lInvInicial, lEntradas, lSalidas, lCostoExistencia
Local lImporteInicial, lImporteEntradas, lImporteSalidas, lImporteExistencia
Local lAlMenosUno, lImpreso
Local lCosto, lImporteTotal, lIdAlmacen, lFechaAnt
// N.D.799 Inicio
//! LOCAL lInvInicialAfectado, lInvInicialSinAfectar
//! LOCAL lImporteInicialAfectado, lImporteInicialSinAfectar
// N.D.799 Fin

  // Inicia acumulados
  lEntradas = 0.0
  lSalidas = 0.0
  lImporteEntradas = 0.0
  lImporteSalidas = 0.0  
  lImporteTotal =0.0 
  lImpreso = 0 
  lAlMenosUno = 0

  lIdAlmacen = tAlmacen (cIdAlmacen)
  // N.D.799 N.D.956 Inicio
  // Obtiene el inventario inicial del producto en todos los almacenes
  //!lInvInicial = fExistenciaInicialProducto(atProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
	//!lInvInicialAfectado 			= 0
	//!lInvInicialSinAfectar 		= 0
	//!SI pAfectado = 0 O pAfectado = 1  // Movimientos afectados y/o todos
	//!	lInvInicialAfectado = fExistenciaInicialProducto(atProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
	//!FINSI
	//!SI pAfectado = 0 O pAfectado = 2  // Movimientos sin afectar y/o todos
	//!	lInvInicialSinAfectar = fExistenciaProductoSinAfectar(atProducto(cIdProducto); 0; pFechaInicial; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tParametros; tDocumento; tMovimiento; tMovtoOwner; tEquivalencia)
	//!FINSI
	//!lInvInicial = lInvInicialAfectado + lInvInicialSinAfectar[C0]

  //!lImporteInicial = fCostoInicialProducto(atProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; atProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambio; pIdMoneda)
	//!lImporteInicialAfectado 	= 0
	//!lImporteInicialSinAfectar = 0
	//!SI pAfectado = 0 O pAfectado = 1  // Movimientos afectados y/o todos
	//!	lImporteInicialAfectado = fCostoInicialProducto(atProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; atProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambio; pIdMoneda)
	//!FINSI
	//!SI pAfectado = 0 O pAfectado = 2  // Movimientos sin afectar y/o todos
	//!	lImporteInicialSinAfectar = fCostoProductoSinAfectar(atProducto(cIdProducto); 0; pFechaInicial; pIdMoneda; tParametros; tDocumento; tMovimiento; tMovtoOwner; tCostoHistorico; tTipoCambio)
	//!FINSI
	//!lImporteInicial = lImporteInicialAfectado + lImporteInicialSinAfectar[C0]
	// N.D.799 N.D.956 Fin

  // RPC - ND 955 El cálculo del costo inicial se hacía con un día de más 
  // provocando que el costo inicial fuera incorrecto. Por ejemplo, se calculaba
  // el costo al 01-01-02  y luego se buscaban los movimientos del mismo día
//!  lInvInicial = fExistenciaInicialProducto(atProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
    lInvInicial = fExistenciaInicialProducto(atProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
  //N.D. 8170: No esta haciendo otro método de costeo mas que el costo promedio del producto
  Si atProducto(cMetodoCosteo) = 7
    lImporteInicial = lInvInicial * atProducto(cCostoEstandar)
  SiNo
    Si pCosto = 0
		lImporteInicial = fCostoInicialProducto(atProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; atProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambio; pIdMoneda)
	SiNo
        lFecha = fFechaAnterior(pFechaInicial)
	    Si pCosto = 1 O pCosto = 2 //Costo promedio
			lCosto = fCostoHistorico( atProducto(cIdProducto); 0; pFechaInicial; 1; tCostoHistorico; tTipoCambio; pIdMoneda)
		SiNo  //Último costo
			lCosto = fCostoHistorico( atProducto( cIdProducto ); 0; pFechaInicial; 3; tCostoHistorico; tTipoCambio; pIdMoneda )
		FinSi
		lImporteInicial = lCosto * lInvInicial
	FinSi
  FinSi  
  // FIN RPC - ND 955

  // Inicializa la Fecha de inicio del rango de fechas del reporte
  lFecha = pFechaInicial 
  // 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
    lAlMenosUno = 0
    Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[2] ]
// RPC SC 150 Ya no se imprimen movtos sin afectar
//!      // Discrimina movimientos sin afectar
//!      // CILA - SC 35
//!      //Si tMovimiento(cAfectadoInventario) = 0      
//!      //  Continua
//!      //FinSi
//!      Si pAfectado = 1 y tMovimiento(cAfectadoInventario) = 0
//!        Continua
//!     FinSi
//!     Si pAfectado = 2 y tMovimiento(cAfectadoInventario) = 1
//!        Continua
//!      FinSi 
//!      // Fin CILA - SC 35
// FIN RPC SC - 150
      // Discrimina los movimientos que no son entradas ni salidas
      Si tMovimiento(cAfectaExistencia) != 1 y tMovimiento(cAfectaExistencia) != 2
        Continua
      FinSi
      // FBCS : Descarta el movto, si es de un docto cancelado
      Si fCancelado(tMovimiento)
        Continua
      Finsi
      // Se verifica si está o no afectado en inventarios después de verificar
      // que el Documeto del movimiento no esté cancelado. 
      //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 tMovimiento(cAfectadoInventario) = 0
// RPC - SC 150 Ahora se maneja un número de error del producto y no se imrpimen
// movtos sin afectar
//!        gAsterisco = '*'
        Continua
        // FIN RPC - SC 150
      FinSi
      
      //N.C.224
      Si tMovimiento(cAfectadoInventario) = 2
      	gTieneMovtosEnCaptura = 1
      FinSi      	      	

      // Por lo menos hay un movimiento
      lAlMenosUno = 1

      lCostoExistencia = fUnidades(pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tEquivalencia)
      lIdAlmacen = 0
      Si pCosto = 2 o pCosto = 4  // Costo Promedio por almacén o último costo
        lIdAlmacen = tMovimiento(cIdAlmacen)
      FinSi
      Si pCosto = 0 
        lImporteExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambio; pIdMoneda)
      Sino
        Si pCosto = 1 o pCosto = 2 // Costo promedio
          lCosto = fCostoHistorico(atProducto(cIdProducto);0;lFecha;1;tCostoHistorico;tTipoCambio;pIdMoneda)
        Sino // Ultimo costo
          lCosto = fCostoHistorico(atProducto(cIdProducto);0;lFecha;3;tCostoHistorico;tTipoCambio;pIdMoneda)
        FinSi
          lImporteExistencia = lCosto * tMovimiento(cUnidades)
      FinSi     

      Si tMovimiento(cAfectaExistencia) = 1 // Es una entrada?
        lEntradas = lEntradas + lCostoExistencia
        lImporteEntradas = lImporteEntradas + lImporteExistencia 
      Sino
        lSalidas = lSalidas + lCostoExistencia
        lImporteSalidas = lImporteSalidas + lImporteExistencia
      FinSi
    FinMientras
    // Incrementa un día a la fecha
    lFecha = fFechaSiguiente(lFecha)
  FinMientras
  
  lImporteTotal = lImporteInicial + lImporteEntradas - lImporteSalidas
    // Todos los productos o los que tengan al menos un movimiento
  // Todos los productos o los que tengan al menos un movimiento
  Si (pImprimirProductos = 0) o (lAlMenosUno) o (pImprimirProductos = 1 y ((lSalidas != 0) o (lEntradas!=0)))
     fImprimeProducto(tProducto; lInvInicial; lEntradas; lSalidas; lImporteInicial; lImporteEntradas; lImporteSalidas)
     lImpreso = 1 
  FinSi

  // No volver a imprimir el producto.
  Si lImpreso = 0
	//N.D.8515: No se debe validar el importeTotal cuando se impriman los productos solo con existencias.
	//N.D.8696: Se requiere que no se imprima el producto cuando no tiene existencias y el parámetro pImprimirProductos "Imprimir Productos" contenga el valor de 2 correspondiente a "Sólo con existencias".
	//N.D.8781: Se modifica la condición para que evalue correctamente los productos sin existencia
    Si (pImprimirProductos = 2 y (@col(lInvInicial;0) !=0 o lSalidas !=0 o lEntradas != 0)/*Y @col(lImporteTotal;0) != 0*/) o (pImprimirProductos = 3 y ( lSalidas!=0 o lEntradas != 0 o @col(lInvInicial;0) != 0))
       fImprimeProducto(tProducto; lInvInicial; lEntradas; lSalidas; lImporteInicial; lImporteEntradas; lImporteSalidas)
       lImpreso = 1
    FinSi
  FinSi
	
	//N.C.224
	gTieneMovtosEnCaptura = 0

  // acumula al total del producto
  Si lImpreso = 1
    gTotalInvInicial = gTotalInvInicial + lInvInicial
    gTotalEntradas = gTotalEntradas + lEntradas
    gTotalSalidas = gTotalSalidas + lSalidas
    gTotalImporteInicial = gTotalImporteInicial + lImporteInicial
    gTotalImporteEntradas = gTotalImporteEntradas + lImporteEntradas
    gTotalImporteSalidas = gTotalImporteSalidas + lImporteSalidas
    lImpreso = 0
  FinSi 
FinFunc


// *****************************************************************************
//  fProcesaPorAlmacen
//
//  Esta función procesa el reporte de stock máximo por almacén.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 15/02/2002   MOFM    SC 23       Se le agregaron las validaciones para le manejo
//                                  de las nuevas opciones de pImprimirProducto 
//                                  y del parámetro pCosto (MOFM) 
// 20/03/2002   CILA    SC 35       Se modifica para mostrar todos los movimientos 
//                                  solo los movimientos afectado o solo los 
//                                  movimientos sin afectar.   
//                                  Se agrego la inicialización de la variable global
//                                  gAsterisco para imprimir en el producto que
//                                  tiene movimientos pendientes de afectar.
// 19/04/2002   EGV     N.D.364     Se imprime el asterisco '*' sí y solo sí el
//                                  movimiento no está afectado y el Documento
//                                  padre no está cancelado.
// 26/07/20002  RPC     SC 150      Ya no se imprimen movtos sin afectarÇ
// 29/07/2002		LAP		  N.D.799		  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.
// 31/07/2002		LAP			N.D.956			Corrección en la obtención del inventario
//																	inicial.
//                                  NOTA: Las N.D. 799 y 956 ya no son validos
//                                  con el cambio a existencias de la N.C. 150
//                                  por eso se eliminan dichos cambios ademas 
//                                  de que fueron programados despues dicha
//                                  notificación. (CILA)
// 26/12/2002   EGV     N.D.1697    Evitar que se imprima por segunda vez un
//                                  producto validando el valor de la variable
//                                  lImpreso. (EGV)
//05/02/2008    JENL    N.D.5062    Se cambia el indice iProductoAlmacenFechaAfec por iProductoAlmacenAfecFecha (JENL).
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fProcesaPorAlmacen(atProducto: Tabla)
Local lFecha, lInvInicial, lEntradas, lSalidas, lCostoExistencia
Local lTotalInvInicial, lTotalEntradas, lTotalSalidas
Local lDatosProducto
Local lImporteInicial, lImporteEntradas, lImporteSalidas, lImporteExistencia
Local lTotalImporteInicial, lTotalImporteEntradas, lTotalImporteSalidas
Local lCosto, lImporteTotal
Local lAlMenosUno, lImpreso, lIdAlmacen, lFechaInicial
// N.D.799 Inicio
//!LOCAL lInvInicialAfectado, lInvInicialSinAfectar
//!LOCAL lImporteInicialAfectado, lImporteInicialSinAfectar
// N.D.799 Fin

  // Imprimir todos los productos
  Si !pImprimirProductos
    // Imprime los datos del producto
    fImprimeDatosProducto(atProducto)
    lDatosProducto = 1
  Sino
    lDatosProducto = 0
  FinSi

  // Inicia acumulados por producto
  lTotalInvInicial = 0.0
  lTotalEntradas = 0.0
  lTotalSalidas = 0.0
  lTotalImporteInicial = 0.0
  lTotalImporteEntradas = 0.0
  lTotalImporteSalidas = 0.0   
  lImpreso = 0 
  lAlMenosUno = 0
  // Recorre los almacenes en el rango
  Mientras [ tAlmacen.Busca[pAlmacenInicial & '..' & pAlmacenFinal]; tAlmacen->Encontro; tAlmacen.Busca Siguiente[1] ]    
    // Inicia acumulados por almacen
    lEntradas = 0.0
    lSalidas = 0.0
    lImporteEntradas = 0.0
    lImporteSalidas = 0.0  
    gAsterisco = ' '

    // Encuentra el inventario inicial del producto en ese almacén
    // Establece el indice necesario para la rutina de inventario inicial
    tMovimiento.Usaindice['iProductoFechaAfecta'] // cIdProducto+cFecha+cAfectaExistencia

    // N.D.799 N.D.956 Inicio
    //!lInvInicial = fExistenciaInicialProducto(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
		//!lInvInicialAfectado 			= 0
		//!lInvInicialSinAfectar 		= 0
		//!SI pAfectado = 0 O pAfectado = 1  // Movimientos afectados y/o todos
		//!	lInvInicialAfectado = fExistenciaInicialProducto(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
		//!FINSI
		//!SI pAfectado = 0 O pAfectado = 2  // Movimientos sin afectar y/o todos
		//!	lInvInicialSinAfectar = fExistenciaProductoSinAfectar(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tParametros; tDocumento; tMovimiento; tMovtoOwner; tEquivalencia)
		//!FINSI
		//!lInvInicial = lInvInicialAfectado + lInvInicialSinAfectar[C0]

    //!lImporteInicial = fCostoInicialProducto(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; atProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambio; pIdMoneda)
		//!lImporteInicialAfectado 	= 0
		//!lImporteInicialSinAfectar = 0
		//!SI pAfectado = 0 O pAfectado = 1  // Movimientos afectados y/o todos
		//!	lImporteInicialAfectado = fCostoInicialProducto(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; atProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambio; pIdMoneda)
		//!FINSI
		//!SI pAfectado = 0 O pAfectado = 2  // Movimientos sin afectar y/o todos
		//!	lImporteInicialSinAfectar = fCostoProductoSinAfectar(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; pIdMoneda; tParametros; tDocumento; tMovimiento; tMovtoOwner; tCostoHistorico; tTipoCambio)
		//!FINSI
		//!lImporteInicial = lImporteInicialAfectado + lImporteInicialSinAfectar[C0]
		// N.D.799 N.D.956 Fin

    // RPC - ND 955 El cálculo del costo inicial se hacía con un día de más 
    // provocando que el costo inicial fuera incorrecto. Por ejemplo, se calculaba
    // el costo al 01-01-02  y luego se buscaban los movimientos del mismo día
//!    lInvInicial = fExistenciaInicialProducto(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
	lInvInicial = fExistenciaInicialProducto(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)
	//N.D. 8170: No esta haciendo otro método de costeo mas que el costo promedio del producto
	Si atProducto(cMetodoCosteo) = 7
		lImporteInicial = lInvInicial * atProducto(cCostoEstandar)
	SiNo
        Si pCosto = 0
			lImporteInicial = fCostoInicialProducto(atProducto(cIdProducto); tAlmacen(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; atProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambio; pIdMoneda)
		SiNo
            lFecha = fFechaAnterior(pFechaInicial)
			Si pCosto = 1 O pCosto = 2 //Costo promedio
				lCosto = fCostoHistorico( atProducto(cIdProducto); tAlmacen(cIdAlmacen); lFecha; 1; tCostoHistorico; tTipoCambio; pIdMoneda)
       		SiNo  //Último costo
				lCosto = fCostoHistorico( atProducto( cIdProducto ); tAlmacen(cIdAlmacen); lFecha; 3; tCostoHistorico; tTipoCambio; pIdMoneda )
			FinSi
			lImporteInicial = lCosto * lInvInicial
		FinSi
	FinSi
    // FIN RPC - ND 955

    // Establece el indice de recorrido
    tMovimiento.Usaindice['iProductoAlmacenFechaAfec'] // cIdProducto+cIdAlmacen+cFecha+cAfectaExistencia
    //tMovimiento.Usaindice['iProductoAlmacenAfecFecha'] // cIdProducto+cIdAlmacen+CAFECTADOINVENTARIO+cFecha N.D.5062
    // Inicializa la Fecha de inicio del rango de fechas del reporte
    lFecha = pFechaInicial 
    // 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
      lAlMenosUno = 0
      Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & tAlmacen(cIdAlmacen) & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[3] ]
      //Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & tAlmacen(cIdAlmacen) & ':' & '1' & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[4] ]//N.D.5062
// RPC SC 150 Ya no se imprimen movtos sin afectar
//!        // Discrimina movimientos sin afectar
//!        // CILA - SC 35 
//!        //Si tMovimiento(cAfectadoInventario) = 0      
//!        //  Continua
//!        //FinSi
//!        Si pAfectado = 1 y tMovimiento(cAfectadoInventario) = 0
//!          Continua
//!        FinSi
//!        Si pAfectado = 2 y tMovimiento(cAfectadoInventario) = 1
//!          Continua
//!        FinSi 
//!        // Fin CILA - SC 35
// FIN RPC - SC 150
        // Discrimina los movimientos que no son entradas ni salidas
        Si tMovimiento(cAfectaExistencia) != 1 y tMovimiento(cAfectaExistencia) != 2
          Continua
        FinSi

        // FBCS descarta los movtos de doctos cancelados
        Si fCancelado(tMovimiento)
          Continua
        Finsi

        // Se verifica si está o no afectado en inventarios después de verificar
        // que el Documeto del movimiento no esté cancelado.
        //N.D.5062 Inicio
        //Si tMovimiento(cAfectadoInventario) != 1
// RPC - SC 150 Ahora se maneja un número de error del producto y no se imrpimen
// movtos sin afectar
//!          gAsterisco = '*'
          //Continua
          // FIN RPC - SC 150
        //FinSi
        //N.D.5062 Fin
        
        //N.C.224
        Si tMovimiento(cAfectadoInventario) = 2
        	gTieneMovtosEnCaptura = 1
        FinSi 

        // Por lo menos hay un movimiento
        lAlMenosUno = 1

        lCostoExistencia = fUnidades(pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tEquivalencia)
        lIdAlmacen = 0
        Si pCosto = 2 o pCosto = 4  // Costo Promedio por almacén o último costo
          lIdAlmacen = tMovimiento(cIdAlmacen)
        FinSi
        Si pCosto = 0 
          lImporteExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambio; pIdMoneda)
        Sino
          Si pCosto = 1 o pCosto = 2 // Costo promedio
            lCosto = fCostoHistorico(atProducto(cIdProducto);lIdAlmacen;lFecha;1;tCostoHistorico;tTipoCambio;pIdMoneda)
          Sino // Ultimo costo
            lCosto = fCostoHistorico(atProducto(cIdProducto);lIdAlmacen;lFecha;3;tCostoHistorico;tTipoCambio;pIdMoneda)
          FinSi
            lImporteExistencia = lCosto * tMovimiento(cUnidades)
        FinSi     

        Si tMovimiento(cAfectaExistencia) = 1 // Es una entrada?
          lEntradas = lEntradas + lCostoExistencia
          lImporteEntradas = lImporteEntradas + lImporteExistencia
        Sino
          lSalidas = lSalidas + lCostoExistencia
          lImporteSalidas = lImporteSalidas + lImporteExistencia
        FinSi
      FinMientras // tMovimiento->Encontro
      // Incrementa un día a la fecha
      lFecha = fFechaSiguiente(lFecha)
    FinMientras // lFecha <= pFechaFinal
    // Imprime el almacén
    lImporteTotal = lImporteInicial + lImporteEntradas - lImporteSalidas
    // Todos los productos o los que tengan al menos un movimiento
    // Todos los productos o los que tengan al menos un movimiento
    Si (pImprimirProductos = 0) o (lAlMenosUno) o (pImprimirProductos = 1 y ((lSalidas != 0) o (lEntradas!=0)))
      // Si no se han impreso los datos del producto, se imprimen
      Si !lDatosProducto
        fImprimeDatosProducto(atProducto)
        lDatosProducto = 1
      FinSi
      fImprimeAlmacen(tAlmacen; lInvInicial; lEntradas; lSalidas)
      fImprimeImportes(atProducto; lImporteInicial; lImporteEntradas; lImporteSalidas)
      lImpreso = 1
    FinSi

    //N.C.224
    gTieneMovtosEnCaptura = 0
		
    // No volver a imprimir el producto.
    Si lImpreso = 0
      Si  (pImprimirProductos = 2 Y @col(lImporteTotal;0) != 0) o (pImprimirProductos = 3 y (lSalidas!=0 o lEntradas != 0 o @col(lInvInicial;0) != 0))
        // Si no se han impreso los datos del producto, se imprimen
        Si !lDatosProducto
          fImprimeDatosProducto(atProducto)
          lDatosProducto = 1
        FinSi
        fImprimeAlmacen(tAlmacen; lInvInicial; lEntradas; lSalidas)
        fImprimeImportes(atProducto; lImporteInicial; lImporteEntradas; lImporteSalidas)
        lImpreso = 1
      FinSi
    FinSi

    // Acumula al total del producto
    Si lImpreso = 1
      lTotalInvInicial = lTotalInvInicial + lInvInicial
      lTotalEntradas = lTotalEntradas + lEntradas
      lTotalSalidas = lTotalSalidas + lSalidas
      lTotalImporteInicial = lTotalImporteInicial + lImporteInicial
      lTotalImporteEntradas = lTotalImporteEntradas + lImporteEntradas
      lTotalImporteSalidas = lTotalImporteSalidas + lImporteSalidas
      lImpreso = 0
    FinSi

  FinMientras // tAlmacen.Busca
  // Imprime el total del producto
  Si lDatosProducto
    fImprimeTotales(lTotalInvInicial; lTotalEntradas; lTotalSalidas; lTotalImporteInicial; lTotalImporteEntradas; lTotalImporteSalidas)
    gTotalInvInicial      = gTotalInvInicial + lTotalInvInicial
    gTotalEntradas        = gTotalEntradas + lTotalEntradas
    gTotalSalidas         = gTotalSalidas + lTotalSalidas
    gTotalImporteInicial  = gTotalImporteInicial + lTotalImporteInicial
    gTotalImporteEntradas = gTotalImporteEntradas + lTotalImporteEntradas
    gTotalImporteSalidas  = gTotalImporteSalidas + lTotalImporteSalidas
  FinSi
FinFunc


// *****************************************************************************
//  fVerificaParametros
//
//  Esta función verifica los parámetros pProductoInicial, pProductoFinal,
//  pAlmacenInicial y pAlmacenFinal.
//  Si están vacíos toma el primer y último registro 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

  Si pTipoReporte = 1 // Si el reporte es por almacén
    // Si el rango inicial es el primer almacén, recupera el código del primero
    Si pAlmacenInicial = ' '
      tAlmacen.Busca Primero
      Si tAlmacen->Encontro
        pAlmacenInicial = tAlmacen(cCodigoAlmacen)
        // Si el almacén inicial es el almacén cero, lee el siguiente
        Si !tAlmacen(cCodigoAlmacen)
          tAlmacen.Saltareg[1]
          Si tAlmacen->Encontro
            pAlmacenInicial = tAlmacen(cCodigoAlmacen)
          FinSi
        FinSI
      FinSi
    FinSi  

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


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

Encab
    // Pone el nombre del sistema
    ws.Range('A' & RenActual).Font.Color = @RGB(255;0;0)[C0]
    ws.Range('A' & RenActual).Font.Size = 10[C0]
    ws.Range('A' & RenActual).Value = 'Negrita'[C0]

    // Pone el nombre de la empresa
    ws.Range('C' & RenActual).Font.Size = 14[C0]
    ws.Range('C' & RenActual).Font.FontStyle = 'Negrita'[C0]
    // Lo centra en las columnas A a la K
    ws.Range('C' & RenActual & ':L' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range('C' & RenActual ).Value = tEmpresa->Nombre

    // Avanza de renglon
    RenActual = RenActual + 1[C0]

    // Pone el titulo del reporte en EXCEL
    ws.Range('A' & RenActual).Font.Size = 12[C0]
    ws.Range('A' & RenActual).Font.FontStyle = 'Negrita'[C0]
    Si pTipoReporte = 1
       ws.Range('A' & RenActual ).Value = 'I N V E N T A R I O  A C T U A L  P O R  A L M A C E N'[C0]
    Sino
       ws.Range('A' & RenActual ).Value = 'I N V E N T A R I O  A C T U A L  G L O B A L'[C0]
    FinSi    
    // Lo centra en las columnas A a la N
    ws.Range('A' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual).Font.Size = 12[C0]
    ws.Range('A' & RenActual).Font.FontStyle = 'Negrita'[C0]
    Si pCosto = 0
      ws.Range('A' & RenActual ).Value = 'EN IMPORTES (COSTO DEFINIDO POR EL PRODUCTO)'[C0]
    FinSi
    Si pCosto = 1
      ws.Range('A' & RenActual ).Value = 'EN IMPORTES (COSTO PROMEDIO GLOBAL)'[C0]
    FinSi
    Si pCosto = 2
      ws.Range('A' & RenActual ).Value = 'EN IMPORTES (COSTO PROMEDIO POR ALMACEN)'[C0]
    FinSi
    Si pCosto = 3
      ws.Range('A' & RenActual ).Value = 'EN IMPORTES (ULTIMO COSTO GLOBAL)'[C0]
    FinSi
    Si pCosto = 4
      ws.Range('A' & RenActual ).Value = 'EN IMPORTES (ULTIMO COSTO POR ALMACEN)'[C0]
    FinSi
    // Lo centra en las columnas A a la N
    ws.Range('A' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]

    // Pone el titulo del reporte en EXCEL
    ws.Range('A' & RenActual).Font.Size = 12[C0]
    ws.Range('A' & RenActual).Font.FontStyle = 'Negrita'[C0]    
    ws.Range('A' & RenActual ).Value = 'Del: ' & fFormateaFecha(pFechaInicial;gIdioma) & ' Al: ' & fFormateaFecha(pFechaFinal;gIdioma)[C0]
    // Lo centra en las columnas A a la N
    ws.Range('A' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]

// RPC - SC 150 Como ya no se incluyen movtos sin afectar ( sólo se detectan y
// se despliega un error ) este mensaje es innecesario
//!    // Pone el titulo del reporte en EXCEL
//!    // CILA - SC 35
//!    ws.Range('A' & RenActual).Font.Size = 12[C0]
//!    ws.Range('A' & RenActual).Font.FontStyle = 'Negrita'[C0]    
//!    Si pAfectado = 0 // Todos
//!      ws.Range('A' & RenActual ).Value = 'Se Incluyen Movimientos Afectados y sin Afectar'
//!    FinSi
//!    Si pAfectado = 1 // Afectados
//!      ws.Range('A' & RenActual ).Value = 'Se Incluyen Movimientos Afectados'
//!    FinSi
//!    Si pAfectado = 2 // Sin Afectar
//!     ws.Range('A' & RenActual ).Value = 'Se Incluyen Movimientos sin Afectar'
//!    FinSi    
//!    // Lo centra en las columnas A a la N
//!    ws.Range('A' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
//!
//!    // Avanza de renglon
//!    RenActual = RenActual + 1[C0]
//!    // Fin CILA - SC 35
// FIN RPC - SC 150
    
    // Se Revisan las clasificaciones, para recuperarlas e imprimirlas en el encabezado
    // ===== se arman los ID en una LIsta para poder recorrerlos en una iteración
    gClasesRecibidas = fCuentaClases(&gNumClasesPorTipo;pIdClase1;pIdClase2;pIdClase3;pIdClase4;pIdClase5;pIdClase6)
    // se cargan las clasificaciones validas y se obtiene el número de clases validas
    gNumDeClases = fCargaClases(tValoresDeClasif;&gListNombreDeClases; &gListIdDeClases; gClasesRecibidas)
    // Si gNumDeClases > 0    // solo si hubo al menos una clase seleccionada
      // fImprimeClasesExcel(gListNombreDeClases;gNumClasesPorTipo) 
    // Finsi

// RPC - SC 150 Como ya no se usa el asterísco para indicar errores del producto
// este mensaje ya no es necesario
//!    // CILA - SC 35
//!    ws.Range('A' & RenActual ).Value = '* - Existen movimientos que No han sido Afectados en Inventario'
//!    // Fin CILA - SC 35
// FIN RPC - SC 150

    // Si el reporte es por almacén  
    Si pTipoReporte = 1
      tMoneda.Busca[@Str(pIdMoneda;0)]
      Si tMoneda->Encontro
        ws.Range('I' & RenActual ).Value = 'Moneda: ' & tMoneda(cNombreMoneda)[C0]
      FinSi

      // Avanza de renglon
      RenActual = RenActual + 1[C0]

      // Pone los titulos de Unidades 
      ws.Range('E' & RenActual & ':H' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
      ws.Range('E' & RenActual & ':H' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('E' & RenActual & ':H' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('E' & RenActual & ':H' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
      ws.Range('E' & RenActual & ':H' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
      ws.Range('E' & RenActual & ':H' & RenActual).Interior.ColorIndex = 3[C0]    
      ws.Range('E' & RenActual).Font.Color = @RGB(255;255;255)[C0]
      ws.Range('E' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('E' & RenActual ).Value = 'EN UNIDADES'[C0]

      // Pone los titulos de Importes
      ws.Range('I' & RenActual & ':L' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
      ws.Range('I' & RenActual & ':L' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('I' & RenActual & ':L' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('I' & RenActual & ':L' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
      ws.Range('I' & RenActual & ':L' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
      ws.Range('I' & RenActual & ':L' & RenActual).Interior.ColorIndex = 3[C0]    
      ws.Range('I' & RenActual).Font.Color = @RGB(255;255;255)[C0]
      ws.Range('I' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('I' & RenActual ).Value = 'EN IMPORTES (COSTO HISTORICO)'[C0]

      // Avanza de renglon
      RenActual = RenActual + 1[C0]
 
      // Pone el titulo de cada columna en EXCEL
      ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':L' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':L' & RenActual).Interior.ColorIndex = 55[C0]    
      ws.Range('A' & RenActual & ':L' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('A' & RenActual & ':L' & RenActual).Font.Color = @RGB(255;255;255)[C0]

      ws.Range('E' & RenActual & ':N' & RenActual).HorizontalAlignment = xlDerecha[C0]
      
      //N.D.5724 Junta la columna M y N para poner los Errores.
      // Pone el titulo de cada columna en EXCEL
      ws.Range('M' & RenActual & ':N' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('M' & RenActual & ':N' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('M' & RenActual & ':N' & RenActual).Interior.ColorIndex = 55[C0]    
      ws.Range('M' & RenActual & ':N' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('M' & RenActual & ':N' & RenActual).Font.Color = @RGB(255;255;255)[C0]
      ws.Range('M' & RenActual & ':N' & RenActual).HorizontalAlignment = xlDerecha[C0]
      ws.Range('M' & RenActual & ':N' & RenActual).HorizontalAlignment = xlCentro[C0]
      
      ws.Range('A' & RenActual & ':N' & RenActual).Value = '','Almacén','Nombre (Almacén)',' ','Inventario Inicial','Entradas','Salidas','Existencia','Inventario Inicial','Entradas','Salidas','Costo Total','Error',''

    // Si el reporte es global
    Sino 
      tMoneda.Busca[@Str(pIdMoneda;0)]
      Si tMoneda->Encontro
        ws.Range('L' & RenActual ).Value = 'Moneda: ' & tMoneda(cNombreMoneda)[C0]
      FinSi

      // Avanza de renglon
      RenActual = RenActual + 1[C0]

      // Pone los titulos de Unidades 
      ws.Range('F' & RenActual & ':I' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
      ws.Range('F' & RenActual & ':I' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('F' & RenActual & ':I' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('F' & RenActual & ':I' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
      ws.Range('F' & RenActual & ':I' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
      ws.Range('F' & RenActual & ':I' & RenActual).Interior.ColorIndex = 3[C0]    
      ws.Range('F' & RenActual).Font.Color = @RGB(255;255;255)[C0]
      ws.Range('F' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('F' & RenActual ).Value = 'EN UNIDADES'[C0]

      // Pone los titulos de Importes
      ws.Range('J' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
      ws.Range('J' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('J' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('J' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
      ws.Range('J' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
      ws.Range('J' & RenActual & ':M' & RenActual).Interior.ColorIndex = 3[C0]    
      ws.Range('J' & RenActual).Font.Color = @RGB(255;255;255)[C0]
      ws.Range('J' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('J' & RenActual ).Value = 'EN IMPORTES (COSTO HISTORICO)'[C0]

      // Avanza de renglon
      RenActual = RenActual + 1[C0]
 
      // Pone el titulo de cada columna en EXCEL
      ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
      ws.Range('A' & RenActual & ':M' & RenActual).Interior.ColorIndex = 55[C0]    
      ws.Range('A' & RenActual & ':M' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('A' & RenActual & ':M' & RenActual).Font.Color = @RGB(255;255;255)[C0]

      ws.Range('E' & RenActual & ':M' & RenActual).HorizontalAlignment = xlDerecha[C0]
      ws.Range('M' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentro[C0]
      
      //N.D.5724 Junta la columna N y O para poner los Errores.
      // Pone el titulo de cada columna en EXCEL
      ws.Range('N' & RenActual & ':O' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
      ws.Range('N' & RenActual & ':O' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
      ws.Range('N' & RenActual & ':O' & RenActual).Interior.ColorIndex = 55[C0]    
      ws.Range('N' & RenActual & ':O' & RenActual).Font.FontStyle = 'Negrita'[C0]    
      ws.Range('N' & RenActual & ':O' & RenActual).Font.Color = @RGB(255;255;255)[C0]
      ws.Range('N' & RenActual & ':O' & RenActual).HorizontalAlignment = xlDerecha[C0]
      ws.Range('N' & RenActual & ':O' & RenActual).HorizontalAlignment = xlCentro[C0]

      ws.Range('A' & RenActual & ':N' & RenActual).Value = '','Producto','Nombre','Método Costeo',' ','Inventario Inicial','Entradas','Salidas','Existencia','Inventario Inicial','Entradas','Salidas','Inventario Final','Error'
    FinSi
   
    Excel.Rows('8:8').Select
    Excel.ActiveWindow.FreezePanes = True
    ws.Range('A' & RenActual).Select
FinEncab



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

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

// Configura los decimales del reporte
fConfiguraDecimales()

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

fEjercicioPeriodo(pFechaInicial; &gPeriodo; &gIdEjercicio; tEjercicio) 

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

  gTotalInvInicial = 0.0
  gTotalEntradas = 0.0
  gTotalSalidas = 0.0
  gTotalImporteInicial = 0.0
  gTotalImporteEntradas = 0.0
  gTotalImporteSalidas = 0.0   

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
	
	//N.D.4538 (MAJU)
  //Al elegir como filtro “Unidad no equivalente” Si uno de los productos a mostrar 
  //no tiene asignada Unidad No Equivalente no se mostrara en el reporte.
	Si pUnidad = 1 y tProducto(cIdUnidadNoConvertible) = 0
 		Continua
 	Sino
 		fVerificaUnidad(tProducto)
  FinSi

  Si pTipoReporte = 0 // Reporte global?
    fProcesaGlobal(tProducto)
  Sino // por almacén
    fProcesaPorAlmacen(tProducto)
  FinSi

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

// Si el reporte es global se manda imprimir los totales
//Si pTipoReporte = 0
fImprimeTotales(gTotalInvInicial; gTotalEntradas; gTotalSalidas; gTotalImporteInicial; gTotalImporteEntradas; gTotalImporteSalidas)
//FinSi

// RPC - SC 150 En los reportes globales ahora se imprime al final la leyenda 
// con los errores de existencias o costos
Si pTipoReporte = 0 o pTipoReporte = 2 // Reporte global?
  ws.Range('A' & (RenActual + 2 )).Value = 'Errores de existencias o costos:'
  ws.Range('B' & (RenActual + 3 )).Value = '(1)  Captura en desorden de entradas'  
  ws.Range('B' & (RenActual + 4 )).Value = '(2)  Captura en desorden de salidas'
  ws.Range('B' & (RenActual + 5 )).Value = '(3)  Existencias negativas'
  ws.Range('B' & (RenActual + 6 )).Value = '(4)  Series sin movimiento de entrada'[C1]
  ws.Range('B' & (RenActual + 7 )).Value = '(5)  Series sin costo'[C1]
  ws.Range('B' & (RenActual + 8 )).Value = '(6)  Movimientos sin afectar'[C1]
  ws.Range('B' & (RenActual + 9 )).Value = '(7)  En proceso de levantamiento de inventario físico'[C1]
  //N.C.224
  ws.Range('B' & (RenActual + 10 )).Value = '(8)  Este producto está incluido en algún movimiento que actualmente está en captura, motivo por el cual dicho movimiento solo está afectado en existencia y no en costo'[C1]  

  ws.Range('A' & (RenActual + 11 )).Value = 'En caso de captura en desorden de entradas se recomienda ejecutar el proceso "Recosteo" para los productos con errores'[C1]
  ws.Range('A' & (RenActual + 12 )).Value = 'En caso de captura en desorden de salidas se recomienda ejecutar el proceso "Recosteo" para los productos con errores'[C1]
  ws.Range('A' & (RenActual + 13 )).Value = 'En caso de existencias Negativas se recomienda registrar las entradas necesarias y ejecutar el proceso "Recosteo" para los productos con errores'[C1]
  ws.Range('A' & (RenActual + 14 )).Value = 'En caso de series sin movimiento de entrada la existencia puede no coincidir con las series desplegadas, se recomienda registrar la entrada de las series pendientes'[C1]
  ws.Range('A' & (RenActual + 15 )).Value = 'En caso de series sin costo se recomienda ejecutar el proceso "Recosteo" para los productos con errores'[C1]
  ws.Range('A' & (RenActual + 16 )).Value = 'En caso de movimientos sin afectar se recomienda consultar el reporte "Movimientos sin Afectar"'[C1]
  ws.Range('A' & (RenActual + 17 )).Value = 'En caso de inventario físico se recomienda aplicar el inventario físico'[C1]
  ws.Range('A' & (RenActual + 18 )).Value = 'En este caso se recomienda consultar el reporte en cuanto se termine de capturar el documento'[C1]
SiNo
  ws.Range('A' & (RenActual + 2 )).Value = '(*)  Este producto está incluido en algún movimiento que actualmente está en captura, motivo por el cual dicho movimiento solo está afectado en existencia y no en costo'[C1]  
Finsi
// FIN RPC - SC 150
