-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrule.py
157 lines (148 loc) · 6.29 KB
/
rule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from util import to_camel_case, fixup
"""
LAC RuleObject from file system JSON object
Raises:
ValueError: JSON Object required
Returns:
_type_: RuleObj
"""
class DotDict(dict):
""" dot.notation access to dictionary attributes """
# thanks: https://stackoverflow.com/questions/2352181/how-to-use-a-dot-to-access-members-of-dictionary/28463329
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
class RuleObj:
def __init__(self, jsonObj: object, jsObj: str = None, sqlObj: str = None):
if not jsonObj:
raise ValueError("RuleObj(jsonObj) JSON Object required")
self.name = jsonObj["name"]
self.entity = jsonObj["entity"]
self.ruleType = jsonObj["ruleType"]
self.jsonObj =jsonObj
self.jsObj = jsObj
self.sqlObj = sqlObj
def __str__(self):
# switch statement for each ruleType
return f"Name: {self.name} Entity: {self.entity} RuleType: {self.ruleType}"
def ruleTypes(self: object):
"""
Args:
RuleObj (object): _description_
"""
j = DotDict(self.jsonObj)
# No need to print inactive rules
if j.isActive == False:
return
name = j.name
entity = ""
if j.entity is not None:
entity = to_camel_case(j.entity)
ruleType = ""
if j.ruleType is not None:
ruleType = j.ruleType
title =""
if j.title is not None:
title = j.title
funName = "fn_" + name.split(".")[0]
comments = j.comments
appliesTo = ""
if j.appliesTo is not None:
appliesTo = j.appliesTo
# Define a function to use in the rule
ruleJSObj = None if self.jsObj is None else fixup(self.jsObj)
tab = "\t\t"
print(f"# RuleType: {ruleType}")
print(f"# Title: {title}")
print(f"# Name: {name}")
print(f"# Entity: {entity}")
print(f"# Comments: {comments}")
print("")
if ruleJSObj is not None:
entityLower = entity.lower()
funName = f"fn_{entityLower}_{ruleType}_{name}"
if len(ruleJSObj) < 80 and ruleType == "formula":
pass
else:
print(f"def {funName}(row: models.{entity}, old_row: models.{entity}, logic_row: LogicRow):")
## print(" if LogicRow.isInserted():")
if len(appliesTo) > 0:
print(f"\t#AppliesTo: {appliesTo}")
print(f" {ruleJSObj}")
match ruleType:
case "sum":
attr = j["attribute"]
roleToChildren = to_camel_case(j.roleToChildren).replace("_","")
childAttr = j.childAttribute
qualification = j.qualification
paren = ")" if qualification is None else ","
print(f"Rule.sum(derive=models.{entity}.{attr}, ")
print(f"{tab}as_sum_of=models.{roleToChildren}.{childAttr}{paren}")
if qualification != None:
qualification = qualification.replace("!=", "is not")
qualification = qualification.replace("==", "is")
qualification = qualification.replace("null", "None")
print(f"{tab}where=lambda row: {qualification})")
case "formula":
attr = j.attribute
print(f"Rule.formula(derive=models.{entity}.{attr},")
if ruleJSObj is not None and len(ruleJSObj) > 80:
print(f"{tab}calling={funName})")
else:
if ruleJSObj is not None:
ruleJSObj = ruleJSObj.replace("return","lambda row: ")
print(f"{tab}as_expression={ruleJSObj})")
case "count":
attr = j.attribute
roleToChildren = to_camel_case(j.roleToChildren).replace("_","")
qualification = j.qualification
if qualification != None:
qualification = qualification.replace("!=", "is not")
qualification = qualification.replace("==", "is")
qualification = qualification.replace("null", "None")
print(f"Rule.count(derive=models.{entity}.{attr},")
print(f"{tab}as_count_of=models.{roleToChildren},")
print(f"{tab}where=Lambda row: {qualification})")
else:
print(f"Rule.count(derive=models.{entity}.{attr},")
print(f"{tab}as_count_of=models.{roleToChildren})")
case "validation":
errorMsg = j.errorMessage
print(f"Rule.constraint(validate=models.{entity},")
print(f"{tab}calling={funName},")
print(f"{tab}error_msg=\"{errorMsg}\")")
case "event":
print(f"Rule.row_event(on_class=models.{entity},")
print(f"{tab}calling={funName})")
case "commitEvent":
print(f"Rule.commit_row_event(on_class=models.{entity},")
print(f"{tab}calling={funName})")
case "parentCopy":
attr = j.attribute
roleToParent = to_camel_case(j.roleToParent).replace("_","")
parentAttr = j.parentAttribute
print(f"Rule.copy(derive=models.{entity}.{attr},")
print(f"{tab}from_parent=models.{roleToParent}.{parentAttr})")
case _:
print(f"#Rule.{ruleType}(...TODO...)")
print("")
if __name__ == "__main__":
jsonObj ={
"name": "CheckCredit",
"entity": "Customers",
"isActive": True,
"ruleType": "validation",
"codeType": "JavaScript",
"errorMessage": "Transaction cannot be completed - Balance ({Balance|#,##0.00}) exceeds Credit Limit ({CreditLimit|#,##0.00})",
"problemAttributes": [
],
"isAutoTitle": True,
"title": "Validation: return row.Balance <= row.CreditLimit;",
"comments": "Observe Error message insertion points {}",
"topics": [
"Check Credit"
]
}
js = "return row.Balance <= row.CreditLimit;"
ruleObj = RuleObj(jsonObj=jsonObj,jsObj=js)
ruleObj.ruleTypes()