| Server IP : 65.108.144.40 / Your IP : 216.73.217.165 Web Server : Apache/2.4.52 (Ubuntu) System : Linux ubuntu-8gb-hel1-1 5.15.0-173-generic #183-Ubuntu SMP Fri Mar 6 13:29:34 UTC 2026 x86_64 User : dev ( 1000) PHP Version : 8.2.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/erp/payroll/ |
Upload File : |
"""
scheduler.py
This module is used to register scheduled tasks
"""
import json
import sys
from datetime import date, timedelta
from apscheduler.schedulers.background import BackgroundScheduler
from dateutil.relativedelta import relativedelta
from payroll.methods.methods import calculate_employer_contribution, save_payslip
from payroll.views.component_views import payroll_calculation
from .models.models import Contract, Payslip
def expire_contract():
"""
Finds all active contracts whose end date is earlier than the current date
and updates their status to "expired".
"""
Contract.objects.filter(
contract_status="active", contract_end_date__lt=date.today()
).update(contract_status="expired")
return
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()
if payslip:
continue
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)
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()