Spaces:
Sleeping
Sleeping
mattoofahaddcube
commited on
Commit
•
95bad29
1
Parent(s):
d4d782c
adding a streamlit application
Browse files- .github/workflows/hf-space.yml +19 -0
- app.py +85 -0
- constants.py +37 -0
- functions.py +248 -53
- salary_calculator.py +14 -5
.github/workflows/hf-space.yml
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Sync to Hugging Face hub
|
2 |
+
on:
|
3 |
+
push:
|
4 |
+
branches: [main]
|
5 |
+
# to run this workflow manually from the Actions tab
|
6 |
+
workflow_dispatch:
|
7 |
+
|
8 |
+
jobs:
|
9 |
+
sync-to-hub:
|
10 |
+
runs-on: ubuntu-latest
|
11 |
+
steps:
|
12 |
+
- uses: actions/checkout@v3
|
13 |
+
with:
|
14 |
+
fetch-depth: 0
|
15 |
+
lfs: true
|
16 |
+
- name: Push to hub
|
17 |
+
env:
|
18 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
19 |
+
run: git push https://mattoofahad:$HF_TOKEN@huggingface.co/spaces/mattoofahad/Net-Salary-Calculator main
|
app.py
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
|
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,
|
24 |
+
st.session_state.daily_cost_of_travel,
|
25 |
+
st.session_state.physical_days_per_week,
|
26 |
+
)
|
27 |
+
|
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 |
+
else:
|
49 |
+
st.info(
|
50 |
+
"ℹ️ Initial Desired Net Salary was calculated based on the provided parameters."
|
51 |
+
)
|
52 |
+
|
53 |
+
# Display a summary of the calculation
|
54 |
+
st.subheader("Calculation Summary")
|
55 |
+
summary_df = pd.DataFrame(
|
56 |
+
{
|
57 |
+
"Parameter": [
|
58 |
+
"Current Salary",
|
59 |
+
"Desired Increment",
|
60 |
+
"Daily Travel Cost",
|
61 |
+
"On-Site Days/Week",
|
62 |
+
"Gross Salary",
|
63 |
+
"Tax",
|
64 |
+
"Final Net Salary",
|
65 |
+
],
|
66 |
+
"Value": [
|
67 |
+
f"PKR {st.session_state.current_salary:,.2f}",
|
68 |
+
f"{st.session_state.desired_increment_percentage:.2%}",
|
69 |
+
f"PKR {st.session_state.daily_cost_of_travel:,.2f}",
|
70 |
+
f"{st.session_state.physical_days_per_week}",
|
71 |
+
f"PKR {result['gross_salary_needed']:,.2f}",
|
72 |
+
f"PKR {result['tax']:,.2f}",
|
73 |
+
f"PKR {result['final_net_salary']:,.2f}",
|
74 |
+
],
|
75 |
+
}
|
76 |
+
)
|
77 |
+
st.table(summary_df)
|
78 |
+
|
79 |
+
st.subheader("Salary Breakdown")
|
80 |
+
breakdown_data = {
|
81 |
+
"Component": ["Net Salary", "Tax"],
|
82 |
+
"Amount": [result["final_net_salary"], result["tax"]],
|
83 |
+
}
|
84 |
+
breakdown_df = pd.DataFrame(breakdown_data)
|
85 |
+
st.bar_chart(breakdown_df.set_index("Component"))
|
constants.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class Constants:
|
2 |
+
DEFAULT_CURRENT_SALARY = 100000.0
|
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),
|
10 |
+
(600000, 1200000, 0.05),
|
11 |
+
(1200000, 2200000, 0.15),
|
12 |
+
(2200000, 3200000, 0.25),
|
13 |
+
(3200000, 4100000, 0.30),
|
14 |
+
(4100000, float("inf"), 0.35),
|
15 |
+
]
|
16 |
+
|
17 |
+
class Styles:
|
18 |
+
METRIC_STYLE = """
|
19 |
+
<style>
|
20 |
+
.metric-container {
|
21 |
+
background-color: #f0f2f6;
|
22 |
+
border-radius: 7px;
|
23 |
+
padding: 10px;
|
24 |
+
margin-bottom: 10px;
|
25 |
+
}
|
26 |
+
.metric-label {
|
27 |
+
font-size: 14px;
|
28 |
+
color: #555;
|
29 |
+
margin-bottom: 5px;
|
30 |
+
}
|
31 |
+
.metric-value {
|
32 |
+
font-size: 24px;
|
33 |
+
font-weight: bold;
|
34 |
+
color: #0066cc;
|
35 |
+
}
|
36 |
+
</style>
|
37 |
+
"""
|
functions.py
CHANGED
@@ -1,53 +1,248 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
)
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from constants import Styles, Constants
|
2 |
+
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
|
9 |
+
total_tax = 0
|
10 |
+
remaining_income = annual_income
|
11 |
+
for lower, upper, rate in tax_brackets:
|
12 |
+
if remaining_income <= 0:
|
13 |
+
break
|
14 |
+
taxable_amount = min(remaining_income, upper - lower)
|
15 |
+
tax = taxable_amount * rate
|
16 |
+
total_tax += tax
|
17 |
+
remaining_income -= taxable_amount
|
18 |
+
monthly_tax = total_tax / 12
|
19 |
+
return round(monthly_tax, 2)
|
20 |
+
|
21 |
+
@staticmethod
|
22 |
+
def calculate_net_salary(gross_salary, tax_brackets):
|
23 |
+
return gross_salary - Functions.calculate_monthly_tax(
|
24 |
+
gross_salary, tax_brackets
|
25 |
+
)
|
26 |
+
|
27 |
+
@staticmethod
|
28 |
+
def calculated_initial_desired_net(
|
29 |
+
current_salary, desired_increment, daily_cost_of_travel, physical_days_per_week
|
30 |
+
):
|
31 |
+
return (current_salary + current_salary * desired_increment) + (
|
32 |
+
daily_cost_of_travel * physical_days_per_week * 4.5
|
33 |
+
)
|
34 |
+
|
35 |
+
@staticmethod
|
36 |
+
def calculate_additional_amount(initial_desired_net, tax_brackets):
|
37 |
+
gross_salary = initial_desired_net
|
38 |
+
max_iterations = 100
|
39 |
+
for _ in range(max_iterations):
|
40 |
+
net_salary = Functions.calculate_net_salary(gross_salary, tax_brackets)
|
41 |
+
if abs(net_salary - initial_desired_net) < 0.01:
|
42 |
+
break
|
43 |
+
gross_salary += initial_desired_net - net_salary
|
44 |
+
additional_amount = gross_salary - initial_desired_net
|
45 |
+
|
46 |
+
return {
|
47 |
+
"initial_desired_net": round(initial_desired_net, 2),
|
48 |
+
"gross_salary_needed": round(gross_salary, 2),
|
49 |
+
"additional_amount": round(additional_amount, 2),
|
50 |
+
"tax": round(
|
51 |
+
Functions.calculate_monthly_tax(gross_salary, tax_brackets), 2
|
52 |
+
),
|
53 |
+
"final_net_salary": round(
|
54 |
+
Functions.calculate_net_salary(gross_salary, tax_brackets), 2
|
55 |
+
),
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
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():
|
94 |
+
def reset_values():
|
95 |
+
st.session_state.user_initial_desired_net = Constants.DEFAULT_INITIAL_NET
|
96 |
+
st.session_state.valid_input = True
|
97 |
+
|
98 |
+
st.button(
|
99 |
+
"Reset Final Desired Net Salary Value",
|
100 |
+
on_click=reset_values,
|
101 |
+
use_container_width=True,
|
102 |
+
)
|
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,
|
116 |
+
key="user_initial_desired_net_state",
|
117 |
+
on_change=StreamlitFunctions.update_initial_salary_parameter,
|
118 |
+
)
|
119 |
+
|
120 |
+
@staticmethod
|
121 |
+
def reset_tax_brackets():
|
122 |
+
def reset_values():
|
123 |
+
st.session_state.tax_brackets = Constants.DEFAULT_TAX_BRACKETS
|
124 |
+
|
125 |
+
st.button(
|
126 |
+
"Reset Tax Brackets",
|
127 |
+
use_container_width=True,
|
128 |
+
on_click=reset_values,
|
129 |
+
)
|
130 |
+
|
131 |
+
@staticmethod
|
132 |
+
def reset_salary_parameters():
|
133 |
+
def reset_values():
|
134 |
+
st.session_state.current_salary = Constants.DEFAULT_CURRENT_SALARY
|
135 |
+
st.session_state.desired_increment_percentage = (
|
136 |
+
Constants.DEFAULT_INCREMENT_PERCENTAGE
|
137 |
+
)
|
138 |
+
st.session_state.daily_cost_of_travel = Constants.DEFAULT_DAILY_TRAVEL_COST
|
139 |
+
st.session_state.physical_days_per_week = Constants.DEFAULT_PHYSICAL_DAYS
|
140 |
+
|
141 |
+
st.button(
|
142 |
+
"Reset Salary Parameters Values",
|
143 |
+
use_container_width=True,
|
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,
|
159 |
+
key="current_salary_state",
|
160 |
+
on_change=update_current_salary_parameter,
|
161 |
+
)
|
162 |
+
|
163 |
+
def update_desired_increment_percentage_parameter():
|
164 |
+
st.session_state.desired_increment_percentage = (
|
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,
|
172 |
+
value=st.session_state.desired_increment_percentage,
|
173 |
+
format="%.2f",
|
174 |
+
key="desired_increment_percentage_state",
|
175 |
+
on_change=update_desired_increment_percentage_parameter,
|
176 |
+
)
|
177 |
+
|
178 |
+
def update_daily_cost_of_travel_parameter():
|
179 |
+
st.session_state.daily_cost_of_travel = (
|
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,
|
187 |
+
value=st.session_state.daily_cost_of_travel,
|
188 |
+
key="daily_cost_of_travel_state",
|
189 |
+
on_change=update_daily_cost_of_travel_parameter,
|
190 |
+
)
|
191 |
+
|
192 |
+
def update_physical_days_per_week_parameter():
|
193 |
+
st.session_state.physical_days_per_week = (
|
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,
|
201 |
+
step=1,
|
202 |
+
value=st.session_state.physical_days_per_week,
|
203 |
+
key="physical_days_per_week_state",
|
204 |
+
on_change=update_physical_days_per_week_parameter,
|
205 |
+
)
|
206 |
+
|
207 |
+
@staticmethod
|
208 |
+
def print_tax_brackets():
|
209 |
+
st.header("Tax Brackets")
|
210 |
+
tax_brackets_df = pd.DataFrame(
|
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 |
+
)
|
218 |
+
|
219 |
+
@staticmethod
|
220 |
+
def initialize_session_values():
|
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:
|
227 |
+
st.session_state.desired_increment_percentage = (
|
228 |
+
Constants.DEFAULT_INCREMENT_PERCENTAGE
|
229 |
+
)
|
230 |
+
if "daily_cost_of_travel" not in st.session_state:
|
231 |
+
st.session_state.daily_cost_of_travel = Constants.DEFAULT_DAILY_TRAVEL_COST
|
232 |
+
if "physical_days_per_week" not in st.session_state:
|
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)
|
240 |
+
st.markdown(
|
241 |
+
f"""
|
242 |
+
<div class="metric-container">
|
243 |
+
<div class="metric-label">{label}</div>
|
244 |
+
<div class="metric-value">PKR {value:,.2f}</div>
|
245 |
+
</div>
|
246 |
+
""",
|
247 |
+
unsafe_allow_html=True,
|
248 |
+
)
|
salary_calculator.py
CHANGED
@@ -1,10 +1,16 @@
|
|
1 |
-
import typer
|
2 |
from typing import Optional
|
3 |
|
4 |
-
|
|
|
|
|
|
|
5 |
|
6 |
app = typer.Typer()
|
7 |
|
|
|
|
|
|
|
|
|
8 |
|
9 |
@app.command()
|
10 |
def calculate_salary(
|
@@ -22,10 +28,13 @@ def calculate_salary(
|
|
22 |
"""
|
23 |
Calculate the additional amount needed for desired salary after tax adjustment.
|
24 |
"""
|
25 |
-
initial_desired_net = calculated_initial_desired_net(
|
26 |
-
current_salary,
|
|
|
|
|
|
|
27 |
)
|
28 |
-
result = calculate_additional_amount(initial_desired_net)
|
29 |
|
30 |
typer.echo("Salary Calculation Results")
|
31 |
typer.echo("--------------------------")
|
|
|
|
|
1 |
from typing import Optional
|
2 |
|
3 |
+
import typer
|
4 |
+
import pandas as pd
|
5 |
+
from constants import Constants
|
6 |
+
from functions import Functions
|
7 |
|
8 |
app = typer.Typer()
|
9 |
|
10 |
+
tax_brackets_df = pd.DataFrame(
|
11 |
+
Constants.DEFAULT_TAX_BRACKETS, columns=["Lower Limit", "Upper Limit", "Tax Rate"]
|
12 |
+
)
|
13 |
+
|
14 |
|
15 |
@app.command()
|
16 |
def calculate_salary(
|
|
|
28 |
"""
|
29 |
Calculate the additional amount needed for desired salary after tax adjustment.
|
30 |
"""
|
31 |
+
initial_desired_net = Functions.calculated_initial_desired_net(
|
32 |
+
current_salary,
|
33 |
+
desired_increment_percentage,
|
34 |
+
daily_cost_of_travel,
|
35 |
+
physical_days_per_week,
|
36 |
)
|
37 |
+
result = Functions.calculate_additional_amount(initial_desired_net, tax_brackets_df)
|
38 |
|
39 |
typer.echo("Salary Calculation Results")
|
40 |
typer.echo("--------------------------")
|