Skip to content

Commit

Permalink
added passenger, driver and company creation commands
Browse files Browse the repository at this point in the history
  • Loading branch information
AndriyBorkovich committed Apr 6, 2024
1 parent 81f8949 commit 614cd12
Show file tree
Hide file tree
Showing 29 changed files with 463 additions and 29 deletions.
8 changes: 4 additions & 4 deletions src/BSMS.API/Controllers/BusController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ namespace BSMS.API.Controllers;
public class BusController(ISender mediator) : ControllerBase
{
/// <summary>
/// Create new bus with its schedule
/// Create new bus with it's schedule
/// </summary>
/// <param name="command">Bus parameters and its schedule data</param>
/// <returns>ID of created bus</returns>
/// <param name="command">Bus data and its schedule data</param>
/// <returns>ID of the created bus</returns>
[HttpPost("Create")]
public async Task<ActionResult<int>> CreateBus(CreateBusCommand command)
public async Task<ActionResult<int>> Create(CreateBusCommand command)
{
var result = await mediator.Send(command);

Expand Down
25 changes: 25 additions & 0 deletions src/BSMS.API/Controllers/CompanyController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using BSMS.API.Extensions;
using BSMS.Application.Features.Company.Commands.Create;
using MediatR;
using Microsoft.AspNetCore.Mvc;

namespace BSMS.API.Controllers;

/// <inheritdoc />
[ApiController]
[Route("api/[controller]")]
public class CompanyController(ISender sender) : ControllerBase
{
/// <summary>
/// Create new transport company
/// </summary>
/// <param name="command">Company's data</param>
/// <returns>ID of the created company</returns>
[HttpPost("Create")]
public async Task<ActionResult<int>> Create(CreateCompanyCommand command)
{
var result = await sender.Send(command);

return result.DecideWhatToReturn();
}
}
25 changes: 25 additions & 0 deletions src/BSMS.API/Controllers/DriverController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using BSMS.API.Extensions;
using BSMS.Application.Features.Driver.Commands.Create;
using MediatR;
using Microsoft.AspNetCore.Mvc;

namespace BSMS.API.Controllers;

/// <inheritdoc />
[ApiController]
[Route("api/[controller]")]
public class DriverController(ISender mediator) : ControllerBase
{
/// <summary>
/// Create new driver (with company and bus (both optional))
/// </summary>
/// <param name="command">Driver data</param>
/// <returns>ID of the created driver</returns>
[HttpPost("Create")]
public async Task<ActionResult<int>> Create(CreateDriverCommand command)
{
var result = await mediator.Send(command);

return result.DecideWhatToReturn();
}
}
25 changes: 25 additions & 0 deletions src/BSMS.API/Controllers/PassengerController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using BSMS.API.Extensions;
using BSMS.Application.Features.Passenger.Commands.Create;
using MediatR;
using Microsoft.AspNetCore.Mvc;

namespace BSMS.API.Controllers;

/// <inheritdoc />
[ApiController]
[Route("api/[controller]")]
public class PassengerController(ISender mediator) : ControllerBase
{
/// <summary>
/// Create new passenger
/// </summary>
/// <param name="command">Passenger's data</param>
/// <returns>ID of the created passenger</returns>
[HttpPost("Create")]
public async Task<ActionResult<int>> Create(CreatePassengerCommand command)
{
var result = await mediator.Send(command);

return result.DecideWhatToReturn();
}
}
4 changes: 2 additions & 2 deletions src/BSMS.API/Controllers/RouteController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ namespace BSMS.API.Controllers;
public class RouteController(ISender mediator) : ControllerBase
{
/// <summary>
/// create new route (with stops included)
/// Create new route (with stops included)
/// </summary>
/// <param name="command">Contains origin and destination of route and list of it's stops names</param>
/// <returns></returns>
/// <returns>ID of the created route</returns>
[HttpPost("Create")]
public async Task<ActionResult<int>> Create(CreateRouteCommand command)
{
Expand Down
17 changes: 16 additions & 1 deletion src/BSMS.Application/ApplicationRegistration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using System.Reflection;
using BSMS.Application.Features.Bus.Commands.Create;
using BSMS.Application.Features.Company.Commands.Create;
using BSMS.Application.Features.Driver.Commands.Create;
using BSMS.Application.Features.Passenger.Commands.Create;
using BSMS.Application.Features.Route.Commands.Create;
using BSMS.Application.Helpers;
using FluentValidation;
Expand All @@ -20,7 +24,18 @@ public static IServiceCollection AddApplicationServices(this IServiceCollection
services.AddScoped<IMapper, ServiceMapper>();

services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));
services.AddScoped<IValidator<CreateRouteCommand>, CreateRouteCommandValidator>();

AddValidators(services);

return services;
}

private static void AddValidators(IServiceCollection services)
{
services.AddScoped<IValidator<CreateRouteCommand>, CreateRouteCommandValidator>();
services.AddScoped<IValidator<CreateBusCommand>, CreateBusCommandValidator>();
services.AddScoped<IValidator<CreatePassengerCommand>, CreatePassengerCommandValidator>();
services.AddScoped<IValidator<CreateDriverCommand>, CreateDriverCommandValidator>();
services.AddScoped<IValidator<CreateCompanyCommand>, CreateCompanyCommandValidator>();
}
}
2 changes: 0 additions & 2 deletions src/BSMS.Application/BSMS.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@

<ItemGroup>
<Folder Include="Contracts\Services\" />
<Folder Include="Features\Bus\Commands\Delete\" />
<Folder Include="Features\Bus\Commands\Edit\" />
<Folder Include="Features\Bus\Queries\" />
<Folder Include="Features\Passenger\" />
<Folder Include="Features\Route\Queries\" />
</ItemGroup>

Expand Down
9 changes: 0 additions & 9 deletions src/BSMS.Application/Contracts/IRouteRepository.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using BSMS.Core.Entities;

namespace BSMS.Application.Contracts.Persistence;

public interface ICompanyRepository : IGenericRepository<Company>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using BSMS.Core.Entities;

namespace BSMS.Application.Contracts.Persistence;

public interface IDriverRepository : IGenericRepository<Driver>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using BSMS.Core.Entities;

namespace BSMS.Application.Contracts.Persistence;

public interface IPassengerRepository : IGenericRepository<Passenger>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using BSMS.Core.Entities;

namespace BSMS.Application.Contracts.Persistence;

public interface IRouteRepository : IGenericRepository<Route>
{

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using BSMS.Application.Contracts;
using BSMS.Application.Contracts.Persistence;
using BSMS.Application.Helpers;
using FluentValidation;

namespace BSMS.Application.Features.Bus.Commands.Create;
Expand All @@ -10,6 +11,22 @@ public CreateBusCommandValidator(IRouteRepository routeRepository)
{
_routeRepository = routeRepository;

RuleFor(c => c.Brand)
.NotEmpty()
.Length(3, 50)
.Matches(RegexConstants.LettersOnly)
.WithMessage("{PropertyName} must consist only from letters");

RuleFor(c => c.Capacity)
.GreaterThanOrEqualTo(5)
.LessThanOrEqualTo(30);

RuleFor(c => c.Number)
.NotEmpty()
.Length(3, 7)
.Matches(RegexConstants.LettersAndNumbers)
.WithMessage("{PropertyName} must consist only from letters and numbers");

RuleFor(c => c)
.MustAsync(HaveValidRoutesForSchedule)
.WithMessage("Invalid routes selected");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Net;
using BSMS.Application.Contracts.Persistence;
using BSMS.Application.Extensions;
using BSMS.Application.Features.Common;
using BSMS.Application.Helpers;
using FluentValidation;
using MapsterMapper;
using MediatR;

namespace BSMS.Application.Features.Company.Commands.Create;

public record CreateCompanyCommand(
string Name,
string Address,
string Phone,
string Email) : IRequest<MethodResult<CreatedEntityResponse>>;

public class CreateCompanyCommandHandler(
ICompanyRepository repository,
IMapper mapper,
IValidator<CreateCompanyCommand> validator,
MethodResultFactory methodResultFactory)
: IRequestHandler<CreateCompanyCommand, MethodResult<CreatedEntityResponse>>
{
public async Task<MethodResult<CreatedEntityResponse>> Handle(CreateCompanyCommand request, CancellationToken cancellationToken)
{
var result = methodResultFactory.Create<CreatedEntityResponse>();

var validationResult = await validator.ValidateAsync(request, cancellationToken);
if (!validationResult.IsValid)
{
result.SetError(validationResult.Errors.ToResponse(), HttpStatusCode.BadRequest);
return result;
}

var company = mapper.Map<Core.Entities.Company>(request);

await repository.InsertAsync(company);

result.Data = new CreatedEntityResponse(company.CompanyId);

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using BSMS.Application.Helpers;
using FluentValidation;

namespace BSMS.Application.Features.Company.Commands.Create;

public class CreateCompanyCommandValidator : AbstractValidator<CreateCompanyCommand>
{
public CreateCompanyCommandValidator()
{
RuleFor(c => c.Name)
.NotEmpty()
.NotNull()
.Length(3, 50)
.Matches(RegexConstants.LettersOnly)
.WithMessage("{PropertyName} must consist only from letters");

RuleFor(c => c.Phone)
.NotEmpty()
.Matches(RegexConstants.PhoneNumber)
.WithMessage("Invalid phone number format");

RuleFor(c => c.Email)
.NotEmpty()
.MaximumLength(50)
.Matches(RegexConstants.Email)
.WithMessage("Invalid email format");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Net;
using BSMS.Application.Contracts.Persistence;
using BSMS.Application.Extensions;
using BSMS.Application.Features.Common;
using BSMS.Application.Helpers;
using FluentValidation;
using MapsterMapper;
using MediatR;

namespace BSMS.Application.Features.Driver.Commands.Create;

public record CreateDriverCommand(
string FirstName,
string LastName,
string DriverLicense,
int? CompanyId,
int? BusId) : IRequest<MethodResult<CreatedEntityResponse>>;

public class CreateDriverCommandHandler(
IDriverRepository repository,
IMapper mapper,
IValidator<CreateDriverCommand> validator,
MethodResultFactory methodResultFactory) : IRequestHandler<CreateDriverCommand, MethodResult<CreatedEntityResponse>>
{
public async Task<MethodResult<CreatedEntityResponse>> Handle(CreateDriverCommand request, CancellationToken cancellationToken)
{
var result = methodResultFactory.Create<CreatedEntityResponse>();

var validationResult = await validator.ValidateAsync(request, cancellationToken);
if (!validationResult.IsValid)
{
result.SetError(validationResult.Errors.ToResponse(), HttpStatusCode.BadRequest);
return result;
}

var driver = mapper.Map<Core.Entities.Driver>(request);

await repository.InsertAsync(driver);

result.Data = new CreatedEntityResponse(driver.DriverId);

return result;
}
}
Loading

0 comments on commit 614cd12

Please sign in to comment.