Dynamic Rules

 

Dynamic Rules

  Imagine you live in a world where item costs, item prices, sales tax rules, business rules, approval rules, validation rules, rules which govern how we extend credit to our customers, and reorder strategies change over time. 

   Example scenario: It is mid February and we are a retail store with physical store front and website/internet presence. Assume for an order to be valid, it the sum must be under $1000 starting in February, then start of March, it changed to requiring $2000. Then start of April, orders cannot be placed by any customer that owe us money over 90 days. 


   Think about having a specific validator class for each entity that requires it:

public sealed class OrderValidator { private readonly IOrderRuleRepository _ruleRepository; public OrderValidator(IOrderRuleRepository ruleRepository) { _ruleRepository = ruleRepository; } public ValidationResult Validate(Order order, DateTimeOffset asOf) { var rules = _ruleRepository.GetRulesFor("Order", asOf); var errors = new List<string>(); foreach (var rule in rules) { var result = rule.Validate(order); if (!result.IsValid) errors.Add(result.ErrorMessage); } return errors.Count == 0 ? ValidationResult.Success() : ValidationResult.Failure(errors); } } public interface IOrderRule { ValidationResult Validate(Order order); } public sealed record ValidationResult(bool IsValid, IReadOnlyList<string> Errors) { public static ValidationResult Success() => new(true, Array.Empty<string>()); public static ValidationResult Failure(params string[] errors) => new(false, errors); public static ValidationResult Failure(IReadOnlyList<string> errors) => new(false, errors); }

Think about a Rule table with these columns: EntityName, RuleCode, EffectiveFrom, EffectiveTo or IsCurrent, Version, Parameters (such as threshold value).

A practical model is: ItemPriceHistory(ItemId, PriceType, EffectiveFrom, EffectiveTo, Value, Version) OrderLine(OrderId, ItemId, Qty, UnitCostAtSale, UnitPriceAtSale) 

ReportSnapshot(ReportId, ReportDate, GeneratedAt, InputVersion, …)

   Discussion1: Rethink each entity and ask what could change on this that affects any dollar amounts or decisions. 

       

   Example2 scenario: It is February and we are a retail store.  Item X costs us $100 and we sell for $200 + old sales tax rules of 10% that came out to $20 for $220. Then start of June, later the cost for item X jumps to $150 and our sales price is $220 + new sales tax rules of 12% that came out to $26 for $246 Now imagine we got audited.  1) Now we dynamically create a Profit and Loss report with the Orders for February and it is June.  So we must not assume that the item X cost us $150. Assume we do not store things into monthly history buckets and the P&L report is does not look to any monthly history bucket, but rather dynamically calculates things. 2) Now we run the report of the customer's order since we do not store the image of the historical order. We need it to calculate the correct sales tax otherwise we will pay the incorrect sales tax and expect a different cash amount when looking through the customer's payments.

A practical model is:

TaxJurisdiction (TaxJurisdictionId, CountryCode, StateCode, CountyCode, CityCode, DistrictCode, JurisdictionName, JurisdictionType)

TaxRateHistory (TaxRateHistoryId, TaxJurisdictionId, TaxCode, EffectiveFrom, EffectiveTo, Rate, TaxabilityRuleCode, Version)

InvoiceLineTax (InvoiceLineTaxId, InvoiceLineId, TaxJurisdictionId, TaxRateHistoryId, TaxableAmount, RateApplied, TaxAmount, CalculatedAt)

   TaxBoundaryMap (TaxBoundaryMapId, CountryCode, StateCode, PostalCode, AddressRangeStart, AddressRangeEnd, TaxJurisdictionId, EffectiveFrom, EffectiveTo)

   Discussion2: Do we use a old calculation or total bucket strategy, historical image, or dynamically calculate on the reprinting of historical reports? Does the business close out periods? What is our data archival strategy?  Maybe we should add calculated things to the table?

How should you implement Strategies? Approvals?


Comments

Popular posts from this blog

GHL Email Campaigns

Whitelabel Options

Await