113 lines
3.9 KiB
C#
113 lines
3.9 KiB
C#
using AVSCartonShipmentVerifier.DTOs;
|
|
using AVSCartonShipmentVerifier.Repositories;
|
|
|
|
namespace AVSCartonShipmentVerifier.Services;
|
|
|
|
public sealed class ShipmentVerificationService(
|
|
ICartonVerificationRepository repository,
|
|
IScanHistoryStore historyStore,
|
|
ILogger<ShipmentVerificationService> logger) : IShipmentVerificationService
|
|
{
|
|
private readonly ICartonVerificationRepository _repository = repository;
|
|
private readonly IScanHistoryStore _historyStore = historyStore;
|
|
private readonly ILogger<ShipmentVerificationService> _logger = logger;
|
|
|
|
public async Task<VerificationResultDto> VerifyQrAsync(string rawQrValue, CancellationToken cancellationToken = default)
|
|
{
|
|
var parseResult = TryParseQr(rawQrValue);
|
|
if (!parseResult.IsValid)
|
|
{
|
|
return BuildFailure(parseResult.ErrorMessage);
|
|
}
|
|
|
|
var nowUtc = DateTime.UtcNow;
|
|
bool exists;
|
|
try
|
|
{
|
|
exists = await _repository.UniqueNumberExistsAsync(parseResult.UniqueNumber, cancellationToken);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
_logger.LogError(exception, "Verification lookup failed for unique number {UniqueNumber}.", parseResult.UniqueNumber);
|
|
return BuildFailure("Unable to verify QR at the moment. Please try again.");
|
|
}
|
|
|
|
if (!exists)
|
|
{
|
|
var missingResult = new VerificationResultDto
|
|
{
|
|
ModelNumber = parseResult.ModelNumber,
|
|
UniqueNumber = parseResult.UniqueNumber,
|
|
RawQrValue = rawQrValue,
|
|
ExistsInSystem = false,
|
|
ShipmentMarked = false,
|
|
Message = "Shipment not completed. Unique number was not found.",
|
|
ProcessedAtUtc = nowUtc
|
|
};
|
|
|
|
_historyStore.Add(ToScannedRecord(missingResult));
|
|
return missingResult;
|
|
}
|
|
|
|
var result = new VerificationResultDto
|
|
{
|
|
ModelNumber = parseResult.ModelNumber,
|
|
UniqueNumber = parseResult.UniqueNumber,
|
|
RawQrValue = rawQrValue,
|
|
ExistsInSystem = true,
|
|
ShipmentMarked = true,
|
|
Message = "Record found in carton verification log.",
|
|
ProcessedAtUtc = nowUtc
|
|
};
|
|
|
|
_historyStore.Add(ToScannedRecord(result));
|
|
return result;
|
|
}
|
|
|
|
private static (bool IsValid, string ModelNumber, string UniqueNumber, string ErrorMessage) TryParseQr(string rawQrValue)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(rawQrValue))
|
|
{
|
|
return (false, string.Empty, string.Empty, "QR value is required.");
|
|
}
|
|
|
|
if (!rawQrValue.Contains(';'))
|
|
{
|
|
return (false, string.Empty, string.Empty, "Invalid QR format. Missing ';' separator. Use modelnumber;uniquenumber.");
|
|
}
|
|
|
|
var parts = rawQrValue.Split(';', StringSplitOptions.TrimEntries);
|
|
if (parts.Length != 2)
|
|
{
|
|
return (false, string.Empty, string.Empty, "Invalid QR format. Use modelnumber;uniquenumber.");
|
|
}
|
|
|
|
var modelNumber = parts[0];
|
|
var uniqueNumber = parts[1];
|
|
if (string.IsNullOrWhiteSpace(uniqueNumber))
|
|
{
|
|
return (false, modelNumber, string.Empty, "Invalid QR format. Unique number is missing after ';'.");
|
|
}
|
|
|
|
return (true, modelNumber, uniqueNumber, string.Empty);
|
|
}
|
|
|
|
private static VerificationResultDto BuildFailure(string message) => new()
|
|
{
|
|
Message = message,
|
|
ExistsInSystem = false,
|
|
ShipmentMarked = false,
|
|
ProcessedAtUtc = DateTime.UtcNow
|
|
};
|
|
|
|
private static ScannedRecordDto ToScannedRecord(VerificationResultDto result) => new()
|
|
{
|
|
ModelNumber = result.ModelNumber,
|
|
UniqueNumber = result.UniqueNumber,
|
|
ExistsInSystem = result.ExistsInSystem,
|
|
ShipmentMarked = result.ShipmentMarked,
|
|
ProcessedAtUtc = result.ProcessedAtUtc
|
|
};
|
|
}
|
|
|