public HttpResponseMessage Post(int establishmentId, EstablishmentNameApiModel model)
        {
            //System.Threading.Thread.Sleep(2000); // test api latency

            if (!FindResources(establishmentId))
                throw new HttpResponseException(HttpStatusCode.NotFound);
            model.OwnerId = establishmentId;

            var command = new CreateEstablishmentName(User);
            Mapper.Map(model, command);

            try
            {
                _createHandler.Handle(command);
            }
            catch (ValidationException ex)
            {
                var badRequest = Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message, "text/plain");
                return badRequest;
            }

            //var response = Request.CreateResponse(HttpStatusCode.Created, Get(establishmentId, command.Id));
            var response = Request.CreateResponse(HttpStatusCode.Created,
                string.Format("Establishment name '{0}' was successfully created.", model.Text));
            var url = Url.Link(null, new
            {
                controller = "EstablishmentNames",
                action = "Get",
                establishmentId,
                establishmentNameId = command.Id,
            });
            Debug.Assert(url != null);
            response.Headers.Location = new Uri(url);
            return response;
        }
示例#2
0
        public void Handle(ImportUsfEstablishments command)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }
            var reportBuilder = command.ReportBuilder ?? new WorkReportBuilder("Import USF Departments");
            var service       = command.Service;

            try
            {
                #region Skip import if not necessary

                // do we need to re-import?
                reportBuilder.Report("Determining whether USF department import should be skipped.");
                var isSkippable = !string.IsNullOrWhiteSpace(service.LastUpdate) // data has already been sync'd at least once
                                                                                 // and the last sync date equals the command's requesting sync date
                                  && (string.IsNullOrWhiteSpace(command.LastUpdate) || service.LastUpdate.Equals(command.LastUpdate))
                                                                                 // and the status does not indicate a failure or in-progress state
                                  && service.Status == UsfFacultyProfileAttribute.Ready.ToString();
                if (isSkippable)
                {
                    reportBuilder.Report("USF department import will be skipped.");
                    return; // note this will also happen when command.SyncDate == null
                }

                #endregion
                #region Wait on import already in progress

                // is there already an import in progress?
                // if so, wait on it to change
                reportBuilder.Report("Determining whether or not USF department import is in progress.");
                _entities.Reload(command.Service.Integration); // freshen status from db
                if (service.Status == UsfFacultyProfileAttribute.InProgress.ToString())
                {
                    // wait for the process to complete
                    reportBuilder.Report("USF Department import is in progress, wait for completion.");
                    WaitOnProgress(command, reportBuilder);

                    // if was in progress, and is now ready, do not import again
                    if (command.Service.Status == UsfFacultyProfileAttribute.Ready.ToString())
                    {
                        reportBuilder.Report("USF Department import is ready, parallel import succeeded.");
                        return;
                    }
                }

                #endregion
                #region Update status, invoke USF service, and load comparison data

                // begin progress
                reportBuilder.Report("Setting status to '{0}'.", UsfFacultyProfileAttribute.InProgress.ToString());
                command.Service.Status = UsfFacultyProfileAttribute.InProgress.ToString();
                _entities.Update(command.Service.Integration);
                _entities.SaveChanges();
                reportBuilder.Report("Status set to '{0}'.", UsfFacultyProfileAttribute.InProgress.ToString());

                // invoke departments service
                reportBuilder.Report("Invoking USF department service.");
                var departmentsData = _queryProcessor.Execute(new UsfDepartments(command.Service)
                {
                    ReportBuilder = reportBuilder
                });
                if (departmentsData == null || departmentsData.Departments == null)
                {
                    throw new InvalidOperationException(string.Format(
                                                            "Could not obtain departments data for '{0}_{1}'service integration.",
                                                            command.Service.Integration.Name, command.Service.Integration.TenantId));
                }
                reportBuilder.Report("Deserialized USF department response to CLR object.");
                reportBuilder.Report("JSON value of deserialized response is:");
                reportBuilder.Report(JsonConvert.SerializeObject(departmentsData));

                // establishment types will be used later when creating establishments
                reportBuilder.Report("Loading establishment type entities.");
                var establishmentTypeName = KnownEstablishmentType.UniversityCampus.AsSentenceFragment();
                var campusType            = _entities.Query <EstablishmentType>().Single(t => t.EnglishName == establishmentTypeName);
                establishmentTypeName = KnownEstablishmentType.College.AsSentenceFragment();
                var collegeType = _entities.Query <EstablishmentType>().Single(t => t.EnglishName == establishmentTypeName);
                establishmentTypeName = KnownEstablishmentType.Department.AsSentenceFragment();
                var departmentType = _entities.Query <EstablishmentType>().Single(t => t.EnglishName == establishmentTypeName);

                // order the service results by campus, college, deptid
                departmentsData.Departments = departmentsData.Departments
                                              .OrderBy(x => x.CampusName).ThenBy(x => x.CollegeName).ThenBy(x => x.DepartmentId).ToArray();

                // all units will be children of USF
                reportBuilder.Report("Loading USF establishment entity.");
                var usf = _entities.Get <Establishment>()
                          .EagerLoad(_entities, new Expression <Func <Establishment, object> >[]
                {
                    x => x.Children,
                    x => x.Offspring.Select(y => y.Offspring),
                })
                          .Single(x => x.RevisionId == command.Service.Integration.TenantId);
                reportBuilder.Report("USF establishment entity loaded with id '{0}'.", usf.RevisionId);
                var isChanged = false;

                #endregion
                #region Populate campuses

                // populate the campuses first (they are ranked)
                var campusRanks = new Dictionary <string, int>
                {
                    { "Tampa", 1 },
                    { "Petersburg", 2 },
                    { "Sarasota", 3 },
                };
                var campusNames = departmentsData.Departments.Select(x => x.CampusName).Distinct().ToArray();
                //campusNames = campusNames.Union(new[] { "Unidentified Campus" }).ToArray();
                if (campusNames.Any(x => !campusRanks.Keys.Any(x.Contains)))
                {
                    throw new InvalidOperationException(string.Format(
                                                            "USF Service returned unexpected campus '{0}'.",
                                                            campusNames.First(x => !campusRanks.Keys.Any(x.Contains))));
                }
                reportBuilder.Report("Iterating over {0} campus names.", campusNames.Length);
                foreach (var campusName in campusNames)
                {
                    // note that the service returns USF Sarasota, but we want official name to be USF Sarasota-Manatee
                    var campusByName = usf.Children.SingleOrDefault(x => x.Names.Any(y => y.Text.Equals(campusName)));
                    if (campusByName == null)
                    {
                        var createCampusCommand = new CreateEstablishment(command.Principal)
                        {
                            NoCommit     = true,
                            NoHierarchy  = true,
                            Parent       = usf,
                            TypeId       = campusType.RevisionId,
                            Rank         = campusRanks.Single(x => campusName.Contains(x.Key)).Value,
                            OfficialName = new CreateEstablishmentName(command.Principal)
                            {
                                NoCommit       = true,
                                IsOfficialName = true,
                                Text           = !campusName.Contains("Sarasota") ? campusName : "USF Sarasota-Manatee",
                            },
                        };
                        _createEstablishment.Handle(createCampusCommand);
                        if (campusName.Contains("Sarasota"))
                        {
                            var createCampusNameCommand = new CreateEstablishmentName(command.Principal)
                            {
                                NoCommit = true,
                                Owner    = createCampusCommand.Created,
                                Text     = campusName,
                            };
                            _createEstablishmentName.Handle(createCampusNameCommand);
                        }
                        isChanged = true;
                    }
                }

                #endregion
                #region Populate Colleges

                // get all unique combinations of campus / college
                var campusColleges = departmentsData.Departments
                                     .Select(x => new { x.CampusName, x.CollegeName, }).Distinct()
                                     .OrderBy(x => x.CampusName).ThenBy(x => x.CollegeName)
                                     .ToArray();
                reportBuilder.Report("Iterating over {0} campus colleges.", campusColleges.Length);
                foreach (var campusCollege in campusColleges)
                {
                    var collegeInCampus = campusCollege;

                    // does the college already exist?
                    var campus = usf.Children
                                 .Single(x => x.Names.Any(y => y.Text.Equals(collegeInCampus.CampusName)));
                    var officialName  = string.Format("{0}, {1}", collegeInCampus.CollegeName, campus.OfficialName);
                    var collegeByName = campus.Children
                                        .SingleOrDefault(x => x.OfficialName.Equals(officialName) ||
                                                         x.Names.Any(y => y.Text.Equals(collegeInCampus.CollegeName) && y.IsContextName));
                    if (collegeByName != null)
                    {
                        continue;
                    }

                    var createCollegeCommand = new CreateEstablishment(command.Principal)
                    {
                        NoCommit     = true,
                        NoHierarchy  = true,
                        Parent       = campus,
                        TypeId       = collegeType.RevisionId,
                        OfficialName = new CreateEstablishmentName(command.Principal)
                        {
                            NoCommit       = true,
                            IsOfficialName = true,
                            Text           = officialName,
                        },
                    };
                    _createEstablishment.Handle(createCollegeCommand);
                    var createCollegeNameCommand = new CreateEstablishmentName(command.Principal)
                    {
                        NoCommit      = true,
                        IsContextName = true,
                        Owner         = createCollegeCommand.Created,
                        Text          = collegeInCampus.CollegeName,
                    };
                    _createEstablishmentName.Handle(createCollegeNameCommand);
                    isChanged = true;

                    // does this college have any department id's?
                    var customIds = departmentsData.Departments
                                    .Where(x => x.CollegeName == collegeInCampus.CollegeName &&
                                           x.CampusName == collegeInCampus.CampusName &&
                                           string.IsNullOrWhiteSpace(x.DepartmentName)
                                           )
                                    .Select(x => x.DepartmentId).Distinct()
                                    // it is possible that this custom DEPTID is named elsewhere
                                    .Where(x => !departmentsData.Departments
                                           .Any(y => y.DepartmentId == x && !string.IsNullOrWhiteSpace(y.DepartmentName)))
                                    .ToArray();
                    //var doubleCheckCustomIds = departmentsData.Departments
                    //    .Where(x => customIds.Contains(x.DepartmentId)).ToArray();

                    foreach (var customId in customIds)
                    {
                        createCollegeCommand.Created.CustomIds.Add(new EstablishmentCustomId
                        {
                            Owner = createCollegeCommand.Created,
                            Value = customId,
                        });
                    }
                }

                #endregion
                #region Populate Departments

                // we are going to skip all unnamed departments
                var namedDepartments = departmentsData.Departments
                                       .Where(x => !string.IsNullOrWhiteSpace(x.DepartmentName))
                                       .ToArray();
                reportBuilder.Report("Iterating over {0} named departments.", namedDepartments.Length);
                foreach (var departmentData in namedDepartments)
                {
                    var campus = usf.Children
                                 .Single(x => x.Names.Any(y => y.Text.Equals(departmentData.CampusName)));
                    var college = campus.Children
                                  .Single(x => x.Names.Any(y => y.Text.Equals(departmentData.CollegeName)));
                    var officialName = string.Format("{0}, {1}, {2}", departmentData.DepartmentName, departmentData.CollegeName, campus.OfficialName);

                    // is the name of the department the same as the name of the college?
                    if (departmentData.DepartmentName == departmentData.CollegeName)
                    {
                        if (college.CustomIds.All(x => x.Value != departmentData.DepartmentId))
                        {
                            college.CustomIds.Add(new EstablishmentCustomId
                            {
                                Owner = college,
                                Value = departmentData.DepartmentId,
                            });
                            isChanged = true;
                        }
                        continue;
                    }

                    // does the department already exist?
                    var departmentByName = college.Children
                                           .SingleOrDefault(x => x.OfficialName.Equals(officialName) ||
                                                            x.Names.Any(y => y.Text.Equals(departmentData.DepartmentName)));
                    var departmentById = college.Children
                                         .SingleOrDefault(x => x.CustomIds.Select(y => y.Value).Contains(departmentData.DepartmentId));

                    if (departmentByName == null)
                    {
                        if (departmentById == null)
                        {
                            var createDepartmentCommand = new CreateEstablishment(command.Principal)
                            {
                                NoCommit     = true,
                                NoHierarchy  = true,
                                Parent       = college,
                                TypeId       = departmentType.RevisionId,
                                OfficialName = new CreateEstablishmentName(command.Principal)
                                {
                                    NoCommit       = true,
                                    IsOfficialName = true,
                                    Text           = officialName,
                                },
                            };
                            _createEstablishment.Handle(createDepartmentCommand);
                            var createDepartmentNameCommand = new CreateEstablishmentName(command.Principal)
                            {
                                NoCommit      = true,
                                IsContextName = true,
                                Owner         = createDepartmentCommand.Created,
                                Text          = departmentData.DepartmentName,
                            };
                            _createEstablishmentName.Handle(createDepartmentNameCommand);
                            departmentByName = createDepartmentCommand.Created;
                        }
                        else
                        {
                            var formerContextNames = departmentById.Names.Where(x => x.IsContextName).ToArray();
                            foreach (var formerContextName in formerContextNames)
                            {
                                formerContextName.IsFormerName = true;
                            }

                            var newContextName = formerContextNames.SingleOrDefault(x => x.Text == departmentData.DepartmentName);
                            if (newContextName != null)
                            {
                                newContextName.IsFormerName = false;
                            }

                            else
                            {
                                departmentById.Names.Add(new EstablishmentName
                                {
                                    ForEstablishment = departmentById,
                                    IsContextName    = true,
                                    Text             = departmentData.DepartmentName,
                                });
                            }
                            departmentById.Names.Single(x => x.IsOfficialName).Text = officialName;
                            departmentById.OfficialName = officialName;
                            departmentByName            = departmentById;
                        }
                        isChanged = true;
                    }

                    if (departmentById == null)
                    {
                        departmentByName.CustomIds.Add(new EstablishmentCustomId
                        {
                            Owner = departmentByName,
                            Value = departmentData.DepartmentId,
                        });
                        isChanged = true;
                    }
                }

                #endregion
                #region Populate Unnamed Department Id's

                var unnamedDepartments = departmentsData.Departments
                                         .Where(x => string.IsNullOrWhiteSpace(x.DepartmentName))
                                         .ToArray();
                foreach (var departmentData in unnamedDepartments)
                {
                    var campus = usf.Children
                                 .Single(x => x.Names.Any(y => y.Text.Equals(departmentData.CampusName)));
                    var college = campus.Children
                                  .Single(x => x.Names.Any(y => y.Text.Equals(departmentData.CollegeName)));
                    if (college.CustomIds.All(x => x.Value != departmentData.DepartmentId))
                    {
                        college.CustomIds.Add(new EstablishmentCustomId
                        {
                            EstablishmentId = college.RevisionId,
                            Owner           = college,
                            Value           = departmentData.DepartmentId,
                        });
                        isChanged = true;
                    }
                }

                #endregion

                if (isChanged)
                { // TODO: only update hierarchy when establishments are added or removed
                    reportBuilder.Report("USF Department import has pending database changes.");
                    _updateHierarchy.Handle(new UpdateEstablishmentHierarchy(usf));
                    _entities.SaveChanges();
                    reportBuilder.Report("USF Department import pending database changes have been committed.");
                }

                reportBuilder.Report("USF Department import is complete.");
                reportBuilder.Report("Setting status to '{0}'.", UsfFacultyProfileAttribute.Ready.ToString());
                command.Service.Status = UsfFacultyProfileAttribute.Ready.ToString();
                reportBuilder.Report("Setting last update to '{0}'.", command.LastUpdate);
                command.Service.LastUpdate = command.LastUpdate;
                _entities.Update(command.Service.Integration);
                _entities.SaveChanges();
                reportBuilder.Report("Status set to '{0}'.", UsfFacultyProfileAttribute.Ready.ToString());
            }
            catch
            {
                reportBuilder.Report("USF Department import encountered an exception.");
                _entities.DiscardChanges();
                reportBuilder.Report("Setting status to '{0}'.", UsfFacultyProfileAttribute.FailedState.ToString());
                command.Service.Status = UsfFacultyProfileAttribute.FailedState.ToString();
                _entities.Update(command.Service.Integration);
                _entities.SaveChanges();
                reportBuilder.Report("Status set to '{0}'.", UsfFacultyProfileAttribute.FailedState.ToString());
                reportBuilder.Report("Rethrowing exception.");
                throw;
            }
        }
        public HttpResponseMessage Validate(int establishmentId, int establishmentNameId, EstablishmentNameApiModel model)
        {
            //System.Threading.Thread.Sleep(2000); // test api latency

            model.OwnerId = establishmentId;
            model.Id = establishmentNameId;

            ValidationResult validationResult;
            string propertyName;
            if (model.OwnerId < 1 || model.Id < 1)
            {
                var command = new CreateEstablishmentName(User);
                Mapper.Map(model, command);
                validationResult = _createValidator.Validate(command);
                propertyName = command.PropertyName(y => y.Text);
            }
            else
            {
                var command = new UpdateEstablishmentName(User);
                Mapper.Map(model, command);
                validationResult = _updateValidator.Validate(command);
                propertyName = command.PropertyName(y => y.Text);
            }

            Func<ValidationFailure, bool> forText = x => x.PropertyName == propertyName;
            if (validationResult.Errors.Any(forText))
                return Request.CreateResponse(HttpStatusCode.BadRequest,
                    validationResult.Errors.First(forText).ErrorMessage, "text/plain");

            return Request.CreateResponse(HttpStatusCode.OK);
        }