public async Task <IActionResult> EditFixture(long id, CancellationToken cancellationToken) { var model = new EditFixtureViewModel(await GetPlannedMatchFromDatabase(id, cancellationToken), _timeZoneConverter) { Tournament = await GetPlanTournament(cancellationToken) }; if (model.PlannedMatch == null || model.Tournament == null) { var msg = $"No data for fixture id '{model.Id}'. User ID '{GetCurrentUserId()}'."; _logger.LogInformation(msg); return(NotFound(msg)); } if (!(await _authorizationService.AuthorizeAsync(User, new MatchEntity { HomeTeamId = model.PlannedMatch.HomeTeamId, GuestTeamId = model.PlannedMatch.GuestTeamId, VenueId = model.PlannedMatch.VenueId, OrigVenueId = model.PlannedMatch.OrigVenueId }, Authorization.MatchOperations.ChangeFixture)).Succeeded) { return(Forbid()); } return(View(ViewNames.Match.EditFixture, await AddDisplayDataToEditFixtureViewModel(model, cancellationToken))); }
private async Task <EditFixtureViewModel> AddDisplayDataToEditFixtureViewModel(EditFixtureViewModel model, CancellationToken cancellationToken) { try { // Get all venues and teams for a tournament and select in-memory is 40% faster compared to database selections var venuesWithTeams = await _appDb.VenueRepository.GetVenueTeamRowsAsync(new PredicateExpression(VenueTeamFields.TournamentId == _siteContext.MatchPlanTournamentId), cancellationToken); var allVenues = await _appDb.VenueRepository.GetVenuesAsync(null, cancellationToken); // get venue entities of match teams var venueIdsOfMatchTeams = venuesWithTeams .Where(vwt => vwt.TeamId == model.PlannedMatch.HomeTeamId || vwt.TeamId == model.PlannedMatch.GuestTeamId).Select(vwt => vwt.VenueId).Distinct(); model.VenuesOfMatchTeams = allVenues.Where(v => venueIdsOfMatchTeams.Contains(v.Id)).ToList(); // get venue entities of current tournament var activeVenueIds = venuesWithTeams.Select(vwt => vwt.VenueId).Distinct(); model.ActiveVenues = allVenues.Where(v => activeVenueIds.Except(venueIdsOfMatchTeams).Contains(v.Id)).ToList(); // get remaining venues (currently inactive) model.UnusedVenues = allVenues.Where(v => !activeVenueIds.Contains(v.Id)).OrderBy(v => v.City).ThenBy(v => v.Name).ToList(); return(model); } catch (Exception e) { _logger.LogCritical(e, $"Error adding display data to model '{nameof(EditFixtureViewModel)}' for user ID '{GetCurrentUserId()}'"); return(null); } }
public async Task <IActionResult> EditFixture([FromForm] EditFixtureViewModel model, CancellationToken cancellationToken) { // [FromBody] => 'content-type': 'application/json' // [FromForm] => 'content-type': 'application/x-www-form-urlencoded' model = new EditFixtureViewModel(await GetPlannedMatchFromDatabase(model.Id, cancellationToken), _timeZoneConverter) { Tournament = await GetPlanTournament(cancellationToken) }; if (model.PlannedMatch == null || model.Tournament == null) { var msg = $"No data for fixture id '{model.Id}'. User ID '{GetCurrentUserId()}'"; _logger.LogInformation(msg); return(NotFound(msg)); } if (!(await _authorizationService.AuthorizeAsync(User, new MatchEntity { HomeTeamId = model.PlannedMatch.HomeTeamId, GuestTeamId = model.PlannedMatch.GuestTeamId, VenueId = model.PlannedMatch.VenueId, OrigVenueId = model.PlannedMatch.OrigVenueId }, Authorization.MatchOperations.ChangeFixture)).Succeeded) { return(Forbid()); } // sync input with new model instance if (!await TryUpdateModelAsync(model)) { return(View(ViewNames.Match.EditFixture, await AddDisplayDataToEditFixtureViewModel(model, cancellationToken))); } // create a new MatchEntity for validation var match = FillMatchEntity(model.PlannedMatch); match.SetPlannedStart(model.MatchDate.HasValue && model.MatchTime.HasValue ? _timeZoneConverter.ToUtc(model.MatchDate.Value.Add(model.MatchTime.Value)) : null, _siteContext.FixtureRuleSet.PlannedDurationOfMatch); match.SetVenueId(model.VenueId); if (match.IsDirty) { match.ChangeSerial += 1; } ModelState.Clear(); // Todo: This business logic should rather go into settings _siteContext.FixtureRuleSet.PlannedMatchTimeMustStayInCurrentLegBoundaries = model.Tournament.IsPlanningMode; if (!await model.ValidateAsync( new FixtureValidator(match, (_siteContext, _timeZoneConverter, model.PlannedMatch), DateTime.UtcNow), ModelState)) { return(View(ViewNames.Match.EditFixture, await AddDisplayDataToEditFixtureViewModel(model, cancellationToken))); } var fixtureIsChanged = match.IsDirty; var fixtureMessage = new EditFixtureViewModel.FixtureMessage { MatchId = model.Id, ChangeSuccess = false }; // save the match entity try { fixtureMessage.ChangeSuccess = await _appDb.GenericRepository.SaveEntityAsync(match, false, false, cancellationToken); _logger.LogInformation($"Fixture for match id {match.Id} updated successfully for user ID '{0}'", GetCurrentUserId()); if (fixtureIsChanged) { SendFixtureNotification(match.Id); } } catch (Exception e) { fixtureMessage.ChangeSuccess = false; _logger.LogCritical(e, "Fixture update for match id {0} failed for user ID '{1}'", match.Id, GetCurrentUserId()); } // redirect to fixture overview, where success message is shown TempData.Put <EditFixtureViewModel.FixtureMessage>(nameof(EditFixtureViewModel.FixtureMessage), fixtureMessage); return(RedirectToAction(nameof(Fixtures), nameof(Match), new { Organization = _siteContext.UrlSegmentValue })); }