phronCare/Models/Repositories/PhSSalesDocumentRepository.cs
leandro 1fcd31080b
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (pull_request) Successful in 9m37s
feat(sales): refine sales document creation from delivery notes
close #68
2026-06-06 13:54:41 -03:00

364 lines
15 KiB
C#

using Domain.Dtos.Sales;
using Domain.Entities;
using Domain.Generics;
using Microsoft.EntityFrameworkCore;
using Models.Helpers;
using Models.Interfaces;
using Models.Models;
namespace Models.Repositories
{
public class PhSSalesDocumentRepository(PhronCareOperationsHubContext context) : IPhSSalesDocumentRepository
{
private readonly PhronCareOperationsHubContext _context = context;
public async Task<PagedResult<SalesDocumentSummaryDto>> SearchAsync(
int? customerId,
string? customerText,
int? quoteId,
int? documentType,
int? status,
DateTime? issueDateFrom,
DateTime? issueDateTo,
int page = 1,
int pageSize = 50)
{
page = page <= 0 ? 1 : page;
pageSize = pageSize <= 0 ? 50 : pageSize;
var query = _context.PhSSalesDocuments
.Include(x => x.Customer)
.Include(x => x.BillToCustomer)
.AsNoTracking()
.AsQueryable();
if (customerId.HasValue && customerId.Value > 0)
{
query = query.Where(x => x.CustomerId == customerId.Value || x.BillToCustomerId == customerId.Value);
}
if (!string.IsNullOrWhiteSpace(customerText))
{
var normalizedCustomerText = customerText.Trim();
query = query.Where(x =>
(x.Customer.Name ?? string.Empty).Contains(normalizedCustomerText) ||
(x.BillToCustomer.Name ?? string.Empty).Contains(normalizedCustomerText));
}
if (quoteId.HasValue && quoteId.Value > 0)
{
query = query.Where(x => x.QuoteId == quoteId.Value);
}
if (documentType.HasValue && documentType.Value > 0)
{
query = query.Where(x => x.DocumentType == documentType.Value);
}
if (status.HasValue && status.Value > 0)
{
query = query.Where(x => x.Status == status.Value);
}
if (issueDateFrom.HasValue)
{
query = query.Where(x => x.IssueDate >= issueDateFrom.Value);
}
if (issueDateTo.HasValue)
{
query = query.Where(x => x.IssueDate <= issueDateTo.Value);
}
var totalItems = await query.CountAsync();
var items = await query
.OrderByDescending(x => x.IssueDate)
.ThenByDescending(x => x.Id)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(x => new SalesDocumentSummaryDto
{
Id = x.Id,
InternalDocumentNumber = x.InternalDocumentNumber,
DocumentType = x.DocumentType,
Status = x.Status,
QuoteId = x.QuoteId,
CustomerId = x.CustomerId,
CustomerName = x.Customer.Name ?? string.Empty,
BillToCustomerId = x.BillToCustomerId,
BillToCustomerName = x.BillToCustomer.Name ?? string.Empty,
IssueDate = x.IssueDate,
Currency = x.Currency,
NetAmount = x.NetAmount,
TaxAmount = x.TaxAmount,
TotalAmount = x.TotalAmount,
PeriodFrom = x.PeriodFrom,
PeriodTo = x.PeriodTo,
Createdat = x.Createdat,
Modifiedat = x.Modifiedat
})
.ToListAsync();
return new PagedResult<SalesDocumentSummaryDto>
{
Items = items,
TotalItems = totalItems,
Page = page,
PageSize = pageSize
};
}
public async Task<ESalesDocument> CreateAsync(ESalesDocument entity)
{
var mapped = EntityMapper.MapEntity<ESalesDocument, PhSSalesDocument>(entity);
await _context.PhSSalesDocuments.AddAsync(mapped);
await _context.SaveChangesAsync();
return EntityMapper.MapEntity<PhSSalesDocument, ESalesDocument>(mapped);
}
public async Task<PagedResult<SalesDocumentDeliveryNoteCandidateDto>> SearchDeliveryNoteCandidatesAsync(
int? customerId,
string? customerText,
string? deliveryNoteNumber,
int? quoteId,
DateTime? issueDateFrom,
DateTime? issueDateTo,
int page = 1,
int pageSize = 50)
{
page = page <= 0 ? 1 : page;
pageSize = pageSize <= 0 ? 50 : pageSize;
var query = _context.PhSDeliveryNotes
.Include(x => x.Customer)
.Include(x => x.Quote)
.Include(x => x.PhSDeliveryNoteDetails)
.ThenInclude(d => d.QuoteDetail)
.AsNoTracking()
.Where(x => x.Status == "Emitido" && x.SalesinvoiceId == null)
.AsQueryable();
if (customerId.HasValue && customerId.Value > 0)
query = query.Where(x => x.CustomerId == customerId.Value);
else if (!string.IsNullOrWhiteSpace(customerText))
query = query.Where(x => (x.Customer.Name ?? string.Empty).Contains(customerText.Trim()));
if (!string.IsNullOrWhiteSpace(deliveryNoteNumber))
query = query.Where(x => x.Deliverynotenumber.Contains(deliveryNoteNumber.Trim()));
if (quoteId.HasValue && quoteId.Value > 0)
query = query.Where(x => x.QuoteId == quoteId.Value);
if (issueDateFrom.HasValue)
query = query.Where(x => x.Issuedate >= issueDateFrom.Value);
if (issueDateTo.HasValue)
query = query.Where(x => x.Issuedate <= issueDateTo.Value);
var totalItems = await query.CountAsync();
var items = await query
.OrderByDescending(x => x.Issuedate)
.ThenByDescending(x => x.Id)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(x => new SalesDocumentDeliveryNoteCandidateDto
{
Id = x.Id,
DeliveryNoteNumber = x.Deliverynotenumber,
QuoteId = x.QuoteId,
QuoteNumber = x.Quote != null ? x.Quote.Quotenumber : null,
IssueDate = x.Issuedate,
CustomerId = x.CustomerId,
CustomerName = x.Customer.Name ?? string.Empty,
Status = x.Status,
ItemCount = x.PhSDeliveryNoteDetails.Count,
ApprovedAmount = x.PhSDeliveryNoteDetails.Sum(d => d.QuoteDetail != null
? (d.QuoteDetail.Approvedamount ?? ((d.QuoteDetail.Approvedunitprice ?? d.QuoteDetail.Unitprice) * d.Quantity))
: 0),
ExtraInfoJson = x.ExtrainfoJson
})
.ToListAsync();
return new PagedResult<SalesDocumentDeliveryNoteCandidateDto>
{
Items = items,
TotalItems = totalItems,
Page = page,
PageSize = pageSize
};
}
public async Task<List<DeliveryNoteDto>> GetDeliveryNotesForSalesDocumentAsync(IReadOnlyCollection<int> deliveryNoteIds)
{
var ids = deliveryNoteIds.Distinct().ToList();
var entities = await _context.PhSDeliveryNotes
.Include(x => x.Customer)
.Include(x => x.Quote)
.Include(x => x.PhSDeliveryNoteDetails)
.ThenInclude(d => d.QuoteDetail)
.AsNoTracking()
.Where(x => ids.Contains(x.Id))
.OrderBy(x => x.Issuedate)
.ThenBy(x => x.Id)
.ToListAsync();
return entities.Select(MapDeliveryNoteDto).ToList();
}
public async Task<ESalesDocument> CreateFromDeliveryNotesAsync(ESalesDocument entity, IReadOnlyCollection<int> deliveryNoteIds)
{
await using var transaction = await _context.Database.BeginTransactionAsync();
var mapped = EntityMapper.MapEntity<ESalesDocument, PhSSalesDocument>(entity);
await _context.PhSSalesDocuments.AddAsync(mapped);
await _context.SaveChangesAsync();
var ids = deliveryNoteIds.Distinct().ToList();
var deliveryNotes = await _context.PhSDeliveryNotes
.Where(x => ids.Contains(x.Id))
.ToListAsync();
foreach (var deliveryNote in deliveryNotes)
{
deliveryNote.SalesinvoiceId = mapped.Id;
deliveryNote.Modifiedat = DateTime.Now;
}
await _context.SaveChangesAsync();
await transaction.CommitAsync();
return EntityMapper.MapEntity<PhSSalesDocument, ESalesDocument>(mapped);
}
private static DeliveryNoteDto MapDeliveryNoteDto(PhSDeliveryNote source)
{
return new DeliveryNoteDto
{
Id = source.Id,
DeliveryNoteNumber = source.Deliverynotenumber,
CustomerName = source.Customer?.Name ?? string.Empty,
QuoteId = source.QuoteId,
QuoteNumber = source.Quote?.Quotenumber,
SalesInvoiceId = source.SalesinvoiceId,
IssueDate = source.Issuedate,
CustomerId = source.CustomerId,
Status = source.Status,
Observations = source.Observations,
ExtraInfoJson = source.ExtrainfoJson,
PrintCount = source.Printcount,
CreatedAt = source.Createdat,
ModifiedAt = source.Modifiedat,
Items = source.PhSDeliveryNoteDetails
.OrderBy(d => d.LineNumber)
.ThenBy(d => d.Id)
.Select(d => new DeliveryNoteItemDto
{
Id = d.Id,
DeliverynoteId = d.DeliverynoteId,
LineNumber = d.LineNumber,
OriginType = d.OriginType,
OriginId = d.OriginId,
QuoteDetailId = d.QuoteDetailId,
Description = d.Description ?? string.Empty,
Quantity = d.Quantity,
ProductId = d.QuoteDetail?.ProductId,
ApprovedUnitPrice = d.QuoteDetail?.Approvedunitprice,
ApprovedAmount = d.QuoteDetail?.Approvedamount,
OriginalUnitPrice = d.QuoteDetail?.Unitprice,
Notes = d.Notes,
Createdat = d.Createdat,
Modifiedat = d.Modifiedat
})
.ToList()
};
}
public async Task<SalesDocumentDto?> GetDtoByIdAsync(int id)
{
var entity = await _context.PhSSalesDocuments
.Include(x => x.Customer)
.Include(x => x.BillToCustomer)
.Include(x => x.PhSSalesDocumentDetails)
.Include(x => x.PhSSalesDocumentCoverages)
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id);
if (entity == null)
return null;
return new SalesDocumentDto
{
Id = entity.Id,
FormseriesId = entity.FormseriesId,
InternalSequenceNumber = entity.InternalSequenceNumber,
InternalDocumentNumber = entity.InternalDocumentNumber,
DocumentType = entity.DocumentType,
FiscalVoucherType = entity.FiscalVoucherType,
FiscalVoucherLetter = entity.FiscalVoucherLetter,
Status = entity.Status,
QuoteId = entity.QuoteId,
CustomerId = entity.CustomerId,
CustomerName = entity.Customer?.Name ?? string.Empty,
BillToCustomerId = entity.BillToCustomerId,
BillToCustomerName = entity.BillToCustomer?.Name ?? string.Empty,
IssueDate = entity.IssueDate,
Currency = entity.Currency,
ExchangeRate = entity.ExchangeRate,
NetAmount = entity.NetAmount,
TaxAmount = entity.TaxAmount,
TotalAmount = entity.TotalAmount,
Observations = entity.Observations,
ExtraInfoJson = entity.ExtraInfoJson,
PeriodFrom = entity.PeriodFrom,
PeriodTo = entity.PeriodTo,
Createdat = entity.Createdat,
Modifiedat = entity.Modifiedat,
Details = entity.PhSSalesDocumentDetails.Select(x => new SalesDocumentDetailDto
{
Id = x.Id,
SalesDocumentId = x.SalesdocumentId,
LineNumber = x.LineNumber,
OriginType = x.OriginType,
OriginId = x.OriginId,
QuoteDetailId = x.QuoteDetailId,
ProductId = x.ProductId,
Description = x.Description,
Quantity = x.Quantity,
AuthorizedUnitPrice = x.AuthorizedUnitPrice,
AuthorizedAmount = x.AuthorizedAmount,
BilledPercentage = x.BilledPercentage,
UnitPrice = x.UnitPrice,
NetAmount = x.NetAmount,
TaxAmount = x.TaxAmount,
TotalAmount = x.TotalAmount,
OriginSnapshotJson = x.OriginSnapshotJson,
Createdat = x.Createdat,
Modifiedat = x.Modifiedat
}).ToList(),
Coverage = entity.PhSSalesDocumentCoverages.Select(x => new SalesDocumentCoverageDto
{
Id = x.Id,
SalesDocumentId = x.SalesdocumentId,
SalesDocumentDetailId = x.SalesdocumentdetailId,
QuoteId = x.QuoteId,
QuoteDetailId = x.QuoteDetailId,
CoverageType = x.CoverageType,
CoveragePercentage = x.CoveragePercentage,
CoverageAmount = x.CoverageAmount,
PeriodFrom = x.PeriodFrom,
PeriodTo = x.PeriodTo,
Notes = x.Notes,
Createdat = x.Createdat,
Modifiedat = x.Modifiedat
}).ToList()
};
}
}
}