File size: 9,298 Bytes
8228e94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ade4524
8228e94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b71327e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8228e94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba3e209
 
 
8228e94
 
 
 
 
b71327e
 
8228e94
 
 
 
 
 
 
 
 
 
 
 
 
 
ade4524
8228e94
 
 
ade4524
 
182873f
 
 
 
ade4524
 
 
 
 
 
182873f
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
import gradio as gr
import pandas as pd
from datetime import datetime
import pytz
import openpyxl

def process_file(file):
    file_name = file.name.lower()
    try:
        if file_name.endswith('.csv'):
            # CSV files do not have multiple sheets.
            return "Error: Please upload an Excel file with a UPS sheet.", None
        elif file_name.endswith(('.xls', '.xlsx', '.xlsm')):
            # Only read data from the "UPS" sheet.
            df = pd.read_excel(file.name, sheet_name="UPS")
        else:
            return f"Unsupported file format: {file_name}", None
    except Exception as e:
        return f"Error reading file: {str(e)}", None

    # Define the new header list as specified.
    output_headers = [
        "Contact Name", "Company or Name", "Country", "Address 1", "Address 2", "Address 3",
        "City", "State/Prov/Other", "Postal Code", "Telephone", "Ext", "Residential Ind",
        "Consignee Email", "Packaging Type", "Customs Value", "Weight", "Length", "Width",
        "Height", "Unit of Measure", "Description of Goods", "Documents of No Commercial Value",
        "GNIFC", "Pkg Decl Value", "Service", "Delivery Confirm", "Shipper Release", "Ret of Documents",
        "Saturday Deliver", "Carbon Neutral", "Large Package", "Addl handling", "Reference 1",
        "Reference 2", "Reference 3", "QV Notif 1-Addr", "QV Notif 1-Ship", "QV Notif 1-Excp",
        "QV Notif 1-Delv", "QV Notif 2-Addr", "QV Notif 2-Ship", "QV Notif 2-Excp", "QV Notif 2-Delv",
        "QV Notif 3-Addr", "QV Notif 3-Ship", "QV Notif 3-Excp", "QV Notif 3-Delv", "QV Notif 4-Addr",
        "QV Notif 4-Ship", "QV Notif 4-Excp", "QV Notif 4-Delv", "QV Notif 5-Addr", "QV Notif 5-Ship",
        "QV Notif 5-Excp", "QV Notif 5-Delv", "QV Notif Msg", "QV Failure Addr", "UPS Premium Care",
        "ADL Location ID", "ADL Media Type", "ADL Language", "ADL Notification Addr", "ADL Failure Addr",
        "ADL COD Value", "ADL Deliver to Addressee", "ADL Shipper Media Type", "ADL Shipper Language",
        "ADL Shipper Notification Addr", "ADL Direct Delivery Only", "Electronic Package Release Authentication",
        "Lithium Ion Alone", "Lithium Ion In Equipment", "Lithium Ion With_Equipment", "Lithium Metal Alone",
        "Lithium Metal In Equipment", "Lithium Metal With Equipment", "Weekend Commercial Delivery",
        "Dry Ice Weight", "Merchandise Description", "UPS SurePost®Limited Quantity/Lithium Battery"
    ]
    
    # Create an output DataFrame with the new header list.
    output_df = pd.DataFrame("", index=range(len(df)), columns=output_headers)
    
    # Mapping from input file to output based on provided rules:
    # 1. Shipping First Name + Shipping Last Name + Shipping Company -> Contact Name and Company or Name
    if {"Shipping First Name", "Shipping Last Name", "Shipping Company"}.issubset(df.columns):
        first_name = df["Shipping First Name"].fillna("").astype(str).str.strip()
        last_name = df["Shipping Last Name"].fillna("").astype(str).str.strip()
        company = df["Shipping Company"].fillna("").astype(str).str.strip()
        combined = (first_name + " " + last_name + " " + company).str.strip()
        output_df["Contact Name"] = combined
        output_df["Company or Name"] = combined

    # 2. Shipping Country Code -> Country
    if "Shipping Country Code" in df.columns:
        output_df["Country"] = df["Shipping Country Code"].fillna("").astype(str).str.strip()
    
    # 3. Shipping Address 1 -> Address 1
    if "Shipping Address 1" in df.columns:
        output_df["Address 1"] = df["Shipping Address 1"].fillna("").astype(str).str.strip()
    
    # 4. Shipping Address 2 -> Address 2
    if "Shipping Address 2" in df.columns:
        output_df["Address 2"] = df["Shipping Address 2"].fillna("").astype(str).str.strip()
    
    # 5. Shipping City -> City
    if "Shipping City" in df.columns:
        output_df["City"] = df["Shipping City"].fillna("").astype(str).str.strip()
    
    # 6. Shipping Province -> State/Prov/Other
    if "Shipping Province" in df.columns:
        output_df["State/Prov/Other"] = df["Shipping Province"].fillna("").astype(str).str.strip()
    
    # Convert full US state names to their 2-letter abbreviations if applicable.
    us_states = {
        'alabama': 'AL',
        'alaska': 'AK',
        'arizona': 'AZ',
        'arkansas': 'AR',
        'california': 'CA',
        'colorado': 'CO',
        'connecticut': 'CT',
        'delaware': 'DE',
        'florida': 'FL',
        'georgia': 'GA',
        'hawaii': 'HI',
        'idaho': 'ID',
        'illinois': 'IL',
        'indiana': 'IN',
        'iowa': 'IA',
        'kansas': 'KS',
        'kentucky': 'KY',
        'louisiana': 'LA',
        'maine': 'ME',
        'maryland': 'MD',
        'massachusetts': 'MA',
        'michigan': 'MI',
        'minnesota': 'MN',
        'mississippi': 'MS',
        'missouri': 'MO',
        'montana': 'MT',
        'nebraska': 'NE',
        'nevada': 'NV',
        'new hampshire': 'NH',
        'new jersey': 'NJ',
        'new mexico': 'NM',
        'new york': 'NY',
        'north carolina': 'NC',
        'north dakota': 'ND',
        'ohio': 'OH',
        'oklahoma': 'OK',
        'oregon': 'OR',
        'pennsylvania': 'PA',
        'rhode island': 'RI',
        'south carolina': 'SC',
        'south dakota': 'SD',
        'tennessee': 'TN',
        'texas': 'TX',
        'utah': 'UT',
        'vermont': 'VT',
        'virginia': 'VA',
        'washington': 'WA',
        'west virginia': 'WV',
        'wisconsin': 'WI',
        'wyoming': 'WY'
    }
    
    def convert_state(state):
        if state:
            state_lower = state.lower()
            return us_states.get(state_lower, state)
        return state
    
    output_df["State/Prov/Other"] = output_df["State/Prov/Other"].apply(convert_state)
    
    # 7. Shipping ZIP -> Postal Code
    if "Shipping ZIP" in df.columns:
        output_df["Postal Code"] = df["Shipping ZIP"].fillna("").astype(str).str.strip()
    
    # 8. Shipping Address Phone -> Telephone
    if "Shipping Address Phone" in df.columns:
        output_df["Telephone"] = df["Shipping Address Phone"].fillna("").astype(str).str.strip()
    
    # 9. Email -> Consignee Email
    if "Email" in df.columns:
        output_df["Consignee Email"] = df["Email"].fillna("").astype(str).str.strip()
    
    # 10. Total Weight -> Weight (divide by 1000)
    if "Total Weight" in df.columns:
        def convert_weight(x):
            try:
                if pd.isna(x) or x == "":
                    return ""
                return float(x) / 1000
            except:
                return ""
        output_df["Weight"] = df["Total Weight"].apply(convert_weight)
    
    # Fixed value mapping (applied for rows with data in Contact Name)
    mask = output_df["Contact Name"].notna() & (output_df["Contact Name"] != "")
    output_df.loc[mask, "Packaging Type"] = "2"
    output_df.loc[mask, "Unit of Measure"] = "KG"
    output_df.loc[mask, "Description of Goods"] = "Eyes Beauty Color Cosmetics"
    output_df.loc[mask, "Service"] = "7"
    
    # Delete duplicate rows based on "Contact Name", keeping the first occurrence.
    output_df = output_df.drop_duplicates(subset=["Contact Name"], keep="first")
    
    # Generate the output file name using the current Hong Kong date.
    hk_timezone = pytz.timezone("Asia/Hong_Kong")
    current_date_hk = datetime.now(hk_timezone).strftime("%y%m%d")
    output_file_name = f"UPS {current_date_hk}.csv"
    
    # Save the output DataFrame to a CSV file without the header.
    output_df.to_csv(output_file_name, index=False, header=False)
    
    return output_df, output_file_name

