From 7c5cfeb56dfd758147a283fafff398dfaa990220 Mon Sep 17 00:00:00 2001 From: Horilla Date: Mon, 19 Aug 2024 09:47:30 +0530 Subject: [PATCH] [UPDT] EMPLOYEE: Dependency removal from payroll app --- .../tabs/allowance_deduction-tab.html | 469 ++++++++---------- employee/urls.py | 5 - employee/views.py | 108 +--- payroll/forms/component_forms.py | 5 +- payroll/urls/component_urls.py | 5 + payroll/views/component_views.py | 128 ++++- 6 files changed, 353 insertions(+), 367 deletions(-) diff --git a/employee/templates/tabs/allowance_deduction-tab.html b/employee/templates/tabs/allowance_deduction-tab.html index 91b45321f..9785f1dd9 100644 --- a/employee/templates/tabs/allowance_deduction-tab.html +++ b/employee/templates/tabs/allowance_deduction-tab.html @@ -3,275 +3,246 @@ {% load basefilters %} {% load horillafilters %} {% if messages %} -
- {% for message in messages %} -
-
- {{ message }} +
+ {% for message in messages %} +
+
+ {{ message }} +
+ {% endfor %}
- {% endfor %} -
{% endif %}
-
    -
  • -
    -
    - - {% trans "Allowances" %} -
    -
    - {% if perms.payroll.add_allowance and active_contracts %} - - {% endif %} - -
  • -
  • -
    - - {% trans "Deductions" %} -
    - -
  • -
-
-
- - {% if allowances %} -
-
-
-
-
-
-
- {% trans "Allowance" %} -
-
-
- -
{% trans "Is Taxable" %}
-
{% trans "Is Condition Based" %}
-
{% trans "Is Fixed" %}
-
{% trans "Amount" %}
-
{% trans "Based On" %}
- {% if perms.payroll.change_allowance or perms.payroll.delete_allowance %} -
{% trans "Actions" %}
- {% endif %} +
    +
  • +
    +
    + + {% trans "Allowances" %}
    -
    - {% for allowance in allowances %} -
    -
    -
    {{allowance.title}}
    -
    - {{allowance.is_taxable|yesno|capfirst}} -
    -
    - {{allowance.is_condition_based|yesno|capfirst}} -
    -
    - {{allowance.is_fixed|yesno|capfirst}} -
    -
    - {% if allowance.amount %}{{allowance.amount}}{% endif %} -
    -
    - {% if allowance.get_based_on_display%} - {{allowance.get_based_on_display}} - {% endif %} -
    - {% if perms.payroll.change_allowance or perms.payroll.delete_allowance %} -
    -
    - - - - - - - - -
    -
    - {% endif %} -
    -
    - {% endfor %}
