mattoofahaddcube commited on
Commit
b398e78
1 Parent(s): 5858a75

adding individual buttons

Browse files
Files changed (3) hide show
  1. app.py +76 -31
  2. constants.py +2 -1
  3. functions.py +68 -35
app.py CHANGED
@@ -3,21 +3,55 @@ import streamlit as st
3
  from functions import Functions, StreamlitFunctions
4
  import pandas as pd
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  StreamlitFunctions.initialize_session_values()
7
  StreamlitFunctions.print_tax_brackets()
8
  StreamlitFunctions.reset_tax_brackets()
9
 
10
  StreamlitFunctions.print_salary_parameters()
11
  StreamlitFunctions.reset_salary_parameters()
 
 
 
 
 
12
 
13
  StreamlitFunctions.initial_salary_parameter()
14
  StreamlitFunctions.reset_initial_salary_parameter()
15
- StreamlitFunctions.check_initial_salary_parameter()
 
 
 
 
16
 
17
- if st.button("Calculate", use_container_width=True) and st.session_state.valid_input:
18
- if st.session_state.user_initial_desired_net > 0:
 
 
 
 
 
 
 
 
 
 
 
 
19
  initial_desired_net = st.session_state.user_initial_desired_net
20
- else:
21
  initial_desired_net = Functions.calculated_initial_desired_net(
22
  st.session_state.current_salary,
23
  st.session_state.desired_increment_percentage,
@@ -28,23 +62,31 @@ if st.button("Calculate", use_container_width=True) and st.session_state.valid_i
28
  result = Functions.calculate_additional_amount(
29
  initial_desired_net, st.session_state.tax_brackets
30
  )
31
- st.header("Salary Calculation Results")
32
- col1, col2 = st.columns(2)
33
- with col1:
34
- # custom_metric("Initial Desired Net Salary", result['initial_desired_net'])
35
- StreamlitFunctions.custom_metric("Final Net Salary", result["final_net_salary"])
36
- StreamlitFunctions.custom_metric("Tax", result["tax"])
37
-
38
- with col2:
39
- # custom_metric("Additional Amount Needed", result['additional_amount'])
40
- StreamlitFunctions.custom_metric(
41
- "Gross Salary Needed", result["gross_salary_needed"]
42
- )
43
 
44
  # Display how initial_desired_net was determined
45
  st.markdown("---")
46
- if st.session_state.user_initial_desired_net > 0:
47
- st.success("✅ Initial Desired Net Salary was provided by the user.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  summary_df = pd.DataFrame(
49
  {
50
  "Parameter": [
@@ -59,9 +101,9 @@ if st.button("Calculate", use_container_width=True) and st.session_state.valid_i
59
  ],
60
  }
61
  )
62
- else:
63
- st.info(
64
- "ℹ️ Initial Desired Net Salary was calculated based on the provided parameters."
65
  )
66
  summary_df = pd.DataFrame(
67
  {
@@ -85,16 +127,19 @@ if st.button("Calculate", use_container_width=True) and st.session_state.valid_i
85
  ],
86
  }
87
  )
 
 
 
 
 
 
88
 
 
 
 
 
 
89
  # Display a summary of the calculation
90
  st.subheader("Calculation Summary")
91
-
92
- st.table(summary_df)
93
-
94
- st.subheader("Salary Breakdown")
95
- breakdown_data = {
96
- "Component": ["Net Salary", "Tax"],
97
- "Amount": [result["final_net_salary"], result["tax"]],
98
- }
99
- breakdown_df = pd.DataFrame(breakdown_data)
100
- st.bar_chart(breakdown_df.set_index("Component"))
 
3
  from functions import Functions, StreamlitFunctions
4
  import pandas as pd
5
 
6
+
7
+ def calculate_salary_parameters():
8
+ st.session_state.type_to_calculate = "salary_parameters"
9
+
10
+
11
+ def calculate_initial_salary_parameter():
12
+ st.session_state.type_to_calculate = "desired_salary"
13
+
14
+
15
+ def calculate_tax_on_current_salary():
16
+ st.session_state.type_to_calculate = "tax_on_current_salary"
17
+
18
+
19
  StreamlitFunctions.initialize_session_values()
