using System; using System.Threading.Tasks; using System.Text; using Compliance.Domain.Models; using Compliance.DTOs; namespace Compliance.Services.ValidationRules { public class ConsumptionValidationRule : IValidationRule { private const string RULE_NAME = "Consumption Validation"; private const string TOTAL_ERROR = "Total amount doesn't match the sum of TUSD and TE amounts"; private const string READING_PERIOD_ERROR = "Invalid reading period"; private const string CONSUMPTION_ERROR = "Consumption amount doesn't match readings difference"; private const string PEAK_OFFPEAK_ERROR = "Total consumption doesn't match sum of peak and off-peak consumption"; private const decimal TOLERANCE = 0.01m; private const int MAX_BILLING_DAYS = 33; // According to ANEEL Resolution public int Priority => 2; // Run after basic validation public async Task ValidateAsync( BillComplianceRequest request, DistributorInformation distributorInfo, Client clientInfo) { var isValid = true; var message = new StringBuilder(); // Validate reading period var billingDays = (request.CurrentReadingDate - request.PreviousReadingDate).Days; if (billingDays <= 0 || billingDays > MAX_BILLING_DAYS) { isValid = false; message.AppendLine(READING_PERIOD_ERROR); } // Validate consumption calculation var calculatedConsumption = request.CurrentReading - request.PreviousReading; if (Math.Abs(calculatedConsumption - request.ConsumptionAmount) > TOLERANCE) { isValid = false; message.AppendLine(CONSUMPTION_ERROR); } // Validate peak/off-peak total if (Math.Abs(request.ConsumptionAmount - (request.PeakConsumption + request.OffPeakConsumption)) > TOLERANCE) { isValid = false; message.AppendLine(PEAK_OFFPEAK_ERROR); } // Validate total amount matches sum of components var expectedTotal = request.TUSDAmount + request.TEAmount + request.PowerFactorAdjustment + request.PublicLightingAmount + request.FlagAmount; if (Math.Abs(request.TotalAmount - expectedTotal) > TOLERANCE) { isValid = false; message.AppendLine(TOTAL_ERROR); } return await Task.FromResult(new ValidationResult { IsValid = isValid, RuleName = RULE_NAME, Message = message.ToString().TrimEnd() }); } } }