keyinnovations commited on
Commit
73df08c
Β·
verified Β·
1 Parent(s): b14bf96

Upload 9 files

Browse files
Files changed (5) hide show
  1. app.py +40 -0
  2. embroideryFullcolor.py +155 -156
  3. embroideryScreenprint.py +176 -0
  4. screenPrint.py +147 -137
  5. screenprintFullcolor.py +176 -0
app.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from embroidery import embroidery
4
+ from screenPrint import screenPrint
5
+ from fullColor import fullColor
6
+ from embroideryFullcolor import embFull
7
+ from embroideryScreenprint import embScreen
8
+ from screenprintFullcolor import screenFull
9
+
10
+
11
+ st.set_page_config(
12
+ page_title="Key Innovations Inc.",
13
+ page_icon="https://tscstatic.keyinnovations.ca/logo/logo_1T895ONEIG.png"
14
+ )
15
+ st.image("https://tscstatic.keyinnovations.ca/logo/logo_1T895ONEIG.png", width=150)
16
+ st.title('Quoting System')
17
+ st.subheader('Key Innovations Inc.')
18
+
19
+ option = st.segmented_control(
20
+ "Select an option:",
21
+ ["Embroidery", "Screen Print", "Full Color", "Embroidery & Screen Print", "Embroidery & Full Color", "Screenprint & Full Color"]
22
+ )
23
+
24
+ if option == 'Embroidery':
25
+ embroidery()
26
+
27
+ elif option == 'Screen Print':
28
+ screenPrint()
29
+
30
+ elif option == "Full Color":
31
+ fullColor()
32
+
33
+ elif option == 'Embroidery & Screen Print':
34
+ embScreen()
35
+
36
+ elif option == "Embroidery & Full Color":
37
+ embFull()
38
+
39
+ elif option == "Screenprint & Full Color":
40
+ screenFull()
embroideryFullcolor.py CHANGED
@@ -1,157 +1,156 @@
1
- import streamlit as st
2
- from utils import *
3
- from data import *
4
-
5
- def embFull():
6
- if "combined_entries" not in st.session_state:
7
- st.session_state.combined_entries = []
8
-
9
- emb_company = st.selectbox("Select Embroidery Company", list(emb_data.keys()), key="combo_emb_company")
10
- fc_company = st.selectbox("Select Full Color Company", list(full_data.keys()), key="combo_fc_company")
11
-
12
- df_emb = pd.DataFrame(emb_data[emb_company])
13
- df_fc = pd.DataFrame(full_data[fc_company])
14
-
15
- col1, col2, col3 = st.columns(3)
16
- with col1:
17
- quantity = st.number_input("Enter Quantity", min_value=1, step=1, key="combo_quantity")
18
- with col2:
19
- stitch_count = st.multiselect("Embroidery Stitch Count", list(df_emb.columns[1:]), key="combo_stitch_count")
20
- with col3:
21
- print_area = st.selectbox("Full Color Print", list(df_fc.columns[1:]), key="combo_print_area")
22
-
23
- item_price = st.number_input("Item Cost (Fixed)", min_value=0.0, step=0.01, key="combo_item_price")
24
-
25
- quantity_labels_emb = df_emb["Quantity"].tolist()
26
- quantity_labels_fc = df_fc["Quantity"].tolist()
27
- emb_range = find_quantity_range(quantity, quantity_labels_emb)
28
- fc_range = find_quantity_range(quantity, quantity_labels_fc)
29
-
30
- emb_stitch_price = float(sum(df_emb[df_emb["Quantity"] == emb_range][stitch_count].values[0])) if stitch_count else 0.0
31
- fc_print_price = float(df_fc[df_fc["Quantity"] == fc_range][print_area].values[0])
32
- total_deco_price = emb_stitch_price + fc_print_price
33
-
34
- net_value = quantity * (item_price + total_deco_price)
35
-
36
- use_manual_margin = st.checkbox("Use Manual Margin", key="combo_manual_margin")
37
- if use_manual_margin:
38
- margin_percentage = st.number_input("Enter Margin (%)", min_value=1.0, max_value=99.0, step=0.1, value=60.0, key="combo_margin_val")
39
- margin = margin_percentage / 100
40
- margin_display = f"{margin_percentage:.2f}%"
41
- else:
42
- margin = next((rate for threshold, rate in reversed(margin_data) if net_value >= threshold), 0.67)
43
- margin_display = f"{margin * 100:.2f}%"
44
-
45
- total_selling_price = net_value / (1 - margin)
46
- unit_selling_price = total_selling_price / quantity
47
-
48
- if st.button("βž• Add Entry", key="add_combo_entry"):
49
- entry = {
50
- "Quantity": quantity,
51
- "Embroidery Stitch Count": stitch_count,
52
- "Emb Price": f"${emb_stitch_price:.2f}",
53
- "Full Color Area": print_area,
54
- "FC Price": f"${fc_print_price:.2f}",
55
- "Total Decoration Cost": f"${total_deco_price:.2f}",
56
- "Item Cost": f"${item_price:.2f}",
57
- "Total Net Cost": f"${net_value:,.2f}",
58
- "Margin": margin_display,
59
- "Unit Selling Price": f"${unit_selling_price:.2f}",
60
- "Total Selling Price": f"${total_selling_price:.2f}"
61
- }
62
- st.session_state.combined_entries.append(entry)
63
-
64
- if st.session_state.combined_entries:
65
- st.subheader("Pricing Breakdown")
66
-
67
- entries = st.session_state.combined_entries
68
- cols = st.columns(len(entries))
69
- for i, (col, entry) in enumerate(zip(cols, entries)):
70
- with col:
71
- st.markdown(f"<h4 style='color: #d31145;'>Entry {i+1}</h4>", unsafe_allow_html=True)
72
- st.markdown(f"<div style='font-size: 16px;'>πŸ“Œ Quantity:<br><b>{entry['Quantity']}</b></div><br>", unsafe_allow_html=True)
73
- st.markdown(f"<div style='font-size: 16px;'>πŸͺ‘ Embroidery Price:<br><b>{entry['Emb Price']}</b></div><br>", unsafe_allow_html=True)
74
- #st.markdown(f"<div style='font-size: 16px;'>🎨 Full Color Area:<br><b>{entry['Full Color Area']}</b></div><br>", unsafe_allow_html=True)
75
- st.markdown(f"<div style='font-size: 16px;'>πŸ–οΈ Full Color Price:<br><b>{entry['FC Price']}</b></div><br>", unsafe_allow_html=True)
76
- st.markdown(f"<div style='font-size: 16px;'>πŸ’° Total Net Cost:<br><b>{entry['Total Net Cost']}</b></div><br>", unsafe_allow_html=True)
77
- st.markdown(f"<div style='font-size: 16px;'>πŸ“ˆ Margin:<br><b>{entry['Margin']}</b></div><br>", unsafe_allow_html=True)
78
- st.markdown(f"<div style='font-size: 16px;'>πŸ“Š Unit Price:<br><b>{entry['Unit Selling Price']}</b></div><br>", unsafe_allow_html=True)
79
- st.markdown(f"<div style='font-size: 16px;'>πŸ’΅ Total Selling Price:<br><b>{entry['Total Selling Price']}</b></div><br>", unsafe_allow_html=True)
80
- if st.button(f"❌ Delete {i+1}", key=f"delete_combo_{i}"):
81
- del st.session_state.combined_entries[i]
82
- st.rerun()
83
-
84
- if st.button("πŸ”„ Reset Entries", key="reset_combo"):
85
- st.session_state.combined_entries = []
86
- st.rerun()
87
-
88
- # πŸ“„ HTML2PDF export section
89
- html = """
90
- <html>
91
- <head>
92
- <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
93
- <style>
94
- .pdf-button {
95
- background-color: #d31145;
96
- color: white;
97
- padding: 12px 24px;
98
- border: none;
99
- border-radius: 8px;
100
- font-size: 14px;
101
- font-weight: bold;
102
- cursor: pointer;
103
- transition: background-color 0.3s ease;
104
- box-shadow: 0 2px 5px rgba(0,0,0,0.2);
105
- }
106
- .pdf-button:hover {
107
- background-color: #b80e3a;
108
- }
109
- </style>
110
- </head>
111
- <body>
112
-
113
- <div id="pdf-content" style="display: none;">
114
- <h2 style='color:#333;'>Embroidery + Full Color Pricing Breakdown</h2>
115
- """
116
-
117
- for i, entry in enumerate(entries):
118
- html += f"""
119
- <div style='margin-bottom: 20px; border:1px solid #ccc; padding: 10px; border-radius: 8px;'>
120
- <h4 style='color:#d31145; margin-bottom: 12px;'>Entry {i+1}</h4>
121
- <p>πŸ“Œ Quantity: {entry['Quantity']}</p>
122
- <p>πŸͺ‘ Embroidery Price: {entry['Emb Price']}</p>
123
- <p>🎨 Full Color Area: {entry['Full Color Area']}</p>
124
- <p>πŸ–οΈ Full Color Price: {entry['FC Price']}</p>
125
- <p>πŸ’° Total Net Cost: {entry['Total Net Cost']}</p>
126
- <p>πŸ“ˆ Margin: {entry['Margin']}</p>
127
- <p>πŸ“Š Unit Price: {entry['Unit Selling Price']}</p>
128
- <p>πŸ’΅ Total Selling Price: {entry['Total Selling Price']}</p>
129
- </div>
130
- """
131
-
132
- html += """
133
- </div>
134
-
135
- <button class="pdf-button" onclick="downloadPDF()">πŸ“„ Download Results as PDF</button>
136
-
137
- <script>
138
- function downloadPDF() {
139
- const element = document.getElementById("pdf-content");
140
- element.style.display = 'block';
141
- html2pdf().set({
142
- margin: 0.5,
143
- filename: 'combo_embroidery_fullcolor_breakdown.pdf',
144
- image: { type: 'jpeg', quality: 0.98 },
145
- html2canvas: { scale: 2 },
146
- jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
147
- }).from(element).save().then(() => {
148
- element.style.display = 'none';
149
- });
150
- }
151
- </script>
152
-
153
- </body>
154
- </html>
155
- """
156
-
157
  st.components.v1.html(html, height=120)
 
