backend-printing/helper/backend_print.py (232 lines of code) (raw):

"""Interface for the helper module. This module contains the interface for the helper module and azure functions. """ import ast import os import json import logging from dataclasses import asdict from marshmallow_dataclass import class_schema from helper.constants import ( SAP_CONFIG_KEY_VAULT_KEY, DOCUMENT_CONTENT_TYPE, NUMBER_OF_THREADS, ) from helper.models import PrintItemStatus from helper.sap_client import SAPPrintClient from helper.models import SAPSystem from helper.key_vault import KeyVault from helper.storage import StorageQueueClient, TableStorageClient from helper.universal_print_client import ( UniversalPrintUsingLogicApp, UniversalPrintClient, ) class BackendPrint: def __init__(self, logger: logging, log_tag: str) -> None: self.logger = logger self.log_tag = log_tag self.sap_systems = [] def _load_schema(self, sap_config: dict): """_summary_ Args: sap_config (dict): _description_ Raises: Exception: _description_ Returns: SAPsystem: system properties """ try: sap_system_schema = class_schema(SAPSystem)() return sap_system_schema.load(sap_config) except Exception as e: raise Exception(f"Error occurred SAP config: {e}") def _get_sap_config(self, sap_sid, sap_environment): """Get the SAP config from the key vault Args: sap_sid (string): SAP system ID sap_environment (string): SAP environment Returns: dict: SAP config """ try: secret = KeyVault().get_sap_config( secret_name=SAP_CONFIG_KEY_VAULT_KEY % ( sap_environment, sap_sid, ), ) return self._load_schema(json.loads(secret.value)) except Exception as e: raise Exception(f"Error occurred getting SAP config: {e}") def _get_all_sap_configs(self): """Get the SAP config from the key vault""" self.sap_systems = [] sap_configs = KeyVault().get_sap_config_secrets() for sap_config in sap_configs: self.sap_systems.append(self._load_schema(json.loads(sap_config.value))) def _send_message_to_storage_queue(self, print_messages): """Send the print messages to the storage queue. Args: print_messages (list): List of print messages """ try: for print_message in print_messages: StorageQueueClient().send_message(message=print_message) except Exception as e: return { "status": "error", "message": "Error occurred while sending message", } def _update_print_messages_status( self, print_messages, status=PrintItemStatus.IN_PROGRESS.value, error_message="" ): """Update the status of the print messages. Args: print_messages (list): List of print messages """ try: for print_message in print_messages: TableStorageClient().put_entity( table_name=os.environ["STORAGE_TABLE_NAME"], entity={ "PartitionKey": print_message["sap_sid"], "RowKey": print_message["print_item"]["queue_item_id"], "Status": status, "Message": error_message, }, ) except Exception as e: return { "status": "error", "message": "Error occurred while sending message", } def validation_engine(self, sap_config: dict): """Validate the connection to the SAP system. Validate the queue names are present in the SAP system. If the validation pass, store the connection details in the Key Vault. Args: sap_config (dict): _description_ Returns: _type_: _description_ """ try: sap_configuration_map = self._load_schema(sap_config) print_client = SAPPrintClient(sap_configuration_map) sap_queues = print_client.get_print_queues() for queue in sap_queues: if not print_client.find_print_queue(queue): return {"status": "error", "message": f"Incorrect queue information - {queue}"} self.logger.info( f"[{self.log_tag}] SAP connection validated, saving to key vault" ) KeyVault().set_kv_secrets( secret_key=SAP_CONFIG_KEY_VAULT_KEY % ( sap_configuration_map.sap_environment, sap_configuration_map.sap_sid, ), secret_value=json.dumps(asdict(sap_configuration_map)), ) return {"status": "success", "message": "SAP connection validated"} except Exception as e: self.logger.error( f"[{self.log_tag}] Error occurred while validating SAP connection: {e}" ) return {"status": "error", "message": str(e)} def fetch_print_items_from_sap(self): """Get the print items from each SAP system. Create a json message for each print item. Move these messages to storage queue. """ print_messages = [] try: self._get_all_sap_configs() self.logger.info(f"[{self.log_tag}] Fetched sap config from key vault") for sap_system in self.sap_systems: sap_client = SAPPrintClient(sap_system) self.logger.info( f"[{self.log_tag}] Fetching print items from SAP system {sap_system.sap_sid}" ) if sap_system.sap_print_queues is not None: for queue in sap_system.sap_print_queues: print_items_from_queue = [] response = sap_client.get_print_items_from_queue( queue_name=queue.queue_name ) ( print_items_from_queue.extend(response) if response is not None else [] ) self.logger.info( f"[{self.log_tag}] Fetched {len(print_items_from_queue)} items from the " + f" SAP queue {queue} for {sap_system.sap_sid}" ) for print_item in print_items_from_queue: queue_item_params = json.loads(print_item["QItemParams"]) for document in json.loads(print_item["Documents"]): print_messages.append( { "sap_sid": sap_system.sap_sid, "sap_environment": sap_system.sap_environment, "sap_print_queue_name": queue.queue_name, "print_item": { "document_blob": document["blob"], "document_name": document["document_name"], "document_file_size": document["filesize"], "printer_share_id": queue.print_share_id, "queue_item_id": print_item["QItemId"], "document_content_type": DOCUMENT_CONTENT_TYPE, "print_job_copies": queue_item_params[ "print_job" ]["copies"], }, } ) # send the print messages to the storage queue if print_messages: self._send_message_to_storage_queue(print_messages=print_messages) self.logger.info( f"[{self.log_tag}] Sent {len(print_messages)} messages to the storage account" ) self._update_print_messages_status( print_messages=print_messages, status=PrintItemStatus.NEW.value ) self.logger.info( f"[{self.log_tag}] Updated {len(print_messages)} messages status in storage table to NEW" ) except Exception as e: self.logger.error( f"[{self.log_tag}] Error occurred while fetching SAP config from the Key Vault: {e}" ) return { "status": "error", "message": "Error occurred while fetching items.", } def send_print_items_to_universal_print(self): """Get the print items from storage account queue. Temporary work around: Since the authorization using SPN is not available for the universal print, """ messages = [] try: messages = StorageQueueClient().receive_messages() self.logger.info( f"[{self.log_tag}] Fetched items {len(messages)} from the storage account" ) self._update_print_messages_status( print_messages=messages, status=PrintItemStatus.IN_PROGRESS.value ) for message in messages: queue_message, message_content = message self.logger.info(f"[{self.log_tag}] Logic app init for printing") response = UniversalPrintUsingLogicApp().call_logic_app( print_items=message_content["print_item"] ) sap_config = self._get_sap_config( sap_sid=message_content["sap_sid"], sap_environment=message_content["sap_environment"], ) sap_client = SAPPrintClient(sap_system_config=sap_config) if response.status_code == 202 or response.status_code == 201: StorageQueueClient().delete_message(message=queue_message) self.logger.info( f"[{self.log_tag}] Deleted the message from the storage account after success" ) self._update_print_messages_status( print_messages=[message_content], status=PrintItemStatus.COMPLETED.value, ) sap_client.fetch_csrf_token_and_update_print_item_status( print_item_id=message_content["print_item"]["queue_item_id"], queue_name=message_content["sap_print_queue_name"], status="S", ) else: sap_client.fetch_csrf_token_and_update_print_item_status( print_item_id=message_content["print_item"]["queue_item_id"], queue_name=message_content["sap_print_queue_name"], status="F", ) except Exception as e: self.logger.error( f"[{self.log_tag}] Error occurred while sending items to logic app: {e}" ) self._update_print_messages_status( print_messages=[message], status=PrintItemStatus.ERROR.value ) return { "status": "error", "message": "Error occurred while sending items to logic app.", } def upload_document_to_universal_print(self, request_body): """Upload the document to the Universal Print using universal print client. Args: request_body (request): request body Returns: response object: response """ try: UniversalPrintClient().upload_document(request_body) self.logger.info( f"[{self.log_tag}] Uploaded document to the universal print server" ) except Exception as e: self.logger.error( f"[{self.log_tag}] Error occurred while uploading document to the universal print server: {e}" ) return { "status": "error", "message": f"Error occurred while uploading the document to the UP Server {e}", }