Compare commits

...

6 Commits

Author SHA1 Message Date
Loretta c9b0bf8334 Enhance ToonDescription docs for PreOrder entities
Expanded and clarified ToonDescription attributes for PreOrder and PreOrderItem classes. Added business rules, constraints, and improved property-level documentation to better describe allocation, conversion, and status logic. No functional changes.
2026-05-30 17:07:29 +02:00
Loretta 98799a79e1 Refactor PreOrder and CargoTruck models, add ICargoTruck
Standardized PreOrder naming across classes, enums, and constants. Updated DB table name constants. Added IsTrailer, Created, and Modified properties to CargoTruck and linked to CargoPartner. Introduced ICargoTruck interface. Added SignalR support for fetching CargoTrucks by CargoPartnerId, with related service, interface, and test updates. Improved ToonDescription docs and updated UI components for new properties and naming. Refactored for clarity and consistency.
2026-05-30 16:26:59 +02:00
Loretta 3e4d3260f0 Add logger support to grids, data sources, and helpers
- Added optional logger to TaskHelper.Forget for fire-and-forget error logging
- Updated MgGridBase and data sources to accept and use logger instances
- Refactored AcSignalRDataSource to log deserialization faults
- Modified constructors and usages of SignalRDataSourceList/Observable for logger injection
- Added CountryCode to CargoTruck and displayed in new GridCargoTruck
- Introduced GridCargoTruck.razor and base class with logger integration
- Updated GridCargoPartner to use new cargo truck grid as detail row
- Improved code style and ensured consistent error handling throughout
2026-05-30 06:47:06 +02:00
Loretta 41ccb10ef7 Add CargoTruck CRUD, grid tabs, and related tests
- Introduced LicencePlate to CargoTruck and Shippings navigation to CargoPartner.
- Implemented CargoTruck CRUD methods in IFruitBankDataControllerCommon and FruitBankSignalRClient.
- Expanded tests for CargoTruck and improved assertions for CargoPartner and Partner.
- Updated CargoPartner grid to show CargoTrucks and Shippings in detail tabs.
- Minor formatting and settings.local.json Bash command update.
2026-05-29 12:16:48 +02:00
Loretta 69010921d7 Add CargoPartner management UI and API integration
- Introduced CRUD operations for CargoPartner in IFruitBankDataControllerCommon and SignalRTags.
- Implemented CargoPartner methods in FruitBankSignalRClient.
- Added GridCargoPartner.razor and GridCargoPartnerBase.cs for CargoPartner grid UI.
- Integrated CargoPartner grid into ShippingsAdmin page.
- Added GetCargoPartnersTest; updated and commented out some tests.
- Added CountryCode column to GridPartner.razor.
- Commented out SandboxEndpointSimpleTests.
- Minor refactoring for new entity and UI support.
2026-05-28 19:48:18 +02:00
Loretta a32f91271d Refactor partner model, add CargoPartner/Truck entities
- Refactored entity classes to be sealed and use new PartnerBase
- Introduced CargoPartner and CargoTruck entities with associations
- Centralized partner properties in abstract PartnerBase
- Updated IPartner, added IPartnerBase and ICargoPartner interfaces
- Added table name constants for new entities in FruitBankConstClient
- Changed AcBinaryHubProtocol FlushPolicy to "Coalesced"
- Cleaned up unused table item classes in DatabaseClient.cs
- Added serialization and documentation attributes to entities
- Updated Preorder and PreorderItem with new structure and docs
2026-05-28 17:47:53 +02:00
44 changed files with 992 additions and 357 deletions

View File

@ -11,7 +11,8 @@
"Bash(while read:*)", "Bash(while read:*)",
"Bash(do sed -i '1a using AyCode.Core.Serializers.Toons;\\\\n' \"$f\")", "Bash(do sed -i '1a using AyCode.Core.Serializers.Toons;\\\\n' \"$f\")",
"Bash(done)", "Bash(done)",
"Bash(rm \"C:/Users/Fullepi/.claude/projects/H--Applications-Mango-Source-FruitBankHybridApp/memory/feedback_framework_docs_no_consumer_types.md\")" "Bash(rm \"C:/Users/Fullepi/.claude/projects/H--Applications-Mango-Source-FruitBankHybridApp/memory/feedback_framework_docs_no_consumer_types.md\")",
"Bash(cd \"H:/Applications/Aycode/Source/AyCode.Core/AyCode.Services.Server/bin/FruitBank\" && ls -la --time-style=full-iso Debug/net9.0/AyCode.Core.dll Release/net9.0/AyCode.Core.dll 2>&1)"
] ]
} }
} }

View File

