timfocus commited on
Commit
273a8ca
·
verified ·
1 Parent(s): a3a8092

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -106
app.py CHANGED
@@ -1,135 +1,197 @@
1
  import os
2
- import pandas as pd
3
  import gradio as gr
 
4
  from reportlab.pdfgen import canvas
5
- from reportlab.lib.pagesizes import letter
6
- from reportlab.lib import colors
7
  from reportlab.lib.utils import ImageReader
8
- from reportlab.lib.styles import getSampleStyleSheet
9
  import barcode
10
  from barcode.writer import ImageWriter
11
 
12
- # Ensure output directories exist
13
  LABELS_DIR = "labels"
14
  BARCODES_DIR = "barcodes"
15
  os.makedirs(LABELS_DIR, exist_ok=True)
16
  os.makedirs(BARCODES_DIR, exist_ok=True)
17
 
18
- # Function to process the uploaded file
19
- def process_file(file_path):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  try:
21
- # Load data from file
22
- if file_path.endswith('.csv'):
23
- df = pd.read_csv(file_path)
24
- elif file_path.endswith(('.xls', '.xlsx')):
25
- df = pd.read_excel(file_path)
 
 
 
 
 
 
26
  else:
27
  return "Invalid file format. Please upload a .csv, .xls, or .xlsx file."
28
 
29
- # Ensure required columns exist
30
- required_cols = [
31
- "Order ID", "Order Date", "Shipper Name", "Shipper Address", "Shipper Phone",
32
- "Receiver Name", "Receiver Address", "Receiver Phone", "Package Weight (kg)",
33
- "Shipping Method", "Tracking Number", "Estimated Delivery Date"
34
  ]
35
-
36
- missing_cols = [col for col in required_cols if col not in df.columns]
37
- if missing_cols:
38
- return f"Missing columns: {', '.join(missing_cols)}"
39
 
40
- # Process each row and generate labels
41
- label_files = []
42
  for i, row in df.iterrows():
43
- label_path = create_shipping_label(row, i + 1)
44
- if os.path.exists(label_path):
45
- label_files.append(label_path)
46
-
47
- return label_files if label_files else "No labels generated."
48
-
49
- except Exception as e:
50
- return f"Error processing file: {str(e)}"
51
 
52
- # Function to create a USPS-style shipping label
53
- def create_shipping_label(row, index):
54
- try:
55
- tracking_number = str(row["Tracking Number"])
56
- barcode_path = os.path.join(BARCODES_DIR, f"barcode_{index}.png")
57
-
58
- # Generate barcode
59
- ean = barcode.get_barcode_class('code128')
60
- ean = ean(tracking_number, writer=ImageWriter())
61
- ean.save(barcode_path)
62
-
63
- # Create PDF label
64
- label_path = os.path.join(LABELS_DIR, f"label_{index}.pdf")
65
- c = canvas.Canvas(label_path, pagesize=letter)
66
-
67
- # Header: USPS branding and tracking info
68
- c.setFont("Helvetica-Bold", 20)
69
- c.drawString(50, 750, "USPS FIRST-CLASS PKG")
70
- c.setFont("Helvetica", 12)
71
- c.drawString(50, 730, f"Order ID: {row['Order ID']} | Date: {row['Order Date']}")
72
-
73
- # Sender information
74
- c.setFont("Helvetica-Bold", 12)
75
- c.drawString(50, 700, "From:")
76
- c.setFont("Helvetica", 12)
77
- c.drawString(50, 685, f"{row['Shipper Name']}")
78
- c.drawString(50, 670, f"{row['Shipper Address']}")
79
- c.drawString(50, 655, f"Phone: {row['Shipper Phone']}")
80
-
81
- # Receiver information
82
- c.setFont("Helvetica-Bold", 12)
83
- c.drawString(50, 620, "To:")
84
- c.setFont("Helvetica-Bold", 14)
85
- c.drawString(50, 605, row["Receiver Name"]) # Bold receiver name
86
- c.setFont("Helvetica", 12)
87
- c.drawString(50, 590, row["Receiver Address"])
88
- c.drawString(50, 575, f"Phone: {row['Receiver Phone']}")
89
-
90
- # Shipping details
91
- c.setFont("Helvetica-Bold", 12)
92
- c.drawString(50, 540, "Shipping Method:")
93
- c.setFont("Helvetica", 12)
94
- c.drawString(50, 525, row["Shipping Method"])
95
-
96
- c.setFont("Helvetica-Bold", 12)
97
- c.drawString(250, 540, "Package Weight:")
98
- c.setFont("Helvetica", 12)
99
- c.drawString(250, 525, f"{row['Package Weight (kg)']} kg")
100
-
101
- c.setFont("Helvetica-Bold", 12)
102
- c.drawString(50, 500, "Estimated Delivery:")
103
- c.setFont("Helvetica", 12)
104
- c.drawString(50, 485, row["Estimated Delivery Date"])
105
-
106
- # Add barcode
107
- c.setFont("Helvetica-Bold", 14)
108
- c.drawString(50, 450, "USPS TRACKING #")
109
- if os.path.exists(barcode_path):
110
- c.drawImage(barcode_path, 50, 400, width=300, height=70)
111
- else:
112
- c.drawString(50, 400, "Barcode generation failed.")
113
 
