AutoDashboard / app.py
joycecast's picture
Update app.py
30f3a3c verified
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).")