@ -19,13 +19,13 @@ namespace FruitBank.Common.Server
/// DateTime generic attribute on Product. /// DateTime generic attribute on Product.
/// The start of the window during which this product is visible for preordering. /// The start of the window during which this product is visible for preordering.
/// </summary> /// </summary>
public const string PreorderWindowStart = "PreorderWindowStart"; public const string PreOrderWindowStart = "PreOrderWindowStart";
/// <summary> /// <summary>
/// DateTime generic attribute on Product. /// DateTime generic attribute on Product.
/// The end of the window during which this product is visible for preordering. /// The end of the window during which this product is visible for preordering.
/// </summary> /// </summary>
public const string PreorderWindowEnd = "PreorderWindowEnd"; public const string PreOrderWindowEnd = "PreOrderWindowEnd";
static FruitBankConst() static FruitBankConst()
{ {

View File

@ -0,0 +1,21 @@
using AyCode.Core.Serializers.Attributes;
using AyCode.Core.Serializers.Toons;
using FruitBank.Common.Interfaces;
using LinqToDB.Mapping;
using Mango.Nop.Core.Entities;
namespace FruitBank.Common.Entities;
[AcBinarySerializable(false, true, false, true, false, false)]
//[ToonDescription("Business partner with address and tax information", Purpose = "Represents an external legal entity, specifically a Supplier who provides goods or a business partner involved in the procurement chain")]
[Table(Name = FruitBankConstClient.CargoPartnerDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.CargoPartnerDbTableName)]
public sealed class CargoPartner : PartnerBase, ICargoPartner
{
[Association(ThisKey = nameof(Id), OtherKey = nameof(CargoTruck.CargoPartnerId), CanBeNull = true)]
public List<CargoTruck>? CargoTrucks { get; set; }
//[Association(ThisKey = nameof(Id), OtherKey = nameof(Shipping.CargoPartnerId), CanBeNull = true)]
public List<Shipping>? Shippings { get; set; }
//public decimal DecProp{get; set; }
}

View File

@ -0,0 +1,25 @@
using AyCode.Core.Serializers.Attributes;
using FruitBank.Common.Interfaces;
using LinqToDB.Mapping;
using Mango.Nop.Core.Entities;
namespace FruitBank.Common.Entities;
[AcBinarySerializable(false, true, false, true, false, false)]
//[ToonDescription("Business partner with address and tax information", Purpose = "Represents an external legal entity, specifically a Supplier who provides goods or a business partner involved in the procurement chain")]
[Table(Name = FruitBankConstClient.CargoTruckDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.CargoTruckDbTableName)]
public sealed class CargoTruck: MgEntityBase, ICargoTruck
{
public int CargoPartnerId { get; set; }
[Association(ThisKey = nameof(CargoPartnerId), OtherKey = nameof(CargoPartner.Id), CanBeNull = true)]
public CargoPartner CargoPartner { get; set; }
public string CountryCode { get; set; }
public string LicencePlate { get; set; }
public bool IsTrailer { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
}

View File

@ -4,7 +4,7 @@ using Mango.Nop.Core.Entities;
namespace FruitBank.Common.Entities; namespace FruitBank.Common.Entities;
public class CustomerCredit: MgEntityBase, IEntityComment public sealed class CustomerCredit: MgEntityBase, IEntityComment
{ {
public int CustomerId { get; set; } public int CustomerId { get; set; }
public decimal CreditLimit { get; set; } public decimal CreditLimit { get; set; }

View File

@ -10,7 +10,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Uploaded file with extracted text content", Purpose = "A centralized repository for all uploaded binary content and metadata, featuring a 'RawText' field that stores OCR-extracted information for full-text search and automated data validation across the system")] [ToonDescription("Uploaded file with extracted text content", Purpose = "A centralized repository for all uploaded binary content and metadata, featuring a 'RawText' field that stores OCR-extracted information for full-text search and automated data validation across the system")]
[Table(Name = FruitBankConstClient.FilesDbTableName)] [Table(Name = FruitBankConstClient.FilesDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.FilesDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.FilesDbTableName)]
public class Files : MgEntityBase, IFiles public sealed class Files : MgEntityBase, IFiles
{ {
public string FileName { get; set; } public string FileName { get; set; }
public string FileSubPath { get; set; } public string FileSubPath { get; set; }

View File

@ -16,7 +16,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Pallet measurements for order items with audit tracking", Purpose = "A measurement record for outgoing goods, used to verify that the net weight being sent to the customer is accurate and audited. NOTE: Despite the 'Pallet' name, this is a general measurement record that is ALWAYS created for every item. If the product is not measurable (IsMeasurable=false), weights are recorded as 0.0 and only TrayQuantity is stored.")] [ToonDescription("Pallet measurements for order items with audit tracking", Purpose = "A measurement record for outgoing goods, used to verify that the net weight being sent to the customer is accurate and audited. NOTE: Despite the 'Pallet' name, this is a general measurement record that is ALWAYS created for every item. If the product is not measurable (IsMeasurable=false), weights are recorded as 0.0 and only TrayQuantity is stored.")]
[Table(Name = FruitBankConstClient.OrderItemPalletDbTableName)] [Table(Name = FruitBankConstClient.OrderItemPalletDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.OrderItemPalletDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.OrderItemPalletDbTableName)]
public class OrderItemPallet : MeasuringItemPalletBase, IOrderItemPallet public sealed class OrderItemPallet : MeasuringItemPalletBase, IOrderItemPallet
{ {
public int OrderItemId public int OrderItemId
{ {

View File

@ -11,7 +11,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Pallet type definition with size and weight")] [ToonDescription("Pallet type definition with size and weight")]
[Table(Name = FruitBankConstClient.PalletDbTableName)] [Table(Name = FruitBankConstClient.PalletDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PalletDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PalletDbTableName)]
public class Pallet : MgEntityBase, IPallet public sealed class Pallet : MgEntityBase, IPallet
{ {
public string Name { get; set; } public string Name { get; set; }
public string Size { get; set; } public string Size { get; set; }

View File

@ -10,24 +10,8 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Business partner with address and tax information", Purpose = "Represents an external legal entity, specifically a Supplier who provides goods or a business partner involved in the procurement chain")] [ToonDescription("Business partner with address and tax information", Purpose = "Represents an external legal entity, specifically a Supplier who provides goods or a business partner involved in the procurement chain")]
[Table(Name = FruitBankConstClient.PartnerDbTableName)] [Table(Name = FruitBankConstClient.PartnerDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PartnerDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PartnerDbTableName)]
public class Partner : MgEntityBase, IPartner public sealed class Partner : PartnerBase, IPartner
{ {
public string Name { get; set; }
public string TaxId { get; set; }
public string CertificationNumber { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string State { get; set; }
public string County { get; set; }
public string City { get; set; }
public string Street { get; set; }
[Association(ThisKey = nameof(Id), OtherKey = nameof(ShippingDocument.ShippingId), CanBeNull = true)] [Association(ThisKey = nameof(Id), OtherKey = nameof(ShippingDocument.ShippingId), CanBeNull = true)]
public List<ShippingDocument>? ShippingDocuments { get; set; } public List<ShippingDocument>? ShippingDocuments { get; set; }
[SkipValuesOnUpdate]
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
} }

View File

@ -0,0 +1,25 @@
using FruitBank.Common.Interfaces;
using LinqToDB.Mapping;
using Mango.Nop.Core.Entities;
namespace FruitBank.Common.Entities;
public abstract class PartnerBase : MgEntityBase, IPartnerBase
{
public string Name { get; set; }
public string TaxId { get; set; }
public string CertificationNumber { get; set; }
public string CountryCode { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string State { get; set; }
public string County { get; set; }
public string City { get; set; }
public string Street { get; set; }
[SkipValuesOnUpdate]
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
}

File diff suppressed because one or more lines are too long

View File

@ -1,17 +1,35 @@
using FruitBank.Common.Enums; using AyCode.Core.Serializers.Attributes;
using AyCode.Core.Serializers.Toons;
using FruitBank.Common.Enums;
using LinqToDB.Mapping; using LinqToDB.Mapping;
using Mango.Nop.Core.Entities; using Mango.Nop.Core.Entities;
namespace FruitBank.Common.Entities; namespace FruitBank.Common.Entities;
[AcBinarySerializable(false, true, false, true, false, false)]
[Table(Name = FruitBankConstClient.PreOrderItemDbTableName)] [Table(Name = FruitBankConstClient.PreOrderItemDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PreOrderItemDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PreOrderItemDbTableName)]
public class PreorderItem : MgEntityBase [ToonDescription("Single product line of a customer preorder with fulfilment tracking", Purpose = "A requested product line within a PreOrder. Tracks requested versus cumulatively fulfilled quantity as incoming stock is allocated across one or more shipping-document conversion runs.")]
public sealed class PreOrderItem : MgEntityBase
{ {
public int PreorderId { get; set; } [ToonDescription(Purpose = "FK to the parent PreOrder.")]
public int PreOrderId { get; set; }
[ToonDescription(Purpose = "FK to the nopCommerce Product being preordered.")]
public int ProductId { get; set; } public int ProductId { get; set; }
[ToonDescription(Purpose = "Quantity of the product the customer requested.", Constraints = "positive")]
public int RequestedQuantity { get; set; } public int RequestedQuantity { get; set; }
[ToonDescription(Purpose = "Quantity allocated from incoming stock so far; accumulates across conversion runs until it reaches RequestedQuantity.",
BusinessRule = "this >= 0 && this <= RequestedQuantity")]
public int FulfilledQuantity { get; set; } public int FulfilledQuantity { get; set; }
[ToonDescription(Purpose = "Gross unit price locked at preorder time. Used as the order-item price on conversion for non-measurable products; measurable products are priced 0 at conversion and weighed afterwards.",
Constraints = "non-negative")]
public decimal UnitPriceInclTax { get; set; } public decimal UnitPriceInclTax { get; set; }
public PreorderItemStatus Status { get; set; }
[ToonDescription(Purpose = "Item lifecycle: Pending / Fulfilled (fully allocated) / PartiallyFulfilled (partly allocated) / Dropped (expired or no incoming stock).",
BusinessRule = "set during conversion: FulfilledQuantity >= RequestedQuantity ? Fulfilled : FulfilledQuantity > 0 ? PartiallyFulfilled : Dropped; stays Pending until first allocation")]
public PreOrderItemStatus Status { get; set; }
} }

View File

@ -11,7 +11,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Shipping record with documents and measurement tracking", Purpose = "Represents a physical inbound delivery event (truck arrival) at the warehouse, tracking the vehicle and the overall measurement status of the shipment")] [ToonDescription("Shipping record with documents and measurement tracking", Purpose = "Represents a physical inbound delivery event (truck arrival) at the warehouse, tracking the vehicle and the overall measurement status of the shipment")]
[Table(Name = FruitBankConstClient.ShippingDbTableName)] [Table(Name = FruitBankConstClient.ShippingDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDbTableName)]
public class Shipping : MgEntityBase, IShipping, IEntityComment public sealed class Shipping : MgEntityBase, IShipping, IEntityComment
{ {
public DateTime ShippingDate { get; set; } = DateTime.Now; public DateTime ShippingDate { get; set; } = DateTime.Now;
public string LicencePlate { get; set; } public string LicencePlate { get; set; }

View File

@ -11,7 +11,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Shipping document with partner, items and files", Purpose = "A digital representation of a supplier's delivery note or invoice associated with the shipment, used for reconciling paper-based data with measured reality")] [ToonDescription("Shipping document with partner, items and files", Purpose = "A digital representation of a supplier's delivery note or invoice associated with the shipment, used for reconciling paper-based data with measured reality")]
[Table(Name = FruitBankConstClient.ShippingDocumentDbTableName)] [Table(Name = FruitBankConstClient.ShippingDocumentDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDocumentDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDocumentDbTableName)]
public class ShippingDocument : MgEntityBase, IShippingDocument public sealed class ShippingDocument : MgEntityBase, IShippingDocument
{ {
public int PartnerId { get; set; } public int PartnerId { get; set; }
public int? ShippingId { get; set; } public int? ShippingId { get; set; }

View File

@ -12,7 +12,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Links shipping documents to files with document type", Purpose = "A many-to-many link table that associates general uploaded files with specific shipping documents, assigning a functional context (DocumentType) to each file, such as identifying which PDF is the supplier's invoice versus the packing list")] [ToonDescription("Links shipping documents to files with document type", Purpose = "A many-to-many link table that associates general uploaded files with specific shipping documents, assigning a functional context (DocumentType) to each file, such as identifying which PDF is the supplier's invoice versus the packing list")]
[LinqToDB.Mapping.Table(Name = FruitBankConstClient.ShippingDocumentToFilesDbTableName)] [LinqToDB.Mapping.Table(Name = FruitBankConstClient.ShippingDocumentToFilesDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDocumentToFilesDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingDocumentToFilesDbTableName)]
public class ShippingDocumentToFiles : MgEntityBase, IShippingDocumentToFiles public sealed class ShippingDocumentToFiles : MgEntityBase, IShippingDocumentToFiles
{ {
public int FilesId { get; set; } public int FilesId { get; set; }

View File

@ -12,7 +12,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Pallet measurements for shipping items", Purpose = "The smallest unit of measurement tracking, representing a single physical measurement event. NOTE: Technically named 'Pallet' for legacy reasons, but it is ALWAYS created even if goods arrive without a physical pallet. For non-measurable products, weights are 0.0 and only TrayQuantity is tracked for tare-weight calculations.")] [ToonDescription("Pallet measurements for shipping items", Purpose = "The smallest unit of measurement tracking, representing a single physical measurement event. NOTE: Technically named 'Pallet' for legacy reasons, but it is ALWAYS created even if goods arrive without a physical pallet. For non-measurable products, weights are 0.0 and only TrayQuantity is tracked for tare-weight calculations.")]
[LinqToDB.Mapping.Table(Name = FruitBankConstClient.ShippingItemPalletDbTableName)] [LinqToDB.Mapping.Table(Name = FruitBankConstClient.ShippingItemPalletDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingItemPalletDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.ShippingItemPalletDbTableName)]
public class ShippingItemPallet : MeasuringItemPalletBase, IShippingItemPallet public sealed class ShippingItemPallet : MeasuringItemPalletBase, IShippingItemPallet
{ {
public int ShippingItemId public int ShippingItemId
{ {

View File

@ -19,7 +19,7 @@ namespace FruitBank.Common.Entities
[Table(Name = FruitBankConstClient.StockQuantityHistoryExtDbTableName)] [Table(Name = FruitBankConstClient.StockQuantityHistoryExtDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockQuantityHistoryExtDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockQuantityHistoryExtDbTableName)]
[ToonDescription("Extended weight-metadata for StockQuantityHistory", Purpose = "Validates quantity deltas against measured weight to detect inconsistencies")] [ToonDescription("Extended weight-metadata for StockQuantityHistory", Purpose = "Validates quantity deltas against measured weight to detect inconsistencies")]
public class StockQuantityHistoryExt : MgEntityBase, IStockQuantityHistoryExt public sealed class StockQuantityHistoryExt : MgEntityBase, IStockQuantityHistoryExt
{ {
public int StockQuantityHistoryId { get; set; } public int StockQuantityHistoryId { get; set; }

View File

@ -9,7 +9,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Inventory session record", Purpose = "Orchestrates inventory sessions by freezing logical stock states")] [ToonDescription("Inventory session record", Purpose = "Orchestrates inventory sessions by freezing logical stock states")]
[Table(Name = FruitBankConstClient.StockTakingDbTableName)] [Table(Name = FruitBankConstClient.StockTakingDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockTakingDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockTakingDbTableName)]
public class StockTaking : MgStockTaking<StockTakingItem> public sealed class StockTaking : MgStockTaking<StockTakingItem>
{ {
public override bool IsReadyForClose() public override bool IsReadyForClose()
{ {

View File

@ -15,7 +15,7 @@ namespace FruitBank.Common.Entities;
[ToonDescription("Line item for product reconciliation", Purpose = "Reconciles snapshot quantity with physical count to calculate final stock delta")] [ToonDescription("Line item for product reconciliation", Purpose = "Reconciles snapshot quantity with physical count to calculate final stock delta")]
[Table(Name = FruitBankConstClient.StockTakingItemDbTableName)] [Table(Name = FruitBankConstClient.StockTakingItemDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockTakingItemDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockTakingItemDbTableName)]
public class StockTakingItem : MgStockTakingItem<StockTaking, ProductDto> public sealed class StockTakingItem : MgStockTakingItem<StockTaking, ProductDto>
{ {
public bool IsMeasurable { get; set; } public bool IsMeasurable { get; set; }

View File

@ -18,7 +18,7 @@ public interface IStockTakingItemPallet : IMeasuringItemPalletBase
[ToonDescription("Weight record for inventory item", Purpose = "Granular weight-based evidence for a stock taking line item. NOTE: This record is mandatory for every inventory item. If weighing is skipped (non-measurable), it serves as a container for TrayQuantity with zeroed weight fields. The term 'Pallet' is a legacy naming convention.")] [ToonDescription("Weight record for inventory item", Purpose = "Granular weight-based evidence for a stock taking line item. NOTE: This record is mandatory for every inventory item. If weighing is skipped (non-measurable), it serves as a container for TrayQuantity with zeroed weight fields. The term 'Pallet' is a legacy naming convention.")]
[LinqToDB.Mapping.Table(Name = FruitBankConstClient.StockTakingItemPalletDbTableName)] [LinqToDB.Mapping.Table(Name = FruitBankConstClient.StockTakingItemPalletDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockTakingItemPalletDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockTakingItemPalletDbTableName)]
public class StockTakingItemPallet : MeasuringItemPalletBase, IStockTakingItemPallet public sealed class StockTakingItemPallet : MeasuringItemPalletBase, IStockTakingItemPallet
{ {
public int StockTakingItemId public int StockTakingItemId
{ {

View File

@ -1,6 +1,6 @@
namespace FruitBank.Common.Enums; namespace FruitBank.Common.Enums;
public enum PreorderItemStatus public enum PreOrderItemStatus
{ {
Pending = 0, Pending = 0,
Fulfilled = 10, Fulfilled = 10,

View File

@ -2,7 +2,7 @@
namespace FruitBank.Common.Enums; namespace FruitBank.Common.Enums;
public enum PreorderStatus public enum PreOrderStatus
{ {
Pending = 0, Pending = 0,
Confirmed = 10, Confirmed = 10,

View File

@ -46,8 +46,11 @@ public static class FruitBankConstClient
public const string StockTakingItemPalletDbTableName = "fbStockTakingItemPallet"; public const string StockTakingItemPalletDbTableName = "fbStockTakingItemPallet";
public const string CustomerCreditDbTableName = "fbCustomerCredit"; public const string CustomerCreditDbTableName = "fbCustomerCredit";
public const string PreOrderDbTableName = "fbPreorder"; public const string PreOrderDbTableName = "fbPreOrder";
public const string PreOrderItemDbTableName = "fbPreorderItem"; public const string PreOrderItemDbTableName = "fbPreOrderItem";
public const string CargoPartnerDbTableName = "fbCargoPartner";
public const string CargoTruckDbTableName = "fbCargoTruck";
public const string DomainDescription = "This is a nopCommerce plugin developed for FruitBank, a fruit and vegetable wholesaler. The plugin manages supplier inbound delivery (receiving), warehouse weighing (net/gross/pallet/tare weights), and inventory stocktaking. The business logic is centered around FruitBank's requirement for precise physical measurement and quantity tracking."; public const string DomainDescription = "This is a nopCommerce plugin developed for FruitBank, a fruit and vegetable wholesaler. The plugin manages supplier inbound delivery (receiving), warehouse weighing (net/gross/pallet/tare weights), and inventory stocktaking. The business logic is centered around FruitBank's requirement for precise physical measurement and quantity tracking.";

View File

@ -0,0 +1,17 @@
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.TimeStampInfo;
using FruitBank.Common.Entities;
namespace FruitBank.Common.Interfaces;
public interface ICargoTruck : IEntityInt, ITimeStampInfo
{
public int CargoPartnerId { get; set; }
public CargoPartner CargoPartner { get; set; }
public string CountryCode { get; set; }
public string LicencePlate { get; set; }
public bool IsTrailer { get; set; }
}

View File

@ -1,6 +1,7 @@
using FruitBank.Common.Dtos; using FruitBank.Common.Dtos;
using FruitBank.Common.Entities; using FruitBank.Common.Entities;
using FruitBank.Common.Models; using FruitBank.Common.Models;
using FruitBank.Common.SignalRs;
using Mango.Nop.Core.Dtos; using Mango.Nop.Core.Dtos;
using Mango.Nop.Core.Entities; using Mango.Nop.Core.Entities;
using Mango.Nop.Core.Models; using Mango.Nop.Core.Models;
@ -19,6 +20,21 @@ public interface IFruitBankDataControllerCommon
public Task<Partner?> UpdatePartner(Partner partner); public Task<Partner?> UpdatePartner(Partner partner);
#endregion Partner #endregion Partner
#region CargoPartner
public Task<List<CargoPartner>?> GetCargoPartners();
public Task<CargoPartner?> GetCargoPartnerById(int id);
public Task<CargoPartner?> AddCargoPartner(CargoPartner cargoPartner);
public Task<CargoPartner?> UpdateCargoPartner(CargoPartner cargoPartner);
#endregion CargoPartner
#region CargoTruck
public Task<List<CargoTruck>?> GetCargoTrucks();
public Task<CargoTruck?> GetCargoTruckById(int id);
public Task<List<CargoTruck>?> GetCargoTrucksByCargoPartnerId(int cargoPartnerId);
public Task<CargoTruck?> AddCargoTruck(CargoTruck cargoTruck);
public Task<CargoTruck?> UpdateCargoTruck(CargoTruck cargoTruck);
#endregion CargoTruck
#region Shipping #region Shipping
public Task<List<Shipping>?> GetShippings(); public Task<List<Shipping>?> GetShippings();
Task<List<Shipping>?> GetNotMeasuredShippings(); Task<List<Shipping>?> GetNotMeasuredShippings();

View File

@ -4,17 +4,26 @@ using FruitBank.Common.Entities;
namespace FruitBank.Common.Interfaces; namespace FruitBank.Common.Interfaces;
public interface IPartner : IEntityInt, ITimeStampInfo public interface ICargoPartner : IPartnerBase
{
List<CargoTruck>? CargoTrucks { get; set; }
}
public interface IPartner : IPartnerBase
{
List<ShippingDocument>? ShippingDocuments { get; set; }
}
public interface IPartnerBase : IEntityInt, ITimeStampInfo
{ {
string Name { get; set; } string Name { get; set; }
string TaxId { get; set; } string TaxId { get; set; }
string CertificationNumber { get; set; } string CertificationNumber { get; set; }
string CountryCode { get; set; }
string PostalCode { get; set; } string PostalCode { get; set; }
string Country { get; set; } string Country { get; set; }
string State { get; set; } string State { get; set; }
string County { get; set; } string County { get; set; }
string City { get; set; } string City { get; set; }
string Street { get; set; } string Street { get; set; }
List<ShippingDocument>? ShippingDocuments { get; set; }
} }

View File

@ -15,6 +15,17 @@ public class SignalRTags : AcSignalRTags
public const int AddPartner = 25; public const int AddPartner = 25;
public const int UpdatePartner = 26; public const int UpdatePartner = 26;
public const int GetCargoPartners = 30;
public const int GetCargoPartnerById = 31;
public const int AddCargoPartner = 32;
public const int UpdateCargoPartner = 33;
public const int GetCargoTrucks = 35;
public const int GetCargoTrucksByCargoPartnerId = 36;
public const int GetCargoTruckById = 37;
public const int AddCargoTruck = 38;
public const int UpdateCargoTruck = 39;
public const int GetShippings = 40; public const int GetShippings = 40;
public const int GetNotMeasuredShippings = 41; public const int GetNotMeasuredShippings = 41;
public const int GetShippingById = 42; public const int GetShippingById = 42;

View File

@ -42,22 +42,22 @@ namespace FruitBankHybrid.Shared.Tests
var partners = await _signalRClient.GetPartners(); var partners = await _signalRClient.GetPartners();
Assert.IsNotNull(partners); Assert.IsNotNull(partners);
Assert.IsTrue(partners.Count != 0); Assert.IsNotEmpty(partners);
} }
//[DataTestMethod] //[TestMethod]
//[DataRow(1)] //[DataRow(1)]
public async Task<Partner> GetPartnerByIdTest(int partnerId) public async Task<Partner> GetPartnerByIdTest(int partnerId)
{ {
var partner = await _signalRClient.GetPartnerById(partnerId); var partner = await _signalRClient.GetPartnerById(partnerId);
Assert.IsNotNull(partner); Assert.IsNotNull(partner);
Assert.IsTrue(partner.Id == partnerId); Assert.AreEqual(partnerId, partner.Id);
return partner; return partner;
} }
[DataTestMethod] [TestMethod]
[DataRow(2)] [DataRow(2)]
public async Task UpdatePartnerTest(int partnerId) public async Task UpdatePartnerTest(int partnerId)
{ {
@ -75,10 +75,108 @@ namespace FruitBankHybrid.Shared.Tests
partner = await _signalRClient.UpdatePartner(partner); partner = await _signalRClient.UpdatePartner(partner);
Assert.IsNotNull(partner); Assert.IsNotNull(partner);
Assert.IsTrue(partner.Id == partnerId); Assert.AreEqual(partnerId, partner.Id);
} }
#endregion Partner #endregion Partner
#region CargoPartner
[TestMethod]
public async Task GetCargoPartnersTest()
{
var partners = await _signalRClient.GetCargoPartners();
Assert.IsNotNull(partners);
Assert.IsNotEmpty(partners);
}
//[TestMethod]
//[DataRow(1)]
public async Task<CargoPartner> GetCargoPartnerByIdTest(int cargoPartnerId)
{
var cargoPartner = await _signalRClient.GetCargoPartnerById(cargoPartnerId);
Assert.IsNotNull(cargoPartner);
Assert.AreEqual(cargoPartnerId, cargoPartner.Id);
return cargoPartner;
}
[TestMethod]
[DataRow(1)]
public async Task UpdateCargoPartnerTest(int cargoPartnerId)
{
var cargoPartner = await GetCargoPartnerByIdTest(cargoPartnerId);
var newName = GetFixtureName(cargoPartner.Name);
cargoPartner.Name = newName;
cargoPartner = await _signalRClient.UpdateCargoPartner(cargoPartner);
Assert.IsNotNull(cargoPartner);
Assert.IsTrue(cargoPartner.Name == newName);
cargoPartner.Name = GetOriginalName(cargoPartner.Name);
cargoPartner = await _signalRClient.UpdateCargoPartner(cargoPartner);
Assert.IsNotNull(cargoPartner);
Assert.AreEqual(cargoPartnerId, cargoPartner.Id);
}
#endregion CargoPartner
#region CargoTruck
[TestMethod]
public async Task GetCargoTrucksTest()
{
var cargoTrucks = await _signalRClient.GetCargoTrucks();
Assert.IsNotNull(cargoTrucks);
Assert.IsNotEmpty(cargoTrucks);
}
//[TestMethod]
//[DataRow(1)]
public async Task<CargoTruck> GetCargoTruckByIdTest(int cargoTruckId)
{
var cargoTruck = await _signalRClient.GetCargoTruckById(cargoTruckId);
Assert.IsNotNull(cargoTruck);
Assert.AreEqual(cargoTruckId, cargoTruck.Id);
return cargoTruck;
}
[TestMethod]
[DataRow(1)]
public async Task GetCargoTrucksByCargoPartnerIdTest(int cargoPartnerId)
{
var cargoTrucks = await _signalRClient.GetCargoTrucksByCargoPartnerId(cargoPartnerId);
Assert.IsNotNull(cargoTrucks);
Assert.IsNotEmpty(cargoTrucks);
}
[TestMethod]
[DataRow(1)]
public async Task UpdateCargoTruckTest(int cargoTruckId)
{
var cargoTruck = await GetCargoTruckByIdTest(cargoTruckId);
var newLicencePlate = GetFixtureName(cargoTruck.LicencePlate);
cargoTruck.LicencePlate = newLicencePlate;
cargoTruck = await _signalRClient.UpdateCargoTruck(cargoTruck);
Assert.IsNotNull(cargoTruck);
Assert.IsTrue(cargoTruck.LicencePlate == newLicencePlate);
cargoTruck.LicencePlate = GetOriginalName(cargoTruck.LicencePlate);
cargoTruck = await _signalRClient.UpdateCargoTruck(cargoTruck);
Assert.IsNotNull(cargoTruck);
Assert.AreEqual(cargoTruckId, cargoTruck.Id);
}
#endregion CargoTruck
#region Shipping #region Shipping
[TestMethod] [TestMethod]
public async Task GetShippingsTest() public async Task GetShippingsTest()
@ -86,7 +184,7 @@ namespace FruitBankHybrid.Shared.Tests
var shippings = await _signalRClient.GetShippings(); var shippings = await _signalRClient.GetShippings();
Assert.IsNotNull(shippings); Assert.IsNotNull(shippings);
Assert.IsTrue(shippings.Count != 0); Assert.IsNotEmpty(shippings);
} }
[TestMethod] [TestMethod]
@ -456,7 +554,7 @@ namespace FruitBankHybrid.Shared.Tests
[DataRow(5, true)] [DataRow(5, true)]
//[DataRow(6, false)] //[DataRow(6, false)]
[DataRow(33, true)] [DataRow(33, true)]
[DataRow(64, false)] //[DataRow(64, false)]
[DataRow(7, true)] [DataRow(7, true)]
public async Task GetProductDtoByIdTest(int productId, bool isMeasurableExcepted) public async Task GetProductDtoByIdTest(int productId, bool isMeasurableExcepted)
{ {

View File

@ -1,316 +1,316 @@
using AyCode.Core.Enums; //using AyCode.Core.Enums;
using AyCode.Core.Loggers; //using AyCode.Core.Loggers;
using AyCode.Utils.Extensions; //using AyCode.Utils.Extensions;
using FruitBank.Common; //using FruitBank.Common;
using FruitBank.Common.Dtos; //using FruitBank.Common.Dtos;
using FruitBank.Common.Entities; //using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces; //using FruitBank.Common.Interfaces;
using FruitBank.Common.Loggers; //using FruitBank.Common.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs; //using FruitBankHybrid.Shared.Services.SignalRs;
using System.Diagnostics.CodeAnalysis; //using System.Diagnostics.CodeAnalysis;
using FruitBank.Common.SignalRs; //using FruitBank.Common.SignalRs;
using AyCode.Services.SignalRs; //using AyCode.Services.SignalRs;
namespace FruitBankHybrid.Shared.Tests; //namespace FruitBankHybrid.Shared.Tests;
/// <summary> ///// <summary>
/// Teszt a TestSignalREndpoint-hoz. ///// Teszt a TestSignalREndpoint-hoz.
/// FONTOS: A SANDBOX-ot manu<6E>lisan kell elind<6E>tani a tesztek futtat<61>sa el<65>tt! ///// FONTOS: A SANDBOX-ot manu<6E>lisan kell elind<6E>tani a tesztek futtat<61>sa el<65>tt!
/// Ind<6E>t<EFBFBD>s: dotnet run --project Mango.Sandbox.EndPoints --urls http://localhost:59579 ///// Ind<6E>t<EFBFBD>s: dotnet run --project Mango.Sandbox.EndPoints --urls http://localhost:59579
/// </summary> ///// </summary>
[TestClass] //[TestClass]
public class SandboxEndpointSimpleTests //public class SandboxEndpointSimpleTests
{ //{
private static readonly string SandboxUrl = FruitBankConstClient.BaseUrl; //"http://localhost:59579"; // private static readonly string SandboxUrl = FruitBankConstClient.BaseUrl; //"http://localhost:59579";
private static readonly string HubUrl = $"{SandboxUrl}/fbHub"; // private static readonly string HubUrl = $"{SandboxUrl}/fbHub";
// Teszt SignalR Tags (TestSignalRTags-b<>l) // // Teszt SignalR Tags (TestSignalRTags-b<>l)
private const int PingTag = SignalRTags.PingTag; // private const int PingTag = SignalRTags.PingTag;
private const int EchoTag = SignalRTags.EchoTag; // private const int EchoTag = SignalRTags.EchoTag;
private const int GetTestItemsTag = 9003; // private const int GetTestItemsTag = 9003;
private FruitBankSignalRClient _signalRClient = null!; // private FruitBankSignalRClient _signalRClient = null!;
[TestInitialize] // [TestInitialize]
public void TestInit() // public void TestInit()
{ // {
if (!SandboxUrl.Contains("localhost:")) throw new Exception("NEM LOCALHOST-ON TESZTEL<45>NK!"); // if (!SandboxUrl.Contains("localhost:")) throw new Exception("NEM LOCALHOST-ON TESZTEL<45>NK!");
_signalRClient = TestSignalRClientFactory.Create(nameof(SandboxEndpointSimpleTests)); // _signalRClient = TestSignalRClientFactory.Create(nameof(SandboxEndpointSimpleTests));
} // }
#region HTTP Endpoint Tests // #region HTTP Endpoint Tests
[TestMethod] // [TestMethod]
public async Task HealthEndpoint_ReturnsSuccess() // public async Task HealthEndpoint_ReturnsSuccess()
{ // {
using var httpClient = new HttpClient(); // using var httpClient = new HttpClient();
var response = await httpClient.GetAsync($"{SandboxUrl}/health"); // var response = await httpClient.GetAsync($"{SandboxUrl}/health");
Assert.IsTrue(response.IsSuccessStatusCode, $"Health endpoint returned {response.StatusCode}"); // Assert.IsTrue(response.IsSuccessStatusCode, $"Health endpoint returned {response.StatusCode}");
} // }
[TestMethod] // [TestMethod]
public async Task RootEndpoint_ReturnsSandboxIsRunning() // public async Task RootEndpoint_ReturnsSandboxIsRunning()
{ // {
using var httpClient = new HttpClient(); // using var httpClient = new HttpClient();
var response = await httpClient.GetStringAsync(SandboxUrl); // var response = await httpClient.GetStringAsync(SandboxUrl);
Assert.AreEqual("SANDBOX is running!", response); // Assert.AreEqual("SANDBOX is running!", response);
} // }
#endregion // #endregion
#region SignalR Connection Tests // #region SignalR Connection Tests
[TestMethod] // [TestMethod]
public async Task SignalR_Negotiate_ReturnsSuccess() // public async Task SignalR_Negotiate_ReturnsSuccess()
{ // {
using var httpClient = new HttpClient(); // using var httpClient = new HttpClient();
var response = await httpClient.PostAsync($"{HubUrl}/negotiate?negotiateVersion=1", null); // var response = await httpClient.PostAsync($"{HubUrl}/negotiate?negotiateVersion=1", null);
Assert.IsTrue(response.IsSuccessStatusCode, $"SignalR negotiate returned {response.StatusCode}"); // Assert.IsTrue(response.IsSuccessStatusCode, $"SignalR negotiate returned {response.StatusCode}");
} // }
[TestMethod] // [TestMethod]
public async Task SignalR_Connect_Succeeds() // public async Task SignalR_Connect_Succeeds()
{ // {
var testItems = await _signalRClient.GetAllAsync<List<TestItem>>(GetTestItemsTag); // var testItems = await _signalRClient.GetAllAsync<List<TestItem>>(GetTestItemsTag);
Assert.IsNotNull(testItems); // Assert.IsNotNull(testItems);
} // }
public class TestItem // public class TestItem
{ // {
public int Id { get; set; } // public int Id { get; set; }
public string Name { get; set; } = string.Empty; // public string Name { get; set; } = string.Empty;
public decimal Value { get; set; } // public decimal Value { get; set; }
} // }
//[TestMethod] ////[TestMethod]
//public async Task SignalR_Connect_Succeeds() // //public async Task SignalR_Connect_Succeeds()
//{ // //{
// var connection = new HubConnectionBuilder() // // var connection = new HubConnectionBuilder()
// .WithUrl(HubUrl) // // .WithUrl(HubUrl)
// .Build(); // // .Build();
// try // // try
// { // // {
// await connection.StartAsync(); // // await connection.StartAsync();
// Assert.AreEqual(HubConnectionState.Connected, connection.State); // // Assert.AreEqual(HubConnectionState.Connected, connection.State);
// } // // }
// finally // // finally
// { // // {
// await connection.StopAsync(); // // await connection.StopAsync();
// } // // }
//} // //}
//#endregion // //#endregion
//#region TestSignalREndpoint Tests // //#region TestSignalREndpoint Tests
//[TestMethod] // //[TestMethod]
//public async Task SignalR_Ping_ReturnsResponse() // //public async Task SignalR_Ping_ReturnsResponse()
//{ // //{
// var testMessage = "Hello SignalR!"; // // var testMessage = "Hello SignalR!";
// await TestSignalREndpoint(PingTag, testMessage, "Ping", response => // // await TestSignalREndpoint(PingTag, testMessage, "Ping", response =>
// { // // {
// Assert.IsNotNull(response, "Response should not be null"); // // Assert.IsNotNull(response, "Response should not be null");
// // Parse JSON response // // // Parse JSON response
// using var jsonDoc = JsonDocument.Parse(response); // // using var jsonDoc = JsonDocument.Parse(response);
// var root = jsonDoc.RootElement; // // var root = jsonDoc.RootElement;
// // Ellen<65>rizz<7A>k, hogy van Message property // // // Ellen<65>rizz<7A>k, hogy van Message property
// Assert.IsTrue(root.TryGetProperty("Message", out var messageElement) || // // Assert.IsTrue(root.TryGetProperty("Message", out var messageElement) ||
// root.TryGetProperty("message", out messageElement), // // root.TryGetProperty("message", out messageElement),
// "Response should contain 'Message' property"); // // "Response should contain 'Message' property");
// Console.WriteLine($"[Ping] Received message: {messageElement.GetString()}"); // // Console.WriteLine($"[Ping] Received message: {messageElement.GetString()}");
// }); // // });
//} // //}
//[TestMethod] // //[TestMethod]
//public async Task SignalR_Echo_ReturnsEchoedData() // //public async Task SignalR_Echo_ReturnsEchoedData()
//{ // //{
// var request = new { Id = 42, Name = "TestName" }; // // var request = new { Id = 42, Name = "TestName" };
// await TestSignalREndpoint(EchoTag, request, "Echo", response => // // await TestSignalREndpoint(EchoTag, request, "Echo", response =>
// { // // {
// Assert.IsNotNull(response, "Response should not be null"); // // Assert.IsNotNull(response, "Response should not be null");
// using var jsonDoc = JsonDocument.Parse(response); // // using var jsonDoc = JsonDocument.Parse(response);
// var root = jsonDoc.RootElement; // // var root = jsonDoc.RootElement;
// // Ellen<65>rizz<7A>k az Id-t // // // Ellen<65>rizz<7A>k az Id-t
// Assert.IsTrue(root.TryGetProperty("Id", out var idElement) || // // Assert.IsTrue(root.TryGetProperty("Id", out var idElement) ||
// root.TryGetProperty("id", out idElement), // // root.TryGetProperty("id", out idElement),
// "Response should contain 'Id' property"); // // "Response should contain 'Id' property");
// Assert.AreEqual(42, idElement.GetInt32(), "Id should be 42"); // // Assert.AreEqual(42, idElement.GetInt32(), "Id should be 42");
// // Ellen<65>rizz<7A>k a Name-et // // // Ellen<65>rizz<7A>k a Name-et
// Assert.IsTrue(root.TryGetProperty("Name", out var nameElement) || // // Assert.IsTrue(root.TryGetProperty("Name", out var nameElement) ||
// root.TryGetProperty("name", out nameElement), // // root.TryGetProperty("name", out nameElement),
// "Response should contain 'Name' property"); // // "Response should contain 'Name' property");
// Assert.AreEqual("TestName", nameElement.GetString(), "Name should be 'TestName'"); // // Assert.AreEqual("TestName", nameElement.GetString(), "Name should be 'TestName'");
// Console.WriteLine($"[Echo] Received: Id={idElement.GetInt32()}, Name={nameElement.GetString()}"); // // Console.WriteLine($"[Echo] Received: Id={idElement.GetInt32()}, Name={nameElement.GetString()}");
// }); // // });
//} // //}
//[TestMethod] // //[TestMethod]
//public async Task SignalR_GetTestItems_ReturnsItemList() // //public async Task SignalR_GetTestItems_ReturnsItemList()
//{ // //{
// await TestSignalREndpoint(GetTestItemsTag, null, "GetTestItems", response => // // await TestSignalREndpoint(GetTestItemsTag, null, "GetTestItems", response =>
// { // // {
// Assert.IsNotNull(response, "Response should not be null"); // // Assert.IsNotNull(response, "Response should not be null");
// using var jsonDoc = JsonDocument.Parse(response); // // using var jsonDoc = JsonDocument.Parse(response);
// var root = jsonDoc.RootElement; // // var root = jsonDoc.RootElement;
// // Ellen<65>rizz<7A>k, hogy t<>mb-e // // // Ellen<65>rizz<7A>k, hogy t<>mb-e
// Assert.AreEqual(JsonValueKind.Array, root.ValueKind, "Response should be an array"); // // Assert.AreEqual(JsonValueKind.Array, root.ValueKind, "Response should be an array");
// Assert.IsTrue(root.GetArrayLength() > 0, "Array should have items"); // // Assert.IsTrue(root.GetArrayLength() > 0, "Array should have items");
// Console.WriteLine($"[GetTestItems] Received {root.GetArrayLength()} items"); // // Console.WriteLine($"[GetTestItems] Received {root.GetArrayLength()} items");
// // Ellen<65>rizz<7A>k az els<6C> elemet // // // Ellen<65>rizz<7A>k az els<6C> elemet
// var firstItem = root[0]; // // var firstItem = root[0];
// Assert.IsTrue(firstItem.TryGetProperty("Id", out _) || firstItem.TryGetProperty("id", out _), // // Assert.IsTrue(firstItem.TryGetProperty("Id", out _) || firstItem.TryGetProperty("id", out _),
// "Item should have 'Id' property"); // // "Item should have 'Id' property");
// Assert.IsTrue(firstItem.TryGetProperty("Name", out _) || firstItem.TryGetProperty("name", out _), // // Assert.IsTrue(firstItem.TryGetProperty("Name", out _) || firstItem.TryGetProperty("name", out _),
// "Item should have 'Name' property"); // // "Item should have 'Name' property");
// }); // // });
//} // //}
//#endregion // //#endregion
//#region EREDETI BUSINESS ENDPOINT TESZTEK - KIKOMMENTEZVE // //#region EREDETI BUSINESS ENDPOINT TESZTEK - KIKOMMENTEZVE
//// =========================================== // //// ===========================================
//// === Az al<61>bbi tesztek az eredeti 3 endpoint-ot tesztelik === // //// === Az al<61>bbi tesztek az eredeti 3 endpoint-ot tesztelik ===
//// === Vissza<7A>ll<6C>t<EFBFBD>shoz: t<>r<EFBFBD>ld a kommenteket <20>s regisztr<74>ld az endpoint-okat a Program.cs-ben === // //// === Vissza<7A>ll<6C>t<EFBFBD>shoz: t<>r<EFBFBD>ld a kommenteket <20>s regisztr<74>ld az endpoint-okat a Program.cs-ben ===
//// =========================================== // //// ===========================================
//// [TestMethod] // //// [TestMethod]
//// public async Task SignalR_GetMeasuringUsers_ReturnsJson() // //// public async Task SignalR_GetMeasuringUsers_ReturnsJson()
//// { // //// {
//// await TestSignalREndpoint(GetMeasuringUsersTag, null, "GetMeasuringUsers"); // //// await TestSignalREndpoint(GetMeasuringUsersTag, null, "GetMeasuringUsers");
//// } // //// }
//// [TestMethod] // //// [TestMethod]
//// public async Task SignalR_GetStockQuantityHistoryDtos_ReturnsJson() // //// public async Task SignalR_GetStockQuantityHistoryDtos_ReturnsJson()
//// { // //// {
//// await TestSignalREndpoint(GetStockQuantityHistoryDtosTag, null, "GetStockQuantityHistoryDtos"); // //// await TestSignalREndpoint(GetStockQuantityHistoryDtosTag, null, "GetStockQuantityHistoryDtos");
//// } // //// }
//// [TestMethod] // //// [TestMethod]
//// public async Task SignalR_GetStockQuantityHistoryDtosByProductId_ReturnsJson() // //// public async Task SignalR_GetStockQuantityHistoryDtosByProductId_ReturnsJson()
//// { // //// {
//// // ProductId = 10 // //// // ProductId = 10
//// await TestSignalREndpoint(GetStockQuantityHistoryDtosByProductIdTag, 10, "GetStockQuantityHistoryDtosByProductId"); // //// await TestSignalREndpoint(GetStockQuantityHistoryDtosByProductIdTag, 10, "GetStockQuantityHistoryDtosByProductId");
//// } // //// }
//// [TestMethod] // //// [TestMethod]
//// public async Task SignalR_GetShippingDocumentsByShippingId_ReturnsJson() // //// public async Task SignalR_GetShippingDocumentsByShippingId_ReturnsJson()
//// { // //// {
//// // ShippingId = 5 // //// // ShippingId = 5
//// await TestSignalREndpoint(GetShippingDocumentsByShippingIdTag, 5, "GetShippingDocumentsByShippingId"); // //// await TestSignalREndpoint(GetShippingDocumentsByShippingIdTag, 5, "GetShippingDocumentsByShippingId");
//// } // //// }
//// [TestMethod] // //// [TestMethod]
//// public async Task SignalR_GetOrderDtoById_ReturnsJson() // //// public async Task SignalR_GetOrderDtoById_ReturnsJson()
//// { // //// {
//// // OrderId = 15 // //// // OrderId = 15
//// await TestSignalREndpoint(GetOrderDtoByIdTag, 15, "GetOrderDtoById"); // //// await TestSignalREndpoint(GetOrderDtoByIdTag, 15, "GetOrderDtoById");
//// } // //// }
//// [TestMethod] // //// [TestMethod]
//// public async Task SignalR_GetStockTakingItemsById_ReturnsJson() // //// public async Task SignalR_GetStockTakingItemsById_ReturnsJson()
//// { // //// {
//// // StockTakingItemId = 200 // //// // StockTakingItemId = 200
//// await TestSignalREndpoint(GetStockTakingItemsByIdTag, 200, "GetStockTakingItemsById"); // //// await TestSignalREndpoint(GetStockTakingItemsByIdTag, 200, "GetStockTakingItemsById");
//// } // //// }
//#endregion // //#endregion
//#region Helper Methods // //#region Helper Methods
//private async Task TestSignalREndpoint(int tag, object? parameter, string endpointName, Action<string?>? validateResponse = null) // //private async Task TestSignalREndpoint(int tag, object? parameter, string endpointName, Action<string?>? validateResponse = null)
//{ // //{
// var connection = new HubConnectionBuilder() // // var connection = new HubConnectionBuilder()
// .WithUrl(HubUrl) // // .WithUrl(HubUrl)
// .Build(); // // .Build();
// string? receivedJson = null; // // string? receivedJson = null;
// int receivedTag = -1; // // int receivedTag = -1;
// var responseReceived = new TaskCompletionSource<bool>(); // // var responseReceived = new TaskCompletionSource<bool>();
// connection.On<int, byte[]>("ReceiveMessage", (responseTag, data) => // // connection.On<int, byte[]>("ReceiveMessage", (responseTag, data) =>
// { // // {
// receivedTag = responseTag; // // receivedTag = responseTag;
// if (data != null && data.Length > 0) // // if (data != null && data.Length > 0)
// { // // {
// receivedJson = Encoding.UTF8.GetString(data); // // receivedJson = Encoding.UTF8.GetString(data);
// } // // }
// responseReceived.TrySetResult(true); // // responseReceived.TrySetResult(true);
// }); // // });
// try // // try
// { // // {
// await connection.StartAsync(); // // await connection.StartAsync();
// Assert.AreEqual(HubConnectionState.Connected, connection.State, $"Failed to connect to SignalR hub for {endpointName}"); // // Assert.AreEqual(HubConnectionState.Connected, connection.State, $"Failed to connect to SignalR hub for {endpointName}");
// // K<>sz<73>ts<74>k el a request data-t // // // K<>sz<73>ts<74>k el a request data-t
// // Ha nincs param<61>ter, null-t k<>ld<6C>nk (nem <20>res byte t<>mb<6D>t!) // // // Ha nincs param<61>ter, null-t k<>ld<6C>nk (nem <20>res byte t<>mb<6D>t!)
// byte[]? requestData = parameter != null // // byte[]? requestData = parameter != null
// ? Encoding.UTF8.GetBytes(JsonSerializer.Serialize(parameter)) // // ? Encoding.UTF8.GetBytes(JsonSerializer.Serialize(parameter))
// : null; // // : null;
// // A Hub met<65>dus neve: OnReceiveMessage (3 param<61>ter: messageTag, messageBytes, requestId) // // // A Hub met<65>dus neve: OnReceiveMessage (3 param<61>ter: messageTag, messageBytes, requestId)
// await connection.InvokeAsync("OnReceiveMessage", tag, requestData, (int?)null); // // await connection.InvokeAsync("OnReceiveMessage", tag, requestData, (int?)null);
// var completed = await Task.WhenAny(responseReceived.Task, Task.Delay(15000)); // // var completed = await Task.WhenAny(responseReceived.Task, Task.Delay(15000));
// if (completed == responseReceived.Task) // // if (completed == responseReceived.Task)
// { // // {
// Console.WriteLine($"[{endpointName}] Response tag: {receivedTag}"); // // Console.WriteLine($"[{endpointName}] Response tag: {receivedTag}");
// Console.WriteLine($"[{endpointName}] Response JSON: {receivedJson?.Substring(0, Math.Min(500, receivedJson?.Length ?? 0))}..."); // // Console.WriteLine($"[{endpointName}] Response JSON: {receivedJson?.Substring(0, Math.Min(500, receivedJson?.Length ?? 0))}...");
// // Ellen<65>rizz<7A>k, hogy valid JSON-e (ha van adat) // // // Ellen<65>rizz<7A>k, hogy valid JSON-e (ha van adat)
// if (!string.IsNullOrEmpty(receivedJson)) // // if (!string.IsNullOrEmpty(receivedJson))
// { // // {
// try // // try
// { // // {
// using var jsonDoc = JsonDocument.Parse(receivedJson); // // using var jsonDoc = JsonDocument.Parse(receivedJson);
// Assert.IsTrue( // // Assert.IsTrue(
// jsonDoc.RootElement.ValueKind == JsonValueKind.Array || // // jsonDoc.RootElement.ValueKind == JsonValueKind.Array ||
// jsonDoc.RootElement.ValueKind == JsonValueKind.Object || // // jsonDoc.RootElement.ValueKind == JsonValueKind.Object ||
// jsonDoc.RootElement.ValueKind == JsonValueKind.Null, // // jsonDoc.RootElement.ValueKind == JsonValueKind.Null,
// $"[{endpointName}] Response is not a valid JSON"); // // $"[{endpointName}] Response is not a valid JSON");
// // Custom validation // // // Custom validation
// validateResponse?.Invoke(receivedJson); // // validateResponse?.Invoke(receivedJson);
// } // // }
// catch (JsonException ex) // // catch (JsonException ex)
// { // // {
// Assert.Fail($"[{endpointName}] Invalid JSON response: {ex.Message}"); // // Assert.Fail($"[{endpointName}] Invalid JSON response: {ex.Message}");
// } // // }
// } // // }
// } // // }
// else // // else
// { // // {
// Assert.AreEqual(HubConnectionState.Connected, connection.State, // // Assert.AreEqual(HubConnectionState.Connected, connection.State,
// $"[{endpointName}] Connection was closed - check SANDBOX logs for DI errors"); // // $"[{endpointName}] Connection was closed - check SANDBOX logs for DI errors");
// } // // }
// } // // }
// catch (Exception ex) // // catch (Exception ex)
// { // // {
// Assert.Fail($"[{endpointName}] SignalR error: {ex.Message}. Check SANDBOX logs for missing DI registrations."); // // Assert.Fail($"[{endpointName}] SignalR error: {ex.Message}. Check SANDBOX logs for missing DI registrations.");
// } // // }
// finally // // finally
// { // // {
// if (connection.State == HubConnectionState.Connected) // // if (connection.State == HubConnectionState.Connected)
// { // // {
// await connection.StopAsync(); // // await connection.StopAsync();
// } // // }
// } // // }
//} // //}
#endregion // #endregion
} //}

View File

@ -86,6 +86,7 @@ public class FullProcessModel
{ {
public List<Shipping> Shippings { get; set; } public List<Shipping> Shippings { get; set; }
public List<OrderDto> Orders { get; set; } public List<OrderDto> Orders { get; set; }
public List<PreOrder> PreOrders { get; set; }
public List<StockTaking> StockTakings { get; set; } public List<StockTaking> StockTakings { get; set; }
} }

View File

@ -276,15 +276,13 @@
private async Task Callback(ToolbarItemClickEventArgs obj) private async Task Callback(ToolbarItemClickEventArgs obj)
{ {
if (windowVisible) if (windowVisible) await windowRef.CloseAsync();
await windowRef.CloseAsync(); else await windowRef.ShowAsync();
else
await windowRef.ShowAsync();
} }
private void Callback2(WindowClosingEventArgs obj) private void Callback2(WindowClosingEventArgs obj)
{ {
ReloadDataFromDb(true).Forget(); ReloadDataFromDb(true).Forget(_logger);
} }
} }

View File

@ -0,0 +1,125 @@
@using System.Collections.ObjectModel
@using AyCode.Blazor.Components.Components.Grids
@using AyCode.Core.Helpers
@using AyCode.Core.Loggers
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Components.Grids.Shippings
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.Loggers
@using FruitBankHybrid.Shared.Services.SignalRs
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject FruitBankSignalRClient FruitBankSignalRClient
<MgGridWithInfoPanel ShowInfoPanel="@IsMasterGrid">
<GridContent>
<GridCargoPartnerBase @ref="Grid"
DataSource="CargoPartners"
AutoSaveLayoutName="GridCargoPartner"
SignalRClient="FruitBankSignalRClient"
Logger="_logger"
CssClass="@GridCss"
ValidationEnabled="false"
OnGridFocusedRowChanged="Grid_FocusedRowChanged">
<Columns>
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true" />
<DxGridDataColumn FieldName="Name" />
<DxGridDataColumn FieldName="TaxId" />
<DxGridDataColumn FieldName="CertificationNumber" />
<DxGridDataColumn FieldName="@nameof(CargoPartner.CountryCode)" />
<DxGridDataColumn FieldName="PostalCode" />
<DxGridDataColumn FieldName="@nameof(CargoPartner.Country)" />
<DxGridDataColumn FieldName="State" />
<DxGridDataColumn FieldName="County" />
<DxGridDataColumn FieldName="City" />
<DxGridDataColumn FieldName="Street" />
<DxGridDataColumn FieldName="Created" ReadOnly="true" />
<DxGridDataColumn FieldName="Modified" ReadOnly="true" />
<DxGridCommandColumn Visible="!IsMasterGrid" Width="120"></DxGridCommandColumn>
</Columns>
<DetailRowTemplate>
@if (IsMasterGrid)
{
var cargoPartner = ((CargoPartner)context.DataItem);
var shippings = cargoPartner?.Shippings ?? [];
var cargoTrucks = cargoPartner?.CargoTrucks ?? [];
<DxTabs>
<DxTabPage Text="Kamionok">
@{
var observableCargoTruck = new AcObservableCollection<CargoTruck>(cargoTrucks);
<GridCargoTruck ParentDataItem="@cargoPartner" CargoTrucks="@observableCargoTruck"></GridCargoTruck>
}
</DxTabPage>
<DxTabPage Text="Szállítmányok">
@{
var observableShippings = new AcObservableCollection<Shipping>(shippings);
<GridShipping Shippings="@observableShippings" IsMasterGrid="false" />
}
</DxTabPage>
</DxTabs>
}
</DetailRowTemplate>
<ToolbarTemplate>
@if (IsMasterGrid)
{
<MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" />
}
</ToolbarTemplate>
</GridCargoPartnerBase>
</GridContent>
</MgGridWithInfoPanel>
@code {
//[Inject] public required ObjectLock ObjectLock { get; set; }
[Inject] public required DatabaseClient Database { get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
[Parameter] public AcObservableCollection<CargoPartner>? CargoPartners { get; set; }
[Parameter] public AcObservableCollection<Shipping>? Shippings { get; set; }
const string ExportFileName = "ExportResult";
string GridSearchText = "";
bool EditItemsEnabled { get; set; }
int FocusedRowVisibleIndex { get; set; }
public GridCargoPartnerBase Grid { get; set; }
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
private int _activeTabIndex;
private LoggerClient<GridCargoPartner> _logger;
protected override async Task OnInitializedAsync()
{
_logger = new LoggerClient<GridCargoPartner>(LogWriters.ToArray());
await ReloadDataFromDb(false);
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
if (!IsMasterGrid) return;
if (Grid == null) return;
using (await ObjectLock.GetSemaphore<CargoPartner>().UseWaitAsync())
if (forceReload) await Grid.ReloadDataSourceAsync();
if (forceReload) Grid.Reload();
}
async Task Grid_FocusedRowChanged(GridFocusedRowChangedEventArgs args)
{
if (Grid == null) return;
if (Grid.IsEditing() && !Grid.IsEditingNewRow())
await Grid.SaveChangesAsync();
FocusedRowVisibleIndex = args.VisibleIndex;
EditItemsEnabled = true;
}
}

View File

@ -0,0 +1,67 @@
using AyCode.Core.Interfaces;
using DevExpress.Blazor;
using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces;
using FruitBank.Common.SignalRs;
using FruitBankHybrid.Shared.Pages;
using Microsoft.AspNetCore.Components;
namespace FruitBankHybrid.Shared.Components.Grids.Cargos;
public class GridCargoPartnerBase: FruitBankGridBase<CargoPartner>, IGrid
{
private bool _isFirstInitializeParameterCore;
private bool _isFirstInitializeParameters;
public GridCargoPartnerBase() : base()
{
GetAllMessageTag = SignalRTags.GetCargoPartners;
AddMessageTag = SignalRTags.AddCargoPartner;
UpdateMessageTag = SignalRTags.UpdateCargoPartner;
//RemoveMessageTag = SignalRTags.;
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
}
protected override void OnParametersSet()
{
base.OnParametersSet();
if (!_isFirstInitializeParameters)
{
//if (!IsMasterGrid && (ContextIds == null || ContextIds.Length == 0))
//{
// ContextIds = [ParentDataItem!.Id];
// GetAllMessageTag = SignalRTags.GetShippingItemsByDocumentId;
//}
_isFirstInitializeParameters = false;
}
}
protected override async Task SetParametersAsyncCore(ParameterView parameters)
{
await base.SetParametersAsyncCore(parameters);
if (!_isFirstInitializeParameterCore)
{
//if (!IsMasterGrid && (ContextIds == null || ContextIds.Length == 0))
//{
// ContextIds = [ParentDataItem!.Id];
// GetAllMessageTag = SignalRTags.GetShippingItemsByDocumentId;
//}
//ShowFilterRow = true;
//ShowGroupPanel = true;
//AllowSort = false;
//etc...
_isFirstInitializeParameterCore = false;
}
}
}

View File

@ -0,0 +1,100 @@
@using System.Collections.ObjectModel
@using AyCode.Blazor.Components.Components.Grids
@using AyCode.Core.Helpers
@using AyCode.Core.Interfaces
@using AyCode.Core.Loggers
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Components.Grids.Shippings
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.Loggers
@using FruitBankHybrid.Shared.Services.SignalRs
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject FruitBankSignalRClient FruitBankSignalRClient
<MgGridWithInfoPanel ShowInfoPanel="@IsMasterGrid">
<GridContent>
<GridCargoTruckBase @ref="Grid"
DataSource="CargoTrucks"
ParentDataItem="ParentDataItem"
AutoSaveLayoutName="GridCargoTruck"
SignalRClient="FruitBankSignalRClient"
Logger="_logger"
CssClass="@GridCss"
ValidationEnabled="false"
OnGridFocusedRowChanged="Grid_FocusedRowChanged">
<Columns>
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true" />
<DxGridDataColumn FieldName="@nameof(CargoTruck.LicencePlate)" />
<DxGridDataColumn FieldName="@nameof(CargoTruck.CountryCode)" />
<DxGridDataColumn FieldName="@nameof(CargoTruck.IsTrailer)" />
<DxGridDataColumn FieldName="Created" ReadOnly="true" />
<DxGridDataColumn FieldName="Modified" ReadOnly="true" />
<DxGridCommandColumn Visible="!IsMasterGrid" Width="120"></DxGridCommandColumn>
</Columns>
<ToolbarTemplate>
@if (IsMasterGrid)
{
<MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" />
}
</ToolbarTemplate>
</GridCargoTruckBase>
</GridContent>
</MgGridWithInfoPanel>
@code {
//[Inject] public required ObjectLock ObjectLock { get; set; }
[Inject] public required DatabaseClient Database { get; set; }
[Parameter] public AcObservableCollection<CargoTruck>? CargoTrucks { get; set; }
const string ExportFileName = "ExportResult";
string GridSearchText = "";
bool EditItemsEnabled { get; set; }
int FocusedRowVisibleIndex { get; set; }
public GridCargoTruckBase Grid { get; set; }
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
[Parameter] public IId<int>? ParentDataItem { get; set; }
public bool IsMasterGrid => ParentDataItem == null;
public bool ParentDataItemIsCargoPartner => (ParentDataItem is CargoPartner);
private int _activeTabIndex;
private LoggerClient<GridCargoTruck> _logger;
protected override async Task OnInitializedAsync()
{
_logger = new LoggerClient<GridCargoTruck>(LogWriters.ToArray());
await ReloadDataFromDb(false);
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
if (!IsMasterGrid) return;
if (Grid == null) return;
using (await ObjectLock.GetSemaphore<CargoTruck>().UseWaitAsync())
if (forceReload) await Grid.ReloadDataSourceAsync();
if (forceReload) Grid.Reload();
}
async Task Grid_FocusedRowChanged(GridFocusedRowChangedEventArgs args)
{
if (Grid == null) return;
if (Grid.IsEditing() && !Grid.IsEditingNewRow())
await Grid.SaveChangesAsync();
FocusedRowVisibleIndex = args.VisibleIndex;
EditItemsEnabled = true;
}
}

View File

@ -0,0 +1,85 @@
using AyCode.Core.Interfaces;
using AyCode.Utils.Extensions;
using DevExpress.Blazor;
using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces;
using FruitBank.Common.SignalRs;
using FruitBankHybrid.Shared.Pages;
using Microsoft.AspNetCore.Components;
namespace FruitBankHybrid.Shared.Components.Grids.Cargos;
public class GridCargoTruckBase: FruitBankGridBase<CargoTruck>, IGrid
{
private bool _isFirstInitializeParameterCore;
private bool _isFirstInitializeParameters;
public GridCargoTruckBase() : base()
{
//GetAllMessageTag = SignalRTags.GetCargoTrucks;
AddMessageTag = SignalRTags.AddCargoTruck;
UpdateMessageTag = SignalRTags.UpdateCargoTruck;
//RemoveMessageTag = SignalRTags.;
}
protected override async Task OnInitializedAsync()
{
if (GetAllMessageTag > 0) return;
if (IsMasterGrid) GetAllMessageTag = SignalRTags.GetCargoTrucks;
else
{
if (ContextIds == null || ContextIds.Length == 0) ContextIds = [ParentDataItem!.Id];
switch (ParentDataItem)
{
case ICargoPartner:
GetAllMessageTag = SignalRTags.GetCargoTrucksByCargoPartnerId;
if (KeyFieldNameToParentId.IsNullOrWhiteSpace()) KeyFieldNameToParentId = nameof(CargoTruck.CargoPartnerId);
break;
}
}
await base.OnInitializedAsync();
}
protected override void OnParametersSet()
{
base.OnParametersSet();
if (!_isFirstInitializeParameters)
{
//if (!IsMasterGrid && (ContextIds == null || ContextIds.Length == 0))
//{
// ContextIds = [ParentDataItem!.Id];
// GetAllMessageTag = SignalRTags.GetShippingItemsByDocumentId;
//}
_isFirstInitializeParameters = false;
}
}
protected override async Task SetParametersAsyncCore(ParameterView parameters)
{
await base.SetParametersAsyncCore(parameters);
if (!_isFirstInitializeParameterCore)
{
//if (!IsMasterGrid && (ContextIds == null || ContextIds.Length == 0))
//{
// ContextIds = [ParentDataItem!.Id];
// GetAllMessageTag = SignalRTags.GetShippingItemsByDocumentId;
//}
//ShowFilterRow = true;
//ShowGroupPanel = true;
//AllowSort = false;
//etc...
_isFirstInitializeParameterCore = false;
}
}
}

View File

@ -29,6 +29,7 @@
<DxGridDataColumn FieldName="Name" /> <DxGridDataColumn FieldName="Name" />
<DxGridDataColumn FieldName="TaxId" /> <DxGridDataColumn FieldName="TaxId" />
<DxGridDataColumn FieldName="CertificationNumber" /> <DxGridDataColumn FieldName="CertificationNumber" />
<DxGridDataColumn FieldName="@nameof(Partner.CountryCode)" />
<DxGridDataColumn FieldName="PostalCode" /> <DxGridDataColumn FieldName="PostalCode" />
<DxGridDataColumn FieldName="@nameof(Partner.Country)" /> <DxGridDataColumn FieldName="@nameof(Partner.Country)" />
<DxGridDataColumn FieldName="State" /> <DxGridDataColumn FieldName="State" />

View File

@ -1,5 +1,7 @@
using AyCode.Core.Extensions; using AyCode.Core.Extensions;
using AyCode.Core.Helpers;
using AyCode.Core.Interfaces; using AyCode.Core.Interfaces;
using AyCode.Core.Loggers;
using AyCode.Interfaces.Entities; using AyCode.Interfaces.Entities;
using AyCode.Services.SignalRs; using AyCode.Services.SignalRs;
using AyCode.Utils.Extensions; using AyCode.Utils.Extensions;
@ -15,18 +17,14 @@ using Nop.Core.Domain.Orders;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Threading; using System.Threading;
using AyCode.Core.Helpers;
namespace FruitBankHybrid.Shared.Databases; namespace FruitBankHybrid.Shared.Databases;
public class ShippingTableItem : Shipping //public class ShippingTableItem : Shipping { }
{ } //public class ShippingDocumentTableItem : ShippingDocument { }
public class ShippingDocumentTableItem : ShippingDocument
{ }
public class ShippingItemTableItem : ShippingItem public class ShippingItemTableItem : ShippingItem
{ } { }
public class ShippingItemPalletTableItem : ShippingItemPallet //public class ShippingItemPalletTableItem : ShippingItemPallet { }
{ }
public class ProductDtoTableItem : ProductDto public class ProductDtoTableItem : ProductDto
{ {
//[Newtonsoft.Json.JsonProperty] //[Newtonsoft.Json.JsonProperty]
@ -45,13 +43,12 @@ public class ShippingItemTable : SignalRDataSourceList<ShippingItemTableItem>
{ {
private static readonly SignalRCrudTags SignalRCrudTags = new(SignalRTags.GetShippingItems, 0, SignalRTags.AddShippingItem, SignalRTags.UpdateShippingItem, 0); private static readonly SignalRCrudTags SignalRCrudTags = new(SignalRTags.GetShippingItems, 0, SignalRTags.AddShippingItem, SignalRTags.UpdateShippingItem, 0);
public ShippingItemTable(AcSignalRClientBase signalRClient, params object[]? contextIds) public ShippingItemTable(AcSignalRClientBase signalRClient, IAcLoggerBase? logger, params object[]? contextIds) : this(signalRClient, SignalRCrudTags, logger, contextIds)
: this(signalRClient, SignalRCrudTags, contextIds)
{ {
} }
public ShippingItemTable(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, params object[]? contextIds) : base(signalRClient, signalRCrudTags, contextIds) public ShippingItemTable(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, IAcLoggerBase? logger, params object[]? contextIds) : base(signalRClient, signalRCrudTags, logger, contextIds)
{ {
} }
} }
@ -111,7 +108,7 @@ public class OrderDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : AcOb
public abstract class DatabaseTableBase<TDataItem> : SignalRDataSourceObservable<TDataItem> where TDataItem : class, IId<int> public abstract class DatabaseTableBase<TDataItem> : SignalRDataSourceObservable<TDataItem> where TDataItem : class, IId<int>
{ {
protected DatabaseTableBase(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, params object[]? contextIds) : base(signalRClient, signalRCrudTags, contextIds) protected DatabaseTableBase(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, IAcLoggerBase? logger, params object[]? contextIds) : base(signalRClient, signalRCrudTags, logger, contextIds)
{ {
} }
@ -171,7 +168,7 @@ public class DatabaseClient : DatabaseClientBase
_fruitBankSignalRClient = fruitBankSignalRClient; _fruitBankSignalRClient = fruitBankSignalRClient;
AddTable(new ProductDtoTable(_fruitBankSignalRClient)); AddTable(new ProductDtoTable(_fruitBankSignalRClient));
AddTable(new ShippingItemTable(_fruitBankSignalRClient)); AddTable(new ShippingItemTable(_fruitBankSignalRClient, null));
AddTable(new OrderDtoTable(_fruitBankSignalRClient)); AddTable(new OrderDtoTable(_fruitBankSignalRClient));
} }

View File

@ -2,6 +2,7 @@
@using FruitBank.Common.Dtos @using FruitBank.Common.Dtos
@using FruitBank.Common.Entities @using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Components @using FruitBankHybrid.Shared.Components
@using FruitBankHybrid.Shared.Components.Grids.Cargos
@using FruitBankHybrid.Shared.Components.Grids.Partners @using FruitBankHybrid.Shared.Components.Grids.Partners
@using FruitBankHybrid.Shared.Components.Grids.Shippings @using FruitBankHybrid.Shared.Components.Grids.Shippings
@using FruitBankHybrid.Shared.Databases @using FruitBankHybrid.Shared.Databases
@ -25,6 +26,9 @@
<DxTabPage Text="Beszállítók" Visible="@(LoggedInModel.IsAdministrator)"> <DxTabPage Text="Beszállítók" Visible="@(LoggedInModel.IsAdministrator)">
<GridPartner @ref="gridPartner" Partners="@Partners" IsMasterGrid="true"></GridPartner> <GridPartner @ref="gridPartner" Partners="@Partners" IsMasterGrid="true"></GridPartner>
</DxTabPage> </DxTabPage>
<DxTabPage Text="Fuvarozók" Visible="@(LoggedInModel.IsAdministrator)">
<GridCargoPartner @ref="gridCargoPartner" CargoPartners="CargoPartners" IsMasterGrid="true"></GridCargoPartner>
</DxTabPage>
<DxTabPage Text="Szállítmányok"> <DxTabPage Text="Szállítmányok">
<GridShipping @ref="gridShipping" Shippings="@Shippings" Partners="@Partners" IsMasterGrid="true"></GridShipping> <GridShipping @ref="gridShipping" Shippings="@Shippings" Partners="@Partners" IsMasterGrid="true"></GridShipping>
</DxTabPage> </DxTabPage>

View File

@ -15,6 +15,7 @@ using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs; using FruitBankHybrid.Shared.Services.SignalRs;
using Mango.Nop.Core.Loggers; using Mango.Nop.Core.Loggers;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using FruitBankHybrid.Shared.Components.Grids.Cargos;
namespace FruitBankHybrid.Shared.Pages; namespace FruitBankHybrid.Shared.Pages;
@ -29,6 +30,7 @@ public partial class ShippingsAdmin : ComponentBase
private GridProductDtoTemplate gridProductDtoTemplate; private GridProductDtoTemplate gridProductDtoTemplate;
private GridPartner gridPartner; private GridPartner gridPartner;
private GridCargoPartner gridCargoPartner;
private GridShipping gridShipping; private GridShipping gridShipping;
private GridShippingDocument gridShippingDocument; private GridShippingDocument gridShippingDocument;
private GridShippingItemTemplate gridShippingItemTemplate; private GridShippingItemTemplate gridShippingItemTemplate;
@ -39,6 +41,7 @@ public partial class ShippingsAdmin : ComponentBase
public AcObservableCollection<ShippingItem> ShippingItems { get; set; } = []; public AcObservableCollection<ShippingItem> ShippingItems { get; set; } = [];
public List<ShippingItemPallet> ShippingItemPallets { get; set; } = []; public List<ShippingItemPallet> ShippingItemPallets { get; set; } = [];
public AcObservableCollection<Partner> Partners { get; set; } = []; public AcObservableCollection<Partner> Partners { get; set; } = [];
public AcObservableCollection<CargoPartner> CargoPartners { get; set; } = [];
public bool AutoCollapseDetailRow { get; set; } public bool AutoCollapseDetailRow { get; set; }

View File

@ -57,25 +57,31 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
} }
} }
public Task<List<MeasuringModel>?> GetMeasuringModels() public Task<List<MeasuringModel>?> GetMeasuringModels() => GetAllAsync<List<MeasuringModel>>(SignalRTags.GetMeasuringModels);
=> GetAllAsync<List<MeasuringModel>>(SignalRTags.GetMeasuringModels);
public Task<List<Partner>?> GetPartners()
=> GetAllAsync<List<Partner>>(SignalRTags.GetPartners);
#region Partner #region Partner
public Task<List<Partner>?> GetPartners() => GetAllAsync<List<Partner>>(SignalRTags.GetPartners);
public Task<Partner?> GetPartnerById(int id) public Task<Partner?> GetPartnerById(int id) => GetByIdAsync<Partner?>(SignalRTags.GetPartnerById, id);
=> GetByIdAsync<Partner?>(SignalRTags.GetPartnerById, id); public Task<Partner?> AddPartner(Partner partner) => PostDataAsync(SignalRTags.AddPartner, partner);
public Task<Partner?> UpdatePartner(Partner partner) => PostDataAsync(SignalRTags.UpdatePartner, partner);
public Task<Partner?> AddPartner(Partner partner)
=> PostDataAsync(SignalRTags.AddPartner, partner);
public Task<Partner?> UpdatePartner(Partner partner)
=> PostDataAsync(SignalRTags.UpdatePartner, partner);
#endregion Partner #endregion Partner
#region CargoPartner
public Task<List<CargoPartner>?> GetCargoPartners() => GetAllAsync<List<CargoPartner>>(SignalRTags.GetCargoPartners);
public Task<CargoPartner?> GetCargoPartnerById(int id) => GetByIdAsync<CargoPartner?>(SignalRTags.GetCargoPartnerById, id);
public Task<CargoPartner?> AddCargoPartner(CargoPartner cargoPartner) => PostDataAsync(SignalRTags.AddCargoPartner, cargoPartner);
public Task<CargoPartner?> UpdateCargoPartner(CargoPartner cargoPartner) => PostDataAsync(SignalRTags.UpdateCargoPartner, cargoPartner);
#endregion CargoPartner
#region CargoTruck
public Task<List<CargoTruck>?> GetCargoTrucks() => GetAllAsync<List<CargoTruck>>(SignalRTags.GetCargoTrucks);
public Task<CargoTruck?> GetCargoTruckById(int id) => GetByIdAsync<CargoTruck?>(SignalRTags.GetCargoTruckById, id);
public Task<List<CargoTruck>?> GetCargoTrucksByCargoPartnerId(int cargoPartnerId) => GetAllAsync<List<CargoTruck>>(SignalRTags.GetCargoTrucksByCargoPartnerId, [cargoPartnerId]);
public Task<CargoTruck?> AddCargoTruck(CargoTruck cargoTruck) => PostDataAsync(SignalRTags.AddCargoTruck, cargoTruck);
public Task<CargoTruck?> UpdateCargoTruck(CargoTruck cargoTruck) => PostDataAsync(SignalRTags.UpdateCargoTruck, cargoTruck);
#endregion CargoTruck
#region Shipping #region Shipping
public Task<List<Shipping>?> GetShippings() public Task<List<Shipping>?> GetShippings()

View File

@ -1,18 +1,19 @@
using System.Collections.ObjectModel; using AyCode.Core.Helpers;
using AyCode.Core.Interfaces; using AyCode.Core.Interfaces;
using AyCode.Core.Loggers;
using AyCode.Services.Server.SignalRs; using AyCode.Services.Server.SignalRs;
using AyCode.Services.SignalRs; using AyCode.Services.SignalRs;
using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using AyCode.Core.Helpers;
namespace FruitBankHybrid.Shared.Services.SignalRs; namespace FruitBankHybrid.Shared.Services.SignalRs;
[Serializable] [Serializable]
[DebuggerDisplay("Count = {Count}")] [DebuggerDisplay("Count = {Count}")]
public class SignalRDataSourceList<TDataItem>(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, params object[]? contextIds) public class SignalRDataSourceList<TDataItem>(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, IAcLoggerBase? logger, params object[]? contextIds)
: AcSignalRDataSource<TDataItem, int, List<TDataItem>>(signalRClient, signalRCrudTags, contextIds) where TDataItem : class, IId<int>; : AcSignalRDataSource<TDataItem, int, List<TDataItem>>(signalRClient, signalRCrudTags, logger, contextIds) where TDataItem : class, IId<int>;
[Serializable] [Serializable]
[DebuggerDisplay("Count = {Count}")] [DebuggerDisplay("Count = {Count}")]
public class SignalRDataSourceObservable<TDataItem>(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, params object[]? contextIds) public class SignalRDataSourceObservable<TDataItem>(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, IAcLoggerBase? logger, params object[]? contextIds)
: AcSignalRDataSource<TDataItem, int, AcObservableCollection<TDataItem>>(signalRClient, signalRCrudTags, contextIds) where TDataItem : class, IId<int>; : AcSignalRDataSource<TDataItem, int, AcObservableCollection<TDataItem>>(signalRClient, signalRCrudTags, logger, contextIds) where TDataItem : class, IId<int>;

View File

@ -38,7 +38,7 @@
"AcBinaryHubProtocol": { "AcBinaryHubProtocol": {
"ProtocolMode": "AsyncSegment", "ProtocolMode": "AsyncSegment",
"BufferSize": 4096, "BufferSize": 4096,
"FlushPolicy": "DoubleBuffered", "FlushPolicy": "Coalesced",
"FlushTimeout": "00:00:10" "FlushTimeout": "00:00:10"
} }
} }

View File

@ -38,7 +38,7 @@
"AcBinaryHubProtocol": { "AcBinaryHubProtocol": {
"ProtocolMode": "AsyncSegment", "ProtocolMode": "AsyncSegment",
"BufferSize": 4096, "BufferSize": 4096,
"FlushPolicy": "DoubleBuffered", "FlushPolicy": "Coalesced",
"FlushTimeout": "00:00:10" "FlushTimeout": "00:00:10"
} }
} }

View File

@ -38,7 +38,7 @@
"AcBinaryHubProtocol": { "AcBinaryHubProtocol": {
"ProtocolMode": "AsyncSegment", "ProtocolMode": "AsyncSegment",
"BufferSize": 4096, "BufferSize": 4096,
"FlushPolicy": "DoubleBuffered", "FlushPolicy": "Coalesced",
"FlushTimeout": "00:00:10" "FlushTimeout": "00:00:10"
} }
} }