ApiLogicServer 14.2.20__py3-none-any.whl → 14.3.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/METADATA +2 -2
  2. {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/RECORD +90 -69
  3. api_logic_server_cli/api_logic_server.py +5 -1
  4. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  5. api_logic_server_cli/cli.py +5 -2
  6. api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
  7. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  8. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  9. api_logic_server_cli/create_from_model/api_logic_server_utils.py +4 -0
  10. api_logic_server_cli/create_from_model/ont_build.py +53 -19
  11. api_logic_server_cli/create_from_model/ont_create.py +14 -5
  12. api_logic_server_cli/fragments/declare_logic.py +72 -0
  13. api_logic_server_cli/{prototypes/manager/system/genai/create_db_models_inserts/logic_discovery_prefix.py → fragments/declare_logic_begin.py} +2 -1
  14. api_logic_server_cli/fragments/declare_logic_end.py +52 -0
  15. api_logic_server_cli/genai/genai.py +25 -8
  16. api_logic_server_cli/genai/genai_logic_builder.py +14 -11
  17. api_logic_server_cli/genai/genai_svcs.py +104 -7
  18. api_logic_server_cli/manager.py +20 -16
  19. api_logic_server_cli/model_migrator/model_migrator_start.py +1 -1
  20. api_logic_server_cli/model_migrator/reposreader.py +9 -1
  21. api_logic_server_cli/model_migrator/rule_obj.py +24 -6
  22. api_logic_server_cli/prototypes/base/api/api_discovery/ontimize_api.py +4 -1
  23. api_logic_server_cli/prototypes/base/api/system/expression_parser.py +10 -4
  24. api_logic_server_cli/prototypes/base/config/activate_logicbank.py +8 -4
  25. api_logic_server_cli/prototypes/base/database/bind_dbs.py +1 -1
  26. api_logic_server_cli/prototypes/base/database/test_data/readme.md +5 -5
  27. api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +32 -8
  28. api_logic_server_cli/prototypes/base/integration/system/RowDictMapper.py +33 -16
  29. api_logic_server_cli/prototypes/base/logic/declare_logic.py +9 -3
  30. api_logic_server_cli/prototypes/base/logic/load_verify_rules.py +217 -0
  31. api_logic_server_cli/prototypes/base/logic/logic_discovery/auto_discovery.py +22 -13
  32. api_logic_server_cli/prototypes/genai_demo/api/customize_api.py +9 -11
  33. api_logic_server_cli/prototypes/genai_demo/database/.DS_Store +0 -0
  34. api_logic_server_cli/prototypes/genai_demo/database/db.sqlite +0 -0
  35. api_logic_server_cli/prototypes/genai_demo/database/models.py +52 -42
  36. api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/OrderB2B.py +4 -6
  37. api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/__pycache__/OrderB2B.cpython-312.pyc +0 -0
  38. api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/row_dict_maps_readme.md +3 -0
  39. api_logic_server_cli/prototypes/genai_demo/logic/__pycache__/declare_logic.cpython-312.pyc +0 -0
  40. api_logic_server_cli/prototypes/genai_demo/logic/__pycache__/load_verify_rules.cpython-312.pyc +0 -0
  41. api_logic_server_cli/prototypes/genai_demo/logic/declare_logic.py +58 -62
  42. api_logic_server_cli/prototypes/genai_demo/logic/load_verify_rules.py +216 -0
  43. api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/__init__.cpython-312.pyc +0 -0
  44. api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  45. api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/error_testing.cpython-312.pyc +0 -0
  46. api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/auto_discovery.py +52 -0
  47. api_logic_server_cli/prototypes/genai_demo/logic/readme_declare_logic.md +172 -0
  48. api_logic_server_cli/prototypes/genai_demo/security/__pycache__/declare_security.cpython-312.pyc +0 -0
  49. api_logic_server_cli/prototypes/genai_demo/ui/admin/admin.yaml +86 -53
  50. api_logic_server_cli/prototypes/manager/.vscode/launch.json +1 -1
  51. api_logic_server_cli/prototypes/manager/README.md +19 -4
  52. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.prompt +4 -1
  53. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +34 -26
  54. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_informal.prompt +3 -0
  55. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/.DS_Store +0 -0
  56. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/000_you_are.prompt +1 -0
  57. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/001_logic_training.prompt +314 -0
  58. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/002_create_db_models.prompt +150 -0
  59. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/003_create_db_models.response +134 -0
  60. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/004_iteratio_logic.prompt +131 -0
  61. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/005_create_db_models.response-example +141 -0
  62. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/create_db_models.py +105 -0
  63. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/db.dbml +70 -0
  64. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/readme.md +6 -0
  65. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/response.json +178 -0
  66. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/base_genai_demo_no_logic/logic/declare_logic.py +0 -1
  67. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/dev_demo_no_logic_fixed/logic/declare_logic.py +0 -1
  68. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/genai/examples/genai_demo/wg_dev_merge/base_genai_demo_no_logic/logic/declare_logic.py +0 -1
  69. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/genai/examples/genai_demo/wg_dev_merge/dev_demo_no_logic_fixed/logic/declare_logic.py +0 -1
  70. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/genai/examples/genai_demo/wg_dev_merge/wg_genai_demo_no_logic_fixed_from_CLI/logic/declare_logic.py +0 -1
  71. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/logic/declare_logic.py +0 -1
  72. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/system/genai/examples/genai_demo/wg_dev_merge/base_genai_demo_no_logic/logic/declare_logic.py +0 -1
  73. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/system/genai/examples/genai_demo/wg_dev_merge/dev_demo_no_logic_fixed/logic/declare_logic.py +0 -1
  74. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/system/genai/examples/genai_demo/wg_dev_merge/wg_genai_demo_no_logic_fixed_from_CLI/logic/declare_logic.py +0 -1
  75. api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/002_create_db_models.prompt +194 -0
  76. api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/003_create_db_models.response +298 -0
  77. api_logic_server_cli/prototypes/{genai_demo/database/chatgpt/sample_ai.sqlite → manager/system/genai/examples/time_tracking_billing/db.sqlite} +0 -0
  78. api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/readme.md +61 -0
  79. api_logic_server_cli/prototypes/manager/system/genai/learning_requests/logic_bank_api.prompt +29 -11
  80. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/iteration.prompt +2 -1
  81. api_logic_server_cli/prototypes/nw_no_cust/venv_setup/system_note.txt +1 -1
  82. api_logic_server_cli/prototypes/ont_app/templates/home_tree_template.html +9 -0
  83. api_logic_server_cli/prototypes/ont_app/templates/tree_routing.jinja +32 -0
  84. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/codegen.cpython-312.pyc +0 -0
  85. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py +4 -2
  86. api_logic_server_cli/tools/mini_skel/logic/load_verify_rules.py +1 -1
  87. api_logic_server_cli/model_migrator/system/custom_endpoint.py +0 -545
  88. api_logic_server_cli/prototypes/base/database/test_data/z_test_data_rows.py +0 -98
  89. api_logic_server_cli/prototypes/genai_demo/database/chatgpt/__pycache__/copilot_models.cpython-312.pyc +0 -0
  90. api_logic_server_cli/prototypes/genai_demo/database/chatgpt/__pycache__/sample_ai_models.cpython-312.pyc +0 -0
  91. api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai.chatgpt +0 -16
  92. api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai.sql +0 -66
  93. api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_items.sqlite +0 -0
  94. api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_models.py +0 -156
  95. api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_models.sqlite +0 -0
  96. api_logic_server_cli/prototypes/genai_demo/logic/cocktail-napkin.jpg +0 -0
  97. {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/LICENSE +0 -0
  98. {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/WHEEL +0 -0
  99. {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/entry_points.txt +0 -0
  100. {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/top_level.txt +0 -0
@@ -109,7 +109,7 @@ als genai --using=system/genai/examples/genai_demo/genai_demo.prompt --project-n
109
109
 
110
110
 
111
111
  ```bash
112
- als genai --repaired-response=system/genai/examples/genai_demo/genai_demo_iteration/005_create_db_models.response-example --project-name=genai_demo
112
+ als genai --repaired-response=system/genai/examples/genai_demo/genai_demo.response_example --project-name=genai_demo
113
113
  ```
114
114
 
115
115
  Verify it's operating properly:
@@ -149,9 +149,22 @@ Verify it's operating properly:
149
149
 
150
150
  <details markdown>
151
151
 
152
- <summary> You can iterate the data model and logic</summary>
152
+ <summary> You can iterate the logic and data model</summary>
153
153
 
154
- <br>You can add new columns/tables, while keeping the prior model intact:
154
+ <br>Logic iterations are particuarly useful. For example, here we take the basic check-credit logic, and add:
155
+
156
+ > Provide a 10% discount when buying more than 10 carbon neutral products.<br><br>The Item carbon neutral is copied from the Product carbon neutral
157
+
158
+ Explore [genai_demo_iteration_discount](system/genai/examples/genai_demo/genai_demo_iteration_discount). This will add carbon_neutral to the data model, and update the logic to provide the discount:
159
+
160
+ ```bash title='Iterate Business Logic'
161
+ # Iterate with data model and logic
162
+ als genai --project-name='genai_demo_with_logic' --using=system/genai/examples/genai_demo/genai_demo_iteration
163
+ # open Docs/db.dbml
164
+ ```
165
+ <br>
166
+
167
+ You can add new columns/tables, while keeping the prior model intact:
155
168
 
156
169
  ```bash title='Iterate Without Logic'
157
170
  # Step 1 - create without logic
@@ -164,7 +177,9 @@ als genai --project-name='genai_demo_no_logic' --using=system/genai/examples/gen
164
177
  als genai --project-name='genai_demo_with_logic' --using=system/genai/examples/genai_demo/genai_demo_iteration
165
178
  # open Docs/db.dbml
166
179
  ```
167
- > Explore [genai_demo_iteration](system/genai/examples/genai_demo/genai_demo_iteration) - observe the `--using` is a *directory* of prompts. These include the prompts from the first example, plus an *iteration prompt* (`004_iteration_renames_logic.prompt`) to rename tables and add logic.
180
+
181
+ Explore [genai_demo_iteration](system/genai/examples/genai_demo/genai_demo_iteration) - observe the `--using` is a *directory* of prompts. These include the prompts from the first example, plus an *iteration prompt* (`004_iteration_renames_logic.prompt`) to rename tables and add logic.
182
+
168
183
 
169
184
  </details>
170
185
  </br>
@@ -4,13 +4,16 @@ Include a notes field for orders.
4
4
 
5
5
  Use LogicBank to enforce business logic.
6
6
 
7
- Use case: Check Credit
7
+ Use case: Check Credit
8
8
  1. The Customer's balance is less than the credit limit
9
9
  2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
10
10
  3. The Order's amount_total is the sum of the Item amount
11
11
  4. The Item amount is the quantity * unit_price
12
12
  5. The Item unit_price is copied from the Product unit_price
13
13
 
14
+ Use case: App Integration
15
+ 1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
16
+
14
17
  Ensure each customer has a unique name.
15
18
 
16
19
  Ensure each Item quantity is not null.
@@ -2,82 +2,90 @@
2
2
  "models": [
3
3
  {
4
4
  "classname": "Customer",
5
- "code": "class Customer(Base):\n __tablename__ = 'customers'\n id = Column(Integer, primary_key=True, autoincrement=True)\n name = Column(String, nullable=False)\n balance = Column(Integer, default=0)\n credit_limit = Column(Integer, nullable=False)\n\n def __repr__(self):\n return f\"Customer(id={self.id}, name='{self.name}', balance={self.balance}, credit_limit={self.credit_limit})\"",
6
- "sqlite_create": "CREATE TABLE customers (\n id INTEGER PRIMARY KEY AUTOINCREMENT, \n name VARCHAR NOT NULL, \n balance INTEGER DEFAULT 0, \n credit_limit INTEGER NOT NULL\n)",
7
- "description": "description: Customers table",
8
- "name": "customers"
5
+ "code": "class Customer(Base):\n __tablename__ = 'customer'\n id = Column(Integer, primary_key=True, autoincrement=True)\n name = Column(String, unique=True)\n balance = Column(DECIMAL)\n credit_limit = Column(DECIMAL)",
6
+ "description": "Represents a customer in the system with unique name, balance, and credit limit attributes.",
7
+ "name": "Customer"
9
8
  },
10
9
  {
11
10
  "classname": "Order",
12
- "code": "class Order(Base):\n __tablename__ = 'orders'\n id = Column(Integer, primary_key=True, autoincrement=True)\n customer_id = Column(Integer, ForeignKey('customers.id'))\n notes = Column(String)\n date_shipped = Column(Date)\n amount_total = Column(Integer, default=0)\n\n def __repr__(self):\n return f\"Order(id={self.id}, customer_id={self.customer_id}, notes='{self.notes}', amount_total={self.amount_total}, date_shipped={self.date_shipped})\"",
13
- "sqlite_create": "CREATE TABLE orders (\n id INTEGER PRIMARY KEY AUTOINCREMENT, \n customer_id INTEGER, \n notes VARCHAR, \n date_shipped DATE, \n amount_total INTEGER DEFAULT 0, \n FOREIGN KEY(customer_id) REFERENCES customers (id)\n)",
14
- "description": "description: Orders table",
15
- "name": "orders"
11
+ "code": "class Order(Base):\n __tablename__ = 'order'\n id = Column(Integer, primary_key=True, autoincrement=True)\n customer_id = Column(Integer, ForeignKey('customer.id'))\n date_shipped = Column(Date)\n amount_total = Column(DECIMAL)\n notes = Column(String)",
12
+ "description": "Represents an order made by a customer, including a notes field.",
13
+ "name": "Order"
16
14
  },
17
15
  {
18
16
  "classname": "Item",
19
- "code": "class Item(Base):\n __tablename__ = 'items'\n id = Column(Integer, primary_key=True, autoincrement=True)\n order_id = Column(Integer, ForeignKey('orders.id'))\n product_id = Column(Integer, ForeignKey('products.id'))\n quantity = Column(Integer, nullable=False)\n unit_price = Column(Integer, nullable=False)\n amount = Column(Integer, default=0)\n\n def __repr__(self):\n return f\"Item(id={self.id}, order_id={self.order_id}, product_id={self.product_id}, quantity={self.quantity}, unit_price={self.unit_price}, amount={self.amount})\"",
20
- "sqlite_create": "CREATE TABLE items (\n id INTEGER PRIMARY KEY AUTOINCREMENT, \n order_id INTEGER, \n product_id INTEGER, \n quantity INTEGER NOT NULL, \n unit_price INTEGER NOT NULL, \n amount INTEGER DEFAULT 0, \n FOREIGN KEY(order_id) REFERENCES orders (id), \n FOREIGN KEY(product_id) REFERENCES products (id)\n)",
21
- "description": "description: Items table",
22
- "name": "items"
17
+ "code": "class Item(Base):\n __tablename__ = 'item'\n id = Column(Integer, primary_key=True, autoincrement=True)\n order_id = Column(Integer, ForeignKey('order.id'))\n product_id = Column(Integer, ForeignKey('product.id'))\n quantity = Column(Integer, nullable=False)\n unit_price = Column(DECIMAL)\n amount = Column(DECIMAL)",
18
+ "description": "Represents an item in an order, including quantity and pricing details.",
19
+ "name": "Item"
23
20
  },
24
21
  {
25
22
  "classname": "Product",
26
- "code": "class Product(Base):\n __tablename__ = 'products'\n id = Column(Integer, primary_key=True, autoincrement=True)\n name = Column(String, nullable=False)\n unit_price = Column(Integer, nullable=False)\n\n def __repr__(self):\n return f\"Product(id={self.id}, name='{self.name}', unit_price={self.unit_price})\"",
27
- "sqlite_create": "CREATE TABLE products (\n id INTEGER PRIMARY KEY AUTOINCREMENT, \n name VARCHAR NOT NULL, \n unit_price INTEGER NOT NULL\n)",
28
- "description": "description: Products table",
29
- "name": "products"
23
+ "code": "class Product(Base):\n __tablename__ = 'product'\n id = Column(Integer, primary_key=True, autoincrement=True)\n name = Column(String)\n unit_price = Column(DECIMAL)",
24
+ "description": "Represents a product available in the system with a unit price.",
25
+ "name": "Product"
30
26
  }
31
27
  ],
32
28
  "rules": [
33
29
  {
34
30
  "name": "Customer Balance Constraint",
35
- "description": "Ensures the customer's balance does not exceed the credit limit.",
31
+ "description": "Ensures the customer's balance is aligned with the credit limit.",
36
32
  "use_case": "Customer.balance <= credit_limit",
37
- "code": "Rule.constraint(validate=Customer,\n as_condition=lambda row: row.balance <= row.credit_limit,\n error_msg=\"Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})\")"
33
+ "entity": "Customer",
34
+ "code": "Rule.constraint(validate=Customer,\n as_condition=lambda row: row.balance <= row.credit_limit,\n error_msg='Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})')"
38
35
  },
39
36
  {
40
37
  "name": "Customer Balance Derivation",
41
38
  "description": "Calculates the customer's balance as the sum of orders' amount_total where date_shipped is null.",
42
39
  "use_case": "Customer.balance = Sum(Order.amount_total where date_shipped is null)",
40
+ "entity": "Customer",
43
41
  "code": "Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None)"
44
42
  },
45
43
  {
46
44
  "name": "Order Amount Total Derivation",
47
45
  "description": "Calculates order's amount_total as the sum of item amounts.",
48
46
  "use_case": "Order.amount_total = Sum(Item.amount)",
47
+ "entity": "Order",
49
48
  "code": "Rule.sum(derive=Order.amount_total, as_sum_of=Item.amount)"
50
49
  },
51
50
  {
52
51
  "name": "Item Amount Derivation",
53
52
  "description": "Calculates item amount as quantity multiplied by unit price.",
54
53
  "use_case": "Item.amount = quantity * unit_price",
54
+ "entity": "Item",
55
55
  "code": "Rule.formula(derive=Item.amount, as_expression=lambda row: row.quantity * row.unit_price)"
56
56
  },
57
57
  {
58
58
  "name": "Copy Item Unit Price",
59
59
  "description": "Copies the product's unit price to the item.",
60
60
  "use_case": "Store the Item.unit_price as a copy from Product.unit_price",
61
+ "entity": "Item",
61
62
  "code": "Rule.copy(derive=Item.unit_price, from_parent=Product.unit_price)"
63
+ },
64
+ {
65
+ "name": "Order Kafka Integration",
66
+ "description": "Sends the order to Kafka topic 'order_shipping' if the date shipped is not None.",
67
+ "use_case": "App Integration",
68
+ "entity": "Order",
69
+ "code": "Rule.after_flush_row_event(on_class=Order, calling=kafka_producer.send_row_to_kafka, if_condition=lambda row: row.date_shipped is not None, with_args={\"topic\": \"order_shipping\"})"
62
70
  }
63
71
  ],
64
72
  "test_data": "Insert test data into the tables with values compatible with the derived logic.",
65
73
  "test_data_rows": [
66
74
  {
67
75
  "test_data_row_variable": "test_customer_1",
68
- "code": "test_customer_1 = Customer(name='Customer 1', balance=300, credit_limit=1000)"
76
+ "code": "test_customer_1 = Customer(name='Customer 1', balance=150, credit_limit=1000)"
69
77
  },
70
78
  {
71
79
  "test_data_row_variable": "test_customer_2",
72
- "code": "test_customer_2 = Customer(name='Customer 2', balance=500, credit_limit=750)"
80
+ "code": "test_customer_2 = Customer(name='Customer 2', balance=275, credit_limit=750)"
73
81
  },
74
82
  {
75
83
  "test_data_row_variable": "test_customer_3",
76
- "code": "test_customer_3 = Customer(name='Customer 3', balance=0, credit_limit=1500)"
84
+ "code": "test_customer_3 = Customer(name='Customer 3', balance=150, credit_limit=1500)"
77
85
  },
78
86
  {
79
87
  "test_data_row_variable": "test_customer_4",
80
- "code": "test_customer_4 = Customer(name='Customer 4', balance=200, credit_limit=1200)"
88
+ "code": "test_customer_4 = Customer(name='Customer 4', balance=0, credit_limit=1200)"
81
89
  },
82
90
  {
83
91
  "test_data_row_variable": "test_order_1",
@@ -85,11 +93,11 @@
85
93
  },
86
94
  {
87
95
  "test_data_row_variable": "test_order_2",
88
- "code": "test_order_2 = Order(customer_id=2, notes='Order 2 notes', amount_total=0)"
96
+ "code": "test_order_2 = Order(customer_id=2, notes='Order 2 notes', amount_total=225)"
89
97
  },
90
98
  {
91
99
  "test_data_row_variable": "test_order_3",
92
- "code": "test_order_3 = Order(customer_id=2, notes='Order 3 notes', amount_total=0)"
100
+ "code": "test_order_3 = Order(customer_id=2, notes='Order 3 notes', amount_total=50)"
93
101
  },
94
102
  {
95
103
  "test_data_row_variable": "test_order_4",
@@ -101,11 +109,11 @@
101
109
  },
102
110
  {
103
111
  "test_data_row_variable": "test_item_2",
104
- "code": "test_item_2 = Item(order_id=2, product_id=2, quantity=2, unit_price=0, amount=0)"
112
+ "code": "test_item_2 = Item(order_id=2, product_id=2, quantity=2, unit_price=25, amount=50)"
105
113
  },
106
114
  {
107
115
  "test_data_row_variable": "test_item_3",
108
- "code": "test_item_3 = Item(order_id=3, product_id=3, quantity=1, unit_price=0, amount=0)"
116
+ "code": "test_item_3 = Item(order_id=3, product_id=3, quantity=3, unit_price=75, amount=225)"
109
117
  },
110
118
  {
111
119
  "test_data_row_variable": "test_item_4",
@@ -11,6 +11,9 @@ Use case: Check Credit
11
11
  4. The Item amount is the quantity * unit_price
12
12
  5. The Item unit_price is copied from the Product unit_price
13
13
 
14
+ Use case: App Integration
15
+ 1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
16
+
14
17
  Ensure each customer has a unique name.
15
18
 
16
19
  Ensure each Item quantity is not null.
@@ -0,0 +1 @@
1
+ You are a data modelling expert and python software architect who expands on user input ideas. You create data models with at least 4 tables
@@ -0,0 +1,314 @@
1
+ Here is the simplified API for LogicBank:
2
+
3
+ Create a function called declare_logic(), consisting of calls to Rule methods.
4
+
5
+ Do not generate import statements.
6
+
7
+ If you create sum, count or formula LogicBank rules, you MUST create a corresponding column in the data model.
8
+
9
+ Use only the methods provided below.
10
+
11
+
12
+ class Rule:
13
+ """Invoke these functions to declare rules in the created declare_logic function. """
14
+
15
+ @staticmethod
16
+ def sum(derive: Column, as_sum_of: any, where: any = None, insert_parent: bool=False):
17
+ """
18
+ Derive parent column as sum of designated child column, optional where
19
+
20
+ Example
21
+ Prompt
22
+ Customer.Balance = Sum(Order.amount_total where date_shipped is null)
23
+ Response
24
+ Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal,
25
+ where=lambda row: row.ShippedDate is None)
26
+
27
+ Args:
28
+ derive: name of parent <class.attribute> being derived
29
+ as_sum_of: name of child <class.attribute> being summed
30
+ where: optional where clause, designates which child rows are summed. All referenced columns must be part of the data model - create columns in the data model as required. Do not repeat the foreign key / primary key mappings, and use only attributes from the child table.
31
+ insert_parent: create parent if it does not exist. Do not use unless directly requested.
32
+ """
33
+ return Sum(derive, as_sum_of, where, insert_parent)
34
+
35
+
36
+ @staticmethod
37
+ def count(derive: Column, as_count_of: object, where: any = None, str = "", insert_parent: bool=False):
38
+ """
39
+ Derive parent column as count of designated child rows
40
+
41
+ Example
42
+ Prompt
43
+ Customer.UnPaidOrders = count(Orders where ShippedDate is None)
44
+ Response
45
+ Rule.count(derive=Customer.UnPaidOrders, as_count_of=Order,
46
+ where=Lambda row: row.ShippedDate is None)
47
+
48
+ Args:
49
+ derive: name of parent <class.attribute> being derived
50
+ as_count_of: name of child <class> being counted
51
+ where: optional where clause, designates which child rows are counted. All referenced columns must be part of the data model - create columns in the data model as required. Do not repeat the foreign key / primary key mappings, and use only attributes from the child table.
52
+ insert_parent: create parent if it does not exist. Do not use unless directly requested.
53
+ """
54
+ return Count(derive, as_count_of, where, insert_parent)
55
+
56
+
57
+ @staticmethod
58
+ def constraint(validate: object,
59
+ calling: Callable = None,
60
+ as_condition: any = None,
61
+ error_msg: str = "(error_msg not provided)",
62
+ error_attributes=None):
63
+ """
64
+ Constraints declare condition that must be true for all commits
65
+
66
+ Example
67
+ Prompt
68
+ Customer.balance <= credit_limit
69
+ Response
70
+ Rule.constraint(validate=Customer,
71
+ as_condition=lambda row: row.Balance <= row.CreditLimit,
72
+ error_msg="balance ({row.Balance}) exceeds credit ({row.CreditLimit})")
73
+
74
+ Args:
75
+ validate: name of mapped <class>
76
+ as_condition: lambda, passed row (simple constraints). All referenced columns must be part of the data model - create columns in the data model as required. Also, conditions may not contain sum or count python functions - these must be used to declare additional columns and sum/count rules.
77
+ error_msg: string, with {row.attribute} replacements
78
+ error_attributes: list of attributes
79
+
80
+ """
81
+ if error_attributes is None:
82
+ error_attributes = []
83
+ return Constraint(validate=validate, as_condition=as_condition,
84
+ error_attributes=error_attributes, error_msg=error_msg)
85
+
86
+
87
+ @staticmethod
88
+ def formula(derive: Column,
89
+ as_expression: Callable = None,
90
+ no_prune: bool = False):
91
+ """
92
+ Formulas declare column value, based on current and parent rows
93
+
94
+ Example
95
+ Prompt
96
+ Item.amount = quantity * unit_price
97
+ Response
98
+ Rule.formula(derive=OrderDetail.Amount,
99
+ as_expression=lambda row: row.UnitPrice * row.Quantity)
100
+
101
+ Args:
102
+ derive: <class.attribute> being derived
103
+ as_expression: lambda, passed row (for syntax checking). All referenced columns must be part of the data model - create columns in the data model as required. Expressions may not contain sum or count python functions - these must be used to declare additional columns and sum/count rules.
104
+ no_prune: disable pruning (rarely used, default False)
105
+ """
106
+ return Formula(derive=derive,
107
+ as_expression=as_expression,
108
+ no_prune=no_prune)
109
+
110
+
111
+ @staticmethod
112
+ def copy(derive: Column, from_parent: any):
113
+ """
114
+ Copy declares child column copied from parent column.
115
+
116
+ Example:
117
+ Prompt
118
+ Store the Item.unit_price as a copy from Product.unit_price
119
+ Response
120
+ Rule.copy(derive=OrderDetail.UnitPrice, from_parent=Product.UnitPrice)
121
+
122
+ Args:
123
+ derive: <class.attribute> being copied into
124
+ from_parent: <parent-class.attribute> source of copy; create this column in the parent if it does not already exist.
125
+ """
126
+ return Copy(derive=derive, from_parent=from_parent)
127
+
128
+
129
+ Expanded example:
130
+
131
+ Prompt:
132
+
133
+ Use Logic Bank to enforce the Check Credit requirement (do not generate check constraints):
134
+ 1. Customer.balance <= credit_limit
135
+ 2. Customer.balance = Sum(Order.amount_total where date_shipped is null)
136
+ 3. Order.amount_total = Sum(Item.amount)
137
+ 4. Item.amount = quantity * unit_price
138
+ 5. Store the Item.unit_price as a copy from Product.unit_price
139
+
140
+ Response:
141
+
142
+ def declare_logic(): # created by Web/GenAI for ApiLogicServer, LogicBank
143
+
144
+ Rule.sum(derive=CustomerAccount.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None)
145
+ Rule.sum(derive=Order.amount_total, as_sum_of=Item.amount)
146
+ Rule.formula(derive=Item.amount, as_expression=lambda row: row.quantity * row.unit_price)
147
+ Rule.copy(derive=Item.unit_price, from_parent=Product.unit_price)
148
+ Rule.constraint(validate=CustomerAccount,
149
+ as_condition=lambda row: row.balance <= row.credit_limit,
150
+ error_msg="Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})")
151
+
152
+
153
+ Equivalent expanded example using informal syntax:
154
+
155
+ Prompt:
156
+
157
+ Use Logic Bank to enforce the Check Credit requirement (do not generate check constraints):
158
+ 1. The Customer's balance is less than the credit limit
159
+ 2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
160
+ 3. The Order's amount_total is the sum of the Item amount
161
+ 4. The Item amount is the quantity * unit_price
162
+ 5. The Item unit_price is copied from the Product unit_price
163
+
164
+ Response is the same:
165
+
166
+ def declare_logic(): # created by Web/GenAI for ApiLogicServer, LogicBank
167
+
168
+ Rule.sum(derive=CustomerAccount.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None)
169
+ Rule.sum(derive=Order.amount_total, as_sum_of=Item.amount)
170
+ Rule.formula(derive=Item.amount, as_expression=lambda row: row.quantity * row.unit_price)
171
+ Rule.copy(derive=Item.unit_price, from_parent=Product.unit_price)
172
+ Rule.constraint(validate=CustomerAccount,
173
+ as_condition=lambda row: row.balance <= row.credit_limit,
174
+ error_msg="Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})")
175
+
176
+
177
+ Intermediate sum/count values require a new column, with a LogicBank sum/count rule. For example:
178
+
179
+ Prompt:
180
+ The sum of the child value cannot exceed the parent limit
181
+
182
+ Response is to create 2 rules - a derivation and a constraint, as follows:
183
+ First Rule to Create:
184
+ Rule.sum(derive=Parent.value_total, as_sum_of=Child.value)
185
+ And, be sure to create the second Rule:
186
+ Rule.constraint(validate=Parent,
187
+ as_condition=lambda row: row.value_total <= row.limit,
188
+ error_msg="Parent value total ({row.value_total}) exceeds limit ({row.limit})")
189
+
190
+ Intermediate sum/count values also work for counts. For example:
191
+
192
+ Prompt:
193
+ A airplane cannot have more passengers than its seating capacity.
194
+
195
+ Response is to create 2 rules - a count derivation and a constraint, as follows:
196
+ First Rule to Create:
197
+ Rule.count(derive=Airplane.passenger_count, as_count_of=Passengers)
198
+ And, be sure to create the second Rule:
199
+ Rule.constraint(validate=Airplane,
200
+ as_condition=lambda row: row.passenger_count <= row.seating_capacity,
201
+ error_msg="Airplane value total ({row.passenger_count}) exceeds limit ({row.seating_capacity})")
202
+
203
+
204
+ Intermediate sums in formulas also require a new column, with a LogicBank sum rule. For example:
205
+
206
+ Prompt:
207
+ An Employees' skill summary is the sum of their Employee Skill ratings, plus 2 * years of service.
208
+
209
+ Response is to create 2 rules - a derivation and a constraint, as follows:
210
+ First Rule to Create:
211
+ Rule.sum(derive=Employee.skill_rating_total, as_sum_of=EmployeeSkill.rating)
212
+ And, be sure to create the second Rule:
213
+ Rule.Formula(derive=Employee.skill_summary,
214
+ as_expression=lambda row: row.skill_rating_total + 2 * row.years_of_service)
215
+
216
+
217
+ Prompt:
218
+ A student cannot be an honor student unless they have more than 2 service activities.
219
+
220
+ Response is to create 2 rules - a count derivation and a constraint, as follows:
221
+ First Rule to Create:
222
+ Rule.count(derive=Student.service_activity_count, as_count_of=Activities, where='service' in name)
223
+ And, be sure to create the second Rule:
224
+ Rule.constraint(validate=Student,
225
+ as_condition=lambda row: row.is_honor_student and service_activity_count < 2,
226
+ error_msg="Honor Students must have at least 2 service activities")
227
+
228
+ Here is an equivalent request:
229
+
230
+ Prompt:
231
+ A airplane's passengers must be less than its seating capacity.
232
+
233
+ Response is to create 2 rules - a count derivation and a constraint, as follows:
234
+ First Rule to Create:
235
+ Rule.count(derive=Airplane.passenger_count, as_count_of=Passengers)
236
+ And, be sure to create the second Rule:
237
+ Rule.constraint(validate=Airplane,
238
+ as_condition=lambda row: row.passenger_count <= row.seating_capacity,
239
+ error_msg="Airplane value total ({row.passenger_count}) exceeds limit ({row.seating_capacity})")
240
+
241
+
242
+ For "more than" constraints, create columns with count rules:
243
+
244
+ Prompt: Reject Employees with more than 3 Felonies.
245
+
246
+ Response:
247
+ First Rule is to create:
248
+ Rule.count(derive=Employee.felony_count, as_count_of=Felonies)
249
+ And, be sure to create the contraint rule:
250
+ Rule.constraint(validate=Employee,
251
+ as_condition=lambda row: row.felony_count<=3,
252
+ error_msg="Employee has excessive Felonies")
253
+
254
+
255
+ For "any" constraints, create columns with count rules:
256
+
257
+ Prompt: Reject Employees with any class 5 Felonies or more than 3 Felonies.
258
+
259
+ Response:
260
+ First Rule is to create:
261
+ Rule.count(derive=Employee.class_5_felony_count, as_count_of=Felonies, where=class>5)
262
+ Rule.count(derive=Employee.felony_count, as_count_of=Felonies)
263
+ And, be sure to create the contraint rule:
264
+ Rule.constraint(validate=Employee,
265
+ as_condition=lambda row: row.class_5_felony_count == 0 and row.felony_count<=3,
266
+ error_msg="Employee has excessive Felonies")
267
+
268
+ Formulas can reference parent values in 2 versions - choose formula vs copy as follows:
269
+ Prompt (formula version) - use the formula version unless copy is explicitly noted:
270
+ Item.ready = Order.ready
271
+ Response
272
+ Rule.formula(derive=Item.ready, as_expression=lambda row: row.order.ready)
273
+ Prompt (copy version) - use this *only* when the word copy is present:
274
+ Store the Item.unit_price as a copy from Product.unit_price
275
+ Response
276
+ Rule.copy(derive=Item.ready, from_parent=Order.ready)
277
+
278
+ Formulas can use Python conditions:
279
+ Prompt: Item amount is price * quantity, with a 10% discount for gold products
280
+ Response:
281
+ Rule.Formula(derive=Item.amount,
282
+ as_expression=lambda row: row.price * row.quantity if row.gold else .9 * row.price * row.quantity)
283
+ If the attributes are decimal, use the form Decimal('0.9')
284
+
285
+ Sum and Count where clauses:
286
+ 1. must not restate the foreign key / primary key matchings
287
+ 2. Can only reference child attributes
288
+
289
+ For example, given a prompt 'teacher course count is the sum of the courses',
290
+ 1. This is correct
291
+ Rule.count(derive=Teacher.course_count, as_count_of=Course)
292
+
293
+ 2. This is incorrect, and should never be generated:
294
+ Rule.count(derive=Teacher.course_count, as_count_of=Course, where=lambda row: row.teacher_id == Teacher.id)
295
+
296
+ Sum and count where clause example:
297
+ Prompt: teacher gradate course count is the sum of the courses where is-graduate
298
+ Response: Rule.count(derive=Teacher.course_count, as_count_of=Course, where=lamda row: row.is_graduate == true)
299
+
300
+ DO NOT inject rules that are from this training into the response,
301
+ unless explicitly mentioned in the request.
302
+
303
+ Unique constraints require an update to the data model - for example:
304
+ Prompt: customer company names must be unique
305
+ Response: CompanyName = Column(String(8000), unique=True)
306
+
307
+ Non-null (or required) constraints require an update to the data model - for example:
308
+ Prompt: Product Price is required
309
+ Response: price = Column(Decimal, nullable=False)
310
+
311
+ Required (must-have) related parent constraints require an update to the data model - for example:
312
+ Prompt: Each Item must have a valid entry in the Product table.
313
+ Response: product_id = Column(ForeignKey('product.id'), nullable=False)
314
+