"""Product submit workflow logic.""" import datetime from flask import g from oto import response from oto import status from oto.error import ERROR_CODE_NOT_FOUND from product_workflow.connectors import mysql from product_workflow.constants import error from product_workflow.constants import release_approval_queue_status as raqs from product_workflow.constants import release_correction_status as rcs from product_workflow.models import ows_product from product_workflow.models import ows_product_review from product_workflow.models import release_approval_queue as raq from product_workflow.models import release_correction @mysql.wrap_db_errors def submit_digital_product(product_id, submit_data): """Product submission workflow. Does actions related to product submission. On success it will also insert a record to the `release_approval_queue` table. Args: product_id (int): id of the product. submit_data (dict): params of product submit process. Returns: response.Response: Response containing the created release approval queue data. """ error_correction_flag_enabled = submit_data.get('error_correction_flag') account_type = submit_data.get('account_type') account_id = submit_data.get('account_id') product_status = '' ows_product_response = ows_product.get_product_by_id( product_id) if not ows_product_response: return ows_product_response if ows_product_response: product_status = ows_product_response.message['status'] submit_result = {} # check product not checked out checked_out_response = _is_product_checked_out(product_id) if not checked_out_response: return checked_out_response if checked_out_response.message: return response.create_error_response( code=error.INTERNAL_ERROR, message=error.ERROR_MESSAGE_PRODUCT_ALREADY_CHECKED_OUT, status=400) # Check whether a product is going to content review or OA release approval. eligibility_response = ( ows_product_review.get_review_queue_eligibility(product_id)) if not eligibility_response: return eligibility_response g.ows.log.info( f'product {product_id} eligibility: {eligibility_response.message}' ) # Submit the error correction. with mysql.db_session() as session: release_correction_id = None if error_correction_flag_enabled: latest_correction = _submit_release_correction_entry( session, product_id, account_type, account_id) submit_result['latest_correction'] = latest_correction if product_status == 'in_content' and not latest_correction: return response.create_error_response( code=error.INTERNAL_ERROR, message=error.ERROR_MESSAGE_MISSING_RELEASE_CORRECTION, status=400) if latest_correction: release_correction_id = latest_correction[ 'release_correction_id'] if eligibility_response.message == 'eligible': return response.Response({ 'release_approval': { 'status': raqs.CHECKED_IN } }) # create_release_approval_queue_entry release_approval = raq.ReleaseApprovalQueue( release_id=product_id, release_correction_id=release_correction_id, status=raqs.CHECKED_IN, admin_approval='N', last_updated=datetime.datetime.now(), date_submitted=datetime.datetime.now() ) session.add(release_approval) session.commit() submit_result['release_approval'] = release_approval.to_dict() return response.Response(message=submit_result) def _submit_release_correction_entry( session, product_id, account_type, account_id): latest_correction = release_correction.get_last_correction_object( session, product_id, for_update=True) if latest_correction is None: return None if latest_correction.status == 'active': latest_correction.status = 'submitted' latest_correction.last_updated = datetime.datetime.now() latest_correction.last_updated_type = account_type latest_correction.last_updated_by = int(account_id) return latest_correction.to_dict() def _is_product_checked_out(product_id): approval_response = raq.get_last_approval( product_id) if approval_response.status == status.NOT_FOUND: return response.Response(message=False) if not approval_response: return approval_response checked_out = approval_response.message.get('status') == raqs.CHECKED_OUT return response.Response(message=checked_out) def unsubmit_digital_product_from_product_review(product_id, account_id, account_type): """Unsubmit the product from product review.""" ows_product_review_response = ows_product_review.unsubmit_product( product_id) if not ows_product_review_response: return ows_product_review_response correction_response = release_correction.get_last_release_correction(product_id) if correction_response.status == status.NOT_FOUND: return ows_product_review_response if not correction_response: return correction_response correction = correction_response.message if correction['status'] != rcs.SUBMITTED: return correction_response correction['status'] = rcs.ACTIVE correction['last_updated_by'] = account_id correction['last_updated_type'] = account_type correction_id = correction.pop('release_correction_id') update_response = release_correction.update(correction_id, correction) return update_response def unsubmit_digital_product(product_id, submit_data): """Delete the last release_approval_queue record.""" account_type = submit_data.get('account_type') account_id = submit_data.get('account_id') def _is_success_or_non_404_error(response_to_check): return ( response_to_check.status == status.OK or response_to_check.errors.get('code') != ( ERROR_CODE_NOT_FOUND) ) unsubmit_from_product_review_response = unsubmit_digital_product_from_product_review( product_id, account_id, account_type) if _is_success_or_non_404_error(unsubmit_from_product_review_response): return unsubmit_from_product_review_response legacy_response = raq.delete_latest_release_approval_queue( product_id, account_id, account_type) if _is_success_or_non_404_error(legacy_response): return legacy_response return response.create_not_found_response( message=error.ERROR_MESSAGE_PRODUCT_APPROVAL_NOT_FOUND.format( product_id))