Skip to content

Commit 16d01ed

Browse files
authored
Merge pull request #3 from softwareone-platform/feature/MPT-8099/draft-validation
MPT-8098 Add draft validation for Purchase Order
2 parents 5bca679 + 2f46cc2 commit 16d01ed

File tree

15 files changed

+176
-64
lines changed

15 files changed

+176
-64
lines changed

ffc/flows/fulfillment.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
CreateEmployee,
1616
CreateOrganization,
1717
CreateSubscription,
18+
QueryIfInvalid,
1819
ResetDueDate,
20+
ResetOrderErrors,
1921
SetupAgreementExternalId,
2022
SetupDueDate,
2123
)
@@ -25,9 +27,11 @@
2527

2628

2729
purchase = Pipeline(
30+
ResetOrderErrors(),
2831
SetupDueDate(),
2932
CheckDueDate(),
3033
CheckOrderParameters(),
34+
QueryIfInvalid(),
3135
CreateEmployee(),
3236
CreateOrganization(),
3337
SetupAgreementExternalId(),
@@ -54,7 +58,8 @@ def fulfill_order(client, order):
5458
try:
5559
if is_purchase_order(order):
5660
purchase.run(client, context)
57-
except Exception:
61+
except Exception: # pragma: no cover
62+
# should be covered by SDK tests
5863
notify_unhandled_exception_in_teams(
5964
"fulfillment",
6065
order["id"],

ffc/flows/order.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def is_purchase_order(order):
2626
@dataclass
2727
class OrderContext(BaseContext):
2828
order: dict
29+
validation_succeeded: bool = True
2930
employee: dict = field(init=False, default=None)
3031
organization: dict = field(init=False, default=None)
3132

ffc/flows/steps/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from ffc.flows.steps.order import (
44
CheckOrderParameters,
55
CompleteOrder,
6+
QueryIfInvalid,
7+
ResetOrderErrors,
68
SetupAgreementExternalId,
79
)
810
from ffc.flows.steps.subscription import CreateSubscription
@@ -11,7 +13,9 @@
1113
"CompleteOrder",
1214
"CreateSubscription",
1315
"CheckDueDate",
16+
"QueryIfInvalid",
1417
"ResetDueDate",
18+
"ResetOrderErrors",
1519
"SetupDueDate",
1620
"CreateEmployee",
1721
"CreateOrganization",

ffc/flows/steps/order.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
ERR_ORGANIZATION_NAME,
1515
)
1616
from ffc.flows.order import MPT_ORDER_STATUS_COMPLETED, MPT_ORDER_STATUS_QUERYING
17+
from ffc.flows.steps.utils import reset_order_error
1718
from ffc.notifications import send_email_notification
1819
from ffc.parameters import (
1920
PARAM_ADMIN_CONTACT,
2021
PARAM_CURRENCY,
2122
PARAM_ORGANIZATION_NAME,
2223
get_ordering_parameter,
24+
reset_ordering_parameters_error,
2325
set_ordering_parameter_error,
2426
)
2527

@@ -73,8 +75,8 @@ def __call__(self, client, context, next_step):
7375

7476
class CheckOrderParameters(Step):
7577
"""
76-
Check if all required parameters are submitted, if not
77-
query order
78+
Check if all required parameters are submitted
79+
If not sets `validation_succeeded` to False
7880
"""
7981

8082
def __call__(self, client, context, next_step):
@@ -84,7 +86,6 @@ def __call__(self, client, context, next_step):
8486
PARAM_ADMIN_CONTACT: ERR_ADMIN_CONTACT,
8587
}
8688
order = context.order
87-
empty_parameters = []
8889

