Compare commits
No commits in common. "e9438e43740dc4f3971bb27b2d225367e3bef7ac" and "954e5ef86a41afe51948b55f6ba7e7612103ed1a" have entirely different histories.
e9438e4374
...
954e5ef86a
|
|
@ -147,10 +147,7 @@
|
|||
"Bash(git -C \"H:/Applications/Aycode/Source/AyCode.Core\" mv \"AyCode.Services.Server/docs/SIGNALR_DATASOURCE\" \"AyCode.Services/docs/SIGNALR_DATASOURCE\")",
|
||||
"Bash(awk 'NR==135' \"H:/Applications/Aycode/Source/AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md\")",
|
||||
"Bash(git -C \"H:/Applications/Aycode/Source/AyCode.Core\" status --short)",
|
||||
"Bash(git -C \"H:/Applications/Aycode/Source/AyCode.Core\" reset)",
|
||||
"Bash(dotnet build *)",
|
||||
"PowerShell(dotnet build AyCode.Services\\\\AyCode.Services.csproj --nologo -v q 2>$null)",
|
||||
"PowerShell(dotnet test AyCode.Services.Server.Tests\\\\AyCode.Services.Server.Tests.csproj --nologo --no-restore --filter \"FullyQualifiedName~AcBinaryHubProtocolConcurrencyTests\" 2>$null)"
|
||||
"Bash(git -C \"H:/Applications/Aycode/Source/AyCode.Core\" reset)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -46,7 +46,6 @@ public sealed class EkaerTradeCardValidatorTests
|
|||
ProductVtsz = "08081010",
|
||||
ProductName = "Alma",
|
||||
Weight = 123.5m,
|
||||
Value = 250_000,
|
||||
});
|
||||
return operation;
|
||||
}
|
||||
|
|
@ -97,30 +96,6 @@ public sealed class EkaerTradeCardValidatorTests
|
|||
Assert.IsTrue(HasError(Sut.Validate(op), "címzett"), "üres/whitespace címzettnév → hiba");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Validate_ZeroWeight_ReportsError()
|
||||
{
|
||||
var op = ValidOperation();
|
||||
op.TradeCard!.Items[0].Weight = 0;
|
||||
Assert.IsTrue(HasError(Sut.Validate(op), "tömege"), "0 tömeg (hiányzó súly a doksin) → üzleti szabály hiba");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Validate_MissingValue_ReportsError()
|
||||
{
|
||||
var op = ValidOperation();
|
||||
op.TradeCard!.Items[0].Value = null;
|
||||
Assert.IsTrue(HasError(Sut.Validate(op), "értéke"), "hiányzó tétel-érték → üzleti szabály hiba (NAV 2021-től)");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Validate_ZeroValue_ReportsError()
|
||||
{
|
||||
var op = ValidOperation();
|
||||
op.TradeCard!.Items[0].Value = 0;
|
||||
Assert.IsTrue(HasError(Sut.Validate(op), "értéke"), "0 tétel-érték → üzleti szabály hiba (NAV 2021-től)");
|
||||
}
|
||||
|
||||
// ---- Séma-szint (generált DataAnnotations) ------------------------------
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace AyCode.Services.Nav.Ekaer;
|
|||
/// <item>a generált modellek <see cref="ValidationAttribute"/>-jai (Required / RegularExpression / Min-MaxLength),
|
||||
/// rekurzívan a tradeCard + tételek + jármű + helyszínek fölött — ezt a <see cref="Validator"/> végzi;</item>
|
||||
/// <item>az XSD-ben NEM jelölt, de a NAV által megkövetelt üzleti szabályok (vonó jármű, legalább egy tétel,
|
||||
/// tétel-tömeg/-érték > 0, feladó/címzett alapadatok) — ezeket kézzel ellenőrizzük.</item>
|
||||
/// feladó/címzett alapadatok) — ezeket kézzel ellenőrizzük.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public sealed class EkaerTradeCardValidator : IEkaerTradeCardValidator
|
||||
|
|
@ -81,12 +81,6 @@ public sealed class EkaerTradeCardValidator : IEkaerTradeCardValidator
|
|||
// a sémán (a null bukik a Required-en, az "" nem, mert a RegularExpression az üreset validnak veszi),
|
||||
// ezért üzleti szabállyal lezárjuk. A { Length: 0 } property-pattern a null-ra NEM illeszkedik → nincs dupla hiba.
|
||||
if (item.ProductVtsz is { Length: 0 }) errors.Add(Error($"{itemPath}.productVtsz", "a tétel VTSZ-száma (productVtsz) nem lehet üres"));
|
||||
|
||||
// A tétel bruttó tömege kötelező és pozitív — a 0 azt jelzi, hogy a forrás-dokumentumról hiányzik a súly (adathiba).
|
||||
if (item.Weight <= 0) errors.Add(Error($"{itemPath}.weight", "a tétel bruttó tömege (weight) kötelező és nem lehet 0"));
|
||||
|
||||
// A NAV 2021.01.01-től minden tételre value > 0-t követel — a hiányzó/0 érték (pl. ismeretlen ár) blokkoló adathiba.
|
||||
if (item.Value is not > 0) errors.Add(Error($"{itemPath}.value", "a tétel értéke (value) kötelező és pozitív (NAV-követelmény 2021-től)"));
|
||||
}
|
||||
|
||||
// 3) Üzleti szabályok (az XSD nem jelöli [Required]-ként, de a NAV megköveteli).
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
> **Forrás:** [`eKAERManagementService_2.2.pdf`](eKAERManagementService_2.2.pdf) + [`ekaermanagement.xsd`](ekaermanagement.xsd) / [`common.xsd`](common.xsd).
|
||||
> Ez **LLM-barát kivonat** a gyakori dolgokról — ütközés esetén **a PDF/XSD a hiteles forrás**.
|
||||
> Online: <https://ekaer.nav.gov.hu/faq/?page_id=9>
|
||||
>
|
||||
> **Verzió-állapot (2026-07-10, a NAV-oldalról ellenőrizve):** a **2.2 az aktuális** interfész-verzió, újabb nincs bejelentve. A NAV a 2.2 dokumentációt **2025-05-14-én frissítette** („Lejárt jelszó kezelése" — `EXPIRED_PASSWORD` eset viselkedése). **A helyi PDF EZ a friss kiadás** (byte-azonos méret az online-nal, letöltve 2026-06-01) — nem kell újra letölteni.
|
||||
|
||||
## Transport
|
||||
|
||||
|
|
|
|||
|
|
@ -86,15 +86,11 @@ Mezők: `name`, `VATNumber`, `phone`, `e-mail`, `country`, `zipCode`, `city`, `s
|
|||
|
||||
| Kód | Jelentés | Biztosíték? |
|
||||
|---|---|---|
|
||||
| `S` | Termékértékesítés **/ -beszerzés** — EGY kód MINDKÉT irányra (kimenő eladás ÉS bejövő beszerzés) | **van** |
|
||||
| `S` | Termékértékesítés / -beszerzés | **van** |
|
||||
| `A` | Saját tulajdonú termék (kivezetve 2015.03.01 után — új bejelentésnél nem adható) | van |
|
||||
| `W` | Bérmunka | nincs |
|
||||
| `O` | Egyéb | nincs |
|
||||
|
||||
> ⚠️ **Gyakori félreértés:** az `A` NEM „beszerzés" (angol *acquisition* alapján kézenfekvő, de TÉVES) — a `common.xsd` szerint `A` = „Saját tulajdonú termék - Törvény változás miatt kivezetve." A **beszerzésre is az `S`** való; belföldön (`D`) ráadásul CSAK az `S` megengedett (lásd lent).
|
||||
>
|
||||
> ⛔ **Az `ekaermanagement.xsd` tétel-kommentje ELAVULT és félrevezet:** a `TradeCardItemGroup`/`tradeReason` elem inline dokumentációja („S: Értékesítés **A: Beszerzés** W: Bérmunka O: Egyéb") a kivezetés ELŐTTI állapot — NE ebből dolgozz. A mérvadó a `common.xsd` `TradeReasonType` enum-annotációja + a PDF (webről is megerősítve, 2026-07-10: az `A` 2015.03.01 után nem adható).
|
||||
|
||||
**A `tradeReason` a `tradeType`-tól függően korlátozott:**
|
||||
- `E` (export): `S`, `W`, `O`
|
||||
- `I` (import): `S`, `W`, `O`
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -261,10 +261,7 @@ public class AcBinaryHubProtocol : IHubProtocol
|
|||
|
||||
public void WriteMessage(HubMessage message, IBufferWriter<byte> output)
|
||||
{
|
||||
// Keepalive pings (~15 s, both directions) would flood the log channel at Information
|
||||
// level — real messages keep the start/end brackets (hang diagnostics, ACCORE-SBP-I-T3W9).
|
||||
var isPing = message is PingMessage;
|
||||
if (!isPing) _logger?.LogInformation("Serialize start");
|
||||
_logger?.LogInformation("Serialize start");
|
||||
|
||||
// AsyncSegment: chunked protocol framing for messages with streamable arguments
|
||||
if (_protocolMode == BinaryProtocolMode.AsyncSegment
|
||||
|
|
@ -330,7 +327,7 @@ public class AcBinaryHubProtocol : IHubProtocol
|
|||
bw.Flush();
|
||||
Unsafe.WriteUnaligned(ref lengthSpan[0], totalPayload);
|
||||
|
||||
if (!isPing) _logger?.LogInformation("Serialize end totalSentSize={TotalSentSize}", LengthPrefixSize + totalPayload);
|
||||
_logger?.LogInformation("Serialize end totalSentSize={TotalSentSize}", LengthPrefixSize + totalPayload);
|
||||
|
||||
if (_logger?.IsEnabled(LogLevel.Debug) == true)
|
||||
_logger.LogDebug("WriteMessage {MessageType} payloadSize={PayloadSize}", message.GetType().Name, totalPayload);
|
||||
|
|
@ -657,12 +654,7 @@ public class AcBinaryHubProtocol : IHubProtocol
|
|||
return false;
|
||||
|
||||
_logger?.LogTrace("TryParseMessage parsing payloadLength={PayloadLength} inputLength={InputLength}", payloadLength, input.Length);
|
||||
|
||||
// Keepalive ping frame (payload = single MsgPing byte) — skip the Information-level
|
||||
// brackets (~15 s spam, both directions). Wire-level check: the routing-fallback that
|
||||
// SURFACES PingMessage.Instance for real payloads (see ParseMessage) must keep its brackets.
|
||||
var isPing = payloadLength == 1 && reader.TryPeek(out var firstByte) && firstByte == MsgPing;
|
||||
if (!isPing) _logger?.LogInformation("Deserialize start");
|
||||
_logger?.LogInformation("Deserialize start");
|
||||
|
||||
message = ParseMessage(ref reader, payloadLength, binder);
|
||||
|
||||
|
|
@ -670,7 +662,7 @@ public class AcBinaryHubProtocol : IHubProtocol
|
|||
{
|
||||
input = input.Slice(LengthPrefixSize + payloadLength);
|
||||
|
||||
if (!isPing) _logger?.LogInformation("Deserialize end");
|
||||
_logger?.LogInformation("Deserialize end");
|
||||
if (_logger?.IsEnabled(LogLevel.Debug) == true) _logger.LogDebug("TryParseMessage parsed {MessageType}", message.GetType().Name);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -6,11 +6,4 @@ public class AcSignalRTags
|
|||
|
||||
public const int PingTag = 90001;
|
||||
public const int EchoTag = 90002;
|
||||
|
||||
/// <summary>
|
||||
/// Grid layout roaming (key-value store): key = composite grid-layout key, value = layout JSON, userId = owning user.
|
||||
/// </summary>
|
||||
public const int GetGridLayoutTag = 90010;
|
||||
public const int SaveGridLayoutTag = 90011;
|
||||
public const int DeleteGridLayoutTag = 90012;
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ Custom binary SignalR protocol, client infrastructure, message tagging, and seri
|
|||
|
||||
### Message Tagging
|
||||
- **`SignalMessageTagAttribute.cs`** — Three attributes: `TagAttribute` (base, int messageTag), `SignalRAttribute` (server method routing + client notification), `SignalRSendToClientAttribute` (client-side receive).
|
||||
- **`AcSignalRTags.cs`** — Static constants: `None`, `PingTag`, `EchoTag`; grid-layout roaming tags `GetGridLayoutTag` / `SaveGridLayoutTag` / `DeleteGridLayoutTag` (90010-12) — key-value layout storage contract (`key`, [`layoutJson`,] `userId`), implemented by consumer hubs.
|
||||
- **`AcSignalRTags.cs`** — Static constants: `None`, `PingTag`, `EchoTag`.
|
||||
- **`SignalRCrudTags.cs`** — Sealed class bundling 5 independent CRUD tag integers. `GetMessageTagByTrackingState()` maps `TrackingState` -> tag. See `AyCode.Services/docs/SIGNALR_DATASOURCE/README.md`.
|
||||
- **`SendToClientType.cs`** — Enum: None, Others, Caller, All.
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -4,7 +4,7 @@
|
|||
>
|
||||
> **Strict rule**: AyCode.Core code, types, namespaces, topic IDs, and any other `.md` files (`docs/`, `.github/` excluding the narrow workspace-meta-history exception) MUST NOT name any specific consumer listed here. **This is the SINGLE place** in ACCORE that may name consumer repos.
|
||||
|
||||
## Workspace consumer map (as of 2026-07-08)
|
||||
## Workspace consumer map (as of 2026-04-26)
|
||||
|
||||
| Prefix | Repo | Layer | Type | Path (workspace-relative) | Brief usage |
|
||||
|----------------|-------------------------------|------:|---------------------|--------------------------------------------------------------------|------------------------------------------------------------------------------|
|
||||
|
|
@ -14,14 +14,13 @@
|
|||
| `MGFBANKPLUG` | Nop.Plugin.Misc.AIPlugin | 3 | consumer (plugin) | `.../Plugins/Nop.Plugin.Misc.AIPlugin` | FruitBank nopCommerce plugin source |
|
||||
| `FBANKNOP` | FruitBank | 2 | product (server) | `Mango/Source/FruitBank` | nopCommerce server source for the FruitBank deployment |
|
||||
| `FBANKAPP` | FruitBankHybridApp | 2 | product (hybrid) | `Mango/Source/FruitBankHybridApp` | MAUI/Blazor hybrid client app |
|
||||
| `GIAAPP` | GiaApp | 2 | product (web) | `Mango/Source/GiaApp` | Blazor Server GPS ↔ worksheet reconciliation app (entities/user-stack/data-layer; app-level SignalR hubs on base `AcBinaryHubProtocol`, tag-based layer unused) |
|
||||
|
||||
(See `.github/REPO_PREFIXES.md` for the prefix scheme; each consumer's own `.github/copilot-instructions.md` `@repo` block declares its `prefix` value per LLMP-DEC-58.)
|
||||
|
||||
## When modifying AyCode.Core — change-impact lens
|
||||
|
||||
Use this list to assess change impact:
|
||||
- A breaking change to a base class affects all 7 consumers above (cascading rebuilds + verification).
|
||||
- A breaking change to a base class affects all 6 consumers above (cascading rebuilds + verification).
|
||||
- A new feature gated behind opt-in DI extension → no cascade, just new capability.
|
||||
- A signature change in a widely-used interface (e.g., `IAcSignalRClientBase`) → at minimum: ACBLAZOR + MGNOPLIB + MGFBANKPLUG + FBANKNOP + FBANKAPP all need verification.
|
||||
- A change to ID format / topic-code conventions → MGNOPCORE and MGFBANKPLUG (inherit-protocol) plus all primary repos need updating.
|
||||
|
|
|
|||
Loading…
Reference in New Issue