[UPDT] BASE: Restructure signals and work record updates to base module functions

This commit is contained in:
Horilla
2025-02-28 19:01:30 +05:30
parent c238bf03b3
commit ffca4e548e
7 changed files with 155 additions and 233 deletions

View File

@@ -14,6 +14,8 @@ class BaseConfig(AppConfig):
name = "base" name = "base"
def ready(self) -> None: def ready(self) -> None:
from base import signals
super().ready() super().ready()
try: try:
from base.models import EmployeeShiftDay from base.models import EmployeeShiftDay

View File

@@ -140,7 +140,6 @@ class CompanyMiddleware:
"loanaccount", "loanaccount",
"payslip", "payslip",
"reimbursement", "reimbursement",
"workrecord",
], ],
"helpdesk": ["ticket"], "helpdesk": ["ticket"],
"offboarding": ["offboarding"], "offboarding": ["offboarding"],

View File

@@ -1,149 +0,0 @@
from django.apps import apps
try:
RecruitmentMailTemplate = apps.get_model("recruitment", "RecruitmentMailTemplate")
HorillaMailTemplate = apps.get_model("base", "HorillaMailTemplate")
recruitment_mail_templates = RecruitmentMailTemplate.objects.all()
for recruitment_mail in recruitment_mail_templates:
if not HorillaMailTemplate.objects.filter(
title=recruitment_mail.title
).exists():
horilla_mail = HorillaMailTemplate(
id=recruitment_mail.id,
title=recruitment_mail.title,
body=recruitment_mail.body,
company_id=recruitment_mail.company_id,
)
horilla_mail.save()
horilla_mail_templates = HorillaMailTemplate.objects.all()
RecruitmentMailTemplate.objects.all().delete()
except Exception as e:
pass
try:
LeaveHoliday = apps.get_model("leave", "Holiday")
BaseHoliday = apps.get_model("base", "Holidays")
leave_holidays = LeaveHoliday.objects.all()
for holiday in leave_holidays:
if not BaseHoliday.objects.filter(
name=holiday.name,
start_date=holiday.start_date,
end_date=holiday.end_date,
).exists():
horilla = BaseHoliday(
id=holiday.id,
name=holiday.name,
start_date=holiday.start_date,
end_date=holiday.end_date,
)
horilla.save()
base_leaves = BaseHoliday.objects.all()
LeaveHoliday.objects.all().delete()
except Exception as e:
pass
try:
PenaltyAccount = apps.get_model("attendance", "PenaltyAccount")
PenaltyAccounts = apps.get_model("base", "PenaltyAccounts")
penalties = PenaltyAccount.objects.all()
for penalty in penalties:
filter_conditions = {
"employee_id": penalty.employee_id,
"penalty_amount": penalty.penalty_amount,
}
if apps.is_installed("attendance"):
filter_conditions.update(
{
"late_early_id": penalty.late_early_id,
}
)
if apps.is_installed("leave"):
filter_conditions.update(
{
"leave_request_id": penalty.leave_request_id,
"leave_type_id": penalty.leave_type_id,
"minus_leaves": penalty.minus_leaves,
"deduct_from_carry_forward": penalty.deduct_from_carry_forward,
}
)
if not PenaltyAccounts.objects.filter(**filter_conditions).exists():
horilla = PenaltyAccounts(
id=penalty.id,
employee_id=penalty.employee_id,
penalty_amount=penalty.penalty_amount,
)
if apps.is_installed("attendance"):
horilla.late_early_id = penalty.late_early_id
if apps.is_installed("leave"):
horilla.leave_request_id = penalty.leave_request_id
horilla.leave_type_id = penalty.leave_type_id
horilla.minus_leaves = penalty.minus_leaves
horilla.deduct_from_carry_forward = penalty.deduct_from_carry_forward
horilla.save()
penalty_accounts = PenaltyAccounts.objects.all()
PenaltyAccount.objects.all().delete()
except Exception as e:
pass
try:
CompanyLeave = apps.get_model("leave", "CompanyLeave")
BaseCompanyLeave = apps.get_model("base", "CompanyLeaves")
company_leaves = CompanyLeave.objects.all()
for leave in company_leaves:
if not BaseCompanyLeave.objects.filter(
based_on_week=leave.based_on_week,
based_on_week_day=leave.based_on_week_day,
).exists():
horilla = BaseCompanyLeave(
id=leave.id,
based_on_week=leave.based_on_week,
based_on_week_day=leave.based_on_week_day,
)
horilla.save()
base_leaves = BaseCompanyLeave.objects.all()
CompanyLeave.objects.all().delete()
except Exception as e:
pass
try:
WorkRecord = apps.get_model("payroll", "WorkRecord")
WorkRecords = apps.get_model("attendance", "WorkRecords")
work_records = WorkRecord.objects.all()
for work_record in work_records:
if not WorkRecords.objects.filter(
record_name=work_record.record_name,
employee_id=work_record.employee_id,
date=work_record.date,
).exists():
new_work_record = WorkRecords(
id=work_record.id,
record_name=work_record.record_name,
work_record_type=work_record.work_record_type,
employee_id=work_record.employee_id,
date=work_record.date,
at_work=work_record.at_work,
min_hour=work_record.min_hour,
at_work_second=work_record.at_work_second,
min_hour_second=work_record.min_hour_second,
note=work_record.note,
message=work_record.message,
is_attendance_record=work_record.is_attendance_record,
is_leave_record=work_record.is_leave_record,
day_percentage=work_record.day_percentage,
last_update=work_record.last_update,
)
new_work_record.save()
new_work_records = WorkRecords.objects.all()
WorkRecord.objects.all().delete()
except Exception as e:
pass

