Skip to content

Commit 9449d4f

Browse files
authored
14853 - Restore Create Task When New Product Add by GOVM/GOVN (#3630)
1 parent bce761a commit 9449d4f

File tree

23 files changed

+564
-106
lines changed

23 files changed

+564
-106
lines changed

auth-api/src/auth_api/exceptions/errors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class Error(Enum):
125125
)
126126
BCEID_USERS_CANT_BE_OWNERS = "BCEID Users cant be owners", HTTPStatus.BAD_REQUEST
127127
PAYMENT_ACCOUNT_UPSERT_FAILED = "Account upsert failed in Pay", HTTPStatus.INTERNAL_SERVER_ERROR
128+
ACCOUNT_FEES_FETCH_FAILED = "Failed to fetch account fees from Pay API", HTTPStatus.INTERNAL_SERVER_ERROR
128129
GOVM_ACCOUNT_DATA_MISSING = (
129130
"GOVM account creation needs payment info , gl code and mailing address",
130131
HTTPStatus.BAD_REQUEST,

auth-api/src/auth_api/models/dataclass.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ class TaskSearch: # pylint: disable=too-many-instance-attributes
183183
submitted_sort_order: str = "asc"
184184
page: int = 1
185185
limit: int = 10
186+
action: str = ""
186187

187188

188189
@dataclass
@@ -201,6 +202,7 @@ class ProductReviewTask:
201202

202203
org_id: str
203204
org_name: str
205+
org_access_type: str
204206
product_code: str
205207
product_description: str
206208
product_subscription_id: int

auth-api/src/auth_api/models/task.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ def fetch_tasks(cls, task_search: TaskSearch):
6666
query = query.filter(Task.type == task_search.type)
6767
if task_search.status:
6868
query = query.filter(Task.status.in_(task_search.status))
69+
if task_search.action:
70+
query = query.filter(Task.action.in_(task_search.action))
6971
start_date = None
7072
end_date = None
7173
if task_search.start_date:

auth-api/src/auth_api/resources/v1/task.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def get_tasks():
4646
relationship_status=request.args.get("relationshipStatus", None),
4747
type=request.args.get("type", None),
4848
status=request.args.getlist("status", None),
49+
action=request.args.getlist("action", None),
4950
modified_by=request.args.get("modifiedBy", None),
5051
submitted_sort_order=request.args.get("submittedSortOrder", None),
5152
page=int(request.args.get("page", 1)),

auth-api/src/auth_api/services/org.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,16 @@ def create_org(org_info: dict, user_id):
141141
# create the membership record for this user if its not created by staff and access_type is anonymous
142142
Org.create_membership(org, user_id)
143143

144+
# Send an email to staff to remind review the pending account
145+
is_staff_review_needed = access_type == AccessType.GOVN.value or (
146+
access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value)
147+
and not AffidavitModel.find_approved_by_user_id(user_id=user_id)
148+
and current_app.config.get("SKIP_STAFF_APPROVAL_BCEID") is False
149+
)
150+
144151
if product_subscriptions is not None:
145152
ProductService.create_product_subscription(
146-
org.id, subscription_data={"subscriptions": product_subscriptions}, skip_auth=True
153+
org.id, subscription_data={"subscriptions": product_subscriptions}, skip_auth=True, staff_review_for_create_org=is_staff_review_needed
147154
)
148155

149156
ProductService.create_subscription_from_bcol_profile(org.id, bcol_profile_flags)
@@ -153,13 +160,6 @@ def create_org(org_info: dict, user_id):
153160
if payment_account_status == PaymentAccountStatus.FAILED and error is not None:
154161
current_app.logger.warning(f"Account update payment Error: {error}")
155162

156-
# Send an email to staff to remind review the pending account
157-
is_staff_review_needed = access_type == AccessType.GOVN.value or (
158-
access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value)
159-
and not AffidavitModel.find_approved_by_user_id(user_id=user_id)
160-
and current_app.config.get("SKIP_STAFF_APPROVAL_BCEID") is False
161-
)
162-
163163
if is_staff_review_needed:
164164
Org._create_staff_review_task(org, UserModel.find_by_jwt_token())
165165

auth-api/src/auth_api/services/products.py

Lines changed: 71 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
get_product_notification_data,
5757
get_product_notification_type,
5858
)
59-
from auth_api.utils.roles import CLIENT_ADMIN_ROLES, CLIENT_AUTH_ROLES, STAFF
59+
from auth_api.utils.roles import CLIENT_ADMIN_ROLES, CLIENT_AUTH_ROLES, GOV_ORG_TYPES, STAFF
6060
from auth_api.utils.user_context import UserContext, user_context
6161

