feat(core): normalize sales document origin types
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (pull_request) Successful in 6m51s
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (pull_request) Successful in 6m51s
closes #62
This commit is contained in:
parent
4d5045718f
commit
3b4f664ae9
@ -29,6 +29,9 @@ namespace Core.Services
|
||||
if (request.Coverage is null || request.Coverage.Count == 0)
|
||||
throw new InvalidOperationException("Debe incluir coverage.");
|
||||
|
||||
foreach (var detail in request.Details)
|
||||
ValidateDetail(detail);
|
||||
|
||||
var netAmount = request.Details.Sum(x => x.NetAmount);
|
||||
var taxAmount = request.Details.Sum(x => x.TaxAmount);
|
||||
var totalAmount = request.Details.Sum(x => x.TotalAmount);
|
||||
@ -65,9 +68,9 @@ namespace Core.Services
|
||||
PhSSalesDocumentDetails = request.Details.Select(x => new ESalesDocumentDetail
|
||||
{
|
||||
LineNumber = x.LineNumber,
|
||||
OriginType = x.OriginType.ToString(),
|
||||
OriginId = x.OriginId,
|
||||
QuoteDetailId = x.QuoteDetailId,
|
||||
OriginType = x.OriginType.ToStorageCode(),
|
||||
OriginId = ResolveOriginId(x),
|
||||
QuoteDetailId = ResolveQuoteDetailId(x),
|
||||
ProductId = x.ProductId,
|
||||
Description = x.Description.Trim(),
|
||||
Quantity = x.Quantity,
|
||||
@ -111,5 +114,49 @@ namespace Core.Services
|
||||
|
||||
return _salesDocumentRepository.GetDtoByIdAsync(id);
|
||||
}
|
||||
private static void ValidateDetail(SalesDocumentCreateDetailRequest detail)
|
||||
{
|
||||
if (detail.LineNumber <= 0)
|
||||
throw new ArgumentException("El número de línea del detail debe ser mayor a cero.", nameof(detail.LineNumber));
|
||||
|
||||
if (!Enum.IsDefined(typeof(SalesDocumentOriginType), detail.OriginType))
|
||||
throw new ArgumentException("El tipo de origen del detail no es válido.", nameof(detail.OriginType));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.Description))
|
||||
throw new ArgumentException("La descripción del detail es obligatoria.", nameof(detail.Description));
|
||||
|
||||
if (detail.Quantity <= 0)
|
||||
throw new ArgumentException("La cantidad del detail debe ser mayor a cero.", nameof(detail.Quantity));
|
||||
|
||||
var hasOriginId = detail.OriginId.HasValue && detail.OriginId.Value > 0;
|
||||
var hasQuoteDetailId = detail.QuoteDetailId.HasValue && detail.QuoteDetailId.Value > 0;
|
||||
|
||||
if (detail.OriginType != SalesDocumentOriginType.Manual && !hasOriginId && !hasQuoteDetailId)
|
||||
throw new ArgumentException("Debe informar OriginId o QuoteDetailId para trazabilidad del origen.", nameof(detail.OriginId));
|
||||
|
||||
if (detail.OriginType == SalesDocumentOriginType.QuoteDetail && !hasQuoteDetailId && !hasOriginId)
|
||||
throw new ArgumentException("Debe informar QuoteDetailId u OriginId para líneas originadas en presupuesto.", nameof(detail.QuoteDetailId));
|
||||
}
|
||||
|
||||
private static int? ResolveOriginId(SalesDocumentCreateDetailRequest detail)
|
||||
{
|
||||
if (detail.OriginId.HasValue && detail.OriginId.Value > 0)
|
||||
return detail.OriginId;
|
||||
|
||||
return detail.OriginType == SalesDocumentOriginType.QuoteDetail
|
||||
? detail.QuoteDetailId
|
||||
: null;
|
||||
}
|
||||
|
||||
private static int? ResolveQuoteDetailId(SalesDocumentCreateDetailRequest detail)
|
||||
{
|
||||
if (detail.QuoteDetailId.HasValue && detail.QuoteDetailId.Value > 0)
|
||||
return detail.QuoteDetailId;
|
||||
|
||||
return detail.OriginType == SalesDocumentOriginType.QuoteDetail
|
||||
? detail.OriginId
|
||||
: null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ namespace Domain.Constants
|
||||
Manual = 1,
|
||||
QuoteDetail = 2,
|
||||
Adjustment = 3,
|
||||
Capita = 4
|
||||
Capita = 4,
|
||||
DeliveryNote = 5
|
||||
}
|
||||
}
|
||||
|
||||
18
Domain/Constants/SalesDocumentOriginTypeExtensions.cs
Normal file
18
Domain/Constants/SalesDocumentOriginTypeExtensions.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace Domain.Constants
|
||||
{
|
||||
public static class SalesDocumentOriginTypeExtensions
|
||||
{
|
||||
public static string ToStorageCode(this SalesDocumentOriginType originType)
|
||||
{
|
||||
return originType switch
|
||||
{
|
||||
SalesDocumentOriginType.Manual => "MANUAL",
|
||||
SalesDocumentOriginType.QuoteDetail => "QUOTE",
|
||||
SalesDocumentOriginType.Adjustment => "ADJUSTMENT",
|
||||
SalesDocumentOriginType.Capita => "CAPITA",
|
||||
SalesDocumentOriginType.DeliveryNote => "DELIVERY_NOTE",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(originType), originType, "Tipo de origen de documento de venta no soportado.")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,11 @@
|
||||
using Domain.Constants;
|
||||
|
||||
namespace Domain.Dtos.Sales
|
||||
{
|
||||
public class SalesDocumentCreateDetailRequest
|
||||
{
|
||||
public int LineNumber { get; set; }
|
||||
public int OriginType { get; set; }
|
||||
public SalesDocumentOriginType OriginType { get; set; }
|
||||
public int? OriginId { get; set; }
|
||||
public int? QuoteDetailId { get; set; }
|
||||
public int? ProductId { get; set; }
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Domain.Entities
|
||||
public int LineNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Origen logico del item: Manual, QuoteDetail, Adjustment u otro valor definido por Domain/Core.
|
||||
/// Origen logico del item. Persistir como codigo semantico: MANUAL, QUOTE, DELIVERY_NOTE, CAPITA o ADJUSTMENT.
|
||||
/// </summary>
|
||||
public string OriginType { get; set; } = null!;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user