1
+ import streamlit as st
2
+ from utils import *
3
+ from data import *
4
+
5
+ def embFull():
6
+ if "combined_entries" not in st.session_state:
7
+ st.session_state.combined_entries = []
8
+
9
+ emb_company = st.selectbox("Select Embroidery Company", list(emb_data.keys()), key="combo_emb_company")
10
+ fc_company = st.selectbox("Select Full Color Company", list(full_data.keys()), key="combo_fc_company")
11
+
12
+ df_emb = pd.DataFrame(emb_data[emb_company])
13
+ df_fc = pd.DataFrame(full_data[fc_company])
14
+
15
+ col1, col2, col3 = st.columns(3)
16
+ with col1:
17
+ quantity = st.number_input("Enter Quantity", min_value=1, step=1, key="combo_quantity")
18
+ with col2:
19
+ stitch_count = st.multiselect("Embroidery Stitch Count", list(df_emb.columns[1:]), key="combo_stitch_count")
20
+ with col3:
21
+ print_area = st.selectbox("Full Color Print", list(df_fc.columns[1:]), key="combo_print_area")
22
+
23
+ item_price = st.number_input("Item Cost (Fixed)", min_value=0.0, step=0.01, key="combo_item_price")
24
+
25
+ quantity_labels_emb = df_emb["Quantity"].tolist()
26
+ quantity_labels_fc = df_fc["Quantity"].tolist()
27
+ emb_range = find_quantity_range(quantity, quantity_labels_emb)
28
+ fc_range = find_quantity_range(quantity, quantity_labels_fc)
29
+
30
+ emb_stitch_price = float(sum(df_emb[df_emb["Quantity"] == emb_range][stitch_count].values[0])) if stitch_count else 0.0
31
+ fc_print_price = float(df_fc[df_fc["Quantity"] == fc_range][print_area].values[0])
32
+ total_deco_price = emb_stitch_price + fc_print_price
33
+
34
+ net_value = quantity * (item_price + total_deco_price)
35
+
36
+ use_manual_margin = st.checkbox("Use Manual Margin", key="combo_manual_margin")
37
+ if use_manual_margin:
38
+ margin_percentage = st.number_input("Enter Margin (%)", min_value=1.0, max_value=99.0, step=0.1, value=60.0, key="combo_margin_val")
39
+ margin = margin_percentage / 100
40
+ margin_display = f"{margin_percentage:.2f}%"
41
+ else:
42
+ margin = next((rate for threshold, rate in reversed(margin_data) if net_value >= threshold), 0.67)
43
+ margin_display = f"{margin * 100:.2f}%"
44
+
45
+ total_selling_price = net_value / (1 - margin)
46
+ unit_selling_price = total_selling_price / quantity
47
+
48
+ if st.button("βž• Add Entry", key="add_combo_entry"):
49
+ entry = {
50
+ "Quantity": quantity,
51
+ "Embroidery Stitch Count": stitch_count,
52
+ "Emb Price": f"${emb_stitch_price:.2f}",
53
+ "Full Color Area": print_area,
54
+ "FC Price": f"${fc_print_price:.2f}",
55
+ "Total Decoration Cost": f"${total_deco_price:.2f}",
56
+ "Item Cost": f"${item_price:.2f}",
57
+ "Total Net Cost": f"${net_value:,.2f}",
58
+ "Margin": margin_display,
59
+ "Unit Selling Price": f"${unit_selling_price:.2f}",
60
+ "Total Selling Price": f"${total_selling_price:.2f}"
61
+ }
62
+ st.session_state.combined_entries.append(entry)
63
+
64
+ if st.session_state.combined_entries:
65
+ st.subheader("Pricing Breakdown")
66
+
67
+ entries = st.session_state.combined_entries
68
+ cols = st.columns(len(entries))
69
+ for i, (col, entry) in enumerate(zip(cols, entries)):
70
+ with col:
71
+ st.markdown(f"<h4 style='color: #d31145;'>Entry {i+1}</h4>", unsafe_allow_html=True)
72
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Œ Quantity:<br><b>{entry['Quantity']}</b></div><br>", unsafe_allow_html=True)
73
+ st.markdown(f"<div style='font-size: 16px;'>πŸͺ‘ Embroidery Price:<br><b>{entry['Emb Price']}</b></div><br>", unsafe_allow_html=True)
74
+ #st.markdown(f"<div style='font-size: 16px;'>🎨 Full Color Area:<br><b>{entry['Full Color Area']}</b></div><br>", unsafe_allow_html=True)
75
+ st.markdown(f"<div style='font-size: 16px;'>πŸ–οΈ Full Color Price:<br><b>{entry['FC Price']}</b></div><br>", unsafe_allow_html=True)
76
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“ˆ Margin:<br><b>{entry['Margin']}</b></div><br>", unsafe_allow_html=True)
77
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Š Unit Price:<br><b>{entry['Unit Selling Price']}</b></div><br>", unsafe_allow_html=True)
78
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’° Total Net Cost:<br><b>{entry['Total Net Cost']}</b></div><br>", unsafe_allow_html=True)
79
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’΅ Total Selling Price:<br><b>{entry['Total Selling Price']}</b></div><br>", unsafe_allow_html=True)
80
+ if st.button(f"❌ Delete {i+1}", key=f"delete_combo_{i}"):
81
+ del st.session_state.combined_entries[i]
82
+ st.rerun()
83
+
84
+ if st.button("πŸ”„ Reset Entries", key="reset_combo"):
85
+ st.session_state.combined_entries = []
86
+ st.rerun()
87
+
88
+ html = """
89
+ <html>
90
+ <head>
91
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
92
+ <style>
93
+ .pdf-button {
94
+ background-color: #d31145;
95
+ color: white;
96
+ padding: 12px 24px;
97
+ border: none;
98
+ border-radius: 8px;
99
+ font-size: 14px;
100
+ font-weight: bold;
101
+ cursor: pointer;
102
+ transition: background-color 0.3s ease;
103
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
104
+ }
105
+ .pdf-button:hover {
106
+ background-color: #b80e3a;
107
+ }
108
+ </style>
109
+ </head>
110
+ <body>
111
+
112
+ <div id="pdf-content" style="display: none;">
113
+ <h2 style='color:#333;'>Embroidery + Full Color Pricing Breakdown</h2>
114
+ """
115
+
116
+ for i, entry in enumerate(entries):
117
+ html += f"""
118
+ <div style='margin-bottom: 20px; border:1px solid #ccc; padding: 10px; border-radius: 8px;'>
119
+ <h4 style='color:#d31145; margin-bottom: 12px;'>Entry {i+1}</h4>
120
+ <p>πŸ“Œ Quantity: {entry['Quantity']}</p>
121
+ <p>πŸͺ‘ Embroidery Price: {entry['Emb Price']}</p>
122
+ <p>🎨 Full Color Area: {entry['Full Color Area']}</p>
123
+ <p>πŸ–οΈ Full Color Price: {entry['FC Price']}</p>
124
+ <p>πŸ’° Total Net Cost: {entry['Total Net Cost']}</p>
125
+ <p>πŸ“ˆ Margin: {entry['Margin']}</p>
126
+ <p>πŸ“Š Unit Price: {entry['Unit Selling Price']}</p>
127
+ <p>πŸ’΅ Total Selling Price: {entry['Total Selling Price']}</p>
128
+ </div>
129
+ """
130
+
131
+ html += """
132
+ </div>
133
+
134
+ <button class="pdf-button" onclick="downloadPDF()">πŸ“„ Download Results as PDF</button>
135
+
136
+ <script>
137
+ function downloadPDF() {
138
+ const element = document.getElementById("pdf-content");
139
+ element.style.display = 'block';
140
+ html2pdf().set({
141
+ margin: 0.5,
142
+ filename: 'combo_embroidery_fullcolor_breakdown.pdf',
143
+ image: { type: 'jpeg', quality: 0.98 },
144
+ html2canvas: { scale: 2 },
145
+ jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
146
+ }).from(element).save().then(() => {
147
+ element.style.display = 'none';
148
+ });
149
+ }
150
+ </script>
151
+
152
+ </body>
153
+ </html>
154
+ """
155
+
 
