- GeradoresService: cada tipo passa a ser um IGenerator (NIF, NIPC, NISS, CC, passaporte, IBAN, NIB, cartões, referência MB, pessoa, telefone, código postal, email, matrícula, EAN, UUID) registado em GeneratorRegistry; remove DAL/EF - GeradoresWS: minimal APIs em /api/v1 com OpenAPI + Scalar e health check - UnitTest: testes de ida e volta, valores conhecidos, detecção e API - geradoresfe: UI construída a partir dos metadados da API, validador livre, exportação CSV/JSON/TXT, nginx com API_UPSTREAM configurável - Docker, docker-compose e Jenkinsfile actualizados Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
2.1 KiB
C#
54 lines
2.1 KiB
C#
using GeradoresService.Core;
|
|
|
|
namespace GeradoresService.Generators.Outros;
|
|
|
|
/// <summary>Códigos de barras EAN-13 / EAN-8 (GS1). Controlo: pesos 3,1,3,1… a partir da direita.</summary>
|
|
public sealed class EanGenerator : GeneratorBase
|
|
{
|
|
public override string Id => "ean";
|
|
public override string Name => "EAN / Código de barras";
|
|
public override string Category => Categories.Outros;
|
|
public override string Description => "Códigos EAN-13 e EAN-8 com dígito de controlo GS1.";
|
|
|
|
public override IReadOnlyList<GeneratorOption> Options =>
|
|
[
|
|
Option("tipo", "Tipo", "ean13", ("ean13", "EAN-13"), ("ean8", "EAN-8")),
|
|
Option("prefixo", "Prefixo GS1", "560", ("560", "560 — Portugal"), ("qualquer", "Qualquer")),
|
|
];
|
|
|
|
public override GeneratedItem Generate(GeneratorContext context)
|
|
{
|
|
var length = context.Option(Options[0]) == "ean8" ? 8 : 13;
|
|
var prefix = context.Option(Options[1]) == "560" ? "560" : context.Digits(3);
|
|
var body = prefix + context.Digits(length - 1 - prefix.Length);
|
|
return new GeneratedItem(body + CheckDigit(body));
|
|
}
|
|
|
|
public static int CheckDigit(string payload)
|
|
{
|
|
var sum = 0;
|
|
for (var i = 0; i < payload.Length; i++)
|
|
{
|
|
var weight = (payload.Length - i) % 2 == 1 ? 3 : 1;
|
|
sum += (payload[i] - '0') * weight;
|
|
}
|
|
return (10 - sum % 10) % 10;
|
|
}
|
|
|
|
public override ValidationResult Validate(string value)
|
|
{
|
|
var ean = Checksums.Clean(value);
|
|
if (ean.Length is not (8 or 13) || !Checksums.AllDigits(ean))
|
|
return ValidationResult.WrongFormat("Um EAN tem 8 ou 13 dígitos.");
|
|
|
|
var expected = CheckDigit(ean[..^1]);
|
|
var details = new List<string> { $"Tipo: EAN-{ean.Length}" };
|
|
if (ean.Length == 13 && ean.StartsWith("560"))
|
|
details.Add("Prefixo 560: Portugal");
|
|
|
|
return expected == ean[^1] - '0'
|
|
? ValidationResult.Valid(ean, $"EAN-{ean.Length} válido.", details)
|
|
: ValidationResult.BadChecksum($"Dígito de controlo inválido: esperado {expected}, encontrado {ean[^1]}.", details);
|
|
}
|
|
}
|