Skip to content

Commit 46e64d7

Browse files
authored
Merge pull request #25 from DiyorMarket/signalR-integration
SignalR integration
2 parents 5770677 + cd4970c commit 46e64d7

File tree

53 files changed

+2992
-272
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2992
-272
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using CheckDrive.Application.DTOs.Car;
2+
using CheckDrive.Application.Interfaces;
3+
using Microsoft.AspNetCore.Mvc;
4+
5+
namespace CheckDrive.Api.Controllers;
6+
7+
[Route("api/cars")]
8+
[ApiController]
9+
public class CarsController : ControllerBase
10+
{
11+
private readonly ICarService _carService;
12+
13+
public CarsController(ICarService carService)
14+
{
15+
_carService = carService;
16+
}
17+
18+
[HttpGet]
19+
public async Task<ActionResult<List<CarDto>>> GetAvailableCars()
20+
{
21+
var cars = await _carService.GetAvailableCarsAsync();
22+
23+
return Ok(cars);
24+
}
25+
}

CheckDrive.Api/CheckDrive.Api/Controllers/CheckPointsController.cs

+8
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,12 @@ public async Task<ActionResult<List<CheckPointDto>>> GetCheckPointsAsync([FromQu
2323

2424
return Ok(checkPoints);
2525
}
26+
27+
[HttpGet("drivers/{driverId:int}/current")]
28+
public async Task<ActionResult<CheckPointDto>> GetCurrentCheckPointByDriverIdAsync(int driverId)
29+
{
30+
var checkPoint = await _service.GetCurrentCheckPointByDriverIdAsync(driverId);
31+
32+
return Ok(checkPoint);
33+
}
2634
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using CheckDrive.Application.DTOs.Driver;
2+
using CheckDrive.Application.Interfaces;
3+
using Microsoft.AspNetCore.Mvc;
4+
5+
namespace CheckDrive.Api.Controllers;
6+
7+
[Route("api/drivers")]
8+
[ApiController]
9+
public class DriversController : ControllerBase
10+
{
11+
private readonly IDriverService _driverService;
12+
13+
public DriversController(IDriverService driverService)
14+
{
15+
_driverService = driverService ?? throw new ArgumentNullException(nameof(driverService));
16+
}
17+
18+
[HttpGet]
19+
public async Task<ActionResult<List<DriverDto>>> GetAvailableDriversAsync()
20+
{
21+
var drivers = await _driverService.GetAvailableDriversAsync();
22+
23+
return Ok(drivers);
24+
}
25+
26+
[HttpPost("reviews")]
27+
public async Task<IActionResult> CreateReviewConfirmation(DriverReviewConfirmationDto confirmationDto)
28+
{
29+
await _driverService.CreateReviewConfirmation(confirmationDto);
30+
31+
return NoContent();
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using CheckDrive.Application.DTOs.OilMark;
2+
using CheckDrive.Application.Interfaces;
3+
using Microsoft.AspNetCore.Mvc;
4+
5+
namespace CheckDrive.Api.Controllers;
6+
7+
[Route("api/oilMarks")]
8+
[ApiController]
9+
public class OilMarksController : ControllerBase
10+
{
11+
private readonly IOilMarkService _oilMarkService;
12+
13+
public OilMarksController(IOilMarkService oilMarkService)
14+
{
15+
_oilMarkService = oilMarkService ?? throw new ArgumentNullException(nameof(oilMarkService));
16+
}
17+
18+
[HttpGet]
19+
public async Task<ActionResult<List<OilMarkDto>>> GetAsync()
20+
{
21+
var oilMarks = await _oilMarkService.GetAllAsync();
22+
23+
return Ok(oilMarks);
24+
}
25+
}

CheckDrive.Api/CheckDrive.Api/Extensions/DependencyInjection.cs

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ public static IServiceCollection ConfigureServices(this IServiceCollection servi
2020
services.RegisterInfrastructure(configuration);
2121

2222
services.AddSingleton<FileExtensionContentTypeProvider>();
23+
services.AddSignalR(options =>
24+
{
25+
options.EnableDetailedErrors = true;
26+
});
2327

2428
AddControllers(services);
2529
AddSwagger(services);

CheckDrive.Api/CheckDrive.Api/Program.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using CheckDrive.Api.Extensions;
22
using CheckDrive.Api.Helpers;
3+
using CheckDrive.Application.Hubs;
34
using Microsoft.AspNetCore.CookiePolicy;
45
using Serilog;
56

67
Log.Logger = new LoggerConfiguration()
7-
.MinimumLevel.Verbose()
8+
.MinimumLevel.Information()
89
.Enrich.FromLogContext()
910
.WriteTo.Console(new CustomJsonFormatter())
1011
.WriteTo.File(new CustomJsonFormatter(), "logs/logs.txt", rollingInterval: RollingInterval.Day)
@@ -44,6 +45,8 @@
4445

4546
app.MapControllers();
4647

48+
app.MapHub<ReviewHub>("/review-hub");
49+
4750
app.Run();
4851

4952
// For API testing
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using CheckDrive.Domain.Interfaces;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.Hosting;
5+
6+
namespace CheckDrive.Application.BackgroundJobs;
7+
8+
internal sealed class CarMonthlyMileageResetService : BackgroundService
9+
{
10+
private readonly IServiceProvider _serviceProvider;
11+
12+
public CarMonthlyMileageResetService(IServiceProvider serviceProvider)
13+
{
14+
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
15+
}
16+
17+
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
18+
{
19+
while (!stoppingToken.IsCancellationRequested)
20+
{
21+
DateTime now = DateTime.UtcNow;
22+
23+
// Check if it's the first day of the month at midnight UTC
24+
if (now.Day == 1 && now.Hour == 0)
25+
{
26+
await ResetCarMonthlyMileage(stoppingToken);
27+
}
28+
29+
await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
30+
}
31+
}
32+
33+
private async Task ResetCarMonthlyMileage(CancellationToken stoppingToken)
34+
{
35+
using var scope = _serviceProvider.CreateScope();
36+
var context = scope.ServiceProvider.GetRequiredService<ICheckDriveDbContext>();
37+
38+
await context.Cars.ExecuteUpdateAsync(
39+
x => x.SetProperty(x => x.CurrentMonthMileage, 0),
40+
stoppingToken);
41+
}
42+
}

CheckDrive.Api/CheckDrive.Application/DTOs/Account/AccountDto.cs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ namespace CheckDrive.Application.DTOs.Account;
44

55
public record class AccountDto(
66
string Id,
7+
string AccountId,
78
string Username,
89
string PhoneNumber,
910
string? Email,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using CheckDrive.Domain.Enums;
2+
3+
namespace CheckDrive.Application.DTOs.Car;
4+
5+
public sealed record CarDto(
6+
int Id,
7+
string Model,
8+
string Color,
9+
string Number,
10+
int ManufacturedYear,
11+
int Mileage,
12+
int CurrentMonthMileage,
13+
int YearlyDistanceLimit,
14+
decimal AverageFuelConsumption,
15+
decimal FuelCapacity,
16+
decimal RemainingFuel,
17+
CarStatus Status);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using CheckDrive.Application.DTOs.Car;
2+
using CheckDrive.Application.DTOs.Review;
3+
using CheckDrive.Domain.Enums;
4+
5+
namespace CheckDrive.Application.DTOs.CheckPoint;
6+
7+
public sealed record DriverCheckPointDto(
8+
int Id,
9+
DateTime StartDate,
10+
CheckPointStage Stage,
11+
CheckPointStatus Status,
12+
string DriverName,
13+
CarDto? Car,
14+
List<DriverReviewDto> Reviews);

CheckDrive.Api/CheckDrive.Application/DTOs/DispatcherReview/DispatcherReviewDto.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ public sealed record DispatcherReviewDto(
2323
Notes: Notes,
2424
Date: Date,
2525
Status: Status,
26-
Type: ReviewType.Dispatcher);
26+
Type: ReviewType.DispatcherReview);

CheckDrive.Api/CheckDrive.Application/DTOs/DoctorReview/DoctorReviewDto.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ public sealed record DoctorReviewDto(
2121
Date: Date,
2222
Notes: Notes,
2323
Status: Status,
24-
Type: ReviewType.Doctor);
24+
Type: ReviewType.DoctorReview);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace CheckDrive.Application.DTOs.Driver;
2+
3+
public record DriverDto(
4+
int Id,
5+
string AccountId,
6+
string FullName);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using CheckDrive.Domain.Enums;
2+
3+
namespace CheckDrive.Application.DTOs.Driver;
4+
5+
public sealed record DriverReviewConfirmationDto(
6+
int CheckPointId,
7+
ReviewType ReviewType,
8+
bool IsAcceptedByDriver,
9+
string? Notes);

CheckDrive.Api/CheckDrive.Application/DTOs/MechanicHandover/MechanicHandoverReviewDto.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using CheckDrive.Application.DTOs.Review;
1+
using CheckDrive.Application.DTOs.Car;
2+
using CheckDrive.Application.DTOs.Review;
23
using CheckDrive.Domain.Enums;
34

45
namespace CheckDrive.Application.DTOs.MechanicHandover;
@@ -12,7 +13,8 @@ public sealed record MechanicHandoverReviewDto(
1213
string? Notes,
1314
DateTime Date,
1415
ReviewStatus Status,
15-
int InitialMileage)
16+
int InitialMileage,
17+
CarDto Car)
1618
: ReviewDtoBase(
1719
CheckPointId: CheckPointId,
1820
ReviewerId: ReviewerId,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace CheckDrive.Application.DTOs.OilMark;
2+
3+
public sealed record OilMarkDto(
4+
int Id,
5+
string Name);

CheckDrive.Api/CheckDrive.Application/DTOs/OperatorReview/OperatorReviewDto.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ public sealed record OperatorReviewDto(
2525
Notes: Notes,
2626
Date: Date,
2727
Status: Status,
28-
Type: ReviewType.Operator);
28+
Type: ReviewType.OperatorReview);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using CheckDrive.Domain.Enums;
2+
3+
namespace CheckDrive.Application.DTOs.Review;
4+
5+
public sealed record DriverReviewDto(
6+
string? Notes,
7+
string ReviewerName,
8+
DateTime Date,
9+
ReviewType Type,
10+
ReviewStatus Status);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using CheckDrive.Domain.Enums;
2+
3+
namespace CheckDrive.Application.DTOs.Review;
4+
5+
public sealed record ReviewConfirmationDto(
6+
int CheckPointId,
7+
ReviewType ReviewType,
8+
string Message);

CheckDrive.Api/CheckDrive.Application/Extensions/DependencyInjection.cs

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.Extensions.DependencyInjection;
66
using CheckDrive.Application.Interfaces.Auth;
77
using CheckDrive.Application.Services.Auth;
8+
using CheckDrive.Application.BackgroundJobs;
89

910
namespace CheckDrive.Application.Extensions;
1011

@@ -28,5 +29,10 @@ private static void AddServices(IServiceCollection services)
2829
services.AddScoped<IDispatcherReviewService, DispatcherReviewService>();
2930
services.AddScoped<ICheckPointService, CheckPointService>();
3031
services.AddScoped<IAccountService, AccountService>();
32+
services.AddScoped<IDriverService, DriverService>();
33+
services.AddScoped<ICarService, CarService>();
34+
services.AddScoped<IOilMarkService, OilMarkService>();
35+
36+
services.AddHostedService<CarMonthlyMileageResetService>();
3137
}
3238
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using CheckDrive.Application.DTOs.MechanicAcceptance;
2+
using CheckDrive.Application.DTOs.MechanicHandover;
3+
using CheckDrive.Application.DTOs.OperatorReview;
4+
using CheckDrive.Application.DTOs.Review;
5+
6+
namespace CheckDrive.Application.Hubs;
7+
8+
public interface IReviewHub
9+
{
10+
Task NotifyDoctorReview(ReviewDtoBase review);
11+
Task MechanicHandoverConfirmation(MechanicHandoverReviewDto review);
12+
Task OperatorReviewConfirmation(OperatorReviewDto review);
13+
Task MechanicAcceptanceConfirmation(MechanicAcceptanceReviewDto review);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using CheckDrive.Application.DTOs.Review;
2+
using Microsoft.AspNetCore.SignalR;
3+
4+
namespace CheckDrive.Application.Hubs;
5+
6+
public sealed class ReviewHub : Hub<IReviewHub>
7+
{
8+
public async Task NotifyNewReviewAsync(ReviewDtoBase review)
9+
{
10+
await Clients
11+
.User(review.DriverId.ToString())
12+
.NotifyDoctorReview(review);
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
using Microsoft.AspNetCore.Identity;
1+
using CheckDrive.Domain.Entities;
22

33
namespace CheckDrive.Application.Interfaces.Auth;
44

55
public interface IJwtTokenGenerator
66
{
7-
string GenerateToken(IdentityUser user, IList<string> roles);
7+
string GenerateToken(Employee employee, IList<string> roles);
88
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using CheckDrive.Application.DTOs.Car;
2+
3+
namespace CheckDrive.Application.Interfaces;
4+
5+
public interface ICarService
6+
{
7+
Task<List<CarDto>> GetAvailableCarsAsync();
8+
}

CheckDrive.Api/CheckDrive.Application/Interfaces/ICheckPointService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ namespace CheckDrive.Application.Interfaces;
66
public interface ICheckPointService
77
{
88
Task<List<CheckPointDto>> GetCheckPointsAsync(CheckPointQueryParameters queryParameters);
9-
Task<CheckPointDto> GetCheckPointsByDriverIdAsync(int driverId);
9+
Task<CheckPointDto> GetCurrentCheckPointByDriverIdAsync(int driverId);
1010
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using CheckDrive.Application.DTOs.Driver;
2+
3+
namespace CheckDrive.Application.Interfaces;
4+
5+
public interface IDriverService
6+
{
7+
Task<List<DriverDto>> GetAvailableDriversAsync();
8+
Task CreateReviewConfirmation(DriverReviewConfirmationDto confirmation);
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using CheckDrive.Application.DTOs.OilMark;
2+
3+
namespace CheckDrive.Application.Interfaces;
4+
5+
public interface IOilMarkService
6+
{
7+
Task<List<OilMarkDto>> GetAllAsync();
8+
}

CheckDrive.Api/CheckDrive.Application/Mappings/AccountMappings.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ internal sealed class AccountMappings : Profile
1010
public AccountMappings()
1111
{
1212
CreateMap<Employee, AccountDto>()
13-
.ForCtorParam(nameof(AccountDto.Id), cfg => cfg.MapFrom(e => e.AccountId))
13+
.ForCtorParam(nameof(AccountDto.Id), cfg => cfg.MapFrom(e => e.Id))
14+
.ForCtorParam(nameof(AccountDto.AccountId), cfg => cfg.MapFrom(e => e.AccountId))
1415
.ForCtorParam(nameof(AccountDto.Username), cfg => cfg.MapFrom(e => e.Account.UserName))
1516
.ForCtorParam(nameof(AccountDto.PhoneNumber), cfg => cfg.MapFrom(e => e.Account.PhoneNumber))
1617
.ForCtorParam(nameof(AccountDto.Email), cfg => cfg.MapFrom(e => e.Account.Email))

0 commit comments

Comments
 (0)