-
Notifications
You must be signed in to change notification settings - Fork 539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Formula-based Final Score calculation in Appraisals #1670
feat: Formula-based Final Score calculation in Appraisals #1670
Conversation
|
||
if based_on_formula == 1: | ||
final_score = eval(sanitized_formula, vars) | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Push this up before doing anything related to the formula. Non-formula eval is lighter so makes sense to check and execute that first.
@@ -178,9 +179,35 @@ def calculate_avg_feedback_score(self, update=False): | |||
self.db_update() | |||
|
|||
def calculate_final_score(self): | |||
final_score = (flt(self.total_score) + flt(self.avg_feedback_score) + flt(self.self_score)) / 3 | |||
if self.appraisal_cycle: | |||
apraisal_cycle_doc = frappe.get_doc("Appraisal Cycle", self.appraisal_cycle) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
apraisal_cycle_doc = frappe.get_doc("Appraisal Cycle", self.appraisal_cycle) | |
appraisal_cycle_doc = frappe.get_doc("Appraisal Cycle", self.appraisal_cycle) |
fix typo everywhere
appraisal_cycle_fields = apraisal_cycle_doc.as_dict() | ||
employee_fields = employee_doc.as_dict() | ||
|
||
sanitized_formula = sanitize_expression(formula) | ||
|
||
vars = { | ||
"goal_score": flt(self.total_score), | ||
"average_feedback_score": flt(self.avg_feedback_score), | ||
"self_appraisal_score": flt(self.self_score), | ||
} | ||
|
||
vars.update(appraisal_cycle_fields) | ||
vars.update(employee_fields) | ||
|
||
vars = {key: flt(value) for (key, value) in vars.items()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
appraisal_cycle_fields = apraisal_cycle_doc.as_dict() | |
employee_fields = employee_doc.as_dict() | |
sanitized_formula = sanitize_expression(formula) | |
vars = { | |
"goal_score": flt(self.total_score), | |
"average_feedback_score": flt(self.avg_feedback_score), | |
"self_appraisal_score": flt(self.self_score), | |
} | |
vars.update(appraisal_cycle_fields) | |
vars.update(employee_fields) | |
vars = {key: flt(value) for (key, value) in vars.items()} | |
sanitized_formula = sanitize_expression(formula) | |
data = frappe._dict({ | |
"goal_score": flt(self.total_score), | |
"average_feedback_score": flt(self.avg_feedback_score), | |
"self_appraisal_score": flt(self.self_score), | |
}) | |
data.update(appraisal_cycle_doc.as_dict()) | |
data.update(self.as_dict()) | |
data.update(employee_doc.as_dict()) |
- updating as_dict() directly here saving some extra variables
- lets call vars -> data?
- Appraisal fields should also be available for eval -> added self.as_dict()
- Do we really need the flt() casting on line number 203. Not all fields in vars are float right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added flt because, adding some field that wasnt a float in expression was throwing incompatible data types error. e.g. employee.employee_name
f5173ec
to
862ebb1
Compare
862ebb1
to
5c8196f
Compare
9516507
to
51a688b
Compare
appraisal_cycle_doc = frappe.get_doc("Appraisal Cycle", self.appraisal_cycle) | ||
employee_doc = frappe.get_doc("Employee", self.employee) | ||
|
||
formula = appraisal_cycle_doc.final_score_formula | ||
based_on_formula = appraisal_cycle_doc.calculate_final_score_based_on_formula |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this inside the else block. We don't need this at all if its not based on formula. For the formula checkbox you can do a db call directly instead of get_doc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved the statements not required to calculate the condition inside else block
012e060
to
cc42051
Compare
- remove unnecessary conditions - get cached doc for formula eval - rearrange related code blocks together
6dbdc61
to
a2c2a8c
Compare
…1670 feat: Formula-based Final Score calculation in Appraisals (backport #1670)
Description: Added field in Appraisal Cycle to calculate final score for an employee appraisal using custom formula. Checking the field makes "Final Score Formula" field visible wherein you can add a Python Expression using autocompletion suggestions for various Employee master, Appraisal and Appraisal Cycle fields. This will automatically calculate the final score when creating new Appraisal
Closes #690
docs: https://frappehr.com/docs/v14/en/appraisal-cycle