public string SaveDocuments(Guid id, UnitDocument[] data)
        {
            if (!CanEditDocuments(this.permissions, id))
            {
                ThrowAuthError();
            }

            Data.SarUnit unit = db.Units.Include("Documents").Single(f => f.Id == id);

            var existingDocuments = db.UnitDocuments.Where(f => f.Unit.Id == id).ToDictionary(f => f.Id, f => f);

            List <UnitDocument> desiredDocuments = new List <UnitDocument>(data);

            foreach (var document in desiredDocuments)
            {
                Data.UnitDocument unitDocument;
                if (existingDocuments.TryGetValue(document.Id, out unitDocument))
                {
                    existingDocuments.Remove(document.Id);
                }

                if (string.IsNullOrWhiteSpace(document.Title))
                {
                    // If there's no name, delete it.
                    if (unitDocument != null)
                    {
                        unit.Documents.Remove(unitDocument);
                    }
                    continue;
                }

                if (string.IsNullOrWhiteSpace(document.Url))
                {
                    return(string.Format("{0}'s url is blank", document.Title));
                }

                if (unitDocument == null)
                {
                    unitDocument = new Data.UnitDocument()
                    {
                        Type = Data.UnitDocumentType.Application
                    };
                    unit.Documents.Add(unitDocument);
                }

                document.UpdateModel(unitDocument);
            }

            foreach (var leftover in existingDocuments.Values)
            {
                unit.Documents.Remove(leftover);
            }

            db.SaveChanges();

            return("OK");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="xl"></param>
        /// <param name="goodList"></param>
        private void GenerateMissionReadySheets(SarUnit unit, ExcelFile xl, ExcelSheet goodList)
        {
            IMissionReadyPlugin extension = null;

              string longName = this.settings.GroupFullName ?? this.settings.GroupName;
              IQueryable<UnitMembership> memberships = this.db.UnitMemberships.Include("Person.ComputedAwards.Course").Include("Status");
              if (unit != null)
              {
            memberships = memberships.Where(um => um.Unit.Id == unit.Id);
            longName = unit.LongName;
            extension = this.extensions.For<IMissionReadyPlugin>(unit);
              }
              memberships = memberships.Where(um => um.EndTime == null && um.Status.IsActive);
              memberships = memberships.OrderBy(f => f.Person.LastName).ThenBy(f => f.Person.FirstName);

              goodList.Header = longName + " Mission Active Roster";
              goodList.Footer = DateTime.Now.ToShortDateString();

              var courses = (from c in this.db.TrainingCourses where c.WacRequired > 0 select c).OrderBy(x => x.DisplayName).ToList();

              int headerIdx = 0;
              Action<string> appendHeader = head =>
            {
              var cell = goodList.CellAt(0, headerIdx++);
              cell.SetValue(head);
              cell.SetBold(true);
              cell.SetTextWrap(true);
            };

              Action<MissionReadyColumns> insertExtensionHeaders = group =>
              {
            if (extension == null) return;
            foreach (var value in extension.GetHeadersAfter(group))
            {
              appendHeader(value);
            }
              };

              insertExtensionHeaders(MissionReadyColumns.Start);
              appendHeader("DEM");
              insertExtensionHeaders(MissionReadyColumns.WorkerNumber);
              appendHeader("Lastname");
              appendHeader("Firstname");
              insertExtensionHeaders(MissionReadyColumns.Name);
              appendHeader("Card Type");
              insertExtensionHeaders(MissionReadyColumns.WorkerType);
              foreach (var course in courses)
              {
            var cell = goodList.CellAt(0, headerIdx++);
            cell.SetValue(course.DisplayName);

            cell.SetBold(true);
            cell.SetTextWrap(true);
              }
              insertExtensionHeaders(MissionReadyColumns.Courses);

              ExcelSheet badList = xl.CopySheet(goodList.Name, "Non-Mission Members");
              ExcelSheet nonFieldList = xl.CopySheet(goodList.Name, "Admin Members");

              using (SheetAutoFitWrapper good = new SheetAutoFitWrapper(xl, goodList))
              {
            using (SheetAutoFitWrapper bad = new SheetAutoFitWrapper(xl, badList))
            {
              using (SheetAutoFitWrapper admin = new SheetAutoFitWrapper(xl, nonFieldList))
              {
            int idx = 1;
            int c = 0;
            Guid lastId = Guid.Empty;

            foreach (UnitMembership membership in memberships)
            {
              Member member = membership.Person;
              if (member.Id == lastId)
              {
                continue;
              }
              lastId = member.Id;

              CompositeTrainingStatus stats = CompositeTrainingStatus.Compute(member, courses, DateTime.Now);

              SheetAutoFitWrapper wrap = bad;
              // If the person isn't supposed to keep up a WAC card, then they're administrative...
              if (membership.Status.WacLevel == WacLevel.None)
              {
                wrap = admin;
              }
              // If they're current on training and have a DEM card, they're good...
              else if (stats.IsGood && member.WacLevel != WacLevel.None)
              {
                wrap = good;
              }
              idx = wrap.Sheet.NumRows + 1;
              c = 0;

              Action<MissionReadyColumns> insertExtensionColumns = group =>
              {
                if (extension == null) return;
                foreach (var value in extension.GetColumnsAfter(group, member))
                {
                  wrap.SetCellValue(value, idx, c++);
                }
              };

              insertExtensionColumns(MissionReadyColumns.Start);
              wrap.SetCellValue(string.Format("{0:0000}", member.DEM), idx, c++);
              insertExtensionColumns(MissionReadyColumns.WorkerNumber);
              wrap.SetCellValue(member.LastName, idx, c++);
              wrap.SetCellValue(member.FirstName, idx, c++);
              insertExtensionColumns(MissionReadyColumns.Name);
              ExcelCell cell = wrap.Sheet.CellAt(idx, c);
              switch (member.WacLevel)
              {
                case WacLevel.Field:
                  cell.SetFillColor(Color.Green);
                  cell.SetFontColor(Color.White);
                  break;
                case WacLevel.Novice:
                  cell.SetFillColor(Color.Red);
                  cell.SetFontColor(Color.White);
                  break;
                case WacLevel.Support:
                  cell.SetFillColor(Color.Orange);
                  break;
              }
              wrap.SetCellValue(member.WacLevel.ToString(), idx, c++);
              insertExtensionColumns(MissionReadyColumns.WorkerType);

              foreach (var course in courses)
              {
                TrainingStatus stat = stats.Expirations[course.Id];

                if ((stat.Status & ExpirationFlags.Okay) != ExpirationFlags.Okay)
                {
                  wrap.Sheet.CellAt(idx, c).SetFillColor(Color.Pink);
                  wrap.Sheet.CellAt(idx, c).SetBorderColor(Color.Red);
                }

                wrap.SetCellValue(stat.ToString(), idx, c);
                if (stat.Expires.HasValue)
                {
                  wrap.Sheet.CellAt(idx, c).SetValue(stat.Expires.Value.Date.ToString("yyyy-MM-dd"));
                }

                c++;
              }
              insertExtensionColumns(MissionReadyColumns.Courses);

              if (wrap == bad)
              {
                wrap.Sheet.CellAt(idx, c).SetValue(member.ContactNumbers.Where(f => f.Type == "email").OrderBy(f => f.Priority).Select(f => f.Value).FirstOrDefault());
              }
              insertExtensionColumns(MissionReadyColumns.End);
              idx++;
            }
            admin.Sheet.AutoFitAll();
            good.Sheet.AutoFitAll();
            bad.Sheet.AutoFitAll();
              }
            }
              }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        public Stream GetMissionReadyList(SarUnit unit)
        {
            string templateFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Templates", "Report", "missionready-template.xls");

              ExcelFile xl;
              using (FileStream fs = new FileStream(templateFile, FileMode.Open, FileAccess.Read))
              {
            xl = ExcelService.Read(fs, ExcelFileType.XLS);
              }

              var goodList = xl.GetSheet(0);

              GenerateMissionReadySheets(unit, xl, goodList);

              MemoryStream ms = new MemoryStream();
              xl.Save(ms);
              ms.Seek(0, SeekOrigin.Begin);
              return ms;
        }
        protected override void AddRosterRowFrom4x4Sheet(ExpandedRowsContext model, SarUnit unit, IRosterEntry row)
        {
            TrainingRoster mrow = (TrainingRoster)row;

              Guid personId = mrow.Person.Id;
              TrainingRoster newRow = new TrainingRoster
              {
            Training = (Training)model.SarEvent,
            Person = this.db.Members.Include("TrainingRosters").Single(f => f.Id == personId),
            TimeIn = mrow.TimeIn,
            TimeOut = mrow.TimeOut,
            Miles = mrow.Miles,
              };
              mrow.Id = newRow.Id;
              this.db.TrainingRosters.Add(newRow);
        }
 public MissionReadyExtension(SarUnit unit)
 {
     this.unit = unit;
 }
        protected override void AddRosterRowFrom4x4Sheet(ExpandedRowsContext model, SarUnit unit, IRosterEntry row)
        {
            MissionRoster mrow = (MissionRoster)row;

              Guid personId = mrow.Person.Id;
              MissionRoster newRow = new MissionRoster
              {
            Mission = (Mission)model.SarEvent,
            Unit = unit,
            Person = this.db.Members.Include("MissionRosters").Single(f => f.Id == personId),
            TimeIn = mrow.TimeIn,
            TimeOut = mrow.TimeOut,
            Miles = mrow.Miles,
            InternalRole = mrow.InternalRole
              };
              mrow.Id = newRow.Id;
              this.db.MissionRosters.Add(newRow);
        }