Skip to content

Commit

Permalink
added getter queries for the Invoice API
Browse files Browse the repository at this point in the history
  • Loading branch information
suxrobGM committed Oct 25, 2023
1 parent a81cc9e commit 5ae8776
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ namespace Logistics.Application.Tenant.Commands;

public class CreateInvoiceCommand : IRequest<ResponseResult>
{
public string? CompanyName { get; set; }
public string? CompanyAddress { get; set; }
public string CustomerId { get; set; } = default!;
public string LoadId { get; set; } = default!;
public PaymentMethod PaymentMethod { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ namespace Logistics.Application.Tenant.Commands;
public class UpdateInvoiceCommand : IRequest<ResponseResult>
{
public string Id { get; set; } = default!;
public string? CompanyName { get; set; }
public string? CompanyAddress { get; set; }
public string CustomerId { get; set; } = default!;
public string LoadId { get; set; } = default!;
public PaymentMethod PaymentMethod { get; set; }
public decimal PaymentAmount { get; set; }

public PaymentMethod? Method { get; set; }
public decimal? Amount { get; set; }
public PaymentStatus? Status { get; set; }
public PaymentFor? PaymentFor { get; set; }
public string? Comment { get; set; }
public PaymentMethod? PaymentMethod { get; set; }
public decimal? PaymentAmount { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Logistics.Application.Tenant.Commands;

internal sealed class UpdateInvoiceHandler : RequestHandler<UpdatePaymentCommand, ResponseResult>
internal sealed class UpdateInvoiceHandler : RequestHandler<UpdateInvoiceCommand, ResponseResult>
{
private readonly ITenantRepository _tenantRepository;

Expand All @@ -10,35 +10,23 @@ public UpdateInvoiceHandler(ITenantRepository tenantRepository)
}

protected override async Task<ResponseResult> HandleValidated(
UpdatePaymentCommand req, CancellationToken cancellationToken)
UpdateInvoiceCommand req, CancellationToken cancellationToken)
{
var payment = await _tenantRepository.GetAsync<Payment>(req.Id);
var invoice = await _tenantRepository.GetAsync<Invoice>(req.Id);

if (payment is null)
return ResponseResult.CreateError($"Could not find a payment with ID '{req.Id}'");

if (req.PaymentFor.HasValue && payment.PaymentFor != req.PaymentFor)
{
payment.PaymentFor = req.PaymentFor.Value;
}
if (req.Method.HasValue && payment.Method != req.Method)
{
payment.Method = req.Method.Value;
}
if (req.Status.HasValue && payment.Status != req.Status)
{
payment.SetStatus(req.Status.Value);
}
if (req.Amount.HasValue && payment.Amount != req.Amount)
if (invoice is null)
return ResponseResult.CreateError($"Could not find an invoice with ID '{req.Id}'");

if (req.PaymentMethod.HasValue && invoice.Payment.Method != req.PaymentMethod)
{
payment.Amount = req.Amount.Value;
invoice.Payment.Method = req.PaymentMethod.Value;
}
if (!string.IsNullOrEmpty(req.Comment) && payment.Comment != req.Comment)
if (req.PaymentAmount.HasValue && invoice.Payment.Amount != req.PaymentAmount)
{
payment.Comment = req.Comment;
invoice.Payment.Amount = req.PaymentAmount.Value;
}

_tenantRepository.Update(payment);
_tenantRepository.Update(invoice);
await _tenantRepository.UnitOfWork.CommitAsync();
return ResponseResult.CreateSuccess();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public static InvoiceDto ToDto(this Invoice entity)
{
return new InvoiceDto
{
CustomerId = entity.CustomerId,
Customer = entity.Customer.ToDto(),
LoadId = entity.LoadId,
Payment = entity.Payment.ToDto()
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Logistics.Application.Tenant.Mappers;
using Logistics.Shared.Models;

namespace Logistics.Application.Tenant.Queries;

internal sealed class GetInvoiceByIdHandler : RequestHandler<GetInvoiceByIdQuery, ResponseResult<InvoiceDto>>
{
private readonly ITenantRepository _tenantRepository;

public GetInvoiceByIdHandler(ITenantRepository tenantRepository)
{
_tenantRepository = tenantRepository;
}

protected override async Task<ResponseResult<InvoiceDto>> HandleValidated(
GetInvoiceByIdQuery req, CancellationToken cancellationToken)
{
var invoiceEntity = await _tenantRepository.GetAsync<Invoice>(req.Id);

if (invoiceEntity is null)
return ResponseResult<InvoiceDto>.CreateError($"Could not find an invoice with ID {req.Id}");

var invoiceDto = invoiceEntity.ToDto();
return ResponseResult<InvoiceDto>.CreateSuccess(invoiceDto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Logistics.Shared.Models;
using MediatR;

namespace Logistics.Application.Tenant.Queries;

public class GetInvoiceByIdQuery : IRequest<ResponseResult<InvoiceDto>>
{
public string? Id { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using FluentValidation;

namespace Logistics.Application.Tenant.Queries;

internal sealed class GetInvoiceByIdValidator : AbstractValidator<GetInvoiceByIdQuery>
{
public GetInvoiceByIdValidator()
{
RuleFor(i => i.Id).NotEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Logistics.Application.Tenant.Mappers;
using Logistics.Shared.Models;

namespace Logistics.Application.Tenant.Queries;

internal sealed class GetInvoicesHandler : RequestHandler<GetInvoicesQuery, PagedResponseResult<InvoiceDto>>
{
private readonly ITenantRepository _tenantRepository;

public GetInvoicesHandler(ITenantRepository tenantRepository)
{
_tenantRepository = tenantRepository;
}

protected override Task<PagedResponseResult<InvoiceDto>> HandleValidated(
GetInvoicesQuery req,
CancellationToken cancellationToken)
{
var totalItems = _tenantRepository.Query<Invoice>().Count();
var specification = new FilterInvoicesByInterval(req.OrderBy, req.StartDate, req.EndDate, req.Descending);

var invoicesDto = _tenantRepository.ApplySpecification(specification)
.Skip((req.Page - 1) * req.PageSize)
.Take(req.PageSize)
.Select(i => i.ToDto())
.ToArray();

var totalPages = (int)Math.Ceiling(totalItems / (double)req.PageSize);
return Task.FromResult(PagedResponseResult<InvoiceDto>.Create(invoicesDto, totalItems, totalPages));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Logistics.Shared.Models;
using MediatR;

namespace Logistics.Application.Tenant.Queries;

public class GetInvoicesQuery : PagedIntervalQuery, IRequest<PagedResponseResult<InvoiceDto>>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using FluentValidation;

namespace Logistics.Application.Tenant.Queries;

internal sealed class GetInvoicesValidator : AbstractValidator<GetInvoicesQuery>
{
public GetInvoicesValidator()
{
RuleFor(i => i.StartDate).LessThan(i => i.EndDate);
RuleFor(i => i.Page)
.GreaterThanOrEqualTo(0);

RuleFor(i => i.PageSize)
.GreaterThanOrEqualTo(1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Linq.Expressions;
using Logistics.Domain.Entities;

namespace Logistics.Domain.Specifications;

public class FilterInvoicesByInterval : BaseSpecification<Invoice>
{
public FilterInvoicesByInterval(string? orderProperty, DateTime? startPeriod, DateTime endPeriod, bool descending)
{
Descending = descending;
OrderBy = InitOrderBy(orderProperty);

Criteria = i =>
i.Created >= startPeriod && i.Created <= endPeriod;
}

private static Expression<Func<Invoice, object>> InitOrderBy(string? propertyName)
{
propertyName = propertyName?.ToLower();
return propertyName switch
{
"paymentamount" => i => i.Payment.Amount,
_ => i => i.Created
};
}
}
8 changes: 4 additions & 4 deletions src/Server/Logistics.API/Controllers/InvoiceController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ public InvoicesController(IMediator mediator)
}

[HttpGet("{id}")]
[ProducesResponseType(typeof(ResponseResult<PaymentDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ResponseResult<InvoiceDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ResponseResult), StatusCodes.Status400BadRequest)]
[Authorize(Policy = Permissions.Invoices.View)]
public async Task<IActionResult> GetById(string id)
{
var result = await _mediator.Send(new GetPaymentByIdQuery {Id = id});
var result = await _mediator.Send(new GetInvoiceByIdQuery {Id = id});

if (result.IsSuccess)
return Ok(result);
Expand All @@ -28,10 +28,10 @@ public async Task<IActionResult> GetById(string id)
}

[HttpGet]
[ProducesResponseType(typeof(PagedResponseResult<PaymentDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(PagedResponseResult<InvoiceDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ResponseResult), StatusCodes.Status400BadRequest)]
[Authorize(Policy = Permissions.Invoices.View)]
public async Task<IActionResult> GetList([FromQuery] GetPaymentsQuery query)
public async Task<IActionResult> GetList([FromQuery] GetInvoicesQuery query)
{
var result = await _mediator.Send(query);

Expand Down
2 changes: 1 addition & 1 deletion src/Shared/Logistics.Shared.Models/InvoiceDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ public class InvoiceDto
public string? CompanyName { get; set; }
public string? CompanyAddress { get; set; }
public string LoadId { get; set; } = default!;
public string CustomerId { get; set; } = default!;
public CustomerDto Customer { get; set; } = default!;
public PaymentDto Payment { get; set; } = default!;
}

0 comments on commit 5ae8776

Please sign in to comment.