View File

@@ -14,14 +14,11 @@ from django.contrib import messages
from django.contrib.auth.models import AbstractUser, User from django.contrib.auth.models import AbstractUser, User
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from base.horilla_company_manager import HorillaCompanyManager from base.horilla_company_manager import HorillaCompanyManager
from horilla import horilla_middlewares from horilla import horilla_middlewares
from horilla.horilla_middlewares import _thread_locals from horilla.horilla_middlewares import _thread_locals
from horilla.methods import get_horilla_model_class
from horilla.models import HorillaModel from horilla.models import HorillaModel
from horilla_audit.models import HorillaAuditInfo, HorillaAuditLog from horilla_audit.models import HorillaAuditInfo, HorillaAuditLog
@@ -1793,53 +1790,4 @@ class NotificationSound(models.Model):
sound_enabled = models.BooleanField(default=False) sound_enabled = models.BooleanField(default=False)
@receiver(post_save, sender=PenaltyAccounts)
def create_deduction_cutleave_from_penalty(sender, instance, created, **kwargs):
"""
This is post save method, used to create deduction and cut availabl leave days"""
# only work when creating
if created:
penalty_amount = instance.penalty_amount
if apps.is_installed("payroll") and penalty_amount:
Deduction = get_horilla_model_class(app_label="payroll", model="deduction")
penalty = Deduction()
if instance.late_early_id:
penalty.title = f"{instance.late_early_id.get_type_display()} penalty"
penalty.one_time_date = (
instance.late_early_id.attendance_id.attendance_date
)
elif instance.leave_request_id:
penalty.title = f"Leave penalty {instance.leave_request_id.end_date}"
penalty.one_time_date = instance.leave_request_id.end_date
else:
penalty.title = f"Penalty on {datetime.today()}"
penalty.one_time_date = datetime.today()
penalty.include_active_employees = False
penalty.is_fixed = True
penalty.amount = instance.penalty_amount
penalty.only_show_under_employee = True
penalty.save()
penalty.include_active_employees = False
penalty.specific_employees.add(instance.employee_id)
penalty.save()
if (
apps.is_installed("leave")
and instance.leave_type_id
and instance.minus_leaves
):
available = instance.employee_id.available_leave.filter(
leave_type_id=instance.leave_type_id
).first()
unit = round(instance.minus_leaves * 2) / 2
if not instance.deduct_from_carry_forward:
available.available_days = max(0, (available.available_days - unit))
else:
available.carryforward_days = max(
0, (available.carryforward_days - unit)
)
available.save()
User.add_to_class("is_new_employee", models.BooleanField(default=False)) User.add_to_class("is_new_employee", models.BooleanField(default=False))

View File