6262
from .activity_log_publisher import ActivityLogPublisher
@@ -156,6 +156,41 @@ def resubmit_product_subscription(org_id, subscription_data: dict[str, Any], ski
156156

157157
return Product.get_all_product_subscription(org_id=org_id, skip_auth=True)
158158

159+
@staticmethod
160+
def _check_gov_org_add_product_previously_approved(
161+
org_id: int,
162+
product_code: str
163+
) -> tuple[bool, Any]:
164+
"""Check if GOV org's account fee product was previously approved (NEW_PRODUCT_FEE_REVIEW task)."""
165+
inactive_sub = ProductSubscriptionModel.find_by_org_id_product_code(
166+
org_id=org_id, product_code=product_code, valid_statuses=(ProductSubscriptionStatus.INACTIVE.value,)
167+
)
168+
if not inactive_sub:
169+
return False, None
170+
task_add_product = TaskModel.find_by_task_relationship_id(
171+
inactive_sub.id, TaskRelationshipType.PRODUCT.value, TaskStatus.COMPLETED.value
172+
)
173+
task_create_org = TaskModel.find_by_task_relationship_id(
174+
org_id, TaskRelationshipType.ORG.value, TaskStatus.COMPLETED.value
175+
)
176+
product_invalid = (
177+
task_add_product is None or (
178+
task_add_product.action in (TaskAction.NEW_PRODUCT_FEE_REVIEW.value, TaskAction.PRODUCT_REVIEW.value)
179+
and task_add_product.relationship_status != TaskRelationshipStatus.ACTIVE.value
180+
)
181+
)
182+
if product_invalid:
183+
org_invalid = (
184+
task_create_org is None or (
185+
task_create_org.action in (TaskAction.AFFIDAVIT_REVIEW.value, TaskAction.ACCOUNT_REVIEW.value)
186+
and task_create_org.relationship_status != TaskRelationshipStatus.ACTIVE.value
187+
)
188+
)
189+
190+
if org_invalid:
191+
return False, None
192+
return True, inactive_sub
193+
159194
@staticmethod
160195
def _is_previously_approved(org_id: int, product_code: str):
161196
"""Check if this product has a task that was previously approved."""
@@ -170,7 +205,7 @@ def _is_previously_approved(org_id: int, product_code: str):
170205
)
171206
if task is None or (
172207
task.relationship_status != TaskRelationshipStatus.ACTIVE.value
173-
and task.action == TaskAction.PRODUCT_REVIEW.value
208+
and task.action in (TaskAction.PRODUCT_REVIEW.value, TaskAction.NEW_PRODUCT_FEE_REVIEW.value)
174209
):
175210
return False, None
176211

