2023-07-26 10:32:58 +05:30
|
|
|
"""
|
|
|
|
|
scheduler.py
|
|
|
|
|
|
|
|
|
|
This module is used to register scheduled tasks
|
|
|
|
|
"""
|
2024-03-10 19:37:46 +05:30
|
|
|
|
2024-07-10 16:13:13 +05:30
|
|
|
import json
|
2025-01-07 15:13:47 +05:30
|
|
|
import sys
|
2024-07-10 16:13:13 +05:30
|
|
|
from datetime import date, timedelta
|
2024-05-07 12:23:36 +05:30
|
|
|
|
2023-07-26 10:32:58 +05:30
|
|
|
from apscheduler.schedulers.background import BackgroundScheduler
|
2024-07-10 16:13:13 +05:30
|
|
|
from dateutil.relativedelta import relativedelta
|
2024-05-07 12:23:36 +05:30
|
|
|
|
2024-07-10 16:13:13 +05:30
|
|
|
from payroll.methods.methods import calculate_employer_contribution, save_payslip
|
|
|
|
|
from payroll.views.component_views import payroll_calculation
|
|
|
|
|
|
|
|
|
|
from .models.models import Contract, Payslip
|
2023-07-26 10:32:58 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
def expire_contract():
|
|
|
|
|
"""
|
2024-03-10 19:37:46 +05:30
|
|
|
Finds all active contracts whose end date is earlier than the current date
|
2023-07-26 10:32:58 +05:30
|
|
|
and updates their status to "expired".
|
|
|
|
|
"""
|
|
|
|
|
Contract.objects.filter(
|
|
|
|
|
contract_status="active", contract_end_date__lt=date.today()
|
|
|
|
|
).update(contract_status="expired")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
2024-07-10 16:13:13 +05:30
|
|
|
def generate_payslip(date, companies, all):
|
|
|
|
|
"""Generate payslip for previous month"""
|
|
|
|
|
|
|
|
|
|
from employee.models import Employee
|
|
|
|
|
|
|
|
|
|
date = date
|
|
|
|
|
employees = Employee.objects.none()
|
|
|
|
|
# Get all employees with in the companies
|
|
|
|
|
if all == True:
|
|
|
|
|
employees = employees | Employee.objects.filter(
|
|
|
|
|
employee_work_info__company_id__isnull=True
|
|
|
|
|
)
|
|
|
|
|
if companies:
|
|
|
|
|
for company in companies:
|
|
|
|
|
employees = employees | Employee.objects.filter(
|
|
|
|
|
employee_work_info__company_id=company
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Filter out employees who don't have a contract_set or whose contract status is not active
|
|
|
|
|
active_employees = employees.filter(
|
|
|
|
|
contract_set__isnull=False, contract_set__contract_status="active"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Remove duplicates if an employee has multiple active contracts
|
|
|
|
|
active_employees = active_employees.distinct()
|
|
|
|
|
# find the date range
|
|
|
|
|
start_date = date - relativedelta(months=1)
|
|
|
|
|
end_date = date - timedelta(days=1)
|
|
|
|
|
# Payslip creation
|
|
|
|
|
for employee in active_employees:
|
|
|
|
|
payslip = Payslip.objects.filter(
|
|
|
|
|
employee_id=employee, start_date=start_date, end_date=end_date
|
|
|
|
|
).first()
|
2024-07-15 12:02:40 +05:30
|
|
|
if payslip:
|
|
|
|
|
continue
|
2024-07-10 16:13:13 +05:30
|
|
|
contract = Contract.objects.filter(
|
|
|
|
|
employee_id=employee, contract_status="active"
|
|
|
|
|
).first()
|
|
|
|
|
if end_date < contract.contract_start_date:
|
|
|
|
|
continue
|
|
|
|
|
if start_date < contract.contract_start_date:
|
|
|
|
|
start_date = contract.contract_start_date
|
|
|
|
|
payslip_data = payroll_calculation(employee, start_date, end_date)
|
|
|
|
|
payslip_data["payslip"] = payslip
|
|
|
|
|
data = {}
|
|
|
|
|
data["employee"] = employee
|
|
|
|
|
data["start_date"] = payslip_data["start_date"]
|
|
|
|
|
data["end_date"] = payslip_data["end_date"]
|
|
|
|
|
data["status"] = "draft"
|
|
|
|
|
data["contract_wage"] = payslip_data["contract_wage"]
|
|
|
|
|
data["basic_pay"] = payslip_data["basic_pay"]
|
|
|
|
|
data["gross_pay"] = payslip_data["gross_pay"]
|
|
|
|
|
data["deduction"] = payslip_data["total_deductions"]
|
|
|
|
|
data["net_pay"] = payslip_data["net_pay"]
|
|
|
|
|
data["pay_data"] = json.loads(payslip_data["json_data"])
|
|
|
|
|
calculate_employer_contribution(data)
|
|
|
|
|
data["installments"] = payslip_data["installments"]
|
|
|
|
|
payslip_data["instance"] = save_payslip(**data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_last_day_of_month(date):
|
|
|
|
|
next_day = date + timedelta(days=1)
|
|
|
|
|
return next_day.month != date.month
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def auto_payslip_generate():
|
|
|
|
|
"""
|
|
|
|
|
Generating payslips for active contract employees
|
|
|
|
|
"""
|
|
|
|
|
from base.models import Company
|
|
|
|
|
|
|
|
|
|
from .models.models import PayslipAutoGenerate
|
|
|
|
|
|
|
|
|
|
# from payroll.models import PayslipAutoGenerate
|
|
|
|
|
if PayslipAutoGenerate.objects.filter(auto_generate=True).exists():
|
|
|
|
|
today = date.today()
|
|
|
|
|
day_today = today.day
|
|
|
|
|
last_day = (today + timedelta(days=1)).replace(day=1) - timedelta(days=1)
|
|
|
|
|
auto_payslips = PayslipAutoGenerate.objects.filter(auto_generate=True)
|
|
|
|
|
companies = []
|
|
|
|
|
auto_companies = [auto.company_id for auto in auto_payslips]
|
|
|
|
|
for auto in auto_payslips:
|
|
|
|
|
generate_day = auto.generate_day
|
|
|
|
|
if generate_day == "last day":
|
|
|
|
|
if is_last_day_of_month(today):
|
|
|
|
|
companies.append(auto.company_id)
|
|
|
|
|
else:
|
|
|
|
|
generate_day = int(generate_day)
|
|
|
|
|
if generate_day >= last_day.day and day_today == last_day.day:
|
|
|
|
|
companies.append(auto.company_id)
|
|
|
|
|
elif generate_day == day_today:
|
|
|
|
|
companies.append(auto.company_id)
|
|
|
|
|
|
|
|
|
|
companies = list(set(companies)) # Remove duplicates
|
|
|
|
|
# Check if 'All company' case exists, i.e., None is in companies
|
|
|
|
|
if companies:
|
|
|
|
|
if None in companies:
|
|
|
|
|
company_all = Company.objects.all()
|
|
|
|
|
generate_companies = []
|
|
|
|
|
# Append the companies that are not in PayslipAutoGenerate
|
|
|
|
|
for company in company_all:
|
|
|
|
|
if company not in auto_companies:
|
|
|
|
|
generate_companies.append(company)
|
|
|
|
|
generate_payslip(
|
|
|
|
|
date=date.today(), companies=generate_companies, all=True
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
generate_payslip(date=date.today(), companies=companies, all=False)
|
|
|
|
|
|
|
|
|
|
|
2025-01-07 15:13:47 +05:30
|
|
|
if not any(
|
|
|
|
|
cmd in sys.argv
|
|
|
|
|
for cmd in ["makemigrations", "migrate", "compilemessages", "flush", "shell"]
|
|
|
|
|
):
|
|
|
|
|
scheduler = BackgroundScheduler()
|
|
|
|
|
scheduler.add_job(expire_contract, "interval", hours=4)
|
|
|
|
|
scheduler.add_job(auto_payslip_generate, "interval", hours=3)
|
|
|
|
|
scheduler.start()
|