public ActionResult IniciarMigracion()
        {
            int NumFol = 0; //ultima registrada

            RecordFCSContext dbx = new RecordFCSContext();

            int bloqueGuardar = 500;

            Guid TipoObraID = new Guid("375ead18-18db-4a8e-bfbf-7d55ee08ff80");
            TipoObra tipoObra = dbx.TipoObras.Find(TipoObraID);

            Guid TipoPiezaID = new Guid("c84ed502-20d8-4691-9a17-2d739c2bf4da");
            TipoPieza tipoPieza = tipoObra.TipoPiezas.FirstOrDefault(a => a.TipoPiezaID == TipoPiezaID);

            LetraFolio letra = dbx.LetraFolios.SingleOrDefault(a => a.Nombre == "A");

            if (tipoObra != null && tipoPieza != null && letra != null)
            {

                //Extraer los atributos requeridos.
                var listaAttRegistro = tipoPieza.Atributos.Where(a => a.Status && a.MostrarAtributos.Any(b => b.TipoMostrar.Nombre == "Registro" && b.Status) && a.TipoAtributo.Status).OrderBy(a => a.Orden).ToList();

                //extraer
                con1.Open();
                string textSql1 = string.Format("SELECT * FROM [{0}]", "ArchivoFondo");
                SqlCommand sql1 = new SqlCommand(textSql1, con1);
                SqlDataReader leer1 = sql1.ExecuteReader();

                List<RowArchivo> listaArchivoCEHM = new List<RowArchivo>();

                int i = NumFol;

                while (leer1.Read())
                {
                    i++;
                    var rowArchivo = new RowArchivo()
                    {
                        ArchivoID = Convert.ToInt32(i),
                        Asunto1 = Regex.Replace(leer1["Asunto1"].ToString().Trim(), @"\s+", " "),
                        Asunto2 = Regex.Replace(leer1["Asunto2"].ToString().Trim(), @"\s+", " "),
                        Caja = Regex.Replace(leer1["Caja"].ToString().Trim(), @"\s+", " "),
                        Carpeta = Regex.Replace(leer1["Carpeta"].ToString().Trim(), @"\s+", " "),
                        Clasificacion = Regex.Replace(leer1["Clasificacion"].ToString().Trim(), @"\s+", " "),
                        Documento = Regex.Replace(leer1["Documento"].ToString().Trim(), @"\s+", " "),
                        FICHA_NO = Convert.ToInt32(leer1["FICHA_NO"]),
                        Firmadopor = Regex.Replace(leer1["Firmadopor"].ToString().Trim(), @"\s+", " "),
                        Fojas = Regex.Replace(leer1["Fojas"].ToString().Trim(), @"\s+", " "),
                        Fondo = Regex.Replace(leer1["Fondo"].ToString().Trim(), @"\s+", " "),
                        Legajo = Regex.Replace(leer1["Legajo"].ToString().Trim(), @"\s+", " "),
                        LugaryFecha = Regex.Replace(leer1["LugaryFecha"].ToString().Trim(), @"\s+", " "),
                        NoImag = Convert.ToInt32(leer1["NoImag"].ToString() == "" ? 0 : leer1["NoImag"]),
                        Nombredelfondo = Regex.Replace(leer1["Nombredelfondo"].ToString().Trim(), @"\s+", " "),
                        Tipodedocumento = Regex.Replace(leer1["Tipodedocumento"].ToString().Trim(), @"\s+", " "),
                        URLFicha = Regex.Replace(leer1["URLFicha"].ToString().Trim(), @"\s+", " "),
                        URLImagen = Regex.Replace(leer1["URLImagen"].ToString().Trim(), @"\s+", " "),
                        Tema = Regex.Replace(leer1["Tema"].ToString().Trim(), @"\s+", " "),
                        Dirigidoa = Regex.Replace(leer1["Dirigidoa"].ToString().Trim(), @"\s+", " ")

                    };

                    if (rowArchivo.ArchivoID > 0)
                        listaArchivoCEHM.Add(rowArchivo);

                }
                con1.Close();
                leer1 = null;

                int numeroRow = 0;
                List<AtributoPieza> listaAdd_AttGen = new List<AtributoPieza>();
                List<AutorPieza> listaAdd_AttAutor = new List<AutorPieza>();

                foreach (var row in listaArchivoCEHM)
                {

                    if(numeroRow == bloqueGuardar)
                    {
                        //guardar los atributos
                        dbx.AtributoPiezas.AddRange(listaAdd_AttGen);
                        dbx.AutorPiezas.AddRange(listaAdd_AttAutor);
                        dbx.SaveChanges();

                        dbx.Dispose();
                        dbx = new RecordFCSContext();
                        dbx.Configuration.AutoDetectChangesEnabled = false;

                        numeroRow = 0;
                        listaAdd_AttAutor = new List<AutorPieza>();
                        listaAdd_AttGen = new List<AtributoPieza>();

                    }

                    //tratar los att de la pieza
                    var obra = new Obra()
                    {
                        ObraID = Guid.NewGuid(),
                        FechaRegistro = DateTime.Now,
                        TipoObraID = tipoObra.TipoObraID,
                        LetraFolioID = letra.LetraFolioID,
                        Status = false,
                        NumeroFolio = row.ArchivoID
                    };
                    dbx.Obras.Add(obra);

                    //Crear pieza
                    Pieza pieza = new Pieza()
                    {
                        PiezaID = Guid.NewGuid(),
                        FechaRegistro = obra.FechaRegistro,
                        ObraID = obra.ObraID,
                        Status = false,
                        PiezaPadreID = null, // null = Principal o Maestra
                        TipoPiezaID = tipoPieza.TipoPiezaID,
                        SubFolio = tipoPieza.Prefijo
                    };
                    dbx.Piezas.Add(pieza);

                    foreach (var att in listaAttRegistro)
                    {
                        var tipoAtt = att.TipoAtributo;

                        if (tipoAtt.EsGenerico)
                        {

                            if (tipoAtt.EsLista)
                            {
                                /*
                                 * GENERICO LISTA
                                 * Fondo - Fondo_CEHM - Fondo
                                 * Colección - Coleccion_Clave - Nombredelfondo
                                 * Legajo - Legajo_CEHM - Legajo
                                 * Fecha de ejecución - FechaEjecucion_Clave - Fecha de ejecucion
                                 */
                                var addOK = true;
                                string valorText = "";
                                switch (tipoAtt.Temp)
                                {
                                    case "Fondo_CEHM":
                                        addOK = row.Fondo == null || row.Fondo == "" ? false : true;
                                        valorText = addOK ? row.Fondo : "";
                                        break;
                                    case "Coleccion_Clave":
                                        addOK = row.Nombredelfondo == null || row.Nombredelfondo == "" ? false : true;
                                        valorText = addOK ? row.Nombredelfondo : "";
                                        break;
                                    case "Legajo_CEHM":
                                        addOK = row.Legajo == null || row.Legajo == "" ? false : true;
                                        valorText = addOK ? row.Legajo : "";
                                        break;
                                    case "FechaEjecucion_Clave":
                                        addOK = row.LugaryFecha == null || row.LugaryFecha == "" ? false : true;
                                        valorText = addOK ? row.LugaryFecha : "";
                                        break;
                                    default:
                                        addOK = false;
                                        break;
                                }

                                if (addOK)
                                {
                                    var listaValor = dbx.ListaValores.SingleOrDefault(a => a.TipoAtributoID == tipoAtt.TipoAtributoID && a.Valor == valorText);

                                    if (listaValor == null)
                                    {
                                        listaValor = new ListaValor()
                                        {
                                            ListaValorID = Guid.NewGuid(),
                                            Status = true,
                                            TipoAtributoID = tipoAtt.TipoAtributoID,
                                            Valor = valorText
                                        };
                                        dbx.ListaValores.Add(listaValor);
                                        dbx.SaveChanges();
                                    }

                                    listaAdd_AttGen.Add(new AtributoPieza()
                                    {
                                        AtributoPiezaID = Guid.NewGuid(),
                                        AtributoID = att.AtributoID,
                                        PiezaID = pieza.PiezaID,
                                        Status = true,
                                        ListaValorID = listaValor.ListaValorID
                                    });
                                }

                            }
                            else
                            {
                                if (tipoAtt.EsMultipleValor)
                                {
                                    /*
                                     * GENERICO TEXTO MULTIPLE
                                     * Descripción - descripcion
                                     *
                                     *
                                     * Se forma con : Asunto1, Asunto2, Tema

                                     */

                                    var addOK = true;
                                    string valorText = "";

                                    switch (tipoAtt.Temp)
                                    {
                                        case "descripcion":
                                            // Tema
                                            addOK = true;
                                            valorText = "";
                                            addOK = row.Tema == null || row.Tema == "" ? false : true;

                                            valorText = addOK ? row.Tema : "";

                                            if (addOK)
                                            {
                                                listaAdd_AttGen.Add(new AtributoPieza()
                                                {
                                                    AtributoPiezaID = Guid.NewGuid(),
                                                    AtributoID = att.AtributoID,
                                                    PiezaID = pieza.PiezaID,
                                                    Status = true,
                                                    Valor = valorText
                                                });
                                            }

                                            // Asunto1
                                            addOK = true;
                                            valorText = "";
                                            addOK = row.Asunto1 == null || row.Asunto1 == "" ? false : true;

                                            valorText = addOK ? row.Asunto1 : "";
                                            if (addOK)
                                            {
                                                listaAdd_AttGen.Add(new AtributoPieza()
                                                {
                                                    AtributoPiezaID = Guid.NewGuid(),
                                                    AtributoID = att.AtributoID,
                                                    PiezaID = pieza.PiezaID,
                                                    Status = true,
                                                    Valor = valorText
                                                });
                                            }

                                            // Asunto2
                                            addOK = true;
                                            valorText = "";
                                            addOK = row.Asunto2 == null || row.Asunto2 == "" ? false : true;

                                            valorText = addOK ? row.Asunto2 : "";
                                            if (addOK)
                                            {
                                                listaAdd_AttGen.Add(new AtributoPieza()
                                                {
                                                    AtributoPiezaID = Guid.NewGuid(),
                                                    AtributoID = att.AtributoID,
                                                    PiezaID = pieza.PiezaID,
                                                    Status = true,
                                                    Valor = valorText
                                                });
                                            }

                                            break;
                                        default:
                                            addOK = false;
                                            break;
                                    }

                                }
                                else
                                {
                                    /*
                                     * GENERICOS TEXTO
                                     * No ficha CEHM            - NoFicha_CEHM
                                     * Clasificacion CEHM       - Clasificacion_CEHM
                                     * No de caja o carpeta     - NoCajaOCarpeta_Cehm
                                     * No de documento o fojas  - NoDocFojas_CEHM
                                     * Título descriptivo       - titulo
                                     * Enlace ficha             - UrlFicha_CEHM
                                     * No de imagenes           - NoImagen_CEHM
                                     * Enlace Imagenes          - URLImagen_CEHM
                                     */

                                    var addOK = true;
                                    string valorText = "";

                                    switch (tipoAtt.Temp)
                                    {
                                        case "NoFicha_CEHM":
                                            addOK = row.FICHA_NO == 0 ? false : true;
                                            valorText = addOK ? row.FICHA_NO.ToString() : "0";
                                            break;

                                        case "Clasificacion_CEHM":
                                            addOK = row.Clasificacion == null || row.Clasificacion == "" ? false : true;
                                            valorText = addOK ? row.Clasificacion : "";
                                            break;

                                        case "NoCajaOCarpeta_Cehm":
                                            // se forma con:  caja y carpeta
                                            // queda: Caja: 1 / Carpeta: 1
                                            // queda: Caja: 1
                                            // queda: Carpeta : 1
                                            var cajaOk = false;
                                            addOK = row.Caja == null || row.Caja == "" ? false : true;
                                            valorText += addOK? "" + row.Caja : "";
                                            cajaOk = addOK;
                                            addOK = row.Carpeta == null || row.Carpeta == "" ? false : true;
                                            valorText += cajaOk && addOK? " / " : "";
                                            valorText += addOK ? "" + row.Carpeta : "";
                                            addOK = addOK || cajaOk ? true : false;
                                            break;

                                        case "NoDocFojas_CEHM":
                                            // se forma con Fojas, Documento
                                            var fojaOk = false;
                                            addOK = row.Fojas == null || row.Fojas == "" ? false : true;
                                            valorText += addOK? "" + row.Fojas : "";
                                            fojaOk = addOK;
                                            addOK = row.Documento == null || row.Documento == "" ? false : true;
                                            valorText += fojaOk && addOK? " / " : "";
                                            valorText += addOK ? "" + row.Documento : "";
                                            addOK = addOK || fojaOk ? true : false;
                                            break;

                                        case "titulo":
                                            // Tipodedocumento, Dirigidoa

                                            var tipoDocOk = false;
                                            addOK = row.Tipodedocumento == null || row.Tipodedocumento == "" ? false : true;
                                            valorText += addOK? row.Tipodedocumento : "";
                                            tipoDocOk = addOK;
                                            addOK = row.Dirigidoa == null || row.Dirigidoa == "" ? false : true;
                                            valorText += tipoDocOk && addOK ? " / " : "";
                                            valorText += addOK ? row.Dirigidoa : "";
                                            addOK = addOK || tipoDocOk ? true : false;
                                            break;
                                        case "UrlFicha_CEHM":
                                            addOK = row.URLFicha == null || row.URLFicha == "" ? false : true;
                                            valorText = addOK ? row.URLFicha : "";
                                            break;
                                        case "NoImagen_CEHM":
                                            addOK = row.NoImag == 0 ? false : true;
                                            valorText = addOK ? row.NoImag.ToString() : "0";
                                            addOK = true;
                                            break;
                                        case "URLImagen_CEHM":
                                            addOK = row.URLImagen == null || row.URLImagen == "" ? false : true;
                                            valorText = addOK ? row.URLImagen : "";
                                            break;

                                        default:
                                            addOK = false;
                                            break;
                                    }

                                    if (addOK)
                                    {
                                        listaAdd_AttGen.Add(new AtributoPieza()
                                        {
                                            AtributoPiezaID = Guid.NewGuid(),
                                            AtributoID = att.AtributoID,
                                            PiezaID = pieza.PiezaID,
                                            Status = true,
                                            Valor = valorText
                                        });

                                    }

                                }
                            }

                        }
                        else
                        {
                            /*
                             * AUTOR LISTA MULTIPLE
                             * Firmado por
                             */

                            var addOK = true;
                            string valorText = "";

                            addOK = row.Firmadopor == null || row.Firmadopor == "" ? false : true;
                            valorText = addOK ? row.Firmadopor : "";

                            if (addOK)
                            {
                                var autor = dbx.Autores.SingleOrDefault(a => a.Nombre == valorText);

                                if (autor == null)
                                {
                                    autor = new Autor()
                                    {
                                        AutorID = Guid.NewGuid(),
                                        Status = true,
                                        Nombre = valorText
                                    };
                                    dbx.Autores.Add(autor);
                                    dbx.SaveChanges();
                                }

                                listaAdd_AttAutor.Add(new AutorPieza()
                                    {
                                        AutorID = autor.AutorID,
                                        esPrincipal = true,
                                        PiezaID = pieza.PiezaID,
                                        Status = true,
                                        Prefijo = "Principal"
                                    });

                            }

                        }

                    }

                    numeroRow++;
                }

                    //guardar los atributos
                    dbx.AtributoPiezas.AddRange(listaAdd_AttGen);
                    dbx.AutorPiezas.AddRange(listaAdd_AttAutor);
                    dbx.SaveChanges();

                    dbx.Dispose();
                    dbx = new RecordFCSContext();
                    dbx.Configuration.AutoDetectChangesEnabled = false;

            }

            return View();
        }
        public ActionResult Registrar(Guid? TipoObraID, int? LetraFolioID, Guid? TipoPiezaID)
        {
            var Formulario = Request.Form;

            int InicioFolio = 1;
            if (TipoObraID == null || LetraFolioID == null || TipoPiezaID == null)
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

            var letra = db.LetraFolios.Find(LetraFolioID);
            var tipoObra = db.TipoObras.Find(TipoObraID);
            var tipoPieza = tipoObra.TipoPiezas.FirstOrDefault(a => a.TipoPiezaID == TipoPiezaID);

            if (tipoObra == null || letra == null || tipoPieza == null)
                return HttpNotFound();

            //buscar el ultimo numero del folio subido

            InicioFolio = db.Obras.Where(a => a.LetraFolioID == letra.LetraFolioID).Select(a=> a.NumeroFolio).OrderByDescending(a=> a).FirstOrDefault();

            var obra = new Obra()
            {
                FechaRegistro = DateTime.Now,
                TipoObraID = tipoObra.TipoObraID,
                LetraFolioID = letra.LetraFolioID,
                Status = false,
                NumeroFolio = InicioFolio
            };

            obra.ObraID = Guid.NewGuid();

            //Crear pieza
            Pieza pieza = new Pieza()
            {
                PiezaID = Guid.NewGuid(),
                FechaRegistro = obra.FechaRegistro,
                ObraID = obra.ObraID,
                Status = false,
                PiezaPadreID = null, // null = Principal o Maestra
                TipoPiezaID = tipoPieza.TipoPiezaID,
                SubFolio = tipoPieza.Prefijo
            };

            //lista de atributos de registro
            var listaAttRegistro = tipoPieza.Atributos.Where(a => a.Status && a.MostrarAtributos.Any(b => b.TipoMostrar.Nombre == "Registro" && b.Status) && a.TipoAtributo.Status).OrderBy(a => a.Orden).ToList();

            List<AtributoPieza> listaAdd_AttGen = new List<AtributoPieza>();
            List<AutorPieza> listaAdd_AttAutor = new List<AutorPieza>();
            List<ImagenPieza> listaAdd_AttImg = new List<ImagenPieza>();
            List<TecnicaPieza> listaAdd_AttTec = new List<TecnicaPieza>();
            List<MedidaPieza> listaAdd_AttMed = new List<MedidaPieza>();
            Ubicacion ubicacionAdd = null;

            List<string> listaKey;

            /*
             * Extraer los registros del formulario dependiendo el tipo de Atributo
             *
             * IMAGEN
             *      SIMPLE
             *          id_####################_File        (File)
             *          id_####################_Titulo      (Input)
             *          id_####################_Descripcion (Input)
             *

             *

             */

            foreach (var att in listaAttRegistro)
            {
                var tipoAtt = att.TipoAtributo;

                if (tipoAtt.EsGenerico)
                {
                    /*
                     * GENERICO
                     *      LISTA
                     *          SIMPLE
                     *              id_#################### (Select)
                     *          MULTI
                     *              id_####################_#################### (Input)
                     */
                    if (tipoAtt.EsLista)
                    {

                        if (tipoAtt.EsMultipleValor)
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID + "_")).ToList();
                        else
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID)).ToList();

                        //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                        foreach (string key in listaKey)
                        {
                            var addOk = true;
                            string valor = Formulario[key];

                            addOk = String.IsNullOrWhiteSpace(valor) ? false : true;

                            //validar el valorID, buscar el valor
                            Guid valorID = addOk ? new Guid(valor) : new Guid(new Byte[16]);

                            addOk = !addOk ? addOk : listaAdd_AttGen.Where(a => a.AtributoID == att.AtributoID && a.ListaValorID == valorID).FirstOrDefault() == null ? true : false;

                            addOk = !addOk ? addOk : db.ListaValores.Where(a => a.TipoAtributoID == tipoAtt.TipoAtributoID && a.Status && a.ListaValorID == valorID).FirstOrDefault() == null ? false : true;

                            if (addOk)
                                listaAdd_AttGen.Add(new AtributoPieza()
                                {
                                    AtributoPiezaID = Guid.NewGuid(),
                                    AtributoID = att.AtributoID,
                                    PiezaID = pieza.PiezaID,
                                    Status = true,
                                    ListaValorID = valorID
                                });
                        }
                    }
                    else
                    {
                        /*
                         * GENERICO
                         *    CAMPO
                         *        SIMPLE
                         *            id_#################### (Input)
                         *        MULTI
                         *            id_####################_##### (Input)
                         */

                        if (tipoAtt.EsMultipleValor)
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID + "_")).ToList();
                        else
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID)).ToList();

                        //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx
                        foreach (string key in listaKey)
                        {
                            var addOk = true;
                            string valor = Formulario[key];

                            //validar el campo, quitar espacios en blanco, bla bla bla
                            valor = valor.Trim(); // quitar espacios en inicio y fin
                            valor = Regex.Replace(valor, @"\s+", " "); //quitar espacios de sobra

                            addOk = String.IsNullOrWhiteSpace(valor) ? false : true;
                            addOk = !addOk ? addOk : listaAdd_AttGen.Where(a => a.AtributoID == att.AtributoID && a.Valor == valor).FirstOrDefault() == null ? true : false;

                            if (addOk)
                                listaAdd_AttGen.Add(new AtributoPieza()
                                {
                                    AtributoPiezaID = Guid.NewGuid(),
                                    AtributoID = att.AtributoID,
                                    PiezaID = pieza.PiezaID,
                                    Status = true,
                                    Valor = valor
                                });

                        }
                    }
                }
                else
                {
                    switch (tipoAtt.TablaSQL)
                    {
                        case "Autor":
                            /*
                                * AUTOR
                                *      MULTIPLE
                                *          id_####################_####################            (Input)
                                *          id_####################_####################_prefijo    (Input)
                            */
                            //filtrar id_#######
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID + "_")).ToList();

                            ///filtrar: ignorar los _prefijo
                            listaKey = listaKey.Where(k => !k.EndsWith("_prefijo")).ToList();

                            //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                            foreach (string key in listaKey)
                            {
                                var addOk = true;
                                string text_autorID = Formulario[key];
                                string text_prefijo = Formulario[key + "_prefijo"];

                                addOk = String.IsNullOrWhiteSpace(text_autorID) ? false : true;

                                //validar el valorID, buscar el valor
                                Guid autorID = addOk ? new Guid(text_autorID) : new Guid(new Byte[16]);

                                addOk = !addOk ? addOk : listaAdd_AttAutor.Where(a => a.AutorID == autorID).FirstOrDefault() == null ? true : false;

                                addOk = !addOk ? addOk : db.Autores.Where(a => a.Status && a.AutorID == autorID).FirstOrDefault() == null ? false : true;

                                if (addOk)
                                {
                                    var autorPieza = new AutorPieza()
                                    {
                                        AutorID = autorID,
                                        PiezaID = pieza.PiezaID,
                                        esPrincipal = false,
                                        Prefijo = text_prefijo,
                                        Status = true
                                    };

                                    //validar si es principal
                                    if (autorPieza.Prefijo.ToLower() == "principal")
                                        autorPieza.esPrincipal = listaAdd_AttAutor.Where(a => a.esPrincipal).Count() == 0 ? true : false;

                                    listaAdd_AttAutor.Add(autorPieza);
                                }
                            }
                            break;

                        case "Ubicacion":
                            /*
                                * UBICACION
                                *      SIMPLE
                                *          id_####################     (select)
                            */

                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID)).ToList();

                            //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                            foreach (string key in listaKey)
                            {
                                var addOk = true;
                                string texto_ubicacionID = Formulario[key];

                                addOk = String.IsNullOrWhiteSpace(texto_ubicacionID) ? false : true;

                                //validar el valorID, buscar el valor
                                Guid ubicacionID = addOk ? new Guid(texto_ubicacionID) : new Guid(new Byte[16]);

                                addOk = !addOk ? addOk : ubicacionAdd == null ? true : false;

                                addOk = !addOk ? addOk : db.Ubicaciones.Where(a => a.Status && a.UbicacionID == ubicacionID).FirstOrDefault() == null ? false : true;

                                if (addOk)
                                    pieza.UbicacionID = ubicacionID;
                            }
                            break;

                        case "TipoTecnica":
                            /*
                                * TECNICA
                                *      SIMPLE
                                *          id_####################     (Select)
                             */

                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID)).ToList();

                            //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                            foreach (string key in listaKey)
                            {
                                var addOk = true;
                                string texto_TecnicaID = Formulario[key];

                                addOk = String.IsNullOrWhiteSpace(texto_TecnicaID) ? false : true;

                                //validar el valorID, buscar el valor
                                Guid tecnicaID = addOk ? new Guid(texto_TecnicaID) : new Guid(new Byte[16]);

                                addOk = !addOk ? addOk : listaAdd_AttTec.Where(a => a.TecnicaID == tecnicaID).FirstOrDefault() == null ? true : false;

                                addOk = !addOk ? addOk : db.Tecnicas.Where(a => a.TecnicaID == tecnicaID && a.Status).FirstOrDefault() == null ? false : true;

                                if (addOk)
                                {
                                    var tecnica = db.Tecnicas.Where(a => a.TecnicaID == tecnicaID && a.Status).FirstOrDefault();

                                    listaAdd_AttTec.Add(new TecnicaPieza()
                                    {
                                        PiezaID = pieza.PiezaID,
                                        Status = true,
                                        TecnicaID = tecnica.TecnicaID,
                                        TipoTecnicaID = tecnica.TipoTecnicaID
                                    });
                                }
                            }

                            break;

                        case "TipoMedida":
                            /*
                                * TIPO MEDIDA
                                *      SIMPLE
                                *          id_####################                 (Select)(TipoMedida)
                                *          id_####################_UML             (Select)
                                *          id_####################_Altura          (input)
                                *          id_####################_Anchura         (input)
                                *          id_####################_Profundidad     (input)
                                *          id_####################_Diametro        (input)
                                *          id_####################_Diametro2       (input)
                            */

                            listaKey = Formulario.AllKeys.Where(k => k == "TipoMedidaID").ToList();

                            //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                            foreach (string key in listaKey)
                            {
                                var addOk = true;
                                string texto_TipoMedidaID = Formulario[key];

                                addOk = String.IsNullOrWhiteSpace(texto_TipoMedidaID) ? false : true;

                                //validar el valorID, buscar el valor
                                Guid tipoMedidaID = addOk ? new Guid(texto_TipoMedidaID) : new Guid(new Byte[16]);

                                addOk = !addOk ? addOk : listaAdd_AttMed.Where(a => a.TipoMedidaID == tipoMedidaID).FirstOrDefault() == null ? true : false;

                                addOk = !addOk ? addOk : db.TipoMedidas.Where(a => a.TipoMedidaID == tipoMedidaID && a.Status).FirstOrDefault() == null ? false : true;

                                if (addOk)
                                {
                                    var medidaPieza = new MedidaPieza()
                                    {
                                        PiezaID = pieza.PiezaID,
                                        Status = true,
                                        TipoMedidaID = tipoMedidaID
                                    };

                                    string text_UML = String.IsNullOrWhiteSpace(Formulario["id_" + att.AtributoID + "_UML"]) ? "cm" : Formulario["id_" + att.AtributoID + "_UML"];
                                    string text_Altura = String.IsNullOrWhiteSpace(Formulario["id_" + att.AtributoID + "_Altura"]) ? "0" : Formulario["id_" + att.AtributoID + "_Altura"];
                                    string text_Anchura = String.IsNullOrWhiteSpace(Formulario["id_" + att.AtributoID + "_Anchura"]) ? "0" : Formulario["id_" + att.AtributoID + "_Anchura"];
                                    string text_Profundidad = String.IsNullOrWhiteSpace(Formulario["id_" + att.AtributoID + "_Profundidad"]) ? "0" : Formulario["id_" + att.AtributoID + "_Profundidad"];
                                    string text_Diametro = String.IsNullOrWhiteSpace(Formulario["id_" + att.AtributoID + "_Diametro"]) ? "0" : Formulario["id_" + att.AtributoID + "_Diametro"];
                                    string text_Diametro2 = String.IsNullOrWhiteSpace(Formulario["id_" + att.AtributoID + "_Diametro2"]) ? "0" : Formulario["id_" + att.AtributoID + "_Diametro2"];

                                    if (text_Altura == "0") medidaPieza.Altura = Convert.ToDouble("text_Altura");
                                    if (text_Anchura == "0") medidaPieza.Anchura = Convert.ToDouble("text_Anchura");
                                    if (text_Altura == "0") medidaPieza.Profundidad = Convert.ToDouble("text_Profundidad");
                                    if (text_Altura == "0") medidaPieza.Diametro = Convert.ToDouble("text_Diametro");
                                    if (text_Altura == "0") medidaPieza.Diametro2 = Convert.ToDouble("text_Diametro2");

                                    switch (text_UML)
                                    {
                                        case "pulgada": medidaPieza.UMLongitud = UMLongitud.pulgada; break;
                                        case "dc": medidaPieza.UMLongitud = UMLongitud.dc; break;
                                        case "m": medidaPieza.UMLongitud = UMLongitud.m; break;
                                        case "dam": medidaPieza.UMLongitud = UMLongitud.dam; break;
                                        case "mm": medidaPieza.UMLongitud = UMLongitud.mm; break;
                                        case "hm": medidaPieza.UMLongitud = UMLongitud.hm; break;
                                        case "km": medidaPieza.UMLongitud = UMLongitud.km; break;
                                        default: medidaPieza.UMLongitud = UMLongitud.cm; break;

                                    }

                                    listaAdd_AttMed.Add(medidaPieza);
                                }
                            }

                            break;

                        case "ImagenPieza":

                            listaKey = Request.Files.AllKeys.Where(k => k == "id_" + att.AtributoID + "_File").ToList();

                            //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                            foreach (string key in listaKey)
                            {
                                HttpPostedFileBase FileImageForm = Request.Files[key];

                                string texto_Titulo = Formulario["id_" + att.AtributoID + "_Titulo"];
                                string texto_Descripcion = Formulario["id_" + att.AtributoID + "_Descripcion"];
                                string extension = Path.GetExtension(FileImageForm.FileName);

                                var imgGuid = Guid.NewGuid();

                                ImagenPieza imagenPieza = new ImagenPieza()
                                {
                                    PiezaID = pieza.PiezaID,
                                    ImagenPiezaID = imgGuid,
                                    Titulo = texto_Titulo,
                                    Descripcion = texto_Descripcion,
                                    EsPrincipal = true,
                                    Orden = 1,
                                    Status = true,
                                    RutaParcial = "/Content/img/pieza/",
                                    NombreImagen = imgGuid.ToString() + extension,
                                };

                                var rutaGuardar_Original = Server.MapPath(imagenPieza.Ruta);

                                FileImageForm.SaveAs(rutaGuardar_Original);

                                FileImageForm.InputStream.Dispose();
                                FileImageForm.InputStream.Close();
                                GC.Collect();

                                //Generar la mini
                                Thumbnail mini = new Thumbnail()
                                {
                                    OrigenSrc = rutaGuardar_Original,
                                    DestinoSrc = Server.MapPath(imagenPieza.RutaMini),
                                    LimiteAnchoAlto = 250
                                };

                                mini.GuardarThumbnail();

                                //add a la lista de imagenes

                                listaAdd_AttImg.Add(imagenPieza);
                            }

                            break;

                        default:
                            AlertaDanger(String.Format("No se pudo guardar el campo, {0}.", att.NombreAlterno));
                            break;
                    }

                }

            }

            if (ModelState.IsValid)
            {
                //validar el numero de folio
                obra.NumeroFolio = DarFolioValido(obra.LetraFolioID, obra.NumeroFolio);

                //Guardar la obra
                db.Obras.Add(obra);
                db.SaveChanges();

                //Guardar la pieza
                db.Piezas.Add(pieza);
                db.SaveChanges();

                //Guardar sus atributos
                db.AtributoPiezas.AddRange(listaAdd_AttGen);
                db.AutorPiezas.AddRange(listaAdd_AttAutor);
                db.ImagenPiezas.AddRange(listaAdd_AttImg);
                db.TecnicaPiezas.AddRange(listaAdd_AttTec);
                db.MedidaPiezas.AddRange(listaAdd_AttMed);

                db.SaveChanges();

                return RedirectToAction("Detalles", "Obra", new { id = obra.ObraID });

            }

            return Json(new { success = false });
        }
        public ActionResult Registrar(Guid? TipoObraID, int? LetraFolioID, Guid? TipoPiezaID)
        {
            var Formulario = Request.Form;

            if (TipoObraID == null || LetraFolioID == null || TipoPiezaID == null)
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

            var letra = db.LetraFolios.Find(LetraFolioID);
            var tipoObra = db.TipoObras.Find(TipoObraID);
            var tipoPieza = tipoObra.TipoPiezas.FirstOrDefault(a => a.TipoPiezaID == TipoPiezaID);

            if (tipoObra == null || letra == null || tipoPieza == null)
                return HttpNotFound();

            var obra = new Obra()
            {
                FechaRegistro = DateTime.Now,
                TipoObraID = tipoObra.TipoObraID,
                LetraFolioID = letra.LetraFolioID,
                Status = false,
                NumeroFolio = 1
            };

            obra.ObraID = Guid.NewGuid();

            //validar el numero de folio
            obra.NumeroFolio = DarFolioValido(obra.LetraFolioID, obra.NumeroFolio);

            //Guardar la obra
            //db.Obras.Add(obra);
            //db.SaveChanges();

            //Crear pieza
            Pieza pieza = new Pieza()
            {
                FechaRegistro = obra.FechaRegistro,
                ObraID = obra.ObraID,
                Status = false,
                PiezaPadreID = null, // null = Principal o Maestra
                TipoPiezaID = tipoPieza.TipoPiezaID,
                SubFolio = tipoPieza.Prefijo
            };

            pieza.PiezaID = Guid.NewGuid();

            //Guardar la pieza
            //db.Piezas.Add(pieza);
            //db.SaveChanges();

            //lista de atributos de registro
            var listaAttRegistro = tipoPieza.Atributos.Where(a => a.Status && a.MostrarAtributos.Any(b => b.TipoMostrar.Nombre == "Registro" && b.Status) && a.TipoAtributo.Status).OrderBy(a => a.Orden).ToList();

            List<AtributoPieza> listaAdd_AttGen = new List<AtributoPieza>();
            List<AutorPieza> listaAdd_AttAutor = new List<AutorPieza>();
            List<ImagenPieza> listaAdd_AttImg = new List<ImagenPieza>();
            List<TecnicaPieza> listaAdd_AttTec = new List<TecnicaPieza>();
            List<MedidaPieza> listaAdd_AttMed = new List<MedidaPieza>();
            Ubicacion ubicacionAdd = null;

            /*
             * Extraer los registros del formulario dependiendo el tipo de Atributo
             *

             * AUTOR
             *      MULTIPLE
             *              id_####################_#################### (Input)
             *
             * IMAGEN
             *      SIMPLE
             *          id_####################_File        (File)
             *          id_####################_Titulo      (Input)
             *          id_####################_Descripcion (Input)
             *
             * TECNICA
             *      SIMPLE
             *          id_####################     (Select)
             *
             *
             * TIPO MEDIDA
             *      SIMPLE
             *          id_####################                 (Select)(TipoMedida)
             *          id_####################_UML             (Select)
             *          id_####################_Altura          (input)
             *          id_####################_Anchura         (input)
             *          id_####################_Profundidad     (input)
             *          id_####################_Diametro        (input)
             *          id_####################_Diametro2       (input)
             *
             *
             *
             * UBICACION
             *      SIMPLE
             *          id_####################     (select)
             *
             */

            foreach (var att in listaAttRegistro)
            {
                var tipoAtt = att.TipoAtributo;

                if (tipoAtt.EsGenerico)
                {
                    /*
                     * GENERICO
                     *      LISTA
                     *          SIMPLE
                     *              id_#################### (Select)
                     *          MULTI
                     *              id_####################_#################### (Input)
                     */
                    if (tipoAtt.EsLista)
                    {
                        List<string> listaKey;

                        if (tipoAtt.EsMultipleValor)
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID + "_")).ToList();
                        else
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID)).ToList();

                        //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                        foreach (string key in listaKey)
                        {
                            var addOk = true;
                            string valor = Formulario[key];

                            addOk = String.IsNullOrWhiteSpace(valor) ? false : true;

                            //validar el valorID, buscar el valor
                            Guid valorID = addOk ? new Guid(valor) : new Guid(new Byte[16]);

                            addOk = !addOk ? addOk : listaAdd_AttGen.Where(a => a.AtributoID == att.AtributoID && a.ListaValorID == valorID).FirstOrDefault() == null ? true : false;

                            addOk = !addOk ? addOk : db.ListaValores.Where(a => a.TipoAtributoID == tipoAtt.TipoAtributoID && a.Status && a.ListaValorID == valorID).FirstOrDefault() == null ? false : true;

                            if (addOk)
                                listaAdd_AttGen.Add(new AtributoPieza()
                                {
                                    AtributoPiezaID = Guid.NewGuid(),
                                    AtributoID = att.AtributoID,
                                    PiezaID = pieza.PiezaID,
                                    Status = true,
                                    ListaValorID = valorID
                                });
                        }
                    }
                    else
                    {
                        /*
                         * GENERICO
                         *    CAMPO
                         *        SIMPLE
                         *            id_#################### (Input)
                         *        MULTI
                         *            id_####################_##### (Input)
                         */

                        List<string> listaKey;

                        if (tipoAtt.EsMultipleValor)
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID + "_")).ToList();
                        else
                            listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID)).ToList();

                        //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx
                        foreach (string key in listaKey)
                        {
                            var addOk = true;
                            string valor = Formulario[key];

                            //validar el campo, quitar espacios en blanco, bla bla bla
                            valor = valor.Trim(); // quitar espacios en inicio y fin
                            valor = Regex.Replace(valor, @"\s+", " "); //quitar espacios de sobra

                            addOk = String.IsNullOrWhiteSpace(valor) ? false : true;
                            addOk = !addOk ? addOk : listaAdd_AttGen.Where(a => a.AtributoID == att.AtributoID && a.Valor == valor).FirstOrDefault() == null ? true : false;

                            if (addOk)
                                listaAdd_AttGen.Add(new AtributoPieza()
                                {
                                    AtributoPiezaID = Guid.NewGuid(),
                                    AtributoID = att.AtributoID,
                                    PiezaID = pieza.PiezaID,
                                    Status = true,
                                    Valor = valor
                                });

                        }
                    }
                }
                else
                {
                    switch (tipoAtt.TablaSQL)
                    {
                        case "Autor":
                            //filtrar id_#######
                            List<string> listaKey = Formulario.AllKeys.Where(k => k.StartsWith("id_" + att.AtributoID + "_")).ToList();

                            ///filtrar: ignorar los _prefijo
                            listaKey = listaKey.Where(k => !k.EndsWith("_prefijo")).ToList();

                            //buscar en form todas las llaves que correspondan al id_xxxxxxxxxxxxxx_xxxxxxxxxxxxxx
                            foreach (string key in listaKey)
                            {
                                var addOk = true;
                                string text_autorID = Formulario[key];
                                string text_prefijo = Formulario[key + "_prefijo"];

                                addOk = String.IsNullOrWhiteSpace(text_autorID) ? false : true;

                                //validar el valorID, buscar el valor
                                Guid autorID = addOk ? new Guid(text_autorID) : new Guid(new Byte[16]);

                                addOk = !addOk ? addOk : listaAdd_AttAutor.Where(a => a.AutorID == autorID).FirstOrDefault() == null ? true : false;

                                addOk = !addOk ? addOk : db.Autores.Where(a => a.Status && a.AutorID == autorID).FirstOrDefault() == null ? false : true;

                                if (addOk)
                                {
                                    var autorPieza = new AutorPieza()
                                    {
                                        AutorID = autorID,
                                        PiezaID = pieza.PiezaID,
                                        esPrincipal = false,
                                        Prefijo = text_prefijo,
                                        Status = true
                                    };

                                    //validar si es principal
                                    if (autorPieza.Prefijo.ToLower() == "principal")
                                        autorPieza.esPrincipal = listaAdd_AttAutor.Where(a => a.esPrincipal).Count() == 0 ? true : false;

                                    listaAdd_AttAutor.Add(autorPieza);
                                }
                            }
                            break;

                        case "Ubicacion":

                            break;

                        case "TipoTecnica":

                            break;

                        case "TipoMedida":

                            break;

                        case "ImagenPieza":

                            break;

                        default:
                            break;
                    }

                }

            }

            if (ModelState.IsValid)
            {
                obra.ObraID = Guid.NewGuid();
                db.Obras.Add(obra);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            var listaLetras = db.LetraFolios.Select(a => new { a.LetraFolioID, Nombre = a.Nombre + " - " + a.Descripcion, a.Status }).Where(a => a.Status).OrderBy(a => a.Nombre);
            var listaTipoObras = db.TipoObras.Select(a => new { a.TipoObraID, Nombre = a.Nombre + " - " + a.Descripcion, a.Status }).Where(a => a.Status).OrderBy(a => a.Nombre);
            ViewBag.LetraFolioID = new SelectList(listaLetras, "LetraFolioID", "Nombre", obra.LetraFolioID);
            ViewBag.TipoObraID = new SelectList(listaTipoObras, "TipoObraID", "Nombre", obra.TipoObraID);

            return View(obra);
        }