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.
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/METADATA +2 -2
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/RECORD +90 -69
- api_logic_server_cli/api_logic_server.py +5 -1
- api_logic_server_cli/api_logic_server_info.yaml +3 -3
- api_logic_server_cli/cli.py +5 -2
- api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/api_logic_server_utils.py +4 -0
- api_logic_server_cli/create_from_model/ont_build.py +53 -19
- api_logic_server_cli/create_from_model/ont_create.py +14 -5
- api_logic_server_cli/fragments/declare_logic.py +72 -0
- api_logic_server_cli/{prototypes/manager/system/genai/create_db_models_inserts/logic_discovery_prefix.py → fragments/declare_logic_begin.py} +2 -1
- api_logic_server_cli/fragments/declare_logic_end.py +52 -0
- api_logic_server_cli/genai/genai.py +25 -8
- api_logic_server_cli/genai/genai_logic_builder.py +14 -11
- api_logic_server_cli/genai/genai_svcs.py +104 -7
- api_logic_server_cli/manager.py +20 -16
- api_logic_server_cli/model_migrator/model_migrator_start.py +1 -1
- api_logic_server_cli/model_migrator/reposreader.py +9 -1
- api_logic_server_cli/model_migrator/rule_obj.py +24 -6
- api_logic_server_cli/prototypes/base/api/api_discovery/ontimize_api.py +4 -1
- api_logic_server_cli/prototypes/base/api/system/expression_parser.py +10 -4
- api_logic_server_cli/prototypes/base/config/activate_logicbank.py +8 -4
- api_logic_server_cli/prototypes/base/database/bind_dbs.py +1 -1
- api_logic_server_cli/prototypes/base/database/test_data/readme.md +5 -5
- api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +32 -8
- api_logic_server_cli/prototypes/base/integration/system/RowDictMapper.py +33 -16
- api_logic_server_cli/prototypes/base/logic/declare_logic.py +9 -3
- api_logic_server_cli/prototypes/base/logic/load_verify_rules.py +217 -0
- api_logic_server_cli/prototypes/base/logic/logic_discovery/auto_discovery.py +22 -13
- api_logic_server_cli/prototypes/genai_demo/api/customize_api.py +9 -11
- api_logic_server_cli/prototypes/genai_demo/database/.DS_Store +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/db.sqlite +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/models.py +52 -42
- api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/OrderB2B.py +4 -6
- api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/__pycache__/OrderB2B.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/row_dict_maps_readme.md +3 -0
- api_logic_server_cli/prototypes/genai_demo/logic/__pycache__/declare_logic.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/__pycache__/load_verify_rules.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/declare_logic.py +58 -62
- api_logic_server_cli/prototypes/genai_demo/logic/load_verify_rules.py +216 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/__init__.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/error_testing.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/auto_discovery.py +52 -0
- api_logic_server_cli/prototypes/genai_demo/logic/readme_declare_logic.md +172 -0
- api_logic_server_cli/prototypes/genai_demo/security/__pycache__/declare_security.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/ui/admin/admin.yaml +86 -53
- api_logic_server_cli/prototypes/manager/.vscode/launch.json +1 -1
- api_logic_server_cli/prototypes/manager/README.md +19 -4
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.prompt +4 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +34 -26
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_informal.prompt +3 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/.DS_Store +0 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/000_you_are.prompt +1 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/001_logic_training.prompt +314 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/002_create_db_models.prompt +150 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/003_create_db_models.response +134 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/004_iteratio_logic.prompt +131 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/005_create_db_models.response-example +141 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/create_db_models.py +105 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/db.dbml +70 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/readme.md +6 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/response.json +178 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/002_create_db_models.prompt +194 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/003_create_db_models.response +298 -0
- api_logic_server_cli/prototypes/{genai_demo/database/chatgpt/sample_ai.sqlite → manager/system/genai/examples/time_tracking_billing/db.sqlite} +0 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/readme.md +61 -0
- api_logic_server_cli/prototypes/manager/system/genai/learning_requests/logic_bank_api.prompt +29 -11
- api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/iteration.prompt +2 -1
- api_logic_server_cli/prototypes/nw_no_cust/venv_setup/system_note.txt +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/home_tree_template.html +9 -0
- api_logic_server_cli/prototypes/ont_app/templates/tree_routing.jinja +32 -0
- api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/codegen.cpython-312.pyc +0 -0
- api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py +4 -2
- api_logic_server_cli/tools/mini_skel/logic/load_verify_rules.py +1 -1
- api_logic_server_cli/model_migrator/system/custom_endpoint.py +0 -545
- api_logic_server_cli/prototypes/base/database/test_data/z_test_data_rows.py +0 -98
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/__pycache__/copilot_models.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/__pycache__/sample_ai_models.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai.chatgpt +0 -16
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai.sql +0 -66
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_items.sqlite +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_models.py +0 -156
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_models.sqlite +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/cocktail-napkin.jpg +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/LICENSE +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/WHEEL +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/entry_points.txt +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/top_level.txt +0 -0
|
@@ -23,21 +23,30 @@ def discover_logic():
|
|
|
23
23
|
spec.loader.exec_module(each_logic_file) # runs "bare" module code (e.g., initialization)
|
|
24
24
|
each_logic_file.declare_logic() # invoke create function
|
|
25
25
|
|
|
26
|
-
if False and Path(__file__).parent.parent.parent.joinpath("docs/project_is_genai_demo.txt").exists():
|
|
27
|
-
|
|
26
|
+
# if False and Path(__file__).parent.parent.parent.joinpath("docs/project_is_genai_demo.txt").exists():
|
|
27
|
+
# return # for genai_demo, logic is in logic/declare_logic.py (so ignore logic_discovery)
|
|
28
28
|
|
|
29
29
|
wg_logic_path = Path(__file__).parent.parent.joinpath("wg_rules")
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
logic.append(
|
|
38
|
-
|
|
39
|
-
spec.loader.exec_module(
|
|
40
|
-
|
|
30
|
+
if wg_logic_path.exists():
|
|
31
|
+
run_local = os.environ.get("WG_PROJECT") is None # eg, running export locally
|
|
32
|
+
# run_local = False # for debug
|
|
33
|
+
if run_local:
|
|
34
|
+
wg_export_logic_path = Path(__file__).parent.parent.parent.joinpath("logic/wg_rules/active_rules_export.py")
|
|
35
|
+
if wg_export_logic_path.is_file():
|
|
36
|
+
spec = importlib.util.spec_from_file_location("module.name", wg_export_logic_path)
|
|
37
|
+
logic.append(str(wg_export_logic_path))
|
|
38
|
+
wg_export_logic_file = importlib.util.module_from_spec(spec)
|
|
39
|
+
spec.loader.exec_module(wg_export_logic_file) # runs "bare" module code (e.g., initialization)
|
|
40
|
+
wg_export_logic_file.declare_logic() # invoke create function
|
|
41
|
+
else:
|
|
42
|
+
for root, dirs, files in os.walk(wg_logic_path):
|
|
43
|
+
for file in files:
|
|
44
|
+
if file.endswith(".py") and 'active_rules_export.py' != file:
|
|
45
|
+
spec = importlib.util.spec_from_file_location("module.name", wg_logic_path.joinpath(file))
|
|
46
|
+
logic.append(file)
|
|
47
|
+
each_logic_file = importlib.util.module_from_spec(spec)
|
|
48
|
+
spec.loader.exec_module(each_logic_file) # runs "bare" module code (e.g., initialization)
|
|
49
|
+
each_logic_file.init_rule() # invoke create function
|
|
41
50
|
|
|
42
51
|
app_logger.info(f"..discovered logic: {logic}")
|
|
43
52
|
return
|
|
@@ -5,8 +5,8 @@ from flask import request, jsonify
|
|
|
5
5
|
from safrs import jsonapi_rpc
|
|
6
6
|
from database import models
|
|
7
7
|
import integration.system.RowDictMapper as row_dict_mapper
|
|
8
|
-
from integration.row_dict_maps.OrderShipping import OrderShipping
|
|
9
|
-
from integration.row_dict_maps.OrderB2B import OrderB2B
|
|
8
|
+
# from integration.row_dict_maps.OrderShipping import OrderShipping
|
|
9
|
+
from integration.row_dict_maps.OrderB2B import OrderB2B # TODO - how to drive; B2B...
|
|
10
10
|
|
|
11
11
|
# called by api_logic_server_run.py, to customize api (new end points, services).
|
|
12
12
|
# separate from expose_api_models.py, to simplify merge if project recreated
|
|
@@ -140,15 +140,13 @@ class ServicesEndPoint(safrs.JABase):
|
|
|
140
140
|
""" # yaml creates Swagger description
|
|
141
141
|
args :
|
|
142
142
|
order:
|
|
143
|
-
Account: "
|
|
143
|
+
Account: "Alice"
|
|
144
144
|
Notes: "Please Rush"
|
|
145
145
|
Items :
|
|
146
|
-
- ProductName: "
|
|
146
|
+
- ProductName: "Product 1"
|
|
147
147
|
QuantityOrdered: 1
|
|
148
|
-
- ProductName: "
|
|
148
|
+
- ProductName: "Product 2"
|
|
149
149
|
QuantityOrdered: 2
|
|
150
|
-
- ProductName: "Green Apples"
|
|
151
|
-
QuantityOrdered: 3
|
|
152
150
|
---
|
|
153
151
|
|
|
154
152
|
Note attribute alias, Lookup automation in OrderB2B
|
|
@@ -159,19 +157,19 @@ class ServicesEndPoint(safrs.JABase):
|
|
|
159
157
|
$(venv) ApiLogicServer login --user=admin --password=p
|
|
160
158
|
$(venv) ApiLogicServer curl "'POST' 'http://localhost:5656/api/ServicesEndPoint/OrderB2B'" --data '
|
|
161
159
|
{"meta": {"args": {"order": {
|
|
162
|
-
"Account": "
|
|
160
|
+
"Account": "Alice",
|
|
163
161
|
"Notes": "Please Rush",
|
|
164
162
|
"Items": [
|
|
165
163
|
{
|
|
166
|
-
"ProductName": "
|
|
164
|
+
"ProductName": "Product 1",
|
|
167
165
|
"QuantityOrdered": 1
|
|
168
166
|
},
|
|
169
167
|
{
|
|
170
|
-
"ProductName": "
|
|
168
|
+
"ProductName": "Product 2",
|
|
171
169
|
"QuantityOrdered": 2
|
|
172
170
|
},
|
|
173
171
|
{
|
|
174
|
-
"ProductName": "
|
|
172
|
+
"ProductName": "Green Apples",
|
|
175
173
|
"QuantityOrdered": 2
|
|
176
174
|
}
|
|
177
175
|
]
|
|
Binary file
|
|
Binary file
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
-
from sqlalchemy import
|
|
2
|
+
from sqlalchemy import DECIMAL, DateTime # API Logic Server GenAI assist
|
|
3
|
+
from sqlalchemy import Column, Date, ForeignKey, Integer, Numeric, String, Boolean
|
|
3
4
|
from sqlalchemy.orm import relationship
|
|
4
5
|
from sqlalchemy.ext.declarative import declarative_base
|
|
5
6
|
|
|
@@ -9,13 +10,13 @@ from sqlalchemy.ext.declarative import declarative_base
|
|
|
9
10
|
# Alter this file per your database maintenance policy
|
|
10
11
|
# See https://apilogicserver.github.io/Docs/Project-Rebuild/#rebuilding
|
|
11
12
|
#
|
|
12
|
-
# Created:
|
|
13
|
-
# Database: sqlite:////Users/val/dev/ApiLogicServer/ApiLogicServer-dev/
|
|
13
|
+
# Created: January 31, 2025 17:52:29
|
|
14
|
+
# Database: sqlite:////Users/val/dev/ApiLogicServer/ApiLogicServer-dev/build_and_test/ApiLogicServer/genai_demo/database/db.sqlite
|
|
14
15
|
# Dialect: sqlite
|
|
15
16
|
#
|
|
16
17
|
# mypy: ignore-errors
|
|
17
18
|
########################################################################################################################
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
from database.system.SAFRSBaseX import SAFRSBaseX, TestBase
|
|
20
21
|
from flask_login import UserMixin
|
|
21
22
|
import safrs, flask_sqlalchemy, os
|
|
@@ -42,72 +43,81 @@ else:
|
|
|
42
43
|
print('*** Models.py Using TestBase ***')
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
|
|
47
|
+
class Customer(Base): # type: ignore
|
|
48
|
+
"""
|
|
49
|
+
description: Customer table with unique name, balance and credit_limit.
|
|
50
|
+
"""
|
|
51
|
+
__tablename__ = 'customer'
|
|
47
52
|
_s_collection_name = 'Customer' # type: ignore
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Balance : DECIMAL = Column(DECIMAL(10, 2))
|
|
54
|
-
CreditLimit : DECIMAL = Column(DECIMAL(10, 2), nullable=False)
|
|
54
|
+
id = Column(Integer, primary_key=True)
|
|
55
|
+
name = Column(String(255), unique=True)
|
|
56
|
+
balance = Column(Numeric)
|
|
57
|
+
credit_limit = Column(Numeric)
|
|
55
58
|
|
|
56
59
|
# parent relationships (access parent)
|
|
57
60
|
|
|
58
61
|
# child relationships (access children)
|
|
59
|
-
OrderList : Mapped[List["Order"]] = relationship(back_populates="
|
|
62
|
+
OrderList : Mapped[List["Order"]] = relationship(back_populates="customer")
|
|
60
63
|
|
|
61
64
|
|
|
62
|
-
class Product(Base):
|
|
63
|
-
__tablename__ = 'Products'
|
|
64
|
-
_s_collection_name = 'Product' # type: ignore
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
class Product(Base): # type: ignore
|
|
67
|
+
"""
|
|
68
|
+
description: Product table with unit_price used for copying to Item.
|
|
69
|
+
"""
|
|
70
|
+
__tablename__ = 'product'
|
|
71
|
+
_s_collection_name = 'Product' # type: ignore
|
|
70
72
|
|
|
73
|
+
id = Column(Integer, primary_key=True)
|
|
74
|
+
name = Column(String(255))
|
|
75
|
+
unit_price = Column(Numeric)
|
|
76
|
+
carbon_neutral = Column(Boolean)
|
|
71
77
|
# parent relationships (access parent)
|
|
72
78
|
|
|
73
79
|
# child relationships (access children)
|
|
74
|
-
ItemList : Mapped[List["Item"]] = relationship(back_populates="
|
|
80
|
+
ItemList : Mapped[List["Item"]] = relationship(back_populates="product")
|
|
75
81
|
|
|
76
82
|
|
|
77
83
|
|
|
78
|
-
class Order(Base):
|
|
79
|
-
|
|
84
|
+
class Order(Base): # type: ignore
|
|
85
|
+
"""
|
|
86
|
+
description: Order table with a foreign key to Customer, a notes field, date_shipped and derived amount_total.
|
|
87
|
+
"""
|
|
88
|
+
__tablename__ = 'order'
|
|
80
89
|
_s_collection_name = 'Order' # type: ignore
|
|
81
90
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
AmountTotal : DECIMAL = Column(DECIMAL(10, 2))
|
|
91
|
+
id = Column(Integer, primary_key=True)
|
|
92
|
+
customer_id = Column(ForeignKey('customer.id'))
|
|
93
|
+
date_shipped = Column(Date)
|
|
94
|
+
notes = Column(String(255))
|
|
95
|
+
amount_total = Column(Numeric)
|
|
88
96
|
|
|
89
97
|
# parent relationships (access parent)
|
|
90
|
-
|
|
98
|
+
customer : Mapped["Customer"] = relationship(back_populates=("OrderList"))
|
|
91
99
|
|
|
92
100
|
# child relationships (access children)
|
|
93
|
-
ItemList : Mapped[List["Item"]] = relationship(back_populates="
|
|
101
|
+
ItemList : Mapped[List["Item"]] = relationship(back_populates="order")
|
|
94
102
|
|
|
95
103
|
|
|
96
104
|
|
|
97
|
-
class Item(Base):
|
|
98
|
-
|
|
105
|
+
class Item(Base): # type: ignore
|
|
106
|
+
"""
|
|
107
|
+
description: Item table with non-null quantity, derived amount and unit_price copied from Product.
|
|
108
|
+
"""
|
|
109
|
+
__tablename__ = 'item'
|
|
99
110
|
_s_collection_name = 'Item' # type: ignore
|
|
100
111
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
112
|
+
id = Column(Integer, primary_key=True)
|
|
113
|
+
order_id = Column(ForeignKey('order.id'))
|
|
114
|
+
product_id = Column(ForeignKey('product.id'))
|
|
115
|
+
quantity = Column(Integer, nullable=False)
|
|
116
|
+
unit_price = Column(Numeric)
|
|
117
|
+
amount = Column(Numeric)
|
|
107
118
|
|
|
108
119
|
# parent relationships (access parent)
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
order : Mapped["Order"] = relationship(back_populates=("ItemList"))
|
|
121
|
+
product : Mapped["Product"] = relationship(back_populates=("ItemList"))
|
|
111
122
|
|
|
112
123
|
# child relationships (access children)
|
|
113
|
-
|
|
@@ -19,15 +19,13 @@ class OrderB2B(RowDictMapper):
|
|
|
19
19
|
order = super(OrderB2B, self).__init__(
|
|
20
20
|
model_class=models.Order
|
|
21
21
|
, alias = "order"
|
|
22
|
-
, fields = [(models.Order.Notes)]
|
|
23
|
-
, parent_lookups = [( models.Customer,
|
|
24
|
-
[(models.Customer.CustomerName, 'Account')]
|
|
25
|
-
)]
|
|
22
|
+
, fields = [(models.Order.notes, "Notes")]
|
|
23
|
+
, parent_lookups = [( models.Customer, [(models.Customer.name, 'Account')] )]
|
|
26
24
|
, related = [
|
|
27
25
|
(RowDictMapper(model_class=models.Item
|
|
28
26
|
, alias="Items"
|
|
29
|
-
, fields = [(models.Item.
|
|
30
|
-
, parent_lookups = [( models.Product, [models.Product.ProductName] )]
|
|
27
|
+
, fields = [(models.Item.quantity, "QuantityOrdered")]
|
|
28
|
+
, parent_lookups = [( models.Product, [(models.Product.name, 'ProductName')] )]
|
|
31
29
|
)
|
|
32
30
|
)
|
|
33
31
|
]
|
|
Binary file
|
|
Binary file
|
api_logic_server_cli/prototypes/genai_demo/logic/__pycache__/load_verify_rules.cpython-312.pyc
ADDED
|
Binary file
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import datetime
|
|
1
|
+
import datetime, os
|
|
2
2
|
from decimal import Decimal
|
|
3
3
|
from logic_bank.exec_row_logic.logic_row import LogicRow
|
|
4
4
|
from logic_bank.extensions.rule_extensions import RuleExtension
|
|
5
5
|
from logic_bank.logic_bank import Rule
|
|
6
|
-
from
|
|
7
|
-
|
|
6
|
+
from logic_bank.logic_bank import DeclareRule
|
|
7
|
+
import database.models as models
|
|
8
8
|
import api.system.opt_locking.opt_locking as opt_locking
|
|
9
|
-
from security.system.authorization import Grant
|
|
10
|
-
import
|
|
11
|
-
from integration.row_dict_maps.OrderShipping import OrderShipping
|
|
12
|
-
from confluent_kafka import Producer, KafkaException
|
|
9
|
+
from security.system.authorization import Grant, Security
|
|
10
|
+
from logic.load_verify_rules import load_verify_rules
|
|
13
11
|
import integration.kafka.kafka_producer as kafka_producer
|
|
12
|
+
import logging
|
|
14
13
|
|
|
15
14
|
app_logger = logging.getLogger(__name__)
|
|
16
15
|
|
|
@@ -22,94 +21,91 @@ def declare_logic():
|
|
|
22
21
|
Brief background: see readme_declare_logic.md
|
|
23
22
|
|
|
24
23
|
Your Code Goes Here - Use code completion (Rule.) to declare rules
|
|
25
|
-
|
|
26
|
-
GenAI: Paste the following into Copilot Chat, and paste the result below.
|
|
27
|
-
|
|
28
|
-
Use Logic Bank to enforce these requirements:
|
|
29
|
-
|
|
30
|
-
Enforce the Check Credit requirement (do not generate check constraints):
|
|
31
|
-
1. Customer.Balance <= CreditLimit
|
|
32
|
-
2. Customer.Balance = Sum(Order.AmountTotal where date shipped is null)
|
|
33
|
-
3. Order.AmountTotal = Sum(Items.Amount)
|
|
34
|
-
4. Items.Amount = Quantity * UnitPrice
|
|
35
|
-
5. Store the Items.UnitPrice as a copy from Product.UnitPrice
|
|
36
24
|
'''
|
|
37
25
|
|
|
38
|
-
|
|
26
|
+
if os.environ.get("WG_PROJECT"):
|
|
27
|
+
# Inside WG: Load rules from docs/expprt/export.json
|
|
28
|
+
load_verify_rules()
|
|
29
|
+
else:
|
|
30
|
+
# Outside WG: load declare_logic function
|
|
31
|
+
from logic.logic_discovery.auto_discovery import discover_logic
|
|
32
|
+
discover_logic()
|
|
39
33
|
|
|
40
|
-
from
|
|
41
|
-
|
|
34
|
+
# Logic from GenAI: (or, use your IDE w/ code completion)
|
|
35
|
+
from database.models import Product, Customer, Item, Order
|
|
42
36
|
|
|
43
|
-
#
|
|
44
|
-
Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal, where=lambda row: row.ShipDate is None)
|
|
45
|
-
Rule.sum(derive=Order.AmountTotal, as_sum_of=Item.Amount)
|
|
46
|
-
# Rule.formula(derive=Item.amount, as_expression=lambda row: row.quantity * row.unit_price)
|
|
47
|
-
Rule.copy(derive=Item.UnitPrice, from_parent=Product.UnitPrice)
|
|
37
|
+
# Ensure that Customer balance does not exceed credit_limit.
|
|
48
38
|
Rule.constraint(validate=Customer,
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
as_condition=lambda row: row.balance <= row.credit_limit,
|
|
40
|
+
error_msg="Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})")
|
|
51
41
|
|
|
52
|
-
#
|
|
42
|
+
# Customer.balance is the sum of Order.amount_total for orders not yet shipped.
|
|
43
|
+
Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None)
|
|
44
|
+
|
|
45
|
+
# Order.amount_total is the sum of Item.amount.
|
|
46
|
+
Rule.sum(derive=Order.amount_total, as_sum_of=Item.amount)
|
|
53
47
|
|
|
54
|
-
def derive_amount(row: Item, old_row: Item, logic_row: LogicRow):
|
|
48
|
+
def derive_amount(row: models.Item, old_row: models.Item, logic_row: LogicRow):
|
|
55
49
|
amount = row.Quantity * row.UnitPrice
|
|
56
50
|
if row.Product.CarbonNeutral == True and row.Quantity >= 10:
|
|
57
51
|
amount = amount * Decimal(0.9) # breakpoint here
|
|
58
52
|
return amount
|
|
59
53
|
|
|
60
|
-
#
|
|
61
|
-
Rule.formula(derive=Item.Amount,
|
|
54
|
+
# Items.Amount = Quantity * UnitPrice with discount for CarbonNeutral products.
|
|
55
|
+
Rule.formula(derive=models.Item.Amount,
|
|
56
|
+
calling=derive_amount)
|
|
62
57
|
|
|
63
|
-
#
|
|
58
|
+
# Item.unit_price is copied from Product.unit_price.
|
|
59
|
+
Rule.copy(derive=Item.unit_price, from_parent=Product.unit_price)
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
NB: the after_flush event makes Order.Id avaible. Contrast to congratulate_sales_rep().
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
row (Order): inserted Order
|
|
74
|
-
old_row (Order): n/a
|
|
75
|
-
logic_row (LogicRow): bundles curr/old row, with ins/upd/dlt logic
|
|
76
|
-
"""
|
|
77
|
-
if logic_row.is_inserted():
|
|
78
|
-
kafka_producer.send_kafka_message(logic_row=logic_row,
|
|
79
|
-
row_dict_mapper=OrderShipping,
|
|
80
|
-
kafka_topic="order_shipping",
|
|
81
|
-
kafka_key=str(row.OrderID),
|
|
82
|
-
msg="Sending Order to Shipping")
|
|
83
|
-
|
|
84
|
-
Rule.after_flush_row_event(on_class=Order, calling=send_order_to_shipping) # see above
|
|
61
|
+
# Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
|
|
62
|
+
Rule.after_flush_row_event(on_class=Order, calling=kafka_producer.send_row_to_kafka,
|
|
63
|
+
if_condition=lambda row: row.date_shipped is not None,
|
|
64
|
+
with_args={'topic': 'order_shipping'})
|
|
85
65
|
|
|
66
|
+
# End Logic from GenAI
|
|
86
67
|
|
|
87
68
|
|
|
88
|
-
def handle_all(logic_row: LogicRow): #
|
|
69
|
+
def handle_all(logic_row: LogicRow): # #als: TIME / DATE STAMPING, OPTIMISTIC LOCKING
|
|
89
70
|
"""
|
|
90
71
|
This is generic - executed for all classes.
|
|
91
72
|
|
|
92
|
-
Invokes optimistic locking.
|
|
73
|
+
Invokes optimistic locking, and checks Grant permissions.
|
|
93
74
|
|
|
94
|
-
|
|
75
|
+
Also provides user/date stamping.
|
|
95
76
|
|
|
96
77
|
Args:
|
|
97
78
|
logic_row (LogicRow): from LogicBank - old/new row, state
|
|
98
79
|
"""
|
|
99
80
|
|
|
100
|
-
if
|
|
81
|
+
if os.getenv("APILOGICPROJECT_NO_FLASK") is not None:
|
|
82
|
+
print("\ndeclare_logic.py Using TestBase\n")
|
|
101
83
|
return # enables rules to be used outside of Flask, e.g., test data loading
|
|
102
84
|
|
|
103
85
|
if logic_row.is_updated() and logic_row.old_row is not None and logic_row.nest_level == 0:
|
|
104
86
|
opt_locking.opt_lock_patch(logic_row=logic_row)
|
|
105
|
-
|
|
106
|
-
|
|
87
|
+
|
|
88
|
+
Grant.process_updates(logic_row=logic_row)
|
|
89
|
+
|
|
90
|
+
did_stamping = False
|
|
91
|
+
if enable_stamping := False: # #als: DATE / USER STAMPING
|
|
107
92
|
row = logic_row.row
|
|
108
93
|
if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedOn"):
|
|
109
94
|
row.CreatedOn = datetime.datetime.now()
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
95
|
+
did_stamping = True
|
|
96
|
+
if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedBy"):
|
|
97
|
+
row.CreatedBy = Security.current_user().id
|
|
98
|
+
# if Config.SECURITY_ENABLED == True else 'public'
|
|
99
|
+
did_stamping = True
|
|
100
|
+
if logic_row.ins_upd_dlt == "upd" and hasattr(row, "UpdatedOn"):
|
|
101
|
+
row.UpdatedOn = datetime.datetime.now()
|
|
102
|
+
did_stamping = True
|
|
103
|
+
if logic_row.ins_upd_dlt == "upd" and hasattr(row, "UpdatedBy"):
|
|
104
|
+
row.UpdatedBy = Security.current_user().id \
|
|
105
|
+
if Config.SECURITY_ENABLED == True else 'public'
|
|
106
|
+
did_stamping = True
|
|
107
|
+
if did_stamping:
|
|
108
|
+
logic_row.log("early_row_event_all_classes - handle_all did stamping")
|
|
113
109
|
Rule.early_row_event_all_classes(early_row_event_all_classes=handle_all)
|
|
114
110
|
|
|
115
111
|
#als rules report
|