Skip to content

Commit bd96add

Browse files
committed
Initial version
1 parent 110442e commit bd96add

File tree

7 files changed

+220
-0
lines changed

7 files changed

+220
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
connection.json
2+
.DS_Store

app/V1/libraries/environment.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: sf_env
2+
channels:
3+
- snowflake
4+
dependencies:
5+
- snowflake-native-apps-permission

app/V1/libraries/procs.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def billing_event(session,number_of_rows):
2+
import time
3+
dts = int(time.time() *1000)
4+
# session.sql(f"CALL SYSTEM$CREATE_BILLING_EVENT('NUM_ROWS', '', {dts}, {dts}, {number_of_rows * .1}, '', '')").collect()
5+
return "Ok"

app/V1/libraries/streamlit.py

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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)

app/V1/libraries/udf.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
def cal_distance(lat1,lon1,lat2,lon2):
2+
import math
3+
radius = 3959 # miles == 6371 km
4+
dlat = math.radians(lat2-lat1)
5+
dlon = math.radians(lon2-lon1)
6+
a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
7+
* math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
8+
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
9+
d = radius * c
10+
return d
11+
12+
# process_supply_day + duration + recovery_weeks * 7 (days)
13+
def cal_lead_time(i,j,k):
14+
return i + j + k

app/V1/manifest.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#version identifier
2+
manifest_version: 1
3+
4+
version:
5+
name: V1
6+
label: Version One
7+
comment: The first version of the application
8+
9+
#artifacts that are distributed from this version of the package
10+
artifacts:
11+
setup_script: scripts/setup.sql
12+
default_streamlit: app_instance_schema.streamlit
13+
extension_code: true
14+
15+
#runtime configuration for this version
16+
configuration:
17+
log_level: debug
18+
trace_level: off
19+
20+
# references: # optional
21+
# - enrichment_table:
22+
# label: "Enrich Orders" # required subfield
23+
# # description is a required subfield
24+
# description: "Select orders table"
25+
# privileges: # required subfield, must be length >= 1
26+
# - SELECT
27+
# - INSERT
28+
# - UPDATE
29+
# object_type: Table # required subfield
30+
# multi_valued: true # optional (default: false)
31+
# register_callback: config.register_reference # required

app/V1/scripts/setup.sql

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
-- =================
2+
-- This script runs when the app is installed
3+
-- =================
4+
5+
-- Create Application Role and Schema
6+
create application role if not exists app_instance_role;
7+
create or alter versioned schema app_instance_schema;
8+
9+
-- Share data
10+
create or replace view app_instance_schema.MFG_SHIPPING as select * from shared_content_schema.MFG_SHIPPING;
11+
12+
-- Create Streamlit app
13+
create or replace streamlit app_instance_schema.streamlit from '/libraries' main_file='streamlit.py';
14+
15+
-- Create UDFs
16+
create or replace function app_instance_schema.cal_lead_time(i int, j int, k int)
17+
returns float
18+
language python
19+
runtime_version = '3.8'
20+
packages = ('snowflake-snowpark-python')
21+
imports = ('/libraries/udf.py')
22+
handler = 'udf.cal_lead_time'
23+
24+
;create or replace function app_instance_schema.cal_distance(slat float,slon float,elat float,elon float)
25+
returns float
26+
language python
27+
runtime_version = '3.8'
28+
packages = ('snowflake-snowpark-python','pandas','scikit-learn==1.1.1')
29+
imports = ('/libraries/udf.py')
30+
handler = 'udf.cal_distance'
31+
;
32+
33+
-- Create Stored Procedure
34+
create or replace procedure app_instance_schema.billing_event(number_of_rows int)
35+
returns string
36+
language python
37+
runtime_version = '3.8'
38+
packages = ('snowflake-snowpark-python')
39+
imports = ('/libraries/procs.py')
40+
handler = 'procs.billing_event'
41+
;
42+
43+
-- Grant usage and permissions on objects
44+
grant usage on schema app_instance_schema to application role app_instance_role;
45+
grant usage on function app_instance_schema.cal_lead_time(int,int,int) to application role app_instance_role;
46+
grant usage on procedure app_instance_schema.billing_event(int) to application role app_instance_role;
47+
grant usage on function app_instance_schema.cal_distance(float,float,float,float) to application role app_instance_role;
48+
grant SELECT on view app_instance_schema.MFG_SHIPPING to application role app_instance_role;
49+
grant usage on streamlit app_instance_schema.streamlit to application role app_instance_role;

0 commit comments

Comments
 (0)