using AyCode.Core.Serializers.Attributes; using AyCode.Core.Serializers.Toons; using FruitBank.Common.Dtos; using LinqToDB; using LinqToDB.Mapping; using Mango.Nop.Core.Entities; using Newtonsoft.Json; using System.ComponentModel.DataAnnotations.Schema; using Column = LinqToDB.Mapping.ColumnAttribute; using Table = LinqToDB.Mapping.TableAttribute; namespace FruitBank.Common.Entities; [AcBinarySerializable(false, true, false, true, false, false)] [ToonDescription("Line item for product reconciliation", Purpose = "Reconciles snapshot quantity with physical count to calculate final stock delta")] [Table(Name = FruitBankConstClient.StockTakingItemDbTableName)] [System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.StockTakingItemDbTableName)] public class StockTakingItem : MgStockTakingItem { public bool IsMeasurable { get; set; } [Column(DataType = DataType.DecFloat, CanBeNull = false)] public double OriginalNetWeight { get; set; } [Column(DataType = DataType.DecFloat, CanBeNull = false)] public double MeasuredNetWeight { get; set; } [ToonDescription(Purpose = "Reserved stock buffer (not yet shipped) to prevent double-deduction during closing")] public int InProcessOrdersQuantity { get; set; } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] [ToonDescription(BusinessRule = "get => OriginalStockQuantity + InProcessOrdersQuantity", Purpose = "Snapshot of total logical stock at session start")] public int TotalOriginalQuantity => OriginalStockQuantity + InProcessOrdersQuantity; [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] [ToonDescription(Purpose = "Final adjustment value for Product.StockQuantity", BusinessRule = "get => IsMeasured ? MeasuredStockQuantity - TotalOriginalQuantity : 0")] public int QuantityDiff => IsMeasured ? MeasuredStockQuantity - TotalOriginalQuantity : 0; [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] [ToonDescription(BusinessRule = "get => IsMeasurable && IsMeasured ? double.Round(MeasuredNetWeight - OriginalNetWeight, 1) : 0d")] public double NetWeightDiff => IsMeasurable && IsMeasured ? double.Round(MeasuredNetWeight - OriginalNetWeight, 1) : 0d; [Association(ThisKey = nameof(Id), OtherKey = nameof(StockTakingItemPallet.StockTakingItemId), CanBeNull = true)] public List? StockTakingItemPallets { get; set; } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] [ToonDescription(Purpose = "Status flag", BusinessRule = "get => !IsInvalid && (TotalOriginalQuantity != 0 || OriginalNetWeight != 0)")] public bool IsRequiredForMeasuring => !IsInvalid && (TotalOriginalQuantity != 0 || OriginalNetWeight != 0); [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] [ToonDescription(Purpose = "Status flag", BusinessRule = "get => TotalOriginalQuantity < 0")] public bool IsInvalid => TotalOriginalQuantity < 0; [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] [ToonDescription(BusinessRule = "get => conditional string based on IsInvalid, IsMeasured, IsRequiredForMeasuring")] public string DisplayText { get { if (IsInvalid) return $"[HIBA] {Product!.Name}"; if (IsMeasured) return $"[KÉSZ] {Product!.Name}"; return IsRequiredForMeasuring ? $"[KÖT] {Product!.Name}" : $"{Product!.Name}"; } } }