private string Procesar(string sAnoMes, string sMeses, string strNodos)
    {
        string    sResul      = "";
        ArrayList aListCorreo = new ArrayList();

        try
        {
            #region abrir conexión y transacción
            try
            {
                oConn = Conexion.Abrir();
                tr    = Conexion.AbrirTransaccionSerializable(oConn);
            }
            catch (Exception ex)
            {
                if (oConn.State == ConnectionState.Open)
                {
                    Conexion.Cerrar(oConn);
                }
                sResul = "Error@#@" + Errores.mostrarError("Error al abrir la conexión", ex);
                return(sResul);
            }
            #endregion

            PROYECTOSUBNODO.EliminarObraEnCursoDotacion(tr, int.Parse(sAnoMes), strNodos);
            DataSet ds     = PROYECTOSUBNODO.ObtenerProyectosObraEnCursoDotacion(tr, int.Parse(sAnoMes), int.Parse(sMeses), strNodos);
            int     idT325 = 0;
            foreach (DataRow oPSN in ds.Tables[0].Rows)
            {
                idT325 = SEGMESPROYECTOSUBNODO.ExisteSegMesProy(tr, (int)oPSN["t305_idproyectosubnodo"], int.Parse(sAnoMes));
                if (idT325 == 0)
                {
                    idT325 = SEGMESPROYECTOSUBNODO.InsertSiNoExiste(tr, (int)oPSN["t305_idproyectosubnodo"], int.Parse(sAnoMes));
                }

                //Insertamos en el año-mes indicado el importe del saldo obra en curso en negativo.
                DATOECO.Insert(tr, idT325, Constantes.nIdClaseDotacionObraEnCurso, "Dotación-Ajuste Obra en Curso", decimal.Parse(oPSN["Obra_Curso_Acum"].ToString()) * -1, null, null, null);
                //Registramos en la cola de correo
                EncolarCorreo(aListCorreo,
                              oPSN["codred_gestorprod"].ToString(),
                              oPSN["codred_comercialhermes"].ToString(),
                              decimal.Parse(oPSN["Obra_Curso_Acum"].ToString()).ToString("N"),
                              int.Parse(oPSN["t306_idcontrato"].ToString()).ToString("#,###"),
                              oPSN["t377_denominacion"].ToString(),
                              int.Parse(oPSN["t301_idproyecto"].ToString()).ToString("#,###"),
                              oPSN["t301_denominacion"].ToString(),
                              sMeses.ToString()
                              );
            }
            ds.Dispose();

            //    Conexion.CommitTransaccion(tr);
            Conexion.CerrarTransaccion(tr);
            EnviarCorreos(aListCorreo);
            sResul = "OK";
        }
        catch (Exception ex)
        {
            Conexion.CerrarTransaccion(tr);
            sResul = "Error@#@" + Errores.mostrarError("Error al realizar el ajuste de la dotación de la obra en curso.", ex, false);
        }
        finally
        {
            Conexion.Cerrar(oConn);
        }
        return(sResul);
    }
    protected string Grabar(string sSerie, string sNumero, string sImpTot, string sAnoMes, string sClaseEco, string strLineas)
    {
        string   sResul = "", sDesc = "", t376_motivo = "";//, sElementosInsertados = "";
        int      idDatoEcoFact, idDatoEcoCob, nAnoMesFact, nAnoMesCobro, idT305, idT325, t329_idclaseeco = -1;
        int?     t313_idempresa = null;
        int?     t302_idcliente = null;
        DateTime?dtFecha = System.DateTime.Today;
        decimal  dTotalFact = decimal.Parse(sImpTot), dImpLinea, dAux, dCobro;
        bool     bProrratear = false;
        string   sRefCliente = "";

        #region abrir conexión y transacción serializable
        try
        {
            oConn = Conexion.Abrir();
            tr    = Conexion.AbrirTransaccionSerializable(oConn);
        }
        catch (Exception ex)
        {
            if (oConn.State == ConnectionState.Open)
            {
                Conexion.Cerrar(oConn);
            }
            sResul = "Error@#@" + Errores.mostrarError("Error al abrir la conexión", ex);
            return(sResul);
        }
        #endregion

        try
        {
            nAnoMesFact = int.Parse(sAnoMes);
            #region Obtener datos de la primera línea de la factura
            SqlDataReader drLineas = Factura.Lineas(tr, sSerie, int.Parse(sNumero));
            if (drLineas.Read())
            {
                t329_idclaseeco = int.Parse(drLineas["t329_idclaseeco"].ToString());
                t376_motivo     = drLineas["t376_motivo"].ToString();
                if (drLineas["t376_fecha"].ToString() != "")
                {
                    dtFecha = DateTime.Parse(drLineas["t376_fecha"].ToString());
                }
                else
                {
                    dtFecha = null;
                }
                if (drLineas["t313_idempresa"].ToString() != "")
                {
                    t313_idempresa = int.Parse(drLineas["t313_idempresa"].ToString());
                }
                else
                {
                    t313_idempresa = null;
                }
                if (drLineas["t302_idcliente"].ToString() != "")
                {
                    t302_idcliente = int.Parse(drLineas["t302_idcliente"].ToString());
                }
                else
                {
                    t302_idcliente = null;
                }

                if (drLineas["t376_refcliente"].ToString() != "")
                {
                    sRefCliente = drLineas["t376_refcliente"].ToString();
                }
            }
            drLineas.Close();
            drLineas.Dispose();
            #endregion
            #region Cargar Cobros agrupados por mes en el array slCobros
            ArrayList     slCobros = new ArrayList();
            SqlDataReader drCobros = Factura.CobrosMes(tr, sSerie, int.Parse(sNumero));
            while (drCobros.Read())
            {
                string[] aDatosAux = new string[] {
                    drCobros["t325_anomes"].ToString(),
                    drCobros["cobro"].ToString(),
                    drCobros["fecha"].ToString()
                };
                slCobros.Add(aDatosAux);
            }
            drCobros.Close();
            drCobros.Dispose();
            #endregion
            #region Actualizar lineas de factura
            string[] aLinea = Regex.Split(strLineas, "///");
            //Para cada linea de factura
            foreach (string oLinea in aLinea)
            {
                if (oLinea == "")
                {
                    continue;
                }

                string[] aValores = Regex.Split(oLinea, "##");
                //0. Opcion BD. "I", "U", "D"
                //1. ID datoEco
                //2. idT305
                //3. Importe linea factura
                switch (aValores[0])
                {
                case "I":
                    bProrratear = true;
                    //if (sElementosInsertados == "") sElementosInsertados = nAux.ToString();
                    //else sElementosInsertados += "//" + nAux.ToString();
                    idT305    = int.Parse(aValores[2]);
                    dImpLinea = decimal.Parse(aValores[3]);
                    idT325    = SEGMESPROYECTOSUBNODO.ExisteSegMesProy(tr, idT305, nAnoMesFact);
                    if (idT325 == 0)
                    {
                        idT325 = SEGMESPROYECTOSUBNODO.InsertSiNoExiste(tr, idT305, nAnoMesFact);
                    }
                    idDatoEcoFact = DATOECO.InsertFactura(tr, idT325, int.Parse(sClaseEco), t376_motivo, dImpLinea, null, null,
                                                          dtFecha, sSerie, int.Parse(sNumero), t313_idempresa, t302_idcliente, null, sRefCliente);
                    break;

                case "U":
                    bProrratear   = true;
                    idDatoEcoFact = int.Parse(aValores[1]);
                    dImpLinea     = decimal.Parse(aValores[3]);
                    DATOECO.UpdateImporte(tr, idDatoEcoFact, dImpLinea);
                    break;

                case "D":
                    bProrratear = true;
                    DATOECO.Delete(tr, int.Parse(aValores[1]));
                    break;
                }
            }
            #endregion
            #region cobros
            //Reparto lo cobrado entre las lineas de factura resultantes
            if (bProrratear)
            {
                #region Obtener datos de las líneas de la factura
                ArrayList     slLineas  = new ArrayList();
                SqlDataReader drLineas2 = Factura.Lineas(tr, sSerie, int.Parse(sNumero));
                while (drLineas2.Read())
                {
                    string[] aDatosAux = new string[] {
                        drLineas2["t305_idproyectosubnodo"].ToString(),
                        drLineas2["t376_iddatoeco"].ToString(),
                        drLineas2["t376_importe"].ToString()
                    };
                    slLineas.Add(aDatosAux);
                }
                drLineas2.Close();
                drLineas2.Dispose();
                #endregion
                //Para cada mes con cobro
                for (int iFilaCob = 0; iFilaCob < slCobros.Count; iFilaCob++)
                {
                    nAnoMesCobro = int.Parse(((string[])slCobros[iFilaCob])[0]);
                    dCobro       = decimal.Parse(((string[])slCobros[iFilaCob])[1]);
                    if (((string[])slCobros[iFilaCob])[2] != "")
                    {
                        dtFecha = DateTime.Parse(((string[])slCobros[iFilaCob])[2]);
                    }
                    else
                    {
                        dtFecha = null;
                    }
                    //Para cada linea de factura
                    for (int iFilaFac = 0; iFilaFac < slLineas.Count; iFilaFac++)
                    {
                        idT305        = int.Parse(((string[])slLineas[iFilaFac])[0]);
                        idDatoEcoFact = int.Parse(((string[])slLineas[iFilaFac])[1]);
                        dImpLinea     = decimal.Parse(((string[])slLineas[iFilaFac])[2]);
                        dAux          = (dImpLinea / dTotalFact) * dCobro;
                        //Miro si hay cobro para esa linea de factura
                        idDatoEcoCob = DATOECO.ExisteCobro(tr, nAnoMesCobro, idDatoEcoFact);
                        if (idDatoEcoCob == 0)
                        {
                            idT325 = SEGMESPROYECTOSUBNODO.ExisteSegMesProy(tr, idT305, nAnoMesCobro);
                            if (idT325 == 0)
                            {
                                idT325 = SEGMESPROYECTOSUBNODO.InsertSiNoExiste(tr, idT305, nAnoMesCobro);
                            }
                            DATOECO.InsertCobro(tr, idT325, dAux, dtFecha, idDatoEcoFact, sSerie, int.Parse(sNumero));
                        }
                        else
                        {
                            DATOECO.UpdateImporte(tr, idDatoEcoCob, dAux);
                        }
                    }
                }
            }
            #endregion
            Conexion.CommitTransaccion(tr);

            sResul = "OK@#@";// +sElementosInsertados;
        }
        catch (Exception ex)
        {
            Conexion.CerrarTransaccion(tr);
            sResul = "Error@#@" + Errores.mostrarError("Error al grabar la factura.", ex, false) + "@#@" + sDesc;
        }
        finally
        {
            Conexion.Cerrar(oConn);
        }

        return(sResul);
    }