MID / app.py
joycecast's picture
Upload 3 files
69184f3 verified
import gradio as gr
import pandas as pd
import re
import os
# ---------- Helpers ----------
def sanitize_string(s):
return re.sub(r'[^A-Z0-9]', '', s.upper())
def extract_letters(s, count):
letters = re.sub(r'[^A-Z]', '', s.upper())
return letters[:count].ljust(count, '0')
def extract_street_number(text: str) -> str:
text_upper = text.upper()
patterns = [
r'ROOM\s+(\d{1,4})',
r'BUILDING\s+(\d{1,4})',
r'NO\.?\s+(\d{1,4})',
]
for pattern in patterns:
match = re.search(pattern, text_upper)
if match:
return match.group(1)
fallback = re.search(r'\d{1,4}', text_upper)
return fallback.group(0) if fallback else ''
def extract_city(text: str) -> str:
city_match = re.search(r'([A-Z]+) CITY', text.upper())
return city_match.group(1) if city_match else "UNKNOWN"
def extract_company_letters(name: str) -> str:
words = name.upper().split()
first = extract_letters(words[0], 3) if len(words) > 0 else ''
second = extract_letters(words[1], 3) if len(words) > 1 else ''
return (first + second)[:6].ljust(3, '0')
def generate_mid(country_code, company_name, full_address):
if not country_code or not company_name or not full_address:
return None
cc = sanitize_string(country_code)[:2]
if len(cc) != 2:
return None
company_part = extract_company_letters(company_name)
street_number = extract_street_number(full_address)
city = extract_city(full_address)
city_part = extract_letters(city, 3)
return f"{cc}{company_part}{street_number}{city_part}"
# ---------- Manual Entry ----------
def manual_mid(full_address, manual_company_name, country_code):
if not full_address.strip():
return "❌ Please provide a full address."
cc = sanitize_string(country_code or "CN")[:2]
if len(cc) != 2:
return "❌ Invalid country code."
company_part = extract_company_letters(manual_company_name or "")
street_number = extract_street_number(full_address)
city = extract_city(full_address)
city_part = extract_letters(city, 3)
mid = f"{cc}{company_part}{street_number}{city_part}"
return (
f"βœ… MID: {mid}\n\n"
f"Company: {manual_company_name or '(auto)'}\n"
f"Street #: {street_number or '(not found)'}\n"
f"City: {city}\n"
f"Country: {cc}"
)
# ---------- File Upload Handling ----------
def process_excel(file_obj):
try:
df = pd.read_excel(file_obj)
if not all(col in df.columns for col in ["CountryCode", "CompanyName", "FullAddress"]):
return "❌ Missing required columns: CountryCode, CompanyName, FullAddress", None
df["MID"] = df.apply(
lambda row: generate_mid(
row["CountryCode"],
row["CompanyName"],
row["FullAddress"]
),
axis=1
)
output_path = "generated_mid_output.xlsx"
df.to_excel(output_path, index=False)
return "βœ… MID generation completed. Download the file below.", output_path
except Exception as e:
return f"❌ Error processing file: {str(e)}", None
# ---------- Gradio UI ----------
with gr.Blocks(title="MID Generator") as demo:
gr.Markdown("## 🏷️ CBP MID Code Generator")
with gr.Tab("πŸ”€ Manual Input"):
full_address = gr.Textbox(label="Full Address", lines=3)
company_name = gr.Textbox(label="Company Name", placeholder="Optional (auto-detect if blank)")
country_code = gr.Textbox(label="Country Code", value="CN")
mid_output = gr.Textbox(label="Generated MID", lines=6)
gen_btn = gr.Button("Generate MID")
gen_btn.click(
fn=manual_mid,
inputs=[full_address, company_name, country_code],
outputs=mid_output
)
with gr.Tab("πŸ“ Upload Excel File"):
gr.Markdown("**Upload an Excel file with the following columns:** `CountryCode`, `CompanyName`, `FullAddress`")
excel_input = gr.File(file_types=[".xlsx"], label="Upload Excel File")
file_status = gr.Textbox(label="Status", interactive=False)
download_link = gr.File(label="Download Output")
excel_input.change(
fn=process_excel,
inputs=[excel_input],
outputs=[file_status, download_link]
)
with gr.Tab("πŸ“„ Template"):
gr.Markdown("⬇️ Download the sample Excel template:")
gr.File(value="mid_upload_template.xlsx", label="Download Template")
demo.launch()