[IMP] Remove inter module dependency (#274)
This commit introduces significant changes to the architecture of the Horilla HRMS system by decoupling interdependent modules. The following modifications were made: 1. **Module Independence**: Each module has been refactored to eliminate reliance on other modules, promoting a more modular and maintainable codebase. 2. **Refactored Imports and Dependencies**: Adjusted import statements and dependency injections to support independent module operation. 3. **Compatibility and Functionality**: Ensured that all modules are compatible with existing systems and maintain their intended functionality both independently and when integrated with other modules. These changes enhance the modularity, maintainability, and scalability of the Horilla HRMS, allowing developers to work on individual modules without affecting the entire system. Future development and deployment will be more efficient and less prone to issues arising from tightly coupled code. **NOTE** For existing Horilla users, if you face any issues during the migrations, please run the following command and try again the migrations. - `python3 manage.py makemigrations` - `python3 manage.py migrate base` - `python3 manage.py migrate` * [IMP] ASSET: Asset module dependency removal from other Horilla apps * [IMP] ATTENDANCE: Attendance module dependency removal from other Horilla apps * [IMP] BASE: Base module dependency removal from other Horilla apps * [IMP] EMPLOYEE: Employee module dependency removal from other Horilla apps * [IMP] HELPDESK: Helpdesk module dependency removal from other Horilla apps * [IMP] HORILLA AUDIT: Horilla Audit module dependency removal from other Horilla apps * [IMP] HORILLA CRUMBS: Horilla Crumbs module dependency removal from other Horilla apps * [IMP] HORILLA AUTOMATIONS: Horilla Automations module dependency removal from other Horilla apps * [IMP] HORILLA VIEWS: Horilla Views module dependency removal from other Horilla apps * [IMP] LEAVE: Leave module dependency removal from other Horilla apps * [IMP] OFFBOARDING: Offboarding module dependency removal from other Horilla apps * [IMP] ONBOARDING: Onboarding module dependency removal from other Horilla apps * [IMP] PMS: PMS module dependency removal from other Horilla apps * [IMP] PAYROLL: Payroll module dependency removal from other Horilla apps * [IMP] RECRUITMENT: Recruitment module dependency removal from other Horilla apps * [IMP] HORILLA: Dependency removal updates * [IMP] TEMPLATES: Dependency removal updates * [IMP] STATIC: Dependency removal updates * [IMP] HORILLA DOCUMENTS: Horilla Documents module dependency removal from other Horilla apps * [ADD] HORILLA: methods.py * [UPDT] HORILLA: Settings.py * [FIX] EMPLOYEE: About tab issue * Update horilla_settings.py * Remove dummy db init password
This commit is contained in:
@@ -7,6 +7,7 @@ import calendar
|
||||
from datetime import date, datetime, timedelta
|
||||
|
||||
from django import forms
|
||||
from django.apps import apps
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
@@ -16,8 +17,6 @@ from django.http import QueryDict
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from asset.models import Asset
|
||||
from attendance.models import Attendance, strtime_seconds, validate_time_format
|
||||
from base.horilla_company_manager import HorillaCompanyManager
|
||||
from base.models import (
|
||||
Company,
|
||||
@@ -26,12 +25,14 @@ from base.models import (
|
||||
JobPosition,
|
||||
JobRole,
|
||||
WorkType,
|
||||
validate_time_format,
|
||||
)
|
||||
from employee.methods.duration_methods import strtime_seconds
|
||||
from employee.models import BonusPoint, Employee, EmployeeWorkInformation
|
||||
from horilla import horilla_middlewares
|
||||
from horilla.methods import get_horilla_model_class
|
||||
from horilla.models import HorillaModel
|
||||
from horilla_audit.models import HorillaAuditInfo, HorillaAuditLog
|
||||
from leave.models import LeaveRequest, LeaveType
|
||||
|
||||
# Create your models here.
|
||||
|
||||
@@ -125,11 +126,14 @@ class Contract(HorillaModel):
|
||||
("monthly", _("Monthly")),
|
||||
("semi_monthly", _("Semi-Monthly")),
|
||||
)
|
||||
WAGE_CHOICES = (
|
||||
("hourly", _("Hourly")),
|
||||
WAGE_CHOICES = [
|
||||
("daily", _("Daily")),
|
||||
("monthly", _("Monthly")),
|
||||
)
|
||||
]
|
||||
|
||||
if apps.is_installed("attendance"):
|
||||
WAGE_CHOICES.append(("hourly", _("Hourly")))
|
||||
|
||||
CONTRACT_STATUS_CHOICES = (
|
||||
("draft", _("Draft")),
|
||||
("active", _("Active")),
|
||||
@@ -425,81 +429,84 @@ class WorkRecord(models.Model):
|
||||
)
|
||||
|
||||
|
||||
class OverrideAttendance(Attendance):
|
||||
"""
|
||||
Class to override Attendance model save method
|
||||
"""
|
||||
if apps.is_installed("attendance"):
|
||||
from attendance.models import Attendance
|
||||
|
||||
# Additional fields and methods specific to AnotherModel
|
||||
@receiver(post_save, sender=Attendance)
|
||||
def attendance_post_save(sender, instance, **kwargs):
|
||||
class OverrideAttendance(Attendance):
|
||||
"""
|
||||
Overriding Attendance model save method
|
||||
Class to override Attendance model save method
|
||||
"""
|
||||
if instance.first_save:
|
||||
min_hour_second = strtime_seconds(instance.minimum_hour)
|
||||
at_work_second = strtime_seconds(instance.attendance_worked_hour)
|
||||
|
||||
status = "FDP" if instance.at_work_second >= min_hour_second else "HDP"
|
||||
# Additional fields and methods specific to AnotherModel
|
||||
@receiver(post_save, sender=Attendance)
|
||||
def attendance_post_save(sender, instance, **kwargs):
|
||||
"""
|
||||
Overriding Attendance model save method
|
||||
"""
|
||||
if instance.first_save:
|
||||
min_hour_second = strtime_seconds(instance.minimum_hour)
|
||||
at_work_second = strtime_seconds(instance.attendance_worked_hour)
|
||||
|
||||
status = "CONF" if instance.attendance_validated is False else status
|
||||
message = (
|
||||
_("Validate the attendance") if status == "CONF" else _("Validated")
|
||||
)
|
||||
status = "FDP" if instance.at_work_second >= min_hour_second else "HDP"
|
||||
|
||||
message = (
|
||||
_("Incomplete minimum hour")
|
||||
if status == "HDP" and min_hour_second > at_work_second
|
||||
else message
|
||||
)
|
||||
work_record = WorkRecord.objects.filter(
|
||||
date=instance.attendance_date,
|
||||
is_attendance_record=True,
|
||||
employee_id=instance.employee_id,
|
||||
)
|
||||
work_record = (
|
||||
WorkRecord()
|
||||
if not WorkRecord.objects.filter(
|
||||
date=instance.attendance_date,
|
||||
employee_id=instance.employee_id,
|
||||
).exists()
|
||||
else WorkRecord.objects.filter(
|
||||
date=instance.attendance_date,
|
||||
employee_id=instance.employee_id,
|
||||
).first()
|
||||
)
|
||||
work_record.employee_id = instance.employee_id
|
||||
work_record.date = instance.attendance_date
|
||||
work_record.at_work = instance.attendance_worked_hour
|
||||
work_record.min_hour = instance.minimum_hour
|
||||
work_record.min_hour_second = min_hour_second
|
||||
work_record.at_work_second = at_work_second
|
||||
work_record.work_record_type = status
|
||||
work_record.message = message
|
||||
work_record.is_attendance_record = True
|
||||
if instance.attendance_validated:
|
||||
work_record.day_percentage = (
|
||||
1.00 if at_work_second > min_hour_second / 2 else 0.50
|
||||
status = "CONF" if instance.attendance_validated is False else status
|
||||
message = (
|
||||
_("Validate the attendance") if status == "CONF" else _("Validated")
|
||||
)
|
||||
work_record.save()
|
||||
|
||||
if status == "HDP" and work_record.is_leave_record:
|
||||
message = _("Half day leave")
|
||||
message = (
|
||||
_("Incomplete minimum hour")
|
||||
if status == "HDP" and min_hour_second > at_work_second
|
||||
else message
|
||||
)
|
||||
work_record = WorkRecord.objects.filter(
|
||||
date=instance.attendance_date,
|
||||
is_attendance_record=True,
|
||||
employee_id=instance.employee_id,
|
||||
)
|
||||
work_record = (
|
||||
WorkRecord()
|
||||
if not WorkRecord.objects.filter(
|
||||
date=instance.attendance_date,
|
||||
employee_id=instance.employee_id,
|
||||
).exists()
|
||||
else WorkRecord.objects.filter(
|
||||
date=instance.attendance_date,
|
||||
employee_id=instance.employee_id,
|
||||
).first()
|
||||
)
|
||||
work_record.employee_id = instance.employee_id
|
||||
work_record.date = instance.attendance_date
|
||||
work_record.at_work = instance.attendance_worked_hour
|
||||
work_record.min_hour = instance.minimum_hour
|
||||
work_record.min_hour_second = min_hour_second
|
||||
work_record.at_work_second = at_work_second
|
||||
work_record.work_record_type = status
|
||||
work_record.message = message
|
||||
work_record.is_attendance_record = True
|
||||
if instance.attendance_validated:
|
||||
work_record.day_percentage = (
|
||||
1.00 if at_work_second > min_hour_second / 2 else 0.50
|
||||
)
|
||||
work_record.save()
|
||||
|
||||
if status == "FDP":
|
||||
message = _("Present")
|
||||
if status == "HDP" and work_record.is_leave_record:
|
||||
message = _("Half day leave")
|
||||
|
||||
work_record.message = message
|
||||
work_record.save()
|
||||
if status == "FDP":
|
||||
message = _("Present")
|
||||
|
||||
message = work_record.message
|
||||
status = work_record.work_record_type
|
||||
if not instance.attendance_clock_out:
|
||||
status = "FDP"
|
||||
message = _("Currently working")
|
||||
work_record.message = message
|
||||
work_record.work_record_type = status
|
||||
work_record.save()
|
||||
work_record.message = message
|
||||
work_record.save()
|
||||
|
||||
message = work_record.message
|
||||
status = work_record.work_record_type
|
||||
if not instance.attendance_clock_out:
|
||||
status = "FDP"
|
||||
message = _("Currently working")
|
||||
work_record.message = message
|
||||
work_record.work_record_type = status
|
||||
work_record.save()
|
||||
|
||||
@receiver(pre_delete, sender=Attendance)
|
||||
def attendance_pre_delete(sender, instance, **_kwargs):
|
||||
@@ -515,75 +522,80 @@ class OverrideAttendance(Attendance):
|
||||
).delete()
|
||||
|
||||
|
||||
class OverrideLeaveRequest(LeaveRequest):
|
||||
"""
|
||||
Class to override Attendance model save method
|
||||
"""
|
||||
if apps.is_installed("leave"):
|
||||
from leave.models import LeaveRequest
|
||||
|
||||
# Additional fields and methods specific to AnotherModel
|
||||
@receiver(pre_save, sender=LeaveRequest)
|
||||
def leaverequest_pre_save(sender, instance, **_kwargs):
|
||||
class OverrideLeaveRequest(LeaveRequest):
|
||||
"""
|
||||
Overriding LeaveRequest model save method
|
||||
Class to override Attendance model save method
|
||||
"""
|
||||
if (
|
||||
instance.start_date == instance.end_date
|
||||
and instance.end_date_breakdown != instance.start_date_breakdown
|
||||
):
|
||||
instance.end_date_breakdown = instance.start_date_breakdown
|
||||
super(LeaveRequest, instance).save()
|
||||
|
||||
period_dates = get_date_range(instance.start_date, instance.end_date)
|
||||
if instance.status == "approved":
|
||||
for date in period_dates:
|
||||
try:
|
||||
work_entry = (
|
||||
WorkRecord.objects.filter(
|
||||
date=date,
|
||||
employee_id=instance.employee_id,
|
||||
# Additional fields and methods specific to AnotherModel
|
||||
@receiver(pre_save, sender=LeaveRequest)
|
||||
def leaverequest_pre_save(sender, instance, **_kwargs):
|
||||
"""
|
||||
Overriding LeaveRequest model save method
|
||||
"""
|
||||
if (
|
||||
instance.start_date == instance.end_date
|
||||
and instance.end_date_breakdown != instance.start_date_breakdown
|
||||
):
|
||||
instance.end_date_breakdown = instance.start_date_breakdown
|
||||
super(LeaveRequest, instance).save()
|
||||
|
||||
period_dates = get_date_range(instance.start_date, instance.end_date)
|
||||
if instance.status == "approved":
|
||||
for date in period_dates:
|
||||
try:
|
||||
work_entry = (
|
||||
WorkRecord.objects.filter(
|
||||
date=date,
|
||||
employee_id=instance.employee_id,
|
||||
)
|
||||
if WorkRecord.objects.filter(
|
||||
date=date,
|
||||
employee_id=instance.employee_id,
|
||||
).exists()
|
||||
else WorkRecord()
|
||||
)
|
||||
if WorkRecord.objects.filter(
|
||||
date=date,
|
||||
employee_id=instance.employee_id,
|
||||
).exists()
|
||||
else WorkRecord()
|
||||
)
|
||||
work_entry.employee_id = instance.employee_id
|
||||
work_entry.is_leave_record = True
|
||||
work_entry.day_percentage = (
|
||||
0.50
|
||||
if instance.start_date == date
|
||||
and instance.start_date_breakdown == "first_half"
|
||||
or instance.end_date == date
|
||||
and instance.end_date_breakdown == "second_half"
|
||||
else 0.00
|
||||
)
|
||||
# scheduler task to validate the conflict entry for half day if they
|
||||
# take half day leave is when they mark the attendance.
|
||||
status = (
|
||||
"CONF"
|
||||
if instance.start_date == date
|
||||
and instance.start_date_breakdown == "first_half"
|
||||
or instance.end_date == date
|
||||
and instance.end_date_breakdown == "second_half"
|
||||
else "ABS"
|
||||
)
|
||||
work_entry.work_record_type = status
|
||||
work_entry.date = date
|
||||
work_entry.message = (
|
||||
"Absent"
|
||||
if status == "ABS"
|
||||
else _("Half day Attendance need to validate")
|
||||
)
|
||||
work_entry.save()
|
||||
except:
|
||||
pass
|
||||
work_entry.employee_id = instance.employee_id
|
||||
work_entry.is_leave_record = True
|
||||
work_entry.day_percentage = (
|
||||
0.50
|
||||
if instance.start_date == date
|
||||
and instance.start_date_breakdown == "first_half"
|
||||
or instance.end_date == date
|
||||
and instance.end_date_breakdown == "second_half"
|
||||
else 0.00
|
||||
)
|
||||
# scheduler task to validate the conflict entry for half day if they
|
||||
# take half day leave is when they mark the attendance.
|
||||
status = (
|
||||
"CONF"
|
||||
if instance.start_date == date
|
||||
and instance.start_date_breakdown == "first_half"
|
||||
or instance.end_date == date
|
||||
and instance.end_date_breakdown == "second_half"
|
||||
else "ABS"
|
||||
)
|
||||
work_entry.work_record_type = status
|
||||
work_entry.date = date
|
||||
work_entry.message = (
|
||||
"Absent"
|
||||
if status == "ABS"
|
||||
else _("Half day Attendance need to validate")
|
||||
)
|
||||
work_entry.save()
|
||||
except:
|
||||
pass
|
||||
|
||||
else:
|
||||
for date in period_dates:
|
||||
WorkRecord.objects.filter(
|
||||
is_leave_record=True, date=date, employee_id=instance.employee_id
|
||||
).delete()
|
||||
else:
|
||||
for date in period_dates:
|
||||
WorkRecord.objects.filter(
|
||||
is_leave_record=True,
|
||||
date=date,
|
||||
employee_id=instance.employee_id,
|
||||
).delete()
|
||||
|
||||
|
||||
class OverrideWorkInfo(EmployeeWorkInformation):
|
||||
@@ -686,13 +698,18 @@ class Allowance(HorillaModel):
|
||||
|
||||
based_on_choice = [
|
||||
("basic_pay", _("Basic Pay")),
|
||||
("attendance", _("Attendance")),
|
||||
("shift_id", _("Shift")),
|
||||
("overtime", _("Overtime")),
|
||||
("work_type_id", _("Work Type")),
|
||||
("children", _("Children")),
|
||||
]
|
||||
|
||||
if apps.is_installed("attendance"):
|
||||
attendance_choices = [
|
||||
("overtime", _("Overtime")),
|
||||
("shift_id", _("Shift")),
|
||||
("work_type_id", _("Work Type")),
|
||||
("attendance", _("Attendance")),
|
||||
]
|
||||
based_on_choice += attendance_choices
|
||||
|
||||
if_condition_choice = [
|
||||
("basic_pay", _("Basic Pay")),
|
||||
]
|
||||
@@ -1005,6 +1022,16 @@ class Allowance(HorillaModel):
|
||||
def __str__(self) -> str:
|
||||
return str(self.title)
|
||||
|
||||
def save(self):
|
||||
super().save()
|
||||
if (
|
||||
not self.include_active_employees
|
||||
and not self.specific_employees.first()
|
||||
and not self.is_condition_based
|
||||
):
|
||||
self.include_active_employees = True
|
||||
super().save()
|
||||
|
||||
|
||||
class Deduction(HorillaModel):
|
||||
"""
|
||||
@@ -1284,6 +1311,16 @@ class Deduction(HorillaModel):
|
||||
def __str__(self) -> str:
|
||||
return str(self.title)
|
||||
|
||||
def save(self):
|
||||
super().save()
|
||||
if (
|
||||
not self.include_active_employees
|
||||
and not self.specific_employees.first()
|
||||
and not self.is_condition_based
|
||||
):
|
||||
self.include_active_employees = True
|
||||
super().save()
|
||||
|
||||
|
||||
class Payslip(HorillaModel):
|
||||
"""
|
||||
@@ -1438,9 +1475,14 @@ class LoanAccount(HorillaModel):
|
||||
)
|
||||
apply_on = models.CharField(default="end_of_month", max_length=20, editable=False)
|
||||
settled = models.BooleanField(default=False)
|
||||
asset_id = models.ForeignKey(
|
||||
Asset, on_delete=models.PROTECT, null=True, editable=False
|
||||
)
|
||||
if apps.is_installed("asset"):
|
||||
asset_id = models.ForeignKey(
|
||||
"asset.Asset",
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
editable=False,
|
||||
)
|
||||
objects = HorillaCompanyManager("employee_id__employee_work_info__company_id")
|
||||
|
||||
def get_installments(self):
|
||||
@@ -1507,7 +1549,10 @@ def create_installments(sender, instance, created, **kwargs):
|
||||
Post save metod for loan account
|
||||
"""
|
||||
installments = []
|
||||
if created and instance.asset_id is None and instance.type != "fine":
|
||||
asset = True
|
||||
if apps.is_installed("asset"):
|
||||
asset = True if instance.asset_id is None else False
|
||||
if created and asset and instance.type != "fine":
|
||||
loan = Allowance()
|
||||
loan.amount = instance.loan_amount
|
||||
loan.title = instance.title
|
||||
@@ -1567,9 +1612,12 @@ class Reimbursement(HorillaModel):
|
||||
|
||||
reimbursement_types = [
|
||||
("reimbursement", "Reimbursement"),
|
||||
("leave_encashment", "Leave Encashment"),
|
||||
("bonus_encashment", "Bonus Point Encashment"),
|
||||
]
|
||||
|
||||
if apps.is_installed("leave"):
|
||||
reimbursement_types.append(("leave_encashment", "Leave Encashment"))
|
||||
|
||||
status_types = [
|
||||
("requested", "Requested"),
|
||||
("approved", "Approved"),
|
||||
@@ -1587,13 +1635,14 @@ class Reimbursement(HorillaModel):
|
||||
other_attachments = models.ManyToManyField(
|
||||
ReimbursementMultipleAttachment, blank=True, editable=False
|
||||
)
|
||||
leave_type_id = models.ForeignKey(
|
||||
LeaveType,
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Leave type",
|
||||
)
|
||||
if apps.is_installed("leave"):
|
||||
leave_type_id = models.ForeignKey(
|
||||
"leave.LeaveType",
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Leave type",
|
||||
)
|
||||
ad_to_encash = models.FloatField(
|
||||
default=0, help_text="Available Days to encash", verbose_name="Available days"
|
||||
)
|
||||
@@ -1888,12 +1937,11 @@ class PayslipAutoGenerate(models.Model):
|
||||
}
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
def save(self):
|
||||
from payroll.scheduler import auto_payslip_generate
|
||||
|
||||
if self.auto_generate:
|
||||
auto_payslip_generate()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.generate_day} | {self.company_id} "
|
||||
|
||||
Reference in New Issue
Block a user