diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 278535fa..76a90611 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -3,7 +3,10 @@ "allow": [ "Bash(dir:*)", "Bash(dotnet list:*)", - "Bash(find:*)" + "Bash(find:*)", + "Bash(grep:*)", + "Bash(dotnet test:*)", + "Bash(dotnet build:*)" ] } } diff --git a/FruitBank.Common/Dtos/OrderDto.cs b/FruitBank.Common/Dtos/OrderDto.cs index 1edbb7c3..7b523ea6 100644 --- a/FruitBank.Common/Dtos/OrderDto.cs +++ b/FruitBank.Common/Dtos/OrderDto.cs @@ -35,6 +35,7 @@ public class OrderDto : MgOrderDto, IOrderDto public List GenericAttributes { get; set; } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => Id > 0 && OrderItemDtos.Count > 0 && OrderItemDtos.All(x => x.IsMeasured)", Constraints = "[#SmartTypeConstraints], readonly")] public bool IsMeasured { get => IsMeasuredAndValid(); @@ -42,6 +43,7 @@ public class OrderDto : MgOrderDto, IOrderDto } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => OrderItemDtos.Any(oi => oi.IsMeasurable)", Constraints = "[#SmartTypeConstraints], readonly")] public bool IsMeasurable { get => OrderItemDtos.Any(oi => oi.IsMeasurable); @@ -69,18 +71,23 @@ public class OrderDto : MgOrderDto, IOrderDto public DateTime DateOfReceiptOrCreated => DateOfReceipt ?? CreatedOnUtc; [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => GenericAttributes.GetValueOrNull(nameof(IOrderDto.DateOfReceipt))")] public DateTime? DateOfReceipt => GenericAttributes.GetValueOrNull(nameof(IOrderDto.DateOfReceipt)); [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => GenericAttributes.GetValueOrDefault(nameof(IOrderDto.RevisorId), 0)")] public int RevisorId => GenericAttributes.GetValueOrDefault(nameof(IOrderDto.RevisorId), 0); [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => GenericAttributes.GetValueOrDefault(nameof(IOrderDto.MeasurementOwnerId), 0)")] public int MeasurementOwnerId => GenericAttributes.GetValueOrDefault(nameof(IOrderDto.MeasurementOwnerId), 0); [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => OrderItemDtos.Count > 0 && OrderItemDtos.All(oi => oi.IsAudited)")] public bool IsAllOrderItemAudited => OrderItemDtos.Count > 0 && OrderItemDtos.All(oi => oi.IsAudited); [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => OrderItemDtos.All(oi => oi.AverageWeightIsValid)")] public bool IsAllOrderItemAvgWeightValid => OrderItemDtos.All(oi => oi.AverageWeightIsValid); [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] @@ -105,6 +112,7 @@ public class OrderDto : MgOrderDto, IOrderDto { } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => OrderStatus == OrderStatus.Complete")] public bool IsComplete => OrderStatus == OrderStatus.Complete; public bool HasMeasuringAccess(int? customerId, bool isRevisorUser = false) diff --git a/FruitBank.Common/Dtos/OrderItemDto.cs b/FruitBank.Common/Dtos/OrderItemDto.cs index f9db3545..c26e3f58 100644 --- a/FruitBank.Common/Dtos/OrderItemDto.cs +++ b/FruitBank.Common/Dtos/OrderItemDto.cs @@ -42,6 +42,7 @@ public class OrderItemDto : MgOrderItemDto, IOrderItemDto } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => ProductDto!.IsMeasurable", Constraints = "[#SmartTypeConstraints], readonly")] public bool IsMeasurable { get => ProductDto!.IsMeasurable; @@ -49,6 +50,7 @@ public class OrderItemDto : MgOrderItemDto, IOrderItemDto } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => OrderItemPallets.Sum(x => x.TrayQuantity)", Constraints = "[#SmartTypeConstraints], readonly")] public int TrayQuantity { get => OrderItemPallets.Sum(x => x.TrayQuantity); @@ -56,6 +58,7 @@ public class OrderItemDto : MgOrderItemDto, IOrderItemDto } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => double.Round(OrderItemPallets.Sum(x => x.NetWeight), 1)", Constraints = "[#SmartTypeConstraints], readonly")] public double NetWeight { get @@ -73,6 +76,7 @@ public class OrderItemDto : MgOrderItemDto, IOrderItemDto } [NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore] + [ToonDescription(BusinessRule = "get => double.Round(OrderItemPallets.Sum(x => x.NetWeight), 1)", Constraints = "[#SmartTypeConstraints], readonly")] public double GrossWeight { get diff --git a/test_toon_businessrule.csx b/test_toon_businessrule.csx new file mode 100644 index 00000000..d316fd6c --- /dev/null +++ b/test_toon_businessrule.csx @@ -0,0 +1,28 @@ +#!/usr/bin/env dotnet-script + +#r "H:/Applications/Mango/Source/FruitBankHybridApp/FruitBank.Common/bin/Debug/net9.0/FruitBank.Common.dll" +#r "H:/Applications/Aycode/Source/AyCode.Core/AyCode.Core/bin/FruitBank/Debug/net9.0/AyCode.Core.dll" + +using AyCode.Core.Serializers.Toons; +using FruitBank.Common.Dtos; + +var toon = AcToonSerializer.SerializeTypeMetadata(); +Console.WriteLine(toon); + +// Search for IsMeasurable property output +if (toon.Contains("business-logic:")) +{ + Console.WriteLine("\n✓ SUCCESS: business-logic attribute found!"); + var lines = toon.Split('\n'); + foreach (var line in lines) + { + if (line.Contains("IsMeasurable") || line.Contains("business-logic:")) + { + Console.WriteLine(line); + } + } +} +else +{ + Console.WriteLine("\n✗ FAIL: business-logic attribute NOT found!"); +}