|
| 1 | +import streamlit as st |
| 2 | +import pandas as pd |
| 3 | +import altair as alt |
| 4 | +from snowflake.snowpark.context import get_active_session |
| 5 | +from snowflake.snowpark.functions import count_distinct,col,sum |
| 6 | +import snowflake.permissions as permission |
| 7 | + |
| 8 | +st.set_page_config(layout="wide") |
| 9 | +st.title("Where Are My Ski Goggles?") |
| 10 | +session = get_active_session() |
| 11 | + |
| 12 | +# def configure_reference_button_click(): |
| 13 | +# permission.request_reference("enrichment_table") |
| 14 | + |
| 15 | +# st.button("Request Reference", on_click=permission.request_reference, args=['enrichment_table'], key="single-valued") |
| 16 | +# st.button("Request Reference", on_click=configure_reference_button_click) |
| 17 | + |
| 18 | +def load_app(orders_table,site_recovery_table): |
| 19 | + with st.spinner("Loading lead time, order status, and supplier performance. Please wait..."): |
| 20 | + df = session.sql(f"SELECT t1.order_id,t2.ship_order_id,t1.material_name,t1.supplier_name, t1.quantity, t1.cost, t2.status, t2.lat, t2.lon FROM {orders_table} as t1 INNER JOIN MFG_SHIPPING as t2 ON t2.ORDER_ID = t1.ORDER_ID ORDER BY t1.order_id") |
| 21 | + session.call("billing_event",df.count()) |
| 22 | + df_order_status = df.group_by('status').agg(count_distinct('order_id').as_('TOTAL RECORDS')).order_by('status').to_pandas() |
| 23 | + |
| 24 | + df_cal_lead_time = session.sql(f"SELECT t1.order_id,t2.ship_order_id,t1.material_name,t1.supplier_name,t1.quantity,t1.cost,t2.status,t2.lat,t2.lon,cal_lead_time(t1.process_supply_day,t2.duration,t2.recovery_days) as lead_time FROM {orders_table} as t1 INNER JOIN (SELECT order_id, ship_order_id, status, duration, MFG_SHIPPING.lat, MFG_SHIPPING.lon, IFF({site_recovery_table}.recovery_weeks * 7::int = {site_recovery_table}.recovery_weeks * 7,{site_recovery_table}.recovery_weeks * 7,0) as recovery_days from MFG_SHIPPING LEFT OUTER JOIN {site_recovery_table} ON MFG_SHIPPING.lon = {site_recovery_table}.lon AND MFG_SHIPPING.lat = {site_recovery_table}.lat) as t2 ON t2.ORDER_ID = t1.ORDER_ID ORDER BY t1.order_id") |
| 25 | + df_supplier_perf = df_cal_lead_time.group_by('supplier_name').agg(sum(col('lead_time')).as_('TOTAL LEAD TIME')).sort('TOTAL LEAD TIME', ascending=True).limit(20).to_pandas() |
| 26 | + df_lead_time = df_cal_lead_time.select('order_id','lead_time').sort('order_id', ascending=True).to_pandas() |
| 27 | + |
| 28 | + with st.container(): |
| 29 | + col1,col2 = st.columns(2,gap='small') |
| 30 | + with col1: |
| 31 | + # Display Lead Time Status chart |
| 32 | + st.subheader("Lead Time Status") |
| 33 | + lead_time_base = alt.Chart(df_lead_time).encode(alt.X("ORDER_ID", title="ORDER ID", sort=None)) |
| 34 | + lead_time_base_bars = lead_time_base.mark_bar().encode( |
| 35 | + color=alt.value("#249DC9"), |
| 36 | + y=alt.Y("LEAD_TIME", title="LEAD TIME DAYS") |
| 37 | + ) |
| 38 | + line = alt.Chart(pd.DataFrame({'y': [60]})).mark_rule(color='rgb(249,158,54)').encode(y='y') |
| 39 | + lead_time_chart = alt.layer(lead_time_base_bars) |
| 40 | + st.altair_chart(lead_time_chart + line, use_container_width=True) |
| 41 | + |
| 42 | + def color_lead_time(val): |
| 43 | + return f'background-color: rgb(249,158,54)' |
| 44 | + |
| 45 | + with col2: |
| 46 | + # Underlying Data |
| 47 | + st.subheader("Orders with Lead Time Status >= 60days") |
| 48 | + df_lead_time_60_days = df_cal_lead_time.select('lead_time','order_id','ship_order_id','material_name','supplier_name','quantity','cost').filter(col('lead_time') > 60).sort('lead_time').to_pandas() |
| 49 | + df_lead_time_60_days['LEAD_TIME'] = df_lead_time_60_days['LEAD_TIME'].astype('int') |
| 50 | + st.dataframe(df_lead_time_60_days.style.applymap(color_lead_time, subset=['LEAD_TIME'])) |
| 51 | + |
| 52 | + with st.container(): |
| 53 | + col1,col2 = st.columns(2,gap='small') |
| 54 | + with col1: |
| 55 | + # Display Supplier Performance |
| 56 | + st.subheader("Supplier Performance") |
| 57 | + supplier_perf_base = alt.Chart(df_supplier_perf).encode(alt.X("SUPPLIER_NAME:N", title="SUPPLIER NAME", sort=None)) |
| 58 | + supplier_perf_base_bars = supplier_perf_base.mark_bar().encode( |
| 59 | + color=alt.value("#249DC9"), |
| 60 | + y=alt.Y("TOTAL LEAD TIME", title="TOTAL LEAD TIME") |
| 61 | + ) |
| 62 | + supplier_perf_chart = alt.layer(supplier_perf_base_bars) |
| 63 | + st.altair_chart(supplier_perf_chart, use_container_width=True) |
| 64 | + |
| 65 | + # Underlying Data |
| 66 | + # st.subheader("Underlying Data") |
| 67 | + # st.dataframe(df_lead_time) |
| 68 | + |
| 69 | + with col2: |
| 70 | + # Display Purchase Order Status |
| 71 | + st.subheader("Purchase Order Status") |
| 72 | + order_status_base = alt.Chart(df_order_status).encode(alt.X("STATUS", sort=['Order_confirmed','Shipped','In_Transit','Out_for_delivery','Delivered'])) |
| 73 | + order_status_base_bars = order_status_base.mark_bar().encode( |
| 74 | + color=alt.value("#249DC9"), |
| 75 | + y=alt.Y("TOTAL RECORDS", title="TOTAL RECORDS") |
| 76 | + ) |
| 77 | + order_status_chart = alt.layer(order_status_base_bars) |
| 78 | + st.altair_chart(order_status_chart, use_container_width=True) |
| 79 | + |
| 80 | + # Underlying Data |
| 81 | + # st.subheader("Underlying Data") |
| 82 | + # st.dataframe(df_order_status) |
| 83 | + |
| 84 | +if ('merge' in st.session_state and st.session_state.merge): |
| 85 | + src_db = st.session_state.src_db |
| 86 | + src_schema = st.session_state.src_schema |
| 87 | + src_orders_table = st.session_state.src_orders_table |
| 88 | + src_site_recovery_table = st.session_state.src_site_recovery_table |
| 89 | + orders_table = f"{src_db}.{src_schema}.{src_orders_table}" |
| 90 | + site_recovery_table = f"{src_db}.{src_schema}.{src_site_recovery_table}" |
| 91 | + load_app(orders_table,site_recovery_table) |
| 92 | +else: |
| 93 | + with st.expander("Select Orders and Site Recovery Datasets"): |
| 94 | + src_db = st.text_input('Database',value='DASH_DB') |
| 95 | + src_schema = st.text_input('Schema',value='DASH_SCHEMA') |
| 96 | + src_orders_table = st.text_input('Orders Table',value='MFG_ORDERS') |
| 97 | + src_site_recovery_table = st.text_input('Site Recovery Table',value='MFG_SITE_RECOVERY') |
| 98 | + orders_table = "" |
| 99 | + site_recovery_table = "" |
| 100 | + if st.button("Merge Orders with Shipping Data"): |
| 101 | + try: |
| 102 | + st.session_state.merge = 'merge' |
| 103 | + st.session_state.src_db = src_db |
| 104 | + st.session_state.src_schema = src_schema |
| 105 | + st.session_state.src_orders_table = src_orders_table |
| 106 | + st.session_state.src_site_recovery_table = src_site_recovery_table |
| 107 | + orders_table = f"{src_db}.{src_schema}.{src_orders_table}" |
| 108 | + site_recovery_table = f"{src_db}.{src_schema}.{src_site_recovery_table}" |
| 109 | + except Exception as e: |
| 110 | + st.write(f"Source datasets in {src_db}.{src_schema} not found. Cannot proceed!") |
| 111 | + st.write(e) |
| 112 | + |
| 113 | + if len(orders_table) > 0: |
| 114 | + load_app(orders_table,site_recovery_table) |
0 commit comments