From 3b22b07d02fb76f885644f786b2120f0f5cc0bee Mon Sep 17 00:00:00 2001 From: Loretta Date: Sun, 7 Jun 2026 07:20:07 +0200 Subject: [PATCH] PartnerDepot API, SignalRTags fixes, and test for duplicates - Added PartnerDepot CRUD API to IFruitBankDataControllerCommon and FruitBankSignalRClient. - Fixed Partner entity association to ShippingDocument.PartnerId. - Changed EkaerHistory to sealed, added ForeignKey, IsOutgoing, Created. - Exposed GetEkaerHistoriesByForeignKey in SignalRTags. - Fixed SignalRTags usage in ShippingDocument queries. - Implemented ProductDtoTableItem deserialization workaround. - Added unit test to detect duplicate SignalRTags constant values. --- FruitBank.Common/Entities/EkaerHistory.cs | 2 +- FruitBank.Common/Entities/Partner.cs | 2 +- .../IFruitBankDataControllerCommon.cs | 8 ++++ FruitBank.Common/SignalRs/SignalRTags.cs | 2 +- .../SignalRTagsTests.cs | 38 +++++++++++++++++++ .../Databases/DatabaseClient.cs | 2 + .../SignalRs/FruitBankSignalRClient.cs | 35 +++++++++++++---- 7 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 FruitBankHybrid.Shared.Tests/SignalRTagsTests.cs diff --git a/FruitBank.Common/Entities/EkaerHistory.cs b/FruitBank.Common/Entities/EkaerHistory.cs index 70fba14a..ed3920fd 100644 --- a/FruitBank.Common/Entities/EkaerHistory.cs +++ b/FruitBank.Common/Entities/EkaerHistory.cs @@ -11,7 +11,7 @@ namespace FruitBank.Common.Entities; [Table(Name = FruitBankConstClient.EkaerHistoryDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.EkaerHistoryDbTableName)] -public abstract class EkaerHistory: MgEntityBase, ITimeStampInfo +public sealed class EkaerHistory: MgEntityBase, ITimeStampInfo { public int ForeignKey { get; set; } public bool IsOutgoing { get; set; } diff --git a/FruitBank.Common/Entities/Partner.cs b/FruitBank.Common/Entities/Partner.cs index 0acd2457..db482074 100644 --- a/FruitBank.Common/Entities/Partner.cs +++ b/FruitBank.Common/Entities/Partner.cs @@ -11,6 +11,6 @@ namespace FruitBank.Common.Entities; [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PartnerDbTableName)] public sealed class Partner : PartnerBase, IPartner { - [Association(ThisKey = nameof(Id), OtherKey = nameof(ShippingDocument.ShippingId), CanBeNull = true)] + [Association(ThisKey = nameof(Id), OtherKey = nameof(ShippingDocument.PartnerId), CanBeNull = true)] public List? ShippingDocuments { get; set; } } \ No newline at end of file diff --git a/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs b/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs index 39a8ae26..ac6d0730 100644 --- a/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs +++ b/FruitBank.Common/Interfaces/IFruitBankDataControllerCommon.cs @@ -20,6 +20,14 @@ public interface IFruitBankDataControllerCommon public Task UpdatePartner(Partner partner); #endregion Partner + #region PartnerDepot + public Task?> GetPartnerDepots(); + public Task GetPartnerDepotById(int id); + public Task?> GetPartnerDepotsByPartnerId(int partnerId); + public Task AddPartnerDepot(PartnerDepot partnerDepot); + public Task UpdatePartnerDepot(PartnerDepot partnerDepot); + #endregion PartnerDepot + #region CargoPartner public Task?> GetCargoPartners(); public Task GetCargoPartnerById(int id); diff --git a/FruitBank.Common/SignalRs/SignalRTags.cs b/FruitBank.Common/SignalRs/SignalRTags.cs index f49ba450..3c23bee4 100644 --- a/FruitBank.Common/SignalRs/SignalRTags.cs +++ b/FruitBank.Common/SignalRs/SignalRTags.cs @@ -120,7 +120,7 @@ public class SignalRTags : AcSignalRTags public const int GetEkaerHistories = 185; public const int GetEkaerHistoryById = 186; - //public const int GetEkaerHistoriesByForeignKey = 187; + public const int GetEkaerHistoriesByForeignKey = 187; public const int AddEkaerHistory = 188; public const int UpdateEkaerHistory = 189; diff --git a/FruitBankHybrid.Shared.Tests/SignalRTagsTests.cs b/FruitBankHybrid.Shared.Tests/SignalRTagsTests.cs new file mode 100644 index 00000000..42cfef12 --- /dev/null +++ b/FruitBankHybrid.Shared.Tests/SignalRTagsTests.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using FruitBank.Common.SignalRs; + +namespace FruitBankHybrid.Shared.Tests +{ + [TestClass] + public sealed class SignalRTagsTests + { + /// + /// A értékei a drót-protokoll azonosítói: két azonos értékű + /// konstans (jellemzően copy-paste után) némán másik endpointra irányítaná a hívást. + /// A kézi számkiosztás szándékos (stabil szerződés), ez a teszt csak alá feszít egy hálót: + /// kibukik a duplikátumon, és megnevezi a vétkes konstansokat. + /// + /// + /// Csak a -ben DEKLARÁLT konstansokat vizsgálja (DeclaredOnly) — + /// ide ír a fejlesztő kézzel. A framework-ős AcSignalRTags-szal való átfedés + /// ellenőrzéséhez BindingFlags.FlattenHierarchy kellene. + /// + [TestMethod] + public void SignalRTags_HasNoDuplicateValues() + { + var tags = typeof(SignalRTags) + .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(f => f.IsLiteral && f.FieldType == typeof(int)) + .Select(f => (f.Name, Value: (int)f.GetRawConstantValue()!)) + .ToList(); + + var duplicates = tags + .GroupBy(t => t.Value) + .Where(g => g.Count() > 1) + .Select(g => $" {g.Key} = {string.Join(", ", g.Select(t => t.Name))}") + .ToList(); + + Assert.AreEqual(0, duplicates.Count, $"Több SignalRTag ugyanazt az értéket kapta:{Environment.NewLine}{string.Join(Environment.NewLine, duplicates)}"); + } + } +} diff --git a/FruitBankHybrid.Shared/Databases/DatabaseClient.cs b/FruitBankHybrid.Shared/Databases/DatabaseClient.cs index 7c7e3531..7968b9e8 100644 --- a/FruitBankHybrid.Shared/Databases/DatabaseClient.cs +++ b/FruitBankHybrid.Shared/Databases/DatabaseClient.cs @@ -70,6 +70,8 @@ public class ProductDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : Ac //Clear(); this.Replace(items); + //this.Replace(items.Cast()); + //foreach (var productDto in items) //{ // this.UpdateCollection(productDto, false); diff --git a/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs b/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs index bf590cd1..00a6854b 100644 --- a/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs +++ b/FruitBankHybrid.Shared/Services/SignalRs/FruitBankSignalRClient.cs @@ -66,6 +66,14 @@ namespace FruitBankHybrid.Shared.Services.SignalRs public Task UpdatePartner(Partner partner) => PostDataAsync(SignalRTags.UpdatePartner, partner); #endregion Partner + #region PartnerDepot + public Task?> GetPartnerDepots() => GetAllAsync>(SignalRTags.GetPartnerDepots); + public Task GetPartnerDepotById(int id) => GetByIdAsync(SignalRTags.GetPartnerDepotById, id); + public Task?> GetPartnerDepotsByPartnerId(int partnerId) => GetAllAsync>(SignalRTags.GetPartnerDepotsByPartnerId, [partnerId]); + public Task AddPartnerDepot(PartnerDepot partnerDepot) => PostDataAsync(SignalRTags.AddPartnerDepot, partnerDepot); + public Task UpdatePartnerDepot(PartnerDepot partnerDepot) => PostDataAsync(SignalRTags.UpdatePartnerDepot, partnerDepot); + #endregion PartnerDepot + #region CargoPartner public Task?> GetCargoPartners() => GetAllAsync>(SignalRTags.GetCargoPartners); public Task GetCargoPartnerById(int id) => GetByIdAsync(SignalRTags.GetCargoPartnerById, id); @@ -163,10 +171,10 @@ namespace FruitBankHybrid.Shared.Services.SignalRs => GetAllAsync>(SignalRTags.GetShippingDocumentsByShippingId, [shippingId]); public Task?> GetShippingDocumentsByProductId(int productId) - => GetAllAsync>(SignalRTags.GetShippingDocumentsByShippingId, [productId]); + => GetAllAsync>(SignalRTags.GetShippingDocumentsByProductId, [productId]); public Task?> GetShippingDocumentsByPartnerId(int partnerId) - => GetAllAsync>(SignalRTags.GetShippingDocumentsByShippingId, [partnerId]); + => GetAllAsync>(SignalRTags.GetShippingDocumentsByPartnerId, [partnerId]); public Task AddShippingDocument(ShippingDocument shippingDocument) => PostDataAsync(SignalRTags.AddShippingDocument, shippingDocument); @@ -185,18 +193,29 @@ namespace FruitBankHybrid.Shared.Services.SignalRs #endregion Customer #region Product + //TODO: itt ProductDtoTableItem kéne, csak az AycodeHubProtocol ProductDto-ra deserialize-ol! - J. + //public Task?> GetProductDtoTableItems() => GetAllAsync>(SignalRTags.GetProductDtos); + // IDEIGLENES gyors fix: a GetProductDtos tagon a szerver List-t küld, a binár + // protokoll viszont a wire-típusba (ProductDto) deszerializál — így a közvetlen + // List kérés üres lett (a ProductDtoTableItem a ProductDto kliens-oldali + // leszármazottja, amit a szerver nem ismer). A működő GetProductDtos()-t hívjuk, és bináris + // round-trippel a kért leszármazottra alakítjuk (azonos mezők). VÉGLEGES megoldás: requestId → + // kért-típus a protokollban (AQN-leváltás) — lásd AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL. + public async Task?> GetProductDtoTableItems() + { + var dtos = await GetProductDtos(); + if (dtos == null) return null; - public Task?> GetProductDtoTableItems() - => GetAllAsync>(SignalRTags.GetProductDtos); + var bytes = SignalRSerializationHelper.SerializeToBinary(dtos); + return SignalRSerializationHelper.DeserializeFromBinary>(bytes); + } - public Task?> GetProductDtos() - => GetAllAsync>(SignalRTags.GetProductDtos); + public Task?> GetProductDtos() => GetAllAsync>(SignalRTags.GetProductDtos); //public Task?> GetAllMeasuringProductDtos() // => GetAllAsync>(SignalRTags.GetAllMeasuringProductDtos); - public Task GetProductDtoById(int productId) - => GetByIdAsync(SignalRTags.GetMeasuringProductDtoById, productId); + public Task GetProductDtoById(int productId) => GetByIdAsync(SignalRTags.GetMeasuringProductDtoById, productId); #endregion Product