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"""
High Priority
Medium Priority
Low Priority
Delivery Alert
""" # Display the FullCalendar.js components.html(calendar_html, height=900, scrolling=False)