Repository URL to install this package:
|
Version:
0.4.192 ▾
|
lib-py-b2b
/
print.py
|
|---|
import boto3
from botocore.exceptions import ClientError
from .fulfillment import Fulfillment
from .profile import Profile
import json
from datetime import datetime
import logging
from pprint import pformat
from .carrier import CarrierType
import binascii
import socket
from .errors import InvalidLabelPrintRequestError, LabelPrintError
from os import environ
logger = logging.getLogger(__name__)
class Printer:
@staticmethod
def for_(customer_edi_id: str):
profile = Profile.profile_for(customer_edi_id)
name = profile.fulfillment_config.fedex_api_config.printer_name
ip_address = profile.fulfillment_config.fedex_api_config.printer_ip_address
port = int(profile.fulfillment_config.fedex_api_config.printer_port)
return Printer(name=name, address=ip_address, port=port)
def __init__(self, name: str, address: str, port: int):
self.name = name
self.address = address
self.port = port
class PrintRequest:
LABEL_PRINT_QUEUE = environ['LABEL_PRINT_QUEUE'] if 'LABEL_PRINT_QUEUE' in environ else 'B2B_LABEL_PRINT_QUEUE_DEV'
LABEL_PRINT_DLQ = environ['LABEL_PRINT_DLQ'] if 'LABEL_PRINT_DLQ' in environ else 'B2B_LABEL_PRINT_DLQ_DEV'
@staticmethod
def setup_queues():
sqs = boto3.resource('sqs')
dlq = sqs.create_queue(QueueName=PrintRequest.LABEL_PRINT_DLQ)
redrive_policy = {
'deadLetterTargetArn': dlq.attributes['QueueArn'],
'maxReceiveCount': '10'
}
queue = sqs.create_queue(QueueName=PrintRequest.LABEL_PRINT_QUEUE,
Attributes={'DelaySeconds': '0',
'VisibilityTimeout': '60',
'RedrivePolicy': json.dumps(redrive_policy)})
return queue
@staticmethod
def __get_print_queue():
try:
sqs = boto3.resource('sqs')
return sqs.get_queue_by_name(QueueName=PrintRequest.LABEL_PRINT_QUEUE)
except ClientError as ce:
if ce.response['Error']['Code'] == 'AWS.SimpleQueueService.NonExistentQueue':
return PrintRequest.setup_queues()
else:
logger.exception("Error received trying to access the print queue.")
return None
@staticmethod
def create(printer: Printer, fulfillment):
_fulfillment = Fulfillment.for_(fulfillment)
print_request = {
'fulfillment_id': _fulfillment['id'],
'printer_address': printer.address,
'printer_port': printer.port,
'request_time': datetime.utcnow().isoformat()
}
logger.debug(f"Sending print request {pformat(print_request)} to {PrintRequest.LABEL_PRINT_QUEUE}")
queue = PrintRequest.__get_print_queue()
response = queue.send_message(MessageBody=json.dumps(print_request))
return response['MessageId']
class PrintRequestHandler:
def __print_label(self, fulfillment_id, labels, printer_address, printer_port):
for label in labels:
for i in range(0, int(label['copies'])):
for image in label['parts']:
label_binary_data = binascii.a2b_base64(image)
try:
s = socket.create_connection(address=(printer_address, printer_port), timeout=60)
except socket.error as se:
logger.error(f"Unable to connect to printer {printer_address}:{printer_port} for fulfillment {fulfillment_id}.", se)
raise LabelPrintError(f"Unable to connect to printer {printer_address}:{printer_port} for fulfillment {fulfillment_id}.") from se
try:
s.send(label_binary_data)
except socket.error as se:
logger.error(f"Unable to print labels for fulfillment {fulfillment_id}.", se)
raise LabelPrintError(f"Unable to print labels for fulfillment {fulfillment_id}.") from se
finally:
s.close()
def handle_print_request(self, record):
pr = json.loads(record.body)
logger.debug(f"Received print request {pformat(pr)}")
fulfillment_id = pr['fulfillment_id']
_fulfillment = Fulfillment.for_(fulfillment_id)
carrier_type = CarrierType(_fulfillment.get('carrier_type', _fulfillment.get('carrier_type', CarrierType.FEDEX_SHIP_MGR.value)))
if carrier_type == CarrierType.FEDEX_API:
if 'labels' in _fulfillment:
logger.info(f"Printing labels for request {pformat(pr)}")
self.__print_label(fulfillment_id=_fulfillment['id'],
labels=_fulfillment['labels'],
printer_address=pr['printer_address'],
printer_port=pr['printer_port'])
else:
logger.warning(f"Attempted to print labels for fulfillment {_fulfillment['id']} and it had no labels.")
else:
raise InvalidLabelPrintRequestError(f"The carrier type {carrier_type} on fulfillment {_fulfillment['id']} does not "
f"support label printing.")