@@ -183,6 +218,7 @@ def create_product_subscription(
183218
is_new_transaction: bool = True,
184219
skip_auth=False,
185220
auto_approve=False,
221+
staff_review_for_create_org=False,
186222
):
187223
"""Create product subscription for the user.
188224
@@ -198,6 +234,7 @@ def create_product_subscription(
198234

199235
subscriptions_list = subscription_data.get("subscriptions")
200236
for subscription in subscriptions_list:
237+
auto_approve_current = auto_approve
201238
product_code = subscription.get("productCode")
202239
if ProductSubscriptionModel.find_by_org_id_product_code(org_id, product_code):
203240
raise BusinessException(Error.PRODUCT_SUBSCRIPTION_EXISTS, None)
@@ -206,11 +243,20 @@ def create_product_subscription(
206243
# Check if product requires system admin, if yes abort
207244
if product_model.need_system_admin:
208245
check_auth(system_required=True, org_id=org_id)
209-
previously_approved, inactive_sub = Product._is_previously_approved(org_id, product_code)
246+
247+
if org.access_type in GOV_ORG_TYPES and not staff_review_for_create_org:
248+
previously_approved, inactive_sub = Product._check_gov_org_add_product_previously_approved(
249+
org.id, product_code
250+
)
251+
else:
252+
previously_approved, inactive_sub = Product._is_previously_approved(org_id, product_code)
253+
210254
if previously_approved:
211-
auto_approve = True
255+
auto_approve_current = True
212256

213-
subscription_status = Product.find_subscription_status(org, product_model, auto_approve)
257+
subscription_status = Product.find_subscription_status(
258+
org, product_model, auto_approve_current, staff_review_for_create_org
259+
)
214260
product_subscription = Product._subscribe_and_publish_activity(
215261
SubscriptionRequest(
216262
org_id=org_id,
@@ -245,6 +291,7 @@ def create_product_subscription(
245291
ProductReviewTask(
246292
org_id=org.id,
247293
org_name=org.name,
294+
org_access_type=org.access_type,
248295
product_code=product_subscription.product_code,
249296
product_description=product_model.description,
250297
product_subscription_id=product_subscription.id,
@@ -374,11 +421,14 @@ def _reset_subscription_and_review_task(
374421
@staticmethod
375422
def _create_review_task(review_task: ProductReviewTask):
376423
task_type = review_task.product_description
377-
action_type = (
378-
TaskAction.QUALIFIED_SUPPLIER_REVIEW.value
379-
if review_task.product_code in QUALIFIED_SUPPLIER_PRODUCT_CODES
380-
else TaskAction.PRODUCT_REVIEW.value
381-
)
424+
425+
required_review_types = {AccessType.GOVM.value, AccessType.GOVN.value}
426+
if review_task.product_code in QUALIFIED_SUPPLIER_PRODUCT_CODES:
427+
action_type = TaskAction.QUALIFIED_SUPPLIER_REVIEW.value
428+
elif review_task.org_access_type in required_review_types:
429+
action_type = TaskAction.NEW_PRODUCT_FEE_REVIEW.value
430+
else:
431+
action_type = TaskAction.PRODUCT_REVIEW.value
382432

383433
task_info = {
384434
"name": review_task.org_name,
@@ -396,14 +446,13 @@ def _create_review_task(review_task: ProductReviewTask):
396446
TaskService.create_task(task_info, False)
397447

398448
@staticmethod
399-
def find_subscription_status(org, product_model, auto_approve=False):
449+
def find_subscription_status(org, product_model, auto_approve=False, staff_review_for_create_org=False):
400450
"""Return the subscriptions status based on org type."""
401-
# GOVM accounts has default active subscriptions
402-
skip_review_types = [AccessType.GOVM.value]
403-
if product_model.need_review and auto_approve is False:
451+
skip_review = org.access_type in GOV_ORG_TYPES and staff_review_for_create_org # prevent create second task when it's already added a staff review when creating org
452+
if (product_model.need_review or org.access_type in GOV_ORG_TYPES) and not auto_approve:
404453
return (
405454
ProductSubscriptionStatus.ACTIVE.value
406-
if (org.access_type in skip_review_types)
455+
if skip_review
407456
else ProductSubscriptionStatus.PENDING_STAFF_REVIEW.value
408457
)
409458
return ProductSubscriptionStatus.ACTIVE.value
@@ -455,7 +504,10 @@ def get_all_product_subscription(org_id, skip_auth=False, **kwargs):
455504
check_auth(one_of_roles=(*CLIENT_AUTH_ROLES, STAFF), org_id=org_id)
456505

457506
product_subscriptions: list[ProductSubscriptionModel] = ProductSubscriptionModel.find_by_org_ids([org_id])
458-
subscriptions_dict = {x.product_code: x.status_code for x in product_subscriptions}
507+
subscription_by_code = {
508+
sub.product_code: sub
509+
for sub in product_subscriptions
510+
}
459511

460512
# Include hidden products only for staff and SBC staff
461513
include_hidden = (
@@ -467,9 +519,9 @@ def get_all_product_subscription(org_id, skip_auth=False, **kwargs):
467519

468520
products = Product.get_products(include_hidden=include_hidden, staff_check=False)
469521
for product in products:
470-
product["subscriptionStatus"] = subscriptions_dict.get(
471-
product.get("code"), ProductSubscriptionStatus.NOT_SUBSCRIBED.value
472-
)
522+
sub = subscription_by_code.get(product.get("code"))
523+
product["subscriptionStatus"] = getattr(sub, "status_code", ProductSubscriptionStatus.NOT_SUBSCRIBED.value)
524+
product["id"] = getattr(sub, "id", None)
473525

474526
return products
475527

@@ -483,7 +535,6 @@ def update_product_subscription(product_sub_info: ProductSubscriptionInfo, is_ne
483535
is_hold = product_sub_info.is_hold
484536
org_id = product_sub_info.org_id
485537
org_name = product_sub_info.org_name
486-
487538
# Approve/Reject Product subscription
488539
product_subscription: ProductSubscriptionModel = ProductSubscriptionModel.find_by_id(product_subscription_id)
489540

@@ -504,7 +555,6 @@ def update_product_subscription(product_sub_info: ProductSubscriptionInfo, is_ne
504555
product_model: ProductCodeModel = ProductCodeModel.find_by_code(product_subscription.product_code)
505556
# Find admin email addresses
506557
admin_emails = UserService.get_admin_emails_for_org(org_id)
507-
508558
if admin_emails != "" and not is_hold:
509559
Product.send_product_subscription_notification(
510560
ProductNotificationInfo(

auth-api/src/auth_api/utils/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ class TaskAction(Enum):
323323
ACCOUNT_REVIEW = "ACCOUNT_REVIEW"
324324
PRODUCT_REVIEW = "PRODUCT_REVIEW"
325325
QUALIFIED_SUPPLIER_REVIEW = "QUALIFIED_SUPPLIER_REVIEW"
326+
NEW_PRODUCT_FEE_REVIEW = "NEW_PRODUCT_FEE_REVIEW"
326327

327328

328329
class ActivityAction(Enum):

auth-api/src/auth_api/utils/roles.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from enum import Enum
1717

18-
from .enums import OrgStatus, OrgType, ProductSubscriptionStatus, Status
18+
from .enums import AccessType, OrgStatus, OrgType, ProductSubscriptionStatus, Status
1919

2020

2121
class Role(Enum):
@@ -87,3 +87,5 @@ class Role(Enum):
8787
EXCLUDED_FIELDS = ("status_code", "type_code")
8888

8989
PREMIUM_ORG_TYPES = (OrgType.PREMIUM.value, OrgType.SBC_STAFF.value, OrgType.STAFF.value)
90+
91+
GOV_ORG_TYPES = (AccessType.GOVM.value, AccessType.GOVN.value)

0 commit comments

Comments
 (0)