114
- # Tracking number below barcode
115
- c.setFont("Helvetica-Bold", 12)
116
- c.drawString(50, 370, tracking_number)
117
 
118
- # Finalize PDF
119
- c.showPage()
120
- c.save()
121
-
122
- return label_path
123
  except Exception as e:
124
- return f"Error creating label: {str(e)}"
125
 
126
- # Gradio interface
 
 
127
  iface = gr.Interface(
128
  fn=process_file,
129
  inputs=gr.File(type="filepath"),
130
- outputs=gr.File(type="filepath", label="Download Labels"),
131
- title="Shipping Label Generator",
132
- description="Upload a .csv, .xls, or .xlsx file to generate USPS-style shipping labels."
 
 
 
 
 
 
133
  )
134
 
135
- iface.launch()
 
 
 
1
  import os
2
+ import zipfile
3
  import gradio as gr
4
+ import pandas as pd
5
  from reportlab.pdfgen import canvas
6
+ from reportlab.lib.pagesizes import inch
 
7
  from reportlab.lib.utils import ImageReader
 
8
  import barcode
9
  from barcode.writer import ImageWriter
10
 
11
+ # Create folders to store generated files
12
  LABELS_DIR = "labels"
13
  BARCODES_DIR = "barcodes"
14
  os.makedirs(LABELS_DIR, exist_ok=True)
15
  os.makedirs(BARCODES_DIR, exist_ok=True)
16
 
17
+ ############################################
18
+ # 1) Draw the static collage / background
19
+ ############################################
20
+ def draw_label_collage(c, width, height):
21
+ """
22
+ Draws the static 'collage' or background layout
23
+ (like the big "F", USPS text, lines, placeholders).
24
+ """
25
+ # Big "F" at top-left
26
+ c.setFont("Helvetica-Bold", 72)
27
+ c.drawString(15, height - 90, "F")
28
+
29
+ # USPS postage info in top-left area
30
+ c.setFont("Helvetica", 8)
31
+ c.drawString(70, height - 25, "US POSTAGE AND FEES PAID")
32
+ c.drawString(70, height - 35, "Apr 12 2018")
33
+ c.drawString(70, height - 45, "Mailed from ZIP 77024")
34
+ c.drawString(70, height - 55, "First-Class Pkg Svc")
35
+ c.drawString(70, height - 65, "CommercialBasePrice")
36
+
37
+ # Placeholder for QR code (top-right)
38
+ c.setFont("Helvetica", 6)
39
+ c.drawString(width - 60, height - 20, "QR CODE")
40
+
41
+ # "USPS FIRST-CLASS PKG" bar
42
+ c.setFont("Helvetica-Bold", 14)
43
+ c.drawString(15, height - 110, "USPS FIRST-CLASS PKG")
44
+
45
+ # Horizontal line
46
+ c.setLineWidth(1)
47
+ c.line(15, height - 115, width - 15, height - 115)
48
+
49
+ ############################################
50
+ # 2) Draw the dynamic text & overlay
51
+ ############################################
52
+ def draw_label_text(c, row, width, height):
53
+ """
54
+ Overlays dynamic text from each row:
55
+ Warehouse info, recipient address, tracking number, etc.
56
+ """
57
+ # Example columns from your data (adjust as needed)
58
+ warehouse_line1 = row.get("Warehouse Line1", "WAREHOUSE 2")
59
+ warehouse_line2 = row.get("Warehouse Line2", "11919 WINK RD")
60
+ warehouse_line3 = row.get("Warehouse Line3", "HOUSTON TX 77024-7134")
61
+ order_number = row.get("Order Number", "286")
62
+
63
+ recipient_name = row.get("Recipient Name", "John Doe")
64
+ recipient_addr1 = row.get("Recipient Addr1", "321 Street Over There")
65
+ recipient_addr2 = row.get("Recipient Addr2", "Salt Lake City, UT 11212")
66
+ recipient_addr3 = row.get("Recipient Addr3", "United States")
67
+
68
+ tracking_number = row.get("Tracking Number", "9400 1102 0079 3961 8936 91")
69
+
70
+ # Warehouse info (top-left under the bar)
71
+ c.setFont("Helvetica-Bold", 9)
72
+ c.drawString(15, height - 130, warehouse_line1)
73
+ c.setFont("Helvetica", 9)
74
+ c.drawString(15, height - 145, warehouse_line2)
75
+ c.drawString(15, height - 160, warehouse_line3)
76
+
77
+ # Order number (top-right)
78
+ c.drawString(width - 80, height - 130, f"Order: {order_number}")
79
+
80
+ # Recipient info (bold name)
81
+ c.setFont("Helvetica-Bold", 12)
82
+ c.drawString(15, height - 200, recipient_name)
83
+ c.setFont("Helvetica", 10)
84
+ c.drawString(15, height - 215, recipient_addr1)
85
+ c.drawString(15, height - 230, recipient_addr2)
86
+ c.drawString(15, height - 245, recipient_addr3)
87
+
88
+ # "USPS TRACKING #"
89
+ c.setFont("Helvetica-Bold", 12)
90
+ c.drawString(15, height - 280, "USPS TRACKING #")
91
+
92
+ # Tracking number
93
+ c.setFont("Helvetica-Bold", 10)
94
+ c.drawString(15, height - 295, tracking_number)
95
+
96
+ ############################################
97
+ # 3) Create the 4x6 USPS-style label
98
+ ############################################
99
+ def create_usps_label(row, index=1):
100
+ """
101
+ Creates a 4x6 inch PDF label using the collage background,
102
+ then overlays dynamic text and a barcode at the bottom.
103
+ """
104
+ # 3A) Generate Code128 barcode
105
+ tracking_number = row.get("Tracking Number", "9400110200793961893691")
106
+ barcode_filename = os.path.join(BARCODES_DIR, f"barcode_{index}.png")
107
+ code128 = barcode.get_barcode_class("code128")
108
+ code128_obj = code128(tracking_number, writer=ImageWriter())
109
+ code128_obj.save(barcode_filename)
110
+
111
+ # 3B) Prepare a 4x6 inch PDF
112
+ width, height = 4 * inch, 6 * inch
113
+ label_filename = os.path.join(LABELS_DIR, f"label_{index}.pdf")
114
+ c = canvas.Canvas(label_filename, pagesize=(width, height))
115
+
116
+ # (1) Draw static collage
117
+ draw_label_collage(c, width, height)
118
+
119
+ # (2) Overlay dynamic text
120
+ draw_label_text(c, row, width, height)
121
+
122
+ # (3) Place the barcode at the bottom
123
+ if os.path.exists(barcode_filename):
124
+ c.drawImage(barcode_filename, 15, 0.8 * inch, width=3 * inch, height=0.8 * inch)
125
+ else:
126
+ c.setFont("Helvetica", 10)
127
+ c.drawString(15, 0.8 * inch, "Barcode generation failed.")
128
+
129
+ c.showPage()
130
+ c.save()
131
+ return label_filename
132
+
133
+ ############################################
134
+ # 4) Gradio Function to Process File Upload
135
+ ############################################
136
+ def process_file(file_obj):
137
  try:
138
+ # Clean old label/barcode files
139
+ for f in os.listdir(LABELS_DIR):
140
+ os.remove(os.path.join(LABELS_DIR, f))
141
+ for f in os.listdir(BARCODES_DIR):
142
+ os.remove(os.path.join(BARCODES_DIR, f))
143
+
144
+ # Read the file
145
+ if file_obj.name.endswith(".csv"):
146
+ df = pd.read_csv(file_obj)
147
+ elif file_obj.name.endswith((".xls", ".xlsx")):
148
+ df = pd.read_excel(file_obj)
149
  else:
150
  return "Invalid file format. Please upload a .csv, .xls, or .xlsx file."
151
 
152
+ # Basic check for columns
153
+ needed_cols = [
154
+ "Warehouse Line1", "Warehouse Line2", "Warehouse Line3", "Order Number",
155
+ "Recipient Name", "Recipient Addr1", "Recipient Addr2", "Recipient Addr3",
156
+ "Tracking Number"
157
  ]
158
+ missing = [c for c in needed_cols if c not in df.columns]
159
+ if missing:
160
+ return f"Missing columns: {', '.join(missing)}"
 
161
 
162
+ # Generate a PDF label for each row
 
163
  for i, row in df.iterrows():
164
+ create_usps_label(row.to_dict(), index=i+1)
 
 
 
 
 
 
 
165
 
166
+ # Zip all PDFs
167
+ zip_filename = "usps_labels.zip"
168
+ with zipfile.ZipFile(zip_filename, "w") as zf:
169
+ for f in os.listdir(LABELS_DIR):
170
+ if f.endswith(".pdf"):
171
+ zf.write(os.path.join(LABELS_DIR, f), f)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
+ return zip_filename
 
 
174
 
 
 
 
 
 
175
  except Exception as e:
176
+ return f"Error processing file: {str(e)}"
177
 
178
+ ############################################
179
+ # 5) Gradio Interface
180
+ ############################################
181
  iface = gr.Interface(
182
  fn=process_file,
183
  inputs=gr.File(type="filepath"),
184
+ outputs=gr.File(type="filepath", label="Download Zipped Labels"),
185
+ title="USPS-Style Label Generator (4x6)",
186
+ description=(
187
+ "Upload a CSV/XLS/XLSX with columns:\n"
188
+ "Warehouse Line1, Warehouse Line2, Warehouse Line3, Order Number,\n"
189
+ "Recipient Name, Recipient Addr1, Recipient Addr2, Recipient Addr3,\n"
190
+ "Tracking Number\n\n"
191
+ "Each row creates a 4x6 USPS-style PDF label. Download the ZIP!"
192
+ ),
193
  )
194
 
195
+ # Launch the app
196
+ if __name__ == "__main__":
197
+ iface.launch()