156
  st.components.v1.html(html, height=120)
embroideryScreenprint.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from utils import *
4
+ from data import *
5
+
6
+ def embScreen():
7
+ if "combined_emb_screen_entries" not in st.session_state:
8
+ st.session_state.combined_emb_screen_entries = []
9
+
10
+ # Select Embroidery and Screen Print Companies
11
+ emb_company = st.selectbox("Select Embroidery Company", list(emb_data.keys()), key="combo_emb_screen_emb_company")
12
+ sp_company = st.selectbox("Select Screen Print Company", list(screen_data.keys()), key="combo_emb_screen_sp_company")
13
+
14
+ df_emb = pd.DataFrame(emb_data[emb_company])
15
+ sp_data = screen_data[sp_company]
16
+
17
+ col1, col2, col3 = st.columns(3)
18
+ with col1:
19
+ quantity = st.number_input("Enter Quantity", min_value=1, step=1, key="combo_emb_screen_quantity")
20
+ with col2:
21
+ stitch_count = st.multiselect("Embroidery Stitch Count", list(df_emb.columns[1:]), key="combo_emb_screen_stitch_count")
22
+ with col3:
23
+ item_price = st.number_input("Item Cost (Fixed)", min_value=0.0, step=0.01, key="combo_emb_screen_item_price")
24
+
25
+ # Screen Print Selection
26
+ col4, col5, col6 = st.columns(3)
27
+ with col4:
28
+ selected_type = st.selectbox("Print Type", list(sp_data.keys()), key="combo_emb_screen_print_type")
29
+ with col5:
30
+ selected_size = st.selectbox("Print Size", list(sp_data[selected_type].columns[1:4]), key="combo_emb_screen_print_size")
31
+ with col6:
32
+ selected_options = st.multiselect("Options", ["Darks", "Fleece", "90% Poly+", "Sleeves & Legs"], key="combo_emb_screen_options")
33
+
34
+ # --- Embroidery Pricing ---
35
+ quantity_labels_emb = df_emb["Quantity"].tolist()
36
+ emb_range = find_quantity_range(quantity, quantity_labels_emb)
37
+ emb_stitch_price = float(sum(df_emb[df_emb["Quantity"] == emb_range][stitch_count].values[0])) if stitch_count else 0.0
38
+
39
+ # --- Screen Print Pricing ---
40
+ sp_df = sp_data[selected_type]
41
+ sp_range = next((row["Qty"] for _, row in sp_df.iterrows() if quantity <= int(row["Qty"].split()[-1])), sp_df.iloc[-1]["Qty"])
42
+ sp_row = sp_df[sp_df["Qty"] == sp_range]
43
+
44
+ sp_base_price = sp_row[selected_size].values[0] if not sp_row.empty else 0.0
45
+ sp_option_cost = sum(sp_row[opt].values[0] for opt in selected_options if opt in sp_row) if not sp_row.empty else 0.0
46
+ sp_total_price = sp_base_price + sp_option_cost
47
+
48
+ # Total Decoration and Net Cost
49
+ total_deco_price = emb_stitch_price + sp_total_price
50
+ net_value = quantity * (item_price + total_deco_price)
51
+
52
+ use_manual_margin = st.checkbox("Use Manual Margin", key="combo_emb_screen_manual_margin")
53
+ if use_manual_margin:
54
+ margin_percentage = st.number_input("Enter Margin (%)", min_value=1.0, max_value=99.0, step=0.1, value=60.0, key="combo_emb_screen_margin_val")
55
+ margin = margin_percentage / 100
56
+ margin_display = f"{margin_percentage:.2f}%"
57
+ else:
58
+ margin = next((rate for threshold, rate in reversed(margin_data) if net_value >= threshold), 0.67)
59
+ margin_display = f"{margin * 100:.2f}%"
60
+
61
+ total_selling_price = net_value / (1 - margin)
62
+ unit_selling_price = total_selling_price / quantity
63
+
64
+ # Add Entry Button
65
+ if st.button("βž• Add Entry", key="add_emb_screen_entry"):
66
+ entry = {
67
+ "Quantity": quantity,
68
+ "Embroidery Stitch Count": stitch_count,
69
+ "Emb Price": f"${emb_stitch_price:.2f}",
70
+ "Print Type": selected_type,
71
+ "Print Size": selected_size,
72
+ "SP Base Price": f"${sp_base_price:.2f}",
73
+ "SP Options": ", ".join(selected_options) if selected_options else "None",
74
+ "SP Option Price": f"${sp_option_cost:.2f}",
75
+ "SP Total Price": f"${sp_total_price:.2f}",
76
+ "Total Decoration Cost": f"${total_deco_price:.2f}",
77
+ "Item Cost": f"${item_price:.2f}",
78
+ "Total Net Cost": f"${net_value:,.2f}",
79
+ "Margin": margin_display,
80
+ "Unit Selling Price": f"${unit_selling_price:.2f}",
81
+ "Total Selling Price": f"${total_selling_price:.2f}"
82
+ }
83
+ st.session_state.combined_emb_screen_entries.append(entry)
84
+
85
+ # Pricing Breakdown Display
86
+ if st.session_state.combined_emb_screen_entries:
87
+ st.subheader("Pricing Breakdown")
88
+ entries = st.session_state.combined_emb_screen_entries
89
+ cols = st.columns(len(entries))
90
+ for i, (col, entry) in enumerate(zip(cols, entries)):
91
+ with col:
92
+ st.markdown(f"<h4 style='color: #d31145;'>Entry {i+1}</h4>", unsafe_allow_html=True)
93
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Œ Quantity:<br><b>{entry['Quantity']}</b></div><br>", unsafe_allow_html=True)
94
+ st.markdown(f"<div style='font-size: 16px;'>πŸͺ‘ Embroidery Price:<br><b>{entry['Emb Price']}</b></div><br>", unsafe_allow_html=True)
95
+ st.markdown(f"<div style='font-size: 16px;'>πŸ–¨οΈ Screen Print Total:<br><b>{entry['SP Total Price']}</b></div><br>", unsafe_allow_html=True)
96
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“ˆ Margin:<br><b>{entry['Margin']}</b></div><br>", unsafe_allow_html=True)
97
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Š Unit Price:<br><b>{entry['Unit Selling Price']}</b></div><br>", unsafe_allow_html=True)
98
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’° Total Net Cost:<br><b>{entry['Total Net Cost']}</b></div><br>", unsafe_allow_html=True)
99
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’΅ Total Selling Price:<br><b>{entry['Total Selling Price']}</b></div><br>", unsafe_allow_html=True)
100
+ if st.button(f"❌ Delete {i+1}", key=f"delete_emb_screen_{i}"):
101
+ del st.session_state.combined_emb_screen_entries[i]
102
+ st.rerun()
103
+
104
+ if st.button("πŸ”„ Reset Entries", key="reset_emb_screen"):
105
+ st.session_state.combined_emb_screen_entries = []
106
+ st.rerun()
107
+
108
+ # PDF Export
109
+ html = """
110
+ <html>
111
+ <head>
112
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
113
+ <style>
114
+ .pdf-button {
115
+ background-color: #d31145;
116
+ color: white;
117
+ padding: 12px 24px;
118
+ border: none;
119
+ border-radius: 8px;
120
+ font-size: 14px;
121
+ font-weight: bold;
122
+ cursor: pointer;
123
+ transition: background-color 0.3s ease;
124
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
125
+ }
126
+ .pdf-button:hover {
127
+ background-color: #b80e3a;
128
+ }
129
+ </style>
130
+ </head>
131
+ <body>
132
+
133
+ <div id="pdf-content" style="display: none;">
134
+ <h2 style='color:#333;'>Embroidery + Screen Print Pricing Breakdown</h2>
135
+ """
136
+
137
+ for i, entry in enumerate(entries):
138
+ html += f"""
139
+ <div style='margin-bottom: 20px; border:1px solid #ccc; padding: 10px; border-radius: 8px;'>
140
+ <h4 style='color:#d31145;'>Entry {i+1}</h4>
141
+ <p>πŸ“Œ Quantity: {entry['Quantity']}</p>
142
+ <p>πŸͺ‘ Embroidery Price: {entry['Emb Price']}</p>
143
+ <p>πŸ–¨οΈ Screen Print Type: {entry['Print Type']}</p>
144
+ <p>πŸ“ Print Size: {entry['Print Size']}</p>
145
+ <p>βš™οΈ Options: {entry['SP Options']}</p>
146
+ <p>πŸ’Έ Screen Print Total: {entry['SP Total Price']}</p>
147
+ <p>πŸ’° Total Net Cost: {entry['Total Net Cost']}</p>
148
+ <p>πŸ“ˆ Margin: {entry['Margin']}</p>
149
+ <p>πŸ“Š Unit Price: {entry['Unit Selling Price']}</p>
150
+ <p>πŸ’΅ Total Selling Price: {entry['Total Selling Price']}</p>
151
+ </div>
152
+ """
153
+
154
+ html += """
155
+ </div>
156
+ <button class="pdf-button" onclick="downloadPDF()">πŸ“„ Download Results as PDF</button>
157
+ <script>
158
+ function downloadPDF() {
159
+ const element = document.getElementById("pdf-content");
160
+ element.style.display = 'block';
161
+ html2pdf().set({
162
+ margin: 0.5,
163
+ filename: 'combo_embroidery_screenprint_breakdown.pdf',
164
+ image: { type: 'jpeg', quality: 0.98 },
165
+ html2canvas: { scale: 2 },
166
+ jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
167
+ }).from(element).save().then(() => {
168
+ element.style.display = 'none';
169
+ });
170
+ }
171
+ </script>
172
+
173
+ </body>
174
+ </html>
175
+ """
176
+ st.components.v1.html(html, height=120)
screenPrint.py CHANGED
@@ -12,149 +12,159 @@ def screenPrint():
12
  if selected_company:
13
  company_data = screen_data[selected_company]
14
  col1, col2, col3, col4 = st.columns(4)
15
- selected_type = col1.selectbox("Print Type", list(company_data.keys()))
16
- selected_size = col2.selectbox("Print Size", list(company_data[selected_type].columns[1:4]))
 
 
 
 
 
 
 
 
 
17
  quantity = col3.number_input("Quantity", min_value=1, step=1)
18
  selected_options = col4.multiselect("Options", ["Darks", "Fleece", "90% Poly+", "Sleeves & Legs"])
19
  item_cost = st.number_input("Enter Base Item Cost", min_value=0.0, step=0.01)
20
  use_manual_margin = st.checkbox("Use Manual Margin")
21
 
22
  # --- Determine Range ---
23
- df = company_data[selected_type]
24
- selected_range = next((row["Qty"] for _, row in df.iterrows() if quantity <= int(row["Qty"].split()[-1])), df.iloc[-1]["Qty"])
25
- row = df[df["Qty"] == selected_range]
26
-
27
- if not row.empty and item_cost > 0:
28
- base_price = row[selected_size].values[0]
29
- unit_price_before_margin = base_price + item_cost
30
- for option in selected_options:
31
- if option in row:
32
- unit_price_before_margin += row[option].values[0]
33
-
34
- total_cost = unit_price_before_margin * quantity
35
-
36
- if use_manual_margin:
37
- margin_percentage = st.number_input("Enter Margin (%)", min_value=1.0, max_value=99.0, step=0.1, value=60.0)
38
- margin = margin_percentage / 100
39
- margin_display = f"{margin_percentage:.2f}%"
40
- else:
41
- margin_data = [
42
- (0, 0.4), (150, 0.5), (210, 0.525), (275, 0.55),
43
- (345, 0.575), (840, 0.6), (1563, 0.625), (2600, 0.65),
44
- (4290, 0.66), (6030, 0.67)
45
- ]
46
- margin = next((rate for threshold, rate in reversed(margin_data) if total_cost >= threshold), 0.67)
47
- margin_display = f"{margin * 100:.2f}%"
48
-
49
- total_selling_price = total_cost / (1 - margin)
50
- unit_price_after_margin = total_selling_price / quantity
51
-
52
- if st.button("βž• Add Entry"):
53
- entry = {
54
- "Quantity": quantity,
55
- "Company": selected_company,
56
- "Print Type": selected_type,
57
- "Print Size": selected_size,
58
- "Options": ", ".join(selected_options) if selected_options else "None",
59
- "Item Cost": item_cost,
60
- "Base Price Per Unit": base_price,
61
- "Total Cost": total_cost,
62
- "Margin": margin,
63
- "Unit Price After Margin": unit_price_after_margin,
64
- "Total Selling Price": total_selling_price
65
- }
66
- st.session_state.entries_screenprint.append(entry)
67
-
68
- # --- Display Pricing Breakdown ---
69
- if st.session_state.entries_screenprint:
70
- st.subheader("Pricing Breakdown")
71
- cols = st.columns(len(st.session_state.entries_screenprint)) # Create one column per entry
72
- for i, (col, entry) in enumerate(zip(cols, st.session_state.entries_screenprint)):
73
- with col:
74
- st.markdown(f"<h4 style='color: #d31145;'>Entry {i+1}</h4>", unsafe_allow_html=True)
75
- st.markdown(f"<div style='font-size: 16px;'>πŸ“Œ <strong>Quantity:</strong><br> {entry['Quantity']}</div><br>", unsafe_allow_html=True)
76
- st.markdown(f"<div style='font-size: 16px;'>πŸ“ <strong>Print Size:</strong><br> {entry['Print Size']}</div><br>", unsafe_allow_html=True)
77
- st.markdown(f"<div style='font-size: 16px;'>πŸͺ‘ <strong>Print Cost (Per Unit):</strong><br> ${entry['Base Price Per Unit']:.2f}</div><br>", unsafe_allow_html=True)
78
- st.markdown(f"<div style='font-size: 16px;'>πŸ’° <strong>Total Net Cost:</strong><br> ${entry['Total Cost']:.2f}</div><br>", unsafe_allow_html=True)
79
- st.markdown(f"<div style='font-size: 16px;'>πŸ“Š <strong>Margin:</strong><br> {entry['Margin'] * 100:.2f}%</div><br>", unsafe_allow_html=True)
80
- st.markdown(f"<div style='font-size: 16px;'>πŸ’Έ <strong>Unit Selling Price:</strong><br> ${entry['Unit Price After Margin']:.2f}</div><br>", unsafe_allow_html=True)
81
- st.markdown(f"<div style='font-size: 16px;'>πŸ’΅ <strong>Total Selling Price:</strong><br> ${entry['Total Selling Price']:.2f}</div><br>", unsafe_allow_html=True)
82
-
83
- # Delete Button
84
- if st.button(f"❌ Delete {i+1}", key=f"delete_screenprint_{i}"):
85
- del st.session_state.entries_screenprint[i]
86
- st.rerun()
87
-
88
- if st.button("πŸ”„ Reset Entries"):
89
- st.session_state.entries_screenprint = []
90
- st.rerun()
91
-
92
- entries = st.session_state.get("entries_screenprint", [])
93
- if entries:
94
- st.subheader("")
95
-
96
- html = """
97
- <html>
98
- <head>
99
- <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
100
- <style>
101
- .pdf-button {
102
- background-color: #d31145;
103
- color: white;
104
- padding: 12px 24px;
105
- border: none;
106
- border-radius: 8px;
107
- font-size: 14px;
108
- font-weight: bold;
109
- cursor: pointer;
110
- transition: background-color 0.3s ease;
111
- box-shadow: 0 2px 5px rgba(0,0,0,0.2);
112
- }
113
- .pdf-button:hover {
114
- background-color: #b80e3a;
115
- }
116
- </style>
117
- </head>
118
- <body>
119
-
120
- <div id="pdf-content" style="display: none;">
121
- <h2 style='color:#333;'>Pricing Breakdown</h2>
122
- """
123
-
124
- for i, entry in enumerate(entries):
125
- html += f"""
126
- <div style='margin-bottom: 20px; border:1px solid #ccc; padding: 10px; border-radius: 8px;'>
127
- <h4 style='color:#d31145;'>Entry {i+1}</h4>
128
- <p>βœ… Quantity: {entry['Quantity']}</p>
129
- <p>πŸ“ Print Size: {entry['Print Size']}</p>
130
- <p>πŸͺ‘ Print Cost (Per Unit): ${entry['Base Price Per Unit']:.2f}</p>
131
- <p>πŸ’° Total Net Cost: ${entry['Total Cost']:.2f}</p>
132
- <p>πŸ“Š Margin: {entry['Margin'] * 100:.2f}%</p>
133
- <p>πŸ’Έ Unit Selling Price: ${entry['Unit Price After Margin']:.2f}</p>
134
- <p>πŸ’΅ Total Selling Price: ${entry['Total Selling Price']:.2f}</p>
135
- </div>
136
  """
