private void contabilidad_asientosAjuste(dbContab_Contab_Entities context, int cuentaContableID, int moneda, short ano, int ciaSeleccionada, out bool error, out string message)
        {
            error   = false;
            message = "";

            // asientos
            string queryString =
                $"Select d.NumeroAutomatico as numeroAutomatico, Sum(d.Debe) as sumOfDebe, Sum(d.Haber) as sumOfHaber, " +
                "Sum(d.Debe) - Sum(d.Haber) as diferencia, Max(d.Partida) as ultimaPartida " +
                "From dAsientos d Inner Join Asientos a On d.NumeroAutomatico = a.NumeroAutomatico " +
                "Where a.AnoFiscal = {0} And a.Moneda = {1} And a.Cia = {2} " +
                "Group By d.NumeroAutomatico " +
                "Having Sum(d.Debe) <> Sum(d.Haber) ";

            List <asiento_sumarizacion> query = context.ExecuteStoreQuery <asiento_sumarizacion>(queryString, ano, moneda, ciaSeleccionada).ToList();
            dAsiento partida;

            int asientosContablesAjustados = 0;

            foreach (asiento_sumarizacion p in query)
            {
                partida = new dAsiento();

                partida.NumeroAutomatico = p.numeroAutomatico;
                partida.Partida          = Convert.ToInt16(p.ultimaPartida + 10);
                partida.CuentaContableID = cuentaContableID;
                partida.Descripcion      = "Reconversión (2018) - ajuste al asiento contable";
                partida.Referencia       = null;
                partida.Debe             = p.diferencia <= 0 ? Math.Abs(p.diferencia) : 0;
                partida.Haber            = p.diferencia > 0 ? Math.Abs(p.diferencia) : 0;

                context.dAsientos.AddObject(partida);
                asientosContablesAjustados++;
            }

            try
            {
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                error   = true;
                message = "Ha ocurrido un error al intentar ejecutar una operación de acceso a la base de datos. <br /> " +
                          "El mensaje específico de error es: " + ex.Message + "<br /><br />";

                context.Dispose();

                return;
            }

            context.Dispose();

            message = $"<h3>Asientos contables - ajuste contra cuenta de reconversión</h3><br />" +
                      $"Ok, El proceso ha finalizado en forma satisfactoria.<br /><br />" +
                      $"En total, se han actualizado: {asientosContablesAjustados.ToString()} asientos contables, para ajustarlos y <em>cuadrarlos</em> a cero. ";

            return;
        }
        private void contabilidad_saldosInicialesCuadrar(dbContab_Contab_Entities context, int cuentaContableID, int moneda, short ano, int ciaSeleccionada, out bool error, out string message)
        {
            error   = false;
            message = "";

            // asientos
            string queryString =
                $"Select s.Moneda as moneda, s.MonedaOriginal as monedaOriginal, s.Ano as ano, s.Cia as cia, Sum(s.Inicial) as sumOfInicial " +
                "From SaldosContables s Inner Join CuentasContables c On s.CuentaContableID = c.ID " +
                "Where s.Ano = {0} And s.Moneda = {1} And s.Cia = {2} " +
                "And c.TotDet = 'D' " +
                "Group By s.Moneda, s.MonedaOriginal, s.Ano, s.Cia";

            List <saldos_sumarizacion> query = context.ExecuteStoreQuery <saldos_sumarizacion>(queryString, ano, moneda, ciaSeleccionada).ToList();
            SaldosContable             saldoContable;

            int saldosContables_ajustados = 0;
            int saldosContables_agregados = 0;

            foreach (saldos_sumarizacion inicial in query)
            {
                if (inicial.sumOfInicial == 0)
                {
                    // si no hay diferencia en el saldo inicial, simplemente continuamos ...
                    continue;
                }


                // leemos un registro de saldos para la cuenta contable, a ver si existe
                saldoContable = context.SaldosContables.Where(s => s.CuentaContableID == cuentaContableID &&
                                                              s.Moneda == inicial.moneda && s.MonedaOriginal == inicial.monedaOriginal &&
                                                              s.Ano == inicial.ano && s.Cia == inicial.cia).FirstOrDefault();

                if (saldoContable != null)
                {
                    // el registro de saldos para la: cuenta, moneda y moneda  original *existe*; lo actualizamos

                    // calculamos el nuevo saldo inicial (ajustado)
                    decimal nuevoInicial = saldoContable.Inicial.HasValue ? saldoContable.Inicial.Value : 0;

                    if (inicial.sumOfInicial >= 0)
                    {
                        nuevoInicial = nuevoInicial - inicial.sumOfInicial;                     // la diferencia es mayor que cero; para ajustar, restamos
                    }
                    else
                    {
                        nuevoInicial = nuevoInicial + Math.Abs(inicial.sumOfInicial);           // la diferencia es menor que cero; para ajustar, sumamos
                    }
                    saldoContable.Inicial = nuevoInicial;
                    saldosContables_ajustados++;
                }
                else
                {
                    // el registro de saldos para la cuenta *no existe*; lo agregamos

                    SaldosContable saldo = new SaldosContable
                    {
                        CuentaContableID = cuentaContableID,
                        Moneda           = inicial.moneda,
                        MonedaOriginal   = inicial.monedaOriginal,
                        Ano = inicial.ano,
                        // agregamos la diferencia, justo con el signo contrario ...
                        Inicial = (inicial.sumOfInicial * -1),
                        Mes01   = 0,
                        Mes02   = 0,
                        Mes03   = 0,
                        Mes04   = 0,
                        Mes05   = 0,
                        Mes06   = 0,
                        Mes07   = 0,
                        Mes08   = 0,
                        Mes09   = 0,
                        Mes10   = 0,
                        Mes11   = 0,
                        Mes12   = 0,
                        Anual   = 0,
                        Cia     = inicial.cia,
                    };

                    saldosContables_agregados++;
                    context.SaldosContables.AddObject(saldo);
                }
            }


            try
            {
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                error   = true;
                message = $"<h3>Saldos iniciales - Cuadre contra cuenta de reconversión</h3><br />" +
                          "Ha ocurrido un error al intentar ejecutar una operación de acceso a la base de datos. <br /> " +
                          "El mensaje específico de error es: " + ex.Message + "<br /><br />";

                context.Dispose();

                return;
            }

            context.Dispose();

            message = $"<h3>Saldos iniciales - ajuste contra cuenta de reconversión</h3><br />" +
                      $"Ok, El proceso ha finalizado en forma satisfactoria.<br /><br />" +
                      $"En total, se han <b>actualizado</b>: {saldosContables_ajustados.ToString()} registros de saldo, para ajustar el saldo inicial del año y <em>cuadrarlo</em> a cero.<br />" +
                      $"Además, se han <b>agregado</b>: {saldosContables_agregados.ToString()} registros de saldo, para ajustar el saldo inicial del año y <em>cuadrarlo</em> a cero.";

            return;
        }
        private void RefreshAndBindInfo()
        {
            if (!User.Identity.IsAuthenticated)
            {
                FormsAuthentication.SignOut();
                return;
            }

            if (Session["filtroForma_consultaAsientosContables"] == null)
            {
                ErrMessage_Span.InnerHtml = "Aparentemente, Ud. no ha indicado un filtro aún.<br />Por favor indique y aplique un filtro " +
                                            "antes de intentar mostrar el resultado de la consulta.";
                ErrMessage_Span.Style["display"] = "block";

                return;
            }

            // --------------------------------------------------------------------------------------------
            // determinamos el mes y año fiscales, para usarlos como criterio para buscar el saldo en la tabla
            // SaldosContables. En esta table, los saldos están para el mes fiscal y no para el mes calendario.
            // Los meses solo varían cuando el año fiscal no es igual al año calendario

            // --------------------------------------------------------------------------------------------
            // eliminamos el contenido de la tabla temporal

            dbContab_Contab_Entities context = new dbContab_Contab_Entities();

            try
            {
                context.ExecuteStoreCommand("Delete From tTempWebReport_ConsultaComprobantesContables Where NombreUsuario = {0}", Membership.GetUser().UserName);
            }
            catch (Exception ex)
            {
                context.Dispose();

                ErrMessage_Span.InnerHtml = "Ha ocurrido un error al intentar ejecutar una operación de acceso a la base de datos. <br /> " +
                                            "El mensaje específico de error es: " + ex.Message + "<br /><br />";
                ErrMessage_Span.Style["display"] = "block";

                return;
            }

            // ----------------------------------------------------------------------------------------------------------------------
            // leemos la tabla de monedas para 'saber' cual es la moneda Bs. Nota: la idea es aplicar las opciones de reconversión
            // *solo* a esta moneda
            var monedaNacional_return = Reconversion.Get_MonedaNacional();

            if (monedaNacional_return.error)
            {
                ErrMessage_Span.InnerHtml        = monedaNacional_return.message;
                ErrMessage_Span.Style["display"] = "block";

                return;
            }

            Monedas monedaNacional = monedaNacional_return.moneda;
            // ----------------------------------------------------------------------------------------------------------------------

            // agregamos este flag luego de la reconversión del 1-Oct-21
            // la idea es que el usuario pueda decidir si reconvertir montos
            bool bReconvertirCifrasAntes_01Oct2021 = (bool)Session["ReconvertirCifrasAntes_01Oct2021"];

            // el usuario puede indicar que desea *solo* asientos con uploads
            string joinTableAsientosUploads = "Left Outer Join ";

            if (Session["SoloAsientosConUploads_CheckBox"] != null && Convert.ToBoolean(Session["SoloAsientosConUploads_CheckBox"]))
            {
                joinTableAsientosUploads = "Join ";
            }

            // usamos el criterio que indico el usuario para leer las cuentas contables y grabarlas a una tabla en la base de datos temporal

            // NOTA: *solo* si el usuario usa algunos criterios en el filtro, usamos un subquery en el select a los asientos contables

            // nótese que el select a la tabla de links (asientos_documentos_links) se hace en un subquery; la idea es evitar que los counts se multipliquen
            // por la cantidad de registros en el primer join. cuando en sql se hacen counts, sum, etc., y hay más de dos tablas en el select, los montos
            // se desvirtúan. La solución es usar subqueries para las tablas que siguen a la segunda ...
            string sSqlQueryString = "";

            if (Session["filtroForma_consultaAsientosContables_subQuery"] == null || Session["filtroForma_consultaAsientosContables_subQuery"].ToString() == "1 = 1")
            {
                sSqlQueryString = "SELECT Asientos.NumeroAutomatico, Asientos.Moneda, Asientos.Fecha, " +
                                  "Count(dAsientos.Partida) As NumPartidas, Sum(dAsientos.Debe) As TotalDebe, Sum(dAsientos.Haber) AS TotalHaber, " +
                                  "iif(links.NumLinks Is Not Null, links.NumLinks, 0) As NumLinks, Lote As Lote " +
                                  "FROM Asientos Left Outer Join dAsientos On Asientos.NumeroAutomatico = dAsientos.NumeroAutomatico " +
                                  joinTableAsientosUploads +    // 'join' o 'left join' dependiendo de si el usuario quiere *solo* asientos con uploads
                                  "(SELECT Asientos_Documentos_Links.NumeroAutomatico, Count(Asientos_Documentos_Links.Id) as NumLinks " +
                                  "FROM Asientos_Documentos_Links " +
                                  "Group By Asientos_Documentos_Links.NumeroAutomatico) as links On Asientos.NumeroAutomatico = links.NumeroAutomatico " +
                                  "Where " + Session["filtroForma_consultaAsientosContables"].ToString() + " " +
                                  "Group By Asientos.NumeroAutomatico, Asientos.Moneda, Asientos.Fecha, Asientos.Lote, links.NumLinks";
            }
            else
            {
                // usamos un subquery para que solo asientos con ciertas cuentas *o* partidas con montos con más de 2 decimales sean seleccionados
                sSqlQueryString = "SELECT Asientos.NumeroAutomatico, Asientos.Moneda, Asientos.Fecha, " +
                                  "Count(dAsientos.Partida) As NumPartidas, Sum(dAsientos.Debe) As TotalDebe, Sum(dAsientos.Haber) AS TotalHaber, " +
                                  "iif(links.NumLinks Is Not Null, links.NumLinks, 0) As NumLinks, Lote As Lote " +
                                  "FROM Asientos " +
                                  "Left Outer Join dAsientos On Asientos.NumeroAutomatico = dAsientos.NumeroAutomatico " +
                                  "Left Outer Join CuentasContables On CuentasContables.ID = dAsientos.CuentaContableID " +

                                  joinTableAsientosUploads +    // 'join' o 'left join' dependiendo de si el usuario quiere *solo* asientos con uploads
                                  "(SELECT Asientos_Documentos_Links.NumeroAutomatico, Count(Asientos_Documentos_Links.Id) as NumLinks " +
                                  "FROM Asientos_Documentos_Links " +
                                  "Group By Asientos_Documentos_Links.NumeroAutomatico) as links On Asientos.NumeroAutomatico = links.NumeroAutomatico " +

                                  "Where " + Session["filtroForma_consultaAsientosContables"].ToString() +
                                  " And (Asientos.NumeroAutomatico In (SELECT Asientos.NumeroAutomatico FROM Asientos " +
                                  "Left Outer Join dAsientos On Asientos.NumeroAutomatico = dAsientos.NumeroAutomatico " +
                                  "Left Outer Join CuentasContables On CuentasContables.ID = dAsientos.CuentaContableID " +
                                  "Where " + Session["filtroForma_consultaAsientosContables"].ToString() + " And " +
                                  Session["filtroForma_consultaAsientosContables_subQuery"].ToString() + "))" +
                                  "Group By Asientos.NumeroAutomatico, Asientos.Moneda, Asientos.Fecha, Asientos.Lote, links.NumLinks";
            }

            if (Session["SoloAsientosDescuadrados"] != null && Convert.ToBoolean(Session["SoloAsientosDescuadrados"]))
            {
                sSqlQueryString = sSqlQueryString + " Having Sum(dAsientos.Debe) <> Sum(dAsientos.Haber)";
            }


            List <ComprobanteContable_Object>            query = context.ExecuteStoreQuery <ComprobanteContable_Object>(sSqlQueryString).ToList();
            tTempWebReport_ConsultaComprobantesContables MyComprobantesContable;

            decimal nTotalDebe        = 0;
            decimal nTotalHaber       = 0;
            int     cantidadRegistros = 0;

            DateTime fechaReconversion2021 = new DateTime(2021, 10, 1);

            foreach (ComprobanteContable_Object a in query)
            {
                decimal totalDebe  = a.TotalDebe != null ? a.TotalDebe.Value : 0;
                decimal totalHaber = a.TotalHaber != null ? a.TotalHaber.Value : 0;
                // -----------------------------------------------------------------------------------------
                // el usuario puede indicar que quiere reconvertir cifras anteriores al 31/Oct/21
                if (bReconvertirCifrasAntes_01Oct2021 && (a.Moneda == monedaNacional.Moneda) && (a.Fecha < fechaReconversion2021))
                {
                    totalDebe /= 1000000;
                    totalDebe  = Math.Round(totalDebe, 2);

                    totalHaber /= 1000000;
                    totalHaber  = Math.Round(totalHaber, 2);
                }

                MyComprobantesContable = new tTempWebReport_ConsultaComprobantesContables();

                MyComprobantesContable.NumeroAutomatico = a.NumeroAutomatico;
                MyComprobantesContable.NumPartidas      = Convert.ToInt16(a.NumPartidas);
                MyComprobantesContable.TotalDebe        = totalDebe;
                MyComprobantesContable.TotalHaber       = totalHaber;
                MyComprobantesContable.NombreUsuario    = Membership.GetUser().UserName;
                MyComprobantesContable.NumUploads       = Convert.ToInt16(a.NumLinks);
                MyComprobantesContable.Lote             = a.Lote;

                context.tTempWebReport_ConsultaComprobantesContables.AddObject(MyComprobantesContable);

                nTotalDebe  += totalDebe;
                nTotalHaber += totalHaber;
                cantidadRegistros++;
            }

            try
            {
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                string errorMessage = ex.Message;
                if (ex.InnerException != null)
                {
                    errorMessage += "<br />" + ex.InnerException.Message;
                }
                ErrMessage_Span.InnerHtml = "Ha ocurrido un error al intentar ejecutar una operación de acceso a la base de datos. <br /> " +
                                            "El mensaje específico de error es: " +
                                            errorMessage;
                ErrMessage_Span.Style["display"] = "block";

                context.Dispose();
                return;
            }

            context.Dispose();

            this.CompaniasFilter_DropDownList.DataBind();
            this.MonedasFilter_DropDownList.DataBind();
            ComprobantesContables_ListView.DataBind();

            // actualizamos los totales en el footer en el ListView
            Label numberOfRecords_label = (Label)ComprobantesContables_ListView.FindControl("numberOfRecords_label");
            Label MySumOfDebe_Label     = (Label)ComprobantesContables_ListView.FindControl("SumOfDebe_Label");
            Label MySumOfHaber_Label    = (Label)ComprobantesContables_ListView.FindControl("SumOfHaber_Label");

            if (numberOfRecords_label != null)
            {
                numberOfRecords_label.Text = cantidadRegistros.ToString();
            }

            if (MySumOfDebe_Label != null)
            {
                MySumOfDebe_Label.Text = nTotalDebe.ToString("#,##0.000");
            }

            if (MySumOfHaber_Label != null)
            {
                MySumOfHaber_Label.Text = nTotalHaber.ToString("#,##0.000");
            }
        }
        public HttpResponseMessage GrabarItemsEditados([FromUri] int ciaContabSeleccionada, [FromBody] List <CodigoPresupuestoEditado> data)
        {
            if (!User.Identity.IsAuthenticated)
            {
                var errorResult = new
                {
                    ErrorFlag    = true,
                    ErrorMessage = "Error: por favor haga un login a esta aplicación, y luego regrese a ejecutar esta función."
                };

                return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
            }

            try
            {
                // el criterio es un json, pero viene como un string
                //List<CodigoPresupuestoEditado> codigosPresupuestoEditados = new List<CodigoPresupuestoEditado>();
                //codigosPresupuestoEditados = JsonConvert.DeserializeObject<List<CodigoPresupuestoEditado>>(data);

                dbContab_Contab_Entities context = new dbContab_Contab_Entities();

                var itemsAgregados  = 0;
                var itemsEditados   = 0;
                var itemsEliminados = 0;

                string message = "";

                foreach (var item in data)
                {
                    // -----------------------------------------------------------------------------------------------------------
                    // nótese como validamos cada cuenta de presupuesto usando los atributos que definimos en la clase (poco) ...

                    // Use the ValidationContext to validate the Product model against the product data annotations
                    // before saving it to the database
                    var validationContext = new ValidationContext(item, serviceProvider: null, items: null);
                    var validationResults = new List <ValidationResult>();

                    bool isValid = true;

                    if (!(item.isDeleted.HasValue && item.isDeleted.Value))
                    {
                        // no validamos los items que el usuario decida eliminar ...
                        isValid = Validator.TryValidateObject(item, validationContext, validationResults, true);
                    }

                    // If there any exception return them in the return result
                    if (!isValid)
                    {
                        foreach (ValidationResult validationResult in validationResults)
                        {
                            if (message == "")
                            {
                                message = "<li>" + validationResult.ErrorMessage + "</li>";
                            }
                            else
                            {
                                message += "<li>" + validationResult.ErrorMessage + "</li>";
                            }
                        }

                        var errorResult = new
                        {
                            ErrorFlag    = true,
                            ErrorMessage = "<b>Error:</b> se ha producido un error al intentar efectuar una operación en la base de datos.<br />" +
                                           "<b>El mensaje específico de error es:</b><ul>" + message + "</ul>"
                        };

                        return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
                    }
                    // -----------------------------------------------------------------------------------------------------------


                    if (item.isDeleted.HasValue && item.isDeleted.Value)
                    {
                        var codigoPresupuesto = context.Presupuesto_Codigos.Where(p => p.Codigo == item.CodigoOriginal && p.CiaContab == ciaContabSeleccionada).
                                                FirstOrDefault();

                        if (codigoPresupuesto != null)
                        {
                            context.Presupuesto_Codigos.DeleteObject(codigoPresupuesto);
                            itemsEliminados++;
                        }
                    }
                    ;

                    if (item.isEdited.HasValue && item.isEdited.Value)
                    {
                        // nótese como usamos el código 'original', pues permitimos al usuario cambiar el código (el cual es la clave del registro)

                        var codigoPresupuesto = context.Presupuesto_Codigos.Where(p => p.Codigo == item.CodigoOriginal && p.CiaContab == ciaContabSeleccionada).
                                                FirstOrDefault();
                        if (codigoPresupuesto != null)
                        {
                            codigoPresupuesto.Codigo         = item.Codigo;
                            codigoPresupuesto.Descripcion    = item.Descripcion;
                            codigoPresupuesto.CantNiveles    = item.CantNiveles.Value;
                            codigoPresupuesto.SuspendidoFlag = item.Suspendido.Value;
                            codigoPresupuesto.GrupoFlag      = item.Grupo.Value;

                            // ----------------------------------------------------------------------------------------
                            // actualizamos las cuentas contables asociadas al código de presupuesto ...

                            var cuentasContablesCount = codigoPresupuesto.CuentasContables.Count();

                            for (int i = 0; i < cuentasContablesCount; i++)
                            {
                                var cuentaContable = codigoPresupuesto.CuentasContables.First();
                                codigoPresupuesto.CuentasContables.Remove(cuentaContable);
                            }

                            foreach (var cuentaContable in item.CuentasContables)
                            {
                                var cuentaContable2 = context.CuentasContables.Where(c => c.ID == cuentaContable.ID).FirstOrDefault();
                                if (cuentaContable2 != null)
                                {
                                    codigoPresupuesto.CuentasContables.Add(cuentaContable2);
                                }
                            }

                            itemsEditados++;
                        }
                    }
                    ;

                    if (item.isNew.HasValue && item.isNew.Value)
                    {
                        var codigoPresupuesto = new Presupuesto_Codigos();

                        codigoPresupuesto.Codigo         = item.Codigo;
                        codigoPresupuesto.Descripcion    = item.Descripcion;
                        codigoPresupuesto.CantNiveles    = item.CantNiveles.Value;
                        codigoPresupuesto.SuspendidoFlag = item.Suspendido.Value;
                        codigoPresupuesto.GrupoFlag      = item.Grupo.Value;
                        codigoPresupuesto.CiaContab      = ciaContabSeleccionada;

                        // ----------------------------------------------------------------------------------------
                        // actualizamos las cuentas contables asociadas al código de presupuesto ...

                        foreach (var cuentaContable in item.CuentasContables)
                        {
                            var cuentaContable2 = context.CuentasContables.Where(c => c.ID == cuentaContable.ID).FirstOrDefault();
                            if (cuentaContable2 != null)
                            {
                                codigoPresupuesto.CuentasContables.Add(cuentaContable2);
                            }
                        }

                        context.Presupuesto_Codigos.AddObject(codigoPresupuesto);

                        itemsAgregados++;
                    }
                }

                context.SaveChanges();

                message = "Ok, " + itemsAgregados.ToString() + " registros han sido agregados; " +
                          itemsEditados.ToString() + " registros han sido modificados; " +
                          itemsEliminados.ToString() + " registros han sido eliminados. ";

                var result = new
                {
                    ErrorFlag     = false,
                    ErrorMessage  = "",
                    ResultMessage = message
                };

                return(Request.CreateResponse(HttpStatusCode.OK, result));
            }
            catch (Exception ex)
            {
                string message = ex.Message;
                if (ex.InnerException != null)
                {
                    message += "<br />" + ex.InnerException.Message;
                }

                var errorResult = new
                {
                    ErrorFlag    = true,
                    ErrorMessage = "Error: se ha producido un error al intentar efectuar una operación en la base de datos.<br />" +
                                   "El mensaje específico de error es: <br />" + message
                };

                return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
            }
        }
        private void RefreshAndBindInfo()
        {
            if (this.User != null && this.User.Identity != null && !User.Identity.IsAuthenticated)
            {
                FormsAuthentication.SignOut();
                return;
            }

            if (Session["FiltroForma"] == null)
            {
                Session["Thread_ErrorMessage"] = "Aparentemente, Ud. no ha indicado un filtro aún.<br /> " +
                                                 "Por favor indique y aplique un filtro antes de intentar mostrar el resultado de " +
                                                 "la consulta.";
                return;
            }

            Session["Progress_Percentage"] = 0;
            string errorMessage = "";

            // nota importante: esta consulta (y otras?) deben, al menos por ahora, ser pedidas para una CiaContab
            // en particular, pues los años fiscales para las Cias Contab pueden variar entre ellas ...
            if (Session["CiaContabSeleccionada"] == null)
            {
                // el usuario debe seleccionar una cia contab en particular, pues los saldos contables se leen
                // de acuerdo al año fiscal de la misma ...

                Session["Thread_ErrorMessage"] = "Aparentemente, no se ha seleccionado una Cia Contab.<br /> " +
                                                 "Por favor seleccione una Cia Contab al establecer el filtro a usar para esta consulta.";

                Session["Progress_SelectedRecs"] = 0;
                Session["Progress_Completed"]    = 1;
                Session["Progress_Percentage"]   = 0;

                return;
            }

            var ciaContabSeleccionada = Convert.ToInt32(Session["CiaContabSeleccionada"].ToString());

            var dFechaInicialPeriodoIndicado = (System.DateTime)Session["FechaInicialPeriodo"];
            var dFechaFinalPeriodoIndicado   = (System.DateTime)Session["FechaFinalPeriodo"];

            bool bReconvertirCifrasAntes_01Oct2021      = (bool)Session["ReconvertirCifrasAntes_01Oct2021"];
            bool bExcluirAsientosReconversion_01Oct2021 = (bool)Session["ExcluirAsientosReconversion_01Oct2021"];

            bool bExcluirAsientosTipoCierreAnual = (bool)Session["ExcluirAsientosTipoCierreAnual"];

            // ----------------------------------------------------------------------------------------------------------------------
            // leemos la tabla de monedas para 'saber' cual es la moneda Bs. Nota: la idea es aplicar las opciones de reconversión
            // *solo* a esta moneda
            var monedaNacional_return = Reconversion.Get_MonedaNacional();

            if (monedaNacional_return.error)
            {
                ErrMessage_Span.InnerHtml        = monedaNacional_return.message;
                ErrMessage_Span.Style["display"] = "block";

                return;
            }

            Monedas monedaNacional = monedaNacional_return.moneda;

            Session["monedaNacional"] = monedaNacional.Moneda;
            // ----------------------------------------------------------------------------------------------------------------------

            // --------------------------------------------------------------------------------------------
            // eliminamos el contenido de la tabla temporal
            dbContab_Contab_Entities dbContext = new dbContab_Contab_Entities();

            try
            {
                int cantRegistrosEliminados = dbContext.ExecuteStoreCommand("Delete From Contab_BalanceComprobacion Where NombreUsuario = {0}", Membership.GetUser().UserName);
            }
            catch (Exception ex) {
                dbContext.Dispose();

                Session["Thread_ErrorMessage"] = "Ha ocurrido un error al intentar ejecutar una operación de " +
                                                 "acceso a la base de datos. <br /> El mensaje específico de error es: " + ex.Message +
                                                 "<br /><br />";
                return;
            }

            // -----------------------------------------------------------------------------------------------
            // para evitar que el reporte se genere en forma incompleta, intentamos buscar cuentas que tengan
            // asientos, más no registros en SaldosContables. De haberlas, lo notificamos al usuario y le
            // indicamos que ejecute un cierre contable para corregir esta situación

            string filtroFormParaAsientos = Session["FiltroForma"].ToString();

            filtroFormParaAsientos = filtroFormParaAsientos.Replace("SaldosContables", "Asientos");

            string filtroFormaParaSaldosContables = Session["FiltroForma"].ToString();

            string sSqlQueryString = "Select dAsientos.CuentaContableID From dAsientos " +
                                     "Inner Join Asientos On dAsientos.NumeroAutomatico = Asientos.NumeroAutomatico " +
                                     "Inner Join CuentasContables On dAsientos.CuentaContableID = CuentasContables.ID " +
                                     "Where Asientos.Fecha Between '" + dFechaInicialPeriodoIndicado.ToString("yyyy-MM-dd") + "' And '" +
                                     dFechaFinalPeriodoIndicado.ToString("yyyy-MM-dd") + "' And " +
                                     filtroFormParaAsientos +
                                     " And dAsientos.CuentaContableID Not In " +
                                     "(Select CuentaContableID From SaldosContables Inner Join CuentasContables On SaldosContables.CuentaContableID = CuentasContables.ID " +
                                     "Where " + filtroFormaParaSaldosContables + ")";

            int nCuentasSinSaldo = dbContext.ExecuteStoreQuery <int>(sSqlQueryString).Count();

            if (nCuentasSinSaldo > 0)
            {
                // hay cuentas contables en asientos que no tienen un registro en SaldosContables; lo notificamos al
                // usuario para que corrija esta situación con un cierre contable
                Session["Thread_ErrorMessage"] = "Existen cuentas contables usadas en asientos contables que no tienen " +
                                                 "un registro en la tabla de saldos. <br /> " +
                                                 "Por favor ejecute un cierre contable para el mes (o los meses) de esta consulta, " +
                                                 "para corregir esta situación (y agregar un registro de saldos a las cuentas contables que no lo tienen).";

                Session["Progress_SelectedRecs"] = 0;
                Session["Progress_Completed"]    = 1;
                Session["Progress_Percentage"]   = 0;

                return;
            }

            // hacemos una validación similar a la anterior, pero esta vez buscando cuentas contables que hayan cambiado de detalle a total
            // recuérdese que solo cuentas de tipo detalle pueden recibir asientos; notificamos ésto al usuario, para que corrija esta
            // situación antes de continuar ...
            sSqlQueryString = "Select CuentasContables.CuentaEditada + ' ' + CuentasContables.Descripcion From dAsientos " +
                              "Inner Join Asientos On dAsientos.NumeroAutomatico = Asientos.NumeroAutomatico " +
                              "Inner Join CuentasContables On dAsientos.CuentaContableID = CuentasContables.ID " +
                              "Where Asientos.Fecha Between '" + dFechaInicialPeriodoIndicado.ToString("yyyy-MM-dd") + "' And '" +
                              dFechaFinalPeriodoIndicado.ToString("yyyy-MM-dd") + "' And " +
                              filtroFormParaAsientos +
                              " And CuentasContables.TotDet <> 'D'";

            List <string> query0 = dbContext.ExecuteStoreQuery <string>(sSqlQueryString).ToList();

            errorMessage = "";

            foreach (string cuentaTipoTotal in query0)
            {
                if (string.IsNullOrEmpty(errorMessage))
                {
                    errorMessage = cuentaTipoTotal;
                }
                else
                {
                    errorMessage += ", " + cuentaTipoTotal;
                }
            }

            if (errorMessage != "")
            {
                Session["Thread_ErrorMessage"] = "Aparentemente, existen cuentas contables que han recibido asientos contables en el período indicado y que " +
                                                 "no son de tipo 'detalle'; <br />deben serlo, pues solo cuentas de tipo 'detalle' pueden recibir asientos. <br /> " +
                                                 "Es probable que una cuenta de tipo 'detalle' y que recibió asientos en el período indicado, fue cambiada a tipo 'total' y mantuvo sus asientos.<br /> " +
                                                 "A continuación mostramos las cuentas que están en este estado y que ha detectado este proceso: " + errorMessage;

                Session["Progress_SelectedRecs"] = 0;
                Session["Progress_Completed"]    = 1;
                Session["Progress_Percentage"]   = 0;

                return;
            }
            ;

            // para leer los saldos, debemos determinar el año fiscal de la Cia Contab; un año calendario puede ser
            // 2013 y el año fiscal 2012. Los saldos contables se registran para el año fiscal. Por esta razón,
            // debemos obtenerlo *antes* de hacer el select que sigue
            GetMesFiscalContable MyGetMesFiscalContable = new GetMesFiscalContable(dFechaInicialPeriodoIndicado, ciaContabSeleccionada);

            string sErrorMessage = "";

            // antes usabamos Linq to Sql en vez de EF ...
            ContabSysNet_Web.ModelosDatos.dbContabDataContext ContabDB = new ContabSysNet_Web.ModelosDatos.dbContabDataContext();
            MyGetMesFiscalContable.dbContabDataContext = ContabDB;

            if (!MyGetMesFiscalContable.DeterminarMesFiscal(ref sErrorMessage))
            {
                ContabDB.Dispose();

                ErrMessage_Span.InnerHtml        = sErrorMessage;
                ErrMessage_Span.Style["display"] = "block";

                return;
            }

            int anoFiscalCiaSeleccionada = MyGetMesFiscalContable.AnoFiscal;

            // ------------------------------------------------------------------------------------------------------------------------------
            // como vamos a usar esta conexión mientras se ejecute el ciclo que viene, la abrimos aquí y la cerramos al final ...
            SqlConnection sqlConnection = new SqlConnection();

            sqlConnection.ConnectionString = ConfigurationManager.ConnectionStrings["dbContabConnectionString"].ConnectionString;
            sqlConnection.Open();

            // -----------------------------------------------------------------------------------------------------
            // usamos esta clase para leer los movimientos (debe, haber) para cada cuenta contable y moneda
            DeterminarMovimientoCuentaContable determinarMovimientoCuentaContable = new DeterminarMovimientoCuentaContable(sqlConnection,
                                                                                                                           bExcluirAsientosTipoCierreAnual,
                                                                                                                           bReconvertirCifrasAntes_01Oct2021,
                                                                                                                           bExcluirAsientosReconversion_01Oct2021,
                                                                                                                           dFechaInicialPeriodoIndicado,
                                                                                                                           dFechaFinalPeriodoIndicado, monedaNacional.Moneda);

            // -----------------------------------------------------------------------------------------------------
            // primero determinamos la cantidad de registros, para mostrar progreso al usuario

            // NOTA IMPORTANTE: usamos el año para leer en la tabla SaldosContables SOLO cuentas/monedas/cias que
            // corresopondan al año indicado. Recuérdese que una cuenta/moneda/cia puede tener MUCHOS registros
            // en SaldosContables, uno para cada año. SIN EMBARGO, deberíamos usar el año fiscal y no el año de
            // la fecha inicial del período (año calendario). Lo hacemos así, sabiendo que muy pocas veces ésto
            // tendrá un efecto importante en el proceso. Creo que bastaría con hacer un cierre contable anual en
            // los casos en que el efecto exista

            // ----------------------------------------------------------------------
            // ahora ejecutamos el query para que regrese los rows uno a uno

            // leemos las cuentas contables y todos sus datos de compañías, grupos, monedas, etc. Nótese que leemos
            // SOLO las que tienen un registro en SaldosContables y para el año de la fecha de inicio. La idea es
            // solo traernos cuentas que tengan un registro en SaldosContables, no leer su saldo, lo cual hacemos
            // más adelante, para cada una, en el loop que sigue

            // nótese como cambiamos el Select que sigue, para eliminar la tabla SaldosContables de la
            // sección Inner Join. La razón es que, a veces, puede ocurrir que una cuenta tiene asientos
            // más no tiene un registro en SaldosContables. Imaginamos que ésto puede ocurrir cuando una
            // cuenta se usa por 1ra. vez y no se ha corrido el cierre contable aún para el mes del reporte.

            // ordenamos por CiaContab para que la lista que resulta de aquí también lo esté

            sSqlQueryString = "Select Distinct CuentasContables.ID As CuentaContableID, CuentasContables.Cuenta As CuentaContable, " +
                              "CuentasContables.Descripcion As NombreCuentaContable, " +
                              "tGruposContables.Grupo As GrupoContable, " +
                              "tGruposContables.Descripcion As NombreGrupoContable, " +
                              "IsNull(tGruposContables.OrdenBalanceGeneral, 0) As GrupoContable_OrdenBalance, " +
                              "CuentasContables.Cia As CiaContab, Companias.NombreCorto As NombreCiaContab, " +
                              "CuentaEditada As CuentaContableEditada, Monedas.Moneda, Monedas.Descripcion As " +
                              "NombreMoneda, " + "Monedas.Simbolo As SimboloMoneda, " +
                              "Case NumNiveles When 2 Then Nivel1 When 3 Then Nivel1 + Nivel2 When 4 Then Nivel1 + " +
                              "Nivel2 + Nivel3 " + "When 5 Then Nivel1 + Nivel2 + Nivel3 + Nivel4 When 6 Then Nivel1 + " +
                              "Nivel2 + Nivel3 + Nivel4 + Nivel5 " +
                              "When 7 Then Nivel1 + Nivel2 + Nivel3 + Nivel4 + Nivel5 + Nivel6 End AS " +
                              "CuentaContable_NivelPrevio, " +
                              "Nivel1, Nivel2, Nivel3, Nivel4, Nivel5, Nivel6, NumNiveles " +
                              "From CuentasContables " +
                              "Inner Join Companias On CuentasContables.Cia = Companias.Numero " +
                              "Inner Join SaldosContables On CuentasContables.ID = SaldosContables.CuentaContableID " +
                              "Inner Join Monedas On SaldosContables.Moneda = Monedas.Moneda " +
                              "Inner Join tGruposContables On CuentasContables.Grupo = tGruposContables.Grupo " +
                              "Where CuentasContables.TotDet = 'D' And SaldosContables.Ano = " +
                              anoFiscalCiaSeleccionada.ToString() +
                              " And " + Session["FiltroForma"].ToString() + " Order by CuentasContables.Cia";

            List <CuentaContable_Object> query = dbContext.ExecuteStoreQuery <CuentaContable_Object>(sSqlQueryString).ToList();

            if (query.Count() == 0)
            {
                Session["Thread_ErrorMessage"] = "No existen registros que cumplan el criterio de selección " +
                                                 "(filtro) que Ud. ha indicado. <br /> Para regresar registros, " +
                                                 "Ud. puede intentar un filtro diferente al que ha indicado.";

                Session["Progress_SelectedRecs"] = 0;
                Session["Progress_Completed"]    = 1;
                Session["Progress_Percentage"]   = 0;

                return;
            }

            // ---------------------------------------------------------------------------------------------
            // variables usadas para mostrar el meter en la página ...
            int nCantidadRegistros = query.Count();

            int nRegistroActual     = 0;
            int nProgreesPercentaje = 0;

            string nombreUsuario = Membership.GetUser().UserName;

            Session["Progress_SelectedRecs"] = 0;
            // ---------------------------------------------------------------------------------------------

            List <BalanceComprobacion_Item> MyBalanceComprobacion_Lista = new List <BalanceComprobacion_Item>();
            BalanceComprobacion_Item        MyBalanceComprobacion_Record;

            foreach (CuentaContable_Object MyComprobanteContable_Query in query)
            {
                MyBalanceComprobacion_Record = new BalanceComprobacion_Item();

                MyBalanceComprobacion_Record.CuentaContableID          = MyComprobanteContable_Query.CuentaContableID;
                MyBalanceComprobacion_Record.Moneda                    = MyComprobanteContable_Query.Moneda;
                MyBalanceComprobacion_Record.NivelPrevioCuentaContable = MyComprobanteContable_Query.CuentaContable_NivelPrevio;
                MyBalanceComprobacion_Record.Cia = MyComprobanteContable_Query.CiaContab;

                // nótese como agregamos todos los niveles 'previos' de la cuenta, para poder totalizar por éstos en el reporte ...
                switch (MyComprobanteContable_Query.NumNiveles)
                {
                case 2:
                    MyBalanceComprobacion_Record.nivel1 = MyComprobanteContable_Query.Nivel1;
                    break;

                case 3:
                    MyBalanceComprobacion_Record.nivel1 = MyComprobanteContable_Query.Nivel1;
                    MyBalanceComprobacion_Record.nivel2 = MyBalanceComprobacion_Record.nivel1 + MyComprobanteContable_Query.Nivel2;
                    break;

                case 4:
                    MyBalanceComprobacion_Record.nivel1 = MyComprobanteContable_Query.Nivel1;
                    MyBalanceComprobacion_Record.nivel2 = MyBalanceComprobacion_Record.nivel1 + MyComprobanteContable_Query.Nivel2;
                    MyBalanceComprobacion_Record.nivel3 = MyBalanceComprobacion_Record.nivel2 + MyComprobanteContable_Query.Nivel3;
                    break;

                case 5:
                    MyBalanceComprobacion_Record.nivel1 = MyComprobanteContable_Query.Nivel1;
                    MyBalanceComprobacion_Record.nivel2 = MyBalanceComprobacion_Record.nivel1 + MyComprobanteContable_Query.Nivel2;
                    MyBalanceComprobacion_Record.nivel3 = MyBalanceComprobacion_Record.nivel2 + MyComprobanteContable_Query.Nivel3;
                    MyBalanceComprobacion_Record.nivel4 = MyBalanceComprobacion_Record.nivel3 + MyComprobanteContable_Query.Nivel4;
                    break;

                case 6:
                    MyBalanceComprobacion_Record.nivel1 = MyComprobanteContable_Query.Nivel1;
                    MyBalanceComprobacion_Record.nivel2 = MyBalanceComprobacion_Record.nivel1 + MyComprobanteContable_Query.Nivel2;
                    MyBalanceComprobacion_Record.nivel3 = MyBalanceComprobacion_Record.nivel2 + MyComprobanteContable_Query.Nivel3;
                    MyBalanceComprobacion_Record.nivel4 = MyBalanceComprobacion_Record.nivel3 + MyComprobanteContable_Query.Nivel4;
                    MyBalanceComprobacion_Record.nivel5 = MyBalanceComprobacion_Record.nivel4 + MyComprobanteContable_Query.Nivel5;
                    break;

                case 7:
                    MyBalanceComprobacion_Record.nivel1 = MyComprobanteContable_Query.Nivel1;
                    MyBalanceComprobacion_Record.nivel2 = MyBalanceComprobacion_Record.nivel1 + MyComprobanteContable_Query.Nivel2;
                    MyBalanceComprobacion_Record.nivel3 = MyBalanceComprobacion_Record.nivel2 + MyComprobanteContable_Query.Nivel3;
                    MyBalanceComprobacion_Record.nivel4 = MyBalanceComprobacion_Record.nivel3 + MyComprobanteContable_Query.Nivel4;
                    MyBalanceComprobacion_Record.nivel5 = MyBalanceComprobacion_Record.nivel4 + MyComprobanteContable_Query.Nivel5;
                    MyBalanceComprobacion_Record.nivel6 = MyBalanceComprobacion_Record.nivel5 + MyComprobanteContable_Query.Nivel6;
                    break;
                }

                MyBalanceComprobacion_Lista.Add(MyBalanceComprobacion_Record);

                // --------------------------------------------------------------------------------------
                // ... para reportar el progreso al usuario; la página ejecuta un ws que lee el valor de
                // estas session variables
                nRegistroActual    += 1;
                nProgreesPercentaje = nRegistroActual * 100 / nCantidadRegistros;

                Session["Progress_Percentage"]   = nProgreesPercentaje;
                Session["Progress_SelectedRecs"] = (int)Session["Progress_SelectedRecs"] + 1;
            }

            // ---------------------------------------------------------------------------------
            // recorremos la lista para determinar saldo anterior, debe, haber y saldo actual

            // -----------------------------------------------------------------
            // determinamos la cantidad de registros para el progress al usuario
            nCantidadRegistros = MyBalanceComprobacion_Lista.Count();
            // -----------------------------------------------------------------

            nRegistroActual = 0;
            Session["Progress_Percentage"] = 0;

            int nCiaContabAnterior = -999999;

            int    nMesFiscal     = 0;
            int    nAnoFiscal     = 0;
            int    nMesCalendario = 0;
            int    nAnoCalendario = 0;
            string sNombreMes     = "";

            System.DateTime dFechaSaldoInicial;

            Session["Progress_SelectedRecs"] = 0;

            foreach (BalanceComprobacion_Item MyBalanceComprobacion_Record2 in MyBalanceComprobacion_Lista.OrderBy(b => b.Cia))
            {
                if (MyBalanceComprobacion_Record2.Cia != nCiaContabAnterior)
                {
                    // buscamos el mes y año fiscal solo cuando cambian las compañías
                    MyGetMesFiscalContable = new GetMesFiscalContable(dFechaInicialPeriodoIndicado, MyBalanceComprobacion_Record2.Cia);

                    sErrorMessage = "";
                    MyGetMesFiscalContable.dbContabDataContext = ContabDB;
                    if (!MyGetMesFiscalContable.DeterminarMesFiscal(ref sErrorMessage))
                    {
                        ContabDB.Dispose();

                        ErrMessage_Span.InnerHtml        = sErrorMessage;
                        ErrMessage_Span.Style["display"] = "block";

                        return;
                    }

                    nMesFiscal         = MyGetMesFiscalContable.MesFiscal;
                    nAnoFiscal         = MyGetMesFiscalContable.AnoFiscal;
                    nMesCalendario     = MyGetMesFiscalContable.MesCalendario;
                    nAnoCalendario     = MyGetMesFiscalContable.AnoCalendario;
                    sNombreMes         = MyGetMesFiscalContable.NombreMes;
                    dFechaSaldoInicial = MyGetMesFiscalContable.FechaSaldo;

                    nCiaContabAnterior = MyBalanceComprobacion_Record2.Cia;
                }

                // determinamos el saldo anterior de cada cuenta (GetSaldoContable es una clase que está en: old_app_code/Generales2.cs)
                GetSaldoContable MyGetSaldoContable = new GetSaldoContable(MyBalanceComprobacion_Record2.CuentaContableID,
                                                                           nMesFiscal,
                                                                           nAnoFiscal,
                                                                           dFechaInicialPeriodoIndicado,
                                                                           MyBalanceComprobacion_Record2.Moneda,
                                                                           MyBalanceComprobacion_Record2.Cia, bReconvertirCifrasAntes_01Oct2021, monedaNacional.Moneda);

                MyGetSaldoContable.bLeerSaldoCuenta();

                decimal nSaldoAnteriorContable = MyGetSaldoContable.SaldoAnterior;

                MyBalanceComprobacion_Record2.SaldoAnterior = nSaldoAnteriorContable;

                // este método lee los movimientos para la cuenta, la moneda y el período
                var result = determinarMovimientoCuentaContable.leerMovimientoCuentaContable(MyBalanceComprobacion_Record2.CuentaContableID, MyBalanceComprobacion_Record2.Moneda);

                MyBalanceComprobacion_Record2.Debe  = result.sumDebe;
                MyBalanceComprobacion_Record2.Haber = result.sumHaber;
                MyBalanceComprobacion_Record2.CantidadMovimientos = result.recCount;

                // --------------------------------------------------------------------------------------------------------------------
                // por último, leemos la descripción del 'nivel previo' de la cuenta
                string selectDescripcionNivelPrevio = "Select Descripcion From CuentasContables Where Cuenta = {0} And Cia = {1}";

                object[] parameters = { MyBalanceComprobacion_Record2.NivelPrevioCuentaContable, MyBalanceComprobacion_Record2.Cia };
                string   sCuentaContable_NivelPrevio_Descripcion = dbContext.ExecuteStoreQuery <string>(selectDescripcionNivelPrevio, parameters).FirstOrDefault();

                MyBalanceComprobacion_Record2.NivelPrevioCuentaContable_Nombre = sCuentaContable_NivelPrevio_Descripcion;
                MyBalanceComprobacion_Record2.SaldoActual = MyBalanceComprobacion_Record2.SaldoAnterior + MyBalanceComprobacion_Record2.Debe - MyBalanceComprobacion_Record2.Haber;

                // --------------------------------------------------------------------------------------
                // para mostrar el progreso al usuario

                nRegistroActual    += 1;
                nProgreesPercentaje = nRegistroActual * 100 / nCantidadRegistros;

                Session["Progress_Percentage"]   = nProgreesPercentaje;
                Session["Progress_SelectedRecs"] = (int)Session["Progress_SelectedRecs"] + 1;
            }

            // tenemos los niveles 'previos' de cada cuenta; vamos a crear una lista con las descripciones de cada cuenta, para luego
            // leer las mismas y completar los niveles previos en la lista. Para cada nivel, ej: 0101002, quedará así: 0101002 - <su descripción> ...

            var queryCuentasContables = dbContext.CuentasContables.Where(c => c.TotDet == "T" && c.Cia == ciaContabSeleccionada).Select(c => new { c.Cuenta, c.Descripcion });
            List <Cuenta_Nombre> listaCuentasYNombres = new List <Cuenta_Nombre>();

            foreach (var cuenta in queryCuentasContables)
            {
                listaCuentasYNombres.Add(new Cuenta_Nombre {
                    cuenta = cuenta.Cuenta, descripcion = cuenta.Descripcion
                });
            }

            // ahora recorremos la lista y buscamos la descripción de cada cuenta contable
            foreach (BalanceComprobacion_Item item in MyBalanceComprobacion_Lista)
            {
                if (item.nivel1 != null)
                {
                    if (listaCuentasYNombres.Where(c => c.cuenta == item.nivel1).Count() > 0)
                    {
                        item.nivel1 += " - " + listaCuentasYNombres.Where(c => c.cuenta == item.nivel1).First().descripcion;
                    }
                }

                if (item.nivel2 != null)
                {
                    if (listaCuentasYNombres.Where(c => c.cuenta == item.nivel2).Count() > 0)
                    {
                        item.nivel2 += " - " + listaCuentasYNombres.Where(c => c.cuenta == item.nivel2).First().descripcion;
                    }
                }

                if (item.nivel3 != null)
                {
                    if (listaCuentasYNombres.Where(c => c.cuenta == item.nivel3).Count() > 0)
                    {
                        item.nivel3 += " - " + listaCuentasYNombres.Where(c => c.cuenta == item.nivel3).First().descripcion;
                    }
                }

                if (item.nivel4 != null)
                {
                    if (listaCuentasYNombres.Where(c => c.cuenta == item.nivel4).Count() > 0)
                    {
                        item.nivel4 += " - " + listaCuentasYNombres.Where(c => c.cuenta == item.nivel4).First().descripcion;
                    }
                }

                if (item.nivel5 != null)
                {
                    if (listaCuentasYNombres.Where(c => c.cuenta == item.nivel5).Count() > 0)
                    {
                        item.nivel5 += " - " + listaCuentasYNombres.Where(c => c.cuenta == item.nivel5).First().descripcion;
                    }
                }

                if (item.nivel6 != null)
                {
                    if (listaCuentasYNombres.Where(c => c.cuenta == item.nivel6).Count() > 0)
                    {
                        item.nivel6 += " - " + listaCuentasYNombres.Where(c => c.cuenta == item.nivel6).First().descripcion;
                    }
                }
            }

            // agregamos el contenido de la lista a la tabla
            Contab_BalanceComprobacion contabBalanceComprobacionItem;

            foreach (BalanceComprobacion_Item item in MyBalanceComprobacion_Lista)
            {
                contabBalanceComprobacionItem = new Contab_BalanceComprobacion()
                {
                    CuentaContableID                       = item.CuentaContableID,
                    Moneda                                 = item.Moneda,
                    CuentaContable_NivelPrevio             = item.NivelPrevioCuentaContable,
                    CuentaContable_NivelPrevio_Descripcion = item.NivelPrevioCuentaContable_Nombre,
                    nivel1                                 = item.nivel1,
                    nivel2                                 = item.nivel2,
                    nivel3                                 = item.nivel3,
                    nivel4                                 = item.nivel4,
                    nivel5                                 = item.nivel5,
                    nivel6                                 = item.nivel6,
                    SaldoAnterior                          = item.SaldoAnterior,
                    Debe                = item.Debe,
                    Haber               = item.Haber,
                    SaldoActual         = item.SaldoActual,
                    CantidadMovimientos = item.CantidadMovimientos,
                    NombreUsuario       = nombreUsuario
                };

                dbContext.Contab_BalanceComprobacion.AddObject(contabBalanceComprobacionItem);
            }

            try
            {
                dbContext.SaveChanges();
            }
            catch (Exception ex)
            {
                errorMessage = ex.Message;
                if (ex.InnerException != null)
                {
                    errorMessage += "<br />" + ex.InnerException.Message;
                }

                Session["Thread_ErrorMessage"] = "Ha ocurrido un error al intentar ejecutar una operación de " +
                                                 "acceso a la base de datos. <br /> El mensaje específico de error es: " +
                                                 errorMessage + "<br />";

                Session["Progress_Completed"]  = 1;
                Session["Progress_Percentage"] = 0;

                return;
            }

            // ------------------------------------------------------------------------------------------
            // por último, eliminamos las cuentas seleccionadas de acuerdo al criterio indicado en las opciones
            if (!(bool)Session["MostrarCuentasSinSaldoYSinMvtos"])
            {
                dbContext.ExecuteStoreCommand("Delete From Contab_BalanceComprobacion Where SaldoAnterior = 0 And CantidadMovimientos = 0 And NombreUsuario = {0}", nombreUsuario);
            }

            if (!(bool)Session["MostrarCuentasConSaldoYSinMvtos"])
            {
                dbContext.ExecuteStoreCommand("Delete From Contab_BalanceComprobacion Where SaldoAnterior <> 0 And CantidadMovimientos = 0 And NombreUsuario = {0}", nombreUsuario);
            }

            if (!(bool)Session["MostrarCuentasSaldosEnCero"])
            {
                dbContext.ExecuteStoreCommand("Delete From Contab_BalanceComprobacion Where SaldoAnterior = 0 And SaldoActual = 0 And NombreUsuario = {0}", nombreUsuario);
            }

            if (!(bool)Session["MostrarCuentasSaldoFinalEnCero"])
            {
                dbContext.ExecuteStoreCommand("Delete From Contab_BalanceComprobacion Where SaldoActual = 0 And NombreUsuario = {0}", nombreUsuario);
            }

            dbContext.Dispose();

            // -----------------------------------------------------
            // por último, inicializamos las variables que se usan
            // para mostrar el progreso de la tarea
            Session["Progress_Completed"]  = 1;
            Session["Progress_Percentage"] = 0;
            // -----------------------------------------------------
        }
