diff --git a/AyCode.Core.Tests/TestModels/StockTakingTestModels.cs b/AyCode.Core.Tests/TestModels/StockTakingTestModels.cs
index 3259f32..cb8fe4f 100644
--- a/AyCode.Core.Tests/TestModels/StockTakingTestModels.cs
+++ b/AyCode.Core.Tests/TestModels/StockTakingTestModels.cs
@@ -252,6 +252,8 @@ public interface IMgProductDto : IEntityInt
string ShortDescription { get; set; }
string FullDescription { get; set; }
+ public string Sku { get; set; }
+
int WarehouseId { get; set; }
decimal Price { 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 FullDescription { get; set; }
+ public string Sku { get; set; }
+
public int WarehouseId { get; set; }
public decimal Price { get; set; }
public int StockQuantity { get; set; }
diff --git a/AyCode.Core/Consts/AcErrorCode.cs b/AyCode.Core/Consts/AcErrorCode.cs
index 4a14088..fda0909 100644
--- a/AyCode.Core/Consts/AcErrorCode.cs
+++ b/AyCode.Core/Consts/AcErrorCode.cs
@@ -52,6 +52,8 @@
DisableAddUser = 44,
PhoneNumberFormatIsNotValid = 45,
+ PlateNumberFormatIsNotValid = 46,
+ CountryCodeFormatIsNotValid = 47,
RefreshTokenUpdateError = 50,
EmailIsNullOrEmpty = 55,
diff --git a/AyCode.Core/Consts/AcRegExpression.cs b/AyCode.Core/Consts/AcRegExpression.cs
index 87ffd41..7f73af8 100644
--- a/AyCode.Core/Consts/AcRegExpression.cs
+++ b/AyCode.Core/Consts/AcRegExpression.cs
@@ -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){1,14}";
+ /// Rendszám (EKÁER-kompatibilis): nagybetű + szám (+ Ö Ő Ü Ű), 4–15 karakter — kötőjel/szóköz NÉLKÜL.
+ public const string PlateNumberMask = "[A-Z0-9ÖŐÜŰ]{4,15}";
+
+ /// Országkód, ISO 3166-1 alpha-2: pontosan 2 nagybetű (pl. HU).
+ public const string CountryCodeAlpha2Mask = "[A-Z]{2}";
+
+ /// Országkód: 1–3 nagybetű (pl. jármű-országkód az EKÁER-ben).
+ public const string CountryCodeMax3Mask = "[A-Z]{1,3}";
+
[GeneratedRegex(AcRegExpression.EmailMask)]
public static partial Regex EmailRegex();
[GeneratedRegex(AcRegExpression.PhoneNumberMask)]
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();
}
\ No newline at end of file
diff --git a/AyCode.Core/Consts/AcValidate.cs b/AyCode.Core/Consts/AcValidate.cs
index f7c6b05..2d88393 100644
--- a/AyCode.Core/Consts/AcValidate.cs
+++ b/AyCode.Core/Consts/AcValidate.cs
@@ -68,6 +68,36 @@ namespace AyCode.Core.Consts
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)
{
acErrorCode = AcErrorCode.Unset;
diff --git a/AyCode.Core/Interfaces/ICompanyInfoBase.cs b/AyCode.Core/Interfaces/ICompanyInfoBase.cs
new file mode 100644
index 0000000..5f4c272
--- /dev/null
+++ b/AyCode.Core/Interfaces/ICompanyInfoBase.cs
@@ -0,0 +1,31 @@
+namespace AyCode.Core.Interfaces;
+
+///
+/// Postai címmel és adóazonosítóval azonosított fél (cég vagy partner) — általános, 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.
+///
+public interface ICompanyInfoBase
+{
+ string Name { get; }
+ string TaxId { get; }
+ string CountryCode { get; }
+ string PostalCode { get; }
+ string City { get; }
+ string Street { get; }
+
+ /// A + + egy sorba fűzve (a nem üres részekből).
+ string FullAddress { get; }
+}
+
+/// Közös segédműveletek — hogy a FullAddress logikája EGY helyen éljen.
+public static class CompanyInfoBaseExtensions
+{
+ /// A PostalCode + City + Street összefűzése egy sorba (a nem üres részekből); üres → null.
+ 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;
+ }
+}
diff --git a/AyCode.Services/Nav/Ekaer/EkaerCompanyInfo.cs b/AyCode.Services/Nav/Ekaer/EkaerCompanyInfo.cs
new file mode 100644
index 0000000..e7500f3
--- /dev/null
+++ b/AyCode.Services/Nav/Ekaer/EkaerCompanyInfo.cs
@@ -0,0 +1,27 @@
+using AyCode.Core.Interfaces;
+using AyCode.Entities;
+using AyCode.Services.Nav.Ekaer.Models;
+
+namespace AyCode.Services.Nav.Ekaer;
+
+///
+/// A NAV-bejelentő saját cégadatai — általános (bármely bejelentő), a DI konfigurációból tölti.
+/// A leképezés -ként kezeli, ugyanúgy, mint a beszállító Partner-t.
+///
+public sealed class EkaerCompanyInfo : ICompanyInfoBase
+{
+ public string? Name { get; set; }
+ public string? TaxId { get; set; }
+
+ /// A bejelentő országkódja. A NAV EKÁER magyar rendszer → gyakorlatilag mindig "HU".
+ 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();
+
+ /// A saját telephely / lerakodási hely. Magyar címnél a NAV a Name/VatNumber/Phone/Email-t is megköveteli.
+ public LocationType? UnloadLocation { get; set; }
+}
diff --git a/AyCode.Services/Nav/NavCredentials.cs b/AyCode.Services/Nav/NavCredentials.cs
new file mode 100644
index 0000000..68f1706
--- /dev/null
+++ b/AyCode.Services/Nav/NavCredentials.cs
@@ -0,0 +1,14 @@
+namespace AyCode.Services.Nav;
+
+///
+/// Az 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.
+///
+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; } = "";
+}