20
  StreamlitFunctions.print_tax_brackets()
21
  StreamlitFunctions.reset_tax_brackets()
22
 
23
  StreamlitFunctions.print_salary_parameters()
24
  StreamlitFunctions.reset_salary_parameters()
25
+ st.button(
26
+ "Calculate Based on Salary Parameters",
27
+ use_container_width=True,
28
+ on_click=calculate_salary_parameters,
29
+ )
30
 
31
  StreamlitFunctions.initial_salary_parameter()
32
  StreamlitFunctions.reset_initial_salary_parameter()
33
+ st.button(
34
+ "Calculate Based on Desired Net Salary",
35
+ use_container_width=True,
36
+ on_click=calculate_initial_salary_parameter,
37
+ )
38
 
39
+ StreamlitFunctions.print_tax_on_current_salary()
40
+ StreamlitFunctions.reset_tax_on_current_salary()
41
+ st.button(
42
+ "Calculate Tax on Current Salary",
43
+ use_container_width=True,
44
+ on_click=calculate_tax_on_current_salary,
45
+ )
46
+
47
+ if st.session_state.type_to_calculate is not None:
48
+ if st.session_state.type_to_calculate == "tax_on_current_salary":
49
+ initial_desired_net = Functions.calculated_current_salary_after_tax(
50
+ st.session_state.tax_on_current_salary, st.session_state.tax_brackets
51
+ )
52
+ elif st.session_state.type_to_calculate == "desired_salary":
53
  initial_desired_net = st.session_state.user_initial_desired_net
54
+ elif st.session_state.type_to_calculate == "salary_parameters":
55
  initial_desired_net = Functions.calculated_initial_desired_net(
56
  st.session_state.current_salary,
57
  st.session_state.desired_increment_percentage,
 
62
  result = Functions.calculate_additional_amount(
63
  initial_desired_net, st.session_state.tax_brackets
64
  )
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  # Display how initial_desired_net was determined
67
  st.markdown("---")
68
+ if st.session_state.type_to_calculate == "tax_on_current_salary":
69
+ st.success(
70
+ "✅ Calculation was done based on the selected value of 'Tax on Current Salary'"
71
+ )
72
+ summary_df = pd.DataFrame(
73
+ {
74
+ "Parameter": [
75
+ "Current Salary",
76
+ "Tax",
77
+ "Gross Salary",
78
+ ],
79
+ "Value": [
80
+ f"PKR {result['final_net_salary']:,.2f}",
81
+ f"PKR {result['tax']:,.2f}",
82
+ f"PKR {result['gross_salary_needed']:,.2f}",
83
+ ],
84
+ }
85
+ )
86
+ elif st.session_state.type_to_calculate == "desired_salary":
87
+ st.success(
88
+ "✅ Calculation was done based on the selected value of 'Final Desired Net Salary'"
89
+ )
90
  summary_df = pd.DataFrame(
91
  {
92
  "Parameter": [
 
101
  ],
102
  }
103
  )
104
+ elif st.session_state.type_to_calculate == "salary_parameters":
105
+ st.success(
106
+ " Calculation was done based on the selected values of 'Salary Parameters'"
107
  )
108
  summary_df = pd.DataFrame(
109
  {
 
127
  ],
128
  }
129
  )
130
+ st.header("Salary Calculation Results")
131
+ col1, col2 = st.columns(2)
132
+ with col1:
133
+ # custom_metric("Initial Desired Net Salary", result['initial_desired_net'])
134
+ StreamlitFunctions.custom_metric("Final Net Salary", result["final_net_salary"])
135
+ StreamlitFunctions.custom_metric("Tax", result["tax"])
136
 
