diff --git a/docker-compose.test.yml b/docker-compose.test.yml
index d7d44b92..993b5ad1 100644
--- a/docker-compose.test.yml
+++ b/docker-compose.test.yml
@@ -8,7 +8,7 @@ services:
ports:
- '8888:80'
environment:
- - ASPNETCORE_ENVIRONMENT=Development
+ - ASPNETCORE_ENVIRONMENT=Testing
- PROFILE_DatabaseSettings__ConnectionString=Server=database;Port=5432;Database=mytestdb;User ID=profiletester;Password=supasupasecured;
depends_on:
database:
diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj
index 09720f26..11e16ecd 100644
--- a/src/Api/Api.csproj
+++ b/src/Api/Api.csproj
@@ -4,6 +4,7 @@
net6.0
enable
enable
+ true
diff --git a/src/Api/ConfigureServices.cs b/src/Api/ConfigureServices.cs
index 6dea0c7d..39dabb10 100644
--- a/src/Api/ConfigureServices.cs
+++ b/src/Api/ConfigureServices.cs
@@ -1,6 +1,8 @@
+using System.Reflection;
using Api.Middlewares;
using Api.Policies;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
+using Microsoft.OpenApi.Models;
namespace Api;
@@ -31,7 +33,18 @@ public static IServiceCollection AddApiServices(this IServiceCollection services
// For swagger
services.AddEndpointsApiExplorer();
- services.AddSwaggerGen();
+ services.AddSwaggerGen(options =>
+ {
+ options.SwaggerDoc("v1", new OpenApiInfo
+ {
+ Version = "v1",
+ Title = "ProFile API",
+ Description = "An ASP.NET Core Web API for managing documents",
+ });
+
+ var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
+ options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
+ });
return services;
}
diff --git a/src/Api/Controllers/AuthController.cs b/src/Api/Controllers/AuthController.cs
index efdd1591..a770a036 100644
--- a/src/Api/Controllers/AuthController.cs
+++ b/src/Api/Controllers/AuthController.cs
@@ -1,6 +1,6 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Authentication;
-using Api.Controllers.Payload.Requests;
+using Api.Controllers.Payload.Requests.Auth;
using Api.Controllers.Payload.Responses;
using Application.Common.Interfaces;
using Application.Common.Models;
@@ -23,6 +23,11 @@ public AuthController(IIdentityService identityService)
_identityService = identityService;
}
+ ///
+ /// Login
+ ///
+ /// Login credentials
+ /// A LoginResult indicating the result of logging in
[AllowAnonymous]
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
@@ -48,23 +53,11 @@ public async Task>> Login([FromBody] LoginModel
return Ok(Result.Succeed(loginResult));
}
-
- [HttpPost]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status401Unauthorized)]
- public async Task Logout()
- {
- var refreshToken = Request.Cookies[nameof(RefreshToken)];
- var jweToken = Request.Cookies["JweToken"];
-
- RemoveJweToken();
- RemoveRefreshToken();
-
- await _identityService.LogoutAsync(jweToken!, refreshToken!);
-
- return Ok();
- }
-
+
+ ///
+ /// Refresh session and token
+ ///
+ /// An IActionResult indicating the result of refreshing token
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
@@ -90,6 +83,10 @@ public async Task Refresh()
return Ok();
}
+ ///
+ /// Validate current user
+ ///
+ /// An IActionResult indicating the result of validating the user
[Authorize]
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
@@ -99,11 +96,32 @@ public IActionResult Validate()
return Ok();
}
+ ///
+ /// Logout of the system
+ ///
+ /// An IActionResult indicating the result of logging out of the system
+ [HttpPost]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ public async Task Logout()
+ {
+ var refreshToken = Request.Cookies[nameof(RefreshToken)];
+ var jweToken = Request.Cookies["JweToken"];
+
+ RemoveJweToken();
+ RemoveRefreshToken();
+
+ await _identityService.LogoutAsync(jweToken!, refreshToken!);
+
+ return Ok();
+ }
+
private void SetJweToken(SecurityToken jweToken, RefreshTokenDto newRefreshToken)
{
var cookieOptions = new CookieOptions
{
HttpOnly = true,
+ Expires = newRefreshToken.ExpiryDateTime
};
var handler = new JwtSecurityTokenHandler();
Response.Cookies.Append("JweToken", handler.WriteToken(jweToken), cookieOptions);
diff --git a/src/Api/Controllers/DepartmentsController.cs b/src/Api/Controllers/DepartmentsController.cs
index 98045cf7..bf01c28a 100644
--- a/src/Api/Controllers/DepartmentsController.cs
+++ b/src/Api/Controllers/DepartmentsController.cs
@@ -1,10 +1,8 @@
-using Api.Controllers.Payload.Requests;
+using Api.Controllers.Payload.Requests.Departments;
using Application.Common.Models;
-using Application.Departments.Commands.DeleteDepartment;
-using Application.Departments.Commands.UpdateDepartment;
-using Application.Departments.Commands.AddDepartment;
-using Application.Departments.Queries.GetAllDepartments;
-using Application.Departments.Queries.GetDepartmentById;
+using Application.Common.Models.Dtos;
+using Application.Departments.Commands;
+using Application.Departments.Queries;
using Application.Identity;
using Application.Users.Queries;
using Infrastructure.Identity.Authorization;
@@ -15,52 +13,57 @@ namespace Api.Controllers;
public class DepartmentsController : ApiControllerBase
{
///
- /// Create a department
+ /// Get back a department based on its id
///
- /// command parameter to create a department
- /// Result[DepartmentDto]
- [RequiresRole(IdentityData.Roles.Admin)]
- [HttpPost]
+ /// id of the department to be retrieved
+ /// A DepartmentDto of the retrieved department
+ [HttpGet("{departmentId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
- [ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> AddDepartment([FromBody] AddDepartmentCommand command)
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public async Task>> GetById([FromRoute] Guid departmentId)
{
- var result = await Mediator.Send(command);
+ var query = new GetDepartmentById.Query()
+ {
+ DepartmentId = departmentId
+ };
+ var result = await Mediator.Send(query);
return Ok(Result.Succeed(result));
}
-
+
///
/// Get all documents
///
- /// a Result of an IEnumerable of DepartmentDto
+ /// A list of DocumentDto
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
- public async Task>>> GetAllDepartments()
+ public async Task>>> GetAll()
{
- var result = await Mediator.Send(new GetAllDepartmentsQuery());
+ var result = await Mediator.Send(new GetAllDepartments.Query());
return Ok(Result>.Succeed(result));
}
///
- /// Get back a department based on its id
+ /// Add a department
///
- /// id of the department to be retrieved
- /// A DepartmentDto of the retrieved department
- [HttpGet("{departmentId:guid}")]
+ /// Add department details
+ /// A DepartmentDto of the the added department
+ [RequiresRole(IdentityData.Roles.Admin)]
+ [HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
- public async Task>> GetDepartmentById([FromRoute] Guid departmentId)
+ [ProducesResponseType(StatusCodes.Status409Conflict)]
+ public async Task>> Add([FromBody] AddDepartmentRequest request)
{
- var query = new GetDepartmentByIdQuery()
+ var command = new AddDepartment.Command()
{
- DepartmentId = departmentId
+ Name = request.Name,
};
- var result = await Mediator.Send(query);
+ var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
+
///
/// Update a department
///
@@ -72,9 +75,9 @@ public async Task>> GetDepartmentById([FromRo
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> UpdateDepartment([FromRoute] Guid departmentId, [FromBody] UpdateDepartmentRequest request)
+ public async Task>> Update([FromRoute] Guid departmentId, [FromBody] UpdateDepartmentRequest request)
{
- var command = new UpdateDepartmentCommand()
+ var command = new UpdateDepartment.Command()
{
DepartmentId = departmentId,
Name = request.Name
@@ -93,9 +96,9 @@ public async Task>> UpdateDepartment([FromRou
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> DeleteDepartment([FromRoute] Guid departmentId)
+ public async Task>> Delete([FromRoute] Guid departmentId)
{
- var command = new DeleteDepartmentCommand()
+ var command = new DeleteDepartment.Command()
{
DepartmentId = departmentId,
};
diff --git a/src/Api/Controllers/DocumentsController.cs b/src/Api/Controllers/DocumentsController.cs
index 41f8fb3d..5c56986b 100644
--- a/src/Api/Controllers/DocumentsController.cs
+++ b/src/Api/Controllers/DocumentsController.cs
@@ -1,12 +1,8 @@
using Api.Controllers.Payload.Requests.Documents;
using Application.Common.Models;
using Application.Common.Models.Dtos.Physical;
-using Application.Documents.Commands.DeleteDocument;
-using Application.Documents.Commands.ImportDocument;
-using Application.Documents.Commands.UpdateDocument;
-using Application.Documents.Queries.GetAllDocumentsPaginated;
-using Application.Documents.Queries.GetDocumentById;
-using Application.Documents.Queries.GetDocumentTypes;
+using Application.Documents.Commands;
+using Application.Documents.Queries;
using Application.Identity;
using Infrastructure.Identity.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -15,65 +11,94 @@ namespace Api.Controllers;
public class DocumentsController : ApiControllerBase
{
- [RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
- [HttpPost]
+ ///
+ /// Get a document by id
+ ///
+ /// Id of the document to be retrieved
+ /// A DocumentDto of the retrieved document
+ [HttpGet("{documentId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- [ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> ImportDocument([FromBody] ImportDocumentCommand command)
+ public async Task>> GetById([FromRoute] Guid documentId)
{
- var result = await Mediator.Send(command);
+ var query = new GetDocumentById.Query()
+ {
+ DocumentId = documentId,
+ };
+ var result = await Mediator.Send(query);
return Ok(Result.Succeed(result));
}
- [RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
- [HttpGet("types")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status403Forbidden)]
- public async Task>>> GetAllDocumentTypes()
- {
- var result = await Mediator.Send(new GetAllDocumentTypesQuery());
- return Ok(Result>.Succeed(result));
- }
-
+ ///
+ /// Get all documents paginated
+ ///
+ /// Get all documents query parameters
+ /// A paginated list of DocumentDto
[RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>>> GetAllDocuments(Guid? roomId, Guid? lockerId, Guid? folderId, int? page, int? size, string? sortBy, string? sortOrder)
+ public async Task>>> GetAllPaginated(
+ [FromQuery] GetAllDocumentsPaginatedQueryParameters queryParameters)
{
- var query = new GetAllDocumentsPaginatedQuery()
+ var query = new GetAllDocumentsPaginated.Query()
{
- RoomId = roomId,
- LockerId = lockerId,
- FolderId = folderId,
- Page = page,
- Size = size,
- SortBy = sortBy,
- SortOrder = sortOrder
+ RoomId = queryParameters.RoomId,
+ LockerId = queryParameters.LockerId,
+ FolderId = queryParameters.FolderId,
+ SearchTerm = queryParameters.SearchTerm,
+ Page = queryParameters.Page,
+ Size = queryParameters.Size,
+ SortBy = queryParameters.SortBy,
+ SortOrder = queryParameters.SortOrder,
};
var result = await Mediator.Send(query);
return Ok(Result>.Succeed(result));
}
- [HttpGet("{id:guid}")]
+ ///
+ /// Get all document types
+ ///
+ /// A list of document types
+ [RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
+ [HttpGet("types")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
+ public async Task>>> GetAllDocumentTypes()
+ {
+ var result = await Mediator.Send(new GetAllDocumentTypes.Query());
+ return Ok(Result>.Succeed(result));
+ }
+
+ ///
+ /// Import a document
+ ///
+ /// Import document details
+ /// A DocumentDto of the imported document
+ [RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
+ [HttpPost]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> GetDocumentById(Guid id)
+ [ProducesResponseType(StatusCodes.Status409Conflict)]
+ public async Task>> Import([FromBody] ImportDocumentRequest request)
{
- var query = new GetDocumentByIdQuery()
+ var command = new ImportDocument.Command()
{
- Id = id
+ Title = request.Title,
+ Description = request.Description,
+ DocumentType = request.DocumentType,
+ FolderId = request.FolderId,
+ ImporterId = request.ImporterId,
};
- var result = await Mediator.Send(query);
+ var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
+
///
/// Update a document
///
@@ -86,9 +111,9 @@ public async Task>> GetDocumentById(Guid id)
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> UpdateDocument([FromRoute] Guid documentId, [FromBody] UpdateDocumentRequest request)
+ public async Task>> Update([FromRoute] Guid documentId, [FromBody] UpdateDocumentRequest request)
{
- var query = new UpdateDocumentCommand()
+ var query = new UpdateDocument.Command()
{
DocumentId = documentId,
Title = request.Title,
@@ -98,7 +123,7 @@ public async Task>> UpdateDocument([FromRoute]
var result = await Mediator.Send(query);
return Ok(Result.Succeed(result));
}
-
+
///
/// Delete a document
///
@@ -108,9 +133,9 @@ public async Task>> UpdateDocument([FromRoute]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> UpdateDocument([FromRoute] Guid documentId)
+ public async Task>> Delete([FromRoute] Guid documentId)
{
- var query = new DeleteDocumentCommand()
+ var query = new DeleteDocument.Command()
{
DocumentId = documentId,
};
diff --git a/src/Api/Controllers/FoldersController.cs b/src/Api/Controllers/FoldersController.cs
index 8ea03dd6..3365ec81 100644
--- a/src/Api/Controllers/FoldersController.cs
+++ b/src/Api/Controllers/FoldersController.cs
@@ -1,13 +1,8 @@
using Api.Controllers.Payload.Requests.Folders;
using Application.Common.Models;
using Application.Common.Models.Dtos.Physical;
-using Application.Folders.Commands.AddFolder;
-using Application.Folders.Commands.DisableFolder;
-using Application.Folders.Commands.EnableFolder;
-using Application.Folders.Commands.RemoveFolder;
-using Application.Folders.Commands.UpdateFolder;
-using Application.Folders.Queries.GetAllFoldersPaginated;
-using Application.Folders.Queries.GetFolderById;
+using Application.Folders.Commands;
+using Application.Folders.Queries;
using Application.Identity;
using Infrastructure.Identity.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -28,9 +23,9 @@ public class FoldersController : ApiControllerBase
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task>> GetById([FromRoute] Guid folderId)
{
- var query = new GetFolderByIdQuery()
+ var query = new GetFolderById.Query()
{
- FolderId = folderId
+ FolderId = folderId,
};
var result = await Mediator.Send(query);
return Ok(Result.Succeed(result));
@@ -39,7 +34,7 @@ public async Task>> GetById([FromRoute] Guid fold
///
/// Get all folders paginated
///
- /// Get all folders query parameters
+ /// Get all folders paginated query parameters
/// A paginated list of FolderDto
[RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
[HttpGet]
@@ -48,7 +43,7 @@ public async Task>> GetById([FromRoute] Guid fold
public async Task>>> GetAllPaginated(
[FromQuery] GetAllFoldersPaginatedQueryParameters queryParameters)
{
- var query = new GetAllFoldersPaginatedQuery()
+ var query = new GetAllFoldersPaginated.Query()
{
RoomId = queryParameters.RoomId,
LockerId = queryParameters.LockerId,
@@ -64,7 +59,7 @@ public async Task>>> GetAllPaginate
///
/// Add a folder
///
- /// Add folder details
+ /// Add folder details
/// A FolderDto of the added folder
[RequiresRole(IdentityData.Roles.Admin)]
[HttpPost]
@@ -73,8 +68,15 @@ public async Task>>> GetAllPaginate
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> AddFolder([FromBody] AddFolderCommand command)
+ public async Task>> AddFolder([FromBody] AddFolderRequest request)
{
+ var command = new AddFolder.Command()
+ {
+ Name = request.Name,
+ Description = request.Description,
+ Capacity = request.Capacity,
+ LockerId = request.LockerId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
@@ -93,7 +95,7 @@ public async Task>> AddFolder([FromBody] AddFolde
[ProducesResponseType(StatusCodes.Status409Conflict)]
public async Task>> RemoveFolder([FromRoute] Guid folderId)
{
- var command = new RemoveFolderCommand()
+ var command = new RemoveFolder.Command()
{
FolderId = folderId,
};
@@ -104,17 +106,21 @@ public async Task>> RemoveFolder([FromRoute] Guid
///
/// Enable a folder
///
- /// Enable folder details
+ /// Id of the folder to be enabled
/// A FolderDto of the enabled folder
[RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
- [HttpPut("enable")]
- [ProducesResponseType(StatusCodes.Status200OK)]
+ [HttpPut("enable/{folderId:guid}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> EnableFolder([FromBody] EnableFolderCommand command)
+ public async Task>> EnableFolder([FromRoute] Guid folderId)
{
+ var command = new EnableFolder.Command()
+ {
+ FolderId = folderId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
@@ -122,17 +128,21 @@ public async Task>> EnableFolder([FromBody] Enabl
///
/// Disable a folder
///
- /// Disable folder details
+ /// Id of the disabled folder
/// A FolderDto of the disabled folder
[RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
- [HttpPut("disable")]
+ [HttpPut("disable/{folderId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> DisableFolder([FromBody] DisableFolderCommand command)
+ public async Task>> DisableFolder([FromRoute] Guid folderId)
{
+ var command = new DisableFolder.Command()
+ {
+ FolderId = folderId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
@@ -150,12 +160,12 @@ public async Task>> DisableFolder([FromBody] Disa
[ProducesResponseType(StatusCodes.Status409Conflict)]
public async Task>> Update([FromRoute] Guid folderId, [FromBody] UpdateFolderRequest request)
{
- var command = new UpdateFolderCommand()
+ var command = new UpdateFolder.Command()
{
FolderId = folderId,
Name = request.Name,
Description = request.Description,
- Capacity = request.Capacity
+ Capacity = request.Capacity,
};
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
diff --git a/src/Api/Controllers/LockersController.cs b/src/Api/Controllers/LockersController.cs
index f064090e..373a0cee 100644
--- a/src/Api/Controllers/LockersController.cs
+++ b/src/Api/Controllers/LockersController.cs
@@ -1,15 +1,9 @@
-using Api.Controllers.Payload.Requests;
-using Api.Controllers.Payload.Requests.Lockers;
+using Api.Controllers.Payload.Requests.Lockers;
using Application.Common.Models;
using Application.Common.Models.Dtos.Physical;
using Application.Identity;
-using Application.Lockers.Commands.AddLocker;
-using Application.Lockers.Commands.DisableLocker;
-using Application.Lockers.Commands.EnableLocker;
-using Application.Lockers.Commands.RemoveLocker;
-using Application.Lockers.Commands.UpdateLocker;
-using Application.Lockers.Queries.GetAllLockersPaginated;
-using Application.Lockers.Queries.GetLockerById;
+using Application.Lockers.Commands;
+using Application.Lockers.Queries;
using Infrastructure.Identity.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -28,9 +22,9 @@ public class LockersController : ApiControllerBase
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task>> GetById([FromRoute] Guid lockerId)
{
- var query = new GetLockerByIdQuery()
+ var query = new GetLockerById.Query()
{
- LockerId = lockerId
+ LockerId = lockerId,
};
var result = await Mediator.Send(query);
return Ok(Result.Succeed(result));
@@ -39,7 +33,7 @@ public async Task>> GetById([FromRoute] Guid lock
///
/// Get all lockers paginated
///
- /// Get all lockers query parameters
+ /// Get all lockers paginated query parameters
/// A paginated list of LockerDto
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
@@ -47,7 +41,7 @@ public async Task>> GetById([FromRoute] Guid lock
public async Task>>> GetAllPaginated(
[FromQuery] GetAllLockersPaginatedQueryParameters queryParameters)
{
- var query = new GetAllLockersPaginatedQuery()
+ var query = new GetAllLockersPaginated.Query()
{
RoomId = queryParameters.RoomId,
Page = queryParameters.Page,
@@ -59,84 +53,114 @@ public async Task>>> GetAllPaginate
return Ok(Result>.Succeed(result));
}
- [RequiresRole(IdentityData.Roles.Staff)]
+ ///
+ /// Add a locker
+ ///
+ /// Add locker details
+ /// A LockerDto of the added locker
+ [RequiresRole(IdentityData.Roles.Admin)]
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> AddLocker([FromBody] AddLockerCommand command)
+ public async Task>> Add([FromBody] AddLockerRequest request)
{
+ var command = new AddLocker.Command()
+ {
+ Name = request.Name,
+ Description = request.Description,
+ Capacity = request.Capacity,
+ RoomId = request.RoomId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
- [RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
- [HttpPut("disable")]
+ ///
+ /// Remove a locker
+ ///
+ /// Id of the locker to be removed
+ /// A LockerDto of the removed locker
+ [HttpDelete("{lockerId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> DisableLocker([FromBody] DisableLockerCommand command)
+ public async Task>> Remove([FromRoute] Guid lockerId)
{
+ var command = new RemoveLocker.Command()
+ {
+ LockerId = lockerId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
+ ///
+ /// Enable a locker
+ ///
+ /// Id of the locker to be enabled
+ /// A LockerDto of the enabled locker
[RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
- [HttpPut("enable")]
+ [HttpPut("enable/{lockerId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> EnableLocker([FromBody] EnableLockerCommand command)
+ public async Task>> Enable([FromRoute] Guid lockerId)
{
+ var command = new EnableLocker.Command()
+ {
+ LockerId = lockerId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
///
- /// Update a locker
+ /// Disable a locker
///
- /// Id of the locker to be updated
- /// Update locker details
- /// A LockerDto of the updated locker
- [HttpPut("{lockerId:guid}")]
+ /// Id of the locker to be disabled
+ /// A LockerDto of the disabled locker
+ [RequiresRole(IdentityData.Roles.Admin, IdentityData.Roles.Staff)]
+ [HttpPut("disable/{lockerId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> Update([FromRoute] Guid lockerId, [FromBody] UpdateLockerRequest request)
+ public async Task>> Disable([FromRoute] Guid lockerId)
{
- var command = new UpdateLockerCommand()
+ var command = new DisableLocker.Command()
{
LockerId = lockerId,
- Name = request.Name,
- Description = request.Description,
- Capacity = request.Capacity
};
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
+
///
- /// Remove a locker
+ /// Update a locker
///
- /// Id of the locker to be removed
- /// A LockerDto of the removed locker
- [HttpDelete("{lockerId:guid}")]
+ /// Id of the locker to be updated
+ /// Update locker details
+ /// A LockerDto of the updated locker
+ [HttpPut("{lockerId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> Remove([FromRoute] Guid lockerId)
+ public async Task>> Update([FromRoute] Guid lockerId, [FromBody] UpdateLockerRequest request)
{
- var command = new RemoveLockerCommand()
+ var command = new UpdateLocker.Command()
{
- LockerId = lockerId
+ LockerId = lockerId,
+ Name = request.Name,
+ Description = request.Description,
+ Capacity = request.Capacity,
};
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
diff --git a/src/Api/Controllers/Payload/Requests/Auth/LoginModel.cs b/src/Api/Controllers/Payload/Requests/Auth/LoginModel.cs
new file mode 100644
index 00000000..99f49b03
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Auth/LoginModel.cs
@@ -0,0 +1,16 @@
+namespace Api.Controllers.Payload.Requests.Auth;
+
+///
+/// Login credentials to login
+///
+public class LoginModel
+{
+ ///
+ /// Email of user
+ ///
+ public string Email { get; set; } = null!;
+ ///
+ /// Password of user
+ ///
+ public string Password { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Auth/RefreshTokenRequest.cs b/src/Api/Controllers/Payload/Requests/Auth/RefreshTokenRequest.cs
new file mode 100644
index 00000000..979dc447
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Auth/RefreshTokenRequest.cs
@@ -0,0 +1,16 @@
+namespace Api.Controllers.Payload.Requests.Auth;
+
+///
+/// Request details to refresh token
+///
+public class RefreshTokenRequest
+{
+ ///
+ /// Access token
+ ///
+ public string Token { get; set; } = null!;
+ ///
+ /// Refresh token
+ ///
+ public string RefreshToken { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Departments/AddDepartmentRequest.cs b/src/Api/Controllers/Payload/Requests/Departments/AddDepartmentRequest.cs
new file mode 100644
index 00000000..2f6444f7
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Departments/AddDepartmentRequest.cs
@@ -0,0 +1,12 @@
+namespace Api.Controllers.Payload.Requests.Departments;
+
+///
+/// Request details to add a department
+///
+public class AddDepartmentRequest
+{
+ ///
+ /// Name of the department to be added
+ ///
+ public string Name { get; init; } = null!;
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Departments/UpdateDepartmentRequest.cs b/src/Api/Controllers/Payload/Requests/Departments/UpdateDepartmentRequest.cs
new file mode 100644
index 00000000..48ad1052
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Departments/UpdateDepartmentRequest.cs
@@ -0,0 +1,12 @@
+namespace Api.Controllers.Payload.Requests.Departments;
+
+///
+/// Request details to update a department
+///
+public class UpdateDepartmentRequest
+{
+ ///
+ /// New name of the department to be updated
+ ///
+ public string Name { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Documents/GetAllDocumentsPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/Documents/GetAllDocumentsPaginatedQueryParameters.cs
new file mode 100644
index 00000000..7f134c04
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Documents/GetAllDocumentsPaginatedQueryParameters.cs
@@ -0,0 +1,40 @@
+namespace Api.Controllers.Payload.Requests.Documents;
+
+///
+/// Query parameters for getting all documents with pagination
+///
+public class GetAllDocumentsPaginatedQueryParameters
+{
+ ///
+ /// Id of the room to find documents in
+ ///
+ public Guid? RoomId { get; set; }
+ ///
+ /// Id of the locker to find documents in
+ ///
+ public Guid? LockerId { get; set; }
+ ///
+ /// Id of the folder to find documents in
+ ///
+ public Guid? FolderId { get; set; }
+ ///
+ /// Search term
+ ///
+ public string? SearchTerm { get; set; }
+ ///
+ /// Page number
+ ///
+ public int? Page { get; set; }
+ ///
+ /// Size number
+ ///
+ public int? Size { get; set; }
+ ///
+ /// Sort criteria
+ ///
+ public string? SortBy { get; set; }
+ ///
+ /// Sort direction
+ ///
+ public string? SortOrder { get; set; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Documents/ImportDocumentRequest.cs b/src/Api/Controllers/Payload/Requests/Documents/ImportDocumentRequest.cs
new file mode 100644
index 00000000..0bbb2723
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Documents/ImportDocumentRequest.cs
@@ -0,0 +1,28 @@
+namespace Api.Controllers.Payload.Requests.Documents;
+
+///
+/// Request details to import a document
+///
+public class ImportDocumentRequest
+{
+ ///
+ /// Title of the document to be imported
+ ///
+ public string Title { get; set; } = null!;
+ ///
+ /// Description of the document to be imported
+ ///
+ public string? Description { get; set; }
+ ///
+ /// Document type of the document to be imported
+ ///
+ public string DocumentType { get; set; } = null!;
+ ///
+ /// Id of the importer
+ ///
+ public Guid ImporterId { get; set; }
+ ///
+ /// Id of the folder that this document will be in
+ ///
+ public Guid FolderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Documents/UpdateDocumentRequest.cs b/src/Api/Controllers/Payload/Requests/Documents/UpdateDocumentRequest.cs
index e6a0885b..a31cec88 100644
--- a/src/Api/Controllers/Payload/Requests/Documents/UpdateDocumentRequest.cs
+++ b/src/Api/Controllers/Payload/Requests/Documents/UpdateDocumentRequest.cs
@@ -1,8 +1,20 @@
namespace Api.Controllers.Payload.Requests.Documents;
+///
+/// Request details to update a document
+///
public class UpdateDocumentRequest
{
+ ///
+ /// New title of the document to be updated
+ ///
public string Title { get; set; } = null!;
+ ///
+ /// New description of the document to be updated
+ ///
public string? Description { get; set; }
+ ///
+ /// New document type of the document to be updated
+ ///
public string DocumentType { get; set; } = null!;
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Folders/AddFolderRequest.cs b/src/Api/Controllers/Payload/Requests/Folders/AddFolderRequest.cs
new file mode 100644
index 00000000..1dd731c0
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Folders/AddFolderRequest.cs
@@ -0,0 +1,23 @@
+namespace Api.Controllers.Payload.Requests.Folders;
+///
+/// Request details to add a folder
+///
+public class AddFolderRequest
+{
+ ///
+ /// Name of the folder to be added
+ ///
+ public string Name { get; init; } = null!;
+ ///
+ /// Description of the folder to be added
+ ///
+ public string? Description { get; init; }
+ ///
+ /// Number of documents this folder can hold
+ ///
+ public int Capacity { get; init; }
+ ///
+ /// Id of the locker that this folder will be in
+ ///
+ public Guid LockerId { get; init; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Folders/GetAllFoldersPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/Folders/GetAllFoldersPaginatedQueryParameters.cs
index db642122..1be3d84f 100644
--- a/src/Api/Controllers/Payload/Requests/Folders/GetAllFoldersPaginatedQueryParameters.cs
+++ b/src/Api/Controllers/Payload/Requests/Folders/GetAllFoldersPaginatedQueryParameters.cs
@@ -1,11 +1,32 @@
namespace Api.Controllers.Payload.Requests.Folders;
+///
+/// Query parameters for getting all folders with pagination
+///
public class GetAllFoldersPaginatedQueryParameters
{
+ ///
+ /// Id of the room to find folders in
+ ///
public Guid? RoomId { get; set; }
+ ///
+ /// Id of the locker to find folders in
+ ///
public Guid? LockerId { get; set; }
+ ///
+ /// Page number
+ ///
public int? Page { get; set; }
+ ///
+ /// Size number
+ ///
public int? Size { get; set; }
+ ///
+ /// Sort criteria
+ ///
public string? SortBy { get; set; }
+ ///
+ /// Sort direction
+ ///
public string? SortOrder { get; set; }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Folders/UpdateFolderRequest.cs b/src/Api/Controllers/Payload/Requests/Folders/UpdateFolderRequest.cs
index 97e9691f..e26cf33b 100644
--- a/src/Api/Controllers/Payload/Requests/Folders/UpdateFolderRequest.cs
+++ b/src/Api/Controllers/Payload/Requests/Folders/UpdateFolderRequest.cs
@@ -1,8 +1,20 @@
namespace Api.Controllers.Payload.Requests.Folders;
+///
+/// Request details to update a folder
+///
public class UpdateFolderRequest
{
+ ///
+ /// New name of the folder to be updated
+ ///
public string Name { get; set; } = null!;
+ ///
+ /// New description of the folder to be updated
+ ///
public string? Description { get; set; }
+ ///
+ /// New capacity of the folder to be updated
+ ///
public int Capacity { get; set; }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Lockers/AddLockerRequest.cs b/src/Api/Controllers/Payload/Requests/Lockers/AddLockerRequest.cs
new file mode 100644
index 00000000..67988e72
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Lockers/AddLockerRequest.cs
@@ -0,0 +1,24 @@
+namespace Api.Controllers.Payload.Requests.Lockers;
+
+///
+/// Request details to add a locker
+///
+public class AddLockerRequest
+{
+ ///
+ /// Name of the locker to be updated
+ ///
+ public string Name { get; init; } = null!;
+ ///
+ /// Description of the locker to be updated
+ ///
+ public string? Description { get; init; }
+ ///
+ /// Id of the room that this locker will be in
+ ///
+ public Guid RoomId { get; init; }
+ ///
+ /// Number of folders this locker can hold
+ ///
+ public int Capacity { get; init; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Lockers/GetAllLockersPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/Lockers/GetAllLockersPaginatedQueryParameters.cs
index b4b7f837..656b96f6 100644
--- a/src/Api/Controllers/Payload/Requests/Lockers/GetAllLockersPaginatedQueryParameters.cs
+++ b/src/Api/Controllers/Payload/Requests/Lockers/GetAllLockersPaginatedQueryParameters.cs
@@ -2,12 +2,29 @@
namespace Api.Controllers.Payload.Requests.Lockers;
-
+///
+/// Query parameters for getting all lockers with pagination
+///
public class GetAllLockersPaginatedQueryParameters
{
+ ///
+ /// Id of the room to find lockers in
+ ///
public Guid? RoomId { get; set; }
+ ///
+ /// Page number
+ ///
public int? Page { get; set; }
+ ///
+ /// Size number
+ ///
public int? Size { get; set; }
+ ///
+ /// Sort criteria
+ ///
public string? SortBy { get; set; }
+ ///
+ /// Sort direction
+ ///
public string? SortOrder { get; set; }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Lockers/UpdateLockerRequest.cs b/src/Api/Controllers/Payload/Requests/Lockers/UpdateLockerRequest.cs
index a7f69036..5558c1ce 100644
--- a/src/Api/Controllers/Payload/Requests/Lockers/UpdateLockerRequest.cs
+++ b/src/Api/Controllers/Payload/Requests/Lockers/UpdateLockerRequest.cs
@@ -1,8 +1,20 @@
namespace Api.Controllers.Payload.Requests.Lockers;
+///
+/// Request details to update a locker
+///
public class UpdateLockerRequest
{
+ ///
+ /// New name of the locker to be updated
+ ///
public string Name { get; set; } = null!;
+ ///
+ /// New description of the locker to be updated
+ ///
public string? Description { get; set; }
+ ///
+ /// New capacity of the locker to be updated
+ ///
public int Capacity { get; set; }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/LoginModel.cs b/src/Api/Controllers/Payload/Requests/LoginModel.cs
deleted file mode 100644
index d5bd6c61..00000000
--- a/src/Api/Controllers/Payload/Requests/LoginModel.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Api.Controllers.Payload.Requests;
-
-public class LoginModel
-{
- public string Email { get; set; }
- public string Password { get; set; }
-}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/RefreshTokenRequest.cs b/src/Api/Controllers/Payload/Requests/RefreshTokenRequest.cs
deleted file mode 100644
index bcc3d8e2..00000000
--- a/src/Api/Controllers/Payload/Requests/RefreshTokenRequest.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Api.Controllers.Payload.Requests;
-
-public class RefreshTokenRequest
-{
- public string Token { get; set; }
- public string RefreshToken { get; set; }
-}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Rooms/AddRoomRequest.cs b/src/Api/Controllers/Payload/Requests/Rooms/AddRoomRequest.cs
new file mode 100644
index 00000000..4228f4da
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Rooms/AddRoomRequest.cs
@@ -0,0 +1,24 @@
+namespace Api.Controllers.Payload.Requests.Rooms;
+
+///
+/// Request details to add a room
+///
+public class AddRoomRequest
+{
+ ///
+ /// Name of the room to be added
+ ///
+ public string Name { get; set; } = null!;
+ ///
+ /// Description of the room to be added
+ ///
+ public string? Description { get; set; }
+ ///
+ /// Number of lockers this room can hold
+ ///
+ public int Capacity { get; set; }
+ ///
+ /// Id of the department this room belongs to
+ ///
+ public Guid DepartmentId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Rooms/GetAllRoomsPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/Rooms/GetAllRoomsPaginatedQueryParameters.cs
new file mode 100644
index 00000000..34721c39
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Rooms/GetAllRoomsPaginatedQueryParameters.cs
@@ -0,0 +1,24 @@
+namespace Api.Controllers.Payload.Requests.Rooms;
+
+///
+/// Query parameters for getting all rooms with pagination
+///
+public class GetAllRoomsPaginatedQueryParameters
+{
+ ///
+ /// Page number
+ ///
+ public int? Page { get; set; }
+ ///
+ /// Size number
+ ///
+ public int? Size { get; set; }
+ ///
+ /// Sort criteria
+ ///
+ public string? SortBy { get; set; }
+ ///
+ /// Sort direction
+ ///
+ public string? SortOrder { get; set; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Rooms/GetEmptyContainersPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/Rooms/GetEmptyContainersPaginatedQueryParameters.cs
new file mode 100644
index 00000000..2d60bb6d
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Rooms/GetEmptyContainersPaginatedQueryParameters.cs
@@ -0,0 +1,16 @@
+namespace Api.Controllers.Payload.Requests.Rooms;
+
+///
+/// Query parameters for getting all empty containers in a room
+///
+public class GetEmptyContainersPaginatedQueryParameters
+{
+ ///
+ /// Page number
+ ///
+ public int? Page { get; set; }
+ ///
+ /// Size number
+ ///
+ public int? Size { get; set; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Rooms/UpdateRoomRequest.cs b/src/Api/Controllers/Payload/Requests/Rooms/UpdateRoomRequest.cs
new file mode 100644
index 00000000..40d4965c
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Rooms/UpdateRoomRequest.cs
@@ -0,0 +1,20 @@
+namespace Api.Controllers.Payload.Requests.Rooms;
+
+///
+/// Request details to update a room
+///
+public class UpdateRoomRequest
+{
+ ///
+ /// New name of the room to be updated
+ ///
+ public string Name { get; set; } = null!;
+ ///
+ /// New description of the room to be updated
+ ///
+ public string? Description { get; set; }
+ ///
+ /// New capacity of the room to be updated
+ ///
+ public int Capacity { get; set; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Staffs/AddStaffRequest.cs b/src/Api/Controllers/Payload/Requests/Staffs/AddStaffRequest.cs
new file mode 100644
index 00000000..47ebbc06
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Staffs/AddStaffRequest.cs
@@ -0,0 +1,16 @@
+namespace Api.Controllers.Payload.Requests.Staffs;
+
+///
+/// Request details to add a staff
+///
+public class AddStaffRequest
+{
+ ///
+ /// User id of the new staff
+ ///
+ public Guid UserId { get; init; }
+ ///
+ /// Id of the room this staff will be in
+ ///
+ public Guid? RoomId { get; init; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Staffs/GetAllStaffsPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/Staffs/GetAllStaffsPaginatedQueryParameters.cs
index bcb47cb4..53fcbb87 100644
--- a/src/Api/Controllers/Payload/Requests/Staffs/GetAllStaffsPaginatedQueryParameters.cs
+++ b/src/Api/Controllers/Payload/Requests/Staffs/GetAllStaffsPaginatedQueryParameters.cs
@@ -1,10 +1,28 @@
namespace Api.Controllers.Payload.Requests.Staffs;
+///
+/// Query parameters for getting all staffs with pagination
+///
public class GetAllStaffsPaginatedQueryParameters
{
+ ///
+ /// Search term
+ ///
public string? SearchTerm { get; set; }
+ ///
+ /// Page number
+ ///
public int? Page { get; set; }
+ ///
+ /// Size number
+ ///
public int? Size { get; set; }
+ ///
+ /// Sort criteria
+ ///
public string? SortBy { get; set; }
+ ///
+ /// Sort direction
+ ///
public string? SortOrder { get; set; }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Staffs/RemoveStaffFromRoomRequest.cs b/src/Api/Controllers/Payload/Requests/Staffs/RemoveStaffFromRoomRequest.cs
deleted file mode 100644
index 811608df..00000000
--- a/src/Api/Controllers/Payload/Requests/Staffs/RemoveStaffFromRoomRequest.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Api.Controllers.Payload.Requests.Staffs;
-
-public class RemoveStaffFromRoomRequest
-{
- public Guid RoomId { get; set; }
-}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/UpdateDepartmentRequest.cs b/src/Api/Controllers/Payload/Requests/UpdateDepartmentRequest.cs
deleted file mode 100644
index 467ceeb5..00000000
--- a/src/Api/Controllers/Payload/Requests/UpdateDepartmentRequest.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Api.Controllers.Payload.Requests;
-
-public class UpdateDepartmentRequest
-{
- public string Name { get; set; } = null!;
-}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/UpdateRoomRequest.cs b/src/Api/Controllers/Payload/Requests/UpdateRoomRequest.cs
deleted file mode 100644
index a579a447..00000000
--- a/src/Api/Controllers/Payload/Requests/UpdateRoomRequest.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Api.Controllers.Payload.Requests;
-
-public class UpdateRoomRequest
-{
- public string Name { get; set; } = null!;
- public string? Description { get; set; }
- public int Capacity { get; set; }
-}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Users/AddUserRequest.cs b/src/Api/Controllers/Payload/Requests/Users/AddUserRequest.cs
new file mode 100644
index 00000000..2c449aff
--- /dev/null
+++ b/src/Api/Controllers/Payload/Requests/Users/AddUserRequest.cs
@@ -0,0 +1,40 @@
+namespace Api.Controllers.Payload.Requests.Users;
+
+///
+/// Request details to add a user
+///
+public class AddUserRequest
+{
+ ///
+ /// Username of the user to be added
+ ///
+ public string Username { get; init; } = null!;
+ ///
+ /// Email of the user to be added
+ ///
+ public string Email { get; init; } = null!;
+ ///
+ /// Password of the user to be added
+ ///
+ public string Password { get; init; } = null!;
+ ///
+ /// First name of the user to be added
+ ///
+ public string? FirstName { get; init; }
+ ///
+ /// Last name of the user to be added
+ ///
+ public string? LastName { get; init; }
+ ///
+ /// Department of the user to be added
+ ///
+ public Guid DepartmentId { get; init; }
+ ///
+ /// Role of the user to be added
+ ///
+ public string Role { get; init; } = null!;
+ ///
+ /// Position of the user to be added
+ ///
+ public string? Position { get; init; }
+}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Users/GetAllUsersPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/Users/GetAllUsersPaginatedQueryParameters.cs
index d3484660..9f47d022 100644
--- a/src/Api/Controllers/Payload/Requests/Users/GetAllUsersPaginatedQueryParameters.cs
+++ b/src/Api/Controllers/Payload/Requests/Users/GetAllUsersPaginatedQueryParameters.cs
@@ -1,11 +1,32 @@
namespace Api.Controllers.Payload.Requests.Users;
+///
+/// Query parameters for getting all users with pagination
+///
public class GetAllUsersPaginatedQueryParameters
{
+ ///
+ /// Id of the department to find users in
+ ///
public Guid? DepartmentId { get; set; }
+ ///
+ /// Search term
+ ///
public string? SearchTerm { get; set; }
+ ///
+ /// Page number
+ ///
public int? Page { get; set; }
+ ///
+ /// Size number
+ ///
public int? Size { get; set; }
+ ///
+ /// Sort criteria
+ ///
public string? SortBy { get; set; }
+ ///
+ /// Sort direction
+ ///
public string? SortOrder { get; set; }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs b/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs
index 77bcb0e4..d162c28a 100644
--- a/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs
+++ b/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs
@@ -1,11 +1,24 @@
namespace Api.Controllers.Payload.Requests.Users;
+///
+/// Request details to update a user
+///
public class UpdateUserRequest
{
- public string Username { get; set; } = null!;
- public string Email { get; set; } = null!;
+ ///
+ /// New first name of the user to be updated
+ ///
public string? FirstName { get; set; }
+ ///
+ /// New last name of the user to be updated
+ ///
public string? LastName { get; set; }
+ ///
+ /// New role of the user to be updated
+ ///
public string Role { get; set; } = null!;
+ ///
+ /// New position of the user to be updated
+ ///
public string? Position { get; set; }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/Payload/Responses/LoginResult.cs b/src/Api/Controllers/Payload/Responses/LoginResult.cs
index 29fb21c4..f731ac4a 100644
--- a/src/Api/Controllers/Payload/Responses/LoginResult.cs
+++ b/src/Api/Controllers/Payload/Responses/LoginResult.cs
@@ -1,3 +1,4 @@
+using Application.Common.Models.Dtos;
using Application.Users.Queries;
namespace Api.Controllers.Payload.Responses;
diff --git a/src/Api/Controllers/RoomsController.cs b/src/Api/Controllers/RoomsController.cs
index 3cbeb8dd..d46390cc 100644
--- a/src/Api/Controllers/RoomsController.cs
+++ b/src/Api/Controllers/RoomsController.cs
@@ -1,15 +1,10 @@
-using Api.Controllers.Payload.Requests;
+using Api.Controllers.Payload.Requests.Lockers;
+using Api.Controllers.Payload.Requests.Rooms;
using Application.Common.Models;
using Application.Common.Models.Dtos.Physical;
using Application.Identity;
-using Application.Rooms.Commands.AddRoom;
-using Application.Rooms.Commands.DisableRoom;
-using Application.Rooms.Commands.EnableRoom;
-using Application.Rooms.Commands.RemoveRoom;
-using Application.Rooms.Commands.UpdateRoom;
-using Application.Rooms.Queries.GetAllRoomPaginated;
-using Application.Rooms.Queries.GetEmptyContainersPaginated;
-using Application.Rooms.Queries.GetRoomById;
+using Application.Rooms.Commands;
+using Application.Rooms.Queries;
using Infrastructure.Identity.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -17,135 +12,179 @@ namespace Api.Controllers;
public class RoomsController : ApiControllerBase
{
- [RequiresRole(IdentityData.Roles.Admin)]
- [HttpPost]
+ ///
+ /// Get a room by id
+ ///
+ /// Id of the room to be retrieved
+ /// A RoomDto of the retrieved room
+ [HttpGet("{roomId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- [ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> AddRoom(AddRoomCommand command)
+ public async Task>> GetById([FromRoute] Guid roomId)
{
- var result = await Mediator.Send(command);
+ var query = new GetRoomById.Query()
+ {
+ RoomId = roomId,
+ };
+ var result = await Mediator.Send(query);
return Ok(Result.Succeed(result));
}
-
+
+ ///
+ /// Get all rooms paginated
+ ///
+ /// Get all rooms paginated details
+ /// A paginated list of rooms
+ [HttpGet]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ public async Task>>> GetAllPaginated(
+ [FromQuery] GetAllLockersPaginatedQueryParameters queryParameters)
+ {
+ var query = new GetAllRoomsPaginated.Query()
+ {
+ Page = queryParameters.Page,
+ Size = queryParameters.Size,
+ SortBy = queryParameters.SortBy,
+ SortOrder = queryParameters.SortOrder,
+ };
+ var result = await Mediator.Send(query);
+ return Ok(Result>.Succeed(result));
+ }
+
+ ///
+ /// Get empty containers in a room
+ ///
+ /// Get empty containers paginated details
+ /// A paginated list of EmptyLockerDto
[RequiresRole(IdentityData.Roles.Staff)]
[HttpPost("empty-containers")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> GetEmptyContainers(GetEmptyContainersPaginatedQuery query)
+ public async Task>> GetEmptyContainers(
+ [FromRoute] Guid roomId,
+ [FromQuery] GetEmptyContainersPaginatedQueryParameters queryParameters)
{
+ var query = new GetEmptyContainersPaginated.Query()
+ {
+ RoomId = roomId,
+ Page = queryParameters.Page,
+ Size = queryParameters.Size,
+ };
var result = await Mediator.Send(query);
return Ok(Result>.Succeed(result));
}
-
+
+ ///
+ /// Add a room
+ ///
+ /// Add room details
+ /// A RoomDto of the added room
[RequiresRole(IdentityData.Roles.Admin)]
- [HttpPut("disable")]
+ [HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> DisableRoom(DisableRoomCommand command)
+ public async Task>> AddRoom([FromBody] AddRoomRequest request)
{
+ var command = new AddRoom.Command()
+ {
+ Name = request.Name,
+ Description = request.Description,
+ Capacity = request.Capacity,
+ DepartmentId = request.DepartmentId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
+
+ ///
+ /// Remove a room
+ ///
+ /// Id of the room to be removed
+ /// A RoomDto of the removed room
[RequiresRole(IdentityData.Roles.Admin)]
- [HttpDelete]
+ [HttpDelete("{roomId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> RemoveRoom(RemoveRoomCommand command)
+ public async Task>> RemoveRoom([FromRoute] Guid roomId)
{
+ var command = new RemoveRoom.Command()
+ {
+ RoomId = roomId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
+
///
/// Enable a room
///
- /// Enable room details
+ /// Id of the room to be enabled
/// A RoomDto of the enabled room
- [HttpPut("enable")]
+ [HttpPut("enable/{roomId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> EnableRoom([FromBody] EnableRoomCommand command)
+ public async Task>> EnableRoom([FromRoute] Guid roomId)
{
+ var command = new EnableRoom.Command()
+ {
+ RoomId = roomId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
///
- /// Update a room
+ /// Disable a room
///
- /// Id of the room to be updated
- /// Update room details
- /// A RoomDto of the updated room
- [HttpPut("{roomId:guid}")]
+ /// Id of the room to be disabled
+ /// A RoomDto of the disabled room
+ [RequiresRole(IdentityData.Roles.Admin)]
+ [HttpPut("disable/{roomId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> Update([FromRoute] Guid roomId, [FromBody] UpdateRoomRequest request)
+ public async Task>> DisableRoom([FromRoute] Guid roomId)
{
- Console.WriteLine(request.Description);
- var command = new UpdateRoomCommand()
+ var command = new DisableRoom.Command()
{
RoomId = roomId,
- Name = request.Name,
- Description = request.Description,
- Capacity = request.Capacity,
};
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
+
///
- /// Get a room by id
+ /// Update a room
///
- /// Id of the room to be retrieved
- /// A RoomDto of the retrieved room
- [HttpGet("{roomId:guid}")]
+ /// Id of the room to be updated
+ /// Update room details
+ /// A RoomDto of the updated room
+ [HttpPut("{roomId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> GetById([FromRoute] Guid roomId)
+ [ProducesResponseType(StatusCodes.Status409Conflict)]
+ public async Task>> Update([FromRoute] Guid roomId, [FromBody] UpdateRoomRequest request)
{
- var query = new GetRoomByIdQuery()
+ var command = new UpdateRoom.Command()
{
RoomId = roomId,
+ Name = request.Name,
+ Description = request.Description,
+ Capacity = request.Capacity,
};
- var result = await Mediator.Send(query);
+ var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
- ///
- /// Get all rooms paginated
- ///
- /// The page index
- /// The size number
- /// Criteria
- /// The order in which the rooms are sorted
- /// A paginated list of rooms
- [HttpGet]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status403Forbidden)]
- public async Task>>> GetAllPaginated(int? page, int? size, string? sortBy, string? sortOrder)
- {
- var query = new GetAllRoomsPaginatedQuery()
- {
- Page = page,
- Size = size,
- SortBy = sortBy,
- SortOrder = sortOrder
- };
- var result = await Mediator.Send(query);
- return Ok(Result>.Succeed(result));
- }
}
\ No newline at end of file
diff --git a/src/Api/Controllers/StaffsController.cs b/src/Api/Controllers/StaffsController.cs
index 1ad6fff1..048f1b4c 100644
--- a/src/Api/Controllers/StaffsController.cs
+++ b/src/Api/Controllers/StaffsController.cs
@@ -1,12 +1,9 @@
using Api.Controllers.Payload.Requests.Staffs;
using Application.Common.Models;
+using Application.Common.Models.Dtos.Physical;
using Application.Identity;
-using Application.Staffs.Commands.RemoveStaffFromRoom;
-using Application.Staffs.Queries.GetAllStaffsPaginated;
-using Application.Staffs.Queries.GetStaffById;
-using Application.Staffs.Queries.GetStaffByRoom;
-using Application.Staffs.Commands.AddStaff;
-using Application.Users.Queries.Physical;
+using Application.Staffs.Commands;
+using Application.Staffs.Queries;
using Infrastructure.Identity.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -25,7 +22,7 @@ public class StaffsController : ApiControllerBase
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task>> GetById([FromRoute] Guid staffId)
{
- var query = new GetStaffByIdQuery()
+ var query = new GetStaffById.Query()
{
StaffId = staffId
};
@@ -44,7 +41,7 @@ public async Task>> GetById([FromRoute] Guid staff
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task>> GetByRoom([FromRoute] Guid roomId)
{
- var query = new GetStaffByRoomQuery()
+ var query = new GetStaffByRoom.Query()
{
RoomId = roomId
};
@@ -63,8 +60,9 @@ public async Task>> GetByRoom([FromRoute] Guid roo
public async Task>>> GetAllPaginated(
[FromQuery] GetAllStaffsPaginatedQueryParameters queryParameters)
{
- var query = new GetAllStaffsPaginatedQuery()
+ var query = new GetAllStaffsPaginated.Query()
{
+ SearchTerm = queryParameters.SearchTerm,
Page = queryParameters.Page,
Size = queryParameters.Size,
SortBy = queryParameters.SortBy,
@@ -74,13 +72,23 @@ public async Task>>> GetAllPaginated
return Ok(Result>.Succeed(result));
}
+ ///
+ /// Add a staff
+ ///
+ /// Add staff details
+ /// A StaffDto of the added staff
[RequiresRole(IdentityData.Roles.Admin)]
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> AddStaff([FromBody] AddStaffCommand command)
+ public async Task>> Add([FromBody] AddStaffRequest request)
{
+ var command = new AddStaff.Command()
+ {
+ RoomId = request.RoomId,
+ UserId = request.UserId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
@@ -89,19 +97,17 @@ public async Task>> AddStaff([FromBody] AddStaffCo
/// Remove a staff from room
///
/// Id of the staff to be removed from room
- /// Remove details
/// A StaffDto of the removed staff
[HttpPut("{staffId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> RemoveStaffFromRoom([FromRoute] Guid staffId,
- [FromBody] RemoveStaffFromRoomRequest request)
+ public async Task>> RemoveFromRoom(
+ [FromRoute] Guid staffId)
{
- var command = new RemoveStaffFromRoomCommand()
+ var command = new RemoveStaffFromRoom.Command()
{
StaffId = staffId,
- RoomId = request.RoomId,
};
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
diff --git a/src/Api/Controllers/UsersController.cs b/src/Api/Controllers/UsersController.cs
index f7d93173..dc2b406e 100644
--- a/src/Api/Controllers/UsersController.cs
+++ b/src/Api/Controllers/UsersController.cs
@@ -1,17 +1,9 @@
using Api.Controllers.Payload.Requests.Users;
using Application.Common.Models;
-using Application.Common.Models.Dtos.Physical;
using Application.Identity;
-using Application.Users.Commands.AddUser;
-using Application.Users.Commands.DisableUser;
-using Application.Users.Commands.EnableUser;
-using Application.Users.Commands.UpdateUser;
+using Application.Users.Commands;
using Application.Users.Queries;
-using Application.Users.Queries.GetAllUsersPaginated;
-using Application.Users.Queries.GetUserById;
-using Application.Users.Queries.GetUsersByName;
using Infrastructure.Identity.Authorization;
-using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Api.Controllers;
@@ -27,9 +19,9 @@ public class UsersController : ApiControllerBase
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> GetUserById([FromRoute] Guid userId)
+ public async Task>> GetById([FromRoute] Guid userId)
{
- var query = new GetUserByIdQuery
+ var query = new GetUserById.Query
{
UserId = userId,
};
@@ -40,7 +32,7 @@ public async Task>> GetUserById([FromRoute] Guid us
///
/// Get all users paginated
///
- /// Get all users query parameters
+ /// Get all users query parameters
/// A paginated list of UserDto
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
@@ -48,7 +40,7 @@ public async Task>> GetUserById([FromRoute] Guid us
public async Task>>> GetAllPaginated(
[FromQuery] GetAllUsersPaginatedQueryParameters queryParameters)
{
- var query = new GetAllUsersPaginatedQuery()
+ var query = new GetAllUsersPaginated.Query()
{
DepartmentId = queryParameters.DepartmentId,
SearchTerm = queryParameters.SearchTerm,
@@ -61,37 +53,37 @@ public async Task>>> GetAllPaginated(
return Ok(Result>.Succeed(result));
}
+ ///
+ /// Add a user
+ ///
+ /// Add user details
+ /// A UserDto of the added user
[RequiresRole(IdentityData.Roles.Admin)]
[HttpPost]
- [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> AddUser([FromBody] AddUserCommand command)
+ public async Task>> Add([FromBody] AddUserRequest request)
{
+ var command = new AddUser.Command()
+ {
+ Username = request.Username,
+ Email = request.Email,
+ Password = request.Password,
+ FirstName = request.FirstName,
+ LastName = request.LastName,
+ Role = request.Role,
+ Position = request.Position,
+ DepartmentId = request.DepartmentId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
-
- // [RequiresRole(IdentityData.Roles.Admin)]
- // [HttpGet]
- // [ProducesResponseType(StatusCodes.Status200OK)]
- // [ProducesResponseType(StatusCodes.Status403Forbidden)]
- // public async Task>>> GetUsersByName(string? searchTerm, int? page, int? size)
- // {
- // var query = new GetUsersByNameQuery
- // {
- // SearchTerm = searchTerm,
- // Page = page,
- // Size = size
- // };
- // var result = await Mediator.Send(query);
- // return Ok(Result>.Succeed(result));
- // }
-
+
///
- /// Disable a user
+ /// Enable a user
///
/// Id of the user to be enabled
/// A UserDto of the enabled user
@@ -100,9 +92,9 @@ public async Task>> AddUser([FromBody] AddUserComma
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task>> EnableUser([FromRoute] Guid userId)
+ public async Task>> Enable([FromRoute] Guid userId)
{
- var command = new EnableUserCommand()
+ var command = new EnableUser.Command()
{
UserId = userId
};
@@ -110,14 +102,23 @@ public async Task>> EnableUser([FromRoute] Guid use
return Ok(Result.Succeed(result));
}
+ ///
+ /// Disable a user
+ ///
+ /// Id of the user to be disabled
+ /// A UserDto of the disabled user
[RequiresRole(IdentityData.Roles.Admin)]
- [HttpPost("disable")]
+ [HttpPut("disable/{userId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
- public async Task>> DisableUser([FromBody] DisableUserCommand command)
+ public async Task>> Disable([FromRoute] Guid userId)
{
+ var command = new DisableUser.Command()
+ {
+ UserId = userId,
+ };
var result = await Mediator.Send(command);
return Ok(Result.Succeed(result));
}
@@ -135,11 +136,9 @@ public async Task>> DisableUser([FromBody] DisableU
[ProducesResponseType(StatusCodes.Status409Conflict)]
public async Task>> Update([FromRoute] Guid userId, [FromBody] UpdateUserRequest request)
{
- var command = new UpdateUserCommand()
+ var command = new UpdateUser.Command()
{
UserId = userId,
- Username = request.Username,
- Email = request.Email,
FirstName = request.FirstName,
LastName = request.LastName,
Role = request.Role,
diff --git a/src/Api/Extensions/WebApplicationExtensions.cs b/src/Api/Extensions/WebApplicationExtensions.cs
index e0a90371..63e834ee 100644
--- a/src/Api/Extensions/WebApplicationExtensions.cs
+++ b/src/Api/Extensions/WebApplicationExtensions.cs
@@ -1,10 +1,12 @@
using Api.Middlewares;
+using Infrastructure.Persistence;
+using Serilog;
namespace Api.Extensions;
public static class WebApplicationExtensions
{
- public static void UseInfrastructure(this WebApplication app)
+ public static void UseInfrastructure(this WebApplication app, IConfiguration configuration)
{
// Configure the HTTP request pipeline.
@@ -15,10 +17,20 @@ public static void UseInfrastructure(this WebApplication app)
{
app.UseSwagger();
app.UseSwaggerUI();
+
app.UseCors("AllowAllOrigins");
+
+ app.MigrateDatabase((context, _) =>
+ {
+ ApplicationDbContextSeed.Seed(context, configuration, Log.Logger).Wait();
+ });
}
- else
+
+ if (app.Environment.IsEnvironment("Testing"))
{
+ app.MigrateDatabase((_, _) =>
+ {
+ });
}
app.UseAuthentication();
diff --git a/src/Api/Program.cs b/src/Api/Program.cs
index 42a37f8f..829f0873 100644
--- a/src/Api/Program.cs
+++ b/src/Api/Program.cs
@@ -21,13 +21,9 @@
var app = builder.Build();
- app.UseInfrastructure();
+ app.UseInfrastructure(builder.Configuration);
- app.MigrateDatabase((context, _) =>
- {
- ApplicationDbContextSeed.Seed(context, builder.Configuration, Log.Logger).Wait();
- })
- .Run();
+ app.Run();
}
catch (Exception ex)
{
diff --git a/src/Api/Services/CurrentUserService.cs b/src/Api/Services/CurrentUserService.cs
index 34a4b5be..d8b6c481 100644
--- a/src/Api/Services/CurrentUserService.cs
+++ b/src/Api/Services/CurrentUserService.cs
@@ -1,6 +1,5 @@
using System.IdentityModel.Tokens.Jwt;
using Application.Common.Interfaces;
-using Application.Identity;
namespace Api.Services;
diff --git a/src/Api/appsettings.Testing.json b/src/Api/appsettings.Testing.json
new file mode 100644
index 00000000..5dbdc362
--- /dev/null
+++ b/src/Api/appsettings.Testing.json
@@ -0,0 +1,20 @@
+{
+ "JweSettings": {
+ "SigningKeyId": "4bd28be8eac5414fb01c5cbe343b50144bd2",
+ "EncryptionKeyId": "4bd28be8eac5414fb01c5cbe343b5014",
+ "TokenLifetime": "00:20:00",
+ "RefreshTokenLifetimeInDays": 3
+ },
+ "Seed": true,
+ "Serilog" : {
+ "MinimumLevel" : {
+ "Default": "Debug",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information",
+ "Microsoft.AspNetCore.Authentication": "Debug",
+ "System": "Warning"
+ }
+ }
+ }
+}
diff --git a/src/Application/Common/Models/Dtos/DepartmentDto.cs b/src/Application/Common/Models/Dtos/DepartmentDto.cs
index 286a4b08..68d00db4 100644
--- a/src/Application/Common/Models/Dtos/DepartmentDto.cs
+++ b/src/Application/Common/Models/Dtos/DepartmentDto.cs
@@ -1,10 +1,12 @@
using Application.Common.Mappings;
+using Application.Common.Models.Dtos.Physical;
using Domain.Entities;
-namespace Application.Users.Queries;
+namespace Application.Common.Models.Dtos;
public class DepartmentDto : IMapFrom
{
public Guid Id { get; set; }
- public string Name { get; set; }
+ public string Name { get; set; } = null!;
+ public RoomDto? Room { get; set; }
}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetAllDocumentsPaginated/DocumentItemDto.cs b/src/Application/Common/Models/Dtos/Physical/DocumentItemDto.cs
similarity index 76%
rename from src/Application/Documents/Queries/GetAllDocumentsPaginated/DocumentItemDto.cs
rename to src/Application/Common/Models/Dtos/Physical/DocumentItemDto.cs
index 86cc8533..7420ad90 100644
--- a/src/Application/Documents/Queries/GetAllDocumentsPaginated/DocumentItemDto.cs
+++ b/src/Application/Common/Models/Dtos/Physical/DocumentItemDto.cs
@@ -1,12 +1,9 @@
using Application.Common.Mappings;
-using Application.Common.Models.Dtos.Physical;
using Application.Users.Queries;
-using AutoMapper;
using Domain.Entities.Physical;
-namespace Application.Documents.Queries.GetAllDocumentsPaginated;
+namespace Application.Common.Models.Dtos.Physical;
-[Obsolete]
public class DocumentItemDto : IMapFrom
{
public Guid Id { get; set; }
diff --git a/src/Application/Rooms/Queries/GetEmptyContainersPaginated/EmptyFolderDto.cs b/src/Application/Common/Models/Dtos/Physical/EmptyFolderDto.cs
similarity index 89%
rename from src/Application/Rooms/Queries/GetEmptyContainersPaginated/EmptyFolderDto.cs
rename to src/Application/Common/Models/Dtos/Physical/EmptyFolderDto.cs
index 0398e867..10e77646 100644
--- a/src/Application/Rooms/Queries/GetEmptyContainersPaginated/EmptyFolderDto.cs
+++ b/src/Application/Common/Models/Dtos/Physical/EmptyFolderDto.cs
@@ -2,7 +2,7 @@
using AutoMapper;
using Domain.Entities.Physical;
-namespace Application.Rooms.Queries.GetEmptyContainersPaginated;
+namespace Application.Common.Models.Dtos.Physical;
public class EmptyFolderDto : IMapFrom
{
diff --git a/src/Application/Rooms/Queries/GetEmptyContainersPaginated/EmptyLockerDto.cs b/src/Application/Common/Models/Dtos/Physical/EmptyLockerDto.cs
similarity index 86%
rename from src/Application/Rooms/Queries/GetEmptyContainersPaginated/EmptyLockerDto.cs
rename to src/Application/Common/Models/Dtos/Physical/EmptyLockerDto.cs
index f9f80d7b..6d7537c7 100644
--- a/src/Application/Rooms/Queries/GetEmptyContainersPaginated/EmptyLockerDto.cs
+++ b/src/Application/Common/Models/Dtos/Physical/EmptyLockerDto.cs
@@ -1,9 +1,8 @@
using Application.Common.Mappings;
-using Application.Common.Models.Dtos.Physical;
using AutoMapper;
using Domain.Entities.Physical;
-namespace Application.Rooms.Queries.GetEmptyContainersPaginated;
+namespace Application.Common.Models.Dtos.Physical;
public class EmptyLockerDto : IMapFrom
{
diff --git a/src/Application/Common/Models/Dtos/Physical/RoomDto.cs b/src/Application/Common/Models/Dtos/Physical/RoomDto.cs
index 5426161f..a2ed7b95 100644
--- a/src/Application/Common/Models/Dtos/Physical/RoomDto.cs
+++ b/src/Application/Common/Models/Dtos/Physical/RoomDto.cs
@@ -1,5 +1,5 @@
using Application.Common.Mappings;
-using Application.Users.Queries.Physical;
+using Application.Users.Queries;
using AutoMapper;
using Domain.Entities.Physical;
@@ -8,9 +8,10 @@ namespace Application.Common.Models.Dtos.Physical;
public class RoomDto : IMapFrom
{
public Guid Id { get; set; }
- public string Name { get; set; }
- public string Description { get; set; }
- public StaffDto Staff { get; set; }
+ public string Name { get; set; } = null!;
+ public string? Description { get; set; }
+ public StaffDto? Staff { get; set; }
+ public DepartmentDto? Department { get; set; }
public int Capacity { get; set; }
public int NumberOfLockers { get; set; }
public bool IsAvailable { get; set; }
diff --git a/src/Application/Common/Models/Dtos/Physical/StaffDto.cs b/src/Application/Common/Models/Dtos/Physical/StaffDto.cs
index b4ff5a80..84563c1b 100644
--- a/src/Application/Common/Models/Dtos/Physical/StaffDto.cs
+++ b/src/Application/Common/Models/Dtos/Physical/StaffDto.cs
@@ -1,11 +1,11 @@
using Application.Common.Mappings;
-using Application.Common.Models.Dtos.Physical;
+using Application.Users.Queries;
using Domain.Entities.Physical;
-namespace Application.Users.Queries.Physical;
+namespace Application.Common.Models.Dtos.Physical;
public class StaffDto : IMapFrom
{
- public UserDto User { get; set; }
- public RoomDto Room { get; set; }
+ public UserDto User { get; set; } = null!;
+ public RoomDto? Room { get; set; }
}
\ No newline at end of file
diff --git a/src/Application/Common/Models/Dtos/UserDto.cs b/src/Application/Common/Models/Dtos/UserDto.cs
index ccb4ba64..64cf73dc 100644
--- a/src/Application/Common/Models/Dtos/UserDto.cs
+++ b/src/Application/Common/Models/Dtos/UserDto.cs
@@ -1,4 +1,5 @@
using Application.Common.Mappings;
+using Application.Common.Models.Dtos;
using AutoMapper;
using Domain.Entities;
diff --git a/src/Application/Departments/Commands/AddDepartment.cs b/src/Application/Departments/Commands/AddDepartment.cs
new file mode 100644
index 00000000..525d83c4
--- /dev/null
+++ b/src/Application/Departments/Commands/AddDepartment.cs
@@ -0,0 +1,50 @@
+using Application.Common.Exceptions;
+using Application.Common.Interfaces;
+using Application.Common.Models.Dtos;
+using Application.Users.Queries;
+using AutoMapper;
+using Domain.Entities;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Departments.Commands;
+
+public class AddDepartment
+{
+ public record Command : IRequest
+ {
+ public string Name { get; init; } = null!;
+ }
+
+ public class AddDepartmentCommandHandler : IRequestHandler
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+
+ public AddDepartmentCommandHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public async Task Handle(Command request, CancellationToken cancellationToken)
+ {
+ var department = await _context.Departments.FirstOrDefaultAsync(x
+ => x.Name.Trim().ToLower().Equals(request.Name.Trim().ToLower()), cancellationToken);
+
+ if (department is not null)
+ {
+ throw new ConflictException("Department name already exists.");
+ }
+
+ var entity = new Department
+ {
+ Name = request.Name
+ };
+
+ var result = await _context.Departments.AddAsync(entity, cancellationToken);
+ await _context.SaveChangesAsync(cancellationToken);
+ return _mapper.Map(result.Entity);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Departments/Commands/AddDepartment/AddDepartmentCommand.cs b/src/Application/Departments/Commands/AddDepartment/AddDepartmentCommand.cs
deleted file mode 100644
index 00f42e5c..00000000
--- a/src/Application/Departments/Commands/AddDepartment/AddDepartmentCommand.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using Application.Common.Exceptions;
-using Application.Common.Interfaces;
-using Application.Users.Queries;
-using AutoMapper;
-using Domain.Entities;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Departments.Commands.AddDepartment;
-
-public record AddDepartmentCommand : IRequest
-{
- public string Name { get; init; } = null!;
-}
-
-public class AddDepartmentCommandHandler : IRequestHandler
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
- public AddDepartmentCommandHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
-
- public async Task Handle(AddDepartmentCommand request, CancellationToken cancellationToken)
- {
- var department = await _context.Departments.FirstOrDefaultAsync(x => x.Name.Trim().ToLower().Equals(request.Name.Trim().ToLower()), cancellationToken);
-
- if (department is not null)
- {
- throw new ConflictException("Department name already exists.");
- }
- var entity = new Department
- {
- Name = request.Name
- };
-
- var result = await _context.Departments.AddAsync(entity, cancellationToken);
- await _context.SaveChangesAsync(cancellationToken);
- return _mapper.Map(result.Entity);
- }
-}
\ No newline at end of file
diff --git a/src/Application/Departments/Commands/DeleteDepartment.cs b/src/Application/Departments/Commands/DeleteDepartment.cs
new file mode 100644
index 00000000..b744630b
--- /dev/null
+++ b/src/Application/Departments/Commands/DeleteDepartment.cs
@@ -0,0 +1,41 @@
+using Application.Common.Interfaces;
+using Application.Common.Models.Dtos;
+using Application.Users.Queries;
+using AutoMapper;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Departments.Commands;
+
+public class DeleteDepartment
+{
+ public record Command : IRequest
+ {
+ public Guid DepartmentId { get; init; }
+ }
+
+ public class CommandHandler : IRequestHandler
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+ public CommandHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public async Task Handle(Command request, CancellationToken cancellationToken)
+ {
+ var department = await _context.Departments.FirstOrDefaultAsync(x => x.Id == request.DepartmentId, cancellationToken);
+
+ if (department is null)
+ {
+ throw new KeyNotFoundException("Department does not exist.");
+ }
+
+ var result = _context.Departments.Remove(department);
+ await _context.SaveChangesAsync(cancellationToken);
+ return _mapper.Map(result.Entity);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Departments/Commands/DeleteDepartment/DeleteDepartmentCommand.cs b/src/Application/Departments/Commands/DeleteDepartment/DeleteDepartmentCommand.cs
deleted file mode 100644
index 93ea7708..00000000
--- a/src/Application/Departments/Commands/DeleteDepartment/DeleteDepartmentCommand.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using Application.Common.Exceptions;
-using Application.Common.Interfaces;
-using Application.Users.Queries;
-using AutoMapper;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Departments.Commands.DeleteDepartment;
-
-public record DeleteDepartmentCommand : IRequest
-{
- public Guid DepartmentId { get; init; }
-}
-
-public class DeleteDepartmentCommandHandler : IRequestHandler
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
- public DeleteDepartmentCommandHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
-
- public async Task Handle(DeleteDepartmentCommand request, CancellationToken cancellationToken)
- {
- var department = await _context.Departments.FirstOrDefaultAsync(x => x.Id == request.DepartmentId, cancellationToken);
-
- if (department is null)
- {
- throw new KeyNotFoundException("Department does not exist");
- }
-
- var result = _context.Departments.Remove(department);
- await _context.SaveChangesAsync(cancellationToken);
- return _mapper.Map(result.Entity);
- }
-}
\ No newline at end of file
diff --git a/src/Application/Departments/Commands/UpdateDepartment.cs b/src/Application/Departments/Commands/UpdateDepartment.cs
new file mode 100644
index 00000000..a080e22d
--- /dev/null
+++ b/src/Application/Departments/Commands/UpdateDepartment.cs
@@ -0,0 +1,14 @@
+using Application.Common.Models.Dtos;
+using Application.Users.Queries;
+using MediatR;
+
+namespace Application.Departments.Commands;
+
+public class UpdateDepartment
+{
+ public record Command : IRequest
+ {
+ public Guid DepartmentId { get; set; }
+ public string Name { get; init; } = null!;
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Departments/Commands/UpdateDepartment/UpdateDepartmentCommand.cs b/src/Application/Departments/Commands/UpdateDepartment/UpdateDepartmentCommand.cs
deleted file mode 100644
index 941879af..00000000
--- a/src/Application/Departments/Commands/UpdateDepartment/UpdateDepartmentCommand.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Application.Users.Queries;
-using MediatR;
-
-namespace Application.Departments.Commands.UpdateDepartment;
-
-public record UpdateDepartmentCommand : IRequest
-{
- public Guid DepartmentId { get; set; }
- public string Name { get; init; } = null!;
-}
\ No newline at end of file
diff --git a/src/Application/Departments/Queries/GetAllDepartments.cs b/src/Application/Departments/Queries/GetAllDepartments.cs
new file mode 100644
index 00000000..a4e5d711
--- /dev/null
+++ b/src/Application/Departments/Queries/GetAllDepartments.cs
@@ -0,0 +1,32 @@
+using System.Collections.ObjectModel;
+using Application.Common.Interfaces;
+using Application.Common.Models.Dtos;
+using AutoMapper;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Departments.Queries;
+
+public class GetAllDepartments
+{
+ public record Query : IRequest>;
+
+ public class QueryHandler : IRequestHandler>
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+
+ public QueryHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public async Task> Handle(Query request, CancellationToken cancellationToken)
+ {
+ var departments = await _context.Departments.ToListAsync(cancellationToken);
+ var result = new ReadOnlyCollection(_mapper.Map>(departments));
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Departments/Queries/GetAllDepartments/GetAllDepartmentsQuery.cs b/src/Application/Departments/Queries/GetAllDepartments/GetAllDepartmentsQuery.cs
deleted file mode 100644
index a0af15e1..00000000
--- a/src/Application/Departments/Queries/GetAllDepartments/GetAllDepartmentsQuery.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Collections.ObjectModel;
-using Application.Common.Interfaces;
-using Application.Users.Queries;
-using AutoMapper;
-using Domain.Entities;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Departments.Queries.GetAllDepartments;
-
-public record GetAllDepartmentsQuery : IRequest>;
-
-public class GetAllDepartmentsQueryHandler : IRequestHandler>
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
-
- public GetAllDepartmentsQueryHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
-
- public async Task> Handle(GetAllDepartmentsQuery request, CancellationToken cancellationToken)
- {
- var departments = await _context.Departments.ToListAsync(cancellationToken);
- var result = new ReadOnlyCollection(_mapper.Map>(departments));
- return result;
- }
-}
\ No newline at end of file
diff --git a/src/Application/Departments/Queries/GetDepartmentById.cs b/src/Application/Departments/Queries/GetDepartmentById.cs
new file mode 100644
index 00000000..e4120c64
--- /dev/null
+++ b/src/Application/Departments/Queries/GetDepartmentById.cs
@@ -0,0 +1,12 @@
+using Application.Common.Models.Dtos;
+using MediatR;
+
+namespace Application.Departments.Queries;
+
+public class GetDepartmentById
+{
+ public record Query : IRequest
+ {
+ public Guid DepartmentId { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Departments/Queries/GetDepartmentById/GetDepartmentByIdQuery.cs b/src/Application/Departments/Queries/GetDepartmentById/GetDepartmentByIdQuery.cs
deleted file mode 100644
index fe0ec11a..00000000
--- a/src/Application/Departments/Queries/GetDepartmentById/GetDepartmentByIdQuery.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Application.Users.Queries;
-using MediatR;
-
-namespace Application.Departments.Queries.GetDepartmentById;
-
-public record GetDepartmentByIdQuery : IRequest
-{
- public Guid DepartmentId { get; init; }
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Commands/DeleteDocument.cs b/src/Application/Documents/Commands/DeleteDocument.cs
new file mode 100644
index 00000000..7b22f634
--- /dev/null
+++ b/src/Application/Documents/Commands/DeleteDocument.cs
@@ -0,0 +1,12 @@
+using Application.Common.Models.Dtos.Physical;
+using MediatR;
+
+namespace Application.Documents.Commands;
+
+public class DeleteDocument
+{
+ public record Command : IRequest
+ {
+ public Guid DocumentId { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Documents/Commands/DeleteDocument/DeleteDocumentCommand.cs b/src/Application/Documents/Commands/DeleteDocument/DeleteDocumentCommand.cs
deleted file mode 100644
index eefecf87..00000000
--- a/src/Application/Documents/Commands/DeleteDocument/DeleteDocumentCommand.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Application.Common.Models.Dtos.Physical;
-using MediatR;
-
-namespace Application.Documents.Commands.DeleteDocument;
-
-public record DeleteDocumentCommand : IRequest
-{
- public Guid DocumentId { get; init; }
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Commands/ImportDocument.cs b/src/Application/Documents/Commands/ImportDocument.cs
new file mode 100644
index 00000000..2f5e8c02
--- /dev/null
+++ b/src/Application/Documents/Commands/ImportDocument.cs
@@ -0,0 +1,76 @@
+using Application.Common.Exceptions;
+using Application.Common.Interfaces;
+using Application.Common.Models.Dtos.Physical;
+using AutoMapper;
+using Domain.Entities.Physical;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Documents.Commands;
+
+public class ImportDocument
+{
+ public record Command : IRequest
+ {
+ public string Title { get; init; } = null!;
+ public string? Description { get; init; }
+ public string DocumentType { get; init; } = null!;
+ public Guid ImporterId { get; init; }
+ public Guid FolderId { get; init; }
+ }
+
+ public class CommandHandler : IRequestHandler
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+
+ public CommandHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public async Task Handle(Command request, CancellationToken cancellationToken)
+ {
+ var importer = await _context.Users
+ .Include(x => x.Department)
+ .FirstOrDefaultAsync(x => x.Id == request.ImporterId, cancellationToken);
+ if (importer is null)
+ {
+ throw new KeyNotFoundException("User does not exist.");
+ }
+
+ var document = _context.Documents.FirstOrDefault(x =>
+ x.Title.Trim().ToLower().Equals(request.Title.Trim().ToLower())
+ && x.Importer != null
+ && x.Importer.Id == request.ImporterId);
+ if (document is not null)
+ {
+ throw new ConflictException($"Document title already exists for user {importer.LastName}.");
+ }
+
+ var folder = await _context.Folders
+ .FirstOrDefaultAsync(x => x.Id == request.FolderId, cancellationToken);
+ if (folder is null)
+ {
+ throw new KeyNotFoundException("Folder does not exist.");
+ }
+
+ var entity = new Document()
+ {
+ Title = request.Title.Trim(),
+ Description = request.Description?.Trim(),
+ DocumentType = request.DocumentType.Trim(),
+ Importer = importer,
+ Department = importer.Department,
+ Folder = folder
+ };
+
+ var result = await _context.Documents.AddAsync(entity, cancellationToken);
+ folder.NumberOfDocuments += 1;
+ _context.Folders.Update(folder);
+ await _context.SaveChangesAsync(cancellationToken);
+ return _mapper.Map(result.Entity);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Documents/Commands/ImportDocument/ImportDocumentCommand.cs b/src/Application/Documents/Commands/ImportDocument/ImportDocumentCommand.cs
deleted file mode 100644
index 7989bf5a..00000000
--- a/src/Application/Documents/Commands/ImportDocument/ImportDocumentCommand.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using Application.Common.Exceptions;
-using Application.Common.Interfaces;
-using Application.Common.Models.Dtos.Physical;
-using AutoMapper;
-using Domain.Entities.Physical;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Documents.Commands.ImportDocument;
-
-public record ImportDocumentCommand : IRequest
-{
- public string Title { get; init; } = null!;
- public string? Description { get; init; }
- public string DocumentType { get; init; } = null!;
- public Guid ImporterId { get; init; }
- public Guid FolderId { get; init; }
-}
-
-public class ImportDocumentCommandHandler : IRequestHandler
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
-
- public ImportDocumentCommandHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
-
- public async Task Handle(ImportDocumentCommand request, CancellationToken cancellationToken)
- {
- var importer = await _context.Users
- .Include(x => x.Department)
- .FirstOrDefaultAsync(x => x.Id == request.ImporterId, cancellationToken);
- if (importer is null)
- {
- throw new KeyNotFoundException("User does not exist.");
- }
-
- var document = _context.Documents.FirstOrDefault(x =>
- x.Title.Trim().ToLower().Equals(request.Title.Trim().ToLower())
- && x.Importer != null
- && x.Importer.Id == request.ImporterId);
- if (document is not null)
- {
- throw new ConflictException($"Document title already exists for user {importer.LastName}.");
- }
-
- var folder = await _context.Folders
- .FirstOrDefaultAsync(x => x.Id == request.FolderId, cancellationToken);
- if (folder is null)
- {
- throw new KeyNotFoundException("Folder does not exist.");
- }
-
- var entity = new Document()
- {
- Title = request.Title.Trim(),
- Description = request.Description?.Trim(),
- DocumentType = request.DocumentType.Trim(),
- Importer = importer,
- Department = importer.Department,
- Folder = folder
- };
-
- var result = await _context.Documents.AddAsync(entity, cancellationToken);
- folder.NumberOfDocuments += 1;
- _context.Folders.Update(folder);
- await _context.SaveChangesAsync(cancellationToken);
- return _mapper.Map(result.Entity);
- }
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Commands/UpdateDocument.cs b/src/Application/Documents/Commands/UpdateDocument.cs
new file mode 100644
index 00000000..b0cac569
--- /dev/null
+++ b/src/Application/Documents/Commands/UpdateDocument.cs
@@ -0,0 +1,15 @@
+using Application.Common.Models.Dtos.Physical;
+using MediatR;
+
+namespace Application.Documents.Commands;
+
+public class UpdateDocument
+{
+ public record Command : IRequest
+ {
+ public Guid DocumentId { get; init; }
+ public string Title { get; init; } = null!;
+ public string? Description { get; init; }
+ public string DocumentType { get; init; } = null!;
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Documents/Commands/UpdateDocument/UpdateDocumentCommand.cs b/src/Application/Documents/Commands/UpdateDocument/UpdateDocumentCommand.cs
deleted file mode 100644
index d7b06736..00000000
--- a/src/Application/Documents/Commands/UpdateDocument/UpdateDocumentCommand.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using Application.Common.Models.Dtos.Physical;
-using MediatR;
-
-namespace Application.Documents.Commands.UpdateDocument;
-
-public record UpdateDocumentCommand : IRequest
-{
- public Guid DocumentId { get; init; }
- public string Title { get; init; } = null!;
- public string? Description { get; init; }
- public string DocumentType { get; init; } = null!;
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetAllDocumentTypes.cs b/src/Application/Documents/Queries/GetAllDocumentTypes.cs
new file mode 100644
index 00000000..41e53d1b
--- /dev/null
+++ b/src/Application/Documents/Queries/GetAllDocumentTypes.cs
@@ -0,0 +1,26 @@
+using System.Collections.ObjectModel;
+using Application.Common.Interfaces;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Documents.Queries;
+
+public class GetAllDocumentTypes
+{
+ public record Query : IRequest>;
+
+ public class QueryHandler : IRequestHandler>
+ {
+ private readonly IApplicationDbContext _context;
+
+ public QueryHandler(IApplicationDbContext context)
+ {
+ _context = context;
+ }
+ public async Task> Handle(Query request, CancellationToken cancellationToken)
+ {
+ return new ReadOnlyCollection(await _context.Documents.Select(x => x.DocumentType).Distinct()
+ .ToListAsync(cancellationToken));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetAllDocumentsPaginated.cs b/src/Application/Documents/Queries/GetAllDocumentsPaginated.cs
new file mode 100644
index 00000000..c6c34a92
--- /dev/null
+++ b/src/Application/Documents/Queries/GetAllDocumentsPaginated.cs
@@ -0,0 +1,138 @@
+using Application.Common.Exceptions;
+using Application.Common.Extensions;
+using Application.Common.Interfaces;
+using Application.Common.Mappings;
+using Application.Common.Models;
+using Application.Common.Models.Dtos.Physical;
+using AutoMapper;
+using AutoMapper.QueryableExtensions;
+using FluentValidation;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Documents.Queries;
+
+public class GetAllDocumentsPaginated
+{
+ public class Validator : AbstractValidator
+ {
+ public Validator()
+ {
+ RuleLevelCascadeMode = CascadeMode.Stop;
+
+ RuleFor(x => x.RoomId)
+ .Must((query, roomId) =>
+ {
+ if (roomId is null)
+ {
+ return query.LockerId is null && query.FolderId is null;
+ }
+
+ if (query.LockerId is null)
+ {
+ return query.FolderId is null;
+ }
+
+ return true;
+ }).WithMessage("Container orientation is not consistent");
+ }
+ }
+
+ public record Query : IRequest>
+ {
+ public Guid? RoomId { get; init; }
+ public Guid? LockerId { get; init; }
+ public Guid? FolderId { get; init; }
+ public string? SearchTerm { get; init; }
+ public int? Page { get; init; }
+ public int? Size { get; init; }
+ public string? SortBy { get; init; }
+ public string? SortOrder { get; init; }
+ }
+
+ public class QueryHandler : IRequestHandler>
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+
+ public QueryHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public async Task> Handle(Query request,
+ CancellationToken cancellationToken)
+ {
+ var documents = _context.Documents.AsQueryable();
+ var roomExists = request.RoomId is not null;
+ var lockerExists = request.LockerId is not null;
+ var folderExists = request.FolderId is not null;
+
+ documents = documents.Include(x => x.Department);
+
+ if (folderExists)
+ {
+ var folder = await _context.Folders
+ .Include(x => x.Locker)
+ .ThenInclude(y => y.Room)
+ .FirstOrDefaultAsync(x => x.Id == request.FolderId
+ && x.IsAvailable, cancellationToken);
+ if (folder is null)
+ {
+ throw new KeyNotFoundException("Folder does not exist.");
+ }
+
+ if (folder.Locker.Id != request.LockerId
+ || folder.Locker.Room.Id != request.RoomId)
+ {
+ throw new ConflictException("Either locker or room does not match folder.");
+ }
+
+ documents = documents
+ .Where(x => x.Folder!.Id == request.FolderId);
+ }
+ else if (lockerExists)
+ {
+ var locker = await _context.Lockers
+ .Include(x => x.Room)
+ .FirstOrDefaultAsync(x => x.Id == request.LockerId
+ && x.IsAvailable, cancellationToken);
+ if (locker is null)
+ {
+ throw new KeyNotFoundException("Locker does not exist.");
+ }
+
+ if (locker.Room.Id != request.RoomId)
+ {
+ throw new ConflictException("Room does not match locker.");
+ }
+
+ documents = documents.Where(x => x.Folder!.Locker.Id == request.LockerId);
+ }
+ else if (roomExists)
+ {
+ var room = await _context.Rooms
+ .FirstOrDefaultAsync(x => x.Id == request.RoomId
+ && x.IsAvailable, cancellationToken);
+ if (room is null)
+ {
+ throw new KeyNotFoundException("Room does not exist.");
+ }
+
+ documents = documents.Where(x => x.Folder!.Locker.Room.Id == request.RoomId);
+ }
+
+ var sortBy = request.SortBy ?? nameof(DocumentDto.Id);
+ var sortOrder = request.SortOrder ?? "asc";
+ var pageNumber = request.Page ?? 1;
+ var sizeNumber = request.Size ?? 5;
+ var result = await documents
+ .ProjectTo(_mapper.ConfigurationProvider)
+ .OrderByCustom(sortBy, sortOrder)
+ .PaginatedListAsync(pageNumber, sizeNumber);
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetAllDocumentsPaginated/GetAllDocumentsPaginatedQuery.cs b/src/Application/Documents/Queries/GetAllDocumentsPaginated/GetAllDocumentsPaginatedQuery.cs
deleted file mode 100644
index ff2de9ad..00000000
--- a/src/Application/Documents/Queries/GetAllDocumentsPaginated/GetAllDocumentsPaginatedQuery.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using Application.Common.Exceptions;
-using Application.Common.Extensions;
-using Application.Common.Interfaces;
-using Application.Common.Mappings;
-using Application.Common.Models;
-using Application.Common.Models.Dtos.Physical;
-using AutoMapper;
-using AutoMapper.QueryableExtensions;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Documents.Queries.GetAllDocumentsPaginated;
-
-public record GetAllDocumentsPaginatedQuery : IRequest>
-{
- public Guid? RoomId { get; init; }
- public Guid? LockerId { get; init; }
- public Guid? FolderId { get; init; }
- public int? Page { get; init; }
- public int? Size { get; init; }
- public string? SortBy { get; init; }
- public string? SortOrder { get; init; }
-}
-
-public class GetAllDocumentsPaginatedQueryHandler : IRequestHandler>
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
-
- public GetAllDocumentsPaginatedQueryHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
-
- public async Task> Handle(GetAllDocumentsPaginatedQuery request,
- CancellationToken cancellationToken)
- {
- var documents = _context.Documents.AsQueryable();
- var roomExists = request.RoomId is not null;
- var lockerExists = request.LockerId is not null;
- var folderExists = request.FolderId is not null;
-
- documents = documents.Include(x => x.Department);
-
- if (folderExists)
- {
- var folder = await _context.Folders
- .Include(x => x.Locker)
- .ThenInclude(y => y.Room)
- .FirstOrDefaultAsync(x => x.Id == request.FolderId
- && x.IsAvailable, cancellationToken);
- if (folder is null)
- {
- throw new KeyNotFoundException("Folder does not exist.");
- }
-
- if (folder.Locker.Id != request.LockerId
- || folder.Locker.Room.Id != request.RoomId)
- {
- throw new ConflictException("Either locker or room does not match folder.");
- }
-
- documents = documents
- .Where(x => x.Folder!.Id == request.FolderId);
- }
- else if (lockerExists)
- {
- var locker = await _context.Lockers
- .Include(x => x.Room)
- .FirstOrDefaultAsync(x => x.Id == request.LockerId
- && x.IsAvailable, cancellationToken);
- if (locker is null)
- {
- throw new KeyNotFoundException("Locker does not exist.");
- }
-
- if (locker.Room.Id != request.RoomId)
- {
- throw new ConflictException("Room does not match locker.");
- }
-
- documents = documents.Where(x => x.Folder!.Locker.Id == request.LockerId);
- }
- else if (roomExists)
- {
- var room = await _context.Rooms
- .FirstOrDefaultAsync(x => x.Id == request.RoomId
- && x.IsAvailable, cancellationToken);
- if (room is null)
- {
- throw new KeyNotFoundException("Room does not exist.");
- }
-
- documents = documents.Where(x => x.Folder!.Locker.Room.Id == request.RoomId);
- }
-
- var sortBy = request.SortBy ?? nameof(DocumentDto.Id);
- var sortOrder = request.SortOrder ?? "asc";
- var pageNumber = request.Page ?? 1;
- var sizeNumber = request.Size ?? 5;
- var result = await documents
- .ProjectTo(_mapper.ConfigurationProvider)
- .OrderByCustom(sortBy, sortOrder)
- .PaginatedListAsync(pageNumber, sizeNumber);
-
- return result;
- }
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetAllDocumentsPaginated/GetAllDocumentsPaginatedQueryValidator.cs b/src/Application/Documents/Queries/GetAllDocumentsPaginated/GetAllDocumentsPaginatedQueryValidator.cs
deleted file mode 100644
index d95c7e3d..00000000
--- a/src/Application/Documents/Queries/GetAllDocumentsPaginated/GetAllDocumentsPaginatedQueryValidator.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using FluentValidation;
-
-namespace Application.Documents.Queries.GetAllDocumentsPaginated;
-
-public class GetAllDocumentsPaginatedQueryValidator : AbstractValidator
-{
- public GetAllDocumentsPaginatedQueryValidator()
- {
- RuleLevelCascadeMode = CascadeMode.Stop;
-
- RuleFor(x => x.RoomId)
- .Must((query, roomId) =>
- {
- if (roomId is null)
- {
- return query.LockerId is null && query.FolderId is null;
- }
-
- if (query.LockerId is null)
- {
- return query.FolderId is null;
- }
-
- return true;
- }).WithMessage("Container orientation is not consistent");
- }
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetDocumentById.cs b/src/Application/Documents/Queries/GetDocumentById.cs
new file mode 100644
index 00000000..bf7c29d7
--- /dev/null
+++ b/src/Application/Documents/Queries/GetDocumentById.cs
@@ -0,0 +1,44 @@
+using Application.Common.Interfaces;
+using Application.Common.Models.Dtos.Physical;
+using AutoMapper;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Documents.Queries;
+
+public class GetDocumentById
+{
+ public record Query : IRequest
+ {
+ public Guid DocumentId { get; init; }
+ }
+
+ public class QueryHandler : IRequestHandler
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+
+ public QueryHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+ public async Task Handle(Query request, CancellationToken cancellationToken)
+ {
+ var document = await _context.Documents
+ .Include(x => x.Department)
+ .Include(x => x.Importer)
+ .Include(x => x.Folder)
+ .ThenInclude(y => y.Locker)
+ .ThenInclude(z => z.Room)
+ .FirstOrDefaultAsync(x => x.Id == request.DocumentId, cancellationToken);
+
+ if (document is null)
+ {
+ throw new KeyNotFoundException("Document does not exist.");
+ }
+
+ return _mapper.Map(document);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetDocumentById/GetDocumentByIdQuery.cs b/src/Application/Documents/Queries/GetDocumentById/GetDocumentByIdQuery.cs
deleted file mode 100644
index c1f62b70..00000000
--- a/src/Application/Documents/Queries/GetDocumentById/GetDocumentByIdQuery.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Application.Common.Interfaces;
-using Application.Common.Models.Dtos.Physical;
-using AutoMapper;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Documents.Queries.GetDocumentById;
-
-public record GetDocumentByIdQuery : IRequest
-{
- public Guid Id { get; init; }
-}
-
-public class GetDocumentByIdQueryHandler : IRequestHandler
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
-
- public GetDocumentByIdQueryHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
- public async Task Handle(GetDocumentByIdQuery request, CancellationToken cancellationToken)
- {
- var document = await _context.Documents
- .Include(x => x.Department)
- .Include(x => x.Importer)
- .Include(x => x.Folder)
- .ThenInclude(y => y.Locker)
- .ThenInclude(z => z.Room)
- .FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken);
-
- if (document is null)
- {
- throw new KeyNotFoundException("Document does not exist.");
- }
-
- return _mapper.Map(document);
- }
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetDocumentTypes/GetAllDocumentTypesQuery.cs b/src/Application/Documents/Queries/GetDocumentTypes/GetAllDocumentTypesQuery.cs
deleted file mode 100644
index 841aa23e..00000000
--- a/src/Application/Documents/Queries/GetDocumentTypes/GetAllDocumentTypesQuery.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Collections.ObjectModel;
-using Application.Common.Interfaces;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Documents.Queries.GetDocumentTypes;
-
-public record GetAllDocumentTypesQuery : IRequest>;
-
-public class GetAllDocumentTypesQueryHandler : IRequestHandler>
-{
- private readonly IApplicationDbContext _context;
-
- public GetAllDocumentTypesQueryHandler(IApplicationDbContext context)
- {
- _context = context;
- }
- public async Task> Handle(GetAllDocumentTypesQuery request, CancellationToken cancellationToken)
- {
- return new ReadOnlyCollection(await _context.Documents.Select(x => x.DocumentType).Distinct()
- .ToListAsync(cancellationToken));
- }
-}
\ No newline at end of file
diff --git a/src/Application/Documents/Queries/GetDocumentTypes/GetDocumentTypesQuery.cs b/src/Application/Documents/Queries/GetDocumentTypes/GetDocumentTypesQuery.cs
deleted file mode 100644
index b6f65030..00000000
--- a/src/Application/Documents/Queries/GetDocumentTypes/GetDocumentTypesQuery.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Collections.ObjectModel;
-using Application.Common.Interfaces;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Documents.Queries.GetDocumentTypes;
-
-public record GetDocumentTypesQuery : IRequest>;
-
-public class GetDocumentTypesQueryHandler : IRequestHandler>
-{
- private readonly IApplicationDbContext _context;
-
- public GetDocumentTypesQueryHandler(IApplicationDbContext context)
- {
- _context = context;
- }
- public async Task> Handle(GetDocumentTypesQuery request, CancellationToken cancellationToken)
- {
- return new ReadOnlyCollection(await _context.Documents.Select(x => x.DocumentType)
- .ToListAsync(cancellationToken));
- }
-}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/AddFolder.cs b/src/Application/Folders/Commands/AddFolder.cs
new file mode 100644
index 00000000..4b7bd9b9
--- /dev/null
+++ b/src/Application/Folders/Commands/AddFolder.cs
@@ -0,0 +1,95 @@
+using Application.Common.Exceptions;
+using Application.Common.Interfaces;
+using Application.Common.Models.Dtos.Physical;
+using AutoMapper;
+using Domain.Entities.Physical;
+using Domain.Exceptions;
+using FluentValidation;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Folders.Commands;
+
+public class AddFolder
+{
+ public class Validator : AbstractValidator
+ {
+ public Validator()
+ {
+ RuleLevelCascadeMode = CascadeMode.Stop;
+
+ RuleFor(f => f.Name)
+ .NotEmpty().WithMessage("Name is required.")
+ .MaximumLength(64).WithMessage("Name cannot exceed 64 characters.");
+
+ RuleFor(f => f.Description)
+ .MaximumLength(256).WithMessage("Description cannot exceed 256 characters.");
+
+ RuleFor(f => f.Capacity)
+ .NotEmpty().WithMessage("Folder capacity is required.")
+ .GreaterThanOrEqualTo(1).WithMessage("Folder's capacity cannot be less than 1.");
+
+ RuleFor(f => f.LockerId)
+ .NotEmpty().WithMessage("LockerId is required.");
+ }
+ }
+
+ public record Command : IRequest
+ {
+ public string Name { get; init; } = null!;
+ public string? Description { get; init; }
+ public int Capacity { get; init; }
+ public Guid LockerId { get; init; }
+ }
+
+ public class CommandHandler : IRequestHandler
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+
+ public CommandHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public async Task Handle(Command request, CancellationToken cancellationToken)
+ {
+ var locker = await _context.Lockers.FirstOrDefaultAsync(l => l.Id == request.LockerId, cancellationToken);
+
+ if (locker is null)
+ {
+ throw new KeyNotFoundException("Locker does not exist.");
+ }
+
+ if (locker.NumberOfFolders >= locker.Capacity)
+ {
+ throw new LimitExceededException("This locker cannot accept more folders.");
+ }
+
+ var folder = await _context.Folders.FirstOrDefaultAsync(x =>
+ x.Name.Trim().ToLower().Equals(request.Name.Trim().ToLower())
+ && x.Locker.Id.Equals(request.LockerId), cancellationToken);
+
+ if (folder is not null)
+ {
+ throw new ConflictException("Folder name already exists.");
+ }
+
+ var entity = new Folder
+ {
+ Name = request.Name.Trim(),
+ Description = request.Description,
+ NumberOfDocuments = 0,
+ Capacity = request.Capacity,
+ Locker = locker,
+ IsAvailable = true
+ };
+ var result = await _context.Folders.AddAsync(entity, cancellationToken);
+ locker.NumberOfFolders += 1;
+ _context.Lockers.Update(locker);
+ await _context.SaveChangesAsync(cancellationToken);
+ return _mapper.Map(result.Entity);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/AddFolder/AddFolderCommand.cs b/src/Application/Folders/Commands/AddFolder/AddFolderCommand.cs
deleted file mode 100644
index bf974013..00000000
--- a/src/Application/Folders/Commands/AddFolder/AddFolderCommand.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-using Application.Common.Exceptions;
-using Application.Common.Interfaces;
-using Application.Common.Models.Dtos.Physical;
-using AutoMapper;
-using Domain.Entities.Physical;
-using Domain.Exceptions;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Folders.Commands.AddFolder;
-
-public record AddFolderCommand : IRequest
-{
- public string Name { get; init; } = null!;
- public string? Description { get; init; }
- public int Capacity { get; init; }
- public Guid LockerId { get; init; }
-}
-
-public class AddFolderCommandHandler : IRequestHandler
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
-
- public AddFolderCommandHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
-
- public async Task Handle(AddFolderCommand request, CancellationToken cancellationToken)
- {
- var locker = await _context.Lockers.FirstOrDefaultAsync(l => l.Id == request.LockerId, cancellationToken);
-
- if (locker is null)
- {
- throw new KeyNotFoundException("Locker does not exist.");
- }
-
- if (locker.NumberOfFolders >= locker.Capacity)
- {
- throw new LimitExceededException("This locker cannot accept more folders.");
- }
-
- var folder = await _context.Folders.FirstOrDefaultAsync(x => x.Name.Trim().ToLower().Equals(request.Name.Trim().ToLower())
- && x.Locker.Id.Equals(request.LockerId), cancellationToken);
-
- if (folder is not null)
- {
- throw new ConflictException("Folder's name already exists.");
- }
-
- var entity = new Folder
- {
- Name = request.Name.Trim(),
- Description = request.Description,
- NumberOfDocuments = 0,
- Capacity = request.Capacity,
- Locker = locker,
- IsAvailable = true
- };
- var result = await _context.Folders.AddAsync(entity, cancellationToken);
- locker.NumberOfFolders += 1;
- _context.Lockers.Update(locker);
- await _context.SaveChangesAsync(cancellationToken);
- return _mapper.Map(result.Entity);
- }
-}
diff --git a/src/Application/Folders/Commands/AddFolder/AddFolderCommandValidator.cs b/src/Application/Folders/Commands/AddFolder/AddFolderCommandValidator.cs
deleted file mode 100644
index f7717f54..00000000
--- a/src/Application/Folders/Commands/AddFolder/AddFolderCommandValidator.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using FluentValidation;
-
-namespace Application.Folders.Commands.AddFolder;
-
-public class AddFolderCommandValidator : AbstractValidator
-{
- public AddFolderCommandValidator()
- {
-
- RuleLevelCascadeMode = CascadeMode.Stop;
-
- RuleFor(f => f.Name)
- .NotEmpty().WithMessage("Name is required.")
- .MaximumLength(64).WithMessage("Name cannot exceed 64 characters.");
-
- RuleFor(f => f.Description)
- .MaximumLength(256).WithMessage("Description cannot exceed 256 characters.");
-
- RuleFor(f => f.Capacity)
- .NotEmpty().WithMessage("Folder capacity is required.")
- .GreaterThanOrEqualTo(1).WithMessage("Folder's capacity cannot be less than 1.");
-
- RuleFor(f => f.LockerId)
- .NotEmpty().WithMessage("LockerId is required.");
- }
-
-}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/DisableFolder.cs b/src/Application/Folders/Commands/DisableFolder.cs
new file mode 100644
index 00000000..020bc1fe
--- /dev/null
+++ b/src/Application/Folders/Commands/DisableFolder.cs
@@ -0,0 +1,66 @@
+using Application.Common.Exceptions;
+using Application.Common.Interfaces;
+using Application.Common.Models.Dtos.Physical;
+using AutoMapper;
+using FluentValidation;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace Application.Folders.Commands;
+
+public class DisableFolder
+{
+ public class Validator : AbstractValidator
+ {
+ public Validator()
+ {
+ RuleLevelCascadeMode = CascadeMode.Stop;
+
+ RuleFor(f => f.FolderId)
+ .NotEmpty().WithMessage("FolderId is required.");
+ }
+ }
+
+ public record Command : IRequest
+ {
+ public Guid FolderId { get; init; }
+ }
+
+ public class CommandHandler : IRequestHandler
+ {
+ private readonly IApplicationDbContext _context;
+ private readonly IMapper _mapper;
+
+ public CommandHandler(IApplicationDbContext context, IMapper mapper)
+ {
+ _context = context;
+ _mapper = mapper;
+ }
+
+ public async Task Handle(Command request, CancellationToken cancellationToken)
+ {
+ var folder = await _context.Folders
+ .FirstOrDefaultAsync(f => f.Id.Equals(request.FolderId), cancellationToken);
+
+ if (folder is null)
+ {
+ throw new KeyNotFoundException("Folder does not exist.");
+ }
+
+ if (!folder.IsAvailable)
+ {
+ throw new ConflictException("Folder has already been disabled.");
+ }
+
+ if (folder.NumberOfDocuments > 0)
+ {
+ throw new InvalidOperationException("Folder cannot be disabled because it contains documents.");
+ }
+
+ folder.IsAvailable = false;
+ _context.Folders.Update(folder);
+ await _context.SaveChangesAsync(cancellationToken);
+ return _mapper.Map(folder);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/DisableFolder/DisableFolderCommand.cs b/src/Application/Folders/Commands/DisableFolder/DisableFolderCommand.cs
deleted file mode 100644
index adf845df..00000000
--- a/src/Application/Folders/Commands/DisableFolder/DisableFolderCommand.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using Application.Common.Exceptions;
-using Application.Common.Interfaces;
-using Application.Common.Models.Dtos.Physical;
-using AutoMapper;
-using MediatR;
-using Microsoft.EntityFrameworkCore;
-
-namespace Application.Folders.Commands.DisableFolder;
-
-public record DisableFolderCommand : IRequest
-{
- public Guid FolderId { get; init; }
-}
-
-public class DisableFolderCommandHandler : IRequestHandler
-{
- private readonly IApplicationDbContext _context;
- private readonly IMapper _mapper;
-
- public DisableFolderCommandHandler(IApplicationDbContext context, IMapper mapper)
- {
- _context = context;
- _mapper = mapper;
- }
-
- public async Task Handle(DisableFolderCommand request, CancellationToken cancellationToken)
- {
- var folder = await _context.Folders
- .FirstOrDefaultAsync(f => f.Id.Equals(request.FolderId), cancellationToken);
-
- if (folder is null)
- {
- throw new KeyNotFoundException("Folder does not exist.");
- }
-
- if (!folder.IsAvailable)
- {
- throw new ConflictException("Folder has already been disabled.");
- }
-
- if (folder.NumberOfDocuments > 0)
- {
- throw new InvalidOperationException("Folder cannot be disabled because it contains documents.");
- }
-
- folder.IsAvailable = false;
- _context.Folders.Update(folder);
- await _context.SaveChangesAsync(cancellationToken);
- return _mapper.Map(folder);
- }
-}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/DisableFolder/DisableFolderCommandValidator.cs b/src/Application/Folders/Commands/DisableFolder/DisableFolderCommandValidator.cs
deleted file mode 100644
index 04621166..00000000
--- a/src/Application/Folders/Commands/DisableFolder/DisableFolderCommandValidator.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using FluentValidation;
-
-namespace Application.Folders.Commands.DisableFolder;
-
-public class DisableFolderCommandValidator : AbstractValidator
-{
- public DisableFolderCommandValidator()
- {
- RuleLevelCascadeMode = CascadeMode.Stop;
-
- RuleFor(f => f.FolderId)
- .NotEmpty().WithMessage("FolderId is required.");
- }
-}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/EnableFolder.cs b/src/Application/Folders/Commands/EnableFolder.cs
new file mode 100644
index 00000000..33e3cb23
--- /dev/null
+++ b/src/Application/Folders/Commands/EnableFolder.cs
@@ -0,0 +1,12 @@
+using Application.Common.Models.Dtos.Physical;
+using MediatR;
+
+namespace Application.Folders.Commands;
+
+public class EnableFolder
+{
+ public record Command : IRequest
+ {
+ public Guid FolderId { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/EnableFolder/EnableFolderCommand.cs b/src/Application/Folders/Commands/EnableFolder/EnableFolderCommand.cs
deleted file mode 100644
index eb7f49f9..00000000
--- a/src/Application/Folders/Commands/EnableFolder/EnableFolderCommand.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Application.Common.Models.Dtos.Physical;
-using MediatR;
-
-namespace Application.Folders.Commands.EnableFolder;
-
-public record EnableFolderCommand : IRequest
-{
- public Guid FolderId { get; init; }
-}
diff --git a/src/Application/Folders/Commands/RemoveFolder.cs b/src/Application/Folders/Commands/RemoveFolder.cs
new file mode 100644
index 00000000..528184ce
--- /dev/null
+++ b/src/Application/Folders/Commands/RemoveFolder.cs
@@ -0,0 +1,12 @@
+using Application.Common.Models.Dtos.Physical;
+using MediatR;
+
+namespace Application.Folders.Commands;
+
+public class RemoveFolder
+{
+ public record Command : IRequest
+ {
+ public Guid FolderId { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/RemoveFolder/RemoveFolderCommand.cs b/src/Application/Folders/Commands/RemoveFolder/RemoveFolderCommand.cs
deleted file mode 100644
index 91db8b5e..00000000
--- a/src/Application/Folders/Commands/RemoveFolder/RemoveFolderCommand.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Application.Common.Models.Dtos.Physical;
-using MediatR;
-
-namespace Application.Folders.Commands.RemoveFolder;
-
-public record RemoveFolderCommand : IRequest
-{
- public Guid FolderId { get; init; }
-}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/UpdateFolder.cs b/src/Application/Folders/Commands/UpdateFolder.cs
new file mode 100644
index 00000000..a467f7e3
--- /dev/null
+++ b/src/Application/Folders/Commands/UpdateFolder.cs
@@ -0,0 +1,15 @@
+using Application.Common.Models.Dtos.Physical;
+using MediatR;
+
+namespace Application.Folders.Commands;
+
+public class UpdateFolder
+{
+ public record Command : IRequest
+ {
+ public Guid FolderId { get; init; }
+ public string Name { get; init; } = null!;
+ public string? Description { get; init; }
+ public int Capacity { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/src/Application/Folders/Commands/UpdateFolder/UpdateFolderCommand.cs b/src/Application/Folders/Commands/UpdateFolder/UpdateFolderCommand.cs
deleted file mode 100644
index 30ebea09..00000000
--- a/src/Application/Folders/Commands/UpdateFolder/UpdateFolderCommand.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using Application.Common.Models.Dtos.Physical;
-using MediatR;
-
-namespace Application.Folders.Commands.UpdateFolder;
-
-public record UpdateFolderCommand : IRequest