feat: adjustments and refinements

This commit is contained in:
Jean Gatto
2023-08-13 11:23:20 -03:00
parent 64da5de6dd
commit c16e397e07
11 changed files with 94 additions and 18 deletions
+28 -1
View File
@@ -1,6 +1,33 @@
@baseUrl = http://localhost:5072/api
###
# @name createCustomers
POST {{baseUrl}}/customers HTTP/1.1
accept: application/json
accept-encoding: gzip, deflate, br
content-type: application/json
{
"firstName": "John",
"lastName": "Doe",
"gender": "male",
"email": "john_doe@gmail.com",
"dateOfBirth": "1990-01-01"
}
###
# @name getCustomers
GET {{baseUrl}}/customers HTTP/1.1
content-type: application/json
accept: application/json
###
# @prompt customerId
# @name getCustomerById
GET {{baseUrl}}/customers/{{customerId}} HTTP/1.1
accept: application/json
###
# @prompt customerId
# @name deleteCustomers
DELETE {{baseUrl}}/customers/{{customerId}} HTTP/1.1
accept: application/json
@@ -7,7 +7,10 @@ namespace Shop.Core.SharedKernel;
/// Represents a repository that allows write-only operations on entities.
/// </summary>
/// <typeparam name="TEntity">The type of entity.</typeparam>
public interface IWriteOnlyRepository<TEntity> : IDisposable where TEntity : IEntity<Guid>
/// <typeparam name="TKey">The type of the entity's key.</typeparam>
public interface IWriteOnlyRepository<TEntity, TKey> : IDisposable
where TEntity : IEntity<TKey>
where TKey : IEquatable<TKey>
{
/// <summary>
/// Adds a new entity to the repository.
@@ -32,5 +35,5 @@ public interface IWriteOnlyRepository<TEntity> : IDisposable where TEntity : IEn
/// </summary>
/// <param name="id">The ID of the entity to retrieve.</param>
/// <returns>The retrieved entity.</returns>
Task<TEntity> GetByIdAsync(Guid id);
Task<TEntity> GetByIdAsync(TKey id);
}
@@ -5,7 +5,7 @@ using Shop.Domain.ValueObjects;
namespace Shop.Domain.Entities.CustomerAggregate;
public interface ICustomerWriteOnlyRepository : IWriteOnlyRepository<Customer>
public interface ICustomerWriteOnlyRepository : IWriteOnlyRepository<Customer, Guid>
{
/// <summary>
/// Checks if a customer with the specified email already exists asynchronously.
@@ -6,8 +6,14 @@ using Shop.Infrastructure.Data.Context;
namespace Shop.Infrastructure.Data.Repositories.Common;
internal abstract class BaseWriteOnlyRepository<TEntity> : IWriteOnlyRepository<TEntity>
where TEntity : class, IEntity<Guid>
/// <summary>
/// Base class for write-only repositories.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="Tkey">The type of the entity's key.</typeparam>
internal abstract class BaseWriteOnlyRepository<TEntity, Tkey> : IWriteOnlyRepository<TEntity, Tkey>
where TEntity : class, IEntity<Tkey>
where Tkey : IEquatable<Tkey>
{
private readonly DbSet<TEntity> _dbSet;
protected readonly WriteDbContext Context;
@@ -27,8 +33,8 @@ internal abstract class BaseWriteOnlyRepository<TEntity> : IWriteOnlyRepository<
public void Remove(TEntity entity) =>
_dbSet.Remove(entity);
public async Task<TEntity> GetByIdAsync(Guid id) =>
await _dbSet.AsNoTrackingWithIdentityResolution().FirstOrDefaultAsync(entity => entity.Id == id);
public async Task<TEntity> GetByIdAsync(Tkey id) =>
await _dbSet.AsNoTrackingWithIdentityResolution().FirstOrDefaultAsync(entity => entity.Id.Equals(id));
#region IDisposable
@@ -8,7 +8,7 @@ using Shop.Infrastructure.Data.Repositories.Common;
namespace Shop.Infrastructure.Data.Repositories;
internal class CustomerWriteOnlyRepository : BaseWriteOnlyRepository<Customer>, ICustomerWriteOnlyRepository
internal class CustomerWriteOnlyRepository : BaseWriteOnlyRepository<Customer, Guid>, ICustomerWriteOnlyRepository
{
public CustomerWriteOnlyRepository(WriteDbContext context) : base(context)
{
@@ -25,6 +25,10 @@ public class CustomersController : ControllerBase
public CustomersController(IMediator mediator) =>
_mediator = mediator;
////////////////////////
// POST: /api/customers
////////////////////////
/// <summary>
/// Register a new customer.
/// </summary>
@@ -41,6 +45,10 @@ public class CustomersController : ControllerBase
public async Task<IActionResult> Create([FromBody][Required] CreateCustomerCommand command) =>
(await _mediator.Send(command)).ToActionResult();
///////////////////////
// PUT: /api/customers
//////////////////////
/// <summary>
/// Updates an existing client.
/// </summary>
@@ -59,6 +67,10 @@ public class CustomersController : ControllerBase
public async Task<IActionResult> Update([FromBody][Required] UpdateCustomerCommand command) =>
(await _mediator.Send(command)).ToActionResult();
//////////////////////////////
// DELETE: /api/customers/{id}
//////////////////////////////
/// <summary>
/// Deletes the client by Id.
/// </summary>
@@ -77,6 +89,10 @@ public class CustomersController : ControllerBase
public async Task<IActionResult> Delete([Required] Guid id) =>
(await _mediator.Send(new DeleteCustomerCommand(id))).ToActionResult();
///////////////////////////
// GET: /api/customers/{id}
///////////////////////////
/// <summary>
/// Gets the client by Id.
/// </summary>
@@ -95,6 +111,10 @@ public class CustomersController : ControllerBase
public async Task<IActionResult> GetById([Required] Guid id) =>
(await _mediator.Send(new GetCustomerByIdQuery(id))).ToActionResult();
//////////////////////
// GET: /api/customers
//////////////////////
/// <summary>
/// Gets a list of all customers.
/// </summary>
@@ -7,12 +7,15 @@ namespace Shop.Query.Abstractions;
/// Represents a read-only repository interface.
/// </summary>
/// <typeparam name="TQueryModel">The type of the query model.</typeparam>
public interface IReadOnlyRepository<TQueryModel> where TQueryModel : IQueryModel<Guid>
/// <typeparam name="TKey">The type of the key for the query model.</typeparam>
public interface IReadOnlyRepository<TQueryModel, TKey>
where TQueryModel : IQueryModel<TKey>
where TKey : IEquatable<TKey>
{
/// <summary>
/// Gets the query model by its ID asynchronously.
/// </summary>
/// <param name="id">The ID of the query model.</param>
/// <returns>The task representing the asynchronous operation, returning the query model.</returns>
Task<TQueryModel> GetByIdAsync(Guid id);
Task<TQueryModel> GetByIdAsync(TKey id);
}
@@ -49,7 +49,7 @@ public class GetCustomerByIdQueryHandler : IRequestHandler<GetCustomerByIdQuery,
// If the customer is null, returns a result indicating that no customer was found.
// Otherwise, returns a successful result with the customer.
return customer == null
? Result<CustomerQueryModel>.NotFound($"No customer found by ID: {request.Id}")
? Result<CustomerQueryModel>.NotFound($"No customer found by Id: {request.Id}")
: Result<CustomerQueryModel>.Success(customer);
}
}
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Shop.Query.Abstractions;
@@ -5,7 +6,7 @@ using Shop.Query.QueriesModel;
namespace Shop.Query.Data.Repositories.Abstractions;
public interface ICustomerReadOnlyRepository : IReadOnlyRepository<CustomerQueryModel>
public interface ICustomerReadOnlyRepository : IReadOnlyRepository<CustomerQueryModel, Guid>
{
Task<IEnumerable<CustomerQueryModel>> GetAllAsync();
}
@@ -5,14 +5,29 @@ using Shop.Query.Abstractions;
namespace Shop.Query.Data.Repositories;
internal abstract class BaseReadOnlyRepository<TQueryModel> : IReadOnlyRepository<TQueryModel>
where TQueryModel : IQueryModel<Guid>
/// <summary>
/// Base repository class for read-only operations.
/// </summary>
/// <typeparam name="TQueryModel">The type of the query model.</typeparam>
/// <typeparam name="Tkey">The type of the key.</typeparam>
internal abstract class BaseReadOnlyRepository<TQueryModel, Tkey> : IReadOnlyRepository<TQueryModel, Tkey>
where TQueryModel : IQueryModel<Tkey>
where Tkey : IEquatable<Tkey>
{
protected readonly IMongoCollection<TQueryModel> Collection;
/// <summary>
/// Initializes a new instance of the <see cref="BaseReadOnlyRepository{TQueryModel, Tkey}"/> class.
/// </summary>
/// <param name="context">The read database context.</param>
protected BaseReadOnlyRepository(IReadDbContext context) =>
Collection = context.GetCollection<TQueryModel>();
public async Task<TQueryModel> GetByIdAsync(Guid id) =>
await Collection.Find(queryModel => queryModel.Id == id).FirstOrDefaultAsync();
/// <summary>
/// Gets a query model by its id.
/// </summary>
/// <param name="id">The id of the query model.</param>
/// <returns>The query model.</returns>
public async Task<TQueryModel> GetByIdAsync(Tkey id) =>
await Collection.Find(queryModel => queryModel.Id.Equals(id)).FirstOrDefaultAsync();
}
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MongoDB.Driver;
@@ -7,7 +8,7 @@ using Shop.Query.QueriesModel;
namespace Shop.Query.Data.Repositories;
internal class CustomerReadOnlyRepository : BaseReadOnlyRepository<CustomerQueryModel>, ICustomerReadOnlyRepository
internal class CustomerReadOnlyRepository : BaseReadOnlyRepository<CustomerQueryModel, Guid>, ICustomerReadOnlyRepository
{
public CustomerReadOnlyRepository(IReadDbContext readDbContext) : base(readDbContext) { }