From e77016feddbd7e20ac4acafc4c43bdfd2312b9c6 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Tue, 25 Nov 2025 17:19:04 +0500 Subject: [PATCH 01/61] feat: proposal for api reorganization --- Api/Controllers/ItemsController.cs | 101 ------------------ Api/DependencyInjection.cs | 5 + .../Handlers/CreateItem/CreateItemHandler.cs | 34 ++++++ .../Handlers/CreateItem}/CreateItemRequest.cs | 2 +- .../CreateItem}/CreateItemResponse.cs | 2 +- .../GetAllItems/GetAllItemsHandler.cs | 48 +++++++++ .../GetAllItems}/HolderEmployeeMapper.cs | 3 +- .../GetAllItems}/HolderEmployeeMapperTests.cs | 2 +- .../Handlers/GetAllItems}/ItemsResponse.cs | 4 +- .../Items/Handlers/ItemsController.cs | 58 ++++++++++ 10 files changed, 152 insertions(+), 107 deletions(-) delete mode 100644 Api/Controllers/ItemsController.cs create mode 100644 Api/Features/Items/Handlers/CreateItem/CreateItemHandler.cs rename Api/{Requests => Features/Items/Handlers/CreateItem}/CreateItemRequest.cs (91%) rename Api/{Responses => Features/Items/Handlers/CreateItem}/CreateItemResponse.cs (63%) create mode 100644 Api/Features/Items/Handlers/GetAllItems/GetAllItemsHandler.cs rename Api/{Mappers => Features/Items/Handlers/GetAllItems}/HolderEmployeeMapper.cs (92%) rename Api/{Mappers => Features/Items/Handlers/GetAllItems}/HolderEmployeeMapperTests.cs (92%) rename Api/{Responses => Features/Items/Handlers/GetAllItems}/ItemsResponse.cs (89%) create mode 100644 Api/Features/Items/Handlers/ItemsController.cs diff --git a/Api/Controllers/ItemsController.cs b/Api/Controllers/ItemsController.cs deleted file mode 100644 index 74446ed..0000000 --- a/Api/Controllers/ItemsController.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Api.EnternalDeps.EmployeesApi; -using Api.Mappers; -using Api.Requests; -using Api.Responses; -using Application.Commands; -using Application.Queries; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using TourmalineCore.AspNetCore.JwtAuthentication.Core.Filters; - -namespace Api.Controllers; - -[Authorize] -[ApiController] -[Route("api/items")] -public class ItemsController : ControllerBase -{ - /// - /// Get all items - /// - [RequiresPermission(UserClaimsProvider.CanViewItems)] - [HttpGet] - public async Task GetAllItemsAsync( - [FromServices] AllItemsQuery allItemsQuery, - [FromServices] EmployeesApi employeesApi - ) - { - var items = await allItemsQuery.GetAsync(); - - var allEmployeesResponse = await employeesApi.GetAllEmployeesAsync(); - - return new ItemsResponse - { - Items = items - .Select(x => new ItemDto - { - Id = x.Id, - Name = x.Name, - SerialNumber = x.SerialNumber, - ItemType = new ItemTypeDto - { - Id = x.ItemType.Id, - Name = x.ItemType.Name - }, - Price = x.Price, - Description = x.Description, - PurchaseDate = x.PurchaseDate, - HolderEmployee = HolderEmployeeMapper.MapToEmployeeDto(x.HolderEmployeeId, allEmployeesResponse) - }) - .ToList() - }; - } - - /// - /// Add an item - /// - /// - [RequiresPermission(UserClaimsProvider.CanManageItems)] - [HttpPost] - public async Task CreateItemAsync( - [FromServices] CreateItemCommand createItemCommand, - [Required][FromBody] CreateItemRequest createItemRequest - ) - { - var createItemCommandParams = new CreateItemCommandParams - { - Name = createItemRequest.Name, - SerialNumber = createItemRequest.SerialNumber, - ItemTypeId = createItemRequest.ItemTypeId, - Price = createItemRequest.Price, - Description = createItemRequest.Description, - PurchaseDate = createItemRequest.PurchaseDate, - HolderEmployeeId = createItemRequest.HolderEmployeeId - }; - - var newItemId = await createItemCommand.ExecuteAsync(createItemCommandParams); - - return new CreateItemResponse() - { - NewItemId = newItemId - }; - } - - /// - /// Deletes specific item - /// - /// - [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemsHardDeleteAllowed)] - [HttpDelete("{itemId}/hard-delete")] - public async Task HardDeleteItemAsync( - [FromServices] HardDeleteItemCommand hardDeleteItemCommand, - [Required][FromRoute] long itemId - ) - { - return new - { - isDeleted = await hardDeleteItemCommand.ExecuteAsync(itemId) - }; - } -} diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index b94215c..8dfd436 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -1,4 +1,6 @@ using Api.EnternalDeps.EmployeesApi; +using Api.Features.Items.Handlers.CreateItem; +using Api.Features.Items.Handlers.GetAllItems; using Application; using Application.Commands; using Application.Queries; @@ -36,5 +38,8 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); services.AddTransient(); services.AddTransient(); + + services.AddScoped(); + services.AddScoped(); } } diff --git a/Api/Features/Items/Handlers/CreateItem/CreateItemHandler.cs b/Api/Features/Items/Handlers/CreateItem/CreateItemHandler.cs new file mode 100644 index 0000000..907dee8 --- /dev/null +++ b/Api/Features/Items/Handlers/CreateItem/CreateItemHandler.cs @@ -0,0 +1,34 @@ +using Application.Commands; + +namespace Api.Features.Items.Handlers.CreateItem; + +public class CreateItemHandler +{ + private readonly CreateItemCommand _createItemCommand; + + public CreateItemHandler(CreateItemCommand createItemCommand) + { + _createItemCommand = createItemCommand; + } + + public async Task HandleAsync(CreateItemRequest createItemRequest) + { + var createItemCommandParams = new CreateItemCommandParams + { + Name = createItemRequest.Name, + SerialNumber = createItemRequest.SerialNumber, + ItemTypeId = createItemRequest.ItemTypeId, + Price = createItemRequest.Price, + Description = createItemRequest.Description, + PurchaseDate = createItemRequest.PurchaseDate, + HolderEmployeeId = createItemRequest.HolderEmployeeId + }; + + var newItemId = await _createItemCommand.ExecuteAsync(createItemCommandParams); + + return new CreateItemResponse() + { + NewItemId = newItemId + }; + } +} diff --git a/Api/Requests/CreateItemRequest.cs b/Api/Features/Items/Handlers/CreateItem/CreateItemRequest.cs similarity index 91% rename from Api/Requests/CreateItemRequest.cs rename to Api/Features/Items/Handlers/CreateItem/CreateItemRequest.cs index 4f427ca..7606e9f 100644 --- a/Api/Requests/CreateItemRequest.cs +++ b/Api/Features/Items/Handlers/CreateItem/CreateItemRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Api.Requests; +namespace Api.Features.Items.Handlers.CreateItem; public class CreateItemRequest { diff --git a/Api/Responses/CreateItemResponse.cs b/Api/Features/Items/Handlers/CreateItem/CreateItemResponse.cs similarity index 63% rename from Api/Responses/CreateItemResponse.cs rename to Api/Features/Items/Handlers/CreateItem/CreateItemResponse.cs index 0fac7f6..5879b00 100644 --- a/Api/Responses/CreateItemResponse.cs +++ b/Api/Features/Items/Handlers/CreateItem/CreateItemResponse.cs @@ -1,4 +1,4 @@ -namespace Api.Responses; +namespace Api.Features.Items.Handlers.CreateItem; public class CreateItemResponse { diff --git a/Api/Features/Items/Handlers/GetAllItems/GetAllItemsHandler.cs b/Api/Features/Items/Handlers/GetAllItems/GetAllItemsHandler.cs new file mode 100644 index 0000000..e83f443 --- /dev/null +++ b/Api/Features/Items/Handlers/GetAllItems/GetAllItemsHandler.cs @@ -0,0 +1,48 @@ +using Api.EnternalDeps.EmployeesApi; +using Api.Responses; +using Application.Queries; + +namespace Api.Features.Items.Handlers.GetAllItems; + +public class GetAllItemsHandler +{ + private readonly AllItemsQuery _allItemsQuery; + private readonly EmployeesApi _employeesApi; + + public GetAllItemsHandler( + AllItemsQuery allItemsQuery, + EmployeesApi employeesApi + ) + { + _allItemsQuery = allItemsQuery; + _employeesApi = employeesApi; + } + + public async Task HandleAsync() + { + var items = await _allItemsQuery.GetAsync(); + + var allEmployeesResponse = await _employeesApi.GetAllEmployeesAsync(); + + return new ItemsResponse + { + Items = items + .Select(x => new ItemDto + { + Id = x.Id, + Name = x.Name, + SerialNumber = x.SerialNumber, + ItemType = new ItemTypeDto + { + Id = x.ItemType.Id, + Name = x.ItemType.Name + }, + Price = x.Price, + Description = x.Description, + PurchaseDate = x.PurchaseDate, + HolderEmployee = HolderEmployeeMapper.MapToEmployeeDto(x.HolderEmployeeId, allEmployeesResponse) + }) + .ToList() + }; + } +} diff --git a/Api/Mappers/HolderEmployeeMapper.cs b/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapper.cs similarity index 92% rename from Api/Mappers/HolderEmployeeMapper.cs rename to Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapper.cs index 14643b6..386011c 100644 --- a/Api/Mappers/HolderEmployeeMapper.cs +++ b/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapper.cs @@ -1,7 +1,6 @@ using Api.EnternalDeps.EmployeesApi.Responses; -using Api.Responses; -namespace Api.Mappers; +namespace Api.Features.Items.Handlers.GetAllItems; public class HolderEmployeeMapper { diff --git a/Api/Mappers/HolderEmployeeMapperTests.cs b/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapperTests.cs similarity index 92% rename from Api/Mappers/HolderEmployeeMapperTests.cs rename to Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapperTests.cs index cbe5d84..7f02ef1 100644 --- a/Api/Mappers/HolderEmployeeMapperTests.cs +++ b/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapperTests.cs @@ -1,7 +1,7 @@ using Api.EnternalDeps.EmployeesApi.Responses; using Xunit; -namespace Api.Mappers; +namespace Api.Features.Items.Handlers.GetAllItems; public class HolderEmployeeMapperTests { diff --git a/Api/Responses/ItemsResponse.cs b/Api/Features/Items/Handlers/GetAllItems/ItemsResponse.cs similarity index 89% rename from Api/Responses/ItemsResponse.cs rename to Api/Features/Items/Handlers/GetAllItems/ItemsResponse.cs index 2bf4cf3..b0d6023 100644 --- a/Api/Responses/ItemsResponse.cs +++ b/Api/Features/Items/Handlers/GetAllItems/ItemsResponse.cs @@ -1,4 +1,6 @@ -namespace Api.Responses; +using Api.Responses; + +namespace Api.Features.Items.Handlers.GetAllItems; public class ItemsResponse { diff --git a/Api/Features/Items/Handlers/ItemsController.cs b/Api/Features/Items/Handlers/ItemsController.cs new file mode 100644 index 0000000..b77100e --- /dev/null +++ b/Api/Features/Items/Handlers/ItemsController.cs @@ -0,0 +1,58 @@ +using System.ComponentModel.DataAnnotations; +using Api.Features.Items.Handlers.CreateItem; +using Api.Features.Items.Handlers.GetAllItems; +using Application.Commands; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using TourmalineCore.AspNetCore.JwtAuthentication.Core.Filters; + +namespace Api.Features.Items.Handlers; + +[Authorize] +[ApiController] +[Route("api/items")] +public class ItemsController : ControllerBase +{ + /// + /// Get all items + /// + [RequiresPermission(UserClaimsProvider.CanViewItems)] + [HttpGet] + public Task GetAllItemsAsync( + [FromServices] GetAllItemsHandler getAllItemsHandler + ) + { + return getAllItemsHandler.HandleAsync(); + } + + /// + /// Add an item + /// + /// + [RequiresPermission(UserClaimsProvider.CanManageItems)] + [HttpPost] + public Task CreateItemAsync( + [FromServices] CreateItemHandler createItemHandler, + [Required][FromBody] CreateItemRequest createItemRequest + ) + { + return createItemHandler.HandleAsync(createItemRequest); + } + + /// + /// Deletes specific item + /// + /// + [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemsHardDeleteAllowed)] + [HttpDelete("{itemId}/hard-delete")] + public async Task HardDeleteItemAsync( + [FromServices] HardDeleteItemCommand hardDeleteItemCommand, + [Required][FromRoute] long itemId + ) + { + return new + { + isDeleted = await hardDeleteItemCommand.ExecuteAsync(itemId) + }; + } +} From b09ed7b00fd63b18fcbd1f6b834683cc9ef79709 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 25 Nov 2025 12:21:46 +0000 Subject: [PATCH 02/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dc12873..af5bae1 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-81.90%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.65%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.78%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-82.22%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.34%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-89.96%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From de904cdc66baa152d45c269c3f92e9d5ebbc6086 Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Tue, 25 Nov 2025 22:37:16 +0500 Subject: [PATCH 03/61] refactor: move ItemsController.cs one level higner in the folders hierarchy --- Api/Features/Items/{Handlers => }/ItemsController.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Api/Features/Items/{Handlers => }/ItemsController.cs (100%) diff --git a/Api/Features/Items/Handlers/ItemsController.cs b/Api/Features/Items/ItemsController.cs similarity index 100% rename from Api/Features/Items/Handlers/ItemsController.cs rename to Api/Features/Items/ItemsController.cs From b2723483869b5bc56a5ce66901b5477190a854bd Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Tue, 25 Nov 2025 22:56:55 +0500 Subject: [PATCH 04/61] format: try to fail on unnecessary usings --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 4701ee2..b94de00 100644 --- a/.editorconfig +++ b/.editorconfig @@ -32,6 +32,9 @@ dotnet_separate_import_directive_groups = false dotnet_sort_system_directives_first = true file_header_template = unset +# no unnecessary usings +dotnet_diagnostic.IDE0005.severity = error + # this. and Me. preferences dotnet_style_qualification_for_event = false dotnet_style_qualification_for_field = false From fa1b865c917475aa53fb1f9252bc3924929c15ea Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Tue, 25 Nov 2025 22:58:53 +0500 Subject: [PATCH 05/61] Revert "format: try to fail on unnecessary usings" This reverts commit b2723483869b5bc56a5ce66901b5477190a854bd. --- .editorconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index b94de00..4701ee2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -32,9 +32,6 @@ dotnet_separate_import_directive_groups = false dotnet_sort_system_directives_first = true file_header_template = unset -# no unnecessary usings -dotnet_diagnostic.IDE0005.severity = error - # this. and Me. preferences dotnet_style_qualification_for_event = false dotnet_style_qualification_for_field = false From b0a61b842e97744417c9e8659062b7205f4db07c Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Wed, 26 Nov 2025 10:52:13 +0500 Subject: [PATCH 06/61] chore: change ItemsController namespace --- Api/Features/Items/ItemsController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index b77100e..a80201b 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Filters; -namespace Api.Features.Items.Handlers; +namespace Api.Features.Items; [Authorize] [ApiController] From 9096fc030e8e6a26874ebd0dee2a5565dce3a87a Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Wed, 26 Nov 2025 16:57:41 +0500 Subject: [PATCH 07/61] chore: remove Handlers folder --- Api/DependencyInjection.cs | 4 ++-- .../Items/{Handlers => }/CreateItem/CreateItemHandler.cs | 2 +- .../Items/{Handlers => }/CreateItem/CreateItemRequest.cs | 2 +- .../Items/{Handlers => }/CreateItem/CreateItemResponse.cs | 2 +- .../Items/{Handlers => }/GetAllItems/GetAllItemsHandler.cs | 2 +- .../Items/{Handlers => }/GetAllItems/HolderEmployeeMapper.cs | 2 +- .../{Handlers => }/GetAllItems/HolderEmployeeMapperTests.cs | 2 +- .../Items/{Handlers => }/GetAllItems/ItemsResponse.cs | 2 +- Api/Features/Items/ItemsController.cs | 4 ++-- 9 files changed, 11 insertions(+), 11 deletions(-) rename Api/Features/Items/{Handlers => }/CreateItem/CreateItemHandler.cs (95%) rename Api/Features/Items/{Handlers => }/CreateItem/CreateItemRequest.cs (91%) rename Api/Features/Items/{Handlers => }/CreateItem/CreateItemResponse.cs (63%) rename Api/Features/Items/{Handlers => }/GetAllItems/GetAllItemsHandler.cs (96%) rename Api/Features/Items/{Handlers => }/GetAllItems/HolderEmployeeMapper.cs (92%) rename Api/Features/Items/{Handlers => }/GetAllItems/HolderEmployeeMapperTests.cs (92%) rename Api/Features/Items/{Handlers => }/GetAllItems/ItemsResponse.cs (93%) diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 8dfd436..8dd71a4 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -1,6 +1,6 @@ using Api.EnternalDeps.EmployeesApi; -using Api.Features.Items.Handlers.CreateItem; -using Api.Features.Items.Handlers.GetAllItems; +using Api.Features.Items.CreateItem; +using Api.Features.Items.GetAllItems; using Application; using Application.Commands; using Application.Queries; diff --git a/Api/Features/Items/Handlers/CreateItem/CreateItemHandler.cs b/Api/Features/Items/CreateItem/CreateItemHandler.cs similarity index 95% rename from Api/Features/Items/Handlers/CreateItem/CreateItemHandler.cs rename to Api/Features/Items/CreateItem/CreateItemHandler.cs index 907dee8..6246b54 100644 --- a/Api/Features/Items/Handlers/CreateItem/CreateItemHandler.cs +++ b/Api/Features/Items/CreateItem/CreateItemHandler.cs @@ -1,6 +1,6 @@ using Application.Commands; -namespace Api.Features.Items.Handlers.CreateItem; +namespace Api.Features.Items.CreateItem; public class CreateItemHandler { diff --git a/Api/Features/Items/Handlers/CreateItem/CreateItemRequest.cs b/Api/Features/Items/CreateItem/CreateItemRequest.cs similarity index 91% rename from Api/Features/Items/Handlers/CreateItem/CreateItemRequest.cs rename to Api/Features/Items/CreateItem/CreateItemRequest.cs index 7606e9f..bebc464 100644 --- a/Api/Features/Items/Handlers/CreateItem/CreateItemRequest.cs +++ b/Api/Features/Items/CreateItem/CreateItemRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Api.Features.Items.Handlers.CreateItem; +namespace Api.Features.Items.CreateItem; public class CreateItemRequest { diff --git a/Api/Features/Items/Handlers/CreateItem/CreateItemResponse.cs b/Api/Features/Items/CreateItem/CreateItemResponse.cs similarity index 63% rename from Api/Features/Items/Handlers/CreateItem/CreateItemResponse.cs rename to Api/Features/Items/CreateItem/CreateItemResponse.cs index 5879b00..40467ea 100644 --- a/Api/Features/Items/Handlers/CreateItem/CreateItemResponse.cs +++ b/Api/Features/Items/CreateItem/CreateItemResponse.cs @@ -1,4 +1,4 @@ -namespace Api.Features.Items.Handlers.CreateItem; +namespace Api.Features.Items.CreateItem; public class CreateItemResponse { diff --git a/Api/Features/Items/Handlers/GetAllItems/GetAllItemsHandler.cs b/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs similarity index 96% rename from Api/Features/Items/Handlers/GetAllItems/GetAllItemsHandler.cs rename to Api/Features/Items/GetAllItems/GetAllItemsHandler.cs index e83f443..8f80075 100644 --- a/Api/Features/Items/Handlers/GetAllItems/GetAllItemsHandler.cs +++ b/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -2,7 +2,7 @@ using Api.Responses; using Application.Queries; -namespace Api.Features.Items.Handlers.GetAllItems; +namespace Api.Features.Items.GetAllItems; public class GetAllItemsHandler { diff --git a/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapper.cs b/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs similarity index 92% rename from Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapper.cs rename to Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs index 386011c..546c914 100644 --- a/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapper.cs +++ b/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs @@ -1,6 +1,6 @@ using Api.EnternalDeps.EmployeesApi.Responses; -namespace Api.Features.Items.Handlers.GetAllItems; +namespace Api.Features.Items.GetAllItems; public class HolderEmployeeMapper { diff --git a/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapperTests.cs b/Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs similarity index 92% rename from Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapperTests.cs rename to Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs index 7f02ef1..9ee567b 100644 --- a/Api/Features/Items/Handlers/GetAllItems/HolderEmployeeMapperTests.cs +++ b/Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs @@ -1,7 +1,7 @@ using Api.EnternalDeps.EmployeesApi.Responses; using Xunit; -namespace Api.Features.Items.Handlers.GetAllItems; +namespace Api.Features.Items.GetAllItems; public class HolderEmployeeMapperTests { diff --git a/Api/Features/Items/Handlers/GetAllItems/ItemsResponse.cs b/Api/Features/Items/GetAllItems/ItemsResponse.cs similarity index 93% rename from Api/Features/Items/Handlers/GetAllItems/ItemsResponse.cs rename to Api/Features/Items/GetAllItems/ItemsResponse.cs index b0d6023..48763f2 100644 --- a/Api/Features/Items/Handlers/GetAllItems/ItemsResponse.cs +++ b/Api/Features/Items/GetAllItems/ItemsResponse.cs @@ -1,6 +1,6 @@ using Api.Responses; -namespace Api.Features.Items.Handlers.GetAllItems; +namespace Api.Features.Items.GetAllItems; public class ItemsResponse { diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index a80201b..905ec69 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -using Api.Features.Items.Handlers.CreateItem; -using Api.Features.Items.Handlers.GetAllItems; +using Api.Features.Items.CreateItem; +using Api.Features.Items.GetAllItems; using Application.Commands; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; From 956958f149e1f11d98913ee37b1a79f5367b7078 Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Wed, 26 Nov 2025 17:55:59 +0500 Subject: [PATCH 08/61] fix!: rename ItemsResponse to GetAllItemsResponse to sync with the rest of naming convention --- Api/Features/Items/GetAllItems/GetAllItemsHandler.cs | 4 ++-- .../GetAllItems/{ItemsResponse.cs => GetAllItemsResponse.cs} | 2 +- Api/Features/Items/ItemsController.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename Api/Features/Items/GetAllItems/{ItemsResponse.cs => GetAllItemsResponse.cs} (95%) diff --git a/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs index 8f80075..f175317 100644 --- a/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -18,13 +18,13 @@ EmployeesApi employeesApi _employeesApi = employeesApi; } - public async Task HandleAsync() + public async Task HandleAsync() { var items = await _allItemsQuery.GetAsync(); var allEmployeesResponse = await _employeesApi.GetAllEmployeesAsync(); - return new ItemsResponse + return new GetAllItemsResponse { Items = items .Select(x => new ItemDto diff --git a/Api/Features/Items/GetAllItems/ItemsResponse.cs b/Api/Features/Items/GetAllItems/GetAllItemsResponse.cs similarity index 95% rename from Api/Features/Items/GetAllItems/ItemsResponse.cs rename to Api/Features/Items/GetAllItems/GetAllItemsResponse.cs index 48763f2..207971d 100644 --- a/Api/Features/Items/GetAllItems/ItemsResponse.cs +++ b/Api/Features/Items/GetAllItems/GetAllItemsResponse.cs @@ -2,7 +2,7 @@ namespace Api.Features.Items.GetAllItems; -public class ItemsResponse +public class GetAllItemsResponse { public required List Items { get; set; } } diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index 905ec69..df2235c 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -18,7 +18,7 @@ public class ItemsController : ControllerBase /// [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] - public Task GetAllItemsAsync( + public Task GetAllItemsAsync( [FromServices] GetAllItemsHandler getAllItemsHandler ) { From 388e95f82aefa0b9939338a8bf9c10afc98ef859 Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Wed, 26 Nov 2025 19:07:41 +0500 Subject: [PATCH 09/61] format: fail lint when namespaces aren't in sync with folder names --- .editorconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.editorconfig b/.editorconfig index 4701ee2..b664d32 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,6 +4,13 @@ root = true # C# files [*.cs] +# this should be causing namespace missmatch to fail the linting workflow and it does +# however, auto fix of formatting accoring to this rule is broken since 2022 :( +# thus, it is validated but needs manual fix as for now +# https://github.com/dotnet/format/issues/1623 +dotnet_style_namespace_match_folder = true:warning +dotnet_diagnostic.IDE0130.severity = warning + #### Core EditorConfig Options #### # Indentation and spacing From e4a243b9983a763b41e93941b4bc1de55b5cb881 Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Wed, 26 Nov 2025 19:08:23 +0500 Subject: [PATCH 10/61] refactor: fix EnternalDeps typo to ExternalDeps --- Api/DependencyInjection.cs | 2 +- .../EmployeesApi/EmployeesApi.cs | 4 ++-- .../EmployeesApi/Responses/EmployeesResponse.cs | 2 +- Api/{EnternalDeps => ExternalDeps}/ExternalDepsUrls.cs | 0 Api/Features/Items/GetAllItems/GetAllItemsHandler.cs | 2 +- Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs | 2 +- Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) rename Api/{EnternalDeps => ExternalDeps}/EmployeesApi/EmployeesApi.cs (94%) rename Api/{EnternalDeps => ExternalDeps}/EmployeesApi/Responses/EmployeesResponse.cs (86%) rename Api/{EnternalDeps => ExternalDeps}/ExternalDepsUrls.cs (100%) diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 8dd71a4..771e2e8 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -1,4 +1,4 @@ -using Api.EnternalDeps.EmployeesApi; +using Api.ExternalDeps.EmployeesApi; using Api.Features.Items.CreateItem; using Api.Features.Items.GetAllItems; using Application; diff --git a/Api/EnternalDeps/EmployeesApi/EmployeesApi.cs b/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs similarity index 94% rename from Api/EnternalDeps/EmployeesApi/EmployeesApi.cs rename to Api/ExternalDeps/EmployeesApi/EmployeesApi.cs index 7036fff..ad8b306 100644 --- a/Api/EnternalDeps/EmployeesApi/EmployeesApi.cs +++ b/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs @@ -1,8 +1,8 @@ -using Api.EnternalDeps.EmployeesApi.Responses; +using Api.ExternalDeps.EmployeesApi.Responses; using Microsoft.Extensions.Options; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Options; -namespace Api.EnternalDeps.EmployeesApi; +namespace Api.ExternalDeps.EmployeesApi; public class EmployeesApi { diff --git a/Api/EnternalDeps/EmployeesApi/Responses/EmployeesResponse.cs b/Api/ExternalDeps/EmployeesApi/Responses/EmployeesResponse.cs similarity index 86% rename from Api/EnternalDeps/EmployeesApi/Responses/EmployeesResponse.cs rename to Api/ExternalDeps/EmployeesApi/Responses/EmployeesResponse.cs index e4c693c..411123a 100644 --- a/Api/EnternalDeps/EmployeesApi/Responses/EmployeesResponse.cs +++ b/Api/ExternalDeps/EmployeesApi/Responses/EmployeesResponse.cs @@ -1,4 +1,4 @@ -namespace Api.EnternalDeps.EmployeesApi.Responses; +namespace Api.ExternalDeps.EmployeesApi.Responses; public class EmployeesResponse { diff --git a/Api/EnternalDeps/ExternalDepsUrls.cs b/Api/ExternalDeps/ExternalDepsUrls.cs similarity index 100% rename from Api/EnternalDeps/ExternalDepsUrls.cs rename to Api/ExternalDeps/ExternalDepsUrls.cs diff --git a/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs index f175317..4d20ba4 100644 --- a/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -1,4 +1,4 @@ -using Api.EnternalDeps.EmployeesApi; +using Api.ExternalDeps.EmployeesApi; using Api.Responses; using Application.Queries; diff --git a/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs b/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs index 546c914..0c3eb12 100644 --- a/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs +++ b/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs @@ -1,4 +1,4 @@ -using Api.EnternalDeps.EmployeesApi.Responses; +using Api.ExternalDeps.EmployeesApi.Responses; namespace Api.Features.Items.GetAllItems; diff --git a/Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs b/Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs index 9ee567b..af563f9 100644 --- a/Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs +++ b/Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs @@ -1,4 +1,4 @@ -using Api.EnternalDeps.EmployeesApi.Responses; +using Api.ExternalDeps.EmployeesApi.Responses; using Xunit; namespace Api.Features.Items.GetAllItems; From e14e045df60f425ce28d79dc9cd412fd2fb174c7 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Thu, 27 Nov 2025 11:16:13 +0500 Subject: [PATCH 11/61] chore: change AddScoped to AddTransient --- Api/DependencyInjection.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 771e2e8..ecd0766 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -39,7 +39,7 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); services.AddTransient(); - services.AddScoped(); - services.AddScoped(); + services.AddTransient(); + services.AddTransient(); } } From bb7e07a75989dfd95d5b8ec153fa7dd92e957195 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Thu, 27 Nov 2025 11:44:52 +0500 Subject: [PATCH 12/61] feat: new proposal for api reorganization --- .../Items => Controllers}/ItemsController.cs | 16 +++-- Api/DependencyInjection.cs | 5 +- Api/ExternalDeps/EmployeesApi/EmployeesApi.cs | 2 +- .../Items/CreateItem/CreateItemHandler.cs | 34 --------- .../Items/GetAllItems/HolderEmployeeMapper.cs | 22 ------ Api/Responses/ItemTypesResponse.cs | 4 +- Application/Commands/CreateItemCommand.cs | 69 ------------------- .../EmployeesApi}/EmployeesResponse.cs | 2 +- .../Features/Dtos}/ItemTypeDto.cs | 2 +- .../Items/CreateItem/CreateItemHandler.cs | 54 +++++++++++++++ .../Items/CreateItem/CreateItemRequest.cs | 2 +- .../Items/CreateItem/CreateItemResponse.cs | 2 +- .../Items/GetAllItems/GetAllItemsHandler.cs | 28 +++++--- .../GetAllItems/GetAllItemsHandlerTests.cs | 0 .../Items/GetAllItems/GetAllItemsResponse.cs | 4 +- 15 files changed, 92 insertions(+), 154 deletions(-) rename Api/{Features/Items => Controllers}/ItemsController.cs (74%) delete mode 100644 Api/Features/Items/CreateItem/CreateItemHandler.cs delete mode 100644 Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs delete mode 100644 Application/Commands/CreateItemCommand.cs rename {Api/ExternalDeps/EmployeesApi/Responses => Application/ExternalDeps/EmployeesApi}/EmployeesResponse.cs (86%) rename {Api/Responses => Application/Features/Dtos}/ItemTypeDto.cs (74%) create mode 100644 Application/Features/Items/CreateItem/CreateItemHandler.cs rename {Api => Application}/Features/Items/CreateItem/CreateItemRequest.cs (91%) rename {Api => Application}/Features/Items/CreateItem/CreateItemResponse.cs (63%) rename {Api => Application}/Features/Items/GetAllItems/GetAllItemsHandler.cs (51%) rename Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs => Application/Features/Items/GetAllItems/GetAllItemsHandlerTests.cs (100%) rename {Api => Application}/Features/Items/GetAllItems/GetAllItemsResponse.cs (90%) diff --git a/Api/Features/Items/ItemsController.cs b/Api/Controllers/ItemsController.cs similarity index 74% rename from Api/Features/Items/ItemsController.cs rename to Api/Controllers/ItemsController.cs index df2235c..e83ee1d 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Controllers/ItemsController.cs @@ -1,12 +1,13 @@ using System.ComponentModel.DataAnnotations; -using Api.Features.Items.CreateItem; -using Api.Features.Items.GetAllItems; +using Api.ExternalDeps.EmployeesApi; using Application.Commands; +using Application.Features.Items.CreateItem; +using Application.Features.Items.GetAllItems; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Filters; -namespace Api.Features.Items; +namespace Api.Controllers; [Authorize] [ApiController] @@ -18,11 +19,14 @@ public class ItemsController : ControllerBase /// [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] - public Task GetAllItemsAsync( - [FromServices] GetAllItemsHandler getAllItemsHandler + public async Task GetAllItemsAsync( + [FromServices] GetAllItemsHandler getAllItemsHandler, + [FromServices] EmployeesApi employeesApi ) { - return getAllItemsHandler.HandleAsync(); + var allEmployeesResponse = await employeesApi.GetAllEmployeesAsync(); + + return await getAllItemsHandler.HandleAsync(allEmployeesResponse); } /// diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index ecd0766..9509072 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -1,8 +1,8 @@ using Api.ExternalDeps.EmployeesApi; -using Api.Features.Items.CreateItem; -using Api.Features.Items.GetAllItems; using Application; using Application.Commands; +using Application.Features.Items.CreateItem; +using Application.Features.Items.GetAllItems; using Application.Queries; using Microsoft.EntityFrameworkCore; @@ -35,7 +35,6 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs b/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs index ad8b306..65d2efe 100644 --- a/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs +++ b/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs @@ -1,4 +1,4 @@ -using Api.ExternalDeps.EmployeesApi.Responses; +using Application.ExternalDeps.EmployeesApi; using Microsoft.Extensions.Options; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Options; diff --git a/Api/Features/Items/CreateItem/CreateItemHandler.cs b/Api/Features/Items/CreateItem/CreateItemHandler.cs deleted file mode 100644 index 6246b54..0000000 --- a/Api/Features/Items/CreateItem/CreateItemHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Application.Commands; - -namespace Api.Features.Items.CreateItem; - -public class CreateItemHandler -{ - private readonly CreateItemCommand _createItemCommand; - - public CreateItemHandler(CreateItemCommand createItemCommand) - { - _createItemCommand = createItemCommand; - } - - public async Task HandleAsync(CreateItemRequest createItemRequest) - { - var createItemCommandParams = new CreateItemCommandParams - { - Name = createItemRequest.Name, - SerialNumber = createItemRequest.SerialNumber, - ItemTypeId = createItemRequest.ItemTypeId, - Price = createItemRequest.Price, - Description = createItemRequest.Description, - PurchaseDate = createItemRequest.PurchaseDate, - HolderEmployeeId = createItemRequest.HolderEmployeeId - }; - - var newItemId = await _createItemCommand.ExecuteAsync(createItemCommandParams); - - return new CreateItemResponse() - { - NewItemId = newItemId - }; - } -} diff --git a/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs b/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs deleted file mode 100644 index 0c3eb12..0000000 --- a/Api/Features/Items/GetAllItems/HolderEmployeeMapper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Api.ExternalDeps.EmployeesApi.Responses; - -namespace Api.Features.Items.GetAllItems; - -public class HolderEmployeeMapper -{ - public const string NotFoundEmployeeFullName = "Not Found"; - - public static EmployeeDto? MapToEmployeeDto(long? holderEmployeeId, EmployeesResponse employeesResponse) - { - return holderEmployeeId == null - ? null - : new EmployeeDto - { - Id = holderEmployeeId.Value, - FullName = employeesResponse - .Employees - .SingleOrDefault(y => y.Id == holderEmployeeId.Value) - ?.FullName ?? NotFoundEmployeeFullName - }; - } -} diff --git a/Api/Responses/ItemTypesResponse.cs b/Api/Responses/ItemTypesResponse.cs index e4389bf..da88bdd 100644 --- a/Api/Responses/ItemTypesResponse.cs +++ b/Api/Responses/ItemTypesResponse.cs @@ -1,4 +1,6 @@ -namespace Api.Responses; +using Application.Features.Dtos; + +namespace Api.Responses; public class ItemTypesResponse { diff --git a/Application/Commands/CreateItemCommand.cs b/Application/Commands/CreateItemCommand.cs deleted file mode 100644 index 91ba52e..0000000 --- a/Application/Commands/CreateItemCommand.cs +++ /dev/null @@ -1,69 +0,0 @@ - -using Core.Entities; -using Microsoft.EntityFrameworkCore; - -namespace Application.Commands; - -public class CreateItemCommandParams -{ - public required string Name { get; set; } - - public required string SerialNumber { get; set; } - - public required long ItemTypeId { get; set; } - - public required decimal Price { get; set; } - - public required string Description { get; set; } - - public required DateOnly? PurchaseDate { get; set; } - - public required long? HolderEmployeeId { get; set; } -} - -public class CreateItemCommand -{ - private readonly TenantAppDbContext _context; - private readonly IClaimsProvider _claimsProvider; - - public CreateItemCommand( - TenantAppDbContext context, - IClaimsProvider claimsProvider - ) - { - _context = context; - _claimsProvider = claimsProvider; - } - - public async Task ExecuteAsync(CreateItemCommandParams createItemCommandParams) - { - var itemTypeIdDoesNotExistWithinTenant = await _context - .QueryableWithinTenant() - .AllAsync(x => x.Id != createItemCommandParams.ItemTypeId); - - if (itemTypeIdDoesNotExistWithinTenant) - { - throw new Exception($"Passed item type where id={createItemCommandParams.ItemTypeId} is not found within tenant where id={_claimsProvider.TenantId}"); - } - - var item = new Item - { - TenantId = _claimsProvider.TenantId, - Name = createItemCommandParams.Name, - SerialNumber = createItemCommandParams.SerialNumber, - ItemTypeId = createItemCommandParams.ItemTypeId, - Price = createItemCommandParams.Price, - Description = createItemCommandParams.Description, - PurchaseDate = createItemCommandParams.PurchaseDate, - HolderEmployeeId = createItemCommandParams.HolderEmployeeId - }; - - await _context - .Items - .AddAsync(item); - - await _context.SaveChangesAsync(); - - return item.Id; - } -} diff --git a/Api/ExternalDeps/EmployeesApi/Responses/EmployeesResponse.cs b/Application/ExternalDeps/EmployeesApi/EmployeesResponse.cs similarity index 86% rename from Api/ExternalDeps/EmployeesApi/Responses/EmployeesResponse.cs rename to Application/ExternalDeps/EmployeesApi/EmployeesResponse.cs index 411123a..fe9b1e8 100644 --- a/Api/ExternalDeps/EmployeesApi/Responses/EmployeesResponse.cs +++ b/Application/ExternalDeps/EmployeesApi/EmployeesResponse.cs @@ -1,4 +1,4 @@ -namespace Api.ExternalDeps.EmployeesApi.Responses; +namespace Application.ExternalDeps.EmployeesApi; public class EmployeesResponse { diff --git a/Api/Responses/ItemTypeDto.cs b/Application/Features/Dtos/ItemTypeDto.cs similarity index 74% rename from Api/Responses/ItemTypeDto.cs rename to Application/Features/Dtos/ItemTypeDto.cs index e5729e4..661277c 100644 --- a/Api/Responses/ItemTypeDto.cs +++ b/Application/Features/Dtos/ItemTypeDto.cs @@ -1,4 +1,4 @@ -namespace Api.Responses; +namespace Application.Features.Dtos; public class ItemTypeDto { diff --git a/Application/Features/Items/CreateItem/CreateItemHandler.cs b/Application/Features/Items/CreateItem/CreateItemHandler.cs new file mode 100644 index 0000000..972e724 --- /dev/null +++ b/Application/Features/Items/CreateItem/CreateItemHandler.cs @@ -0,0 +1,54 @@ +using Core.Entities; +using Microsoft.EntityFrameworkCore; + +namespace Application.Features.Items.CreateItem; + +public class CreateItemHandler +{ + private readonly TenantAppDbContext _context; + private readonly IClaimsProvider _claimsProvider; + + public CreateItemHandler( + TenantAppDbContext context, + IClaimsProvider claimsProvider + ) + { + _context = context; + _claimsProvider = claimsProvider; + } + + public async Task HandleAsync(CreateItemRequest createItemRequest) + { + var itemTypeIdDoesNotExistWithinTenant = await _context + .QueryableWithinTenant() + .AllAsync(x => x.Id != createItemRequest.ItemTypeId); + + if (itemTypeIdDoesNotExistWithinTenant) + { + throw new Exception($"Passed item type where id={createItemRequest.ItemTypeId} is not found within tenant where id={_claimsProvider.TenantId}"); + } + + var item = new Item + { + TenantId = _claimsProvider.TenantId, + Name = createItemRequest.Name, + SerialNumber = createItemRequest.SerialNumber, + ItemTypeId = createItemRequest.ItemTypeId, + Price = createItemRequest.Price, + Description = createItemRequest.Description, + PurchaseDate = createItemRequest.PurchaseDate, + HolderEmployeeId = createItemRequest.HolderEmployeeId + }; + + await _context + .Items + .AddAsync(item); + + await _context.SaveChangesAsync(); + + return new CreateItemResponse() + { + NewItemId = item.Id + }; + } +} diff --git a/Api/Features/Items/CreateItem/CreateItemRequest.cs b/Application/Features/Items/CreateItem/CreateItemRequest.cs similarity index 91% rename from Api/Features/Items/CreateItem/CreateItemRequest.cs rename to Application/Features/Items/CreateItem/CreateItemRequest.cs index bebc464..278a963 100644 --- a/Api/Features/Items/CreateItem/CreateItemRequest.cs +++ b/Application/Features/Items/CreateItem/CreateItemRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Api.Features.Items.CreateItem; +namespace Application.Features.Items.CreateItem; public class CreateItemRequest { diff --git a/Api/Features/Items/CreateItem/CreateItemResponse.cs b/Application/Features/Items/CreateItem/CreateItemResponse.cs similarity index 63% rename from Api/Features/Items/CreateItem/CreateItemResponse.cs rename to Application/Features/Items/CreateItem/CreateItemResponse.cs index 40467ea..0ef53b9 100644 --- a/Api/Features/Items/CreateItem/CreateItemResponse.cs +++ b/Application/Features/Items/CreateItem/CreateItemResponse.cs @@ -1,4 +1,4 @@ -namespace Api.Features.Items.CreateItem; +namespace Application.Features.Items.CreateItem; public class CreateItemResponse { diff --git a/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs similarity index 51% rename from Api/Features/Items/GetAllItems/GetAllItemsHandler.cs rename to Application/Features/Items/GetAllItems/GetAllItemsHandler.cs index 4d20ba4..54e4824 100644 --- a/Api/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -1,29 +1,26 @@ -using Api.ExternalDeps.EmployeesApi; -using Api.Responses; +using Application.ExternalDeps.EmployeesApi; +using Application.Features.Dtos; using Application.Queries; -namespace Api.Features.Items.GetAllItems; +namespace Application.Features.Items.GetAllItems; public class GetAllItemsHandler { private readonly AllItemsQuery _allItemsQuery; - private readonly EmployeesApi _employeesApi; + + public const string NotFoundEmployeeFullName = "Not Found"; public GetAllItemsHandler( - AllItemsQuery allItemsQuery, - EmployeesApi employeesApi + AllItemsQuery allItemsQuery ) { _allItemsQuery = allItemsQuery; - _employeesApi = employeesApi; } - public async Task HandleAsync() + public async Task HandleAsync(EmployeesResponse allEmployeesResponse) { var items = await _allItemsQuery.GetAsync(); - var allEmployeesResponse = await _employeesApi.GetAllEmployeesAsync(); - return new GetAllItemsResponse { Items = items @@ -40,7 +37,16 @@ public async Task HandleAsync() Price = x.Price, Description = x.Description, PurchaseDate = x.PurchaseDate, - HolderEmployee = HolderEmployeeMapper.MapToEmployeeDto(x.HolderEmployeeId, allEmployeesResponse) + HolderEmployee = x.HolderEmployeeId == null + ? null + : new EmployeeDto + { + Id = x.HolderEmployeeId.Value, + FullName = allEmployeesResponse + .Employees + .SingleOrDefault(y => y.Id == x.HolderEmployeeId.Value) + ?.FullName ?? NotFoundEmployeeFullName + } }) .ToList() }; diff --git a/Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandlerTests.cs similarity index 100% rename from Api/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs rename to Application/Features/Items/GetAllItems/GetAllItemsHandlerTests.cs diff --git a/Api/Features/Items/GetAllItems/GetAllItemsResponse.cs b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs similarity index 90% rename from Api/Features/Items/GetAllItems/GetAllItemsResponse.cs rename to Application/Features/Items/GetAllItems/GetAllItemsResponse.cs index 207971d..b9d50c2 100644 --- a/Api/Features/Items/GetAllItems/GetAllItemsResponse.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs @@ -1,6 +1,4 @@ -using Api.Responses; - -namespace Api.Features.Items.GetAllItems; +namespace Application.Features.Items.GetAllItems; public class GetAllItemsResponse { From 12ae07a32d72e4d45ad99bde05e59baf1ac6edb4 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Thu, 27 Nov 2025 17:16:43 +0500 Subject: [PATCH 13/61] chore: add using --- Application/Features/Items/GetAllItems/GetAllItemsResponse.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs index b9d50c2..4f643ea 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs @@ -1,4 +1,6 @@ -namespace Application.Features.Items.GetAllItems; +using Application.Features.Dtos; + +namespace Application.Features.Items.GetAllItems; public class GetAllItemsResponse { From dc426d768d99412350f75dd763899468f862dd99 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Thu, 27 Nov 2025 17:23:29 +0500 Subject: [PATCH 14/61] test: remove test --- .../GetAllItems/GetAllItemsHandlerTests.cs | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 Application/Features/Items/GetAllItems/GetAllItemsHandlerTests.cs diff --git a/Application/Features/Items/GetAllItems/GetAllItemsHandlerTests.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandlerTests.cs deleted file mode 100644 index af563f9..0000000 --- a/Application/Features/Items/GetAllItems/GetAllItemsHandlerTests.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Api.ExternalDeps.EmployeesApi.Responses; -using Xunit; - -namespace Api.Features.Items.GetAllItems; - -public class HolderEmployeeMapperTests -{ - [Fact] - public void MapNonExistentEmployee_ShouldUseNotFoundAsFullName() - { - var empltyEmployeesResponse = new EmployeesResponse - { - Employees = new List() - }; - - var employeeId = 5; - - var mappedHolderEmployeeDto = HolderEmployeeMapper.MapToEmployeeDto(employeeId, empltyEmployeesResponse); - - Assert.Equal(employeeId, mappedHolderEmployeeDto!.Id); - Assert.Equal(HolderEmployeeMapper.NotFoundEmployeeFullName, mappedHolderEmployeeDto.FullName); - } -} From 656782d3eee7d007ad0f27d6eb610448871a6ee0 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Thu, 27 Nov 2025 17:26:03 +0500 Subject: [PATCH 15/61] chore: add using --- Api/Controllers/ItemTypesController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Api/Controllers/ItemTypesController.cs b/Api/Controllers/ItemTypesController.cs index 5c86dba..acb2f3e 100644 --- a/Api/Controllers/ItemTypesController.cs +++ b/Api/Controllers/ItemTypesController.cs @@ -2,6 +2,7 @@ using Api.Requests; using Api.Responses; using Application.Commands; +using Application.Features.Dtos; using Application.Queries; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; From 126f94edc98863ac2beab3c15805b0cac442d400 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Thu, 27 Nov 2025 12:28:24 +0000 Subject: [PATCH 16/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index af5bae1..28afcd9 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-82.22%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.34%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.96%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-82.47%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-15.80%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-89.59%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From 0f4d5926401716aff22c45e5c8703b8aeb086c7d Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 19 Jan 2026 14:01:25 +0500 Subject: [PATCH 17/61] feat: return HolderEmployeeMapper --- .../Items/GetAllItems/GetAllItemsHandler.cs | 11 +-------- .../Items/GetAllItems/HolderEmployeeMapper.cs | 22 ++++++++++++++++++ .../GetAllItems/HolderEmployeeMapperTests.cs | 23 +++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs create mode 100644 Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs diff --git a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs index 54e4824..53d8828 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -37,16 +37,7 @@ public async Task HandleAsync(EmployeesResponse allEmployee Price = x.Price, Description = x.Description, PurchaseDate = x.PurchaseDate, - HolderEmployee = x.HolderEmployeeId == null - ? null - : new EmployeeDto - { - Id = x.HolderEmployeeId.Value, - FullName = allEmployeesResponse - .Employees - .SingleOrDefault(y => y.Id == x.HolderEmployeeId.Value) - ?.FullName ?? NotFoundEmployeeFullName - } + HolderEmployee = HolderEmployeeMapper.MapToEmployeeDto(x.HolderEmployeeId, allEmployeesResponse) }) .ToList() }; diff --git a/Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs b/Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs new file mode 100644 index 0000000..e63fe72 --- /dev/null +++ b/Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs @@ -0,0 +1,22 @@ +using Application.ExternalDeps.EmployeesApi; + +namespace Application.Features.Items.GetAllItems; + +public class HolderEmployeeMapper +{ + public const string NotFoundEmployeeFullName = "Not Found"; + + public static EmployeeDto? MapToEmployeeDto(long? holderEmployeeId, EmployeesResponse employeesResponse) + { + return holderEmployeeId == null + ? null + : new EmployeeDto + { + Id = holderEmployeeId.Value, + FullName = employeesResponse + .Employees + .SingleOrDefault(y => y.Id == holderEmployeeId.Value) + ?.FullName ?? NotFoundEmployeeFullName + }; + } +} \ No newline at end of file diff --git a/Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs b/Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs new file mode 100644 index 0000000..65faa81 --- /dev/null +++ b/Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs @@ -0,0 +1,23 @@ +using Application.ExternalDeps.EmployeesApi; +using Xunit; + +namespace Application.Features.Items.GetAllItems; + +public class HolderEmployeeMapperTests +{ + [Fact] + public void MapNonExistentEmployee_ShouldUseNotFoundAsFullName() + { + var empltyEmployeesResponse = new EmployeesResponse + { + Employees = new List() + }; + + var employeeId = 5; + + var mappedHolderEmployeeDto = HolderEmployeeMapper.MapToEmployeeDto(employeeId, empltyEmployeesResponse); + + Assert.Equal(employeeId, mappedHolderEmployeeDto!.Id); + Assert.Equal(HolderEmployeeMapper.NotFoundEmployeeFullName, mappedHolderEmployeeDto.FullName); + } +} \ No newline at end of file From fb8162ae26ce0ec8b5c54e59c227b964fd598f56 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Mon, 19 Jan 2026 09:03:40 +0000 Subject: [PATCH 18/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 28afcd9..7de3ef5 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-82.47%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-15.80%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.59%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-81.77%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.78%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-89.71%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From b18305bf90a576bfb2969bdca41ea257a8136185 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 19 Jan 2026 14:10:46 +0500 Subject: [PATCH 19/61] fix: fix lint --- Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs | 2 +- .../Features/Items/GetAllItems/HolderEmployeeMapperTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs b/Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs index e63fe72..ccc4827 100644 --- a/Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs +++ b/Application/Features/Items/GetAllItems/HolderEmployeeMapper.cs @@ -19,4 +19,4 @@ public class HolderEmployeeMapper ?.FullName ?? NotFoundEmployeeFullName }; } -} \ No newline at end of file +} diff --git a/Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs b/Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs index 65faa81..2c7b68e 100644 --- a/Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs +++ b/Application/Features/Items/GetAllItems/HolderEmployeeMapperTests.cs @@ -20,4 +20,4 @@ public void MapNonExistentEmployee_ShouldUseNotFoundAsFullName() Assert.Equal(employeeId, mappedHolderEmployeeDto!.Id); Assert.Equal(HolderEmployeeMapper.NotFoundEmployeeFullName, mappedHolderEmployeeDto.FullName); } -} \ No newline at end of file +} From a4516f7df84f159fe4972c2a189f3ad269cf24cd Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Tue, 20 Jan 2026 17:18:33 +0500 Subject: [PATCH 20/61] fix: fix summary for swagger --- Api/Controllers/ItemTypesController.cs | 12 +++--------- Api/Controllers/ItemsController.cs | 12 +++--------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Api/Controllers/ItemTypesController.cs b/Api/Controllers/ItemTypesController.cs index acb2f3e..e40cab3 100644 --- a/Api/Controllers/ItemTypesController.cs +++ b/Api/Controllers/ItemTypesController.cs @@ -15,9 +15,7 @@ namespace Api.Controllers; [Route("api/item-types")] public class ItemTypesController : ControllerBase { - /// - /// Get all item types - /// + [EndpointSummary("Get all item types")] [RequiresPermission(UserClaimsProvider.CanViewItemsTypes)] [HttpGet] public async Task GetAllItemTypesAsync( @@ -38,9 +36,7 @@ [FromServices] AllItemTypesQuery allItemTypesQuery }; } - /// - /// Adds item type - /// + [EndpointSummary("Adds item type")] /// [RequiresPermission(UserClaimsProvider.CanManageItemsTypes)] [HttpPost] @@ -62,9 +58,7 @@ [Required][FromBody] CreateItemTypeRequest createItemTypeRequest }; } - /// - /// Deletes specific item type - /// + [EndpointSummary("Deletes specific item type")] /// [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemTypesHardDeleteAllowed)] [HttpDelete("{itemTypeId}/hard-delete")] diff --git a/Api/Controllers/ItemsController.cs b/Api/Controllers/ItemsController.cs index e83ee1d..abf1b7f 100644 --- a/Api/Controllers/ItemsController.cs +++ b/Api/Controllers/ItemsController.cs @@ -14,9 +14,7 @@ namespace Api.Controllers; [Route("api/items")] public class ItemsController : ControllerBase { - /// - /// Get all items - /// + [EndpointSummary("Get all items")] [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] public async Task GetAllItemsAsync( @@ -29,9 +27,7 @@ [FromServices] EmployeesApi employeesApi return await getAllItemsHandler.HandleAsync(allEmployeesResponse); } - /// - /// Add an item - /// + [EndpointSummary("Add an item")] /// [RequiresPermission(UserClaimsProvider.CanManageItems)] [HttpPost] @@ -43,9 +39,7 @@ [Required][FromBody] CreateItemRequest createItemRequest return createItemHandler.HandleAsync(createItemRequest); } - /// - /// Deletes specific item - /// + [EndpointSummary("Deletes specific item")] /// [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemsHardDeleteAllowed)] [HttpDelete("{itemId}/hard-delete")] From 3801c2b7f001457f71728f8eca52500e831562eb Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Tue, 20 Jan 2026 17:20:23 +0500 Subject: [PATCH 21/61] refactor: move CreateItemTypeRequest and CreateItemTypeResponse to Application --- Api/Controllers/ItemTypesController.cs | 10 ++-------- Application/Commands/CreateItemTypeCommand.cs | 12 ++++-------- .../Features/ItemTypes}/CreateItemTypeRequest.cs | 2 +- .../Features/ItemTypes}/CreateItemTypeResponse.cs | 2 +- .../Features/ItemTypes}/ItemTypesResponse.cs | 2 +- 5 files changed, 9 insertions(+), 19 deletions(-) rename {Api/Requests => Application/Features/ItemTypes}/CreateItemTypeRequest.cs (80%) rename {Api/Responses => Application/Features/ItemTypes}/CreateItemTypeResponse.cs (69%) rename {Api/Responses => Application/Features/ItemTypes}/ItemTypesResponse.cs (76%) diff --git a/Api/Controllers/ItemTypesController.cs b/Api/Controllers/ItemTypesController.cs index e40cab3..f38effb 100644 --- a/Api/Controllers/ItemTypesController.cs +++ b/Api/Controllers/ItemTypesController.cs @@ -1,8 +1,7 @@ using System.ComponentModel.DataAnnotations; -using Api.Requests; -using Api.Responses; using Application.Commands; using Application.Features.Dtos; +using Application.Features.ItemTypes; using Application.Queries; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -45,12 +44,7 @@ public async Task CreateItemTypeAsync( [Required][FromBody] CreateItemTypeRequest createItemTypeRequest ) { - var createItemTypeCommandParams = new CreateItemTypeCommandParams - { - Name = createItemTypeRequest.Name - }; - - var newItemTypeId = await createItemTypeCommand.ExecuteAsync(createItemTypeCommandParams); + var newItemTypeId = await createItemTypeCommand.ExecuteAsync(createItemTypeRequest); return new CreateItemTypeResponse() { diff --git a/Application/Commands/CreateItemTypeCommand.cs b/Application/Commands/CreateItemTypeCommand.cs index fbcf765..d6e1aac 100644 --- a/Application/Commands/CreateItemTypeCommand.cs +++ b/Application/Commands/CreateItemTypeCommand.cs @@ -1,12 +1,8 @@ -using Core.Entities; +using Application.Features.ItemTypes; +using Core.Entities; namespace Application.Commands; -public class CreateItemTypeCommandParams -{ - public required string Name { get; set; } -} - public class CreateItemTypeCommand { private readonly TenantAppDbContext _context; @@ -21,12 +17,12 @@ IClaimsProvider claimsProvider _claimsProvider = claimsProvider; } - public async Task ExecuteAsync(CreateItemTypeCommandParams createItemTypeCommandParams) + public async Task ExecuteAsync(CreateItemTypeRequest CreateItemTypeRequest) { var itemType = new ItemType { TenantId = _claimsProvider.TenantId, - Name = createItemTypeCommandParams.Name + Name = CreateItemTypeRequest.Name }; await _context diff --git a/Api/Requests/CreateItemTypeRequest.cs b/Application/Features/ItemTypes/CreateItemTypeRequest.cs similarity index 80% rename from Api/Requests/CreateItemTypeRequest.cs rename to Application/Features/ItemTypes/CreateItemTypeRequest.cs index 46643ba..669a968 100644 --- a/Api/Requests/CreateItemTypeRequest.cs +++ b/Application/Features/ItemTypes/CreateItemTypeRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Api.Requests; +namespace Application.Features.ItemTypes; public class CreateItemTypeRequest { diff --git a/Api/Responses/CreateItemTypeResponse.cs b/Application/Features/ItemTypes/CreateItemTypeResponse.cs similarity index 69% rename from Api/Responses/CreateItemTypeResponse.cs rename to Application/Features/ItemTypes/CreateItemTypeResponse.cs index 81ab6ca..010184a 100644 --- a/Api/Responses/CreateItemTypeResponse.cs +++ b/Application/Features/ItemTypes/CreateItemTypeResponse.cs @@ -1,4 +1,4 @@ -namespace Api.Responses; +namespace Application.Features.ItemTypes; public class CreateItemTypeResponse { diff --git a/Api/Responses/ItemTypesResponse.cs b/Application/Features/ItemTypes/ItemTypesResponse.cs similarity index 76% rename from Api/Responses/ItemTypesResponse.cs rename to Application/Features/ItemTypes/ItemTypesResponse.cs index da88bdd..b1f23b3 100644 --- a/Api/Responses/ItemTypesResponse.cs +++ b/Application/Features/ItemTypes/ItemTypesResponse.cs @@ -1,6 +1,6 @@ using Application.Features.Dtos; -namespace Api.Responses; +namespace Application.Features.ItemTypes; public class ItemTypesResponse { From f57a525b8472f5c466e9ae9cb90d6fa5947d639d Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 20 Jan 2026 12:22:48 +0000 Subject: [PATCH 22/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7de3ef5..b4cc094 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-81.77%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.78%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.71%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-81.69%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.86%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-89.66%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From 7070545e020da38527433708ad3d839e4de4bb4c Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Wed, 21 Jan 2026 16:40:23 +0500 Subject: [PATCH 23/61] test: add swagger attributes --- Api/Controllers/ItemsController.cs | 8 ++++++-- .../Items/GetAllItems/GetAllItemsResponse.cs | 20 ++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Api/Controllers/ItemsController.cs b/Api/Controllers/ItemsController.cs index abf1b7f..75093a9 100644 --- a/Api/Controllers/ItemsController.cs +++ b/Api/Controllers/ItemsController.cs @@ -1,3 +1,4 @@ +using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Api.ExternalDeps.EmployeesApi; using Application.Commands; @@ -11,10 +12,14 @@ namespace Api.Controllers; [Authorize] [ApiController] +[Tags("Tag 1")] // If not set, defaults to "Items" [Route("api/items")] public class ItemsController : ControllerBase { + [EndpointName("GetAllItems")] // For operationId [EndpointSummary("Get all items")] + [Tags("Tag 2")] + [EndpointDescription("This is a description.")] [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] public async Task GetAllItemsAsync( @@ -40,12 +45,11 @@ [Required][FromBody] CreateItemRequest createItemRequest } [EndpointSummary("Deletes specific item")] - /// [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemsHardDeleteAllowed)] [HttpDelete("{itemId}/hard-delete")] public async Task HardDeleteItemAsync( [FromServices] HardDeleteItemCommand hardDeleteItemCommand, - [Required][FromRoute] long itemId + [Required][FromRoute, Description("ID of the item to delete")] long itemId ) { return new diff --git a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs index 4f643ea..c4339d4 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs @@ -1,4 +1,6 @@ -using Application.Features.Dtos; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using Application.Features.Dtos; namespace Application.Features.Items.GetAllItems; @@ -9,26 +11,42 @@ public class GetAllItemsResponse public class ItemDto { + [Required] public required long Id { get; set; } + [MaxLength(128)] + [Description("Description for Name")] + [DefaultValue("DefaultName")] + [RegularExpression(@"^[a-zA-Z\s]+$", ErrorMessage = "Name can contain only letters and spaces.")] + [Required] public required string Name { get; set; } + [Required] public required string SerialNumber { get; set; } + [Required] public required ItemTypeDto ItemType { get; set; } + [Required] + [Range(1, 100)] //Set default 100 public required decimal Price { get; set; } + [Required] public required string Description { get; set; } + [Required] public required DateOnly? PurchaseDate { get; set; } + [Required] public required EmployeeDto? HolderEmployee { get; set; } } public class EmployeeDto { + [Required] public required long Id { get; set; } + [MaxLength(128)] + [Required] public required string FullName { get; set; } } From 7594cbc61bba3962bd0c82e23a3dd8a4d7480a43 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Thu, 22 Jan 2026 09:57:51 +0000 Subject: [PATCH 24/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/js-client/index.ts b/js-client/index.ts index 89c49e1..e121354 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -45,16 +45,31 @@ export interface CreateItemTypeResponse { export type EmployeeDto = { /** @format int64 */ id: number; + /** @maxLength 128 */ fullName: string; } | null; +export interface GetAllItemsResponse { + items: ItemDto[]; +} + export interface ItemDto { /** @format int64 */ id: number; + /** + * Description for Name + * @maxLength 128 + * @default "DefaultName" + * @pattern ^[a-zA-Z\s]+$ + */ name: string; serialNumber: string; itemType: ItemTypeDto; - /** @format double */ + /** + * @format double + * @min 1 + * @max 100 + */ price: number; description: string; /** @format date */ @@ -62,10 +77,6 @@ export interface ItemDto { holderEmployee: EmployeeDto; } -export interface ItemsResponse { - items: ItemDto[]; -} - export interface ItemTypeDto { /** @format int64 */ id: number; @@ -261,14 +272,15 @@ export class Api< > extends HttpClient { api = { /** - * No description + * @description This is a description. * - * @tags Items + * @tags Tag 2 * @name ItemsGetAllItems + * @summary Get all items * @request GET:/api/items */ itemsGetAllItems: (params: RequestParams = {}) => - this.request({ + this.request({ path: `/api/items`, method: "GET", format: "json", @@ -278,8 +290,9 @@ export class Api< /** * No description * - * @tags Items + * @tags Tag 1 * @name ItemsCreateItem + * @summary Add an item * @request POST:/api/items */ itemsCreateItem: (data: CreateItemRequest, params: RequestParams = {}) => @@ -295,8 +308,9 @@ export class Api< /** * No description * - * @tags Items + * @tags Tag 1 * @name ItemsHardDeleteItem + * @summary Deletes specific item * @request DELETE:/api/items/{itemId}/hard-delete */ itemsHardDeleteItem: (itemId: number, params: RequestParams = {}) => @@ -311,6 +325,7 @@ export class Api< * * @tags ItemTypes * @name ItemTypesGetAllItemTypes + * @summary Get all item types * @request GET:/api/item-types */ itemTypesGetAllItemTypes: (params: RequestParams = {}) => @@ -326,6 +341,7 @@ export class Api< * * @tags ItemTypes * @name ItemTypesCreateItemType + * @summary Adds item type * @request POST:/api/item-types */ itemTypesCreateItemType: ( @@ -346,6 +362,7 @@ export class Api< * * @tags ItemTypes * @name ItemTypesHardDeleteItemType + * @summary Deletes specific item type * @request DELETE:/api/item-types/{itemTypeId}/hard-delete */ itemTypesHardDeleteItemType: ( From 5ef8a363200699996f90b5089b7015bcb961c270 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Thu, 22 Jan 2026 09:58:16 +0000 Subject: [PATCH 25/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b4cc094..df17669 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-81.69%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.86%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.66%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-81.92%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.64%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-89.79%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From 5811d492405597d59b4484ab0fdf4f4e06671bea Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Mon, 9 Feb 2026 09:14:33 +0000 Subject: [PATCH 26/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js-client/index.ts b/js-client/index.ts index 89c49e1..55521ac 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -48,6 +48,10 @@ export type EmployeeDto = { fullName: string; } | null; +export interface GetAllItemsResponse { + items: ItemDto[]; +} + export interface ItemDto { /** @format int64 */ id: number; @@ -62,10 +66,6 @@ export interface ItemDto { holderEmployee: EmployeeDto; } -export interface ItemsResponse { - items: ItemDto[]; -} - export interface ItemTypeDto { /** @format int64 */ id: number; @@ -268,7 +268,7 @@ export class Api< * @request GET:/api/items */ itemsGetAllItems: (params: RequestParams = {}) => - this.request({ + this.request({ path: `/api/items`, method: "GET", format: "json", From e128af072633fa43775f14d54031abd7756982d3 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Mon, 9 Feb 2026 09:15:24 +0000 Subject: [PATCH 27/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b965451..b9e9f65 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-82.12%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.43%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.91%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-82.43%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.13%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-90.09%25-forestgreen)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From 1165a09394cd135acdf9c481c8a555ea726bb4fb Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 9 Feb 2026 17:35:21 +0500 Subject: [PATCH 28/61] chore: delete new swagger attributes --- Api/Controllers/ItemsController.cs | 7 ++----- .../Items/GetAllItems/GetAllItemsResponse.cs | 20 +------------------ 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/Api/Controllers/ItemsController.cs b/Api/Controllers/ItemsController.cs index 75093a9..3d46d93 100644 --- a/Api/Controllers/ItemsController.cs +++ b/Api/Controllers/ItemsController.cs @@ -12,14 +12,10 @@ namespace Api.Controllers; [Authorize] [ApiController] -[Tags("Tag 1")] // If not set, defaults to "Items" [Route("api/items")] public class ItemsController : ControllerBase { - [EndpointName("GetAllItems")] // For operationId [EndpointSummary("Get all items")] - [Tags("Tag 2")] - [EndpointDescription("This is a description.")] [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] public async Task GetAllItemsAsync( @@ -45,11 +41,12 @@ [Required][FromBody] CreateItemRequest createItemRequest } [EndpointSummary("Deletes specific item")] + /// [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemsHardDeleteAllowed)] [HttpDelete("{itemId}/hard-delete")] public async Task HardDeleteItemAsync( [FromServices] HardDeleteItemCommand hardDeleteItemCommand, - [Required][FromRoute, Description("ID of the item to delete")] long itemId + [Required][FromRoute] long itemId ) { return new diff --git a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs index c4339d4..4f643ea 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs @@ -1,6 +1,4 @@ -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; -using Application.Features.Dtos; +using Application.Features.Dtos; namespace Application.Features.Items.GetAllItems; @@ -11,42 +9,26 @@ public class GetAllItemsResponse public class ItemDto { - [Required] public required long Id { get; set; } - [MaxLength(128)] - [Description("Description for Name")] - [DefaultValue("DefaultName")] - [RegularExpression(@"^[a-zA-Z\s]+$", ErrorMessage = "Name can contain only letters and spaces.")] - [Required] public required string Name { get; set; } - [Required] public required string SerialNumber { get; set; } - [Required] public required ItemTypeDto ItemType { get; set; } - [Required] - [Range(1, 100)] //Set default 100 public required decimal Price { get; set; } - [Required] public required string Description { get; set; } - [Required] public required DateOnly? PurchaseDate { get; set; } - [Required] public required EmployeeDto? HolderEmployee { get; set; } } public class EmployeeDto { - [Required] public required long Id { get; set; } - [MaxLength(128)] - [Required] public required string FullName { get; set; } } From 23c4cdbe65878983786125008c298c8a0db0b540 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 9 Feb 2026 17:49:40 +0500 Subject: [PATCH 29/61] chore: return new swagger XML comments --- Api/Controllers/ItemTypesController.cs | 12 +++++++++--- Api/Controllers/ItemsController.cs | 14 ++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Api/Controllers/ItemTypesController.cs b/Api/Controllers/ItemTypesController.cs index f38effb..b99aecf 100644 --- a/Api/Controllers/ItemTypesController.cs +++ b/Api/Controllers/ItemTypesController.cs @@ -14,7 +14,9 @@ namespace Api.Controllers; [Route("api/item-types")] public class ItemTypesController : ControllerBase { - [EndpointSummary("Get all item types")] + /// + /// Get all item types + /// [RequiresPermission(UserClaimsProvider.CanViewItemsTypes)] [HttpGet] public async Task GetAllItemTypesAsync( @@ -35,7 +37,9 @@ [FromServices] AllItemTypesQuery allItemTypesQuery }; } - [EndpointSummary("Adds item type")] + /// + /// Adds item type + /// /// [RequiresPermission(UserClaimsProvider.CanManageItemsTypes)] [HttpPost] @@ -52,7 +56,9 @@ [Required][FromBody] CreateItemTypeRequest createItemTypeRequest }; } - [EndpointSummary("Deletes specific item type")] + /// + /// Deletes specific item type + /// /// [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemTypesHardDeleteAllowed)] [HttpDelete("{itemTypeId}/hard-delete")] diff --git a/Api/Controllers/ItemsController.cs b/Api/Controllers/ItemsController.cs index 3d46d93..336de80 100644 --- a/Api/Controllers/ItemsController.cs +++ b/Api/Controllers/ItemsController.cs @@ -15,7 +15,9 @@ namespace Api.Controllers; [Route("api/items")] public class ItemsController : ControllerBase { - [EndpointSummary("Get all items")] + /// + /// Get all items + /// [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] public async Task GetAllItemsAsync( @@ -28,7 +30,9 @@ [FromServices] EmployeesApi employeesApi return await getAllItemsHandler.HandleAsync(allEmployeesResponse); } - [EndpointSummary("Add an item")] + /// + /// Add an item + /// /// [RequiresPermission(UserClaimsProvider.CanManageItems)] [HttpPost] @@ -40,13 +44,15 @@ [Required][FromBody] CreateItemRequest createItemRequest return createItemHandler.HandleAsync(createItemRequest); } - [EndpointSummary("Deletes specific item")] + /// + /// Deletes specific item + /// /// [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemsHardDeleteAllowed)] [HttpDelete("{itemId}/hard-delete")] public async Task HardDeleteItemAsync( [FromServices] HardDeleteItemCommand hardDeleteItemCommand, - [Required][FromRoute] long itemId + [Required][FromRoute] long itemId ) { return new From beea9675ffb1f71cc4ec0b14507752bf8c91709f Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 9 Feb 2026 17:51:35 +0500 Subject: [PATCH 30/61] refactor: delete unused import --- Api/Controllers/ItemsController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Api/Controllers/ItemsController.cs b/Api/Controllers/ItemsController.cs index 336de80..e83ee1d 100644 --- a/Api/Controllers/ItemsController.cs +++ b/Api/Controllers/ItemsController.cs @@ -1,4 +1,3 @@ -using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Api.ExternalDeps.EmployeesApi; using Application.Commands; From 6bd766a56aac79d09b4a0d659e12444cb3e870f7 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 9 Feb 2026 17:57:48 +0500 Subject: [PATCH 31/61] refactor: discard changes in Program.cs --- Api/Program.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/Api/Program.cs b/Api/Program.cs index cb6cb84..7540491 100644 --- a/Api/Program.cs +++ b/Api/Program.cs @@ -1,5 +1,4 @@ using Application; -using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.EntityFrameworkCore; using TourmalineCore.AspNetCore.JwtAuthentication.Core; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Options; @@ -16,21 +15,7 @@ public static void Main(string[] args) // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi - builder.Services.AddOpenApi(options => - { - options.AddOperationTransformer((operation, context, _) => - { - // Try to get the ControllerActionDescriptor to access method information - if (context.Description.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor) - { - // Set the operationId to the ControllerName and ActionName (which is typically the method name) - // This allows to have unique operationId even if there is the same method name across multiple controllers - operation.OperationId = $"{controllerActionDescriptor.ControllerName}{controllerActionDescriptor.ActionName}"; - } - - return Task.CompletedTask; - }); - }); + builder.Services.AddOpenApi(); builder.Services.AddApplication(configuration); From ac29ce24a5abed6face4e283be2090593a9433d8 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 9 Feb 2026 18:04:27 +0500 Subject: [PATCH 32/61] refactor: delete unused line --- Application/Features/Items/GetAllItems/GetAllItemsHandler.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs index 53d8828..086c36b 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -8,8 +8,6 @@ public class GetAllItemsHandler { private readonly AllItemsQuery _allItemsQuery; - public const string NotFoundEmployeeFullName = "Not Found"; - public GetAllItemsHandler( AllItemsQuery allItemsQuery ) From 339113b606c723e3a5820dfa13d9d6fb07c5d092 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Tue, 10 Feb 2026 10:35:13 +0500 Subject: [PATCH 33/61] refactor: return changes in Program.cs --- Api/Program.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Api/Program.cs b/Api/Program.cs index 7540491..cb6cb84 100644 --- a/Api/Program.cs +++ b/Api/Program.cs @@ -1,4 +1,5 @@ using Application; +using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.EntityFrameworkCore; using TourmalineCore.AspNetCore.JwtAuthentication.Core; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Options; @@ -15,7 +16,21 @@ public static void Main(string[] args) // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi - builder.Services.AddOpenApi(); + builder.Services.AddOpenApi(options => + { + options.AddOperationTransformer((operation, context, _) => + { + // Try to get the ControllerActionDescriptor to access method information + if (context.Description.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor) + { + // Set the operationId to the ControllerName and ActionName (which is typically the method name) + // This allows to have unique operationId even if there is the same method name across multiple controllers + operation.OperationId = $"{controllerActionDescriptor.ControllerName}{controllerActionDescriptor.ActionName}"; + } + + return Task.CompletedTask; + }); + }); builder.Services.AddApplication(configuration); From 59fdf9d531d4a5a6ef6edb9f8a5bd45d312d0cc7 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 06:48:56 +0000 Subject: [PATCH 34/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 101 +++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 59 deletions(-) diff --git a/js-client/index.ts b/js-client/index.ts index e121354..7fdc2c3 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -45,7 +45,6 @@ export interface CreateItemTypeResponse { export type EmployeeDto = { /** @format int64 */ id: number; - /** @maxLength 128 */ fullName: string; } | null; @@ -56,20 +55,10 @@ export interface GetAllItemsResponse { export interface ItemDto { /** @format int64 */ id: number; - /** - * Description for Name - * @maxLength 128 - * @default "DefaultName" - * @pattern ^[a-zA-Z\s]+$ - */ name: string; serialNumber: string; itemType: ItemTypeDto; - /** - * @format double - * @min 1 - * @max 100 - */ + /** @format double */ price: number; description: string; /** @format date */ @@ -272,16 +261,15 @@ export class Api< > extends HttpClient { api = { /** - * @description This is a description. + * No description * - * @tags Tag 2 - * @name ItemsGetAllItems - * @summary Get all items - * @request GET:/api/items + * @tags ItemTypes + * @name ItemTypesGetAllItemTypes + * @request GET:/api/item-types */ - itemsGetAllItems: (params: RequestParams = {}) => - this.request({ - path: `/api/items`, + itemTypesGetAllItemTypes: (params: RequestParams = {}) => + this.request({ + path: `/api/item-types`, method: "GET", format: "json", ...params, @@ -290,14 +278,16 @@ export class Api< /** * No description * - * @tags Tag 1 - * @name ItemsCreateItem - * @summary Add an item - * @request POST:/api/items + * @tags ItemTypes + * @name ItemTypesCreateItemType + * @request POST:/api/item-types */ - itemsCreateItem: (data: CreateItemRequest, params: RequestParams = {}) => - this.request({ - path: `/api/items`, + itemTypesCreateItemType: ( + data: CreateItemTypeRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/item-types`, method: "POST", body: data, type: ContentType.Json, @@ -308,14 +298,16 @@ export class Api< /** * No description * - * @tags Tag 1 - * @name ItemsHardDeleteItem - * @summary Deletes specific item - * @request DELETE:/api/items/{itemId}/hard-delete + * @tags ItemTypes + * @name ItemTypesHardDeleteItemType + * @request DELETE:/api/item-types/{itemTypeId}/hard-delete */ - itemsHardDeleteItem: (itemId: number, params: RequestParams = {}) => + itemTypesHardDeleteItemType: ( + itemTypeId: number, + params: RequestParams = {}, + ) => this.request({ - path: `/api/items/${itemId}/hard-delete`, + path: `/api/item-types/${itemTypeId}/hard-delete`, method: "DELETE", ...params, }), @@ -323,14 +315,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesGetAllItemTypes - * @summary Get all item types - * @request GET:/api/item-types + * @tags Items + * @name ItemsGetAllItems + * @request GET:/api/items */ - itemTypesGetAllItemTypes: (params: RequestParams = {}) => - this.request({ - path: `/api/item-types`, + itemsGetAllItems: (params: RequestParams = {}) => + this.request({ + path: `/api/items`, method: "GET", format: "json", ...params, @@ -339,17 +330,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesCreateItemType - * @summary Adds item type - * @request POST:/api/item-types + * @tags Items + * @name ItemsCreateItem + * @request POST:/api/items */ - itemTypesCreateItemType: ( - data: CreateItemTypeRequest, - params: RequestParams = {}, - ) => - this.request({ - path: `/api/item-types`, + itemsCreateItem: (data: CreateItemRequest, params: RequestParams = {}) => + this.request({ + path: `/api/items`, method: "POST", body: data, type: ContentType.Json, @@ -360,17 +347,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesHardDeleteItemType - * @summary Deletes specific item type - * @request DELETE:/api/item-types/{itemTypeId}/hard-delete + * @tags Items + * @name ItemsHardDeleteItem + * @request DELETE:/api/items/{itemId}/hard-delete */ - itemTypesHardDeleteItemType: ( - itemTypeId: number, - params: RequestParams = {}, - ) => + itemsHardDeleteItem: (itemId: number, params: RequestParams = {}) => this.request({ - path: `/api/item-types/${itemTypeId}/hard-delete`, + path: `/api/items/${itemId}/hard-delete`, method: "DELETE", ...params, }), From 3a2a267edb02f3e3c27a546e2155fe142c4dd995 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:49:25 +0500 Subject: [PATCH 35/61] refactor: change namespace in ItemsController --- Api/Features/Items/ItemsController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index 47f5f7a..f593bc3 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Mvc; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Filters; -namespace Api.Controllers; +namespace Api.Features.Items; [Authorize] [ApiController] From 7db02c93d9e335e83412b5e61cabfd1d83ef4c7b Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 06:49:49 +0000 Subject: [PATCH 36/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b9e9f65..df17669 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-82.43%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.13%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-90.09%25-forestgreen)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-81.92%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.64%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-89.79%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From 2da0724a349ed6485619fddf87c693d54065b5bf Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 06:51:06 +0000 Subject: [PATCH 37/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 80 +++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/js-client/index.ts b/js-client/index.ts index 7fdc2c3..55521ac 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -263,13 +263,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesGetAllItemTypes - * @request GET:/api/item-types + * @tags Items + * @name ItemsGetAllItems + * @request GET:/api/items */ - itemTypesGetAllItemTypes: (params: RequestParams = {}) => - this.request({ - path: `/api/item-types`, + itemsGetAllItems: (params: RequestParams = {}) => + this.request({ + path: `/api/items`, method: "GET", format: "json", ...params, @@ -278,16 +278,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesCreateItemType - * @request POST:/api/item-types + * @tags Items + * @name ItemsCreateItem + * @request POST:/api/items */ - itemTypesCreateItemType: ( - data: CreateItemTypeRequest, - params: RequestParams = {}, - ) => - this.request({ - path: `/api/item-types`, + itemsCreateItem: (data: CreateItemRequest, params: RequestParams = {}) => + this.request({ + path: `/api/items`, method: "POST", body: data, type: ContentType.Json, @@ -298,16 +295,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesHardDeleteItemType - * @request DELETE:/api/item-types/{itemTypeId}/hard-delete + * @tags Items + * @name ItemsHardDeleteItem + * @request DELETE:/api/items/{itemId}/hard-delete */ - itemTypesHardDeleteItemType: ( - itemTypeId: number, - params: RequestParams = {}, - ) => + itemsHardDeleteItem: (itemId: number, params: RequestParams = {}) => this.request({ - path: `/api/item-types/${itemTypeId}/hard-delete`, + path: `/api/items/${itemId}/hard-delete`, method: "DELETE", ...params, }), @@ -315,13 +309,13 @@ export class Api< /** * No description * - * @tags Items - * @name ItemsGetAllItems - * @request GET:/api/items + * @tags ItemTypes + * @name ItemTypesGetAllItemTypes + * @request GET:/api/item-types */ - itemsGetAllItems: (params: RequestParams = {}) => - this.request({ - path: `/api/items`, + itemTypesGetAllItemTypes: (params: RequestParams = {}) => + this.request({ + path: `/api/item-types`, method: "GET", format: "json", ...params, @@ -330,13 +324,16 @@ export class Api< /** * No description * - * @tags Items - * @name ItemsCreateItem - * @request POST:/api/items + * @tags ItemTypes + * @name ItemTypesCreateItemType + * @request POST:/api/item-types */ - itemsCreateItem: (data: CreateItemRequest, params: RequestParams = {}) => - this.request({ - path: `/api/items`, + itemTypesCreateItemType: ( + data: CreateItemTypeRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/item-types`, method: "POST", body: data, type: ContentType.Json, @@ -347,13 +344,16 @@ export class Api< /** * No description * - * @tags Items - * @name ItemsHardDeleteItem - * @request DELETE:/api/items/{itemId}/hard-delete + * @tags ItemTypes + * @name ItemTypesHardDeleteItemType + * @request DELETE:/api/item-types/{itemTypeId}/hard-delete */ - itemsHardDeleteItem: (itemId: number, params: RequestParams = {}) => + itemTypesHardDeleteItemType: ( + itemTypeId: number, + params: RequestParams = {}, + ) => this.request({ - path: `/api/items/${itemId}/hard-delete`, + path: `/api/item-types/${itemTypeId}/hard-delete`, method: "DELETE", ...params, }), From 67957a47214f6c110f7f26100b5f354790caf685 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:54:02 +0500 Subject: [PATCH 38/61] fix: fix lint --- Api/Features/Items/ItemsController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index f593bc3..c81b23e 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -59,4 +59,4 @@ [Required][FromRoute] long itemId isDeleted = await hardDeleteItemCommand.ExecuteAsync(itemId) }; } -} \ No newline at end of file +} From bbb9c46004cef45f4c81da1e5652eff3bd97321d Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Tue, 10 Feb 2026 13:30:15 +0500 Subject: [PATCH 39/61] refactor: change latter in name of parameter --- Application/Commands/CreateItemTypeCommand.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Application/Commands/CreateItemTypeCommand.cs b/Application/Commands/CreateItemTypeCommand.cs index d6e1aac..1ba90ac 100644 --- a/Application/Commands/CreateItemTypeCommand.cs +++ b/Application/Commands/CreateItemTypeCommand.cs @@ -17,12 +17,12 @@ IClaimsProvider claimsProvider _claimsProvider = claimsProvider; } - public async Task ExecuteAsync(CreateItemTypeRequest CreateItemTypeRequest) + public async Task ExecuteAsync(CreateItemTypeRequest createItemTypeRequest) { var itemType = new ItemType { TenantId = _claimsProvider.TenantId, - Name = CreateItemTypeRequest.Name + Name = createItemTypeRequest.Name }; await _context From fe576236190190265d3bcdb4de89aa19fd631ac3 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:57:51 +0500 Subject: [PATCH 40/61] refactor: return CreateItemCommand --- Api/DependencyInjection.cs | 1 + Application/Commands/CreateItemCommand.cs | 52 +++++++++++++++++++ .../Items/CreateItem/CreateItemHandler.cs | 43 +++------------ 3 files changed, 59 insertions(+), 37 deletions(-) create mode 100644 Application/Commands/CreateItemCommand.cs diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 9509072..871e70f 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -31,6 +31,7 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Application/Commands/CreateItemCommand.cs b/Application/Commands/CreateItemCommand.cs new file mode 100644 index 0000000..c9cd2b8 --- /dev/null +++ b/Application/Commands/CreateItemCommand.cs @@ -0,0 +1,52 @@ +using Application.Features.Items.CreateItem; +using Core.Entities; +using Microsoft.EntityFrameworkCore; + +namespace Application.Commands; + +public class CreateItemCommand +{ + private readonly TenantAppDbContext _context; + private readonly IClaimsProvider _claimsProvider; + + public CreateItemCommand( + TenantAppDbContext context, + IClaimsProvider claimsProvider + ) + { + _context = context; + _claimsProvider = claimsProvider; + } + + public async Task ExecuteAsync(CreateItemRequest createItemRequest) + { + var itemTypeIdDoesNotExistWithinTenant = await _context + .QueryableWithinTenant() + .AllAsync(x => x.Id != createItemRequest.ItemTypeId); + + if (itemTypeIdDoesNotExistWithinTenant) + { + throw new Exception($"Passed item type where id={createItemRequest.ItemTypeId} is not found within tenant where id={_claimsProvider.TenantId}"); + } + + var item = new Item + { + TenantId = _claimsProvider.TenantId, + Name = createItemRequest.Name, + SerialNumber = createItemRequest.SerialNumber, + ItemTypeId = createItemRequest.ItemTypeId, + Price = createItemRequest.Price, + Description = createItemRequest.Description, + PurchaseDate = createItemRequest.PurchaseDate, + HolderEmployeeId = createItemRequest.HolderEmployeeId + }; + + await _context + .Items + .AddAsync(item); + + await _context.SaveChangesAsync(); + + return item.Id; + } +} \ No newline at end of file diff --git a/Application/Features/Items/CreateItem/CreateItemHandler.cs b/Application/Features/Items/CreateItem/CreateItemHandler.cs index 972e724..f864de2 100644 --- a/Application/Features/Items/CreateItem/CreateItemHandler.cs +++ b/Application/Features/Items/CreateItem/CreateItemHandler.cs @@ -1,54 +1,23 @@ -using Core.Entities; -using Microsoft.EntityFrameworkCore; +using Application.Commands; namespace Application.Features.Items.CreateItem; public class CreateItemHandler { - private readonly TenantAppDbContext _context; - private readonly IClaimsProvider _claimsProvider; + private readonly CreateItemCommand _createItemCommand; public CreateItemHandler( - TenantAppDbContext context, - IClaimsProvider claimsProvider + CreateItemCommand createItemCommand ) { - _context = context; - _claimsProvider = claimsProvider; + _createItemCommand = createItemCommand; } public async Task HandleAsync(CreateItemRequest createItemRequest) { - var itemTypeIdDoesNotExistWithinTenant = await _context - .QueryableWithinTenant() - .AllAsync(x => x.Id != createItemRequest.ItemTypeId); - - if (itemTypeIdDoesNotExistWithinTenant) - { - throw new Exception($"Passed item type where id={createItemRequest.ItemTypeId} is not found within tenant where id={_claimsProvider.TenantId}"); - } - - var item = new Item - { - TenantId = _claimsProvider.TenantId, - Name = createItemRequest.Name, - SerialNumber = createItemRequest.SerialNumber, - ItemTypeId = createItemRequest.ItemTypeId, - Price = createItemRequest.Price, - Description = createItemRequest.Description, - PurchaseDate = createItemRequest.PurchaseDate, - HolderEmployeeId = createItemRequest.HolderEmployeeId - }; - - await _context - .Items - .AddAsync(item); - - await _context.SaveChangesAsync(); - - return new CreateItemResponse() + return new CreateItemResponse { - NewItemId = item.Id + NewItemId = await _createItemCommand.ExecuteAsync(createItemRequest) }; } } From cd0817f068cd1f1a71e0e2f470e66acf037486ae Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 09:00:11 +0000 Subject: [PATCH 41/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index df17669..65853e1 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-81.92%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.64%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.79%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-82.08%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.48%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-89.88%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From f50cf67438c7e2233d4af4c6bbb23a90dad80144 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:31:44 +0500 Subject: [PATCH 42/61] refactor: add HardDeleteItemHandler --- Api/DependencyInjection.cs | 3 ++- Api/Features/Items/ItemsController.cs | 5 +++-- Application/Commands/HardDeleteItemCommand.cs | 18 ------------------ .../HardDeleteItem/HardDeleteItemHandler.cs | 19 +++++++++++++++++++ 4 files changed, 24 insertions(+), 21 deletions(-) delete mode 100644 Application/Commands/HardDeleteItemCommand.cs create mode 100644 Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 871e70f..ddde0f1 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -3,6 +3,7 @@ using Application.Commands; using Application.Features.Items.CreateItem; using Application.Features.Items.GetAllItems; +using Application.Features.Items.HardDeleteItem; using Application.Queries; using Microsoft.EntityFrameworkCore; @@ -37,9 +38,9 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index c81b23e..583fa50 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -3,6 +3,7 @@ using Application.Commands; using Application.Features.Items.CreateItem; using Application.Features.Items.GetAllItems; +using Application.Features.Items.HardDeleteItem; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Filters; @@ -50,13 +51,13 @@ [Required][FromBody] CreateItemRequest createItemRequest [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemsHardDeleteAllowed)] [HttpDelete("{itemId}/hard-delete")] public async Task HardDeleteItemAsync( - [FromServices] HardDeleteItemCommand hardDeleteItemCommand, + [FromServices] HardDeleteItemHandler hardDeleteItemHandler, [Required][FromRoute] long itemId ) { return new { - isDeleted = await hardDeleteItemCommand.ExecuteAsync(itemId) + isDeleted = await hardDeleteItemHandler.HandleAsync(itemId) }; } } diff --git a/Application/Commands/HardDeleteItemCommand.cs b/Application/Commands/HardDeleteItemCommand.cs deleted file mode 100644 index 8f62646..0000000 --- a/Application/Commands/HardDeleteItemCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Core.Entities; - -namespace Application.Commands; - -public class HardDeleteItemCommand -{ - private readonly HardDeleteEntityCommand _hardDeleteEntityCommand; - - public HardDeleteItemCommand(TenantAppDbContext context) - { - _hardDeleteEntityCommand = new HardDeleteEntityCommand(context); - } - - public Task ExecuteAsync(long itemId) - { - return _hardDeleteEntityCommand.ExecuteAsync(itemId); - } -} diff --git a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs new file mode 100644 index 0000000..fd59a97 --- /dev/null +++ b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs @@ -0,0 +1,19 @@ +using Application.Commands; +using Core.Entities; + +namespace Application.Features.Items.HardDeleteItem; + +public class HardDeleteItemHandler +{ + private readonly HardDeleteEntityCommand _hardDeleteEntityCommand; + + public HardDeleteItemHandler(TenantAppDbContext context) + { + _hardDeleteEntityCommand = new HardDeleteEntityCommand(context); + } + + public async Task HandleAsync(long itemId) + { + return await _hardDeleteEntityCommand.ExecuteAsync(itemId); + } +} From 2c4ffdb84d231192d746e9258688df4f545eadd8 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 09:33:41 +0000 Subject: [PATCH 43/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js-client/index.ts b/js-client/index.ts index 0e6cd47..016b5d9 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -253,7 +253,7 @@ export class HttpClient { /** * @title inner-circle-items-api - * @version 1.0.7 + * @version 1.0.8 * @baseUrl http://localhost:6501/ */ export class Api< From 86715d5662ac55e30fade31281c91b2562b1c7c0 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 09:34:40 +0000 Subject: [PATCH 44/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4e99153..954e74f 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-82.08%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.48%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-89.88%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-82.47%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-17.10%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-90.10%25-forestgreen)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From 62a37b002b4bb6b3cf0d3dfe025cc30e64446195 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Tue, 10 Feb 2026 15:06:07 +0500 Subject: [PATCH 45/61] refactor: add handlers to ItemTypes and delete HardDeleteItemTypeCommand.cs --- Api/DependencyInjection.cs | 8 +++- .../ItemTypes}/ItemTypesController.cs | 38 ++++++------------- .../Commands/HardDeleteEntityCommandTests.cs | 27 +++++++++++++ .../Commands/HardDeleteItemTypeCommand.cs | 18 --------- .../HardDeleteItemTypeCommandTests.cs | 35 ----------------- .../CreateItemType/CreateItemTypeHandler.cs | 26 +++++++++++++ .../CreateItemTypeRequest.cs | 0 .../CreateItemTypeResponse.cs | 0 .../GetAllItemTypes/GetAllItemTypesHandler.cs | 32 ++++++++++++++++ .../HardDeleteItemTypeHandler.cs | 19 ++++++++++ .../HardDeleteItem/HardDeleteItemHandler.cs | 4 +- 11 files changed, 124 insertions(+), 83 deletions(-) rename Api/{Controllers => Features/ItemTypes}/ItemTypesController.cs (55%) delete mode 100644 Application/Commands/HardDeleteItemTypeCommand.cs delete mode 100644 Application/Commands/HardDeleteItemTypeCommandTests.cs create mode 100644 Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs rename Application/Features/ItemTypes/{ => CreateItemType}/CreateItemTypeRequest.cs (100%) rename Application/Features/ItemTypes/{ => CreateItemType}/CreateItemTypeResponse.cs (100%) create mode 100644 Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs create mode 100644 Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index ddde0f1..dee2e92 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -4,6 +4,9 @@ using Application.Features.Items.CreateItem; using Application.Features.Items.GetAllItems; using Application.Features.Items.HardDeleteItem; +using Application.Features.ItemTypes.CreateItemType; +using Application.Features.ItemTypes.GetAllItemTypes; +using Application.Features.ItemTypes.HardDeleteItemType; using Application.Queries; using Microsoft.EntityFrameworkCore; @@ -34,7 +37,6 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -42,5 +44,9 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); services.AddTransient(); services.AddTransient(); + + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } } diff --git a/Api/Controllers/ItemTypesController.cs b/Api/Features/ItemTypes/ItemTypesController.cs similarity index 55% rename from Api/Controllers/ItemTypesController.cs rename to Api/Features/ItemTypes/ItemTypesController.cs index b99aecf..90a2f9f 100644 --- a/Api/Controllers/ItemTypesController.cs +++ b/Api/Features/ItemTypes/ItemTypesController.cs @@ -1,13 +1,13 @@ using System.ComponentModel.DataAnnotations; -using Application.Commands; -using Application.Features.Dtos; using Application.Features.ItemTypes; -using Application.Queries; +using Application.Features.ItemTypes.CreateItemType; +using Application.Features.ItemTypes.GetAllItemTypes; +using Application.Features.ItemTypes.HardDeleteItemType; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using TourmalineCore.AspNetCore.JwtAuthentication.Core.Filters; -namespace Api.Controllers; +namespace Api.Features.ItemTypes; [Authorize] [ApiController] @@ -20,21 +20,10 @@ public class ItemTypesController : ControllerBase [RequiresPermission(UserClaimsProvider.CanViewItemsTypes)] [HttpGet] public async Task GetAllItemTypesAsync( - [FromServices] AllItemTypesQuery allItemTypesQuery + [FromServices] GetAllItemTypesHandler getAllItemTypesHandler ) { - var itemTypes = await allItemTypesQuery.GetAsync(); - - return new ItemTypesResponse - { - ItemTypes = itemTypes - .Select(x => new ItemTypeDto - { - Id = x.Id, - Name = x.Name, - }) - .ToList() - }; + return await getAllItemTypesHandler.HandleAsync(); } /// @@ -43,17 +32,12 @@ [FromServices] AllItemTypesQuery allItemTypesQuery /// [RequiresPermission(UserClaimsProvider.CanManageItemsTypes)] [HttpPost] - public async Task CreateItemTypeAsync( - [FromServices] CreateItemTypeCommand createItemTypeCommand, + public Task CreateItemTypeAsync( + [FromServices] CreateItemTypeHandler createItemTypeHandler, [Required][FromBody] CreateItemTypeRequest createItemTypeRequest ) { - var newItemTypeId = await createItemTypeCommand.ExecuteAsync(createItemTypeRequest); - - return new CreateItemTypeResponse() - { - NewItemTypeId = newItemTypeId - }; + return createItemTypeHandler.HandleAsync(createItemTypeRequest); } /// @@ -63,13 +47,13 @@ [Required][FromBody] CreateItemTypeRequest createItemTypeRequest [RequiresPermission(UserClaimsProvider.AUTO_TESTS_ONLY_IsItemTypesHardDeleteAllowed)] [HttpDelete("{itemTypeId}/hard-delete")] public async Task HardDeleteItemTypeAsync( - [FromServices] HardDeleteItemTypeCommand hardDeleteItemTypeCommand, + [FromServices] HardDeleteItemTypeHandler hardDeleteItemTypeHandler, [Required][FromRoute] long itemTypeId ) { return new { - isDeleted = await hardDeleteItemTypeCommand.ExecuteAsync(itemTypeId) + isDeleted = await hardDeleteItemTypeHandler.HandleAsync(itemTypeId) }; } } diff --git a/Application/Commands/HardDeleteEntityCommandTests.cs b/Application/Commands/HardDeleteEntityCommandTests.cs index 615a0fa..026ea78 100644 --- a/Application/Commands/HardDeleteEntityCommandTests.cs +++ b/Application/Commands/HardDeleteEntityCommandTests.cs @@ -52,4 +52,31 @@ await context.AddEntityAndSaveAsync(new Item Assert.Null(await Record.ExceptionAsync(async () => wasNonExistedDeleted = await hardDeleteEntityCommand.ExecuteAsync(2))); Assert.False(wasNonExistedDeleted); } + + [Fact] + public async Task DeleteItemTypeThatHasRelatedItem_ShouldDeleteItemAsWell() + { + var context = TenantAppDbContextExtensionsTestsRelated.CteateInMemoryTenantContextForTests(); + + await context.AddEntityAndSaveAsync(new ItemType + { + Id = 1 + }); + + await context.AddEntityAndSaveAsync(new Item + { + Id = 2, + ItemTypeId = 1 + }); + + var hardDeleteEntityCommand = new HardDeleteEntityCommand(context); + + await hardDeleteEntityCommand.ExecuteAsync(1); + + var itemDoesNotExist = await context + .Items + .AllAsync(x => x.Id != 2); + + Assert.True(itemDoesNotExist); + } } diff --git a/Application/Commands/HardDeleteItemTypeCommand.cs b/Application/Commands/HardDeleteItemTypeCommand.cs deleted file mode 100644 index 4d1ed21..0000000 --- a/Application/Commands/HardDeleteItemTypeCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Core.Entities; - -namespace Application.Commands; - -public class HardDeleteItemTypeCommand -{ - private readonly HardDeleteEntityCommand _hardDeleteEntityCommand; - - public HardDeleteItemTypeCommand(TenantAppDbContext context) - { - _hardDeleteEntityCommand = new HardDeleteEntityCommand(context); - } - - public Task ExecuteAsync(long itemTypeId) - { - return _hardDeleteEntityCommand.ExecuteAsync(itemTypeId); - } -} diff --git a/Application/Commands/HardDeleteItemTypeCommandTests.cs b/Application/Commands/HardDeleteItemTypeCommandTests.cs deleted file mode 100644 index 4181362..0000000 --- a/Application/Commands/HardDeleteItemTypeCommandTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Core.Entities; -using Microsoft.EntityFrameworkCore; -using Xunit; - -namespace Application.Commands; - -public class HardDeleteItemTypeCommandTests -{ - [Fact] - public async Task DeleteItemTypeThatHasRelatedItem_ShouldDeleteItemAsWell() - { - var context = TenantAppDbContextExtensionsTestsRelated.CteateInMemoryTenantContextForTests(); - - await context.AddEntityAndSaveAsync(new ItemType - { - Id = 1 - }); - - await context.AddEntityAndSaveAsync(new Item - { - Id = 2, - ItemTypeId = 1 - }); - - var deleteItemTypeCommand = new HardDeleteItemTypeCommand(context); - - await deleteItemTypeCommand.ExecuteAsync(1); - - var itemDoesNotExist = await context - .Items - .AllAsync(x => x.Id != 2); - - Assert.True(itemDoesNotExist); - } -} diff --git a/Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs new file mode 100644 index 0000000..410a11b --- /dev/null +++ b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs @@ -0,0 +1,26 @@ + +using Application.Commands; + +namespace Application.Features.ItemTypes.CreateItemType; + +public class CreateItemTypeHandler +{ + private readonly CreateItemTypeCommand _createItemTypeCommand; + + public CreateItemTypeHandler( + CreateItemTypeCommand createItemTypeCommand + ) + { + _createItemTypeCommand = createItemTypeCommand; + } + + public async Task HandleAsync(CreateItemTypeRequest createItemTypeRequest) + { + var newItemTypeId = await _createItemTypeCommand.ExecuteAsync(createItemTypeRequest); + + return new CreateItemTypeResponse() + { + NewItemTypeId = newItemTypeId + }; + } +} diff --git a/Application/Features/ItemTypes/CreateItemTypeRequest.cs b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeRequest.cs similarity index 100% rename from Application/Features/ItemTypes/CreateItemTypeRequest.cs rename to Application/Features/ItemTypes/CreateItemType/CreateItemTypeRequest.cs diff --git a/Application/Features/ItemTypes/CreateItemTypeResponse.cs b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeResponse.cs similarity index 100% rename from Application/Features/ItemTypes/CreateItemTypeResponse.cs rename to Application/Features/ItemTypes/CreateItemType/CreateItemTypeResponse.cs diff --git a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs new file mode 100644 index 0000000..74e73e6 --- /dev/null +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs @@ -0,0 +1,32 @@ +using Application.Features.Dtos; +using Application.Queries; + +namespace Application.Features.ItemTypes.GetAllItemTypes; + +public class GetAllItemTypesHandler +{ + private readonly AllItemTypesQuery _allItemTypesQuery; + + public GetAllItemTypesHandler( + AllItemTypesQuery allItemTypesQuery + ) + { + _allItemTypesQuery = allItemTypesQuery; + } + + public async Task HandleAsync() + { + var itemTypes = await _allItemTypesQuery.GetAsync(); + + return new ItemTypesResponse + { + ItemTypes = itemTypes + .Select(x => new ItemTypeDto + { + Id = x.Id, + Name = x.Name, + }) + .ToList() + }; + } +} diff --git a/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs new file mode 100644 index 0000000..cb3e3f6 --- /dev/null +++ b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs @@ -0,0 +1,19 @@ + +using Application.Commands; +using Core.Entities; + +namespace Application.Features.ItemTypes.HardDeleteItemType; + +public class HardDeleteItemTypeHandler +{ + private readonly HardDeleteEntityCommand _hardDeleteEntityCommand; + + public HardDeleteItemTypeHandler(TenantAppDbContext context) + { + _hardDeleteEntityCommand = new HardDeleteEntityCommand(context); + } + public Task HandleAsync(long itemTypeId) + { + return _hardDeleteEntityCommand.ExecuteAsync(itemTypeId); + } +} diff --git a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs index fd59a97..e504e01 100644 --- a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs +++ b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs @@ -12,8 +12,8 @@ public HardDeleteItemHandler(TenantAppDbContext context) _hardDeleteEntityCommand = new HardDeleteEntityCommand(context); } - public async Task HandleAsync(long itemId) + public Task HandleAsync(long itemId) { - return await _hardDeleteEntityCommand.ExecuteAsync(itemId); + return _hardDeleteEntityCommand.ExecuteAsync(itemId); } } From 26b5f04101c5b160fafa203571b64542318c074b Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 10:07:43 +0000 Subject: [PATCH 46/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 80 +++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/js-client/index.ts b/js-client/index.ts index 016b5d9..eba94bb 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -263,13 +263,13 @@ export class Api< /** * No description * - * @tags Items - * @name ItemsGetAllItems - * @request GET:/api/items + * @tags ItemTypes + * @name ItemTypesGetAllItemTypes + * @request GET:/api/item-types */ - itemsGetAllItems: (params: RequestParams = {}) => - this.request({ - path: `/api/items`, + itemTypesGetAllItemTypes: (params: RequestParams = {}) => + this.request({ + path: `/api/item-types`, method: "GET", format: "json", ...params, @@ -278,13 +278,16 @@ export class Api< /** * No description * - * @tags Items - * @name ItemsCreateItem - * @request POST:/api/items + * @tags ItemTypes + * @name ItemTypesCreateItemType + * @request POST:/api/item-types */ - itemsCreateItem: (data: CreateItemRequest, params: RequestParams = {}) => - this.request({ - path: `/api/items`, + itemTypesCreateItemType: ( + data: CreateItemTypeRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/item-types`, method: "POST", body: data, type: ContentType.Json, @@ -295,13 +298,16 @@ export class Api< /** * No description * - * @tags Items - * @name ItemsHardDeleteItem - * @request DELETE:/api/items/{itemId}/hard-delete + * @tags ItemTypes + * @name ItemTypesHardDeleteItemType + * @request DELETE:/api/item-types/{itemTypeId}/hard-delete */ - itemsHardDeleteItem: (itemId: number, params: RequestParams = {}) => + itemTypesHardDeleteItemType: ( + itemTypeId: number, + params: RequestParams = {}, + ) => this.request({ - path: `/api/items/${itemId}/hard-delete`, + path: `/api/item-types/${itemTypeId}/hard-delete`, method: "DELETE", ...params, }), @@ -309,13 +315,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesGetAllItemTypes - * @request GET:/api/item-types + * @tags Items + * @name ItemsGetAllItems + * @request GET:/api/items */ - itemTypesGetAllItemTypes: (params: RequestParams = {}) => - this.request({ - path: `/api/item-types`, + itemsGetAllItems: (params: RequestParams = {}) => + this.request({ + path: `/api/items`, method: "GET", format: "json", ...params, @@ -324,16 +330,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesCreateItemType - * @request POST:/api/item-types + * @tags Items + * @name ItemsCreateItem + * @request POST:/api/items */ - itemTypesCreateItemType: ( - data: CreateItemTypeRequest, - params: RequestParams = {}, - ) => - this.request({ - path: `/api/item-types`, + itemsCreateItem: (data: CreateItemRequest, params: RequestParams = {}) => + this.request({ + path: `/api/items`, method: "POST", body: data, type: ContentType.Json, @@ -344,16 +347,13 @@ export class Api< /** * No description * - * @tags ItemTypes - * @name ItemTypesHardDeleteItemType - * @request DELETE:/api/item-types/{itemTypeId}/hard-delete + * @tags Items + * @name ItemsHardDeleteItem + * @request DELETE:/api/items/{itemId}/hard-delete */ - itemTypesHardDeleteItemType: ( - itemTypeId: number, - params: RequestParams = {}, - ) => + itemsHardDeleteItem: (itemId: number, params: RequestParams = {}) => this.request({ - path: `/api/item-types/${itemTypeId}/hard-delete`, + path: `/api/items/${itemId}/hard-delete`, method: "DELETE", ...params, }), From f90304f426b248ea4163f4bd07a7037a53575fa9 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 10:08:23 +0000 Subject: [PATCH 47/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 954e74f..21f2bbb 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-82.47%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-17.10%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-90.10%25-forestgreen)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-82.76%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-16.21%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-90.27%25-forestgreen)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API. From 546c783a0284b60d4995b73f7fcb616c9eb2108b Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Tue, 10 Feb 2026 15:08:50 +0500 Subject: [PATCH 48/61] refactor: move commands to features folders --- .../ItemTypes/CreateItemType}/CreateItemTypeCommand.cs | 5 ++--- .../Items/CreateItem}/CreateItemCommand.cs | 3 +-- .../{Commands => SharedCommands}/HardDeleteEntityCommand.cs | 0 .../HardDeleteEntityCommandTests.cs | 0 4 files changed, 3 insertions(+), 5 deletions(-) rename Application/{Commands => Features/ItemTypes/CreateItemType}/CreateItemTypeCommand.cs (88%) rename Application/{Commands => Features/Items/CreateItem}/CreateItemCommand.cs (95%) rename Application/{Commands => SharedCommands}/HardDeleteEntityCommand.cs (100%) rename Application/{Commands => SharedCommands}/HardDeleteEntityCommandTests.cs (100%) diff --git a/Application/Commands/CreateItemTypeCommand.cs b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeCommand.cs similarity index 88% rename from Application/Commands/CreateItemTypeCommand.cs rename to Application/Features/ItemTypes/CreateItemType/CreateItemTypeCommand.cs index 1ba90ac..4c89a2b 100644 --- a/Application/Commands/CreateItemTypeCommand.cs +++ b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeCommand.cs @@ -1,7 +1,6 @@ -using Application.Features.ItemTypes; -using Core.Entities; +using Core.Entities; -namespace Application.Commands; +namespace Application.Features.ItemTypes.CreateItemType; public class CreateItemTypeCommand { diff --git a/Application/Commands/CreateItemCommand.cs b/Application/Features/Items/CreateItem/CreateItemCommand.cs similarity index 95% rename from Application/Commands/CreateItemCommand.cs rename to Application/Features/Items/CreateItem/CreateItemCommand.cs index c9cd2b8..7d1c59d 100644 --- a/Application/Commands/CreateItemCommand.cs +++ b/Application/Features/Items/CreateItem/CreateItemCommand.cs @@ -1,8 +1,7 @@ -using Application.Features.Items.CreateItem; using Core.Entities; using Microsoft.EntityFrameworkCore; -namespace Application.Commands; +namespace Application.Features.Items.CreateItem; public class CreateItemCommand { diff --git a/Application/Commands/HardDeleteEntityCommand.cs b/Application/SharedCommands/HardDeleteEntityCommand.cs similarity index 100% rename from Application/Commands/HardDeleteEntityCommand.cs rename to Application/SharedCommands/HardDeleteEntityCommand.cs diff --git a/Application/Commands/HardDeleteEntityCommandTests.cs b/Application/SharedCommands/HardDeleteEntityCommandTests.cs similarity index 100% rename from Application/Commands/HardDeleteEntityCommandTests.cs rename to Application/SharedCommands/HardDeleteEntityCommandTests.cs From 02a0ac2732c1501fd824aa88d750fa86aaac8df7 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Tue, 10 Feb 2026 15:15:14 +0500 Subject: [PATCH 49/61] refactor: rename Dto folder to SharedDto and fix usings --- Api/DependencyInjection.cs | 1 - .../Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs | 3 --- .../Features/ItemTypes/CreateItemType/CreateItemTypeRequest.cs | 2 +- .../ItemTypes/CreateItemType/CreateItemTypeResponse.cs | 2 +- .../ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs | 2 +- .../ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs | 3 +-- Application/Features/ItemTypes/ItemTypesResponse.cs | 2 +- Application/Features/Items/CreateItem/CreateItemCommand.cs | 2 +- Application/Features/Items/CreateItem/CreateItemHandler.cs | 2 -- Application/Features/Items/GetAllItems/GetAllItemsHandler.cs | 2 +- Application/Features/Items/GetAllItems/GetAllItemsResponse.cs | 2 +- .../Features/Items/HardDeleteItem/HardDeleteItemHandler.cs | 2 +- Application/Features/{Dtos => SharedDtos}/ItemTypeDto.cs | 2 +- Application/SharedCommands/HardDeleteEntityCommand.cs | 2 +- Application/SharedCommands/HardDeleteEntityCommandTests.cs | 2 +- 15 files changed, 12 insertions(+), 19 deletions(-) rename Application/Features/{Dtos => SharedDtos}/ItemTypeDto.cs (72%) diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index dee2e92..4ceecef 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -1,6 +1,5 @@ using Api.ExternalDeps.EmployeesApi; using Application; -using Application.Commands; using Application.Features.Items.CreateItem; using Application.Features.Items.GetAllItems; using Application.Features.Items.HardDeleteItem; diff --git a/Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs index 410a11b..7f0e2db 100644 --- a/Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs +++ b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeHandler.cs @@ -1,6 +1,3 @@ - -using Application.Commands; - namespace Application.Features.ItemTypes.CreateItemType; public class CreateItemTypeHandler diff --git a/Application/Features/ItemTypes/CreateItemType/CreateItemTypeRequest.cs b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeRequest.cs index 669a968..038ff61 100644 --- a/Application/Features/ItemTypes/CreateItemType/CreateItemTypeRequest.cs +++ b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Application.Features.ItemTypes; +namespace Application.Features.ItemTypes.CreateItemType; public class CreateItemTypeRequest { diff --git a/Application/Features/ItemTypes/CreateItemType/CreateItemTypeResponse.cs b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeResponse.cs index 010184a..1634dc7 100644 --- a/Application/Features/ItemTypes/CreateItemType/CreateItemTypeResponse.cs +++ b/Application/Features/ItemTypes/CreateItemType/CreateItemTypeResponse.cs @@ -1,4 +1,4 @@ -namespace Application.Features.ItemTypes; +namespace Application.Features.ItemTypes.CreateItemType; public class CreateItemTypeResponse { diff --git a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs index 74e73e6..5ac499f 100644 --- a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs @@ -1,4 +1,4 @@ -using Application.Features.Dtos; +using Application.Features.SharedDtos; using Application.Queries; namespace Application.Features.ItemTypes.GetAllItemTypes; diff --git a/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs index cb3e3f6..2db0768 100644 --- a/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs +++ b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs @@ -1,5 +1,4 @@ - -using Application.Commands; +using Application.SharedCommands; using Core.Entities; namespace Application.Features.ItemTypes.HardDeleteItemType; diff --git a/Application/Features/ItemTypes/ItemTypesResponse.cs b/Application/Features/ItemTypes/ItemTypesResponse.cs index b1f23b3..6405c79 100644 --- a/Application/Features/ItemTypes/ItemTypesResponse.cs +++ b/Application/Features/ItemTypes/ItemTypesResponse.cs @@ -1,4 +1,4 @@ -using Application.Features.Dtos; +using Application.Features.SharedDtos; namespace Application.Features.ItemTypes; diff --git a/Application/Features/Items/CreateItem/CreateItemCommand.cs b/Application/Features/Items/CreateItem/CreateItemCommand.cs index 7d1c59d..a92fddf 100644 --- a/Application/Features/Items/CreateItem/CreateItemCommand.cs +++ b/Application/Features/Items/CreateItem/CreateItemCommand.cs @@ -48,4 +48,4 @@ await _context return item.Id; } -} \ No newline at end of file +} diff --git a/Application/Features/Items/CreateItem/CreateItemHandler.cs b/Application/Features/Items/CreateItem/CreateItemHandler.cs index f864de2..fcb4925 100644 --- a/Application/Features/Items/CreateItem/CreateItemHandler.cs +++ b/Application/Features/Items/CreateItem/CreateItemHandler.cs @@ -1,5 +1,3 @@ -using Application.Commands; - namespace Application.Features.Items.CreateItem; public class CreateItemHandler diff --git a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs index 086c36b..b90f542 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -1,5 +1,5 @@ using Application.ExternalDeps.EmployeesApi; -using Application.Features.Dtos; +using Application.Features.SharedDtos; using Application.Queries; namespace Application.Features.Items.GetAllItems; diff --git a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs index 505d755..9e13a7e 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs @@ -1,4 +1,4 @@ -using Application.Features.Dtos; +using Application.Features.SharedDtos; namespace Application.Features.Items.GetAllItems; diff --git a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs index e504e01..c2fead4 100644 --- a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs +++ b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs @@ -1,4 +1,4 @@ -using Application.Commands; +using Application.SharedCommands; using Core.Entities; namespace Application.Features.Items.HardDeleteItem; diff --git a/Application/Features/Dtos/ItemTypeDto.cs b/Application/Features/SharedDtos/ItemTypeDto.cs similarity index 72% rename from Application/Features/Dtos/ItemTypeDto.cs rename to Application/Features/SharedDtos/ItemTypeDto.cs index 661277c..875b146 100644 --- a/Application/Features/Dtos/ItemTypeDto.cs +++ b/Application/Features/SharedDtos/ItemTypeDto.cs @@ -1,4 +1,4 @@ -namespace Application.Features.Dtos; +namespace Application.Features.SharedDtos; public class ItemTypeDto { diff --git a/Application/SharedCommands/HardDeleteEntityCommand.cs b/Application/SharedCommands/HardDeleteEntityCommand.cs index 7699f12..52be655 100644 --- a/Application/SharedCommands/HardDeleteEntityCommand.cs +++ b/Application/SharedCommands/HardDeleteEntityCommand.cs @@ -1,7 +1,7 @@ using Core; using Microsoft.EntityFrameworkCore; -namespace Application.Commands; +namespace Application.SharedCommands; public class HardDeleteEntityCommand { diff --git a/Application/SharedCommands/HardDeleteEntityCommandTests.cs b/Application/SharedCommands/HardDeleteEntityCommandTests.cs index 026ea78..1a2cb0a 100644 --- a/Application/SharedCommands/HardDeleteEntityCommandTests.cs +++ b/Application/SharedCommands/HardDeleteEntityCommandTests.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using Xunit; -namespace Application.Commands; +namespace Application.SharedCommands; public class HardDeleteEntityCommandTests { From b8c6a4df9853382b183a636b53a92f8df7aa8b47 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:20:09 +0500 Subject: [PATCH 50/61] refacot: rename ItemTypesResponse to GetAllItemTypesResponse --- Api/Features/ItemTypes/ItemTypesController.cs | 2 +- Api/Features/Items/ItemsController.cs | 1 - .../ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs | 4 ++-- .../GetAllItemTypesResponse.cs} | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) rename Application/Features/ItemTypes/{ItemTypesResponse.cs => GetAllItemTypes/GetAllItemTypesResponse.cs} (53%) diff --git a/Api/Features/ItemTypes/ItemTypesController.cs b/Api/Features/ItemTypes/ItemTypesController.cs index 90a2f9f..7b6575c 100644 --- a/Api/Features/ItemTypes/ItemTypesController.cs +++ b/Api/Features/ItemTypes/ItemTypesController.cs @@ -19,7 +19,7 @@ public class ItemTypesController : ControllerBase /// [RequiresPermission(UserClaimsProvider.CanViewItemsTypes)] [HttpGet] - public async Task GetAllItemTypesAsync( + public async Task GetAllItemTypesAsync( [FromServices] GetAllItemTypesHandler getAllItemTypesHandler ) { diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index 583fa50..f412094 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -1,6 +1,5 @@ using System.ComponentModel.DataAnnotations; using Api.ExternalDeps.EmployeesApi; -using Application.Commands; using Application.Features.Items.CreateItem; using Application.Features.Items.GetAllItems; using Application.Features.Items.HardDeleteItem; diff --git a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs index 5ac499f..fa2732a 100644 --- a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs @@ -14,11 +14,11 @@ AllItemTypesQuery allItemTypesQuery _allItemTypesQuery = allItemTypesQuery; } - public async Task HandleAsync() + public async Task HandleAsync() { var itemTypes = await _allItemTypesQuery.GetAsync(); - return new ItemTypesResponse + return new GetAllItemTypesResponse { ItemTypes = itemTypes .Select(x => new ItemTypeDto diff --git a/Application/Features/ItemTypes/ItemTypesResponse.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs similarity index 53% rename from Application/Features/ItemTypes/ItemTypesResponse.cs rename to Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs index 6405c79..11cbd6b 100644 --- a/Application/Features/ItemTypes/ItemTypesResponse.cs +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs @@ -1,8 +1,8 @@ using Application.Features.SharedDtos; -namespace Application.Features.ItemTypes; +namespace Application.Features.ItemTypes.GetAllItemTypes; -public class ItemTypesResponse +public class GetAllItemTypesResponse { public required List ItemTypes { get; set; } } From 79d0d9f9e77ee5a3a4b17b80b63aec95a86ebd61 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 10:21:41 +0000 Subject: [PATCH 51/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js-client/index.ts b/js-client/index.ts index eba94bb..34df580 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -52,6 +52,10 @@ export interface GetAllItemsResponse { items: ItemDto[]; } +export interface GetAllItemTypesResponse { + itemTypes: ItemTypeDto[]; +} + export interface ItemDto { /** @format int64 */ id: number; @@ -72,10 +76,6 @@ export interface ItemTypeDto { name: string; } -export interface ItemTypesResponse { - itemTypes: ItemTypeDto[]; -} - import type { AxiosInstance, AxiosRequestConfig, @@ -268,7 +268,7 @@ export class Api< * @request GET:/api/item-types */ itemTypesGetAllItemTypes: (params: RequestParams = {}) => - this.request({ + this.request({ path: `/api/item-types`, method: "GET", format: "json", From d6b77e91bf4dc113bd9c6abadc1ed73c4c6f8234 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:22:24 +0500 Subject: [PATCH 52/61] refactor: move SharedCommands to Features --- Api/Features/ItemTypes/ItemTypesController.cs | 1 - .../ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs | 2 +- .../Features/Items/HardDeleteItem/HardDeleteItemHandler.cs | 2 +- .../{ => Features}/SharedCommands/HardDeleteEntityCommand.cs | 2 +- .../SharedCommands/HardDeleteEntityCommandTests.cs | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) rename Application/{ => Features}/SharedCommands/HardDeleteEntityCommand.cs (93%) rename Application/{ => Features}/SharedCommands/HardDeleteEntityCommandTests.cs (98%) diff --git a/Api/Features/ItemTypes/ItemTypesController.cs b/Api/Features/ItemTypes/ItemTypesController.cs index 7b6575c..0998b66 100644 --- a/Api/Features/ItemTypes/ItemTypesController.cs +++ b/Api/Features/ItemTypes/ItemTypesController.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations; -using Application.Features.ItemTypes; using Application.Features.ItemTypes.CreateItemType; using Application.Features.ItemTypes.GetAllItemTypes; using Application.Features.ItemTypes.HardDeleteItemType; diff --git a/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs index 2db0768..517ff74 100644 --- a/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs +++ b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs @@ -1,4 +1,4 @@ -using Application.SharedCommands; +using Application.Features.SharedCommands; using Core.Entities; namespace Application.Features.ItemTypes.HardDeleteItemType; diff --git a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs index c2fead4..eb2dc66 100644 --- a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs +++ b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs @@ -1,4 +1,4 @@ -using Application.SharedCommands; +using Application.Features.SharedCommands; using Core.Entities; namespace Application.Features.Items.HardDeleteItem; diff --git a/Application/SharedCommands/HardDeleteEntityCommand.cs b/Application/Features/SharedCommands/HardDeleteEntityCommand.cs similarity index 93% rename from Application/SharedCommands/HardDeleteEntityCommand.cs rename to Application/Features/SharedCommands/HardDeleteEntityCommand.cs index 52be655..79497e7 100644 --- a/Application/SharedCommands/HardDeleteEntityCommand.cs +++ b/Application/Features/SharedCommands/HardDeleteEntityCommand.cs @@ -1,7 +1,7 @@ using Core; using Microsoft.EntityFrameworkCore; -namespace Application.SharedCommands; +namespace Application.Features.SharedCommands; public class HardDeleteEntityCommand { diff --git a/Application/SharedCommands/HardDeleteEntityCommandTests.cs b/Application/Features/SharedCommands/HardDeleteEntityCommandTests.cs similarity index 98% rename from Application/SharedCommands/HardDeleteEntityCommandTests.cs rename to Application/Features/SharedCommands/HardDeleteEntityCommandTests.cs index 1a2cb0a..780e856 100644 --- a/Application/SharedCommands/HardDeleteEntityCommandTests.cs +++ b/Application/Features/SharedCommands/HardDeleteEntityCommandTests.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using Xunit; -namespace Application.SharedCommands; +namespace Application.Features.SharedCommands; public class HardDeleteEntityCommandTests { From f57f46d1d5482856783f9978737d74d60bf6fad1 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:30:50 +0500 Subject: [PATCH 53/61] refactor: rename queries and move them to Features --- Api/DependencyInjection.cs | 5 ++--- .../ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs | 9 ++++----- .../ItemTypes/GetAllItemTypes/GetAllItemTypesQuery.cs} | 6 +++--- .../Features/Items/GetAllItems/GetAllItemsHandler.cs | 9 ++++----- .../Items/GetAllItems/GetAllItemsQuery.cs} | 6 +++--- 5 files changed, 16 insertions(+), 19 deletions(-) rename Application/{Queries/AllItemTypesQuery.cs => Features/ItemTypes/GetAllItemTypes/GetAllItemTypesQuery.cs} (68%) rename Application/{Queries/AllItemsQuery.cs => Features/Items/GetAllItems/GetAllItemsQuery.cs} (72%) diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 4ceecef..4eb41ea 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -6,7 +6,6 @@ using Application.Features.ItemTypes.CreateItemType; using Application.Features.ItemTypes.GetAllItemTypes; using Application.Features.ItemTypes.HardDeleteItemType; -using Application.Queries; using Microsoft.EntityFrameworkCore; namespace Api; @@ -36,9 +35,9 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs index fa2732a..03a479a 100644 --- a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs @@ -1,22 +1,21 @@ using Application.Features.SharedDtos; -using Application.Queries; namespace Application.Features.ItemTypes.GetAllItemTypes; public class GetAllItemTypesHandler { - private readonly AllItemTypesQuery _allItemTypesQuery; + private readonly GetAllItemTypesQuery _getAllItemTypesQuery; public GetAllItemTypesHandler( - AllItemTypesQuery allItemTypesQuery + GetAllItemTypesQuery getAllItemTypesQuery ) { - _allItemTypesQuery = allItemTypesQuery; + _getAllItemTypesQuery = getAllItemTypesQuery; } public async Task HandleAsync() { - var itemTypes = await _allItemTypesQuery.GetAsync(); + var itemTypes = await _getAllItemTypesQuery.GetAsync(); return new GetAllItemTypesResponse { diff --git a/Application/Queries/AllItemTypesQuery.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesQuery.cs similarity index 68% rename from Application/Queries/AllItemTypesQuery.cs rename to Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesQuery.cs index be19827..6be7079 100644 --- a/Application/Queries/AllItemTypesQuery.cs +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesQuery.cs @@ -1,13 +1,13 @@ using Core.Entities; using Microsoft.EntityFrameworkCore; -namespace Application.Queries; +namespace Application.Features.ItemTypes.GetAllItemTypes; -public class AllItemTypesQuery +public class GetAllItemTypesQuery { private readonly TenantAppDbContext _context; - public AllItemTypesQuery(TenantAppDbContext context) + public GetAllItemTypesQuery(TenantAppDbContext context) { _context = context; } diff --git a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs index b90f542..a17c46b 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -1,23 +1,22 @@ using Application.ExternalDeps.EmployeesApi; using Application.Features.SharedDtos; -using Application.Queries; namespace Application.Features.Items.GetAllItems; public class GetAllItemsHandler { - private readonly AllItemsQuery _allItemsQuery; + private readonly GetAllItemsQuery _getAllItemsQuery; public GetAllItemsHandler( - AllItemsQuery allItemsQuery + GetAllItemsQuery getAllItemsQuery ) { - _allItemsQuery = allItemsQuery; + _getAllItemsQuery = getAllItemsQuery; } public async Task HandleAsync(EmployeesResponse allEmployeesResponse) { - var items = await _allItemsQuery.GetAsync(); + var items = await _getAllItemsQuery.GetAsync(); return new GetAllItemsResponse { diff --git a/Application/Queries/AllItemsQuery.cs b/Application/Features/Items/GetAllItems/GetAllItemsQuery.cs similarity index 72% rename from Application/Queries/AllItemsQuery.cs rename to Application/Features/Items/GetAllItems/GetAllItemsQuery.cs index cc273bb..24c314e 100644 --- a/Application/Queries/AllItemsQuery.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsQuery.cs @@ -1,13 +1,13 @@ using Core.Entities; using Microsoft.EntityFrameworkCore; -namespace Application.Queries; +namespace Application.Features.Items.GetAllItems; -public class AllItemsQuery +public class GetAllItemsQuery { private readonly TenantAppDbContext _context; - public AllItemsQuery(TenantAppDbContext context) + public GetAllItemsQuery(TenantAppDbContext context) { _context = context; } From 1dcc506badcab72d1803c4406d55dfa094be00e5 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 11:10:50 +0000 Subject: [PATCH 54/61] chore(js-client): Update js-client by OpenAPI --- js-client/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js-client/index.ts b/js-client/index.ts index 34df580..777362c 100644 --- a/js-client/index.ts +++ b/js-client/index.ts @@ -253,7 +253,7 @@ export class HttpClient { /** * @title inner-circle-items-api - * @version 1.0.8 + * @version 1.0.9 * @baseUrl http://localhost:6501/ */ export class Api< From b4953798abbabfa6d9ac27c1344f2159d163b272 Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Tue, 10 Feb 2026 16:21:10 +0500 Subject: [PATCH 55/61] chore: remove extra await in ItemTypesController.cs --- Api/Features/ItemTypes/ItemTypesController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Api/Features/ItemTypes/ItemTypesController.cs b/Api/Features/ItemTypes/ItemTypesController.cs index 0998b66..611c658 100644 --- a/Api/Features/ItemTypes/ItemTypesController.cs +++ b/Api/Features/ItemTypes/ItemTypesController.cs @@ -18,11 +18,11 @@ public class ItemTypesController : ControllerBase /// [RequiresPermission(UserClaimsProvider.CanViewItemsTypes)] [HttpGet] - public async Task GetAllItemTypesAsync( + public Task GetAllItemTypesAsync( [FromServices] GetAllItemTypesHandler getAllItemTypesHandler ) { - return await getAllItemTypesHandler.HandleAsync(); + return getAllItemTypesHandler.HandleAsync(); } /// From 32be13769bb3cebcad7f4b595994d7530690403b Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Tue, 10 Feb 2026 16:28:10 +0500 Subject: [PATCH 56/61] chore: reorder DependencyInjection.cs to group by operation, not by type --- Api/DependencyInjection.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 4eb41ea..77356a6 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -33,18 +33,20 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); + + services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + services.AddTransient(); } } From 93ce1b7badecb85cf761bf4336833138106b1ad1 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:43:49 +0500 Subject: [PATCH 57/61] refactor: move SharedCommand and SharedDtos to the root folder of Application --- .../ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs | 2 +- .../ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs | 2 +- .../ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs | 2 +- Application/Features/Items/GetAllItems/GetAllItemsHandler.cs | 2 +- Application/Features/Items/GetAllItems/GetAllItemsResponse.cs | 2 +- .../Features/Items/HardDeleteItem/HardDeleteItemHandler.cs | 2 +- .../{Features => }/SharedCommands/HardDeleteEntityCommand.cs | 2 +- .../SharedCommands/HardDeleteEntityCommandTests.cs | 2 +- Application/{Features => }/SharedDtos/ItemTypeDto.cs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) rename Application/{Features => }/SharedCommands/HardDeleteEntityCommand.cs (93%) rename Application/{Features => }/SharedCommands/HardDeleteEntityCommandTests.cs (98%) rename Application/{Features => }/SharedDtos/ItemTypeDto.cs (72%) diff --git a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs index 03a479a..d7e5d0f 100644 --- a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesHandler.cs @@ -1,4 +1,4 @@ -using Application.Features.SharedDtos; +using Application.SharedDtos; namespace Application.Features.ItemTypes.GetAllItemTypes; diff --git a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs index 11cbd6b..1a25b62 100644 --- a/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs +++ b/Application/Features/ItemTypes/GetAllItemTypes/GetAllItemTypesResponse.cs @@ -1,4 +1,4 @@ -using Application.Features.SharedDtos; +using Application.SharedDtos; namespace Application.Features.ItemTypes.GetAllItemTypes; diff --git a/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs index 517ff74..2db0768 100644 --- a/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs +++ b/Application/Features/ItemTypes/HardDeleteItemType/HardDeleteItemTypeHandler.cs @@ -1,4 +1,4 @@ -using Application.Features.SharedCommands; +using Application.SharedCommands; using Core.Entities; namespace Application.Features.ItemTypes.HardDeleteItemType; diff --git a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs index a17c46b..7856c88 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -1,5 +1,5 @@ using Application.ExternalDeps.EmployeesApi; -using Application.Features.SharedDtos; +using Application.SharedDtos; namespace Application.Features.Items.GetAllItems; diff --git a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs index 9e13a7e..5ba99dd 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsResponse.cs @@ -1,4 +1,4 @@ -using Application.Features.SharedDtos; +using Application.SharedDtos; namespace Application.Features.Items.GetAllItems; diff --git a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs index eb2dc66..c2fead4 100644 --- a/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs +++ b/Application/Features/Items/HardDeleteItem/HardDeleteItemHandler.cs @@ -1,4 +1,4 @@ -using Application.Features.SharedCommands; +using Application.SharedCommands; using Core.Entities; namespace Application.Features.Items.HardDeleteItem; diff --git a/Application/Features/SharedCommands/HardDeleteEntityCommand.cs b/Application/SharedCommands/HardDeleteEntityCommand.cs similarity index 93% rename from Application/Features/SharedCommands/HardDeleteEntityCommand.cs rename to Application/SharedCommands/HardDeleteEntityCommand.cs index 79497e7..52be655 100644 --- a/Application/Features/SharedCommands/HardDeleteEntityCommand.cs +++ b/Application/SharedCommands/HardDeleteEntityCommand.cs @@ -1,7 +1,7 @@ using Core; using Microsoft.EntityFrameworkCore; -namespace Application.Features.SharedCommands; +namespace Application.SharedCommands; public class HardDeleteEntityCommand { diff --git a/Application/Features/SharedCommands/HardDeleteEntityCommandTests.cs b/Application/SharedCommands/HardDeleteEntityCommandTests.cs similarity index 98% rename from Application/Features/SharedCommands/HardDeleteEntityCommandTests.cs rename to Application/SharedCommands/HardDeleteEntityCommandTests.cs index 780e856..1a2cb0a 100644 --- a/Application/Features/SharedCommands/HardDeleteEntityCommandTests.cs +++ b/Application/SharedCommands/HardDeleteEntityCommandTests.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using Xunit; -namespace Application.Features.SharedCommands; +namespace Application.SharedCommands; public class HardDeleteEntityCommandTests { diff --git a/Application/Features/SharedDtos/ItemTypeDto.cs b/Application/SharedDtos/ItemTypeDto.cs similarity index 72% rename from Application/Features/SharedDtos/ItemTypeDto.cs rename to Application/SharedDtos/ItemTypeDto.cs index 875b146..f1d8d2b 100644 --- a/Application/Features/SharedDtos/ItemTypeDto.cs +++ b/Application/SharedDtos/ItemTypeDto.cs @@ -1,4 +1,4 @@ -namespace Application.Features.SharedDtos; +namespace Application.SharedDtos; public class ItemTypeDto { From 42f144b29d4ebc79aea595707fe5d11d17687006 Mon Sep 17 00:00:00 2001 From: Dmitriy Myakotin <75628188+MDI74@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:54:11 +0500 Subject: [PATCH 58/61] fix: remove seed from memory database so that fix flacky --- Application/TenantAppDbContextExtensionsTestsRelated.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/TenantAppDbContextExtensionsTestsRelated.cs b/Application/TenantAppDbContextExtensionsTestsRelated.cs index cd14e65..30a431d 100644 --- a/Application/TenantAppDbContextExtensionsTestsRelated.cs +++ b/Application/TenantAppDbContextExtensionsTestsRelated.cs @@ -13,7 +13,7 @@ public static TenantAppDbContext CteateInMemoryTenantContextForTests() .UseInMemoryDatabase( // we need a unique db name so that tests of the same collection can run in isolation // otherwise they inrefere and see each others data - new Random(100500).Next().ToString(), + new Random().Next().ToString(), // we want to provide as little setup data as possible to check a certain piece of a flow // thus, we don't want to specify all properties of seeded data when it isn't used by the logic // for instance, I need to check that an entity exists by Id, I don't need to setup its required Name property From af8cdfaf2273a7457b42e10ba6bf0b206763fd3e Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Tue, 10 Feb 2026 21:47:40 +0500 Subject: [PATCH 59/61] refactor: introduce IEmployeesApi.cs in Aplication and inject it in GetAllItemsHandler.cs instead of using it in controller layer --- Api/DependencyInjection.cs | 3 ++- Api/ExternalDeps/EmployeesApi/EmployeesApi.cs | 2 +- Api/Features/Items/ItemsController.cs | 8 ++------ Application/ExternalDeps/EmployeesApi/IEmployeesApi.cs | 6 ++++++ .../Features/Items/GetAllItems/GetAllItemsHandler.cs | 7 ++++++- 5 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 Application/ExternalDeps/EmployeesApi/IEmployeesApi.cs diff --git a/Api/DependencyInjection.cs b/Api/DependencyInjection.cs index 77356a6..05cd46c 100644 --- a/Api/DependencyInjection.cs +++ b/Api/DependencyInjection.cs @@ -1,5 +1,6 @@ using Api.ExternalDeps.EmployeesApi; using Application; +using Application.ExternalDeps.EmployeesApi; using Application.Features.Items.CreateItem; using Application.Features.Items.GetAllItems; using Application.Features.Items.HardDeleteItem; @@ -31,7 +32,7 @@ public static void AddApplication(this IServiceCollection services, IConfigurati services.Configure(configuration.GetSection(nameof(ExternalDepsUrls))); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs b/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs index 65d2efe..f20af56 100644 --- a/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs +++ b/Api/ExternalDeps/EmployeesApi/EmployeesApi.cs @@ -4,7 +4,7 @@ namespace Api.ExternalDeps.EmployeesApi; -public class EmployeesApi +public class EmployeesApi : IEmployeesApi { private readonly ExternalDepsUrls _externalDepsUrls; private readonly AuthenticationOptions _authenticationOptions; diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index f412094..635f794 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations; -using Api.ExternalDeps.EmployeesApi; using Application.Features.Items.CreateItem; using Application.Features.Items.GetAllItems; using Application.Features.Items.HardDeleteItem; @@ -20,13 +19,10 @@ public class ItemsController : ControllerBase [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] public async Task GetAllItemsAsync( - [FromServices] GetAllItemsHandler getAllItemsHandler, - [FromServices] EmployeesApi employeesApi + [FromServices] GetAllItemsHandler getAllItemsHandler ) { - var allEmployeesResponse = await employeesApi.GetAllEmployeesAsync(); - - return await getAllItemsHandler.HandleAsync(allEmployeesResponse); + return await getAllItemsHandler.HandleAsync(); } /// diff --git a/Application/ExternalDeps/EmployeesApi/IEmployeesApi.cs b/Application/ExternalDeps/EmployeesApi/IEmployeesApi.cs new file mode 100644 index 0000000..ef0eeed --- /dev/null +++ b/Application/ExternalDeps/EmployeesApi/IEmployeesApi.cs @@ -0,0 +1,6 @@ +namespace Application.ExternalDeps.EmployeesApi; + +public interface IEmployeesApi +{ + Task GetAllEmployeesAsync(); +} diff --git a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs index 7856c88..722f066 100644 --- a/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs +++ b/Application/Features/Items/GetAllItems/GetAllItemsHandler.cs @@ -5,17 +5,22 @@ namespace Application.Features.Items.GetAllItems; public class GetAllItemsHandler { + private readonly IEmployeesApi _employeesApi; private readonly GetAllItemsQuery _getAllItemsQuery; public GetAllItemsHandler( + IEmployeesApi employeesApi, GetAllItemsQuery getAllItemsQuery ) { + _employeesApi = employeesApi; _getAllItemsQuery = getAllItemsQuery; } - public async Task HandleAsync(EmployeesResponse allEmployeesResponse) + public async Task HandleAsync() { + var allEmployeesResponse = await _employeesApi.GetAllEmployeesAsync(); + var items = await _getAllItemsQuery.GetAsync(); return new GetAllItemsResponse From 0030a4e8362196eff1bb0ce50d7829cacbcc89f5 Mon Sep 17 00:00:00 2001 From: Aleksandr Shinkarev Date: Tue, 10 Feb 2026 21:49:12 +0500 Subject: [PATCH 60/61] chore: remove extra await in ItemsController.cs --- Api/Features/Items/ItemsController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Api/Features/Items/ItemsController.cs b/Api/Features/Items/ItemsController.cs index 635f794..a89ee36 100644 --- a/Api/Features/Items/ItemsController.cs +++ b/Api/Features/Items/ItemsController.cs @@ -18,11 +18,11 @@ public class ItemsController : ControllerBase /// [RequiresPermission(UserClaimsProvider.CanViewItems)] [HttpGet] - public async Task GetAllItemsAsync( + public Task GetAllItemsAsync( [FromServices] GetAllItemsHandler getAllItemsHandler ) { - return await getAllItemsHandler.HandleAsync(); + return getAllItemsHandler.HandleAsync(); } /// From bfbb3eb755dc20d188c70142dae77332f0471b20 Mon Sep 17 00:00:00 2001 From: Workflow Action Date: Tue, 10 Feb 2026 16:50:27 +0000 Subject: [PATCH 61/61] docs(readme): bring test coverage score up to date --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 21f2bbb..b8a63d7 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # inner-circle-items-api -[![coverage](https://img.shields.io/badge/e2e_coverage-82.76%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/units_coverage-16.21%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) -[![coverage](https://img.shields.io/badge/full_coverage-90.27%25-forestgreen)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/e2e_coverage-82.79%25-olivedrab)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/units_coverage-16.18%25-crimson)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) +[![coverage](https://img.shields.io/badge/full_coverage-90.29%25-forestgreen)](https://github.com/TourmalineCore/inner-circle-items-api/actions/workflows/calculate-tests-coverage-on-pull-request.yml) This repo contains Inner Circle Items API.