Refactor EKÁER mapping: unify company info, doc updates
- Introduced ICompanyInfoBase for standardized company/partner data; refactored PartnerBase and interfaces to implement it - Replaced EkaerMappingOptions with EkaerCompanyInfo; updated all usages, constructors, and tests - Refactored EKÁER mapping logic to use ICompanyInfoBase; improved normalization and address handling - Added regex/validation for plate numbers and country codes; new error codes - Added Currency to PartnerBase; updated grids to display it - Updated ProductDto doc for GTIN/VTSZ data model issue - Enabled validation in CargoTruck grid - Added DMODEL topic docs: TOPIC_CODES.md, DATAMODEL_ISSUES.md, README.md - Removed obsolete files and updated settings.local.json - General code and doc improvements for maintainability
This commit is contained in:
parent
b3c82d6ad2
commit
d2bdf7e4eb
|
|
@ -252,6 +252,8 @@ public interface IMgProductDto : IEntityInt
|
||||||
string ShortDescription { get; set; }
|
string ShortDescription { get; set; }
|
||||||
string FullDescription { get; set; }
|
string FullDescription { get; set; }
|
||||||
|
|
||||||
|
public string Sku { get; set; }
|
||||||
|
|
||||||
int WarehouseId { get; set; }
|
int WarehouseId { get; set; }
|
||||||
decimal Price { get; set; }
|
decimal Price { get; set; }
|
||||||
int StockQuantity { get; set; }
|
int StockQuantity { get; set; }
|
||||||
|
|
@ -290,6 +292,8 @@ public abstract class MgProductDto : MgEntityBase, /*Product,*/ IMgProductDto//I
|
||||||
public string ShortDescription { get; set; }
|
public string ShortDescription { get; set; }
|
||||||
public string FullDescription { get; set; }
|
public string FullDescription { get; set; }
|
||||||
|
|
||||||
|
public string Sku { get; set; }
|
||||||
|
|
||||||
public int WarehouseId { get; set; }
|
public int WarehouseId { get; set; }
|
||||||
public decimal Price { get; set; }
|
public decimal Price { get; set; }
|
||||||
public int StockQuantity { get; set; }
|
public int StockQuantity { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@
|
||||||
|
|
||||||
DisableAddUser = 44,
|
DisableAddUser = 44,
|
||||||
PhoneNumberFormatIsNotValid = 45,
|
PhoneNumberFormatIsNotValid = 45,
|
||||||
|
PlateNumberFormatIsNotValid = 46,
|
||||||
|
CountryCodeFormatIsNotValid = 47,
|
||||||
RefreshTokenUpdateError = 50,
|
RefreshTokenUpdateError = 50,
|
||||||
|
|
||||||
EmailIsNullOrEmpty = 55,
|
EmailIsNullOrEmpty = 55,
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,29 @@ public static partial class AcRegExpression
|
||||||
//public const string PhoneNumberMask = @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*(\d{1,2})";
|
//public const string PhoneNumberMask = @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*(\d{1,2})";
|
||||||
public const string PhoneNumberMask = @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d(\W*\d){1,14}";
|
public const string PhoneNumberMask = @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d(\W*\d){1,14}";
|
||||||
|
|
||||||
|
/// <summary>Rendszám (EKÁER-kompatibilis): nagybetű + szám (+ <c>Ö Ő Ü Ű</c>), 4–15 karakter — kötőjel/szóköz NÉLKÜL.</summary>
|
||||||
|
public const string PlateNumberMask = "[A-Z0-9ÖŐÜŰ]{4,15}";
|
||||||
|
|
||||||
|
/// <summary>Országkód, ISO 3166-1 alpha-2: pontosan 2 nagybetű (pl. <c>HU</c>).</summary>
|
||||||
|
public const string CountryCodeAlpha2Mask = "[A-Z]{2}";
|
||||||
|
|
||||||
|
/// <summary>Országkód: 1–3 nagybetű (pl. jármű-országkód az EKÁER-ben).</summary>
|
||||||
|
public const string CountryCodeMax3Mask = "[A-Z]{1,3}";
|
||||||
|
|
||||||
[GeneratedRegex(AcRegExpression.EmailMask)]
|
[GeneratedRegex(AcRegExpression.EmailMask)]
|
||||||
public static partial Regex EmailRegex();
|
public static partial Regex EmailRegex();
|
||||||
|
|
||||||
[GeneratedRegex(AcRegExpression.PhoneNumberMask)]
|
[GeneratedRegex(AcRegExpression.PhoneNumberMask)]
|
||||||
public static partial Regex PhoneNumberRegex();
|
public static partial Regex PhoneNumberRegex();
|
||||||
|
|
||||||
|
// A Regex-eket horgonyozzuk (^…$): a const Mask nyers (a [RegularExpression] attribútum maga
|
||||||
|
// teljes-string egyezést vár), de az IsMatch különben részstringet is elfogadna.
|
||||||
|
[GeneratedRegex("^" + AcRegExpression.PlateNumberMask + "$")]
|
||||||
|
public static partial Regex PlateNumberRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex("^" + AcRegExpression.CountryCodeAlpha2Mask + "$")]
|
||||||
|
public static partial Regex CountryCodeAlpha2Regex();
|
||||||
|
|
||||||
|
[GeneratedRegex("^" + AcRegExpression.CountryCodeMax3Mask + "$")]
|
||||||
|
public static partial Regex CountryCodeMax3Regex();
|
||||||
}
|
}
|
||||||
|
|
@ -68,6 +68,36 @@ namespace AyCode.Core.Consts
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsValidPlateNumberFormat(string? plateNumber, out AcErrorCode acErrorCode)
|
||||||
|
{
|
||||||
|
acErrorCode = AcErrorCode.Unset;
|
||||||
|
|
||||||
|
var isValid = !string.IsNullOrWhiteSpace(plateNumber) && AcRegExpression.PlateNumberRegex().IsMatch(plateNumber);
|
||||||
|
|
||||||
|
if (!isValid) acErrorCode = AcErrorCode.PlateNumberFormatIsNotValid;
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsValidCountryCodeAlpha2Format(string? countryCode, out AcErrorCode acErrorCode)
|
||||||
|
{
|
||||||
|
acErrorCode = AcErrorCode.Unset;
|
||||||
|
|
||||||
|
var isValid = !string.IsNullOrWhiteSpace(countryCode) && AcRegExpression.CountryCodeAlpha2Regex().IsMatch(countryCode);
|
||||||
|
|
||||||
|
if (!isValid) acErrorCode = AcErrorCode.CountryCodeFormatIsNotValid;
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsValidCountryCodeMax3Format(string? countryCode, out AcErrorCode acErrorCode)
|
||||||
|
{
|
||||||
|
acErrorCode = AcErrorCode.Unset;
|
||||||
|
|
||||||
|
var isValid = !string.IsNullOrWhiteSpace(countryCode) && AcRegExpression.CountryCodeMax3Regex().IsMatch(countryCode);
|
||||||
|
|
||||||
|
if (!isValid) acErrorCode = AcErrorCode.CountryCodeFormatIsNotValid;
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsValidUserTokenFormat(string verificationToken, out AcErrorCode acErrorCode)
|
public static bool IsValidUserTokenFormat(string verificationToken, out AcErrorCode acErrorCode)
|
||||||
{
|
{
|
||||||
acErrorCode = AcErrorCode.Unset;
|
acErrorCode = AcErrorCode.Unset;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
namespace AyCode.Core.Interfaces;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Postai címmel és adóazonosítóval azonosított fél (cég vagy partner) — <b>általános</b>, alsó-rétegű szerződés.
|
||||||
|
/// Bárhol használható, ahol egy felet név + adószám + postai cím alapján kell egységesen kezelni (számlázás,
|
||||||
|
/// szállítás, hatósági bejelentés stb.). Több, eltérő rétegű típus is implementálhatja (egy domain-entitás és
|
||||||
|
/// egy konfig-objektum egyaránt), így a feldolgozó kód egyetlen interfészen dolgozhat, a konkrét típus ismerete nélkül.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICompanyInfoBase
|
||||||
|
{
|
||||||
|
string Name { get; }
|
||||||
|
string TaxId { get; }
|
||||||
|
string CountryCode { get; }
|
||||||
|
string PostalCode { get; }
|
||||||
|
string City { get; }
|
||||||
|
string Street { get; }
|
||||||
|
|
||||||
|
/// <summary>A <see cref="PostalCode"/> + <see cref="City"/> + <see cref="Street"/> egy sorba fűzve (a nem üres részekből).</summary>
|
||||||
|
string FullAddress { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Közös <see cref="ICompanyInfoBase"/> segédműveletek — hogy a <c>FullAddress</c> logikája EGY helyen éljen.</summary>
|
||||||
|
public static class CompanyInfoBaseExtensions
|
||||||
|
{
|
||||||
|
/// <summary>A <c>PostalCode</c> + <c>City</c> + <c>Street</c> összefűzése egy sorba (a nem üres részekből); üres → <c>null</c>.</summary>
|
||||||
|
public static string? ComposeFullAddress(this ICompanyInfoBase company)
|
||||||
|
{
|
||||||
|
var joined = string.Join(" ", new[] { company.PostalCode, company.City, company.Street }.Where(p => !string.IsNullOrWhiteSpace(p))).Trim();
|
||||||
|
return string.IsNullOrWhiteSpace(joined) ? null : joined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
using AyCode.Core.Interfaces;
|
||||||
|
using AyCode.Entities;
|
||||||
|
using AyCode.Services.Nav.Ekaer.Models;
|
||||||
|
|
||||||
|
namespace AyCode.Services.Nav.Ekaer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A NAV-bejelentő saját cégadatai — általános (bármely bejelentő), a DI konfigurációból tölti.
|
||||||
|
/// A leképezés <see cref="ICompanyInfoBase"/>-ként kezeli, ugyanúgy, mint a beszállító <c>Partner</c>-t.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class EkaerCompanyInfo : ICompanyInfoBase
|
||||||
|
{
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? TaxId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>A bejelentő országkódja. A NAV EKÁER magyar rendszer → gyakorlatilag mindig <c>"HU"</c>.</summary>
|
||||||
|
public string? CountryCode { get; set; } = "HU";
|
||||||
|
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
public string? City { get; set; }
|
||||||
|
public string? Street { get; set; }
|
||||||
|
|
||||||
|
public string? FullAddress => this.ComposeFullAddress();
|
||||||
|
|
||||||
|
/// <summary>A saját telephely / lerakodási hely. Magyar címnél a NAV a Name/VatNumber/Phone/Email-t is megköveteli.</summary>
|
||||||
|
public LocationType? UnloadLocation { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace AyCode.Services.Nav;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Az <see cref="INavCredentials"/> egyszerű, beállítható megvalósítása — a hívó (DI) konfigurációból
|
||||||
|
/// (appsettings / secret store) tölti. ⚠️ Soha NE hardcode-old a kulcsokat a forráskódba.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class NavCredentials : INavCredentials
|
||||||
|
{
|
||||||
|
public string User { get; set; } = "";
|
||||||
|
public string Password { get; set; } = "";
|
||||||
|
public string SigningKey { get; set; } = "";
|
||||||
|
public string TaxNumber { get; set; } = "";
|
||||||
|
public string BaseUrl { get; set; } = "";
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue