import streamlit as st import pandas as pd st.set_page_config( page_title="Key Innovations Inc.", page_icon="https://tscstatic.keyinnovations.ca/logo/logo_1T895ONEIG.png" ) st.image("https://tscstatic.keyinnovations.ca/logo/logo_1T895ONEIG.png", width=150) st.title('Quoting System') st.subheader('Key Innovation Inc.') #Option to select a clothing method. option = st.segmented_control( "Select an option:", ["Embroidery", "Screen Print", "Embroidery & Screen Print"] ) #Embroidory Pricing Dataset data = { "Quantity": ["0-11", "12-17", "18-23", "24-35", "36-59", "60-119", "120-239", "240-599","600+"], "1-1,000": [10.00, 5.00, 4.00, 3.25, 2.75, 2.25, 2.00, 1.75, 1.50], "1,000-2,000": [11.00, 5.50, 4.40, 3.60, 3.05, 2.53, 2.27, 2.01, 1.75], "2,001-3,000": [12.00, 6.00, 4.80, 3.95, 3.35, 2.81, 2.54, 2.27, 2.00], "3,001-4,000": [13.00, 6.50, 5.20, 4.30, 3.65, 3.09, 2.81, 2.53, 2.25], "4,001-5,000": [14.00, 7.00, 5.60, 4.65, 3.95, 3.37, 3.08, 2.79, 2.50], "5,001-6,000": [15.00, 7.50, 6.00, 5.00, 4.25, 3.65, 3.35, 3.05, 2.75], "6,001-7,000": [16.00, 8.00, 6.40, 5.35, 4.55, 3.93, 3.62, 3.31, 3.00], "7,001-8,000": [17.00, 8.50, 6.80, 5.70, 4.85, 4.21, 3.89, 3.57, 3.25], "8,001-9,000": [18.00, 9.00, 7.20, 6.05, 5.15, 4.49, 4.16, 3.83, 3.50], "9,001-10,000": [19.00, 9.50, 7.60, 6.40, 5.45, 4.77, 4.43, 4.09, 3.75], "10,001-11,000": [20.00, 10.00, 8.00, 6.75, 5.75, 5.05, 4.70, 4.35, 4.00], "11,001-12,000": [21.00, 10.50, 8.40, 7.10, 6.05, 5.33, 4.97, 4.61, 4.25], "12,001-13,000": [22.00, 11.00, 8.80, 7.45, 6.35, 5.61, 5.24, 4.87, 4.50], "13,001-14,000": [23.00, 11.50, 9.20, 7.80, 6.65, 5.89, 5.51, 5.13, 4.75], "14,001-15,000": [24.00, 12.00, 9.60, 8.15, 6.95, 6.17, 5.78, 5.39, 5.00], "15,001-16,000": [25.00, 12.50, 10.00, 8.50, 7.25, 6.45, 6.05, 5.65, 5.25], "16,001-17,000": [26.00, 13.00, 10.40, 8.85, 7.55, 6.73, 6.32, 5.91, 5.50], "17,001-18,000": [27.00, 13.50, 10.80, 9.20, 7.85, 7.01, 6.59, 6.17, 5.75], "18,001-19,000": [28.00, 14.00, 11.20, 9.55, 8.15, 7.29, 6.86, 6.43, 6.00], "19,001-20,000": [29.00, 14.50, 11.60, 9.90, 8.45, 7.57, 7.13, 6.69, 6.25] } df = pd.DataFrame(data) net_value = 0 if option == 'Embroidery': if "entries" not in st.session_state: st.session_state.entries = [] st.subheader("Enter Item Details") col1, col2, col3 = st.columns(3) with col1: quantity = st.number_input("Enter Quantity", min_value=1, step=1, key="quantity") with col2: stitch_count = st.selectbox( "Select Stitch Count", options=list(df.columns[1:]), key="stitch_count" ) with col3: item_price = st.number_input('Item Cost (Fixed)', min_value=0.0, step=0.01, key="item_price") use_manual_margin = st.checkbox("Use Manual Margin") # Ensure selected_range & stitch_price are always calculated selected_range = next((key for key, val in { "0-11": range(0, 12), "12-17": range(12, 18), "18-23": range(18, 24), "24-35": range(24, 36), "36-59": range(36, 60), "60-119": range(60, 120), "120-239": range(120, 240), "240-599": range(240, 600), "600+": range(601, 2000) }.items() if quantity in val), "600+") stitch_price = df[df["Quantity"] == selected_range][stitch_count].values[0] # Calculate Net Value Before Margin Selection net_value = quantity * (item_price + stitch_price) if use_manual_margin: margin_percentage = st.slider("Select Margin (%)", min_value=1.0, max_value=99.0, step=0.5, value=60.0, format="%.2f%%") margin = margin_percentage / 100 # Manual margin stored as decimal margin_display = f"{margin_percentage:.2f}%" # Display the exact selected percentage else: # Automatic Margin Selection margin_data = [ (0, 0.4), (150, 0.5), (210, 0.525), (275, 0.55), (345, 0.575), (840, 0.6), (1563, 0.625), (2600, 0.65), (4290, 0.66), (6030, 0.67) ] margin = next((rate for threshold, rate in reversed(margin_data) if net_value >= threshold), 0.67) margin_display = f"{margin * 100:.2f}%" # Convert automatic margin if st.button("➕ Add Entry"): if quantity and stitch_count and item_price: total_selling_price = net_value / (1 - margin) unit_selling_price = total_selling_price / quantity entry = { "Quantity": quantity, "Stitch Count": stitch_count, "Stitch Price": stitch_price, "Total Net Cost": f"${net_value:,.2f}", "Margin": margin_display, "Unit Selling Price": f"${unit_selling_price:.2f}", "Total Selling Price": f"${total_selling_price:.2f}" } st.session_state.entries.append(entry) if st.session_state.entries: st.subheader("Pricing Breakdown") for i, entry in enumerate(st.session_state.entries): st.text("==========================================================================") st.write(f"### Entry {i+1}") col1, col2, col3 = st.columns(3) with col1: st.metric(label="📌 Quantity", value=entry["Quantity"]) with col2: #st.metric(label="🪡 Stitch Count", value=entry["Stitch Count"]) st.metric(label="🪡 Stitch Price (per unit)", value=entry["Stitch Price"]) with col3: st.metric(label="💰 Total Net Cost", value=entry["Total Net Cost"]) col1, col2, col3 = st.columns(3) with col1: st.metric(label="📈 Margin", value=entry["Margin"]) #st.metric(label="📊 Margin", value=f"{(entry['Margin']) * 100:.2f}%") with col2: st.metric(label=f"📊 Unit Price", value=entry["Unit Selling Price"]) with col3: st.metric(label="💰 Total Selling Price", value=entry["Total Selling Price"]) col1, col2 = st.columns(2) with col1: if st.button(f"❌ Delete {i+1}", key=f"delete_{i}"): del st.session_state.entries[i] st.rerun() st.text("===========================================================================") if st.button("🔄 Reset Entries"): st.session_state.entries = [] st.rerun() elif option == 'Screen Print': #Pricing data for screenprint. pricing_data = { "1-Color ScreenPrint": pd.DataFrame({ "Qty": ["below 6", "6 to 12", "13 - 18", "19 - 24", "25 - 36", "37 - 48","49 - 72", "73 - 96", "97 - 144", "145 - 288", "289 - 500", "Above 500"], "4x4": [7.42, 4.61, 4.13, 3.53, 2.88, 2.49, 2.13, 1.79, 1.51, 1.19, 0.89, 0.73], "12x12": [10.47, 6.17, 5.45, 4.51, 3.55, 2.96, 2.49, 1.96, 1.59, 1.35, 1.05, 0.85], "14x16": [11.87, 7.27, 6.34, 5.19, 4.13, 3.53, 3.02, 2.47, 2.08, 1.75, 1.35, 1.14], "Darks": [0.35, 0.35, 0.35, 0.35, 0.35, 0.25, 0.25, 0.25, 0.25, 0.15, 0.15, 0.15], "Fleece": [0.6, 0.6, 0.6, 0.6, 0.6, 0.5, 0.5, 0.5, 0.5, 0.45, 0.45, 0.45], "90% Poly+": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.3, 0.3, 0.3], "Sleeves & Legs":[0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40] }), "2-Color ScreenPrint": pd.DataFrame({ "Qty": ["below 6", "6 to 12", "13 - 18", "19 - 24", "25 - 36", "37 - 48","49 - 72", "73 - 96", "97 - 144", "145 - 288", "289 - 500", "Above 500"], "4x4": [11.0, 7.16, 6.17, 4.91, 3.93, 3.43, 2.84, 2.30, 1.83, 1.58, 1.19, 1.0], "12x12": [16.74, 10.40, 8.77, 6.76, 5.28, 4.64, 3.74, 2.81, 2.30, 1.83, 1.48, 1.23], "14x16": [19.29, 12.69, 10.55, 7.93, 6.34, 5.55, 4.54, 3.23, 2.71, 2.29, 1.95, 1.73], "Darks": [0.45, 0.45, 0.45, 0.45, 0.45, 0.35, 0.35, 0.35, 0.35, 0.25, 0.25, 0.25], "Fleece": [0.6, 0.6, 0.6, 0.6, 0.6, 0.5, 0.5, 0.5, 0.5, 0.45, 0.45, 0.45], "90% Poly+": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.3, 0.3, 0.3], "Sleeves & Legs":[0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40] }), "3-Color ScreenPrint": pd.DataFrame({ "Qty": ["below 6", "6 to 12", "13 - 18", "19 - 24", "25 - 36", "37 - 48","49 - 72", "73 - 96", "97 - 144", "145 - 288", "289 - 500", "Above 500"], "4x4": [16.11, 10.13, 8.53, 6.58, 5.25, 4.35, 3.73, 3.04, 2.58, 2.02, 1.72, 1.51], "12x12": [25.81, 15.87, 12.88, 9.72, 7.71, 6.32, 5.26, 3.82, 3.17, 2.75, 2.31, 2.01], "14x16": [29.55, 17.87, 14.91, 11.29, 9.09, 7.65, 6.27, 4.77, 4.05, 3.40, 3.0, 2.56], "Darks": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.35, 0.35, 0.35], "Fleece": [0.6, 0.6, 0.6, 0.6, 0.6, 0.5, 0.5, 0.5, 0.5, 0.45, 0.45, 0.45], "90% Poly+": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.3, 0.3, 0.3], "Sleeves & Legs":[0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40] }), "4-Color ScreenPrint": pd.DataFrame({ "Qty": ["below 6", "6 to 12", "13 - 18", "19 - 24", "25 - 36", "37 - 48","49 - 72", "73 - 96", "97 - 144", "145 - 288", "289 - 500", "Above 500"], "4x4": [18.88, 11.74, 9.95, 7.72, 6.07, 5.18, 4.37, 3.71, 3.21, 2.43, 2.29, 2.06], "12x12": [30.81, 18.37, 15.36, 11.86, 9.2, 7.82, 6.27, 4.86, 4.07, 3.13, 2.75, 2.62], "14x16": [35.8, 21.26, 18.58, 15.17, 10.8, 9.34, 7.62, 5.99, 5.19, 3.92, 3.55, 3.33], "Darks": [0.65, 0.65, 0.65, 0.65, 0.65, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45], "Fleece": [0.6, 0.6, 0.6, 0.6, 0.6, 0.5, 0.5, 0.5, 0.5, 0.45, 0.45, 0.45], "90% Poly+": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.3, 0.3, 0.3], "Sleeves & Legs":[0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40] }), "5-Color ScreenPrint": pd.DataFrame({ "Qty": ["below 6", "6 to 12", "13 - 18", "19 - 24", "25 - 36", "37 - 48","49 - 72", "73 - 96", "97 - 144", "145 - 288", "289 - 500", "Above 500"], "4x4": [23.87, 14.02, 11.79, 9.04, 7.09, 6.05, 5.09, 4.28, 3.76, 2.84, 2.68, 2.54], "12x12": [39.36, 22.53, 18.66, 13.93, 10.88, 9.34, 7.26, 5.87, 4.88, 3.56, 3.15, 3.10], "14x16": [46.2, 26.02, 22.05, 17.14, 12.87, 11.05, 9.00, 7.21, 6.02, 4.51, 4.02, 3.74], "Darks": [0.8, 0.8, 0.8, 0.8, 0.8, 0.65, 0.65, 0.65, 0.65, 0.55, 0.55, 0.55], "Fleece": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.40, 0.40, 0.40], "90% Poly+": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.3, 0.3, 0.3], "Sleeves & Legs":[0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40] }), "6-Color ScreenPrint": pd.DataFrame({ "Qty": ["below 6", "6 to 12", "13 - 18", "19 - 24", "25 - 36", "37 - 48","49 - 72", "73 - 96", "97 - 144", "145 - 288", "289 - 500", "Above 500"], "4x4": [28.07, 16.41, 13.69, 10.36, 8.15, 6.89, 5.45, 4.95, 4.33, 3.35, 3.07, 2.94], "12x12": [46.62, 26.69, 22.32, 14.22, 12.60, 10.85, 8.35, 6.92, 5.73, 4.07, 3.47, 3.33], "14x16": [55.03, 30.88, 25.52, 19.03, 14.98, 12.74, 10.34, 8.53, 6.96, 5.18, 4.42, 4.21], "Darks": [0.9, 0.9, 0.9, 0.9, 0.9, 0.75, 0.75, 0.75, 0.75, 0.65, 0.65, 0.65], "Fleece": [0.6, 0.6, 0.6, 0.6, 0.6, 0.5, 0.5, 0.5, 0.5, 0.45, 0.45, 0.45], "90% Poly+": [0.55, 0.55, 0.55, 0.55, 0.55, 0.45, 0.45, 0.45, 0.45, 0.3, 0.3, 0.3], "Sleeves & Legs":[0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40,0.40] }), } # --- Margin Matrix --- margin_data = [ (0, 0.4), (150, 0.5), (210, 0.525), (275, 0.55), (345, 0.575), (840, 0.6), (1563, 0.625), (2600, 0.65), (4290, 0.66), (6030, 0.67) ] # --- Session State Initialization --- if "entries_screenprint" not in st.session_state: st.session_state.entries_screenprint = [] # --- User Inputs --- col1, col2, col3, col4 = st.columns(4) selected_type = col1.selectbox("Select Screen Print Type", pricing_data.keys()) selected_size = col2.selectbox("Select Print Size", ["4x4", "12x12", "14x16"]) quantity = col3.number_input("Enter Quantity", min_value=1, step=1) selected_options = col4.multiselect("Select Options", ["Darks", "Fleece", "90% Poly+", "Sleeves & Legs"]) item_cost = st.number_input("Enter Base Item Cost", min_value=0.0, step=0.01) use_manual_margin = st.checkbox("Use Manual Margin") # --- Determine the Price Tier Based on Quantity --- df = pricing_data[selected_type] selected_range = next((row["Qty"] for _, row in df.iterrows() if quantity <= int(row["Qty"].split()[-1])), "Above 500") # --- Fetch the Price Per Unit --- row = df[df["Qty"] == selected_range] if not row.empty and item_cost > 0: base_price = row[selected_size].values[0] unit_price_before_margin = base_price + item_cost # --- Apply Additional Costs --- for option in selected_options: unit_price_before_margin += row[option].values[0] # --- Calculate Total Cost Before Margin --- total_cost = unit_price_before_margin * quantity # --- Apply Manual or Automatic Margin --- if use_manual_margin: margin_percentage = st.slider( "Select Margin (%)", min_value=1.0, max_value=99.0, step=0.5, value=60.0, format="%.2f%%" ) margin = margin_percentage / 100 # ✅ correct logic margin_display = f"{margin_percentage:.2f}%" # ✅ matches manual input else: margin_data = [ (0, 0.4), (150, 0.5), (210, 0.525), (275, 0.55), (345, 0.575), (840, 0.6), (1563, 0.625), (2600, 0.65), (4290, 0.66), (6030, 0.67) ] margin = next((rate for threshold, rate in reversed(margin_data) if total_cost >= threshold), 0.67) margin_display = f"{margin * 100:.2f}%" # ✅ correct display # --- Calculate Selling Prices --- total_selling_price = total_cost / (1-margin) unit_price_after_margin = total_selling_price / quantity # --- Add Entry Button --- if st.button("➕ Add Entry"): entry = { "Quantity": quantity, "Print Type": selected_type, "Print Size": selected_size, "Options": ", ".join(selected_options) if selected_options else "None", "Item Cost": item_cost, "Base Price Per Unit": base_price, "Total Cost": total_cost, "Margin": margin, "Unit Price After Margin": unit_price_after_margin, "Total Selling Price": total_selling_price } st.session_state.entries_screenprint.append(entry) # --- Display Pricing Breakdown --- if st.session_state.entries_screenprint: st.subheader("Pricing Breakdown") for i, entry in enumerate(st.session_state.entries_screenprint): st.text("===========================================================================") st.write(f"### Entry {i+1}") col1, col2, col3 = st.columns(3) with col1: st.metric(label="✅ Quantity", value=entry["Quantity"]) st.metric(label="💰 Total Net Cost", value=f"${entry['Total Cost']:.2f}") with col2: st.metric(label="📏 Print Size", value=entry["Print Size"]) #st.metric(label="📊 Margin", value=f"{(1 - entry['Margin']) * 100:.2f}%") st.metric(label="📊 Margin", value=f"{entry['Margin'] * 100:.2f}%") with col3: #st.metric(label="🎨 Print Option", value=entry["Options"]) st.metric(label="🪡 Print Cost (Per Unit)", value=f"${entry['Base Price Per Unit']:.2f}") st.metric(label="💸 Unit Selling Price", value=f"${entry['Unit Price After Margin']:.2f}") st.metric(label="💵 Total Selling Price", value=f"${entry['Total Selling Price']:.2f}") # Delete Button if st.button(f"❌ Delete {i+1}", key=f"delete_{i}"): del st.session_state.entries_screenprint[i] st.rerun() if st.button("🔄 Reset Entries"): st.session_state.entries_screenprint = [] st.rerun() elif option == 'Embroidery & Screen Print': st.text('\nDevelopment in Progress.......') def footer(): theme_bg = st.get_option("theme.backgroundColor") theme_text = st.get_option("theme.textColor") theme_primary = st.get_option("theme.primaryColor") footer_html = f""" """ st.markdown(footer_html, unsafe_allow_html=True) footer()