[UPDT] PAYROLL: Add contribution report

This commit is contained in:
Horilla
2024-01-31 16:20:15 +05:30
parent 1539a3ae09
commit a34aa73d50
12 changed files with 393 additions and 143 deletions

View File

@@ -3,7 +3,9 @@ context_processor.py
This module is used to register context processor`
"""
from employee.models import Employee
from payroll.models import tax_models as models
from payroll.models.models import Deduction
def default_currency(request):
@@ -24,3 +26,21 @@ def host(request):
"""
protocol = "https" if request.is_secure() else "http"
return {"host": request.get_host(), "protocol": protocol}
def get_deductions(request):
"""
This method used to return the deduction
"""
deductions = Deduction.objects.filter(
only_show_under_employee=False, employer_rate__gt=0
)
return {"get_deductions": deductions}
def get_active_employees(request):
"""
This method used to return the deduction
"""
employees = Employee.objects.filter(is_active=True)
return {"get_active_employees": employees}

View File

@@ -204,6 +204,9 @@ class PayslipForm(ModelForm):
for contract in active_contracts
if contract.employee_id.is_active
]
if self.instance.pk is None:
self.initial["start_date"] = datetime.date.today().replace(day=1)
self.initial["end_date"] = datetime.date.today()
class Meta:
"""
@@ -281,6 +284,8 @@ class GeneratePayslipForm(HorillaForm):
self.fields["start_date"].widget.attrs.update({"class": "oh-input w-100"})
self.fields["group_name"].widget.attrs.update({"class": "oh-input w-100"})
self.fields["end_date"].widget.attrs.update({"class": "oh-input w-100"})
self.initial["start_date"] = datetime.date.today().replace(day=1)
self.initial["end_date"] = datetime.date.today()
class Meta:
"""
@@ -420,7 +425,9 @@ class PayslipDeductionForm(ModelForm):
"""
Bonus Creating Form
"""
verbose_name = _("Deduction")
class Meta:
model = Deduction
fields = [
@@ -450,7 +457,7 @@ class PayslipDeductionForm(ModelForm):
context = {"form": self}
table_html = render_to_string("one_time_deduction.html", context)
return table_html
class LoanAccountForm(ModelForm):
"""

View File

@@ -1,6 +1,7 @@
"""
forms.py
"""
from django import forms
from django.forms import widgets
from django.utils.translation import gettext_lazy as trans
@@ -65,7 +66,7 @@ class ContractForm(ModelForm):
verbose_name = trans("Contract")
contract_start_date = forms.DateField()
contract_end_date = forms.DateField()
contract_end_date = forms.DateField(required=False)
class Meta:
"""
@@ -97,6 +98,20 @@ class ContractForm(ModelForm):
"placeholder": "Select a date",
}
)
self.fields["contract_status"].widget.attrs.update(
{
"class": "oh-select",
}
)
if self.instance and self.instance.pk:
dynamic_url = self.get_dynamic_hx_post_url(self.instance)
self.fields["contract_status"].widget.attrs.update(
{
"hx-target": "#contractFormTarget",
"hx-post": dynamic_url,
"hx-swap": "outerHTML",
}
)
first = PayrollGeneralSetting.objects.first()
if first and self.instance.pk is None:
self.initial["notice_period_in_month"] = first.notice_period
@@ -109,6 +124,9 @@ class ContractForm(ModelForm):
table_html = render_to_string("contract_form.html", context)
return table_html
def get_dynamic_hx_post_url(self, instance):
return f"/payroll/update-contract-status/{instance.pk}"
class WorkRecordForm(ModelForm):
"""

View File

@@ -9,6 +9,12 @@ from horilla.settings import TEMPLATES
TEMPLATES[0]["OPTIONS"]["context_processors"].append(
"payroll.context_processors.default_currency",
)
TEMPLATES[0]["OPTIONS"]["context_processors"].append(
"payroll.context_processors.get_deductions",
)
TEMPLATES[0]["OPTIONS"]["context_processors"].append(
"payroll.context_processors.get_active_employees",
)
TEMPLATES[0]["OPTIONS"]["context_processors"].append(
"payroll.context_processors.host",
)

View File

@@ -8,6 +8,9 @@
{{ form.verbose_name }}
</div>
</div>
<div class="oh-payslip__header-right">
{{ form.contract_status }}
</div>
</div>
<div class="oh-profile-section__card">
<div class="row">
@@ -16,6 +19,7 @@
</div>
{% for field in form.visible_fields %}
{% if field.name != 'contract_status' %}
<div class="col-12 col-md-6">
<div class="oh-label__info" for="id_{{ field.name }}">
<label class="oh-label" for="id_{{ field.name }}">{% trans field.label %}</label>
@@ -31,6 +35,7 @@
{% else %} {{ field|add_class:"form-control" }} {% endif %}
{{field.errors}}
</div>
{% endif %}
{% endfor %}
</div>

View File

@@ -1,99 +1,99 @@
{% extends 'index.html' %} {% block content %} {% load static %}
<div id="contractFormTarget">
<div class="oh-wrapper d-flex justify-content-center mt-4 mb-4">
<form action="" hx-swap="none" class="oh-onboarding-card" method="post">
{% csrf_token %} {{form.as_p}}
</form>
</div>
<script>
function toggleFunction() {
if ($("#id_calculate_daily_leave_amount").is(":checked")) {
$(
"#id_deduction_for_one_leave_amount,[for=id_deduction_for_one_leave_amount]"
).hide();
} else {
$(
"#id_deduction_for_one_leave_amount,[for=id_deduction_for_one_leave_amount]"
).show();
}
if ($("#id_calculate_daily_leave_amount").is(":checked")) {
$("#id_deduction_for_one_leave_amount").parent().hide();
} else {
$("#id_deduction_for_one_leave_amount").parent().show();
}
}
function contractInitial(element) {
var employee_id = $(element).val();
$.ajax({
type: "GET",
url: "{% url 'contract-info-initial' %}",
data: { employee_id: employee_id },
success: function (response) {
var data;
data = response;
const change = new Event('change');
$("#id_department").val(data.department);
document.getElementById("id_department").dispatchEvent(change)
$("#id_job_position").val(data.job_position);
document.getElementById("id_job_position").dispatchEvent(change)
$("#id_job_role").val(data.job_role);
document.getElementById("id_job_role").dispatchEvent(change)
$("#id_shift").val(data.shift);
document.getElementById("id_shift").dispatchEvent(change)
$("#id_work_type").val(data.work_type);
document.getElementById("id_work_type").dispatchEvent(change)
$("#id_wage").val(data.wage);
document.getElementById("id_wage").dispatchEvent(change)
$("#id_contract_start_date").val(data.contract_start_date);
document.getElementById("id_contract_start_date").dispatchEvent(change)
$("#id_contract_end_date").val(data.contract_end_date);
document.getElementById("id_contract_end_date").dispatchEvent(change)
},
});
}
<div class="oh-wrapper d-flex justify-content-center mt-4 mb-4">
<form action="" hx-swap="none" class="oh-onboarding-card" method="post">
{% csrf_token %} {{form.as_p}}
</form>
</div>
<script>
function toggleFunction() {
if ($("#id_calculate_daily_leave_amount").is(":checked")) {
$(
"#id_deduction_for_one_leave_amount,[for=id_deduction_for_one_leave_amount]"
).hide();
} else {
$(
"#id_deduction_for_one_leave_amount,[for=id_deduction_for_one_leave_amount]"
).show();
}
if ($("#id_calculate_daily_leave_amount").is(":checked")) {
$("#id_deduction_for_one_leave_amount").parent().hide();
} else {
$("#id_deduction_for_one_leave_amount").parent().show();
}
}
function contractInitial(element) {
var employee_id = $(element).val();
$.ajax({
type: "GET",
url: "{% url 'contract-info-initial' %}",
data: { employee_id: employee_id },
success: function (response) {
var data;
data = response;
const change = new Event('change');
$("#id_department").val(data.department);
document.getElementById("id_department").dispatchEvent(change)
$("#id_job_position").val(data.job_position);
document.getElementById("id_job_position").dispatchEvent(change)
$("#id_job_role").val(data.job_role);
document.getElementById("id_job_role").dispatchEvent(change)
$("#id_shift").val(data.shift);
document.getElementById("id_shift").dispatchEvent(change)
$("#id_work_type").val(data.work_type);
document.getElementById("id_work_type").dispatchEvent(change)
$("#id_wage").val(data.wage);
document.getElementById("id_wage").dispatchEvent(change)
$("#id_contract_start_date").val(data.contract_start_date);
document.getElementById("id_contract_start_date").dispatchEvent(change)
$("#id_contract_end_date").val(data.contract_end_date);
document.getElementById("id_contract_end_date").dispatchEvent(change)
},
});
}
$(document).ready(function () {
$("[type=checkbox]").change(function (e) {
e.preventDefault();
$(document).ready(function () {
$("[type=checkbox]").change(function (e) {
e.preventDefault();
toggleFunction();
});
});
toggleFunction();
});
});
toggleFunction();
{% if form.instance.pk %}
{% if form.instance.pk %}
{% for condition in form.instance.other_conditions.all %}
conditionSet = $(
`
<div class="row">
<div class="col-12 col-md-4 condition-highlight">
${$("[for=id_field]").clone().attr("class", "style-widget form-control oh-label__info").prop("outerHTML")}
${$("#id_field").clone().attr("data-initial-value", "{{condition.field}}").attr("name", "other_fields").attr("class", "style-widget form-control").prop("outerHTML")}
</div>
<div class="col-12 col-md-4 condition-highlight">
${$("[for=id_condition]").clone().attr("class", "style-widget form-control oh-label__info").prop("outerHTML")}
${$("#id_condition").clone().attr("data-initial-value", "{{condition.condition}}").attr("class", "style-widget form-control").attr("name", "other_conditions").attr("class", "style-widget form-control").prop("outerHTML")}
</div>
<div class="col-12 col-md-4 condition-highlight">
<div class="d-flex">
${$("[for=id_value]").clone().attr("class", "style-widget form-control oh-label__info").prop("outerHTML")}
<div class="m-1 p-1" onclick="$(this).closest('.row').remove()" align="center" style="border-radius:15px; width:25px;border:solid 1px red;cursor:pointer;display:inline;">
-
{% for condition in form.instance.other_conditions.all %}
conditionSet = $(
`
<div class="row">
<div class="col-12 col-md-4 condition-highlight">
${$("[for=id_field]").clone().attr("class", "style-widget form-control oh-label__info").prop("outerHTML")}
${$("#id_field").clone().attr("data-initial-value", "{{condition.field}}").attr("name", "other_fields").attr("class", "style-widget form-control").prop("outerHTML")}
</div>
<div class="col-12 col-md-4 condition-highlight">
${$("[for=id_condition]").clone().attr("class", "style-widget form-control oh-label__info").prop("outerHTML")}
${$("#id_condition").clone().attr("data-initial-value", "{{condition.condition}}").attr("class", "style-widget form-control").attr("name", "other_conditions").attr("class", "style-widget form-control").prop("outerHTML")}
</div>
<div class="col-12 col-md-4 condition-highlight">
<div class="d-flex">
${$("[for=id_value]").clone().attr("class", "style-widget form-control oh-label__info").prop("outerHTML")}
<div class="m-1 p-1" onclick="$(this).closest('.row').remove()" align="center" style="border-radius:15px; width:25px;border:solid 1px red;cursor:pointer;display:inline;">
-
</div>
</div>
${$("#id_value").clone().attr("data-initial-value", "{{condition.value}}").attr("name", "other_values").attr("value", "{{condition.value}}").change().attr("class", "style-widget form-control").prop("outerHTML")}
</div>
</div>
${$("#id_value").clone().attr("data-initial-value", "{{condition.value}}").attr("name", "other_values").attr("value", "{{condition.value}}").change().attr("class", "style-widget form-control").prop("outerHTML")}
</div>
</div>
`
);
$("#conditionContainer").prepend(conditionSet)
{% endfor %}
function initialData () {
$.each($("[name=other_fields],[name=other_conditions]"), function (indexInArray, valueOfElement) {
$(valueOfElement).val($(valueOfElement).attr("data-initial-value")).change()
});
}
initialData()
{% endif %}
</script>
{% endblock content %}
`
);
$("#conditionContainer").prepend(conditionSet)
{% endfor %}
function initialData () {
$.each($("[name=other_fields],[name=other_conditions]"), function (indexInArray, valueOfElement) {
$(valueOfElement).val($(valueOfElement).attr("data-initial-value")).change()
});
}
initialData()
{% endif %}
</script>
</div>
{% endblock content %}

View File

@@ -171,6 +171,40 @@
</div>
</div>
<div class="col-12 col-sm-12 col-md-12 col-lg-6 oh-card-dashboard--moveable mb-4">
<form hx-get="{% url 'get-contribution-report' %}" hx-trigger="load, submit" hx-target="#contributionReportContainer" class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent" >
<div class="d-flex justify-content-between oh-card-dashboard__header oh-card-dashboard__header--divider" style = "cursor: default;">
{% comment %} <span class="oh-card-dashboard__title" id="employee-previous" style = "cursor: pointer;"><ion-icon name="caret-back-outline"></ion-icon></span> {% endcomment %}
<span class="oh-card-dashboard__title">{% trans "Employer Contributions" %}</span>
<div>
<span class="oh-card-dashboard__title">
<select name="employee_id" class="oh-select" onchange="$(this).closest('form').find('[type=submit]').click()" id="deduction">
{% for employee in get_active_employees %}
{% if request.user == employee.employee_user_id %}
<option value="{{employee.id}}" selected>{{employee.get_full_name}}</option>
{% else %}
<option value="{{employee.id}}">{{employee.get_full_name}}</option>
{% endif %}
{% endfor %}
</select>
</span>
{% comment %} <span class="oh-card-dashboard__title">
<select name="deduction_id" class="oh-select" onchange="$(this).closest('form').find('[type=submit]').click()" id="deduction">
<option value="">{% trans "All" %}</option>
{% for deduction in get_deductions %}
<option value="{{deduction.id}}">{{deduction.title}}</option>
{% endfor %}
</select>
</span> {% endcomment %}
</div>
{% comment %} <span class="oh-card-dashboard__title float-end" id="payroll-employee-next" style = "cursor: pointer;"><ion-icon name="caret-forward"></ion-icon></span> {% endcomment %}
</div>
<div class="oh-card-dashboard__body" id="contributionReportContainer" >
</div>
<button type="submit" hidden>
</form>
</div>
<div class="col-12 col-sm-12 col-md-12 col-lg-6 oh-card-dashboard--moveable">
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent" style = "cursor: default;">
<h4 class="ms-4 m-2 fw-bold text-danger">{% trans "Contracts ending " %} <b><span class=""></span></b></h4>

View File

@@ -0,0 +1,39 @@
{% load i18n static %}
<div class="oh-sticky-table" style="height: 250px;">
<div class="oh-sticky-table__table oh-table--sortable">
<div class="oh-sticky-table__thead">
<div class="oh-sticky-table__tr">
<div class="oh-sticky-table__th">
{% trans 'Deduction' %}
</div>
<div class="oh-sticky-table__th">
{% trans 'Employee Contribution' %}
</div>
<div class="oh-sticky-table__th">
{% trans 'Employer Contribution' %}
</div>
</div>
</div>
<div class="oh-sticky-table__tbody">
{% for deduction in contribution_deductions %}
<div class="oh-sticky-table__tr" draggable="true">
<div class="oh-sticky-table__sd">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img src="https://ui-avatars.com/api/?name={{ deduction.title }}&background=random" class="oh-profile__image" />
</div>
<span class="oh-profile__name oh-text--dark">{{ deduction.title }}</span>
</div>
</div>
<div class="oh-sticky-table__td">{{ currency }} {{ deduction.employee_contribution }}</div>
<div class="oh-sticky-table__td">{{ currency }} {{ deduction.employer_contribution }}</div>
</div>
{% endfor %}
{% if not contribution_deductions %}
<div align="center" style="width: 720px">
<img width="100px" class="mt-5" src="{% static 'images/ui/joiningchart.png' %}" alt="" srcset="" />
</div>
{% endif %}
</div>
</div>
</div>

View File

@@ -127,4 +127,5 @@ urlpatterns = [
component_views.delete_attachments,
name="delete-attachments",
),
path("get-contribution-report",component_views.get_contribution_report,name="get-contribution-report")
]

View File

@@ -3,6 +3,7 @@ urls.py
This module is used to map url pattern or request path with view functions
"""
from django.urls import path, include
from payroll.views import views
from payroll.models.models import Contract, Payslip
@@ -18,6 +19,11 @@ urlpatterns = [
name="update-contract",
kwargs={"model": Contract},
),
path(
"update-contract-status/<int:contract_id>",
views.contract_status_update,
name="update-contract-status",
),
path(
"delete-contract/<int:contract_id>",
views.contract_delete,
@@ -126,7 +132,6 @@ urlpatterns = [
views.payslip_select_filter,
name="payslip-select-filter",
),
path(
"payroll-request-add-comment/<int:payroll_id>/",
views.create_payrollrequest_comment,
@@ -142,5 +147,9 @@ urlpatterns = [
views.delete_payrollrequest_comment,
name="payroll-request-delete-comment",
),
path("initial-notice-period",views.initial_notice_period,name="initial-notice-period")
path(
"initial-notice-period",
views.initial_notice_period,
name="initial-notice-period",
),
]

View File

@@ -4,6 +4,7 @@ component_views.py
This module is used to write methods to the component_urls patterns respectively
"""
from collections import defaultdict
from itertools import groupby
import json
import operator
from datetime import date, datetime
@@ -930,7 +931,6 @@ def add_deduction(request):
initial={"employee_id": employee_id, "one_time_date": instance.start_date},
)
if form.is_valid():
# Save the form to create the Deduction instance
deduction_instance = form.save(commit=False)
deduction_instance.only_show_under_employee = True
@@ -940,7 +940,7 @@ def add_deduction(request):
deduction_instance.specific_employees.set([employee_id])
deduction_instance.include_active_employees = False
deduction_instance.save()
# Now create new payslip by deleting existing payslip
new_post_data = QueryDict(mutable=True)
new_post_data.update(
@@ -1269,3 +1269,66 @@ def delete_attachments(request, _reimbursement_id):
ReimbursementMultipleAttachment.objects.filter(id__in=ids).delete()
messages.success(request, "Attachment deleted")
return redirect(view_reimbursement)
@login_required
@permission_required("payroll.view_payslip")
def get_contribution_report(request):
"""
This method is used to get the contribution report
"""
employee_id = request.GET["employee_id"]
deudction_id = request.GET.get("deduction_id")
pay_heads = Payslip.objects.filter(employee_id__id=employee_id).values_list(
"pay_head_data", flat=True
)
contribution_deductions = []
deductions = []
for head in pay_heads:
for deduction in head["gross_pay_deductions"]:
if deduction.get("deduction_id"):
deductions.append(deduction)
for deduction in head["basic_pay_deductions"]:
if deduction.get("deduction_id"):
deductions.append(deduction)
for deduction in head["pretax_deductions"]:
if deduction.get("deduction_id"):
deductions.append(deduction)
for deduction in head["post_tax_deductions"]:
if deduction.get("deduction_id"):
deductions.append(deduction)
for deduction in head["tax_deductions"]:
if deduction.get("deduction_id"):
deductions.append(deduction)
for deduction in head["net_deductions"]:
deductions.append(deduction)
deductions.sort(key=lambda x: x["deduction_id"])
grouped_deductions = {
key: list(group)
for key, group in groupby(deductions, key=lambda x: x["deduction_id"])
}
for deduction_id, group in grouped_deductions.items():
title = group[0]["title"]
employee_contribution = sum(item["amount"] for item in group)
employer_contribution = sum(
item["employer_contribution_amount"] for item in group
)
total_contribution = employee_contribution + employer_contribution
contribution_deductions.append(
{
"deduction_id": deduction_id,
"title": title,
"employee_contribution": employee_contribution,
"employer_contribution": employer_contribution,
"total_contribution": total_contribution,
}
)
return render(
request,
"payroll/dashboard/contribution.html",
{"contribution_deductions": contribution_deductions},
)

View File

@@ -3,6 +3,7 @@ views.py
This module is used to define the method for the path in the urls
"""
from collections import defaultdict
from urllib.parse import parse_qs
import pandas as pd
@@ -20,8 +21,19 @@ from base.methods import export_data, generate_colors, get_key_instances
from employee.models import Employee, EmployeeWorkInformation
from base.methods import closest_numbers
from base.methods import generate_pdf
from payroll.models.models import PayrollGeneralSetting, Payslip, Reimbursement, ReimbursementrequestComment, WorkRecord, Contract
from payroll.forms.forms import ContractForm, ReimbursementrequestCommentForm, WorkRecordForm
from payroll.models.models import (
PayrollGeneralSetting,
Payslip,
Reimbursement,
ReimbursementrequestComment,
WorkRecord,
Contract,
)
from payroll.forms.forms import (
ContractForm,
ReimbursementrequestCommentForm,
WorkRecordForm,
)
from payroll.models.tax_models import PayrollSettings
from payroll.forms.component_forms import ContractExportFieldForm, PayrollSettingsForm
from payroll.methods.methods import save_payslip
@@ -94,6 +106,20 @@ def contract_update(request, contract_id, **kwargs):
)
def contract_status_update(request, contract_id):
if request.method == "POST":
contract = Contract.objects.get(id=contract_id)
contract_form = ContractForm(request.POST, request.FILES, instance=contract)
if contract_form.is_valid():
contract_form.save()
messages.success(request, _("Contract status updated"))
else:
for errors in contract_form.errors.values():
for error in errors:
messages.error(request, error)
return HttpResponse("<script>window.location.reload()</script>")
@login_required
@permission_required("payroll.delete_contract")
def contract_delete(request, contract_id):
@@ -424,24 +450,26 @@ def contract_info_initial(request):
employee_id = request.GET["employee_id"]
work_info = EmployeeWorkInformation.objects.filter(employee_id=employee_id).first()
response_data = {
"department": work_info.department_id.id
if work_info.department_id is not None
else "",
"job_position": work_info.job_position_id.id
if work_info.job_position_id is not None
else "",
"job_role": work_info.job_role_id.id
if work_info.job_role_id is not None
else "",
"department": (
work_info.department_id.id if work_info.department_id is not None else ""
),
"job_position": (
work_info.job_position_id.id
if work_info.job_position_id is not None
else ""
),
"job_role": (
work_info.job_role_id.id if work_info.job_role_id is not None else ""
),
"shift": work_info.shift_id.id if work_info.shift_id is not None else "",
"work_type": work_info.work_type_id.id
if work_info.work_type_id is not None
else "",
"work_type": (
work_info.work_type_id.id if work_info.work_type_id is not None else ""
),
"wage": work_info.basic_salary,
"contract_start_date": work_info.date_joining if work_info.date_joining else "",
"contract_end_date": work_info.contract_end_date
if work_info.contract_end_date
else "",
"contract_end_date": (
work_info.contract_end_date if work_info.contract_end_date else ""
),
}
return JsonResponse(response_data)
@@ -641,15 +669,19 @@ def contract_ending(request):
date = request.GET.get("period")
month = date.split("-")[1]
year = date.split("-")[0]
if request.GET.get("initialLoad") == 'true':
if month == '12':
month =0
if request.GET.get("initialLoad") == "true":
if month == "12":
month = 0
year = int(year) + 1
contract_end = Contract.objects.filter(contract_end_date__month=int(month)+1,contract_end_date__year=int(year))
contract_end = Contract.objects.filter(
contract_end_date__month=int(month) + 1, contract_end_date__year=int(year)
)
else:
contract_end = Contract.objects.filter(contract_end_date__month=int(month),contract_end_date__year=int(year))
contract_end = Contract.objects.filter(
contract_end_date__month=int(month), contract_end_date__year=int(year)
)
ending_contract = []
for contract in contract_end:
@@ -851,9 +883,11 @@ def payslip_export(request):
df_table3 = df_table3.rename(
columns={
"contract_ending": f"Contract Ending {start_date} to {end_date}"
if start_date and end_date
else f"Contract Ending",
"contract_ending": (
f"Contract Ending {start_date} to {end_date}"
if start_date and end_date
else f"Contract Ending"
),
}
)
@@ -918,9 +952,11 @@ def payslip_export(request):
0,
0,
max_columns - 1,
f"Payroll details {start_date} to {end_date}"
if start_date and end_date
else f"Payroll details",
(
f"Payroll details {start_date} to {end_date}"
if start_date and end_date
else f"Payroll details"
),
heading_format,
)
@@ -1202,19 +1238,25 @@ def create_payrollrequest_comment(request, payroll_id):
"""
payroll = Reimbursement.objects.filter(id=payroll_id).first()
emp = request.user.employee_get
form = ReimbursementrequestCommentForm(initial={'employee_id':emp.id, 'request_id':payroll_id})
form = ReimbursementrequestCommentForm(
initial={"employee_id": emp.id, "request_id": payroll_id}
)
if request.method == "POST":
form = ReimbursementrequestCommentForm(request.POST )
form = ReimbursementrequestCommentForm(request.POST)
if form.is_valid():
form.instance.employee_id = emp
form.instance.request_id = payroll
form.save()
form = ReimbursementrequestCommentForm(initial={'employee_id':emp.id, 'request_id':payroll_id})
form = ReimbursementrequestCommentForm(
initial={"employee_id": emp.id, "request_id": payroll_id}
)
messages.success(request, _("Comment added successfully!"))
if request.user.employee_get.id == payroll.employee_id.id:
rec = payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id
rec = (
payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id
)
notify.send(
request.user.employee_get,
recipient=rec,
@@ -1226,7 +1268,10 @@ def create_payrollrequest_comment(request, payroll_id):
redirect="/payroll/view-reimbursement",
icon="chatbox-ellipses",
)
elif request.user.employee_get.id == payroll.employee_id.employee_work_info.reporting_manager_id.id:
elif (
request.user.employee_get.id
== payroll.employee_id.employee_work_info.reporting_manager_id.id
):
rec = payroll.employee_id.employee_user_id
notify.send(
request.user.employee_get,
@@ -1240,7 +1285,10 @@ def create_payrollrequest_comment(request, payroll_id):
icon="chatbox-ellipses",
)
else:
rec = [payroll.employee_id.employee_user_id, payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id]
rec = [
payroll.employee_id.employee_user_id,
payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id,
]
notify.send(
request.user.employee_get,
recipient=rec,
@@ -1252,14 +1300,12 @@ def create_payrollrequest_comment(request, payroll_id):
redirect="/payroll/view-reimbursement",
icon="chatbox-ellipses",
)
return HttpResponse("<script>window.location.reload()</script>")
return render(
request,
"payroll/reimbursement/reimbursement_request_comment_form.html",
{
"form": form, "request_id":payroll_id
},
{"form": form, "request_id": payroll_id},
)
@@ -1268,7 +1314,9 @@ def view_payrollrequest_comment(request, payroll_id):
"""
This method is used to show Reimbursement request comments
"""
comments = ReimbursementrequestComment.objects.filter(request_id=payroll_id).order_by('-created_at')
comments = ReimbursementrequestComment.objects.filter(
request_id=payroll_id
).order_by("-created_at")
no_comments = False
if not comments.exists():
no_comments = True
@@ -1276,7 +1324,7 @@ def view_payrollrequest_comment(request, payroll_id):
return render(
request,
"payroll/reimbursement/comment_view.html",
{"comments": comments, 'no_comments': no_comments }
{"comments": comments, "no_comments": no_comments},
)
@@ -1300,7 +1348,7 @@ def initial_notice_period(request):
notice_period = eval(request.GET["notice_period"])
settings = PayrollGeneralSetting.objects.first()
settings = settings if settings else PayrollGeneralSetting()
settings.notice_period = max(notice_period,0)
settings.notice_period = max(notice_period, 0)
settings.save()
messages.success(request,"Initial notice period updated")
messages.success(request, "Initial notice period updated")
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))