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.
This commit is contained in:
parent
0083a7bd6e
commit
3b22b07d02
|
|
@ -11,7 +11,7 @@ namespace FruitBank.Common.Entities;
|
||||||
[Table(Name = FruitBankConstClient.EkaerHistoryDbTableName)]
|
[Table(Name = FruitBankConstClient.EkaerHistoryDbTableName)]
|
||||||
[System.ComponentModel.DataAnnotations.Schema.Table(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 int ForeignKey { get; set; }
|
||||||
public bool IsOutgoing { get; set; }
|
public bool IsOutgoing { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,6 @@ namespace FruitBank.Common.Entities;
|
||||||
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PartnerDbTableName)]
|
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PartnerDbTableName)]
|
||||||
public sealed class Partner : PartnerBase, IPartner
|
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<ShippingDocument>? ShippingDocuments { get; set; }
|
public List<ShippingDocument>? ShippingDocuments { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -20,6 +20,14 @@ public interface IFruitBankDataControllerCommon
|
||||||
public Task<Partner?> UpdatePartner(Partner partner);
|
public Task<Partner?> UpdatePartner(Partner partner);
|
||||||
#endregion Partner
|
#endregion Partner
|
||||||
|
|
||||||
|
#region PartnerDepot
|
||||||
|
public Task<List<PartnerDepot>?> GetPartnerDepots();
|
||||||
|
public Task<PartnerDepot?> GetPartnerDepotById(int id);
|
||||||
|
public Task<List<PartnerDepot>?> GetPartnerDepotsByPartnerId(int partnerId);
|
||||||
|
public Task<PartnerDepot?> AddPartnerDepot(PartnerDepot partnerDepot);
|
||||||
|
public Task<PartnerDepot?> UpdatePartnerDepot(PartnerDepot partnerDepot);
|
||||||
|
#endregion PartnerDepot
|
||||||
|
|
||||||
#region CargoPartner
|
#region CargoPartner
|
||||||
public Task<List<CargoPartner>?> GetCargoPartners();
|
public Task<List<CargoPartner>?> GetCargoPartners();
|
||||||
public Task<CargoPartner?> GetCargoPartnerById(int id);
|
public Task<CargoPartner?> GetCargoPartnerById(int id);
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ public class SignalRTags : AcSignalRTags
|
||||||
|
|
||||||
public const int GetEkaerHistories = 185;
|
public const int GetEkaerHistories = 185;
|
||||||
public const int GetEkaerHistoryById = 186;
|
public const int GetEkaerHistoryById = 186;
|
||||||
//public const int GetEkaerHistoriesByForeignKey = 187;
|
public const int GetEkaerHistoriesByForeignKey = 187;
|
||||||
public const int AddEkaerHistory = 188;
|
public const int AddEkaerHistory = 188;
|
||||||
public const int UpdateEkaerHistory = 189;
|
public const int UpdateEkaerHistory = 189;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using FruitBank.Common.SignalRs;
|
||||||
|
|
||||||
|
namespace FruitBankHybrid.Shared.Tests
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public sealed class SignalRTagsTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="SignalRTags"/> é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.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Csak a <see cref="SignalRTags"/>-ben DEKLARÁLT konstansokat vizsgálja (<c>DeclaredOnly</c>) —
|
||||||
|
/// ide ír a fejlesztő kézzel. A framework-ős <c>AcSignalRTags</c>-szal való átfedés
|
||||||
|
/// ellenőrzéséhez <c>BindingFlags.FlattenHierarchy</c> kellene.
|
||||||
|
/// </remarks>
|
||||||
|
[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)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -70,6 +70,8 @@ public class ProductDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : Ac
|
||||||
|
|
||||||
//Clear();
|
//Clear();
|
||||||
this.Replace(items);
|
this.Replace(items);
|
||||||
|
//this.Replace(items.Cast<ProductDtoTableItem>());
|
||||||
|
|
||||||
//foreach (var productDto in items)
|
//foreach (var productDto in items)
|
||||||
//{
|
//{
|
||||||
// this.UpdateCollection(productDto, false);
|
// this.UpdateCollection(productDto, false);
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,14 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
|
||||||
public Task<Partner?> UpdatePartner(Partner partner) => PostDataAsync(SignalRTags.UpdatePartner, partner);
|
public Task<Partner?> UpdatePartner(Partner partner) => PostDataAsync(SignalRTags.UpdatePartner, partner);
|
||||||
#endregion Partner
|
#endregion Partner
|
||||||
|
|
||||||
|
#region PartnerDepot
|
||||||
|
public Task<List<PartnerDepot>?> GetPartnerDepots() => GetAllAsync<List<PartnerDepot>>(SignalRTags.GetPartnerDepots);
|
||||||
|
public Task<PartnerDepot?> GetPartnerDepotById(int id) => GetByIdAsync<PartnerDepot?>(SignalRTags.GetPartnerDepotById, id);
|
||||||
|
public Task<List<PartnerDepot>?> GetPartnerDepotsByPartnerId(int partnerId) => GetAllAsync<List<PartnerDepot>>(SignalRTags.GetPartnerDepotsByPartnerId, [partnerId]);
|
||||||
|
public Task<PartnerDepot?> AddPartnerDepot(PartnerDepot partnerDepot) => PostDataAsync(SignalRTags.AddPartnerDepot, partnerDepot);
|
||||||
|
public Task<PartnerDepot?> UpdatePartnerDepot(PartnerDepot partnerDepot) => PostDataAsync(SignalRTags.UpdatePartnerDepot, partnerDepot);
|
||||||
|
#endregion PartnerDepot
|
||||||
|
|
||||||
#region CargoPartner
|
#region CargoPartner
|
||||||
public Task<List<CargoPartner>?> GetCargoPartners() => GetAllAsync<List<CargoPartner>>(SignalRTags.GetCargoPartners);
|
public Task<List<CargoPartner>?> GetCargoPartners() => GetAllAsync<List<CargoPartner>>(SignalRTags.GetCargoPartners);
|
||||||
public Task<CargoPartner?> GetCargoPartnerById(int id) => GetByIdAsync<CargoPartner?>(SignalRTags.GetCargoPartnerById, id);
|
public Task<CargoPartner?> GetCargoPartnerById(int id) => GetByIdAsync<CargoPartner?>(SignalRTags.GetCargoPartnerById, id);
|
||||||
|
|
@ -163,10 +171,10 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
|
||||||
=> GetAllAsync<List<ShippingDocument>>(SignalRTags.GetShippingDocumentsByShippingId, [shippingId]);
|
=> GetAllAsync<List<ShippingDocument>>(SignalRTags.GetShippingDocumentsByShippingId, [shippingId]);
|
||||||
|
|
||||||
public Task<List<ShippingDocument>?> GetShippingDocumentsByProductId(int productId)
|
public Task<List<ShippingDocument>?> GetShippingDocumentsByProductId(int productId)
|
||||||
=> GetAllAsync<List<ShippingDocument>>(SignalRTags.GetShippingDocumentsByShippingId, [productId]);
|
=> GetAllAsync<List<ShippingDocument>>(SignalRTags.GetShippingDocumentsByProductId, [productId]);
|
||||||
|
|
||||||
public Task<List<ShippingDocument>?> GetShippingDocumentsByPartnerId(int partnerId)
|
public Task<List<ShippingDocument>?> GetShippingDocumentsByPartnerId(int partnerId)
|
||||||
=> GetAllAsync<List<ShippingDocument>>(SignalRTags.GetShippingDocumentsByShippingId, [partnerId]);
|
=> GetAllAsync<List<ShippingDocument>>(SignalRTags.GetShippingDocumentsByPartnerId, [partnerId]);
|
||||||
|
|
||||||
public Task<ShippingDocument?> AddShippingDocument(ShippingDocument shippingDocument)
|
public Task<ShippingDocument?> AddShippingDocument(ShippingDocument shippingDocument)
|
||||||
=> PostDataAsync(SignalRTags.AddShippingDocument, shippingDocument);
|
=> PostDataAsync(SignalRTags.AddShippingDocument, shippingDocument);
|
||||||
|
|
@ -185,18 +193,29 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
|
||||||
#endregion Customer
|
#endregion Customer
|
||||||
|
|
||||||
#region Product
|
#region Product
|
||||||
|
//TODO: itt ProductDtoTableItem kéne, csak az AycodeHubProtocol ProductDto-ra deserialize-ol! - J.
|
||||||
|
//public Task<List<ProductDto>?> GetProductDtoTableItems() => GetAllAsync<List<ProductDto>>(SignalRTags.GetProductDtos);
|
||||||
|
// IDEIGLENES gyors fix: a GetProductDtos tagon a szerver List<ProductDto>-t küld, a binár
|
||||||
|
// protokoll viszont a wire-típusba (ProductDto) deszerializál — így a közvetlen
|
||||||
|
// List<ProductDtoTableItem> 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<List<ProductDtoTableItem>?> GetProductDtoTableItems()
|
||||||
|
{
|
||||||
|
var dtos = await GetProductDtos();
|
||||||
|
if (dtos == null) return null;
|
||||||
|
|
||||||
public Task<List<ProductDtoTableItem>?> GetProductDtoTableItems()
|
var bytes = SignalRSerializationHelper.SerializeToBinary(dtos);
|
||||||
=> GetAllAsync<List<ProductDtoTableItem>>(SignalRTags.GetProductDtos);
|
return SignalRSerializationHelper.DeserializeFromBinary<List<ProductDtoTableItem>>(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
public Task<List<ProductDto>?> GetProductDtos()
|
public Task<List<ProductDto>?> GetProductDtos() => GetAllAsync<List<ProductDto>>(SignalRTags.GetProductDtos);
|
||||||
=> GetAllAsync<List<ProductDto>>(SignalRTags.GetProductDtos);
|
|
||||||
|
|
||||||
//public Task<List<MeasuringProductDto>?> GetAllMeasuringProductDtos()
|
//public Task<List<MeasuringProductDto>?> GetAllMeasuringProductDtos()
|
||||||
// => GetAllAsync<List<MeasuringProductDto>>(SignalRTags.GetAllMeasuringProductDtos);
|
// => GetAllAsync<List<MeasuringProductDto>>(SignalRTags.GetAllMeasuringProductDtos);
|
||||||
|
|
||||||
public Task<ProductDto?> GetProductDtoById(int productId)
|
public Task<ProductDto?> GetProductDtoById(int productId) => GetByIdAsync<ProductDto?>(SignalRTags.GetMeasuringProductDtoById, productId);
|
||||||
=> GetByIdAsync<ProductDto?>(SignalRTags.GetMeasuringProductDtoById, productId);
|
|
||||||
|
|
||||||
#endregion Product
|
#endregion Product
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue