backend-printing/helper/sap_client.py (100 lines of code) (raw):

"""SAP system configuration """ import json from dataclasses import dataclass, field from marshmallow_dataclass import dataclass import requests from requests.auth import HTTPBasicAuth from requests.exceptions import RequestException from requests.adapters import HTTPAdapter from helper.models import SAPSystem from helper.constants import ( BASE_URL, GET_PRINT_QUEUES, GET_N_NEXT_PRINT_ITEMS, GET_NEXT_PRINT_ITEM, GET_NUMBER_OF_PRINT_ITEMS, ITEM_STATUS, ) class SAPPrintClient: def __init__(self, sap_system_config: SAPSystem): """Constructor for SAPSystem Args: sap_sid (string): SAP system ID sap_user (string): SAP username that has access to the ODATA service sap_password (string): SAP password for the user sap_hostname (string): URL of the ODATA service sap_print_queues (list(PrintQueue), optional): List of print queues. Defaults to None. skip_ssl_verification (bool, optional): Boolean whether to skip SSL verification. """ self.sap_sid = sap_system_config.sap_sid self.sap_user = sap_system_config.sap_user self.sap_password = sap_system_config.sap_password self.sap_hostname = sap_system_config.sap_hostname self.sap_print_queues = sap_system_config.sap_print_queues self.skip_ssl_verification = sap_system_config.skip_ssl_verification self.api_url = BASE_URL % self.sap_hostname def _call_sap_api(self, url): """Call SAP ODATA APIs Args: url (strings): URL that contains the ODATA API name Returns: response: SAP ODATA API response """ try: session = requests.Session() # needs to be updated with better retry logic if self.sap_hostname.startswith("https://"): session.mount("https://", HTTPAdapter(max_retries=3)) elif self.sap_hostname.startswith("http://"): session.mount("http://", HTTPAdapter(max_retries=3)) response_object = requests.get( headers={"Accept": "application/json"}, url=url, auth=HTTPBasicAuth(self.sap_user, self.sap_password), verify=not self.skip_ssl_verification, ) response_object.raise_for_status() return json.loads(response_object.text) except Exception as e: raise Exception(f"Error occurred while calling SAP API: {e}") def _get_number_of_print_items(self, queue_name): """Get the number of print items in a queue Args: queue_name (string): queue name Returns: requests.Response: Response object from the request """ try: response = self._call_sap_api( f"{self.api_url}{GET_NUMBER_OF_PRINT_ITEMS}?Qname='{queue_name}'" ) return response["d"]["NrOfNewItems"] if response else 0 except Exception as e: raise Exception(f"Error occurred while getting number of print items: {e}") def find_print_queue(self, queue_name): """Find a print queue by name Args: queue_name (string): queue name Returns: PrintQueue: print queue """ if self.sap_print_queues is not None: for print_queue in self.sap_print_queues: if print_queue.queue_name == queue_name: return True return False def get_print_queues(self): """Get the print queues of the user Returns: list[str]: list of print queues """ try: response = self._call_sap_api(f"{self.api_url}{GET_PRINT_QUEUES}") return [result["Qname"] for result in response["d"]["results"]] except Exception as e: raise Exception(f"Error occurred while getting print queues: {e}") def get_print_items_from_queue(self, queue_name): """Get the print items from a queue Args: queue_name (string): queue name Returns: requests.Response: Response object from the request """ try: number_of_print_items = self._get_number_of_print_items(queue_name) if number_of_print_items: print_items = self._call_sap_api( f"{self.api_url}{GET_N_NEXT_PRINT_ITEMS}?Qname='{queue_name}" + f"'&NumberOfItems={number_of_print_items}" ) return print_items["d"]["results"] except Exception as e: raise Exception(f"Error occurred while getting print items: {e}") def fetch_csrf_token_and_update_print_item_status( self, print_item_id, queue_name, status ): """Fetch CSRF token and update the print item status Args: print_item_id (string): Print item ID queue_name (string): Queue name status (string): Status to update (F/S) Raises: Exception: Error occurred while fetching CSRF token or updating print item status """ try: response_object = requests.head( headers={"Accept": "application/json", "X-CSRF-Token": "Fetch"}, url=f"{self.api_url}PrintItemStatusSet", auth=HTTPBasicAuth(self.sap_user, self.sap_password), ) sap_cookie = response_object.headers["Set-Cookie"].replace(",", ";") x_csrf_token = response_object.headers["X-CSRF-Token"] response_object = requests.post( headers={ "Content-Type": "application/json", "X-CSRF-Token": f"{x_csrf_token}", "Accept": "application/json", }, cookies={"cookie": sap_cookie}, json={ "ItemsStatus": ITEM_STATUS % (print_item_id, status), "Qname": queue_name, }, url=f"{self.api_url}PrintItemStatusSet", auth=HTTPBasicAuth(self.sap_user, self.sap_password), ) except Exception as e: raise Exception(f"Error occurred while fetching CSRF token: {e}")