@@ -0,0 +1,82 @@
from datetime import datetime
from django.apps import apps
from django.db.models import Max
from django.db.models.signals import post_migrate, post_save
from django.dispatch import receiver
from base.models import PenaltyAccounts
from horilla.methods import get_horilla_model_class
@receiver(post_save, sender=PenaltyAccounts)
def create_deduction_cutleave_from_penalty(sender, instance, created, **kwargs):
"""
This is post save method, used to create deduction and cut availabl leave days"""
# only work when creating
if created:
penalty_amount = instance.penalty_amount
if apps.is_installed("payroll") and penalty_amount:
Deduction = get_horilla_model_class(app_label="payroll", model="deduction")
penalty = Deduction()
if instance.late_early_id:
penalty.title = f"{instance.late_early_id.get_type_display()} penalty"
penalty.one_time_date = (
instance.late_early_id.attendance_id.attendance_date
)
elif instance.leave_request_id:
penalty.title = f"Leave penalty {instance.leave_request_id.end_date}"
penalty.one_time_date = instance.leave_request_id.end_date
else:
penalty.title = f"Penalty on {datetime.today()}"
penalty.one_time_date = datetime.today()
penalty.include_active_employees = False
penalty.is_fixed = True
penalty.amount = instance.penalty_amount
penalty.only_show_under_employee = True
penalty.save()
penalty.include_active_employees = False
penalty.specific_employees.add(instance.employee_id)
penalty.save()
if (
apps.is_installed("leave")
and instance.leave_type_id
and instance.minus_leaves
):
available = instance.employee_id.available_leave.filter(
leave_type_id=instance.leave_type_id
).first()
unit = round(instance.minus_leaves * 2) / 2
if not instance.deduct_from_carry_forward:
available.available_days = max(0, (available.available_days - unit))
else:
available.carryforward_days = max(
0, (available.carryforward_days - unit)
)
available.save()
@receiver(post_migrate)
def clean_work_records(sender, **kwargs):
if sender.label not in ["attendance"]:
return
from attendance.models import WorkRecords
latest_records = (
WorkRecords.objects.exclude(work_record_type="DFT")
.values("employee_id", "date")
.annotate(latest_id=Max("id"))
)
# Delete all but the latest WorkRecord
deleted_count = 0
for record in latest_records:
deleted_count += (
WorkRecords.objects.filter(
employee_id=record["employee_id"], date=record["date"]
)
.exclude(id=record["latest_id"])
.delete()[0]
)

View File

@@ -1,41 +1,60 @@
{% load i18n %} {% load i18n %} {% if messages %}
{% if messages %} <span
<span hx-trigger="load" hx-target="#companyLeave" hx-get="{% url 'company-leave-filter' %}" hx-on-htmx-after-request="setTimeout(() => { hx-trigger="load"
hx-target="#companyLeave"
hx-get="{% url 'company-leave-filter' %}"
hx-on-htmx-after-request="setTimeout(() => {
$('.oh-modal__close').click(); $('.oh-modal__close').click();
}, 1000);"> }, 1000);"
</span> >
{% endif %} </span>
{% if form.errors %} {% endif %} {% if form.errors %}
<div class="oh-wrapper"> <div class="oh-wrapper">
<div class="oh-alert-container"> <div class="oh-alert-container">
{% for error in form.non_field_errors %} {% for error in form.non_field_errors %}
<div class="oh-alert oh-alert--animated oh-alert--danger">{{ error }}</div> <div class="oh-alert oh-alert--animated oh-alert--danger">
{% endfor %} {{ error }}
</div> </div>
{% endfor %}
</div> </div>
</div>
{% endif %} {% endif %}
<div class="oh-modal__dialog-header pb-0"> <div class="oh-modal__dialog-header pb-0">
<span class="oh-modal__dialog-title" id="editDialogDialog">{% trans "Update Company Leaves" %}</span> <span class="oh-modal__dialog-title" id="editDialogDialog"
>{% trans "Update Company Leaves" %}</span
>
<button class="oh-modal__close" aria-label="Close"> <button class="oh-modal__close" aria-label="Close">
<ion-icon name="close-outline"></ion-icon> <ion-icon name="close-outline"></ion-icon>
</button> </button>
</div> </div>
<div class="oh-modal__dialog-body pt-1"> <div class="oh-modal__dialog-body pt-1">
<form hx-post="{% url 'company-leave-update' id %}" hx-target="#objectUpdateModalTarget" class="oh-profile-section"> <form
hx-post="{% url 'company-leave-update' id %}"
hx-target="#objectCreateModalTarget"
class="oh-profile-section pt-1"
>
<label class="oh-label d-block">{% trans "Based On Week" %}</label> <label class="oh-label d-block">{% trans "Based On Week" %}</label>
{{form.based_on_week}} {{form.based_on_week}} {{form.based_on_week.errors}}
<label class="oh-label d-block">{% trans "Based On Week Day" %}</label> <label class="oh-label d-block">{% trans "Based On Week Day" %}</label>
{{form.based_on_week_day}} {{form.based_on_week_day}} {{form.based_on_week_day.errors}}
<label class="oh-label d-block">{% trans "Company" %}</label>
{{form.company_id}} {{form.company_id.errors}}
<div class="oh-modal__dialog-footer p-0 mt-3"> <div class="oh-modal__dialog-footer p-0 mt-3">
<button type="submit" class="oh-btn oh-btn--secondary oh-btn--shadow"> <button
type="submit"
class="oh-btn oh-btn--secondary oh-btn--shadow"
>
{% trans "Save" %} {% trans "Save" %}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
<script> <script>
var week_select = $('#objectUpdateModalTarget #id_based_on_week'); var week_select = $("#objectUpdateModalTarget #id_based_on_week");
week_select.find('option').filter(function () { week_select
return $(this).text() === '---------'; .find("option")
}).text('All'); .filter(function () {
return $(this).text() === "---------";
})
.text("All");
</script> </script>

View File

@@ -19,27 +19,48 @@
<div class="row"> <div class="row">
<div class="col-12 col-sm-12 col-md-6 col-lg-6"> <div class="col-12 col-sm-12 col-md-6 col-lg-6">
<div class="oh-input__group"> <div class="oh-input__group">
<label class="oh-input__label" for="{{form.start_date.id_for_label}}"> <label
class="oh-input__label"
for="{{form.start_date.id_for_label}}"
>
{% trans "Start Date" %} {% trans "Start Date" %}
</label> </label>
{{form.start_date }} {{form.start_date.errors }} {{ form.start_date }} {{ form.start_date.errors }}
</div> </div>
</div> </div>
<div class="col-12 col-sm-12 col-md-6 col-lg-6"> <div class="col-12 col-sm-12 col-md-6 col-lg-6">
<div class="oh-input__group"> <div class="oh-input__group">
<label class="oh-input__label" for="{{form.end_date.id_for_label}}"> <label
class="oh-input__label"
for="{{form.end_date.id_for_label}}"
>
{% trans "End Date" %} {% trans "End Date" %}
</label> </label>
{{form.end_date }} {{form.end_date.errors}} {{ form.end_date }} {{ form.end_date.errors }}
</div>
</div>
<div class="col-12 col-sm-12 col-md-6 col-lg-6">
<div class="oh-input__group">
<label
class="oh-input__label"
for="{{form.end_date.id_for_label}}"
>
{% trans "Company" %}
</label>
{{ form.company_id }} {{ form.company_id.errors }}
</div>
</div>
<div class="col-12 col-sm-12 col-md-6 col-lg-6">
<label
class="oh-label d-block"
for="{{ form.name.id_for_label }}"
>{% trans "Recurring" %}</label
>
<div class="oh-switch">
{{ form.recurring }} {{ form.recurring.errors }}
</div> </div>
</div> </div>
</div> </div>
<label class="oh-label d-block" for="{{ form.recurring.id_for_label }}">{% trans "Recurring" %}</label>
<div class="oh-switch">{{form.recurring}} {{form.recurring.errors}}</div>
<label class="oh-label d-block" for="{{ form.recurring.id_for_label }}">{% trans "Company" %}</label>
<div class="oh-switch">{{ form.company_id }} {{ form.company_id.errors }}</div>
<div class="oh-modal__dialog-footer p-0"> <div class="oh-modal__dialog-footer p-0">
<button type="submit" class="oh-btn oh-btn--secondary oh-btn--shadow"> <button type="submit" class="oh-btn oh-btn--secondary oh-btn--shadow">
{% trans "Save" %} {% trans "Save" %}