+ {% if perms.payroll.add_allowance and active_contracts %} + + {% endif %} + +
  • +
    + + {% trans "Deductions" %}
    - {% else %} -
    - {% if active_contracts %} - {% if basic_pay <= 0 %} -
    {% trans "Basic pay not added . Please update in the active contract." %}
    - {% else %} -
    {% trans "This employee is not eligible for any allowances." %}
    - {% endif %} - {% else %} -
    {% trans "This employee doesn't have an active contract. Please check the employee's contract" %}
    - {% endif %} -
    - {% endif %} -
  • -
    - {% if deductions %} -
    + + +
    +
    + + {% if allowances %} +
    -
    -
    -
    -
    -
    - {% trans "Deduction" %} -
    -
    -
    +
    +
    +
    +
    +
    + {% trans "Allowance" %} +
    +
    +
    -
    {% trans "Is Pretax" %}
    -
    {% trans "Is Condition Based" %}
    -
    {% trans "Condition" %}
    -
    {% trans "Is Fixed" %}
    -
    {% trans "Amount" %}
    -
    {% trans "Based On" %}
    - {% if perms.payroll.change_deduction or perms.payroll.delete_deduction %} -
    {% trans "Actions" %}
    - {% endif %} -
    -
    - {% for deduction in deductions %} -
    -
    -
    {{deduction.title}}
    - -
    - {{deduction.is_pretax|yesno|capfirst}} -
    -
    - {{deduction.is_condition_based|yesno|capfirst}} -
    -
    - {% if deduction.field %} {{deduction.get_field_display}} - {{deduction.get_condition_display}} {{deduction.value}} - {% endif %} -
    -
    - {{deduction.is_fixed|yesno|capfirst}} -
    -
    - {% if deduction.amount %} - {{deduction.amount}} - {% endif %} -
    -
    - {% if deduction.based_on %} - {{deduction.get_based_on_display}} - {% endif%} -
    - {% if perms.payroll.change_deduction or perms.payroll.delete_deduction %} -
    -
    - - - - - - +
    {% trans "Is Taxable" %}
    +
    {% trans "Is Condition Based" %}
    +
    {% trans "Is Fixed" %}
    +
    {% trans "Amount" %}
    +
    {% trans "Based On" %}
    + {% if perms.payroll.change_allowance or perms.payroll.delete_allowance %} +
    {% trans "Actions" %}
    + {% endif %}
    -
    - {% endif %}
    -
    - {% endfor %} + {% for allowance in allowances %} +
    +
    +
    {{allowance.title}}
    +
    + {{allowance.is_taxable|yesno|capfirst}} +
    +
    + {{allowance.is_condition_based|yesno|capfirst}} +
    +
    + {{allowance.is_fixed|yesno|capfirst}} +
    +
    + {% if allowance.amount %}{{allowance.amount}}{% endif %} +
    +
    + {% if allowance.get_based_on_display%} + {{allowance.get_based_on_display}} + {% endif %} +
    + {% if perms.payroll.change_allowance or perms.payroll.delete_allowance %} +
    +
    + + + + + + + + +
    +
    + {% endif %} +
    +
    + {% endfor %}
    - {% else %} -
    + {% else %} +
    {% if active_contracts %} -
    {% trans "This employee is not eligible for any deductions." %}
    - {% else %} -
    {% trans "This employee doesn't have an active contract. Please check the employee's contract" %}
    + {% if basic_pay <= 0 %} +
    + {% trans "Basic pay not added . Please update in the active contract." %} +
    + {% else %} +
    + {% trans "This employee is not eligible for any allowances." %} +
    + {% endif %} + {% else %} +
    + {% trans "This employee doesn't have an active contract. Please check the employee's contract" %} +
    {% endif %} -
    - {% endif %} -
    -
    -
    +
    + {% endif %} +
    +
    + {% if deductions %} +
    +
    +
    +
    +
    +
    +
    + {% trans "Deduction" %} +
    +
    +
    +
    {% trans "Is Pretax" %}
    +
    {% trans "Is Condition Based" %}
    +
    {% trans "Condition" %}
    +
    {% trans "Is Fixed" %}
    +
    {% trans "Amount" %}
    +
    {% trans "Based On" %}
    + {% if perms.payroll.change_deduction or perms.payroll.delete_deduction %} +
    {% trans "Actions" %}
    + {% endif %} +
    +
    + {% for deduction in deductions %} +
    +
    +
    {{deduction.title}}
    +
    + {{deduction.is_pretax|yesno|capfirst}} +
    +
    + {{deduction.is_condition_based|yesno|capfirst}} +
    +
    + {% if deduction.field %} {{deduction.get_field_display}} + {{deduction.get_condition_display}} {{deduction.value}} + {% endif %} +
    +
    + {{deduction.is_fixed|yesno|capfirst}} +
    +
    + {% if deduction.amount %} + {{deduction.amount}} + {% endif %} +
    +
    + {% if deduction.based_on %} + {{deduction.get_based_on_display}} + {% endif%} +
    + {% if perms.payroll.change_deduction or perms.payroll.delete_deduction %} +
    + +
    + {% endif %} +
    +
    + {% endfor %} +
    +
    + {% else %} +
    + {% if active_contracts %} +
    {% trans "This employee is not eligible for any deductions." %}
    + {% else %} +
    + {% trans "This employee doesn't have an active contract. Please check the employee's contract" %} +
    + {% endif %} +
    + {% endif %} +
    +
    +
    diff --git a/employee/urls.py b/employee/urls.py index 01773861d..25a1397dc 100644 --- a/employee/urls.py +++ b/employee/urls.py @@ -206,11 +206,6 @@ urlpatterns = [ views.employee_note_delete, name="employee-note-delete", ), - path( - "allowances-deductions-tab/", - views.allowances_deductions_tab, - name="allowances-deductions-tab", - ), path("shift-tab/", views.shift_tab, name="shift-tab"), path( "about-tab/", diff --git a/employee/views.py b/employee/views.py index 7dd9a9275..b15e06b28 100755 --- a/employee/views.py +++ b/employee/views.py @@ -97,7 +97,7 @@ from horilla.decorators import ( ) from horilla.filters import HorillaPaginator from horilla.group_by import group_by_queryset -from horilla.methods import dynamic_attr, get_horilla_model_class +from horilla.methods import get_horilla_model_class from horilla_audit.models import AccountBlockUnblock, HistoryTrackingFields from horilla_documents.forms import ( DocumentForm, @@ -325,112 +325,6 @@ def about_tab(request, obj_id, **kwargs): ) -@login_required -@hx_request_required -def allowances_deductions_tab(request, emp_id): - """ - Retrieve and render the allowances and deductions applicable to an employee. - - This view function retrieves the active contract, basic pay, allowances, and - deductions for a specified employee. It filters allowances and deductions - based on various conditions, including specific employee assignments and - condition-based rules. The results are then rendered in the allowance and - deduction tab template. - """ - employee = Employee.objects.get(id=emp_id) - active_contracts = ( - employee.contract_set.filter(contract_status="active").first() - if apps.is_installed("payroll") - else None - ) - basic_pay = active_contracts.wage if active_contracts else None - employee_allowances = [] - employee_deductions = [] - if basic_pay: - # Find the applicable allowances for the employee - Allowance = get_horilla_model_class(app_label="payroll", model="allowance") - specific_allowances = Allowance.objects.filter(specific_employees=employee) - conditional_allowances = Allowance.objects.filter( - is_condition_based=True - ).exclude(exclude_employees=employee) - active_employees = Allowance.objects.filter( - include_active_employees=True - ).exclude(exclude_employees=employee) - allowances = specific_allowances | conditional_allowances | active_employees - - for allowance in allowances: - if allowance.is_condition_based: - condition_field = allowance.field - condition_operator = allowance.condition - condition_value = allowance.value.lower().replace(" ", "_") - employee_value = dynamic_attr(employee, condition_field) - employee_value = 0 - operator_func = operator_mapping.get(condition_operator) - if employee_value is not None: - condition_value = type(employee_value)(condition_value) - if operator_func(employee_value, condition_value): - employee_allowances.append(allowance) - else: - employee_allowances.append(allowance) - for allowance in employee_allowances: - operator_func = operator_mapping.get(allowance.if_condition) - condition_value = basic_pay if allowance.if_choice == "basic_pay" else 0 - if not operator_func(condition_value, allowance.if_amount): - employee_allowances.remove(allowance) - - # Find the applicable deductions for the employee - Deduction = get_horilla_model_class(app_label="payroll", model="deduction") - specific_deductions = Deduction.objects.filter( - specific_employees=employee, is_pretax=True, is_tax=False - ) - conditional_deduction = Deduction.objects.filter( - is_condition_based=True, is_pretax=True, is_tax=False - ).exclude(exclude_employees=employee) - active_employee_deduction = Deduction.objects.filter( - include_active_employees=True, is_pretax=True, is_tax=False - ).exclude(exclude_employees=employee) - deductions = ( - specific_deductions | conditional_deduction | active_employee_deduction - ) - employee_deductions = list(deductions) - for deduction in deductions: - if deduction.is_condition_based: - condition_field = deduction.field - condition_operator = deduction.condition - condition_value = deduction.value.lower().replace(" ", "_") - employee_value = dynamic_attr(employee, condition_field) - employee_value = 0 - operator_func = operator_mapping.get(condition_operator) - - if ( - employee_value is not None - and not operator_func( - employee_value, type(employee_value)(condition_value) - ) - ) or employee_value is None: - employee_deductions.remove(deduction) - allowance_ids = ( - json.dumps([instance.id for instance in employee_allowances]) - if employee_allowances - else None - ) - deduction_ids = ( - json.dumps([instance.id for instance in employee_deductions]) - if employee_deductions - else None - ) - context = { - "active_contracts": active_contracts, - "basic_pay": basic_pay, - "allowances": employee_allowances if employee_allowances else None, - "allowance_ids": allowance_ids, - "deductions": employee_deductions if employee_deductions else None, - "deduction_ids": deduction_ids, - "employee": employee, - } - return render(request, "tabs/allowance_deduction-tab.html", context=context) - - @login_required @hx_request_required @owner_can_enter("perms.employee.view_employee", Employee) diff --git a/payroll/forms/component_forms.py b/payroll/forms/component_forms.py index 36acc342a..82efc7f89 100644 --- a/payroll/forms/component_forms.py +++ b/payroll/forms/component_forms.py @@ -23,8 +23,6 @@ from horilla.methods import get_horilla_model_class from horilla_widgets.forms import HorillaForm from horilla_widgets.widgets.horilla_multi_select_field import HorillaMultiSelectField from horilla_widgets.widgets.select_widgets import HorillaMultiSelectWidget - -# from leave.models import AvailableLeave, LeaveType from notifications.signals import notify from payroll.models import tax_models as models from payroll.models.models import ( @@ -845,6 +843,9 @@ class ReimbursementForm(ModelForm): {"leave_type_id": "This leave type is not encashable"} ) else: + AvailableLeave = get_horilla_model_class( + app_label="leave", model="availableleave" + ) available_leave = AvailableLeave.objects.filter( leave_type_id=leave_type_id, employee_id=employee_id ).first() diff --git a/payroll/urls/component_urls.py b/payroll/urls/component_urls.py index c3d7b8437..492785a4a 100644 --- a/payroll/urls/component_urls.py +++ b/payroll/urls/component_urls.py @@ -10,6 +10,11 @@ from payroll.models.models import Allowance, Deduction from payroll.views import component_views urlpatterns = [ + path( + "allowances-deductions-tab/", + component_views.allowances_deductions_tab, + name="allowances-deductions-tab", + ), path("create-allowance", component_views.create_allowance, name="create-allowance"), path("view-allowance/", component_views.view_allowance, name="view-allowance"), path( diff --git a/payroll/views/component_views.py b/payroll/views/component_views.py index b88f06cf8..fb1486c30 100644 --- a/payroll/views/component_views.py +++ b/payroll/views/component_views.py @@ -35,7 +35,7 @@ from horilla.decorators import ( permission_required, ) from horilla.group_by import group_by_queryset -from horilla.methods import get_horilla_model_class +from horilla.methods import dynamic_attr, get_horilla_model_class # from leave.models import AvailableLeave from notifications.signals import notify @@ -227,6 +227,126 @@ def payroll_calculation(employee, start_date, end_date): return payslip_data +@login_required +@hx_request_required +def allowances_deductions_tab(request, emp_id): + """ + Retrieve and render the allowances and deductions applicable to an employee. + + This view function retrieves the active contract, basic pay, allowances, and + deductions for a specified employee. It filters allowances and deductions + based on various conditions, including specific employee assignments and + condition-based rules. The results are then rendered in the allowance and + deduction tab template. + """ + employee_deductions = [] + employee_allowances = [] + employee = Employee.objects.get(id=emp_id) + active_contracts = employee.contract_set.filter(contract_status="active").first() + basic_pay = active_contracts.wage if active_contracts else None + if basic_pay: + allowances = ( + Allowance.objects.filter(specific_employees=employee) + | Allowance.objects.filter(is_condition_based=True).exclude( + exclude_employees=employee + ) + | Allowance.objects.filter(include_active_employees=True).exclude( + exclude_employees=employee + ) + ) + + for allowance in allowances: + applicable = True + if allowance.is_condition_based: + conditions = list( + allowance.other_conditions.values_list( + "field", "condition", "value" + ) + ) + conditions.append( + ( + allowance.field, + allowance.condition, + allowance.value.lower().replace(" ", "_"), + ) + ) + for field, operator, value in conditions: + val = dynamic_attr(employee, field) + if val is None or not operator_mapping.get(operator)( + val, type(val)(value) + ): + applicable = False + break + if applicable: + employee_allowances.append(allowance) + employee_allowances = [ + allowance + for allowance in employee_allowances + if operator_mapping.get(allowance.if_condition)( + basic_pay if allowance.if_choice == "basic_pay" else 0, + allowance.if_amount, + ) + ] + + # Find the applicable deductions for the employee + deductions = ( + Deduction.objects.filter( + specific_employees=employee, + ) + | Deduction.objects.filter( + is_condition_based=True, + ).exclude(exclude_employees=employee) + | Deduction.objects.filter( + include_active_employees=True, + ).exclude(exclude_employees=employee) + ) + for deduction in deductions: + applicable = True + if deduction.is_condition_based: + conditions = list( + deduction.other_conditions.values_list( + "field", "condition", "value" + ) + ) + conditions.append( + ( + deduction.field, + deduction.condition, + deduction.value.lower().replace(" ", "_"), + ) + ) + for field, operator, value in conditions: + val = dynamic_attr(employee, field) + if val is None or not operator_mapping.get(operator)( + val, type(val)(value) + ): + applicable = False + break + if applicable: + employee_deductions.append(deduction) + + allowance_ids = ( + json.dumps([instance.id for instance in employee_deductions]) + if employee_deductions + else None + ) + deduction_ids = ( + json.dumps([instance.id for instance in employee_deductions]) + if employee_deductions + else None + ) + context = { + "active_contracts": active_contracts, + "basic_pay": basic_pay, + "allowances": employee_allowances if employee_allowances else None, + "allowance_ids": allowance_ids, + "deductions": employee_deductions if employee_deductions else None, + "deduction_ids": deduction_ids, + "employee": employee, + } + return render(request, "tabs/allowance_deduction-tab.html", context=context) + + @login_required @permission_required("payroll.add_allowance") def create_allowance(request): @@ -439,7 +559,7 @@ def view_single_deduction(request, deduction_id): try: employee_id = int(HTTP_REFERERS[-1]) context["close_hx_url"] = ( - f"/employee/allowances-deductions-tab/{employee_id}" + f"/payroll/allowances-deductions-tab/{employee_id}" ) context["close_hx_target"] = "#allowance_deduction" except ValueError: @@ -447,7 +567,7 @@ def view_single_deduction(request, deduction_id): elif HTTP_REFERER.endswith("employee-profile/"): context["close_hx_url"] = ( - f"/employee/allowances-deductions-tab/{request.user.employee_get.id}" + f"/payroll/allowances-deductions-tab/{request.user.employee_get.id}" ) context["close_hx_target"] = "#allowance_deduction" @@ -530,7 +650,7 @@ def delete_deduction(request, deduction_id, emp_id=None): paths = { "payroll-deduction-container": f"/payroll/filter-deduction?{request.GET.urlencode()}", - "allowance_deduction": f"/employee/allowances-deductions-tab/{emp_id}", + "allowance_deduction": f"/payroll/allowances-deductions-tab/{emp_id}", "objectDetailsModalTarget": f"/payroll/single-deduction-view/{next_instance}?instances_ids={instances_list}", } http_hx_target = request.META.get("HTTP_HX_TARGET")