137
 
138
- html += """
139
- </div>
140
- <button class="pdf-button" onclick="downloadPDF()">πŸ“„ Download Results as PDF</button>
141
- <script>
142
- function downloadPDF() {
143
- const element = document.getElementById("pdf-content");
144
- element.style.display = 'block';
145
- html2pdf().set({
146
- margin: 0.5,
147
- filename: 'pricing_breakdown.pdf',
148
- image: { type: 'jpeg', quality: 0.98 },
149
- html2canvas: { scale: 2 },
150
- jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
151
- }).from(element).save().then(() => {
152
- element.style.display = 'none';
153
- });
154
- }
155
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
- </body>
158
- </html>
159
- """
160
- st.components.v1.html(html, height=100)
 
12
  if selected_company:
13
  company_data = screen_data[selected_company]
14
  col1, col2, col3, col4 = st.columns(4)
15
+ # selected_type = col1.selectbox("Print Type", list(company_data.keys()))
16
+ # selected_size = col2.selectbox("Print Size", list(company_data[selected_type].columns[1:4]))
17
+ selected_types = col1.multiselect("Print Type", list(company_data.keys()))
18
+ selected_type = selected_types[0] if selected_types else None
19
+
20
+ selected_sizes = col2.multiselect(
21
+ "Print Size",
22
+ list(company_data[selected_type].columns[1:4]) if selected_type else []
23
+ )
24
+ selected_size = selected_sizes[0] if selected_sizes else None
25
+
26
  quantity = col3.number_input("Quantity", min_value=1, step=1)