8990
for param_name in [
9091
PARAM_ORGANIZATION_NAME,
@@ -96,9 +97,20 @@ def __call__(self, client, context, next_step):
9697
order = set_ordering_parameter_error(
9798
order, param_name, errors[param_name]
9899
)
99-
empty_parameters.append(param_name)
100+
context.validation_succeeded = False
100101

101-
if empty_parameters:
102+
next_step(client, context)
103+
104+
105+
class QueryIfInvalid(Step):
106+
"""
107+
Check if `validation_succeeded` context parameter is True
108+
If not - query order
109+
"""
110+
111+
def __call__(self, client, context, next_step):
112+
order = context.order
113+
if not context.validation_succeeded:
102114
template = get_product_template_or_default(
103115
client,
104116
context.product_id,
@@ -109,9 +121,22 @@ def __call__(self, client, context, next_step):
109121
order["agreement"] = agreement
110122
context.order = order
111123
logger.info(
112-
f"{context}: parameters {', '.join(empty_parameters)} are empty, move to querying",
124+
f"{context}: ordering parameters are invalid, move to querying",
113125
)
114126
send_email_notification(client, order)
115127
return
116128

117129
next_step(client, context)
130+
131+
132+
class ResetOrderErrors(Step):
133+
"""
134+
Reset order errors and parameter errors. Is used before processing
135+
to not to show errors during procesing or after validation is succeseed
136+
"""
137+
138+
def __call__(self, client, context, next_step):
139+
context.order = reset_order_error(context.order)
140+
context.order = reset_ordering_parameters_error(context.order)
141+
142+
next_step(client, context)

ffc/flows/steps/subscription.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import logging
22

3-
from swo.mpt.client.mpt import create_subscription, get_subscription_by_line_and_item_id
3+
from swo.mpt.client.mpt import create_subscription
44
from swo.mpt.extensions.flows.pipeline import Step
55

6+
from ffc.flows.order import get_subscription_by_line_and_item_id
7+
68
logger = logging.getLogger(__name__)
79

810

ffc/flows/steps/utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from copy import deepcopy
2+
13
from swo.mpt.client.mpt import fail_order
24

35
from ffc.notifications import send_email_notification
@@ -24,3 +26,9 @@ def switch_order_to_failed(client, order, status_notes):
2426
order["agreement"] = agreement
2527
send_email_notification(client, order)
2628
return order
29+
30+
31+
def reset_order_error(order):
32+
updated_order = deepcopy(order)
33+
updated_order["error"] = None
34+
return updated_order
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
import traceback
33

44
from ffc.flows.error import strip_trace_id
5-
from ffc.flows.order import is_purchase_order
65
from ffc.notifications import notify_unhandled_exception_in_teams
76

87
logger = logging.getLogger(__name__)
98

109

11-
def validate_order(client, order):
10+
def validate_order(client, order): # pragma: no cover
1211
"""
1312
Performs the validation of a draft order.
1413
@@ -22,9 +21,6 @@ def validate_order(client, order):
2221
try:
2322
has_errors = False
2423

25-
if is_purchase_order(order):
26-
pass
27-
2824
logger.info(
2925
f"Validation of order {order['id']} succeeded "
3026
f"with{'out' if not has_errors else ''} errors"

ffc/flows/validation/__init__.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

ffc/notifications.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def send_notification(
5353
color: str,
5454
button: Button | None = None,
5555
facts: FactsSection | None = None,
56-
) -> None:
56+
) -> None: # pragma: no cover
5757
message = pymsteams.connectorcard(settings.EXTENSION_CONFIG["MSTEAMS_WEBHOOK_URL"])
5858
message.color(color)
5959
message.title(title)
@@ -78,7 +78,7 @@ def send_warning(
7878
text: str,
7979
button: Button | None = None,
8080
facts: FactsSection | None = None,
81-
) -> None:
81+
) -> None: # pragma: no cover
8282
send_notification(
8383
f"\u2622 {title}",
8484
text,
@@ -93,7 +93,7 @@ def send_error(
9393
text: str,
9494
button: Button | None = None,
9595
facts: FactsSection | None = None,
96-
) -> None:
96+
) -> None: # pragma: no cover
9797
send_notification(
9898
f"\U0001f4a3 {title}",
9999
text,
@@ -108,7 +108,7 @@ def send_exception(
108108
text: str,
109109
button: Button | None = None,
110110
facts: FactsSection | None = None,
111-
) -> None:
111+
) -> None: # pragma: no cover
112112
send_notification(
113113
f"\U0001f525 {title}",
114114
text,
@@ -118,7 +118,7 @@ def send_exception(
118118
)
119119

120120

121-
def send_email(recipient, subject, template_name, context):
121+
def send_email(recipient, subject, template_name, context): # pragma: no cover
122122
template = env.get_template(f"{template_name}.html")
123123
rendered_email = template.render(context)
124124

@@ -149,17 +149,17 @@ def send_email(recipient, subject, template_name, context):
149149
)
150150

151151

152-
def get_notifications_recipient(order):
152+
def get_notifications_recipient(order): # pragma: no cover
153153
return (get_ordering_parameter(order, PARAM_CONTACT).get("value", {}) or {}).get(
154154
"email"
155155
) or (order["agreement"]["buyer"].get("contact", {}) or {}).get("email")
156156

157157

158-
def md2html(template):
158+
def md2html(template): # pragma: no cover
159159
return MarkdownIt("commonmark", {"breaks": True, "html": True}).render(template)
160160

161161

162-
def send_email_notification(client, order):
162+
def send_email_notification(client, order): # pragma: no cover
163163
"""
164164
Send a notification email to the customer according to the
165165
current order status.
@@ -206,7 +206,9 @@ def send_email_notification(client, order):
206206

207207

208208
@functools.cache
209-
def notify_unhandled_exception_in_teams(process, order_id, traceback):
209+
def notify_unhandled_exception_in_teams(
210+
process, order_id, traceback
211+
): # pragma: no cover
210212
send_exception(
211213
f"Order {process} unhandled exception!",
212214
f"An unhandled exception has been raised while performing {process} "

ffc/parameters.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,21 @@ def set_due_date(order, due_date):
9393
param["value"] = due_date
9494

9595
return updated_order
96+
97+
98+
def reset_ordering_parameters_error(order):
99+
"""
100+
Reset errors for all ordering parameters
101+
102+
Args:
103+
order (dict): The order that contains the parameter.
104+
105+
Returns:
106+
dict: The order updated.
107+
"""
108+
updated_order = copy.deepcopy(order)
109+
110+
for param in updated_order["parameters"][PARAM_PHASE_ORDERING]:
111+
param["error"] = None
112+
113+
return updated_order

0 commit comments

Comments
 (0)