Пример #6
0
        public bool ObtenerNumeroAsientoContab(DateTime fechaAsiento, int ciaContab, string tipoAsiento,
                                               out short numeroAsientoContab, out string errorMessage)
        {
            // esta función determina y regresa un número de asiento Contab. Nótese que el número determinado
            // depende de si se genera por grupos de tipo o no. Esto lo determina un flag en ParametrosContab:
            // NumeracionAsientosSeparadaFlag.

            // nótese como, lamentablemente, tenemos que crear aquí un nuevo context, pues vamos a actualizar AsientosID
            // cada vez que ejecutemos la función; esto evitará que se generen números duplicados si otros usuarios
            // graban asientos contables en forma simultanea a la ejecución de esta función ...

            dbContab_Contab_Entities context = new dbContab_Contab_Entities();

            errorMessage        = "";
            numeroAsientoContab = 0;

            short nMesCalendario = (short)fechaAsiento.Month;
            short nAnoCalendario = (short)fechaAsiento.Year;

            Compania companiaContab = context.Companias.Where(c => c.Numero == ciaContab).FirstOrDefault();

            if (companiaContab == null)
            {
                errorMessage = " ... error inesperado: no pudimos leer la compañía Contab asociada al " +
                               "asiento contable.";
                return(false);
            }

            if (companiaContab.ParametrosContab == null)
            {
                errorMessage = " ... error inesperado: no pudimos leer los parámetros de la compañía Contab " +
                               "en la tabla Parametros Contab.";
                return(false);
            }

            // lo primero que hacemos es determinar si el número se genera de acuerdo al tipo

            bool?bNumeracionSeparadaPorTipo = companiaContab.ParametrosContab.NumeracionAsientosSeparadaFlag;


            if (bNumeracionSeparadaPorTipo == null)
            {
                errorMessage = "Error: aparentemente, no se ha definido si la numeración de los asientos es o " +
                               "no separada de acuerdo a su tipo.<br /><br />" +
                               "Por favor abra la tabla 'Parámetros' en Contab y defina un valor para este item.";

                return(false);
            }

            if (!bNumeracionSeparadaPorTipo.Value)
            {
                // la númeración NO ES separada de acuerdo al tipo del asiento. La determinación del número
                // es más simple

                // leemos el número del asiento de la tabla AsientosId

                AsientosId MyAsientosId = context.AsientosIds.Where(a => a.Mes == nMesCalendario && a.Ano == nAnoCalendario && a.Cia == ciaContab).FirstOrDefault();

                if (MyAsientosId == null)
                {
                    // no existe un registro en la tabla para el mes, año y cia. Lo creamos y asumimos 1
                    // como número

                    numeroAsientoContab = 1;

                    AsientosId MyAsientosId_Nuevo = new AsientosId();

                    MyAsientosId_Nuevo.Mes    = Convert.ToInt16(nMesCalendario);
                    MyAsientosId_Nuevo.Ano    = Convert.ToInt16(nAnoCalendario);
                    MyAsientosId_Nuevo.Cia    = ciaContab;
                    MyAsientosId_Nuevo.Numero = 2;

                    context.AsientosIds.AddObject(MyAsientosId_Nuevo);
                }
                else
                {
                    numeroAsientoContab  = (short)MyAsientosId.Numero;
                    MyAsientosId.Numero += 1;
                }
            }
            else
            {
                // leemos el grupo de la tabla TiposDeAsiento
                // leemos el número del asiento de la tabla AsientosIdPorGrupo
                TiposDeAsiento tipoAsientoContable = (from t in context.TiposDeAsientoes
                                                      where t.Tipo == tipoAsiento
                                                      select t).FirstOrDefault();

                if (tipoAsientoContable.tGruposDeTiposDeAsiento == null)
                {
                    errorMessage = "Error: aparentemente, no se ha definido el Grupo que corresponde al tipo " +
                                   "de asientos que Ud. ha indicado para el asiento contable.<br /><br />" +
                                   "Como la numeración de los asientos contables es separada de acuerdo a su tipo " +
                                   "(según está ahora definido en el sistema Contab), cada tipo debe corresponder " +
                                   "a un grupo.<br /><br />" +
                                   "Por favor abra la tabla Tipos de Asiento en Contab y " +
                                   "defina un valor para este item.";

                    return(false);
                }

                AsientosIdPorGrupo MyAsientosIdPorGrupo = (from aidg in context.AsientosIdPorGrupoes
                                                           where aidg.Mes == nMesCalendario &&
                                                           aidg.Ano == nAnoCalendario &&
                                                           aidg.Grupo == tipoAsientoContable.tGruposDeTiposDeAsiento.Grupo &&
                                                           aidg.Cia == ciaContab
                                                           select aidg).SingleOrDefault();

                if (MyAsientosIdPorGrupo == null)
                {
                    // no existe un registro en la tabla para el mes, año y cia. Buscamos el número INICIAL
                    // en la tabla tGruposDeTiposDeAsiento

                    var MyGrupoTipoAsiento = (from g in context.tGruposDeTiposDeAsientoes
                                              where g.Grupo == tipoAsientoContable.tGruposDeTiposDeAsiento.Grupo
                                              select g).FirstOrDefault();

                    if (MyGrupoTipoAsiento == null || MyGrupoTipoAsiento.NumeroInicial == null)
                    {
                        errorMessage = "Error: aparentemente, no se ha definido el Grupo que corresponde al " +
                                       "tipo de asientos que Ud. ha indicado para el asiento contable.<br /><br />" +
                                       "Como la numeración de los asientos contables es separada de acuerdo a su tipo " +
                                       "(según está ahora definido en el sistema Contab), cada tipo debe " +
                                       "corresponder a un grupo.<br /><br />" +
                                       "Por favor abra la tabla Tipos de Asiento en Contab y " +
                                       "defina un valor para este item;<br /><br />" +
                                       "o, abra la tabla Grupos de Tipos de Asiento y defina un grupo y un " +
                                       "número de inicio para este grupo.";

                        return(false);
                    }

                    numeroAsientoContab = (short)MyGrupoTipoAsiento.NumeroInicial;

                    // nótese como usamos un nuevo context, para no interferir con la operación que llama este
                    // método (ie: Inserting)

                    AsientosIdPorGrupo MyAsientosIdPorGrupo_Nuevo = new AsientosIdPorGrupo();

                    MyAsientosIdPorGrupo_Nuevo.Mes    = Convert.ToInt16(nMesCalendario);
                    MyAsientosIdPorGrupo_Nuevo.Ano    = Convert.ToInt16(nAnoCalendario);
                    MyAsientosIdPorGrupo_Nuevo.Grupo  = tipoAsientoContable.tGruposDeTiposDeAsiento.Grupo;
                    MyAsientosIdPorGrupo_Nuevo.Cia    = ciaContab;
                    MyAsientosIdPorGrupo_Nuevo.Numero = MyGrupoTipoAsiento.NumeroInicial + 1;

                    context.AsientosIdPorGrupoes.AddObject(MyAsientosIdPorGrupo);
                }
                else
                {
                    numeroAsientoContab          = (short)MyAsientosIdPorGrupo.Numero.Value;
                    MyAsientosIdPorGrupo.Numero += 1;
                }
            }

            try
            {
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                errorMessage = "Error: hemos obtenido un error al intentar efectuar una operación en la " +
                               "base de datos.<br /><br />" +
                               "El mensaje específico de error es: <br /><br />" + ex.Message;

                if (ex.InnerException != null)
                {
                    errorMessage += ex.InnerException.Message;
                }

                context = null;
                return(false);
            }

            context = null;
            return(true);
        }
