import streamlit as st
import json
import requests
import streamlit.components.v1 as components
import datetime
st.set_page_config(
page_title="Key Innovations Inc.",
page_icon="https://tscstatic.keyinnovations.ca/logo/logo_1T895ONEIG.png",
layout="wide"
)
st.image("https://tscstatic.keyinnovations.ca/logo/logo_1T895ONEIG.png", width=150)
#st.title('Syncore Calendar')
st.subheader('Syncore Calendarπ
')
# API Endpoint
ALL_JOBS_URL = "https://api.syncore.app/v2/orders/jobs?date_from={}&date_to={}&limit=1000"
SALES_ORDERS_URL = "https://api.syncore.app/v2/orders/jobs/{}/salesorders"
# API Headers
HEADERS = {
"x-api-key": "69c23811-1073-4c1c-9902-8d552703c460",
"Accept": "application/json"
}
# Function to fetch jobs for the selected month with pagination
def fetch_jobs(selected_year, selected_month):
first_day = datetime.date(selected_year, selected_month, 1)
last_day = (first_day + datetime.timedelta(days=32)).replace(day=1) - datetime.timedelta(days=1)
date_from, date_to = first_day.strftime("%Y-%m-%d"), last_day.strftime("%Y-%m-%d")
all_jobs = []
page = 1
while True:
url = f"https://api.syncore.app/v2/orders/jobs?date_from={date_from}&date_to={date_to}&limit=100&page={page}"
response = requests.get(url, headers=HEADERS)
if response.status_code == 200:
data = response.json()
new_jobs = data.get("jobs", [])
if not new_jobs:
break
all_jobs.extend(new_jobs)
page += 1
else:
st.error(f"API Error (Fetching Jobs): {response.status_code} - {response.text}")
break
return [job["id"] for job in all_jobs]
# Function to fetch sales orders for jobs
def fetch_sales_orders_for_jobs(job_ids):
orders = []
priority_colors = {"High": "#dc2626", "Medium": "#2563eb", "Low": "#22c55e"}
today = datetime.date.today()
processed_alerts = set()
for job_id in job_ids:
url = SALES_ORDERS_URL.format(job_id)
response = requests.get(url, headers=HEADERS)
if response.status_code == 200:
data = response.json()
if "salesorders" in data:
for order in data["salesorders"]:
job_created = order.get("date", "Not Available")
estimated_delivery_date = order.get("estimated_delivery_date", "Not Available")
job_number = order.get("job_number", "NA")
# Extract supplier names
supplier_names = list({
item["supplier"]["name"]
for item in order.get("line_items", []) if item.get("supplier")
})
if len(supplier_names) < 2:
#print(len(supplier_names))
continue
# Assign priority based on estimated delivery date
priority = "Low"
if estimated_delivery_date != "Not Available":
estimated_date = datetime.datetime.strptime(estimated_delivery_date, "%Y-%m-%d").date()
days_until_delivery = (estimated_date - today).days
if days_until_delivery <= 15:
priority = "High"
elif 16 <= days_until_delivery <= 30:
priority = "Medium"
# Add job event
if job_created != "Not Available":
job_event = {
"id": f"{job_number}-job",
"title": f"{job_number}
π Suppliers: {', '.join(supplier_names)}
π
{job_created} β π {estimated_delivery_date}",
"start": job_created,
"color": priority_colors.get(priority, "#2563eb")
}
orders.append(job_event)
# Add delivery alert
if estimated_delivery_date != "Not Available" and job_id not in processed_alerts:
delivery_alert_event = {
"id": f"{job_number}-alert",
"title": f"{job_number}
π¨ Delivery Day",
"start": estimated_delivery_date,
"color": "#ff9800"
}
orders.append(delivery_alert_event)
processed_alerts.add(job_id)
else:
st.error(f"API Fetch Error (Sales Orders for Job {job_id}): {response.status_code}")
return orders
# Handle Calendar Month Switching
if "selected_month" not in st.session_state:
today = datetime.date.today()
st.session_state.selected_year = today.year
st.session_state.selected_month = today.month
params = st.query_params
if "year" in params and "month" in params:
st.session_state.selected_year = int(params["year"][0])
st.session_state.selected_month = int(params["month"][0])
# Show loading animation
with st.spinner("Fetching jobs... Please wait."):
job_ids = fetch_jobs(st.session_state.selected_year, st.session_state.selected_month)
with st.spinner("Processing sales orders... This may take up to 60 seconds"):
orders = fetch_sales_orders_for_jobs(job_ids)
st.balloons()
events_json = json.dumps(orders)
# Calendar with Priority Legend & Delivery Alerts
calendar_html = f"""