diff --git a/api/shipping_client.py b/api/shipping_client.py index 15d7ab1..542cc41 100644 --- a/api/shipping_client.py +++ b/api/shipping_client.py @@ -135,6 +135,46 @@ def resolve_city_state_from_address(address_str, pincode=""): return city, state, clean_pin +def format_pdf_to_4x6(pdf_bytes: bytes) -> bytes: + """ + Format a Delhivery packing slip PDF into an exact 4x6 inch (288x432 pt) thermal page. + Delhivery returns vector labels inside an A4 (595x842 pt) canvas. + This crops out the empty canvas and maps the vector label directly to 4x6 dimensions. + """ + try: + import pymupdf + src_doc = pymupdf.open(stream=pdf_bytes, filetype="pdf") + if len(src_doc) == 0: + return pdf_bytes + src_page = src_doc[0] + + # Auto-detect label border/drawings from the original page + drawings = src_page.get_drawings() + outer_rects = [d["rect"] for d in drawings if d["rect"].width > 200 and d["rect"].height > 350] + if outer_rects: + label_rect = outer_rects[0] + else: + label_rect = pymupdf.Rect(211.0, 19.0, 470.0, 469.0) + + # 4x6 inches in PDF points (72 points/inch) + TARGET_WIDTH = 288.0 # 4 inches + TARGET_HEIGHT = 432.0 # 6 inches + + out_doc = pymupdf.open() + new_page = out_doc.new_page(width=TARGET_WIDTH, height=TARGET_HEIGHT) + + padding = 4.0 + target_rect = pymupdf.Rect(padding, padding, TARGET_WIDTH - padding, TARGET_HEIGHT - padding) + new_page.show_pdf_page(target_rect, src_doc, 0, clip=label_rect) + + out_bytes = out_doc.tobytes() + out_doc.close() + src_doc.close() + return out_bytes + except Exception as e: + logger.warning("Failed to format PDF to 4x6: %s", e) + return pdf_bytes + class ShippingServiceClient: """ Client for interacting with Tradhox Shipping Microservice (shippingservice). @@ -1081,7 +1121,18 @@ class ShippingServiceClient: pdf_pkgs = pdf_json.get('packages', []) if pdf_pkgs and isinstance(pdf_pkgs[0], dict): pdf_url = pdf_pkgs[0].get('pdf_download_link') - pdf_encoding = pdf_pkgs[0].get('pdf_encoding') + raw_encoding = pdf_pkgs[0].get('pdf_encoding') + if raw_encoding: + import base64 + raw_bytes = base64.b64decode(raw_encoding.strip()) + formatted_4x6 = format_pdf_to_4x6(raw_bytes) + pdf_encoding = base64.b64encode(formatted_4x6).decode('utf-8') + elif pdf_url: + s3_res = requests.get(pdf_url, timeout=6) + if s3_res.status_code == 200: + import base64 + formatted_4x6 = format_pdf_to_4x6(s3_res.content) + pdf_encoding = base64.b64encode(formatted_4x6).decode('utf-8') except Exception as pdf_exc: logger.warning("Delhivery PDF link lookup notice: %s", pdf_exc) diff --git a/api/views.py b/api/views.py index 4a61651..9e9a554 100644 --- a/api/views.py +++ b/api/views.py @@ -1640,20 +1640,23 @@ class OrderViewSet(viewsets.ModelViewSet): token = getattr(settings, 'DELHIVERY_API_TOKEN', 'e70dfd63665335ee6e0a1094f6d34e17a126f5a6') d_url = f"https://track.delhivery.com/api/p/packing_slip?wbns={awb}&pdf=true" try: + from .shipping_client import format_pdf_to_4x6 res = requests.get(d_url, headers={"Authorization": f"Token {token}"}, timeout=8) if res.status_code == 200: pkgs = res.json().get('packages', []) if pkgs and pkgs[0].get('pdf_encoding'): import base64 pdf_bytes = base64.b64decode(pkgs[0]['pdf_encoding']) - response = HttpResponse(pdf_bytes, content_type='application/pdf') - response['Content-Disposition'] = f'inline; filename="delhivery_label_{awb}.pdf"' + pdf_4x6_bytes = format_pdf_to_4x6(pdf_bytes) + response = HttpResponse(pdf_4x6_bytes, content_type='application/pdf') + response['Content-Disposition'] = f'inline; filename="delhivery_label_4x6_{awb}.pdf"' return response elif pkgs and pkgs[0].get('pdf_download_link'): s3_res = requests.get(pkgs[0]['pdf_download_link'], timeout=8) if s3_res.status_code == 200: - response = HttpResponse(s3_res.content, content_type='application/pdf') - response['Content-Disposition'] = f'inline; filename="delhivery_label_{awb}.pdf"' + pdf_4x6_bytes = format_pdf_to_4x6(s3_res.content) + response = HttpResponse(pdf_4x6_bytes, content_type='application/pdf') + response['Content-Disposition'] = f'inline; filename="delhivery_label_4x6_{awb}.pdf"' return response except Exception as e: logger.error("Failed to fetch label PDF: %s", e) diff --git a/requirements.txt b/requirements.txt index 62f552d..3f38640 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,3 +13,4 @@ boto3 djangorestframework-simplejwt requests +pymupdf