public async Task <IActionResult> GetMaintenanceJobAsync(DateTime planningDate, Guid jobId) { if (ModelState.IsValid) { try { // get planning WorkshopPlanning planning = await _planningRepo.GetWorkshopPlanningAsync(planningDate); if (planning == null || planning.Jobs == null) { return(NotFound()); } // get job var job = planning.Jobs.FirstOrDefault(j => j.Id == jobId); if (job == null) { return(NotFound()); } return(Ok(job)); } catch (Exception ex) { Log.Error(ex.ToString()); throw; } } return(BadRequest()); }
public async Task <WorkshopPlanning> HandleCommandAsync(DateTime planningDate, PlanMaintenanceJob command) { // get or create workshop-planning var aggregateId = WorkshopPlanningId.Create(planningDate); var planning = await _planningRepo.GetByIdAsync(aggregateId); if (planning == null) { planning = WorkshopPlanning.Create(planningDate); } // handle command planning.PlanMaintenanceJob(command); // persist IEnumerable <Event> events = planning.GetEvents(); await _planningRepo.SaveAsync( planning.Id, planning.OriginalVersion, planning.Version, events); // publish event foreach (var e in events) { await _messagePublisher.PublishMessageAsync(e.MessageType, e, ""); } // return result return(planning); }
public void Plan_MaintenanceJob_That_Spans_Two_Days_Should_Throw_Exception() { // arrange DateTime date = DateTime.Today; var initializingEvents = new Event[] { new WorkshopPlanningCreatedEventBuilder().WithDate(date).Build() }; WorkshopPlanning sut = new WorkshopPlanning(date, initializingEvents); MaintenanceJobBuilder maintenanceJobBuilder = new MaintenanceJobBuilder(); maintenanceJobBuilder .WithStartTime(DateTime.Today.AddHours(-2)); // to make the job span 2 days PlanMaintenanceJob command = new PlanMaintenanceJobCommandBuilder() .WithMaintenanceJobBuilder(maintenanceJobBuilder) .Build(); // act var thrownException = Assert.Throws <BusinessRuleViolationException>(() => sut.PlanMaintenanceJob(command)); // assert Assert.Equal("Start-time and end-time of a Maintenance Job must be within a 1 day.", thrownException.Message); }
public async Task <WorkshopPlanning> HandleCommandAsync(DateTime planningDate, FinishMaintenanceJob command) { // get planning WorkshopPlanning planning = await _planningRepo.GetWorkshopPlanningAsync(planningDate); if (planning == null) { return(null); } // handle command IEnumerable <Event> events = planning.FinishMaintenanceJob(command); // persist await _planningRepo.SaveWorkshopPlanningAsync(planning, events); // publish event foreach (var e in events) { await _messagePublisher.PublishMessageAsync(e.MessageType, e, ""); } // return result return(planning); }
public async Task <WorkshopPlanning> HandleCommandAsync(DateTime planningDate, PlanMaintenanceJob command) { List <Event> events = new List <Event>(); // get or create workshop-planning WorkshopPlanning planning = await _planningRepo.GetWorkshopPlanningAsync(planningDate); if (planning == null) { events.AddRange(WorkshopPlanning.Create(planningDate, out planning)); } // handle command events.AddRange(planning.PlanMaintenanceJob(command)); // persist await _planningRepo.SaveWorkshopPlanningAsync( planning.Id, planning.OriginalVersion, planning.Version, events); // publish event foreach (var e in events) { await _messagePublisher.PublishMessageAsync(e.MessageType, e, ""); } // return result return(planning); }
public async Task <IActionResult> FinishMaintenanceJobAsync(DateTime planningDate, Guid jobId, [FromBody] FinishMaintenanceJob command) { try { if (ModelState.IsValid) { // handle command WorkshopPlanning planning = await _finishMaintenanceJobCommandHandler.HandleCommandAsync(planningDate, command); // handle result if (planning == null) { return(NotFound()); } // return result return(Ok()); } return(BadRequest()); } catch (ConcurrencyException) { string errorMessage = "Unable to save changes. " + "Try again, and if the problem persists " + "see your system administrator."; Log.Error(errorMessage); ModelState.AddModelError("", errorMessage); return(StatusCode(StatusCodes.Status500InternalServerError)); } }
public async Task <WorkshopPlanning> GetWorkshopPlanningAsync(DateTime date) { WorkshopPlanning planning = null; using (SqlConnection conn = new SqlConnection(_connectionString)) { // get aggregate var aggregate = await conn .QuerySingleOrDefaultAsync <Aggregate>( "select * from WorkshopPlanning where Id = @Id", new { Id = date.ToString("yyyy-MM-dd") }); if (aggregate == null) { return(null); } // get events IEnumerable <AggregateEvent> aggregateEvents = await conn .QueryAsync <AggregateEvent>( "select * from WorkshopPlanningEvent where Id = @Id order by [Version];", new { Id = date.ToString("yyyy-MM-dd") }); List <Event> events = new List <Event>(); foreach (var aggregateEvent in aggregateEvents) { events.Add(DeserializeEventData(aggregateEvent.MessageType, aggregateEvent.EventData)); } planning = new WorkshopPlanning(events); } return(planning); }
public void Planning_Too_Much_MaintenanceJobs_In_Parallel_Should_Throw_Exception() { // arrange var initializingEvents = new Event[] { new WorkshopPlanningCreatedEventBuilder().WithDate(DateTime.Today).Build() }; WorkshopPlanning sut = new WorkshopPlanning(initializingEvents); VehicleBuilder vehicleBuilder = new VehicleBuilder(); PlanMaintenanceJobCommandBuilder commandBuilder = new PlanMaintenanceJobCommandBuilder() .WithVehicleBuilder(vehicleBuilder); PlanMaintenanceJob command1 = commandBuilder.Build(); vehicleBuilder.WithLicenseNumber(Guid.NewGuid().ToString()); PlanMaintenanceJob command2 = commandBuilder.Build(); vehicleBuilder.WithLicenseNumber(Guid.NewGuid().ToString()); PlanMaintenanceJob command3 = commandBuilder.Build(); vehicleBuilder.WithLicenseNumber(Guid.NewGuid().ToString()); PlanMaintenanceJob command4 = commandBuilder.Build(); // act sut.PlanMaintenanceJob(command1); sut.PlanMaintenanceJob(command2); sut.PlanMaintenanceJob(command3); var thrownException = Assert.Throws <BusinessRuleViolationException>(() => { sut.PlanMaintenanceJob(command4); // 4th parallel job }); // assert Assert.Equal("Maintenancejob overlaps with more than 3 other jobs.", thrownException.Message); }
public async Task SaveWorkshopPlanningAsync(WorkshopPlanning planning, IEnumerable <Event> newEvents) { using (SqlConnection conn = new SqlConnection(_connectionString)) { Aggregate aggregate = await conn .QueryFirstOrDefaultAsync <Aggregate>("select * from WorkshopPlanning where Id = @Id", new { Id = planning.Id }); if (aggregate != null) { // add new events to existing events var aggregateEvents = DeserializeState(aggregate.EventData); aggregateEvents.AddRange(newEvents); // determine versions int currentVersion = planning.Version; int newVersion = aggregateEvents.Count; // update aggregate await conn.ExecuteAsync( "update WorkshopPlanning set Version = @NewVersion, EventData = @EventData where Id = @Id and Version = @CurrentVersion", new { Id = planning.Id, CurrentVersion = currentVersion, NewVersion = newVersion, EventData = SerializeState(aggregateEvents) }); } else { // insert new aggregate var aggregateEvents = new List <Event>(newEvents); await conn.ExecuteAsync( "insert WorkshopPlanning (Id, Version, EventData) values (@Id, @Version, @EventData)", new { Id = planning.Id, Version = aggregateEvents.Count, EventData = SerializeState(aggregateEvents) }); } } }
public async Task <WorkshopPlanning> HandleCommandAsync(DateTime planningDate, UpdateMaintenanceJob command) { // get or create workshop-planning WorkshopPlanning planning = await planningRepository.GetWorkshopPlanningAsync(planningDate); if (planning == null) { return(null); } // handle command planning.UpdateMaintenanceJob(command); // persist IEnumerable <Event> events = planning.GetEvents(); await planningRepository.SaveWorkshopPlanningAsync( planning.Id, planning.OriginalVersion, planning.Version, events); // publish event foreach (var e in events) { await messagePublisher.PublishMessageAsync(e.MessageType, e, ""); } // return result return(planning); }
public async Task <IActionResult> Index(DateTime?date) { return(await ExecuteWithFallback(async() => { if (date == null) { date = DateTime.Now.Date; } var model = new WorkshopManagementViewModel { Date = date.Value, MaintenanceJobs = new List <MaintenanceJob>() }; // get planning string dateStr = date.Value.ToString("yyyy-MM-dd"); WorkshopPlanning planning = await _workshopManagementAPI.GetWorkshopPlanning(dateStr); if (planning?.Jobs?.Count > 0) { model.MaintenanceJobs.AddRange(planning.Jobs.OrderBy(j => j.StartTime)); } return View(model); })); }
public async Task <IActionResult> Index(DateTime?planningDate) { return(await _resiliencyHelper.ExecuteResilient(async() => { if (planningDate == null) { planningDate = DateTime.Now.Date; } var model = new WorkshopManagementViewModel { Date = planningDate.Value, MaintenanceJobs = new List <MaintenanceJob>() }; // get planning string dateStr = planningDate.Value.ToString("yyyy-MM-dd"); WorkshopPlanning planning = await _workshopManagementAPI.GetWorkshopPlanning(dateStr); if (planning?.Jobs?.Count > 0) { model.MaintenanceJobs.AddRange(planning.Jobs.OrderBy(j => j.StartTime)); } return View(model); }, View("Offline", new WorkshopManagementOfflineViewModel()))); }
public async void FinishMaintenanceJob_Handler_Should_Handle_Command() { // arrange DateTime date = DateTime.Today; Guid jobId = Guid.NewGuid(); DateTime startTime = date.AddHours(8); DateTime endTime = date.AddHours(11); DateTime actualStartTime = date.AddHours(9); DateTime actualEndTime = date.AddHours(12); var initializingEvents = new Event[] { new WorkshopPlanningCreatedEventBuilder() .WithDate(date) .Build(), new MaintenanceJobPlannedEventBuilder() .WithStartTime(startTime) .WithEndTime(endTime) .WithJobId(jobId) .Build() }; WorkshopPlanning planning = new WorkshopPlanning(initializingEvents); FinishMaintenanceJob command = new FinishMaintenanceJobCommandBuilder() .WithJobId(jobId) .WithActualStartTime(actualStartTime) .WithActualEndTime(actualEndTime) .Build(); Mock <IMessagePublisher> messagePublisherMock = new Mock <IMessagePublisher>(MockBehavior.Strict); Mock <IWorkshopPlanningRepository> repoMock = new Mock <IWorkshopPlanningRepository>(MockBehavior.Strict); repoMock .Setup(m => m.GetWorkshopPlanningAsync(It.Is <DateTime>(p => p == date))) .Returns(Task.FromResult(planning)); repoMock .Setup(m => m.SaveWorkshopPlanningAsync( It.Is <string>(p => p == planning.Id), It.Is <int>(p => p == 2), It.Is <int>(p => p == 3), It.IsAny <IEnumerable <Event> >() )) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "MaintenanceJobFinished"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); FinishMaintenanceJobCommandHandler sut = new FinishMaintenanceJobCommandHandler(messagePublisherMock.Object, repoMock.Object); // act await sut.HandleCommandAsync(date, command); // assert messagePublisherMock.VerifyAll(); repoMock.VerifyAll(); }
public static void UpdatedMaintenanceJobShouldFallWithinOneBusinessDay( this WorkshopPlanning planning, UpdateMaintenanceJob command) { if (command.StartTime.Date != command.EndTime.Date) { throw new BusinessRuleViolationException("Start-time and end-time of a Maintenance Job must be within a 1 day."); } }
public static void NumberOfParallelMaintenanceJobsMustNotExceedAvailableWorkStations( this WorkshopPlanning planning, PlanMaintenanceJob command) { if (planning.Jobs.Count(j => j.PlannedTimeslot.OverlapsWith(command.StartTime, command.EndTime)) >= AVAILABLE_WORKSTATIONS) { throw new BusinessRuleViolationException($"Maintenancejob overlaps with more than {AVAILABLE_WORKSTATIONS} other jobs."); } }
/// <summary> /// Creates a new instance of a workshop-planning for the specified date. /// </summary> /// <param name="date">The date to create the planning for.</param> public static WorkshopPlanning Create(DateTime date) { WorkshopPlanning planning = new WorkshopPlanning(date); WorkshopPlanningCreated e = new WorkshopPlanningCreated(Guid.NewGuid(), date); planning.RaiseEvent(e); return(planning); }
public static void NumberOfParallelMaintenanceJobsOnAVehicleMustNotExceedOne( this WorkshopPlanning planning, PlanMaintenanceJob command) { if (planning.Jobs.Any(j => j.Vehicle.Id == command.VehicleInfo.LicenseNumber && j.PlannedTimeslot.OverlapsWith(command.StartTime, command.EndTime))) { throw new BusinessRuleViolationException($"Only 1 maintenance job can be executed on a vehicle during a certain time-slot."); } }
public async void FinishMaintenanceJob_Handler_Should_Handle_Command() { // arrange DateTime date = DateTime.Today; Guid jobId = Guid.NewGuid(); DateTime startTime = date.AddHours(8); DateTime endTime = date.AddHours(11); DateTime actualStartTime = date.AddHours(9); DateTime actualEndTime = date.AddHours(12); var customerInfo = ("customer id", "customer name", "123456780"); var vehicleInfo = ("AB-123-C", "Volkswagen", "Tiguan"); string description = "Job description"; var initializingEvents = new Event[] { new WorkshopPlanningCreated(Guid.NewGuid(), date), new MaintenanceJobPlanned(Guid.NewGuid(), jobId, startTime, endTime, customerInfo, vehicleInfo, description) }; WorkshopPlanning planning = new WorkshopPlanning(initializingEvents); FinishMaintenanceJob command = new FinishMaintenanceJob(Guid.NewGuid(), jobId, actualStartTime, actualEndTime, "Notes"); Mock <IMessagePublisher> messagePublisherMock = new Mock <IMessagePublisher>(MockBehavior.Strict); Mock <IWorkshopPlanningRepository> repoMock = new Mock <IWorkshopPlanningRepository>(MockBehavior.Strict); repoMock .Setup(m => m.GetWorkshopPlanningAsync(It.Is <DateTime>(p => p == date))) .Returns(Task.FromResult(planning)); repoMock .Setup(m => m.SaveWorkshopPlanningAsync( It.Is <string>(p => p == planning.Id), It.Is <int>(p => p == 2), It.Is <int>(p => p == 3), It.IsAny <IEnumerable <Event> >() )) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "MaintenanceJobFinished"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); FinishMaintenanceJobCommandHandler sut = new FinishMaintenanceJobCommandHandler(messagePublisherMock.Object, repoMock.Object); // act await sut.HandleCommandAsync(date, command); // assert messagePublisherMock.VerifyAll(); repoMock.VerifyAll(); }
public static void NumberOfParallelMaintenanceJobsMustNotExceedAvailableWorkStations( this WorkshopPlanning planning, UpdateMaintenanceJob command) { if (planning.Jobs.Count(j => (j.Id != command.JobId) && ((j.StartTime >= command.StartTime && j.StartTime <= command.EndTime) || (j.EndTime >= command.StartTime && j.EndTime <= command.EndTime))) >= AVAILABLE_WORKSTATIONS) { throw new BusinessRuleViolationException($"Maintenancejob overlaps with more than {AVAILABLE_WORKSTATIONS} other jobs."); } }
public static void NumberOfParallelMaintenanceJobsOnAVehicleIsOne( this WorkshopPlanning planning, UpdateMaintenanceJob command) { if (planning.Jobs.Any(j => j.Id != command.JobId && j.Vehicle.Id == command.VehicleInfo.LicenseNumber && (j.StartTime >= command.StartTime && j.StartTime <= command.EndTime || j.EndTime >= command.StartTime && j.EndTime <= command.EndTime))) { throw new BusinessRuleViolationException($"Only 1 maintenance job can be executed on a vehicle during a certain time-slot."); } }
public async void Given_A_Non_Existing_Job_The_Handler_Should_Return_Null() { // arrange DateTime date = DateTime.Today; string workshopPlanningId = date.ToString("yyy-MM-dd"); PlanMaintenanceJob command = new PlanMaintenanceJobCommandBuilder() .Build(); Mock <IMessagePublisher> messagePublisherMock = new Mock <IMessagePublisher>(); Mock <IEventSourceRepository <WorkshopPlanning> > repoMock = new Mock <IEventSourceRepository <WorkshopPlanning> >(); repoMock .Setup(m => m.GetByIdAsync(It.Is <string>(p => p == workshopPlanningId))) .Returns(Task.FromResult <WorkshopPlanning>(null)); repoMock .Setup(m => m.SaveAsync( It.Is <string>(p => p == workshopPlanningId), It.Is <int>(p => p == 0), It.Is <int>(p => p == 2), It.Is <IEnumerable <Event> >(p => p.First().MessageType == "WorkshopPlanningCreated" && p.Last().MessageType == "MaintenanceJobPlanned") )) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "WorkshopPlanningCreated"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "MaintenanceJobPlanned"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); PlanMaintenanceJobCommandHandler sut = new PlanMaintenanceJobCommandHandler(messagePublisherMock.Object, repoMock.Object); // act WorkshopPlanning result = await sut.HandleCommandAsync(date, command); // assert messagePublisherMock.VerifyAll(); messagePublisherMock.VerifyNoOtherCalls(); repoMock.VerifyAll(); repoMock.VerifyNoOtherCalls(); Assert.IsAssignableFrom <WorkshopPlanning>(result); }
public async void Given_An_Existing_Job_The_Handler_Should_Handle_The_Command() { // arrange DateTime date = DateTime.Today; string workshopPlanningId = date.ToString("yyy-MM-dd"); var initializingEvents = new Event[] { new WorkshopPlanningCreatedEventBuilder().WithDate(date).Build() }; WorkshopPlanning planning = new WorkshopPlanning(date, initializingEvents); PlanMaintenanceJob command = new PlanMaintenanceJobCommandBuilder() .Build(); Mock <IMessagePublisher> messagePublisherMock = new Mock <IMessagePublisher>(); Mock <IEventSourceRepository <WorkshopPlanning> > repoMock = new Mock <IEventSourceRepository <WorkshopPlanning> >(); repoMock .Setup(m => m.GetByIdAsync(It.Is <string>(p => p == workshopPlanningId))) .Returns(Task.FromResult(planning)); repoMock .Setup(m => m.SaveAsync( It.Is <string>(p => p == planning.Id), It.Is <int>(p => p == 1), It.Is <int>(p => p == 2), It.IsAny <List <Event> >() )) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "MaintenanceJobPlanned"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); PlanMaintenanceJobCommandHandler sut = new PlanMaintenanceJobCommandHandler(messagePublisherMock.Object, repoMock.Object); // act WorkshopPlanning result = await sut.HandleCommandAsync(date, command); // assert messagePublisherMock.VerifyAll(); messagePublisherMock.VerifyNoOtherCalls(); repoMock.VerifyAll(); repoMock.VerifyNoOtherCalls(); Assert.IsAssignableFrom <WorkshopPlanning>(result); }
public async void Given_A_Non_Existing_Job_The_Handler_Should_Return_Null() { // arrange DateTime date = DateTime.Today; PlanMaintenanceJob command = new PlanMaintenanceJobCommandBuilder() .Build(); Mock <IMessagePublisher> messagePublisherMock = new Mock <IMessagePublisher>(MockBehavior.Strict); Mock <IWorkshopPlanningRepository> repoMock = new Mock <IWorkshopPlanningRepository>(MockBehavior.Strict); repoMock .Setup(m => m.GetWorkshopPlanningAsync(It.Is <DateTime>(p => p == date))) .Returns(Task.FromResult <WorkshopPlanning>(null)); repoMock .Setup(m => m.SaveWorkshopPlanningAsync( It.Is <string>(p => p == date.ToString("yyyy-MM-dd")), It.Is <int>(p => p == 0), It.Is <int>(p => p == 2), It.Is <List <Event> >(p => p[0].MessageType == "WorkshopPlanningCreated" && p[1].MessageType == "MaintenanceJobPlanned") )) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "WorkshopPlanningCreated"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "MaintenanceJobPlanned"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); PlanMaintenanceJobCommandHandler sut = new PlanMaintenanceJobCommandHandler(messagePublisherMock.Object, repoMock.Object); // act WorkshopPlanning result = await sut.HandleCommandAsync(date, command); // assert messagePublisherMock.VerifyAll(); repoMock.VerifyAll(); Assert.IsAssignableFrom <WorkshopPlanning>(result); }
public void Finish_MaintenanceJob_Should_Finish_A_New_MaintenanceJob() { // arrange DateTime date = DateTime.Today; string workshopPlanningId = date.ToString("yyyy-MM-dd"); Guid jobId = Guid.NewGuid(); DateTime startTime = date.AddHours(8); DateTime endTime = date.AddHours(11); DateTime actualStartTime = date.AddHours(9); DateTime actualEndTime = date.AddHours(12); var initializingEvents = new Event[] { new WorkshopPlanningCreatedEventBuilder() .WithDate(date) .Build(), new MaintenanceJobPlannedEventBuilder() .WithStartTime(startTime) .WithEndTime(endTime) .WithJobId(jobId) .Build() }; WorkshopPlanning sut = new WorkshopPlanning(date, initializingEvents); FinishMaintenanceJob command = new FinishMaintenanceJobCommandBuilder() .WithJobId(jobId) .WithActualStartTime(actualStartTime) .WithActualEndTime(actualEndTime) .Build(); // act sut.FinishMaintenanceJob(command); IEnumerable <Event> events = sut.GetEvents(); // assert Assert.NotNull(sut); Assert.NotNull(sut.Id); Assert.Equal(workshopPlanningId, sut.Id); Assert.Equal(2, sut.OriginalVersion); Assert.Equal(3, sut.Version); Assert.Collection(sut.Jobs, item0 => { Assert.Equal(command.JobId, item0.Id); Assert.Equal(startTime, item0.StartTime); Assert.Equal(endTime, item0.EndTime); Assert.Equal(command.StartTime, item0.ActualStartTime); Assert.Equal(command.Notes, item0.Notes); } ); Assert.Collection(events, item0 => Assert.IsAssignableFrom <MaintenanceJobFinished>(item0)); }
public void Updating_A_Job_That_Conflicts_With_MaintenanceJobs_In_Parallel_Should_Throw_Exception() { // arrange var date = DateTime.Today; var jobId = Guid.NewGuid(); var startTime = date.AddHours(12); var endTime = date.AddHours(13); var createdEvent = new WorkshopPlanningCreatedEventBuilder() .WithDate(date) .Build(); var plannedEvent1 = new MaintenanceJobPlannedEventBuilder() .Build(); var plannedEvent2 = new MaintenanceJobPlannedEventBuilder() .Build(); var plannedEvent3 = new MaintenanceJobPlannedEventBuilder() .Build(); var plannedEvent4 = new MaintenanceJobPlannedEventBuilder() .WithStartTime(startTime) .WithEndTime(endTime) .WithJobId(jobId) .Build(); var initializingEvents = new Event[] { createdEvent, plannedEvent1, plannedEvent2, plannedEvent3, plannedEvent4 }; var sut = new WorkshopPlanning(date, initializingEvents); var command = new UpdateMaintenanceJobCommandBuilder() .WithEvent(plannedEvent4) .WithChangedStartTime(plannedEvent1.StartTime) .WithChangedEndTime(plannedEvent1.EndTime) .Build(); // act var thrownException = Assert.Throws <BusinessRuleViolationException>(() => { sut.UpdateMaintenanceJob(command); // 4th job is updated to conflict with the 1st job }); // assert Assert.Equal("Maintenancejob overlaps with more than 3 other jobs.", thrownException.Message); }
public async Task <IActionResult> PlanMaintenanceJobAsync(DateTime date, [FromBody] PlanMaintenanceJob command) { try { if (ModelState.IsValid) { // get planning WorkshopPlanning planning = await _planningRepo.GetWorkshopPlanningAsync(date); if (planning == null) { return(NotFound()); } // handle command try { IEnumerable <Event> events = planning.PlanMaintenanceJob(command); // persist await _planningRepo.SaveWorkshopPlanningAsync(planning, events); // publish event foreach (var e in events) { await _messagePublisher.PublishMessageAsync(e.MessageType, e, ""); } // return result return(CreatedAtRoute("GetByDate", new { date = planning.Date }, planning)); } catch (BusinessRuleViolationException ex) { return(StatusCode(StatusCodes.Status409Conflict, new BusinessRuleViolation { ErrorMessage = ex.Message })); } } return(BadRequest()); } catch (ConcurrencyException) { ModelState.AddModelError("ErrorMessage", "Unable to save changes. " + "Try again, and if the problem persists " + "see your system administrator."); return(StatusCode(StatusCodes.Status500InternalServerError)); } }
public async void Given_An_Existing_Job_The_Handler_Should_Handle_The_Command() { // arrange DateTime date = DateTime.Today; var initializingEvents = new Event[] { new WorkshopPlanningCreated(Guid.NewGuid(), date) }; WorkshopPlanning planning = new WorkshopPlanning(initializingEvents); PlanMaintenanceJob command = new PlanMaintenanceJobCommandBuilder() .Build(); Mock <IMessagePublisher> messagePublisherMock = new Mock <IMessagePublisher>(MockBehavior.Strict); Mock <IWorkshopPlanningRepository> repoMock = new Mock <IWorkshopPlanningRepository>(MockBehavior.Strict); repoMock .Setup(m => m.GetWorkshopPlanningAsync(It.Is <DateTime>(p => p == date))) .Returns(Task.FromResult(planning)); repoMock .Setup(m => m.SaveWorkshopPlanningAsync( It.Is <string>(p => p == planning.Id), It.Is <int>(p => p == 1), It.Is <int>(p => p == 2), It.IsAny <List <Event> >() )) .Returns(Task.CompletedTask); messagePublisherMock .Setup(m => m.PublishMessageAsync( It.Is <string>(p => p == "MaintenanceJobPlanned"), It.IsAny <object>(), "")) .Returns(Task.CompletedTask); PlanMaintenanceJobCommandHandler sut = new PlanMaintenanceJobCommandHandler(messagePublisherMock.Object, repoMock.Object); // act WorkshopPlanning result = await sut.HandleCommandAsync(date, command); // assert messagePublisherMock.VerifyAll(); repoMock.VerifyAll(); Assert.IsAssignableFrom <WorkshopPlanning>(result); }
public void Create_Should_Create_A_New_Instance() { // arrange DateTime date = DateTime.Today; // act List <Event> events = new List <Event>(WorkshopPlanning.Create(date, out WorkshopPlanning sut)); // assert Assert.NotNull(sut); Assert.NotNull(sut.Id); Assert.Equal(date, sut.Date); Assert.Equal(0, sut.OriginalVersion); Assert.Equal(1, sut.Version); Assert.Empty(sut.Jobs); Assert.Collection(events, item0 => Assert.IsAssignableFrom <WorkshopPlanningCreated>(item0)); }
public async Task <WorkshopPlanning> GetWorkshopPlanningAsync(DateTime date) { WorkshopPlanning planning = null; using (SqlConnection conn = new SqlConnection(_connectionString)) { Aggregate aggregate = await conn .QueryFirstOrDefaultAsync <Aggregate>("select * from WorkshopPlanning where Id = @Id", new { Id = date.ToString("yyyy-MM-dd") }); if (aggregate != null) { IEnumerable <Event> events = DeserializeState(aggregate.EventData); planning = new WorkshopPlanning(events); } } return(planning); }
public void Finish_An_Already_Finished_MaintenanceJob_Should_Throw_Exception() { // arrange DateTime date = DateTime.Today; Guid jobId = Guid.NewGuid(); DateTime startTime = date.AddHours(8); DateTime endTime = date.AddHours(11); DateTime actualStartTime = date.AddHours(9); DateTime actualEndTime = date.AddHours(12); string notes = "Ok"; var initializingEvents = new Event[] { new WorkshopPlanningCreatedEventBuilder() .WithDate(date) .Build(), new MaintenanceJobPlannedEventBuilder() .WithStartTime(startTime) .WithEndTime(endTime) .WithJobId(jobId) .Build(), new MaintenanceJobFinishedEventBuilder() .WithJobId(jobId) .WithActualStartTime(actualStartTime) .WithActualEndTime(actualEndTime) .WithNotes(notes) .Build() }; WorkshopPlanning sut = new WorkshopPlanning(initializingEvents); FinishMaintenanceJob command = new FinishMaintenanceJobCommandBuilder() .WithJobId(jobId) .WithActualStartTime(actualStartTime) .WithActualEndTime(actualEndTime) .WithNotes(notes) .Build(); // act var thrownException = Assert.Throws <BusinessRuleViolationException>(() => sut.FinishMaintenanceJob(command)); // assert Assert.Equal("An already finished job can not be finished.", thrownException.Message); }