137
+ with col2:
138
+ # custom_metric("Additional Amount Needed", result['additional_amount'])
139
+ StreamlitFunctions.custom_metric(
140
+ "Gross Salary Needed", result["gross_salary_needed"]
141
+ )
142
  # Display a summary of the calculation
143
  st.subheader("Calculation Summary")
144
+ st.data_editor(summary_df, use_container_width=True, hide_index=True)
145
+ st.session_state.type_to_calculate = None
 
 
 
 
 
 
 
 
constants.py CHANGED
@@ -3,7 +3,8 @@ class Constants:
3
  DEFAULT_INCREMENT_PERCENTAGE = 0.3
4
  DEFAULT_DAILY_TRAVEL_COST = 1500
5
  DEFAULT_PHYSICAL_DAYS = 5
6
- DEFAULT_INITIAL_NET = 0.0
 
7
 
8
  DEFAULT_TAX_BRACKETS = [
9
  (0, 600000, 0),
 
3
  DEFAULT_INCREMENT_PERCENTAGE = 0.3
4
  DEFAULT_DAILY_TRAVEL_COST = 1500
5
  DEFAULT_PHYSICAL_DAYS = 5
6
+ DEFAULT_INITIAL_NET = 212500.0
7
+ DEFAULT_CURRENT_SALARY_WITH_TAX = 200000.0
8
 
9
  DEFAULT_TAX_BRACKETS = [
10
  (0, 600000, 0),
functions.py CHANGED
@@ -3,6 +3,12 @@ import streamlit as st
3
 
4
 
5
  class Functions:
 
 
 
 
 
 
6
  @staticmethod
7
  def calculate_monthly_tax(monthly_income, tax_brackets):
8
  annual_income = monthly_income * 12
@@ -60,34 +66,20 @@ import pandas as pd
60
 
61
 
62
  class StreamlitFunctions:
63
- @staticmethod
64
- def check_initial_salary_parameter():
65
- if (
66
- st.session_state.user_initial_desired_net > 0
67
- and st.session_state.user_initial_desired_net
68
- <= st.session_state.current_salary
69
- ):
70
- st.warning(
71
- "⚠️ The Initial Desired Net Salary should be greater than your Current Salary. Please adjust your input or leave it at 0 to calculate automatically."
72
- )
73
- st.session_state.valid_input = False
74
- else:
75
- st.session_state.valid_input = True
76
-
77
  @staticmethod
78
  def update_initial_salary_parameter():
79
- if (
 
 
 
 
 
 
 
 
 
80
  st.session_state.user_initial_desired_net_state
81
- < st.session_state.current_salary
82
- ):
83
- st.session_state.user_initial_desired_net = (
84
- st.session_state.current_salary
85
- + st.session_state.user_initial_desired_net_state
86
- )
87
- else:
88
- st.session_state.user_initial_desired_net = (
89
- st.session_state.user_initial_desired_net_state
90
- )
91
 
92
  @staticmethod
93
  def reset_initial_salary_parameter():
@@ -103,13 +95,13 @@ class StreamlitFunctions:
103
 
104
  @staticmethod
105
  def initial_salary_parameter():
106
- st.header("Calculation based on Final Desired Net Salary")
107
  if st.session_state.user_initial_desired_net >= st.session_state.current_salary:
108
  minimum_value = st.session_state.current_salary
109
  else:
110
  minimum_value = 0.0
111
  st.number_input(
112
- "Final Desired Net Salary (PKR, optional)",
113
  min_value=minimum_value,
114
  value=st.session_state.user_initial_desired_net,
115
  step=1000.0,
@@ -144,15 +136,46 @@ class StreamlitFunctions:
144
  on_click=reset_values,
145
  )
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  @staticmethod
148
  def print_salary_parameters():
149
- st.header("Calculation Based on Salary Parameters")
150
 
151
  def update_current_salary_parameter():
152
  st.session_state.current_salary = st.session_state.current_salary_state
153
 
154
- st.session_state.current_salary = st.number_input(
155
- "Current monthly salary (PKR)",
156
  min_value=0.0,
157
  step=1000.0,
158
  value=st.session_state.current_salary,
@@ -165,7 +188,7 @@ class StreamlitFunctions:
165
  st.session_state.desired_increment_percentage_state
166
  )
167
 
168
- st.session_state.desired_increment_percentage = st.number_input(
169
  "Desired salary increment (as a decimal)",
170
  min_value=0.0,
171
  step=0.05,
@@ -180,7 +203,7 @@ class StreamlitFunctions:
180
  st.session_state.daily_cost_of_travel_state
181
  )
182
 
183
- st.session_state.daily_cost_of_travel = st.number_input(
184
  "Daily cost of travel (PKR)",
185
  min_value=0,
186
  step=100,
@@ -194,7 +217,7 @@ class StreamlitFunctions:
194
  st.session_state.physical_days_per_week_state
195
  )
196
 
197
- st.session_state.physical_days_per_week = st.number_input(
198
  "Number of On-Site days per week",
199
  min_value=0,
200
  max_value=7,
@@ -211,7 +234,10 @@ class StreamlitFunctions:
211
  st.session_state.tax_brackets,
212
  columns=["Lower Limit", "Upper Limit", "Tax Rate"],
213
  )
214
- edited_tax_brackets = st.data_editor(tax_brackets_df, num_rows="dynamic")
 
 
 
215
  st.session_state.tax_brackets = list(
216
  edited_tax_brackets.itertuples(index=False, name=None)
217
  )
@@ -221,6 +247,10 @@ class StreamlitFunctions:
221
  st.title("Net Salary Calculator")
222
  if "tax_brackets" not in st.session_state:
223
  st.session_state.tax_brackets = Constants.DEFAULT_TAX_BRACKETS
 
 
 
 
224
  if "current_salary" not in st.session_state:
225
  st.session_state.current_salary = Constants.DEFAULT_CURRENT_SALARY
226
  if "desired_increment_percentage" not in st.session_state:
@@ -233,7 +263,10 @@ class StreamlitFunctions:
233
  st.session_state.physical_days_per_week = Constants.DEFAULT_PHYSICAL_DAYS
234
  if "user_initial_desired_net" not in st.session_state:
235
  st.session_state.user_initial_desired_net = Constants.DEFAULT_INITIAL_NET
236
-
 
 
 
237
  @staticmethod
238
  def custom_metric(label, value):
239
  st.markdown(Styles.METRIC_STYLE, unsafe_allow_html=True)
 
3
 
4
 
5
  class Functions:
6
+ @staticmethod
7
+ def calculated_current_salary_after_tax(current_salary, tax_brackets):
8
+ return current_salary - Functions.calculate_monthly_tax(
9
+ current_salary, tax_brackets
10
+ )
11
+
12
  @staticmethod
13
  def calculate_monthly_tax(monthly_income, tax_brackets):
14
  annual_income = monthly_income * 12
 
66
 
67
 
68
  class StreamlitFunctions:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  @staticmethod
70
  def update_initial_salary_parameter():
71
+ # if (
72
+ # st.session_state.user_initial_desired_net_state
73
+ # < st.session_state.current_salary
74
+ # ):
75
+ # st.session_state.user_initial_desired_net = (
76
+ # st.session_state.current_salary
77
+ # + st.session_state.user_initial_desired_net_state
78
+ # )
79
+ # else:
80
+ st.session_state.user_initial_desired_net = (
81
  st.session_state.user_initial_desired_net_state
82
+ )
 
 
 
 
 
 
 
 
 
83
 
84
  @staticmethod
85
  def reset_initial_salary_parameter():
 
95
 
96
  @staticmethod
97
  def initial_salary_parameter():
98
+ st.header("Final Desired Net Salary")
99
  if st.session_state.user_initial_desired_net >= st.session_state.current_salary:
100
  minimum_value = st.session_state.current_salary
101
  else:
102
  minimum_value = 0.0
103
  st.number_input(
104
+ "Final Desired Net Salary (PKR)",
105
  min_value=minimum_value,
106
  value=st.session_state.user_initial_desired_net,
107
  step=1000.0,
 
136
  on_click=reset_values,
137
  )
138
 
139
+ @staticmethod
140
+ def reset_tax_on_current_salary():
141
+ def reset_values():
142
+ st.session_state.tax_on_current_salary = (
143
+ Constants.DEFAULT_CURRENT_SALARY_WITH_TAX
144
+ )
145
+
146
+ st.button(
147
+ "Reset Current Salary",
148
+ use_container_width=True,
149
+ on_click=reset_values,
150
+ )
151
+
152
+ @staticmethod
153
+ def print_tax_on_current_salary():
154
+ st.header("Tax on Current Salary")
155
+
156
+ def update_tax_on_current_salary_parameter():
157
+ st.session_state.tax_on_current_salary = (
158
+ st.session_state.tax_on_current_salary_state
159
+ )
160
+
161
+ st.number_input(
162
+ "Current monthly Salary (PKR)",
163
+ min_value=0.0,
164
+ step=1000.0,
165
+ value=st.session_state.tax_on_current_salary,
166
+ key="tax_on_current_salary_state",
167
+ on_change=update_tax_on_current_salary_parameter,
168
+ )
169
+
170
  @staticmethod
171
  def print_salary_parameters():
172
+ st.header("Salary Parameters")
173
 
174
  def update_current_salary_parameter():
175
  st.session_state.current_salary = st.session_state.current_salary_state
176
 
177
+ st.number_input(
178
+ "Current monthly salary after Tax (PKR)",
179
  min_value=0.0,
180
  step=1000.0,
181
  value=st.session_state.current_salary,
 
188
  st.session_state.desired_increment_percentage_state
189
  )
190
 
191
+ st.number_input(
192
  "Desired salary increment (as a decimal)",
193
  min_value=0.0,
194
  step=0.05,
 
203
  st.session_state.daily_cost_of_travel_state
204
  )
205
 
206
+ st.number_input(
207
  "Daily cost of travel (PKR)",
208
  min_value=0,
209
  step=100,
 
217
  st.session_state.physical_days_per_week_state
218
  )
219
 
220
+ st.number_input(
221
  "Number of On-Site days per week",
222
  min_value=0,
223
  max_value=7,
 
234
  st.session_state.tax_brackets,
235
  columns=["Lower Limit", "Upper Limit", "Tax Rate"],
236
  )
237
+
238
+ edited_tax_brackets = st.data_editor(
239
+ tax_brackets_df, num_rows="dynamic", use_container_width=True
240
+ )
241
  st.session_state.tax_brackets = list(
242
  edited_tax_brackets.itertuples(index=False, name=None)
243
  )
 
247
  st.title("Net Salary Calculator")
248
  if "tax_brackets" not in st.session_state:
249
  st.session_state.tax_brackets = Constants.DEFAULT_TAX_BRACKETS
250
+ if "tax_on_current_salary" not in st.session_state:
251
+ st.session_state.tax_on_current_salary = (
252
+ Constants.DEFAULT_CURRENT_SALARY_WITH_TAX
253
+ )
254
  if "current_salary" not in st.session_state:
255
  st.session_state.current_salary = Constants.DEFAULT_CURRENT_SALARY
256
  if "desired_increment_percentage" not in st.session_state:
 
263
  st.session_state.physical_days_per_week = Constants.DEFAULT_PHYSICAL_DAYS
264
  if "user_initial_desired_net" not in st.session_state:
265
  st.session_state.user_initial_desired_net = Constants.DEFAULT_INITIAL_NET
266
+
267
+ if "type_to_calculate" not in st.session_state:
268
+ st.session_state.type_to_calculate = None
269
+
270
  @staticmethod
271
  def custom_metric(label, value):
272
  st.markdown(Styles.METRIC_STYLE, unsafe_allow_html=True)