faturas_4docs/Compliance/Services/ValidationRules/MunicipalTaxValidationRule.cs

98 lines
3.6 KiB
C#

using System;
using System.Threading.Tasks;
using System.Text;
using Compliance.Domain.Models;
using Compliance.DTOs;
using Compliance.Infrastructure.Repositories;
namespace Compliance.Services.ValidationRules
{
public class MunicipalTaxValidationRule(IDistributorRepository distributorRepository) : IValidationRule
{
private readonly IDistributorRepository _distributorRepository = distributorRepository;
private const string RULE_NAME = "Municipal Tax Validation";
private const string AMOUNT_ERROR = "Municipal tax amount doesn't match the expected value";
private const string BASE_ERROR = "Municipal tax base calculation is incorrect";
private const string EXEMPT_ERROR = "Municipal tax charged to exempt consumer";
private const decimal TOLERANCE = 0.01m;
public int Priority => 7; // Run after ICMS validation
public async Task<ValidationResult> ValidateAsync(
BillComplianceRequest request,
DistributorInformation distributorInfo,
Client clientInfo)
{
var taxInfo = await _distributorRepository.GetMunicipalTaxInformationAsync(
request.DistributorName,
request.Municipality,
request.Month) ?? throw new InvalidOperationException("Municipal tax information not found");
var isValid = true;
var message = new StringBuilder();
// Check if consumer is exempt
if (taxInfo.ExemptGroups.Contains(request.ConsumerGroup.ToLower()))
{
if (request.MunicipalTaxAmount != 0)
{
isValid = false;
message.AppendLine(EXEMPT_ERROR);
}
return new ValidationResult
{
IsValid = isValid,
RuleName = RULE_NAME,
Message = message.ToString().TrimEnd()
};
}
// Get applicable rate
var rate = taxInfo.SpecialRates.TryGetValue(request.ConsumerGroup.ToLower(), out var specialRate)
? specialRate
: taxInfo.BaseRate;
// Calculate base and expected tax
var baseAmount = CalculateTaxBase(request, taxInfo);
var expectedTax = baseAmount * (rate / 100m);
if (Math.Abs(request.MunicipalTaxBase - baseAmount) > TOLERANCE)
{
isValid = false;
message.AppendLine($"{BASE_ERROR}. Expected: {baseAmount:F2}, Found: {request.MunicipalTaxBase:F2}");
}
if (Math.Abs(request.MunicipalTaxAmount - expectedTax) > TOLERANCE)
{
isValid = false;
message.AppendLine($"{AMOUNT_ERROR}. Expected: {expectedTax:F2}, Found: {request.MunicipalTaxAmount:F2}");
}
return new ValidationResult
{
IsValid = isValid,
RuleName = RULE_NAME,
Message = message.ToString().TrimEnd()
};
}
private static decimal CalculateTaxBase(BillComplianceRequest request, MunicipalTaxInformation taxInfo)
{
var baseAmount = request.TUSDAmount +
request.TEAmount +
request.PowerFactorAdjustment +
request.FlagAmount;
if (taxInfo.ApplyToICMS)
{
baseAmount += request.ICMSAmount;
}
if (taxInfo.ApplyToPublicLighting)
{
baseAmount += request.PublicLightingAmount;
}
return baseAmount;
}
}
}