with gr.Blocks(title="Shipping - UPS") as demo:
    gr.Markdown("# Shipping - UPS")
    with gr.Row():
        file_input = gr.File(label="Upload Excel File with a UPS sheet")
        process_button = gr.Button("Process Data")
    with gr.Row():
        output_data = gr.DataFrame()
        output_file_component = gr.File(label="Download Processed File")
    
    process_button.click(fn=process_file, inputs=[file_input], outputs=[output_data, output_file_component])
    
    # Updated hyperlink block with separate sections for Shipping Tools and Administration Tools.
    gr.HTML(
        """
        <div style="text-align: center; font-size: 16px; margin-top: 20px;">
            <h3>Shipping Tools</h3>
            <a href="https://huggingface.co/spaces/leadingbridge/shipping-dhl-e-commerce">DHL</a> | 
            <a href="https://huggingface.co/spaces/leadingbridge/shipping-ec-ship">EC-Ship</a> | 
            <a href="https://huggingface.co/spaces/leadingbridge/shipping-fedex">Fedex</a> | 
            <a href="https://huggingface.co/spaces/leadingbridge/shipping-UPS">UPS</a>
        </div>
        <div style="text-align: center; font-size: 16px; margin-top: 20px;">
            <h3>Administration Tools</h3>
            <a href="https://huggingface.co/spaces/leadingbridge/email-template">Email Template</a> | 
            <a href="https://huggingface.co/spaces/leadingbridge/product-feed">Google Merchant</a> | 
            <a href="https://huggingface.co/spaces/leadingbridge/tss-order">Order Processing</a>
        </div>
        """
    )

demo.launch()