27
  selected_options = col4.multiselect("Options", ["Darks", "Fleece", "90% Poly+", "Sleeves & Legs"])
28
  item_cost = st.number_input("Enter Base Item Cost", min_value=0.0, step=0.01)
29
  use_manual_margin = st.checkbox("Use Manual Margin")
30
 
31
  # --- Determine Range ---
32
+ if selected_type and selected_size and quantity and item_cost:
33
+ df = company_data[selected_type]
34
+ selected_range = next((row["Qty"] for _, row in df.iterrows() if quantity <= int(row["Qty"].split()[-1])), df.iloc[-1]["Qty"])
35
+ row = df[df["Qty"] == selected_range]
36
+
37
+ if not row.empty and item_cost > 0:
38
+ base_price = row[selected_size].values[0]
39
+ unit_price_before_margin = base_price + item_cost
40
+ for option in selected_options:
41
+ if option in row:
42
+ unit_price_before_margin += row[option].values[0]
43
+
44
+ total_cost = unit_price_before_margin * quantity
45
+
46
+ if use_manual_margin:
47
+ margin_percentage = st.number_input("Enter Margin (%)", min_value=1.0, max_value=99.0, step=0.1, value=60.0)
48
+ margin = margin_percentage / 100
49
+ margin_display = f"{margin_percentage:.2f}%"
50
+ else:
51
+ margin_data = [
52
+ (0, 0.4), (150, 0.5), (210, 0.525), (275, 0.55),
53
+ (345, 0.575), (840, 0.6), (1563, 0.625), (2600, 0.65),
54
+ (4290, 0.66), (6030, 0.67)
55
+ ]
56
+ margin = next((rate for threshold, rate in reversed(margin_data) if total_cost >= threshold), 0.67)
57
+ margin_display = f"{margin * 100:.2f}%"
58
+
59
+ total_selling_price = total_cost / (1 - margin)
60
+ unit_price_after_margin = total_selling_price / quantity
61
+
62
+ if st.button("βž• Add Entry"):
63
+ entry = {
64
+ "Quantity": quantity,
65
+ "Company": selected_company,
66
+ "Print Type": selected_type,
67
+ "Print Size": selected_size,
68
+ "Options": ", ".join(selected_options) if selected_options else "None",
69
+ "Item Cost": item_cost,
70
+ "Base Price Per Unit": base_price,
71
+ "Total Cost": total_cost,
72
+ "Margin": margin,
73
+ "Unit Price After Margin": unit_price_after_margin,
74
+ "Total Selling Price": total_selling_price
75
+ }
76
+ st.session_state.entries_screenprint.append(entry)
77
+
78
+ # --- Display Pricing Breakdown ---
79
+ if st.session_state.entries_screenprint:
80
+ st.subheader("Pricing Breakdown")
81
+ cols = st.columns(len(st.session_state.entries_screenprint)) # Create one column per entry
82
+ for i, (col, entry) in enumerate(zip(cols, st.session_state.entries_screenprint)):
83
+ with col:
84
+ st.markdown(f"<h4 style='color: #d31145;'>Entry {i+1}</h4>", unsafe_allow_html=True)
85
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Œ <strong>Quantity:</strong><br> {entry['Quantity']}</div><br>", unsafe_allow_html=True)
86
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“ <strong>Print Size:</strong><br> {entry['Print Size']}</div><br>", unsafe_allow_html=True)
87
+ st.markdown(f"<div style='font-size: 16px;'>πŸͺ‘ <strong>Print Cost (Per Unit):</strong><br> ${entry['Base Price Per Unit']:.2f}</div><br>", unsafe_allow_html=True)
88
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’° <strong>Total Net Cost:</strong><br> ${entry['Total Cost']:.2f}</div><br>", unsafe_allow_html=True)
89
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Š <strong>Margin:</strong><br> {entry['Margin'] * 100:.2f}%</div><br>", unsafe_allow_html=True)
90
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’Έ <strong>Unit Selling Price:</strong><br> ${entry['Unit Price After Margin']:.2f}</div><br>", unsafe_allow_html=True)
91
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’΅ <strong>Total Selling Price:</strong><br> ${entry['Total Selling Price']:.2f}</div><br>", unsafe_allow_html=True)
92
+
93
+ # Delete Button
94
+ if st.button(f"❌ Delete {i+1}", key=f"delete_screenprint_{i}"):
95
+ del st.session_state.entries_screenprint[i]
96
+ st.rerun()
97
+
98
+ if st.button("πŸ”„ Reset Entries"):
99
+ st.session_state.entries_screenprint = []
100
+ st.rerun()
101
+
102
+ entries = st.session_state.get("entries_screenprint", [])
103
+ if entries:
104
+ st.subheader("")
105
+
106
+ html = """
107
+ <html>
108
+ <head>
109
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
110
+ <style>
111
+ .pdf-button {
112
+ background-color: #d31145;
113
+ color: white;
114
+ padding: 12px 24px;
115
+ border: none;
116
+ border-radius: 8px;
117
+ font-size: 14px;
118
+ font-weight: bold;
119
+ cursor: pointer;
120
+ transition: background-color 0.3s ease;
121
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
122
+ }
123
+ .pdf-button:hover {
124
+ background-color: #b80e3a;
125
+ }
126
+ </style>
127
+ </head>
128
+ <body>
129
+
130
+ <div id="pdf-content" style="display: none;">
131
+ <h2 style='color:#333;'>Pricing Breakdown</h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  """
133
 
