Sample: basic_demo
Basic Demo Sample
This is a basic demonstration project created from a simple natural language prompt using API Logic Server's GenAI capabilities.
Data Model

Creation Prompt
This project was created from the following natural language prompt:
Create a system with customers, orders, items and products.
Include a notes field for orders.
Use case: Check Credit
1. The Customer's balance is less than the credit limit
2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
3. The Order's amount_total is the sum of the Item amount
4. The Item amount is the quantity * unit_price
5. The Item unit_price is copied from the Product unit_price
Use case: App Integration
1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
The sample Scenarios below were chosen to illustrate the basic patterns of using rules. Open the disclosure box ("Tests - and their logic...") to see the implementation and notes.
The following report was created during test suite execution.
Behave Logic Report
Feature: About Sample
Scenario: Transaction Processing
Scenario: Transaction Processing
Given Sample Database
When Transactions are submitted
Then Enforce business policies with Logic (rules + code)
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Transaction Processing
Logic Log in Scenario: Transaction ProcessingLogic Phase: ROW LOGIC (session=0x1098628b0) (sqlalchemy before_flush) - 2025-10-26 17:10:57,158 - logic_logger - INF
..Customer[None] {Insert - client} id: None, name: Alice 1761523857156, balance: 0, credit_limit: 1000, email: None, email_opt_out: None row: 0x10991f6d0 session: 0x1098628b0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,158 - logic_logger - INF
..Customer[None] {server aggregate_defaults: balance } id: None, name: Alice 1761523857156, balance: 0, credit_limit: 1000, email: None, email_opt_out: None row: 0x10991f6d0 session: 0x1098628b0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,158 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x1098628b0) - 2025-10-26 17:10:57,158 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x1098628b0) - 2025-10-26 17:10:57,158 - logic_logger - INF
Feature: Order Processing with Business Logic
Scenario: Good Order Created via B2B API
Scenario: Good Order Created via B2B API
Given Customer "Alice" with balance 0 and credit limit 1000
When B2B order placed for "Alice" with 5 Widget
Then Customer balance should be 450
And Order amount_total should be 450
And Each item amount calculated correctly
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Good Order Created via B2B API
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Item
2. Derive <class 'database.models.Item'>.unit_price as Copy(product.unit_price)
3. Derive <class 'database.models.Item'>.amount as Formula (1): <function>
Order
4. Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)
5. RowEvent Order.send_order_to_shipping()
Logic Phase: ROW LOGIC (session=0x109863f00) (sqlalchemy before_flush) - 2025-10-26 17:10:57,165 - logic_logger - INF
..Product[2] {Update - client} id: 2, name: Widget, unit_price: 90.0000000000, carbon_neutral: None row: 0x109a510f0 session: 0x109863f00 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,165 - logic_logger - INF
..Item[None] {Insert - client} id: None, order_id: None, product_id: None, quantity: 5, amount: None, unit_price: None row: 0x109a4d3d0 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,165 - logic_logger - INF
..Item[None] {copy_rules for role: product - unit_price} id: None, order_id: None, product_id: None, quantity: 5, amount: None, unit_price: 90.0000000000 row: 0x109a4d3d0 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,165 - logic_logger - INF
..Item[None] {Formula amount} id: None, order_id: None, product_id: None, quantity: 5, amount: 450.0000000000, unit_price: 90.0000000000 row: 0x109a4d3d0 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,165 - logic_logger - INF
....Order[None] {server aggregate_defaults: amount_total } id: None, notes: Test order 1761523857162, customer_id: 50, CreatedOn: None, date_shipped: None, amount_total: [None-->] 0 row: 0x109a33f50 session: 0x109863f00 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,165 - logic_logger - INF
..Item[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)} id: None, order_id: None, product_id: None, quantity: 5, amount: 450.0000000000, unit_price: 90.0000000000 row: 0x109a4d3d0 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,165 - logic_logger - INF
....Order[None] {Adjustment logic chaining deferred for this parent parent do_defer_adjustment: True, is_parent_submitted: True, is_parent_row_processed: False, order} id: None, notes: Test order 1761523857162, customer_id: 50, CreatedOn: None, date_shipped: None, amount_total: [None-->] 450.0000000000 row: 0x109a33f50 session: 0x109863f00 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,165 - logic_logger - INF
..Order[None] {Insert - client} id: None, notes: Test order 1761523857162, customer_id: 50, CreatedOn: None, date_shipped: None, amount_total: 450.0000000000 row: 0x109a33f50 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,165 - logic_logger - INF
..Order[None] {early_row_event_all_classes - handle_all did stamping} id: None, notes: Test order 1761523857162, customer_id: 50, CreatedOn: 2025-10-26 17:10:57.165840, date_shipped: None, amount_total: 450.0000000000 row: 0x109a33f50 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,165 - logic_logger - INF
..Order[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)} id: None, notes: Test order 1761523857162, customer_id: 50, CreatedOn: 2025-10-26 17:10:57.165840, date_shipped: None, amount_total: 450.0000000000 row: 0x109a33f50 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,166 - logic_logger - INF
....Customer[50] {Update - Adjusting customer: balance} id: 50, name: Alice 1761523857156, balance: [0E-10-->] 450.0000000000, credit_limit: 1000.0000000000, email: None, email_opt_out: None row: 0x109a4db50 session: 0x109863f00 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,166 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109863f00) - 2025-10-26 17:10:57,166 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109863f00) - 2025-10-26 17:10:57,167 - logic_logger - INF
..Order[47] {AfterFlush Event} id: 47, notes: Test order 1761523857162, customer_id: 50, CreatedOn: 2025-10-26 17:10:57.165840, date_shipped: None, amount_total: 450.0000000000 row: 0x109a33f50 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,167 - logic_logger - INF
..Order[47] {Sending Order to Shipping [Note: **Kafka not enabled** ]} id: 47, notes: Test order 1761523857162, customer_id: 50, CreatedOn: 2025-10-26 17:10:57.165840, date_shipped: None, amount_total: 450.0000000000 row: 0x109a33f50 session: 0x109863f00 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,167 - logic_logger - INF
Scenario: Carbon Neutral Discount Applied
Scenario: Carbon Neutral Discount Applied
Given Customer "Bob" with balance 0 and credit limit 2000
When B2B order placed for "Bob" with 10 carbon neutral Gadget
Then Customer balance should be 900
And Item amount reflects 10% discount
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Carbon Neutral Discount Applied
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Item
2. Derive <class 'database.models.Item'>.unit_price as Copy(product.unit_price)
3. Derive <class 'database.models.Item'>.amount as Formula (1): <function>
Order
4. Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)
5. RowEvent Order.send_order_to_shipping()
Logic Phase: ROW LOGIC (session=0x109863570) (sqlalchemy before_flush) - 2025-10-26 17:10:57,186 - logic_logger - INF
..Product[1] {Update - client} id: 1, name: Gadget, unit_price: 100.0000000000, carbon_neutral: True row: 0x1099600c0 session: 0x109863570 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,186 - logic_logger - INF
..Item[None] {Insert - client} id: None, order_id: None, product_id: None, quantity: 10, amount: None, unit_price: None row: 0x10991f3d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,186 - logic_logger - INF
..Item[None] {copy_rules for role: product - unit_price} id: None, order_id: None, product_id: None, quantity: 10, amount: None, unit_price: 100.0000000000 row: 0x10991f3d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,187 - logic_logger - INF
..Item[None] {Formula amount} id: None, order_id: None, product_id: None, quantity: 10, amount: 900.0000000000000222044604925, unit_price: 100.0000000000 row: 0x10991f3d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,187 - logic_logger - INF
....Order[None] {server aggregate_defaults: amount_total } id: None, notes: Carbon neutral test 1761523857184, customer_id: 51, CreatedOn: None, date_shipped: None, amount_total: [None-->] 0 row: 0x10984f9d0 session: 0x109863570 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,187 - logic_logger - INF
..Item[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)} id: None, order_id: None, product_id: None, quantity: 10, amount: 900.0000000000000222044604925, unit_price: 100.0000000000 row: 0x10991f3d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,187 - logic_logger - INF
....Order[None] {Adjustment logic chaining deferred for this parent parent do_defer_adjustment: True, is_parent_submitted: True, is_parent_row_processed: False, order} id: None, notes: Carbon neutral test 1761523857184, customer_id: 51, CreatedOn: None, date_shipped: None, amount_total: [None-->] 900.0000000000000222044604925 row: 0x10984f9d0 session: 0x109863570 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,187 - logic_logger - INF
..Order[None] {Insert - client} id: None, notes: Carbon neutral test 1761523857184, customer_id: 51, CreatedOn: None, date_shipped: None, amount_total: 900.0000000000000222044604925 row: 0x10984f9d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,187 - logic_logger - INF
..Order[None] {early_row_event_all_classes - handle_all did stamping} id: None, notes: Carbon neutral test 1761523857184, customer_id: 51, CreatedOn: 2025-10-26 17:10:57.187415, date_shipped: None, amount_total: 900.0000000000000222044604925 row: 0x10984f9d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,187 - logic_logger - INF
..Order[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)} id: None, notes: Carbon neutral test 1761523857184, customer_id: 51, CreatedOn: 2025-10-26 17:10:57.187415, date_shipped: None, amount_total: 900.0000000000000222044604925 row: 0x10984f9d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,187 - logic_logger - INF
....Customer[51] {Update - Adjusting customer: balance} id: 51, name: Bob 1761523857179, balance: [0E-10-->] 900.0000000000000222044604925, credit_limit: 2000.0000000000, email: None, email_opt_out: None row: 0x10991eed0 session: 0x109863570 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,187 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109863570) - 2025-10-26 17:10:57,187 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109863570) - 2025-10-26 17:10:57,188 - logic_logger - INF
..Order[48] {AfterFlush Event} id: 48, notes: Carbon neutral test 1761523857184, customer_id: 51, CreatedOn: 2025-10-26 17:10:57.187415, date_shipped: None, amount_total: 900.0000000000000222044604925 row: 0x10984f9d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,188 - logic_logger - INF
..Order[48] {Sending Order to Shipping [Note: **Kafka not enabled** ]} id: 48, notes: Carbon neutral test 1761523857184, customer_id: 51, CreatedOn: 2025-10-26 17:10:57.187415, date_shipped: None, amount_total: 900.0000000000000222044604925 row: 0x10984f9d0 session: 0x109863570 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,188 - logic_logger - INF
Scenario: Multi-Item Order Totals Correctly
Scenario: Multi-Item Order Totals Correctly
Given Customer "Diana" with balance 0 and credit limit 3000
When B2B order placed for "Diana" with 3 Widget and 2 Gadget
Then Customer balance should be 470
And Order contains 2 items
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Multi-Item Order Totals Correctly
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Item
2. Derive <class 'database.models.Item'>.unit_price as Copy(product.unit_price)
3. Derive <class 'database.models.Item'>.amount as Formula (1): <function>
Order
4. Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)
5. RowEvent Order.send_order_to_shipping()
Logic Phase: ROW LOGIC (session=0x109863bd0) (sqlalchemy before_flush) - 2025-10-26 17:10:57,204 - logic_logger - INF
..Product[1] {Update - client} id: 1, name: Gadget, unit_price: 100.0000000000, carbon_neutral: True row: 0x1098b25f0 session: 0x109863bd0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,204 - logic_logger - INF
..Item[None] {Insert - client} id: None, order_id: None, product_id: 2, quantity: 3, amount: None, unit_price: None row: 0x10991f650 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,204 - logic_logger - INF
..Item[None] {copy_rules for role: product - unit_price} id: None, order_id: None, product_id: 2, quantity: 3, amount: None, unit_price: 90.0000000000 row: 0x10991f650 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,204 - logic_logger - INF
..Item[None] {Formula amount} id: None, order_id: None, product_id: 2, quantity: 3, amount: 270.0000000000, unit_price: 90.0000000000 row: 0x10991f650 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,204 - logic_logger - INF
....Order[None] {server aggregate_defaults: amount_total } id: None, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: None, date_shipped: None, amount_total: [None-->] 0 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,204 - logic_logger - INF
..Item[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)} id: None, order_id: None, product_id: 2, quantity: 3, amount: 270.0000000000, unit_price: 90.0000000000 row: 0x10991f650 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,204 - logic_logger - INF
....Order[None] {Adjustment logic chaining deferred for this parent parent do_defer_adjustment: True, is_parent_submitted: True, is_parent_row_processed: False, order} id: None, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: None, date_shipped: None, amount_total: [None-->] 270.0000000000 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,204 - logic_logger - INF
..Item[None] {Insert - client} id: None, order_id: None, product_id: None, quantity: 2, amount: None, unit_price: None row: 0x10991fe50 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,204 - logic_logger - INF
..Item[None] {copy_rules for role: product - unit_price} id: None, order_id: None, product_id: None, quantity: 2, amount: None, unit_price: 100.0000000000 row: 0x10991fe50 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,205 - logic_logger - INF
..Item[None] {Formula amount} id: None, order_id: None, product_id: None, quantity: 2, amount: 200.0000000000, unit_price: 100.0000000000 row: 0x10991fe50 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,205 - logic_logger - INF
..Item[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)} id: None, order_id: None, product_id: None, quantity: 2, amount: 200.0000000000, unit_price: 100.0000000000 row: 0x10991fe50 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,205 - logic_logger - INF
....Order[None] {Adjustment logic chaining deferred for this parent parent do_defer_adjustment: True, is_parent_submitted: True, is_parent_row_processed: False, order} id: None, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: None, date_shipped: None, amount_total: [270.0000000000-->] 470.0000000000 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,205 - logic_logger - INF
..Order[None] {Insert - client} id: None, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: None, date_shipped: None, amount_total: 470.0000000000 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,205 - logic_logger - INF
..Order[None] {early_row_event_all_classes - handle_all did stamping} id: None, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: 2025-10-26 17:10:57.205310, date_shipped: None, amount_total: 470.0000000000 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,205 - logic_logger - INF
..Order[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)} id: None, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: 2025-10-26 17:10:57.205310, date_shipped: None, amount_total: 470.0000000000 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,205 - logic_logger - INF
....Customer[52] {Update - Adjusting customer: balance} id: 52, name: Diana 1761523857196, balance: [0E-10-->] 470.0000000000, credit_limit: 3000.0000000000, email: None, email_opt_out: None row: 0x10991e3d0 session: 0x109863bd0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,205 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109863bd0) - 2025-10-26 17:10:57,205 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109863bd0) - 2025-10-26 17:10:57,206 - logic_logger - INF
..Order[49] {AfterFlush Event} id: 49, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: 2025-10-26 17:10:57.205310, date_shipped: None, amount_total: 470.0000000000 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,206 - logic_logger - INF
..Order[49] {Sending Order to Shipping [Note: **Kafka not enabled** ]} id: 49, notes: Multi-item test 1761523857201, customer_id: 52, CreatedOn: 2025-10-26 17:10:57.205310, date_shipped: None, amount_total: 470.0000000000 row: 0x1098b69d0 session: 0x109863bd0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,206 - logic_logger - INF
Scenario: Item Quantity Change Updates Totals
Scenario: Item Quantity Change Updates Totals
Given Customer "Alice" with balance 0 and credit limit 1000
And Order is created for "Alice" with 5 Widget
When Item quantity changed to 10
Then Item amount should be 900
And Order amount_total should be 900
And Customer balance should be 900
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Item Quantity Change Updates Totals
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Item
2. Derive <class 'database.models.Item'>.amount as Formula (1): <function>
Order
3. RowEvent Order.send_order_to_shipping()
4. Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)
Logic Phase: ROW LOGIC (session=0x109861e10) (sqlalchemy before_flush) - 2025-10-26 17:10:57,246 - logic_logger - INF
..Item[60] {Update - client} id: 60, order_id: 50, product_id: 2, quantity: [5-->] 10, amount: 450.0000000000, unit_price: 90.0000000000 row: 0x10991cad0 session: 0x109861e10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,246 - logic_logger - INF
..Item[60] {Formula amount} id: 60, order_id: 50, product_id: 2, quantity: [5-->] 10, amount: [450.0000000000-->] 900.0000000000, unit_price: 90.0000000000 row: 0x10991cad0 session: 0x109861e10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,246 - logic_logger - INF
....Order[50] {Update - Adjusting order: amount_total} id: 50, notes: Test order 1761523857230, customer_id: 53, CreatedOn: 2025-10-26, date_shipped: None, amount_total: [450.0000000000-->] 900.0000000000 row: 0x10991f7d0 session: 0x109861e10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,247 - logic_logger - INF
......Customer[53] {Update - Adjusting customer: balance} id: 53, name: Alice 1761523857220, balance: [450.0000000000-->] 900.0000000000, credit_limit: 1000.0000000000, email: None, email_opt_out: None row: 0x109a4c150 session: 0x109861e10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,247 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109861e10) - 2025-10-26 17:10:57,247 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109861e10) - 2025-10-26 17:10:57,248 - logic_logger - INF
....Order[50] {AfterFlush Event} id: 50, notes: Test order 1761523857230, customer_id: 53, CreatedOn: 2025-10-26, date_shipped: None, amount_total: [450.0000000000-->] 900.0000000000 row: 0x10991f7d0 session: 0x109861e10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,248 - logic_logger - INF
Scenario: Changing Customer Adjusts Both Balances
Scenario: Changing Customer Adjusts Both Balances
Given Customer "Alice" with balance 0 and credit limit 1000
And Customer "Bob" with balance 0 and credit limit 2000
And Order is created for "Alice" with 3 Widget
When Order customer changed to "Bob"
Then Customer "Alice" balance should be 0
And Customer "Bob" balance should be 270
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Changing Customer Adjusts Both Balances
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Order
2. RowEvent Order.send_order_to_shipping()
Logic Phase: ROW LOGIC (session=0x109862f10) (sqlalchemy before_flush) - 2025-10-26 17:10:57,278 - logic_logger - INF
..Order[51] {Update - client} id: 51, notes: Test order 1761523857266, customer_id: [54-->] 55, CreatedOn: 2025-10-26, date_shipped: None, amount_total: 270.0000000000 row: 0x109a4c3d0 session: 0x109862f10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,278 - logic_logger - INF
....Customer[55] {Update - Adjusting customer: balance, balance} id: 55, name: Bob 1761523857259, balance: [0E-10-->] 270.0000000000, credit_limit: 2000.0000000000, email: None, email_opt_out: None row: 0x109a4c9d0 session: 0x109862f10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,279 - logic_logger - INF
....Customer[54] {Update - Adjusting Old customer} id: 54, name: Alice 1761523857255, balance: [270.0000000000-->] 0E-10, credit_limit: 1000.0000000000, email: None, email_opt_out: None row: 0x109a4cad0 session: 0x109862f10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,279 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109862f10) - 2025-10-26 17:10:57,279 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109862f10) - 2025-10-26 17:10:57,280 - logic_logger - INF
..Order[51] {AfterFlush Event} id: 51, notes: Test order 1761523857266, customer_id: [54-->] 55, CreatedOn: 2025-10-26, date_shipped: None, amount_total: 270.0000000000 row: 0x109a4c3d0 session: 0x109862f10 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,280 - logic_logger - INF
Scenario: Delete Item Reduces Order Total
Scenario: Delete Item Reduces Order Total
Given Customer "Charlie" with balance 0 and credit limit 2000
And Order is created for "Charlie" with 2 Widget and 3 Gadget
When First item is deleted
Then Order amount_total should be 300
And Customer balance should be 300
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Delete Item Reduces Order Total
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Order
2. RowEvent Order.send_order_to_shipping()
3. Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)
Logic Phase: ROW LOGIC (session=0x109863570) (sqlalchemy before_flush) - 2025-10-26 17:10:57,310 - logic_logger - INF
..Item[62] {Delete - client} id: 62, order_id: 52, product_id: 2, quantity: 2, amount: 180.0000000000, unit_price: 90.0000000000 row: 0x10991fe50 session: 0x109863570 ins_upd_dlt: dlt, initial: dlt - 2025-10-26 17:10:57,310 - logic_logger - INF
....Order[52] {Update - Adjusting order: amount_total} id: 52, notes: Test order 1761523857290, customer_id: 56, CreatedOn: 2025-10-26, date_shipped: None, amount_total: [480.0000000000-->] 300.0000000000 row: 0x10991f6d0 session: 0x109863570 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,310 - logic_logger - INF
......Customer[56] {Update - Adjusting customer: balance} id: 56, name: Charlie 1761523857285, balance: [480.0000000000-->] 300.0000000000, credit_limit: 2000.0000000000, email: None, email_opt_out: None row: 0x109a4cb50 session: 0x109863570 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,311 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109863570) - 2025-10-26 17:10:57,311 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109863570) - 2025-10-26 17:10:57,311 - logic_logger - INF
....Order[52] {AfterFlush Event} id: 52, notes: Test order 1761523857290, customer_id: 56, CreatedOn: 2025-10-26, date_shipped: None, amount_total: [480.0000000000-->] 300.0000000000 row: 0x10991f6d0 session: 0x109863570 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,311 - logic_logger - INF
Scenario: Ship Order Excludes from Balance
Scenario: Ship Order Excludes from Balance
Given Customer "Diana" with balance 0 and credit limit 2000
And Order is created for "Diana" with 2 Widget
When Order is shipped
Then Customer balance should be 0
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Ship Order Excludes from Balance
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Order
2. RowEvent Order.send_order_to_shipping()
Logic Phase: ROW LOGIC (session=0x109863ce0) (sqlalchemy before_flush) - 2025-10-26 17:10:57,333 - logic_logger - INF
..Order[53] {Update - client} id: 53, notes: Test order 1761523857322, customer_id: 57, CreatedOn: 2025-10-26, date_shipped: [None-->] 2025-10-26 00:00:00, amount_total: 180.0000000000 row: 0x109a4d250 session: 0x109863ce0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,333 - logic_logger - INF
....Customer[57] {Update - Adjusting customer: balance} id: 57, name: Diana 1761523857316, balance: [180.0000000000-->] 0E-10, credit_limit: 2000.0000000000, email: None, email_opt_out: None row: 0x109a4e150 session: 0x109863ce0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,334 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109863ce0) - 2025-10-26 17:10:57,334 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109863ce0) - 2025-10-26 17:10:57,334 - logic_logger - INF
..Order[53] {AfterFlush Event} id: 53, notes: Test order 1761523857322, customer_id: 57, CreatedOn: 2025-10-26, date_shipped: [None-->] 2025-10-26 00:00:00, amount_total: 180.0000000000 row: 0x109a4d250 session: 0x109863ce0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,334 - logic_logger - INF
Scenario: Unship Order Includes in Balance
Scenario: Unship Order Includes in Balance
Given Customer "Alice" with balance 0 and credit limit 2000
And Shipped order is created for "Alice" with 4 Widget
When Order is unshipped
Then Customer balance should be 360
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Unship Order Includes in Balance
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Order
2. RowEvent Order.send_order_to_shipping()
Logic Phase: ROW LOGIC (session=0x109a648d0) (sqlalchemy before_flush) - 2025-10-26 17:10:57,355 - logic_logger - INF
..Order[54] {Update - client} id: 54, notes: Shipped order 1761523857344, customer_id: 58, CreatedOn: 2025-10-26, date_shipped: [2025-10-26-->] None, amount_total: 360.0000000000 row: 0x109a4d5d0 session: 0x109a648d0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,355 - logic_logger - INF
....Customer[58] {Update - Adjusting customer: balance} id: 58, name: Alice 1761523857337, balance: [0E-10-->] 360.0000000000, credit_limit: 2000.0000000000, email: None, email_opt_out: None row: 0x109a4ead0 session: 0x109a648d0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,355 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109a648d0) - 2025-10-26 17:10:57,355 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109a648d0) - 2025-10-26 17:10:57,356 - logic_logger - INF
..Order[54] {AfterFlush Event} id: 54, notes: Shipped order 1761523857344, customer_id: 58, CreatedOn: 2025-10-26, date_shipped: [2025-10-26-->] None, amount_total: 360.0000000000 row: 0x109a4d5d0 session: 0x109a648d0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,356 - logic_logger - INF
Scenario: Exceed Credit Limit Rejected
Scenario: Exceed Credit Limit Rejected
Given Customer "Bob" with balance 0 and credit limit 500
When B2B order placed for "Bob" with 10 Widget
Then Order creation should fail
And Error message mentions credit limit
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Exceed Credit Limit Rejected
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
2. Constraint Function: None
Item
3. Derive <class 'database.models.Item'>.unit_price as Copy(product.unit_price)
4. Derive <class 'database.models.Item'>.amount as Formula (1): <function>
Order
5. Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)
Logic Phase: ROW LOGIC (session=0x1098638a0) (sqlalchemy before_flush) - 2025-10-26 17:10:57,369 - logic_logger - INFO
..Customer[None] {Insert - client} id: None, name: Alice 1761523857368, balance: 0, credit_limit: 2000, email: None, email_opt_out: None row: 0x10991f850 session: 0x1098638a0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,369 - logic_logger - INFO
..Customer[None] {server aggregate_defaults: balance } id: None, name: Alice 1761523857368, balance: 0, credit_limit: 2000, email: None, email_opt_out: None row: 0x10991f850 session: 0x1098638a0 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,370 - logic_logger - INFO
Logic Phase: COMMIT LOGIC (session=0x1098638a0) - 2025-10-26 17:10:57,370 - logic_logger - INFO
Logic Phase: AFTER_FLUSH LOGIC (session=0x1098638a0) - 2025-10-26 17:10:57,370 - logic_logger - INFO
These Rules Fired (see Logic Phases, above, for actual order):
Logic Phase: ROW LOGIC (session=0x109a64160) (sqlalchemy before_flush) - 2025-10-26 17:10:57,365 - logic_logger - INF
..Product[2] {Update - client} id: 2, name: Widget, unit_price: 90.0000000000, carbon_neutral: None row: 0x109a523c0 session: 0x109a64160 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,365 - logic_logger - INF
..Item[None] {Insert - client} id: None, order_id: None, product_id: None, quantity: 10, amount: None, unit_price: None row: 0x109a4ddd0 session: 0x109a64160 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,365 - logic_logger - INF
..Item[None] {copy_rules for role: product - unit_price} id: None, order_id: None, product_id: None, quantity: 10, amount: None, unit_price: 90.0000000000 row: 0x109a4ddd0 session: 0x109a64160 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,365 - logic_logger - INF
..Item[None] {Formula amount} id: None, order_id: None, product_id: None, quantity: 10, amount: 900.0000000000, unit_price: 90.0000000000 row: 0x109a4ddd0 session: 0x109a64160 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,365 - logic_logger - INF
....Order[None] {server aggregate_defaults: amount_total } id: None, notes: Test order 1761523857363, customer_id: 59, CreatedOn: None, date_shipped: None, amount_total: [None-->] 0 row: 0x109a33ed0 session: 0x109a64160 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,366 - logic_logger - INF
..Item[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)} id: None, order_id: None, product_id: None, quantity: 10, amount: 900.0000000000, unit_price: 90.0000000000 row: 0x109a4ddd0 session: 0x109a64160 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,366 - logic_logger - INF
....Order[None] {Adjustment logic chaining deferred for this parent parent do_defer_adjustment: True, is_parent_submitted: True, is_parent_row_processed: False, order} id: None, notes: Test order 1761523857363, customer_id: 59, CreatedOn: None, date_shipped: None, amount_total: [None-->] 900.0000000000 row: 0x109a33ed0 session: 0x109a64160 ins_upd_dlt: *, initial: * - 2025-10-26 17:10:57,366 - logic_logger - INF
..Order[None] {Insert - client} id: None, notes: Test order 1761523857363, customer_id: 59, CreatedOn: None, date_shipped: None, amount_total: 900.0000000000 row: 0x109a33ed0 session: 0x109a64160 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,366 - logic_logger - INF
..Order[None] {early_row_event_all_classes - handle_all did stamping} id: None, notes: Test order 1761523857363, customer_id: 59, CreatedOn: 2025-10-26 17:10:57.366212, date_shipped: None, amount_total: 900.0000000000 row: 0x109a33ed0 session: 0x109a64160 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,366 - logic_logger - INF
..Order[None] {TODO DB adjust_from_inserted/adopted_child adjusts Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)} id: None, notes: Test order 1761523857363, customer_id: 59, CreatedOn: 2025-10-26 17:10:57.366212, date_shipped: None, amount_total: 900.0000000000 row: 0x109a33ed0 session: 0x109a64160 ins_upd_dlt: ins, initial: ins - 2025-10-26 17:10:57,366 - logic_logger - INF
....Customer[59] {Update - Adjusting customer: balance} id: 59, name: Bob 1761523857359, balance: [0E-10-->] 900.0000000000, credit_limit: 500.0000000000, email: None, email_opt_out: None row: 0x109a4e950 session: 0x109a64160 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,366 - logic_logger - INF
....Customer[59] {Constraint Failure: Customer balance (900.0000000000) exceeds credit limit (500.0000000000)} id: 59, name: Bob 1761523857359, balance: [0E-10-->] 900.0000000000, credit_limit: 500.0000000000, email: None, email_opt_out: None row: 0x109a4e950 session: 0x109a64160 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,366 - logic_logger - INF
Scenario: Change Product Updates Unit Price
Scenario: Change Product Updates Unit Price
Given Customer "Alice" with balance 0 and credit limit 2000
And Order is created for "Alice" with 5 Widget
When Item product changed to "Gadget"
Then Item unit_price should be 100
And Item amount should be 500
And Customer balance should be 500
Tests - and their logic - are transparent.. click to see Logic
Rules Used in Scenario: Change Product Updates Unit Price
Customer
1. Derive <class 'database.models.Customer'>.balance as Sum(Order.amount_total Where Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None) - <function declare_logic.<locals>.<lambda> at 0x10883d260>)
Item
2. Derive <class 'database.models.Item'>.unit_price as Copy(product.unit_price)
3. Derive <class 'database.models.Item'>.amount as Formula (1): <function>
Order
4. Derive <class 'database.models.Order'>.amount_total as Sum(Item.amount Where - None)
5. RowEvent Order.send_order_to_shipping()
Logic Phase: ROW LOGIC (session=0x109862cf0) (sqlalchemy before_flush) - 2025-10-26 17:10:57,389 - logic_logger - INF
..Item[66] {Update - client} id: 66, order_id: 55, product_id: [2-->] 1, quantity: 5, amount: 450.0000000000, unit_price: 90.0000000000 row: 0x109a4e050 session: 0x109862cf0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,389 - logic_logger - INF
..Item[66] {copy_rules for role: product - unit_price} id: 66, order_id: 55, product_id: [2-->] 1, quantity: 5, amount: 450.0000000000, unit_price: [90.0000000000-->] 100.0000000000 row: 0x109a4e050 session: 0x109862cf0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,389 - logic_logger - INF
..Item[66] {Formula amount} id: 66, order_id: 55, product_id: [2-->] 1, quantity: 5, amount: [450.0000000000-->] 500.0000000000, unit_price: [90.0000000000-->] 100.0000000000 row: 0x109a4e050 session: 0x109862cf0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,389 - logic_logger - INF
....Order[55] {Update - Adjusting order: amount_total} id: 55, notes: Test order 1761523857375, customer_id: 60, CreatedOn: 2025-10-26, date_shipped: None, amount_total: [450.0000000000-->] 500.0000000000 row: 0x109a4ced0 session: 0x109862cf0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,390 - logic_logger - INF
......Customer[60] {Update - Adjusting customer: balance} id: 60, name: Alice 1761523857368, balance: [450.0000000000-->] 500.0000000000, credit_limit: 2000.0000000000, email: None, email_opt_out: None row: 0x109a4d0d0 session: 0x109862cf0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,390 - logic_logger - INF
Logic Phase: COMMIT LOGIC (session=0x109862cf0) - 2025-10-26 17:10:57,390 - logic_logger - INF
Logic Phase: AFTER_FLUSH LOGIC (session=0x109862cf0) - 2025-10-26 17:10:57,391 - logic_logger - INF
....Order[55] {AfterFlush Event} id: 55, notes: Test order 1761523857375, customer_id: 60, CreatedOn: 2025-10-26, date_shipped: None, amount_total: [450.0000000000-->] 500.0000000000 row: 0x109a4ced0 session: 0x109862cf0 ins_upd_dlt: upd, initial: upd - 2025-10-26 17:10:57,391 - logic_logger - INF
/Users/val/dev/ApiLogicServer/ApiLogicServer-dev/build_and_test/ApiLogicServer/basic_demo/test/api_logic_server_behave/behave_run.py completed at October 26, 2025 17:10:5