From 54dd38cfd62d1c955347994b2332d8486d47112d Mon Sep 17 00:00:00 2001 From: Oscar Morales Date: Thu, 31 Jul 2025 19:07:22 -0600 Subject: [PATCH] Add TagType CRUD --- .../Controllers/TagTypeController.cs | 154 ++++++++++++++++++ .../Inventory/Request/TagTypeRequest.cs | 44 +++++ .../Contracts/ITagTypeProvider.cs | 59 +++++++ .../Core.Inventory.Provider.csproj | 2 +- .../Providers/Inventory/TagTypeProvider.cs | 149 +++++++++++++++++ .../ServiceCollectionExtensions.cs | 3 + 6 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 Core.Inventory.DAL.API/Controllers/TagTypeController.cs create mode 100644 Core.Inventory.Domain/Contexts/Inventory/Request/TagTypeRequest.cs create mode 100644 Core.Inventory.Provider/Contracts/ITagTypeProvider.cs create mode 100644 Core.Inventory.Provider/Providers/Inventory/TagTypeProvider.cs diff --git a/Core.Inventory.DAL.API/Controllers/TagTypeController.cs b/Core.Inventory.DAL.API/Controllers/TagTypeController.cs new file mode 100644 index 0000000..77a3f13 --- /dev/null +++ b/Core.Inventory.DAL.API/Controllers/TagTypeController.cs @@ -0,0 +1,154 @@ +using Asp.Versioning; +using Core.Adapters.Lib; +using Core.Blueprint.Logging; +using Core.Blueprint.Mongo; +using Core.Inventory.Domain.Contexts.Inventory.Request; +using Core.Inventory.Provider.Contracts; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Inventory.DAL.API.Controllers +{ + /// + /// Handles all requests for TagType authentication. + /// + [ApiVersion(MimeTypes.ApplicationVersion)] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces(MimeTypes.ApplicationJson)] + [Consumes(MimeTypes.ApplicationJson)] + [ApiController] + [AllowAnonymous] + public class TagTypeController(ITagTypeProvider service) : ControllerBase + { + /// + /// Gets all the TagTypes. + /// + /// The found entities. + /// The tagTypes found. + /// The tagTypes not found error. + /// The service internal error. + [HttpGet] + [Consumes(MimeTypes.ApplicationJson)] + [Produces(MimeTypes.ApplicationJson)] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAllTagTypesAsync(CancellationToken cancellationToken) + { + var result = await service.GetAllTagTypes(cancellationToken).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Gets all the TagTypes by TagType identifiers. + /// + /// The list of TagType identifiers. + /// The found entities. + /// The TagTypes found. + /// The TagTypes not found error. + /// The service internal error. + [HttpPost] + [Route("GetTagTypeList")] + [Consumes(MimeTypes.ApplicationJson)] + [Produces(MimeTypes.ApplicationJson)] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAllTagTypesByList([FromBody] string[] tagTypes, CancellationToken cancellationToken) + { + if (tagTypes == null || !tagTypes.Any()) + { + return BadRequest("TagType identifiers are required."); + } + + var result = await service.GetAllTagTypesByList(tagTypes, cancellationToken).ConfigureAwait(false); + return Ok(result); + } + + + /// + /// Gets the TagType by identifier. + /// + /// The TagType identifier. + /// The found entity. + /// The TagType found. + /// The TagType not found error. + /// The service internal error. + [HttpGet] + [Route("{id}")] + [Consumes(MimeTypes.ApplicationJson)] + [Produces(MimeTypes.ApplicationJson)] + [ProducesResponseType(typeof(TagTypeAdapter), StatusCodes.Status200OK)] + public async Task GetTagTypeByIdAsync([FromRoute] string id, CancellationToken cancellationToken) + { + var result = await service.GetTagTypeById(id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + return NotFound("Entity not found"); + } + + return Ok(result); + } + + /// + /// Creates a new TagType. + /// + /// The TagType to be added. + /// The created entity. + /// The TagType created. + /// The TagType could not be created. + /// The service internal e|ror. + [HttpPost] + [ProducesResponseType(typeof(TagTypeAdapter), StatusCodes.Status201Created)] + public async Task CreateTagTypeAsync([FromBody] TagTypeRequest newTagType, CancellationToken cancellationToken) + { + var result = await service.CreateTagType(newTagType, cancellationToken).ConfigureAwait(false); + return Created("CreatedWithIdAsync", result); + } + + /// + /// Updates a full TagType by identifier. + /// + /// The TagType to update. + /// The TagType identifier. + /// The updated entity. + /// The TagType updated. + /// The TagType not found. + /// The TagType could not be updated. + /// The service internal error. + [HttpPut] + [Route("{id}")] + [Consumes(MimeTypes.ApplicationJson)] + [Produces(MimeTypes.ApplicationJson)] + [ProducesResponseType(typeof(TagTypeAdapter), StatusCodes.Status200OK)] + public async Task UpdateTagTypeAsync([FromRoute] string id, TagTypeAdapter entity, CancellationToken cancellationToken) + { + if (id != entity.Id?.ToString()) + { + return BadRequest("TagType ID mismatch"); + } + + var result = await service.UpdateTagType(entity, cancellationToken).ConfigureAwait(false); + + return Ok(result); + } + + /// + /// Changes the status of the TagType. + /// + /// The TagType identifier. + /// The new status of the TagType. + /// The updated entity. + /// The TagType updates. + /// The TagType not found. + /// The TagType could not be deleted. + /// The service internal error. + [HttpPatch] + [Route("{id}/{newStatus}/ChangeStatus")] + [Consumes(MimeTypes.ApplicationJson)] + [Produces(MimeTypes.ApplicationJson)] + [ProducesResponseType(typeof(TagTypeAdapter), StatusCodes.Status200OK)] + public async Task ChangeTagTypeStatus([FromRoute] string id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) + { + var result = await service.ChangeTagTypeStatus(id, newStatus, cancellationToken).ConfigureAwait(false); + return Ok(result); + } + } +} diff --git a/Core.Inventory.Domain/Contexts/Inventory/Request/TagTypeRequest.cs b/Core.Inventory.Domain/Contexts/Inventory/Request/TagTypeRequest.cs new file mode 100644 index 0000000..874bd76 --- /dev/null +++ b/Core.Inventory.Domain/Contexts/Inventory/Request/TagTypeRequest.cs @@ -0,0 +1,44 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using System.Text.Json.Serialization; + +namespace Core.Inventory.Domain.Contexts.Inventory.Request +{ + /// + /// Data transfer object (DTO) for adding tagType. + /// + public class TagTypeRequest + { + /// + /// Gets or sets the tenantId of the tagType. + /// + [BsonElement("tenantId")] + [BsonRepresentation(BsonType.String)] + [JsonPropertyName("tenantId")] + public string TenantId { get; set; } = null!; + + /// + /// Gets or sets the typeName of the tagType. + /// + [BsonElement("typeName")] + [BsonRepresentation(BsonType.String)] + [JsonPropertyName("typeName")] + public string TypeName { get; set; } = null!; + + /// + /// Gets or sets the level of the tagType. + /// + [BsonElement("level")] + [BsonRepresentation(BsonType.Int32)] + [JsonPropertyName("level")] + public int Level { get; set; } + + /// + /// Gets or sets the parentTypeId of the tagType. + /// + [BsonElement("parentTypeId")] + [BsonRepresentation(BsonType.String)] + [JsonPropertyName("parentTypeId")] + public string ParentTypeId { get; set; } = null!; + } +} diff --git a/Core.Inventory.Provider/Contracts/ITagTypeProvider.cs b/Core.Inventory.Provider/Contracts/ITagTypeProvider.cs new file mode 100644 index 0000000..9c0b567 --- /dev/null +++ b/Core.Inventory.Provider/Contracts/ITagTypeProvider.cs @@ -0,0 +1,59 @@ +using Core.Adapters.Lib; +using Core.Blueprint.Mongo; +using Core.Inventory.Domain.Contexts.Inventory.Request; + +namespace Core.Inventory.Provider.Contracts +{ + public interface ITagTypeProvider + { + /// + /// Creates a new TagType. + /// + /// The TagType to be created. + /// A representing + /// the asynchronous execution of the service. + ValueTask CreateTagType(TagTypeRequest newTagType, CancellationToken cancellationToken); + + /// + /// Gets an TagType by identifier. + /// + /// The TagType identifier. + /// A representing + /// the asynchronous execution of the service. + ValueTask GetTagTypeById(string _id, CancellationToken cancellationToken); + + /// + /// Gets all the tagTypes. + /// + /// A representing + /// the asynchronous execution of the service. + ValueTask> GetAllTagTypes(CancellationToken cancellationToken); + + /// + /// Gets all the tagTypes by tagTypes identifier list. + /// + /// The list of tagTypes identifiers. + /// A representing + /// the asynchronous execution of the service. + ValueTask> GetAllTagTypesByList(string[] TagTypes, CancellationToken cancellationToken); + + /// + /// Changes the status of the tagType. + /// + /// The tagType identifier. + /// The new status of the tagType. + /// The updated entity. + /// A representing + /// the asynchronous execution of the service. + ValueTask ChangeTagTypeStatus(string id, StatusEnum newStatus, CancellationToken cancellationToken); + + /// + /// Updates a TagType by id. + /// + /// The TagType to be updated. + /// The TagType identifier. + /// A representing + /// the asynchronous execution of the service. + ValueTask UpdateTagType(TagTypeAdapter entity, CancellationToken cancellationToken); + } +} diff --git a/Core.Inventory.Provider/Core.Inventory.Provider.csproj b/Core.Inventory.Provider/Core.Inventory.Provider.csproj index d04076e..963ec5e 100644 --- a/Core.Inventory.Provider/Core.Inventory.Provider.csproj +++ b/Core.Inventory.Provider/Core.Inventory.Provider.csproj @@ -7,7 +7,7 @@ - + diff --git a/Core.Inventory.Provider/Providers/Inventory/TagTypeProvider.cs b/Core.Inventory.Provider/Providers/Inventory/TagTypeProvider.cs new file mode 100644 index 0000000..2d765b5 --- /dev/null +++ b/Core.Inventory.Provider/Providers/Inventory/TagTypeProvider.cs @@ -0,0 +1,149 @@ +using Core.Adapters.Lib; +using Core.Blueprint.Mongo; +using Core.Blueprint.Redis; +using Core.Blueprint.Redis.Helpers; +using Core.Inventory.Domain.Contexts.Inventory.Request; +using Core.Inventory.Provider.Contracts; +using Mapster; +using Microsoft.Extensions.Options; +using MongoDB.Driver; + +namespace Core.Inventory.Provider.Providers.Inventory +{ + /// + /// Handles all services and business rules related to . + /// + public class TagTypeProvider : ITagTypeProvider + { + private readonly CollectionRepository repository; + private readonly CacheSettings cacheSettings; + private readonly IRedisCacheProvider cacheProvider; + + public TagTypeProvider(CollectionRepository repository, + IRedisCacheProvider cacheProvider, + IOptions cacheSettings) + { + this.repository = repository; + this.repository.CollectionInitialization(); + this.cacheSettings = cacheSettings.Value; + this.cacheProvider = cacheProvider; + } + + /// + /// Creates a new TagType. + /// + /// The TagType to be created. + /// A representing + /// the asynchronous execution of the service. + public async ValueTask CreateTagType(TagTypeRequest newTagType, CancellationToken cancellationToken) + { + var tagTypeCollection = newTagType.Adapt(); + + await repository.InsertOneAsync(tagTypeCollection); + + return tagTypeCollection; + } + + /// + /// Gets an TagType by identifier. + /// + /// The TagType identifier. + /// A representing + /// the asynchronous execution of the service.0 + public async ValueTask GetTagTypeById(string _id, CancellationToken cancellationToken) + { + var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetTagTypeById", _id); + var cachedData = await cacheProvider.GetAsync(cacheKey); + + if (cachedData is not null) { return cachedData; } + + var tagType = await repository.FindByIdAsync(_id); + + await cacheProvider.SetAsync(cacheKey, tagType); + + return tagType; + } + + /// + /// Gets all the TagTypes. + /// + /// A representing + /// the asynchronous execution of the service. + public async ValueTask> GetAllTagTypes(CancellationToken cancellationToken) + { + var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetTagTypes"); + var cachedData = await cacheProvider.GetAsync>(cacheKey) ?? []; + + if (cachedData.Any()) return cachedData; + + var tagTypes = await repository.AsQueryable(); + + await cacheProvider.SetAsync(cacheKey, tagTypes); + + return tagTypes; + } + + /// + /// Gets all the TagTypes by TagTypes identifier list. + /// + /// The list of TagTypes identifiers. + /// A representing + /// the asynchronous execution of the service. + public async ValueTask> GetAllTagTypesByList(string[] tagTypes, CancellationToken cancellationToken) + { + var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllTagTypesByList", tagTypes); + + var cachedData = await cacheProvider.GetAsync>(cacheKey) ?? []; + + if (cachedData.Any()) return cachedData; + + var builder = Builders.Filter; + var filters = new List>(); + + if (tagTypes != null || !tagTypes.Any()) + { + filters.Add(builder.In(x => x._Id, tagTypes)); + } + + var finalFilter = filters.Any() ? builder.And(filters) : builder.Empty; + + var tagTypesList = await repository.FilterByMongoFilterAsync(finalFilter); + + await cacheProvider.SetAsync(cacheKey, tagTypesList); + + return tagTypesList; + } + + + /// + /// Changes the status of the TagType. + /// + /// The TagType identifier. + /// The new status of the TagType. + /// A representing + /// the asynchronous execution of the service. + public async ValueTask ChangeTagTypeStatus(string id, StatusEnum newStatus, CancellationToken cancellationToken) + { + var entity = await repository.FindByIdAsync(id); + entity.Status = newStatus; + + await repository.ReplaceOneAsync(entity); + + return entity; + } + + /// + /// Updates a TagType by id. + /// + /// The TagType to be updated. + /// The TagType identifier. + /// A representing + /// the asynchronous execution of the service. + public async ValueTask UpdateTagType(TagTypeAdapter entity, CancellationToken cancellationToken) + { + await repository.ReplaceOneAsync(entity); + + return entity; + } + } +} diff --git a/Core.Inventory.Provider/ServiceCollectionExtensions.cs b/Core.Inventory.Provider/ServiceCollectionExtensions.cs index c6af67e..4c408a2 100644 --- a/Core.Inventory.Provider/ServiceCollectionExtensions.cs +++ b/Core.Inventory.Provider/ServiceCollectionExtensions.cs @@ -17,6 +17,9 @@ namespace Core.Inventory.Provider services.AddScoped(); services.AddScoped>(); + services.AddScoped(); + services.AddScoped>(); + return services; }