134
+ for i, entry in enumerate(entries):
135
+ html += f"""
136
+ <div style='margin-bottom: 20px; border:1px solid #ccc; padding: 10px; border-radius: 8px;'>
137
+ <h4 style='color:#d31145;'>Entry {i+1}</h4>
138
+ <p>βœ… Quantity: {entry['Quantity']}</p>
139
+ <p>πŸ“ Print Size: {entry['Print Size']}</p>
140
+ <p>πŸͺ‘ Print Cost (Per Unit): ${entry['Base Price Per Unit']:.2f}</p>
141
+ <p>πŸ’° Total Net Cost: ${entry['Total Cost']:.2f}</p>
142
+ <p>πŸ“Š Margin: {entry['Margin'] * 100:.2f}%</p>
143
+ <p>πŸ’Έ Unit Selling Price: ${entry['Unit Price After Margin']:.2f}</p>
144
+ <p>πŸ’΅ Total Selling Price: ${entry['Total Selling Price']:.2f}</p>
145
+ </div>
146
+ """
147
+
148
+ html += """
149
+ </div>
150
+ <button class="pdf-button" onclick="downloadPDF()">πŸ“„ Download Results as PDF</button>
151
+ <script>
152
+ function downloadPDF() {
153
+ const element = document.getElementById("pdf-content");
154
+ element.style.display = 'block';
155
+ html2pdf().set({
156
+ margin: 0.5,
157
+ filename: 'pricing_breakdown.pdf',
158
+ image: { type: 'jpeg', quality: 0.98 },
159
+ html2canvas: { scale: 2 },
160
+ jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
161
+ }).from(element).save().then(() => {
162
+ element.style.display = 'none';
163
+ });
164
+ }
165
+ </script>
166
 
167
+ </body>
168
+ </html>
169
+ """
170
+ st.components.v1.html(html, height=100)
screenprintFullcolor.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from utils import *
4
+ from data import *
5
+
6
+ def screenFull():
7
+ if "screen_full_entries" not in st.session_state:
8
+ st.session_state.screen_full_entries = []
9
+
10
+ # Select Companies
11
+ sp_company = st.selectbox("Select Screen Print Company", list(screen_data.keys()), key="combo_screen_full_sp_company")
12
+ fc_company = st.selectbox("Select Full Color Company", list(full_data.keys()), key="combo_screen_full_fc_company")
13
+
14
+ sp_data = screen_data[sp_company]
15
+ df_fc = pd.DataFrame(full_data[fc_company])
16
+
17
+ col1, col2, col3 = st.columns(3)
18
+ with col1:
19
+ selected_type = st.selectbox("Print Type", list(sp_data.keys()), key="combo_screen_full_print_type")
20
+ with col2:
21
+ selected_size = st.selectbox("Print Size", list(sp_data[selected_type].columns[1:4]), key="combo_screen_full_print_size")
22
+ with col3:
23
+ selected_options = st.multiselect("Options", ["Darks", "Fleece", "90% Poly+", "Sleeves & Legs"], key="combo_screen_full_options")
24
+
25
+ col4, col5, col6 = st.columns(3)
26
+ with col4:
27
+ print_area = st.selectbox("Full Color Print", list(df_fc.columns[1:]), key="combo_screen_full_print_area")
28
+ with col5:
29
+ quantity = st.number_input("Enter Quantity", min_value=1, step=1, key="combo_screen_full_quantity")
30
+ with col6:
31
+ item_price = st.number_input("Item Cost (Fixed)", min_value=0.0, step=0.01, key="combo_screen_full_item_price")
32
+
33
+ # Calculate Prices
34
+ # --- Screen Print ---
35
+ sp_df = sp_data[selected_type]
36
+ sp_range = next((row["Qty"] for _, row in sp_df.iterrows() if quantity <= int(row["Qty"].split()[-1])), sp_df.iloc[-1]["Qty"])
37
+ sp_row = sp_df[sp_df["Qty"] == sp_range]
38
+
39
+ sp_base_price = sp_row[selected_size].values[0] if not sp_row.empty else 0.0
40
+ sp_option_cost = sum(sp_row[opt].values[0] for opt in selected_options if opt in sp_row) if not sp_row.empty else 0.0
41
+ sp_total_price = sp_base_price + sp_option_cost
42
+
43
+ # --- Full Color ---
44
+ quantity_labels_fc = df_fc["Quantity"].tolist()
45
+ fc_range = find_quantity_range(quantity, quantity_labels_fc)
46
+ fc_print_price = float(df_fc[df_fc["Quantity"] == fc_range][print_area].values[0])
47
+
48
+ total_deco_price = sp_total_price + fc_print_price
49
+ net_value = quantity * (item_price + total_deco_price)
50
+
51
+ use_manual_margin = st.checkbox("Use Manual Margin", key="combo_screen_full_manual_margin")
52
+ if use_manual_margin:
53
+ margin_percentage = st.number_input("Enter Margin (%)", min_value=1.0, max_value=99.0, step=0.1, value=60.0, key="combo_screen_full_margin_val")
54
+ margin = margin_percentage / 100
55
+ margin_display = f"{margin_percentage:.2f}%"
56
+ else:
57
+ margin = next((rate for threshold, rate in reversed(margin_data) if net_value >= threshold), 0.67)
58
+ margin_display = f"{margin * 100:.2f}%"
59
+
60
+ total_selling_price = net_value / (1 - margin)
61
+ unit_selling_price = total_selling_price / quantity
62
+
63
+ # Add Entry
64
+ if st.button("βž• Add Entry", key="add_screen_full_entry"):
65
+ entry = {
66
+ "Quantity": quantity,
67
+ "Print Type": selected_type,
68
+ "Print Size": selected_size,
69
+ "SP Base Price": f"${sp_base_price:.2f}",
70
+ "SP Options": ", ".join(selected_options) if selected_options else "None",
71
+ "SP Option Price": f"${sp_option_cost:.2f}",
72
+ "SP Total Price": f"${sp_total_price:.2f}",
73
+ "Full Color Area": print_area,
74
+ "FC Price": f"${fc_print_price:.2f}",
75
+ "Total Decoration Cost": f"${total_deco_price:.2f}",
76
+ "Item Cost": f"${item_price:.2f}",
77
+ "Total Net Cost": f"${net_value:,.2f}",
78
+ "Margin": margin_display,
79
+ "Unit Selling Price": f"${unit_selling_price:.2f}",
80
+ "Total Selling Price": f"${total_selling_price:.2f}"
81
+ }
82
+ st.session_state.screen_full_entries.append(entry)
83
+
84
+ # Display Breakdown
85
+ if st.session_state.screen_full_entries:
86
+ st.subheader("Pricing Breakdown")
87
+ entries = st.session_state.screen_full_entries
88
+ cols = st.columns(len(entries))
89
+ for i, (col, entry) in enumerate(zip(cols, entries)):
90
+ with col:
91
+ st.markdown(f"<h4 style='color: #d31145;'>Entry {i+1}</h4>", unsafe_allow_html=True)
92
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Œ Quantity:<br><b>{entry['Quantity']}</b></div><br>", unsafe_allow_html=True)
93
+ st.markdown(f"<div style='font-size: 16px;'>πŸ–¨οΈ Screen Print Total:<br><b>{entry['SP Total Price']}</b></div><br>", unsafe_allow_html=True)
94
+ st.markdown(f"<div style='font-size: 16px;'>🎨 Full Color Price:<br><b>{entry['FC Price']}</b></div><br>", unsafe_allow_html=True)
95
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“ˆ Margin:<br><b>{entry['Margin']}</b></div><br>", unsafe_allow_html=True)
96
+ st.markdown(f"<div style='font-size: 16px;'>πŸ“Š Unit Price:<br><b>{entry['Unit Selling Price']}</b></div><br>", unsafe_allow_html=True)
97
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’° Total Net Cost:<br><b>{entry['Total Net Cost']}</b></div><br>", unsafe_allow_html=True)
98
+ st.markdown(f"<div style='font-size: 16px;'>πŸ’΅ Total Selling Price:<br><b>{entry['Total Selling Price']}</b></div><br>", unsafe_allow_html=True)
99
+ if st.button(f"❌ Delete {i+1}", key=f"delete_screen_full_{i}"):
100
+ del st.session_state.screen_full_entries[i]
101
+ st.rerun()
102
+
103
+ if st.button("πŸ”„ Reset Entries", key="reset_screen_full"):
104
+ st.session_state.screen_full_entries = []
105
+ st.rerun()
106
+
107
+ # PDF Export
108
+ html = """
109
+ <html>
110
+ <head>
111
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
112
+ <style>
113
+ .pdf-button {
114
+ background-color: #d31145;
115
+ color: white;
116
+ padding: 12px 24px;
117
+ border: none;
118
+ border-radius: 8px;
119
+ font-size: 14px;
120
+ font-weight: bold;
121
+ cursor: pointer;
122
+ transition: background-color 0.3s ease;
123
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
124
+ }
125
+ .pdf-button:hover {
126
+ background-color: #b80e3a;
127
+ }
128
+ </style>
129
+ </head>
130
+ <body>
131
+
132
+ <div id="pdf-content" style="display: none;">
133
+ <h2 style='color:#333;'>Screen Print + Full Color Pricing Breakdown</h2>
134
+ """
135
+
136
+ for i, entry in enumerate(entries):
137
+ html += f"""
138
+ <div style='margin-bottom: 20px; border:1px solid #ccc; padding: 10px; border-radius: 8px;'>
139
+ <h4 style='color:#d31145;'>Entry {i+1}</h4>
140
+ <p>πŸ“Œ Quantity: {entry['Quantity']}</p>
141
+ <p>πŸ–¨οΈ Screen Print Type: {entry['Print Type']}</p>
142
+ <p>πŸ“ Print Size: {entry['Print Size']}</p>
143
+ <p>βš™οΈ Options: {entry['SP Options']}</p>
144
+ <p>πŸ’Έ Screen Print Total: {entry['SP Total Price']}</p>
145
+ <p>🎨 Full Color Area: {entry['Full Color Area']}</p>
146
+ <p>πŸ–οΈ Full Color Price: {entry['FC Price']}</p>
147
+ <p>πŸ’° Total Net Cost: {entry['Total Net Cost']}</p>
148
+ <p>πŸ“ˆ Margin: {entry['Margin']}</p>
149
+ <p>πŸ“Š Unit Price: {entry['Unit Selling Price']}</p>
150
+ <p>πŸ’΅ Total Selling Price: {entry['Total Selling Price']}</p>
151
+ </div>
152
+ """
153
+
154
+ html += """
155
+ </div>
156
+ <button class="pdf-button" onclick="downloadPDF()">πŸ“„ Download Results as PDF</button>
157
+ <script>
158
+ function downloadPDF() {
159
+ const element = document.getElementById("pdf-content");
160
+ element.style.display = 'block';
161
+ html2pdf().set({
162
+ margin: 0.5,
163
+ filename: 'combo_screenprint_fullcolor_breakdown.pdf',
164
+ image: { type: 'jpeg', quality: 0.98 },
165
+ html2canvas: { scale: 2 },
166
+ jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
167
+ }).from(element).save().then(() => {
168
+ element.style.display = 'none';
169
+ });
170
+ }
171
+ </script>
172
+
173
+ </body>
174
+ </html>
175
+ """
176
+ st.components.v1.html(html, height=120)