File size: 6,179 Bytes
e573ff3
 
 
 
 
2f60b4d
e573ff3
a7d00db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2626b66
 
 
 
 
a7d00db
 
 
 
 
 
 
 
 
 
 
 
 
2d5d3c0
a7d00db
 
 
 
 
 
 
 
 
 
e8b72fe
 
a7d00db
 
 
2626b66
a7d00db
2626b66
a7d00db
 
cab1211
 
a7d00db
 
2626b66
a7d00db
2626b66
 
a7d00db
2626b66
a7d00db
 
 
 
2d5d3c0
a7d00db
2d5d3c0
 
 
 
 
 
 
 
1ecc1c6
a7d00db
 
1ecc1c6
 
 
b25d7a1
 
 
6c74bda
 
b25d7a1
 
 
 
 
6c74bda
1ecc1c6
a7d00db
 
30f3a3c
 
a7d00db
1ecc1c6
 
 
 
 
 
 
a7d00db
30f3a3c
 
 
 
 
 
 
 
 
 
 
 
 
1ecc1c6
30f3a3c
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
import streamlit as st
import pandas as pd
import altair as alt

st.set_page_config(page_title="Shipment Monitoring Dashboard", layout="wide")
st.title("Shipment Monitoring Dashboard")

tabs = st.tabs(["Main Dashboard", "Last Mile Summary"])

with tabs[0]:
    uploaded_file = st.file_uploader("Upload your Excel file", type=["xlsx"], key="main_upload")

    if uploaded_file:
        df = pd.read_excel(uploaded_file, sheet_name=0)

        # Rename columns
        df.columns = ['MAWB', 'MAWB Serial Number', 'Injection Gateway', 'Clearance Port', 'Latest Status',
                      'Cartons', 'Packages', 'Weights', 'Not online packages count', 'ETD', 'ETA', 'ATD', 'ATA',
                      'Last Mile Carrier', 'Readynotice has been notified', 'Vehicle has been arranged',
                      'Pick-upcompletedfrom', 'WH-IN Scan', 'Cargo Ready', 'Ship Out', 'Note',
                      'Exception Note', 'Exception Note Description']

        # Add status column
        def determine_status(row):
            if pd.isna(row['WH-IN Scan']):
                return "Pending"
            elif pd.isna(row['Cargo Ready']):
                return "WH-IN"
            elif pd.isna(row['Ship Out']):
                return "Cargo Ready"
            else:
                return "Ship Out"

        df['Shipment Status'] = df.apply(determine_status, axis=1)
        df['ETA'] = pd.to_datetime(df['ETA'])
        df['ATA'] = pd.to_datetime(df['ATA'])

        # Fallback date: ATA if available, otherwise ETA
        df['Final Arrival Date'] = df['ATA'].fillna(df['ETA'])
        df['Final Arrival Date'] = pd.to_datetime(df['Final Arrival Date']).dt.date

        # Filter for Injection Gateway
        injection_gateways = df['Injection Gateway'].dropna().unique().tolist()
        selected_gateway = st.selectbox("Filter by Injection Gateway", options=["All"] + injection_gateways)
        if selected_gateway != "All":
            df = df[df['Injection Gateway'] == selected_gateway]

        # Filter by ETA date range
        st.subheader("Filter by ETA Date Range")
        min_date, max_date = df['ETA'].min(), df['ETA'].max()
        start_date, end_date = st.date_input("Select ETA date range:", [min_date, max_date], min_value=min_date, max_value=max_date)
        df = df[(df['ETA'] >= pd.to_datetime(start_date)) & (df['ETA'] <= pd.to_datetime(end_date))]

        # Shipment status distribution
        st.subheader("Shipment Status Distribution")
        status_order = ["Pending", "WH-IN", "Cargo Ready", "Ship Out"]
        status_counts = df['Shipment Status'].value_counts().reindex(status_order).reset_index()
        status_counts.columns = ['Shipment Status', 'Count']
        status_counts = status_counts.dropna()

        chart = alt.Chart(status_counts).mark_bar().encode(
            x=alt.X('Shipment Status', sort=status_order),
            y='Count',
            color='Shipment Status',
            tooltip=['Shipment Status', 'Count']
        ).properties(height=300)

        st.altair_chart(chart, use_container_width=True)

        # Volume by final arrival date (ATA preferred, fallback to ETA)
        st.subheader("Shipment Volume by ETA")
        volume_by_arrival = df.groupby('Final Arrival Date').agg({
            'MAWB': 'count',
            'Cartons': 'sum',
            'Packages': 'sum',
            'Weights': 'sum'
        }).reset_index().rename(columns={'MAWB': 'Shipment Count'})

        st.dataframe(volume_by_arrival, use_container_width=True)

        line_chart = alt.Chart(volume_by_arrival).mark_line(point=True).encode(
            x='Final Arrival Date:T',
            y='Cartons:Q',
            tooltip=['Final Arrival Date:T', 'Shipment Count:Q', 'Cartons:Q', 'Packages:Q', 'Weights:Q']
        ).properties(height=400)

        st.altair_chart(line_chart, use_container_width=True)

        # Status filter before detail view
        st.subheader("Shipment Detail View by ETA")
        status_options = ["All"] + status_order
        selected_status = st.radio("Select a Shipment Status to filter the details below:", options=status_options, index=0)

        if selected_status == "All":
            filtered_df = df.copy()
        else:
            filtered_df = df[df['Shipment Status'] == selected_status]

        sorted_df = filtered_df[['MAWB', 'ETA', 'ATA', 'Shipment Status', 'Cartons', 'Last Mile Carrier']].sort_values(by='ETA')
        st.dataframe(sorted_df, use_container_width=True)

        # Add download as Excel button
        import io

        excel_buffer = io.BytesIO()
        with pd.ExcelWriter(excel_buffer, engine='xlsxwriter') as writer:
            sorted_df.to_excel(writer, index=False, sheet_name='Shipment Details')
        excel_data = excel_buffer.getvalue()

        st.download_button(
            label="📥 Download Shipment Details as Excel",
            data=excel_data,
            file_name="shipment_details.xlsx",
            mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        )

with tabs[1]:
    st.header("Upload CTN File for Last Mile Summary")
    ctn_files = st.file_uploader("Upload one or more Excel files with Last Mile Service", 
                                  type=["xlsx"], key="ctn_upload", accept_multiple_files=True)

    if ctn_files:
        df_list = []
        for file in ctn_files:
            df_part = pd.read_excel(file, sheet_name=0)
            df_list.append(df_part)

        df_ctn = pd.concat(df_list, ignore_index=True)

        # Columns of interest
        carton_col = "No. Large box"
        last_mile_col = "Last mile service"

        # ✅ Count unique cartons by last mile service
        st.subheader("Unique Cartons by Last Mile Service")
        if carton_col in df_ctn.columns and last_mile_col in df_ctn.columns:
            unique_summary = (
                df_ctn.groupby(last_mile_col)[carton_col]
                .nunique()
                .reset_index(name="Unique Carton Count")
            )
            st.dataframe(unique_summary, use_container_width=True)
        else:
            st.warning(f"Columns '{carton_col}' or '{last_mile_col}' not found in uploaded file(s).")