Пример #7
0
        public bool CopiarAsientosContables(string filter, string filter_subQuery,
                                            string userName, int ciaTarget, string multiplicarPor_textBox,
                                            string dividirPor_textBox, out int cantidadAsientosCopiados, out string errorMessage)
        {
            errorMessage             = "";
            cantidadAsientosCopiados = 0;

            // sabemos que ambos controles, si tienen un valor, debe ser numérico; nota: también pueden venir vacíos ...
            double multiplicarPor = multiplicarPor_textBox.Trim() != "" ? Convert.ToDouble(multiplicarPor_textBox) : 1;
            double dividirPor     = dividirPor_textBox.Trim() != "" ? Convert.ToDouble(dividirPor_textBox) : 1;

            string filtroAsientosContables = "";

            if (filter_subQuery == null || filter_subQuery == "1 = 1")
            {
                // el usuario no usó criterio por cuenta contable o más de 2 decimales; no usamos sub-query
                filtroAsientosContables = filter;
            }
            else
            {
                // si el usuario indica cuentas contables en su filtro, debemos hacer un subquery para que el resultado final
                // solo incluya asientos que las tengan ...
                filtroAsientosContables = filter +
                                          " And (Asientos.NumeroAutomatico In (SELECT Asientos.NumeroAutomatico FROM Asientos " +
                                          "Left Outer Join dAsientos On Asientos.NumeroAutomatico = dAsientos.NumeroAutomatico " +
                                          "Left Outer Join CuentasContables On CuentasContables.ID = dAsientos.CuentaContableID " +
                                          "Where " + filter + " And " + filter_subQuery + "))";
            }

            // como el filtro viene para Sql, y no para linq to entities, intentamos leer los asientos usando Sql ...
            var query = _context.ExecuteStoreQuery <Asiento>("Select * from Asientos Where" + filtroAsientosContables + " Order By Asientos.Fecha, Asientos.Numero");

            int mesAnterior = -99;
            int anoAnterior = -99;

            short mesFiscal = 0;
            short anoFiscal = 0;

            Asiento  asiento;
            dAsiento partida;

            foreach (Asiento a in query)
            {
                if (mesAnterior != a.Fecha.Month || anoAnterior != a.Fecha.Year)
                {
                    // para cada mes diferente, validamos que el mes no esté cerrado en la compañía 'target' ...
                    if (!ValidarMesCerradoEnContab(a.Fecha, ciaTarget, out mesFiscal, out anoFiscal, out errorMessage))
                    {
                        return(false);
                    }

                    mesAnterior = a.Fecha.Month;
                    anoAnterior = a.Fecha.Year;
                }

                // determinamos un número para el asiento contable en ciaTarget ...
                short numeroAsientoContab = 0;

                if (!ObtenerNumeroAsientoContab(a.Fecha, ciaTarget, a.Tipo, out numeroAsientoContab, out errorMessage))
                {
                    return(false);
                }

                asiento = new Asiento();

                asiento.Mes                        = a.Mes;
                asiento.Ano                        = a.Ano;
                asiento.Numero                     = numeroAsientoContab;
                asiento.Fecha                      = a.Fecha;
                asiento.Tipo                       = a.Tipo;
                asiento.Descripcion                = a.Descripcion;
                asiento.Moneda                     = a.Moneda;
                asiento.MonedaOriginal             = a.MonedaOriginal;
                asiento.ConvertirFlag              = a.ConvertirFlag;
                asiento.FactorDeCambio             = a.FactorDeCambio;
                asiento.ProvieneDe                 = a.ProvieneDe;
                asiento.Ingreso                    = DateTime.Now;
                asiento.UltAct                     = DateTime.Now;
                asiento.CopiableFlag               = a.CopiableFlag;
                asiento.AsientoTipoCierreAnualFlag = false;         // nótese como nunca asumimos que un asiento de cierre anual lo es también en Cia Target ...
                asiento.MesFiscal                  = mesFiscal;
                asiento.AnoFiscal                  = anoFiscal;
                asiento.Usuario                    = userName;
                asiento.Cia                        = ciaTarget;

                // leemos las partidas del asiento y las copiamos al nuevo ...
                var partidas = _context.dAsientos.Where(p => p.NumeroAutomatico == a.NumeroAutomatico).OrderBy(p => p.Partida);

                foreach (dAsiento p in partidas)
                {
                    partida = new dAsiento();

                    // para cada cuenta contable, debemos buscar una idéntica en la compañía target ...
                    int?cuentaContableCiaTarget = _context.CuentasContables.Where(c => c.Cuenta == p.CuentasContable.Cuenta).
                                                  Where(c => c.Cia == ciaTarget).
                                                  Select(c => c.ID).
                                                  FirstOrDefault();

                    if (cuentaContableCiaTarget == null || cuentaContableCiaTarget == 0)
                    {
                        errorMessage = "<b>Error:</b> no hemos podido leer la cuenta contable '" + p.CuentasContable.Cuenta + "' en la compañía indicada.";
                        return(false);
                    }

                    partida.Partida          = p.Partida;
                    partida.CuentaContableID = cuentaContableCiaTarget.Value;
                    partida.Descripcion      = p.Descripcion;
                    partida.Referencia       = p.Referencia;

                    // multiplicamos y dividimos por lo montos que indique el usuario; nota: si no indica estos montos, usamos 1 ...
                    partida.Debe  = Convert.ToDecimal((Convert.ToDouble(p.Debe) * multiplicarPor) / dividirPor);
                    partida.Haber = Convert.ToDecimal((Convert.ToDouble(p.Haber) * multiplicarPor) / dividirPor);

                    asiento.dAsientos.Add(partida);
                }

                _context.Asientos.AddObject(asiento);
                cantidadAsientosCopiados++;
            }

            try
            {
                _context.SaveChanges();
            }
            catch (Exception ex)
            {
                errorMessage = "<b>Error:</b> hemos obtenido un error al intentar efectuar una operación en la " +
                               "base de datos.<br /><br />" +
                               "El mensaje específico de error es: <br /><br />" + ex.Message;

                if (ex.InnerException != null)
                {
                    errorMessage += "<br />" + ex.InnerException.Message;
                }

                return(false);
            }
            finally
            {
                _context = null;
            }

            return(true);
        }
        public HttpResponseMessage AgregarMontosEstimados([FromBody] MontosEstimados_Agregar_Parametro data)
        {
            if (!User.Identity.IsAuthenticated)
            {
                var errorResult = new
                {
                    ErrorFlag     = true,
                    ResultMessage = "Error: por favor haga un login a esta aplicación, y luego regrese a ejecutar esta función."
                };

                return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
            }

            if (data.AnoCopiarDesde != null && string.IsNullOrEmpty(data.MontosEjecutadosEstimados))
            {
                var errorResult = new
                {
                    ErrorFlag     = true,
                    ResultMessage = "<b>Error:</b> si Ud. desea inicializar los montos estimados en base a un año, " +
                                    "debe indicar el <em>tipo de monto base</em>: estimados o ejecutados."
                };

                return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
            }

            try
            {
                dbContab_Contab_Entities context = new dbContab_Contab_Entities();

                int itemsLeidos     = 0;
                int itemsAgregados  = 0;
                int itemsYaExistian = 0;

                string message = "";

                // nos aseguramos de leer solo códigos para la cía seleccionada ...
                var query = context.Presupuesto_Codigos.Include("Presupuesto_Montos").Where(p => p.CiaContab == data.CiaContabSeleccionada);

                // leemos usando el filtro o año/moneda (nota: si viene un filtro es por 'aplicarSoloItemsSeleccionados'; de otra forma, el filtro es nulls

                // leemos solo 'no grupos' y 'no suspendidos'
                query = query.Where(c => !c.GrupoFlag);
                query = query.Where(c => !c.SuspendidoFlag);

                Presupuesto_Montos montoEstimadoAnoBase = null;        // para leer los montos estimados de un año 'base', si el usuario lo indicó
                Presupuesto_Montos montoEstimado;

                foreach (var codigoPresupuesto in query)
                {
                    // intentamos leer un año monto 'base', para usar como base cuando agreguemos los montos

                    if (data.AnoCopiarDesde != null)
                    {
                        montoEstimadoAnoBase = context.Presupuesto_Montos.Where(m => m.CiaContab == data.CiaContabSeleccionada).
                                               Where(m => m.Moneda == data.MonedaID).
                                               Where(m => m.Ano == data.AnoCopiarDesde).
                                               Where(m => m.CodigoPresupuesto == codigoPresupuesto.Codigo).
                                               FirstOrDefault();
                    }



                    montoEstimado = codigoPresupuesto.Presupuesto_Montos.Where(m => m.Moneda == data.MonedaID).
                                    Where(m => m.Ano == data.Ano).
                                    FirstOrDefault();

                    if (montoEstimadoAnoBase != null)
                    {
                        // el usuario indicó un año 'base' y existe un monto para este año y el código tratado

                        if (montoEstimado != null)
                        {
                            // el monto estimado existe para el código de presupuesto; lo actualizamos en base a los montos del año base
                            // nótese como usamos los montos estimados o ejecutados, según la definición que el usuario haya indicado
                            if (data.ActualizarMontosSiExisten.HasValue && data.ActualizarMontosSiExisten.Value)
                            {
                                if (data.MontosEjecutadosEstimados == "ejecutados")
                                {
                                    montoEstimado.Mes01_Est = montoEstimadoAnoBase.Mes01_Eje != null ? montoEstimadoAnoBase.Mes01_Eje : 0;
                                    montoEstimado.Mes02_Est = montoEstimadoAnoBase.Mes02_Eje != null ? montoEstimadoAnoBase.Mes02_Eje : 0;
                                    montoEstimado.Mes03_Est = montoEstimadoAnoBase.Mes03_Eje != null ? montoEstimadoAnoBase.Mes03_Eje : 0;
                                    montoEstimado.Mes04_Est = montoEstimadoAnoBase.Mes04_Eje != null ? montoEstimadoAnoBase.Mes04_Eje : 0;
                                    montoEstimado.Mes05_Est = montoEstimadoAnoBase.Mes05_Eje != null ? montoEstimadoAnoBase.Mes05_Eje : 0;
                                    montoEstimado.Mes06_Est = montoEstimadoAnoBase.Mes06_Eje != null ? montoEstimadoAnoBase.Mes06_Eje : 0;
                                    montoEstimado.Mes07_Est = montoEstimadoAnoBase.Mes07_Eje != null ? montoEstimadoAnoBase.Mes07_Eje : 0;
                                    montoEstimado.Mes08_Est = montoEstimadoAnoBase.Mes08_Eje != null ? montoEstimadoAnoBase.Mes08_Eje : 0;
                                    montoEstimado.Mes09_Est = montoEstimadoAnoBase.Mes09_Eje != null ? montoEstimadoAnoBase.Mes09_Eje : 0;
                                    montoEstimado.Mes10_Est = montoEstimadoAnoBase.Mes10_Eje != null ? montoEstimadoAnoBase.Mes10_Eje : 0;
                                    montoEstimado.Mes11_Est = montoEstimadoAnoBase.Mes11_Eje != null ? montoEstimadoAnoBase.Mes11_Eje : 0;
                                    montoEstimado.Mes12_Est = montoEstimadoAnoBase.Mes12_Eje != null ? montoEstimadoAnoBase.Mes12_Eje : 0;
                                }
                                else
                                {
                                    montoEstimado.Mes01_Est = montoEstimadoAnoBase.Mes01_Est != null ? montoEstimadoAnoBase.Mes01_Est : 0;
                                    montoEstimado.Mes02_Est = montoEstimadoAnoBase.Mes02_Est != null ? montoEstimadoAnoBase.Mes02_Est : 0;
                                    montoEstimado.Mes03_Est = montoEstimadoAnoBase.Mes03_Est != null ? montoEstimadoAnoBase.Mes03_Est : 0;
                                    montoEstimado.Mes04_Est = montoEstimadoAnoBase.Mes04_Est != null ? montoEstimadoAnoBase.Mes04_Est : 0;
                                    montoEstimado.Mes05_Est = montoEstimadoAnoBase.Mes05_Est != null ? montoEstimadoAnoBase.Mes05_Est : 0;
                                    montoEstimado.Mes06_Est = montoEstimadoAnoBase.Mes06_Est != null ? montoEstimadoAnoBase.Mes06_Est : 0;
                                    montoEstimado.Mes07_Est = montoEstimadoAnoBase.Mes07_Est != null ? montoEstimadoAnoBase.Mes07_Est : 0;
                                    montoEstimado.Mes08_Est = montoEstimadoAnoBase.Mes08_Est != null ? montoEstimadoAnoBase.Mes08_Est : 0;
                                    montoEstimado.Mes09_Est = montoEstimadoAnoBase.Mes09_Est != null ? montoEstimadoAnoBase.Mes09_Est : 0;
                                    montoEstimado.Mes10_Est = montoEstimadoAnoBase.Mes10_Est != null ? montoEstimadoAnoBase.Mes10_Est : 0;
                                    montoEstimado.Mes11_Est = montoEstimadoAnoBase.Mes11_Est != null ? montoEstimadoAnoBase.Mes11_Est : 0;
                                    montoEstimado.Mes12_Est = montoEstimadoAnoBase.Mes12_Est != null ? montoEstimadoAnoBase.Mes12_Est : 0;
                                }

                                itemsYaExistian++;
                            }
                        }
                        else
                        {
                            // el monto estimado no existe, lo creamos en base al año base

                            montoEstimado = new Presupuesto_Montos();

                            montoEstimado.CodigoPresupuesto = codigoPresupuesto.Codigo;
                            montoEstimado.CiaContab         = codigoPresupuesto.CiaContab;
                            montoEstimado.Moneda            = data.MonedaID;
                            montoEstimado.Ano = data.Ano;

                            if (data.MontosEjecutadosEstimados == "ejecutados")
                            {
                                montoEstimado.Mes01_Est = montoEstimadoAnoBase.Mes01_Eje != null ? montoEstimadoAnoBase.Mes01_Eje : 0;
                                montoEstimado.Mes02_Est = montoEstimadoAnoBase.Mes02_Eje != null ? montoEstimadoAnoBase.Mes02_Eje : 0;
                                montoEstimado.Mes03_Est = montoEstimadoAnoBase.Mes03_Eje != null ? montoEstimadoAnoBase.Mes03_Eje : 0;
                                montoEstimado.Mes04_Est = montoEstimadoAnoBase.Mes04_Eje != null ? montoEstimadoAnoBase.Mes04_Eje : 0;
                                montoEstimado.Mes05_Est = montoEstimadoAnoBase.Mes05_Eje != null ? montoEstimadoAnoBase.Mes05_Eje : 0;
                                montoEstimado.Mes06_Est = montoEstimadoAnoBase.Mes06_Eje != null ? montoEstimadoAnoBase.Mes06_Eje : 0;
                                montoEstimado.Mes07_Est = montoEstimadoAnoBase.Mes07_Eje != null ? montoEstimadoAnoBase.Mes07_Eje : 0;
                                montoEstimado.Mes08_Est = montoEstimadoAnoBase.Mes08_Eje != null ? montoEstimadoAnoBase.Mes08_Eje : 0;
                                montoEstimado.Mes09_Est = montoEstimadoAnoBase.Mes09_Eje != null ? montoEstimadoAnoBase.Mes09_Eje : 0;
                                montoEstimado.Mes10_Est = montoEstimadoAnoBase.Mes10_Eje != null ? montoEstimadoAnoBase.Mes10_Eje : 0;
                                montoEstimado.Mes11_Est = montoEstimadoAnoBase.Mes11_Eje != null ? montoEstimadoAnoBase.Mes11_Eje : 0;
                                montoEstimado.Mes12_Est = montoEstimadoAnoBase.Mes12_Eje != null ? montoEstimadoAnoBase.Mes12_Eje : 0;
                            }
                            else
                            {
                                montoEstimado.Mes01_Est = montoEstimadoAnoBase.Mes01_Est != null ? montoEstimadoAnoBase.Mes01_Est : 0;
                                montoEstimado.Mes02_Est = montoEstimadoAnoBase.Mes02_Est != null ? montoEstimadoAnoBase.Mes02_Est : 0;
                                montoEstimado.Mes03_Est = montoEstimadoAnoBase.Mes03_Est != null ? montoEstimadoAnoBase.Mes03_Est : 0;
                                montoEstimado.Mes04_Est = montoEstimadoAnoBase.Mes04_Est != null ? montoEstimadoAnoBase.Mes04_Est : 0;
                                montoEstimado.Mes05_Est = montoEstimadoAnoBase.Mes05_Est != null ? montoEstimadoAnoBase.Mes05_Est : 0;
                                montoEstimado.Mes06_Est = montoEstimadoAnoBase.Mes06_Est != null ? montoEstimadoAnoBase.Mes06_Est : 0;
                                montoEstimado.Mes07_Est = montoEstimadoAnoBase.Mes07_Est != null ? montoEstimadoAnoBase.Mes07_Est : 0;
                                montoEstimado.Mes08_Est = montoEstimadoAnoBase.Mes08_Est != null ? montoEstimadoAnoBase.Mes08_Est : 0;
                                montoEstimado.Mes09_Est = montoEstimadoAnoBase.Mes09_Est != null ? montoEstimadoAnoBase.Mes09_Est : 0;
                                montoEstimado.Mes10_Est = montoEstimadoAnoBase.Mes10_Est != null ? montoEstimadoAnoBase.Mes10_Est : 0;
                                montoEstimado.Mes11_Est = montoEstimadoAnoBase.Mes11_Est != null ? montoEstimadoAnoBase.Mes11_Est : 0;
                                montoEstimado.Mes12_Est = montoEstimadoAnoBase.Mes12_Est != null ? montoEstimadoAnoBase.Mes12_Est : 0;
                            }


                            codigoPresupuesto.Presupuesto_Montos.Add(montoEstimado);

                            itemsAgregados++;
                        }
                    }
                    else
                    {
                        // el monto para el año base no existe o el usuario no indicó uno (el tratamiendo aplicado es el mismo)

                        if (montoEstimado == null)
                        {
                            // el monto estimado no existe, lo creamos con sus montos en cero

                            montoEstimado = new Presupuesto_Montos();

                            montoEstimado.CodigoPresupuesto = codigoPresupuesto.Codigo;
                            montoEstimado.CiaContab         = codigoPresupuesto.CiaContab;
                            montoEstimado.Moneda            = data.MonedaID;
                            montoEstimado.Ano = data.Ano;

                            montoEstimado.Mes01_Est = 0;
                            montoEstimado.Mes02_Est = 0;
                            montoEstimado.Mes03_Est = 0;
                            montoEstimado.Mes04_Est = 0;
                            montoEstimado.Mes05_Est = 0;
                            montoEstimado.Mes06_Est = 0;
                            montoEstimado.Mes07_Est = 0;
                            montoEstimado.Mes08_Est = 0;
                            montoEstimado.Mes09_Est = 0;
                            montoEstimado.Mes10_Est = 0;
                            montoEstimado.Mes11_Est = 0;
                            montoEstimado.Mes12_Est = 0;

                            codigoPresupuesto.Presupuesto_Montos.Add(montoEstimado);
                            itemsAgregados++;
                        }
                        else
                        {
                            // el monto estimado existe, pero no se ha leído un monto 'base' de otro año;
                            // tan solo revisamos si existen montos en null, para ponerlos en cero ...

                            if (montoEstimado.Mes01_Est == null)
                            {
                                montoEstimado.Mes01_Est = 0;
                            }
                            if (montoEstimado.Mes02_Est == null)
                            {
                                montoEstimado.Mes02_Est = 0;
                            }
                            if (montoEstimado.Mes03_Est == null)
                            {
                                montoEstimado.Mes03_Est = 0;
                            }
                            if (montoEstimado.Mes04_Est == null)
                            {
                                montoEstimado.Mes04_Est = 0;
                            }
                            if (montoEstimado.Mes05_Est == null)
                            {
                                montoEstimado.Mes05_Est = 0;
                            }
                            if (montoEstimado.Mes06_Est == null)
                            {
                                montoEstimado.Mes06_Est = 0;
                            }
                            if (montoEstimado.Mes07_Est == null)
                            {
                                montoEstimado.Mes07_Est = 0;
                            }
                            if (montoEstimado.Mes08_Est == null)
                            {
                                montoEstimado.Mes08_Est = 0;
                            }
                            if (montoEstimado.Mes09_Est == null)
                            {
                                montoEstimado.Mes09_Est = 0;
                            }
                            if (montoEstimado.Mes10_Est == null)
                            {
                                montoEstimado.Mes10_Est = 0;
                            }
                            if (montoEstimado.Mes11_Est == null)
                            {
                                montoEstimado.Mes11_Est = 0;
                            }
                            if (montoEstimado.Mes12_Est == null)
                            {
                                montoEstimado.Mes12_Est = 0;
                            }
                        }
                    }

                    itemsLeidos++;
                }

                context.SaveChanges();

                message = "Ok, " + itemsLeidos.ToString() + " códigos de presupuesto han sido leídos;<br />" +
                          "para éstos, " + itemsAgregados.ToString() + " registros (de montos estimados) han sido agregados, pues no existían; <br /> " +
                          itemsYaExistian.ToString() + " han sido actualizados pues existían.";

                var result = new
                {
                    ErrorFlag     = false,
                    ResultMessage = message
                };

                return(Request.CreateResponse(HttpStatusCode.OK, result));
            }
            catch (Exception ex)
            {
                string message = ex.Message;
                if (ex.InnerException != null)
                {
                    message += "<br />" + ex.InnerException.Message;
                }

                var errorResult = new
                {
                    ErrorFlag     = true,
                    ResultMessage = "Error: se ha producido un error al intentar efectuar una operación en la base de datos.<br />" +
                                    "El mensaje específico de error es: <br />" + message
                };

                return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
            }
        }
        public HttpResponseMessage GrabarItemsEditados([FromUri] int ciaContabSeleccionada, [FromBody] List <MontoEstimadoEditado> data)
        {
            if (!User.Identity.IsAuthenticated)
            {
                var errorResult = new
                {
                    ErrorFlag    = true,
                    ErrorMessage = "Error: por favor haga un login a esta aplicación, y luego regrese a ejecutar esta función."
                };

                return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
            }

            try
            {
                // el criterio es un json, pero viene como un string
                //List<CodigoPresupuestoEditado> codigosPresupuestoEditados = new List<CodigoPresupuestoEditado>();
                //codigosPresupuestoEditados = JsonConvert.DeserializeObject<List<CodigoPresupuestoEditado>>(data);

                dbContab_Contab_Entities context = new dbContab_Contab_Entities();

                var itemsAgregados  = 0;
                var itemsEditados   = 0;
                var itemsEliminados = 0;

                string message = "";

                foreach (var item in data)
                {
                    // -----------------------------------------------------------------------------------------------------------
                    // nótese como validamos cada item usando los atributos que definimos en la clase (poco) ...

                    // Use the ValidationContext to validate the Product model against the product data annotations
                    // before saving it to the database
                    var validationContext = new ValidationContext(item, serviceProvider: null, items: null);
                    var validationResults = new List <ValidationResult>();

                    var isValid = Validator.TryValidateObject(item, validationContext, validationResults, true);

                    // If there are any exceptions, return them in the return result
                    if (!isValid)
                    {
                        foreach (ValidationResult validationResult in validationResults)
                        {
                            if (message == "")
                            {
                                message = "<li>" + validationResult.ErrorMessage + "</li>";
                            }
                            else
                            {
                                message += "<li>" + validationResult.ErrorMessage + "</li>";
                            }
                        }

                        var errorResult = new
                        {
                            ErrorFlag     = true,
                            ResultMessage = "<b>Error:</b> se ha producido un error al intentar efectuar una operación en la base de datos.<br />" +
                                            "<b>El mensaje específico de error es:</b><ul>" + message + "</ul>"
                        };

                        return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
                    }
                    // -----------------------------------------------------------------------------------------------------------


                    if (item.isDeleted.HasValue && item.isDeleted.Value)
                    {
                        var montoEstimado = context.Presupuesto_Montos
                                            .Where(p => p.CodigoPresupuesto == item.Codigo &&
                                                   p.Ano == item.Ano &&
                                                   p.Moneda == item.Moneda &&
                                                   p.CiaContab == ciaContabSeleccionada).
                                            FirstOrDefault();

                        if (montoEstimado != null)
                        {
                            context.Presupuesto_Montos.DeleteObject(montoEstimado);
                            itemsEliminados++;
                        }
                    }
                    ;

                    if (item.isEdited.HasValue && item.isEdited.Value)
                    {
                        var montoEstimado = context.Presupuesto_Montos
                                            .Where(p => p.CodigoPresupuesto == item.Codigo &&
                                                   p.Ano == item.Ano &&
                                                   p.Moneda == item.Moneda &&
                                                   p.CiaContab == ciaContabSeleccionada).
                                            FirstOrDefault();

                        if (montoEstimado != null)
                        {
                            // nótese que cambiamos solo los montos; otros valores (código, ano, moneda y cia) son parte del pk y entity framework
                            // no permite cambiarlos

                            montoEstimado.Mes01_Est = item.Mes01_Est;
                            montoEstimado.Mes02_Est = item.Mes02_Est;
                            montoEstimado.Mes03_Est = item.Mes03_Est;
                            montoEstimado.Mes04_Est = item.Mes04_Est;
                            montoEstimado.Mes05_Est = item.Mes05_Est;
                            montoEstimado.Mes06_Est = item.Mes06_Est;
                            montoEstimado.Mes07_Est = item.Mes07_Est;
                            montoEstimado.Mes08_Est = item.Mes08_Est;
                            montoEstimado.Mes09_Est = item.Mes09_Est;
                            montoEstimado.Mes10_Est = item.Mes10_Est;
                            montoEstimado.Mes11_Est = item.Mes11_Est;
                            montoEstimado.Mes12_Est = item.Mes12_Est;

                            itemsEditados++;
                        }
                    }
                    ;

                    if (item.isNew.HasValue && item.isNew.Value)
                    {
                        var montoEstimado = new Presupuesto_Montos();

                        montoEstimado.CodigoPresupuesto = item.Codigo;
                        montoEstimado.Moneda            = item.Moneda;
                        montoEstimado.Ano       = item.Ano;
                        montoEstimado.CiaContab = ciaContabSeleccionada;

                        montoEstimado.Mes01_Est = item.Mes01_Est;
                        montoEstimado.Mes02_Est = item.Mes02_Est;
                        montoEstimado.Mes03_Est = item.Mes03_Est;
                        montoEstimado.Mes04_Est = item.Mes04_Est;
                        montoEstimado.Mes05_Est = item.Mes05_Est;
                        montoEstimado.Mes06_Est = item.Mes06_Est;
                        montoEstimado.Mes07_Est = item.Mes07_Est;
                        montoEstimado.Mes08_Est = item.Mes08_Est;
                        montoEstimado.Mes09_Est = item.Mes09_Est;
                        montoEstimado.Mes10_Est = item.Mes10_Est;
                        montoEstimado.Mes11_Est = item.Mes11_Est;
                        montoEstimado.Mes12_Est = item.Mes12_Est;

                        context.Presupuesto_Montos.AddObject(montoEstimado);

                        itemsAgregados++;
                    }
                }

                context.SaveChanges();

                message = "Ok, " + itemsAgregados.ToString() + " registros han sido agregados; " +
                          itemsEditados.ToString() + " registros han sido modificados; " +
                          itemsEliminados.ToString() + " registros han sido eliminados. ";

                var result = new
                {
                    ErrorFlag     = false,
                    ResultMessage = message
                };

                return(Request.CreateResponse(HttpStatusCode.OK, result));
            }
            catch (Exception ex)
            {
                string message = ex.Message;
                if (ex.InnerException != null)
                {
                    message += "<br />" + ex.InnerException.Message;
                }

                var errorResult = new
                {
                    ErrorFlag     = true,
                    ResultMessage = "Error: se ha producido un error al intentar efectuar una operación en la base de datos.<br />" +
                                    "El mensaje específico de error es: <br />" + message
                };

                return(Request.CreateResponse(HttpStatusCode.OK, errorResult));
            }
        }