diff --git a/CargoHubV2/app/controllers/packinglist_controller.py b/CargoHubV2/app/controllers/packinglist_controller.py
new file mode 100644
index 0000000..9d1eef9
--- /dev/null
+++ b/CargoHubV2/app/controllers/packinglist_controller.py
@@ -0,0 +1,33 @@
+from fastapi import APIRouter, HTTPException, Depends, Header
+from sqlalchemy.orm import Session
+from CargoHubV2.app.database import get_db
+from CargoHubV2.app.services import packinglist_service
+from CargoHubV2.app.models.orders_model import Order
+from fastapi.responses import FileResponse
+from pathlib import Path
+
+router = APIRouter(
+ prefix="/api/v2/packinglist",
+ tags=["packinglist"]
+)
+
+@router.get("/api/v2/packinglist/{order_id}")
+def create_packing_list(
+ order_id: int,
+ db: Session = Depends(get_db),
+ api_key: str = Header(...),
+):
+ order = db.query(Order).filter(Order.id == order_id).first()
+ if not order:
+ raise HTTPException(status_code=404, detail="Order not found")
+ return packinglist_service.generate_packing_list(order)
+
+
+@router.get("/get-pdf/{filename}")
+def get_pdf(filename: str):
+ PDF_DIR = Path("generated_pdfs")
+ pdf_path = PDF_DIR/filename
+ if pdf_path.exists():
+ return FileResponse(pdf_path, media_type="application/pdf", filename=filename)
+ else:
+ raise HTTPException(status_code=404, detail="PDF not found")
\ No newline at end of file
diff --git a/CargoHubV2/app/main.py b/CargoHubV2/app/main.py
index 2991519..18601a7 100644
--- a/CargoHubV2/app/main.py
+++ b/CargoHubV2/app/main.py
@@ -13,6 +13,7 @@
from CargoHubV2.app.controllers import inventories_controller
from CargoHubV2.app.controllers import orders_controller
from CargoHubV2.app.controllers import reporting_controller
+from CargoHubV2.app.controllers import packinglist_controller
from CargoHubV2.app.controllers import docks_controller
import time
from starlette.responses import JSONResponse
@@ -38,6 +39,7 @@
app.include_router(shipments_controller.router)
app.include_router(inventories_controller.router)
app.include_router(orders_controller.router)
+app.include_router(packinglist_controller.router)
app.include_router(docks_controller.router)
logger = logging.getLogger("uvicorn.error")
diff --git a/CargoHubV2/app/packinglist_template.html b/CargoHubV2/app/packinglist_template.html
new file mode 100644
index 0000000..614eef0
--- /dev/null
+++ b/CargoHubV2/app/packinglist_template.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+ Packing List
+
+
+
+
+ Packing List
+ Warehouse ID: {{ warehouse_id }}
+ Source ID: {{ source_id }}
+ Order ID: {{ order_id }}
+ Order Date: {{ order_date }}
+ Request Date: {{ request_date }}
+ Shipping Notes: {{ shipping_notes }}
+ Total Different Items: {{ total_items }}
+ Total Amount of Items: {{ total_amount }}
+
+ Items
+
+
+
+ Item ID |
+ Quantity |
+
+
+
+ {% for item in items %}
+
+ {{ item.item_id }} |
+ {{ item.amount }} |
+
+ {% endfor %}
+
+
+
+
+
\ No newline at end of file
diff --git a/CargoHubV2/app/services/packinglist_service.py b/CargoHubV2/app/services/packinglist_service.py
new file mode 100644
index 0000000..9fdf40f
--- /dev/null
+++ b/CargoHubV2/app/services/packinglist_service.py
@@ -0,0 +1,72 @@
+import io
+import os
+import json
+import pdfkit
+import base64
+import matplotlib.pyplot as plt
+
+from pathlib import Path
+from jinja2 import Template
+from itertools import chain
+from datetime import datetime
+from sqlalchemy import extract
+from sqlalchemy.orm import Session
+from fastapi import HTTPException, status, FastAPI
+from CargoHubV2.app.models.orders_model import Order
+from fastapi.responses import FileResponse, JSONResponse
+
+
+PDF_DIR = Path("generated_pdfs")
+PDF_DIR.mkdir(exist_ok=True)
+
+TEMPLATE_FILE = Path(os.path.dirname(__file__)).parent / "packinglist_template.html"
+
+
+def generate_packing_list(order: Order):
+ try:
+ # Parse the items data from the order
+ try:
+ items = json.loads(order.items) if isinstance(order.items, str) else order.items
+ if not isinstance(items, list):
+ raise ValueError("Items should be a list of dictionaries with 'item_id' and 'amount'.")
+ except json.JSONDecodeError:
+ raise ValueError("Failed to decode order items. Ensure items are in valid JSON format.")
+
+
+ total_amount = sum(item["amount"] for item in items)
+
+ # Prepare data for the packing list
+ content = {
+ "warehouse_id": order.warehouse_id,
+ "source_id": order.source_id,
+ "shipping_notes": order.shipping_notes,
+ "order_date": order.order_date.strftime("%Y-%m-%d"),
+ "order_id": order.id,
+ "request_date": order.request_date.strftime("%Y-%m-%d"),
+ "total_items": len(items),
+ "total_amount": total_amount,
+ "items": [{"item_id": item["item_id"], "amount": item["amount"]} for item in items], # Simplified item list
+ }
+
+ # Load the packing list template
+ with open(TEMPLATE_FILE, "r") as file:
+ html_template = file.read()
+
+ # Render the template
+ template = Template(html_template)
+ html_content = template.render(**content)
+
+ # Define PDF file path
+ pdf_filename = f"packinglist_order_{order.id}.pdf"
+ pdf_path = PDF_DIR / pdf_filename
+
+ # Generate PDF
+ pdfkit.from_string(html_content, str(pdf_path))
+
+ # Return the file URL or file path
+ pdf_url = f"http://127.0.0.1:3000/api/v2/packinglist/get-pdf/{pdf_filename}"
+ return JSONResponse({"message": "Packing list PDF generated successfully.", "pdf_url": pdf_url})
+ except ValueError as ve:
+ raise HTTPException(status_code=400, detail=str(ve))
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=f"Error generating packing list PDF, {e}")
diff --git a/generated_pdfs/packinglist_order_1.pdf b/generated_pdfs/packinglist_order_1.pdf
new file mode 100644
index 0000000..9e876bf
Binary files /dev/null and b/generated_pdfs/packinglist_order_1.pdf differ