271 lines
7.8 KiB
Python
271 lines
7.8 KiB
Python
import datetime
|
|
import random
|
|
|
|
import frappe
|
|
from frappe.utils import add_days, get_last_day, getdate, random_string
|
|
from frappe.utils.make_random import get_random
|
|
|
|
import erpnext
|
|
from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry
|
|
from erpnext.hr.doctype.expense_claim.test_expense_claim import get_payable_account
|
|
from erpnext.hr.doctype.leave_application.leave_application import (
|
|
AttendanceAlreadyMarkedError,
|
|
OverlapError,
|
|
get_leave_balance_on,
|
|
)
|
|
from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet
|
|
from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
|
|
|
|
|
|
def work():
|
|
frappe.set_user(frappe.db.get_global("demo_hr_user"))
|
|
year, month = frappe.flags.current_date.strftime("%Y-%m").split("-")
|
|
setup_department_approvers()
|
|
mark_attendance()
|
|
make_leave_application()
|
|
|
|
# payroll entry
|
|
if not frappe.db.sql(
|
|
"select name from `tabSalary Slip` where month(adddate(start_date, interval 1 month))=month(curdate())"
|
|
):
|
|
# based on frequency
|
|
payroll_entry = get_payroll_entry()
|
|
payroll_entry.salary_slip_based_on_timesheet = 0
|
|
payroll_entry.save()
|
|
payroll_entry.create_salary_slips()
|
|
payroll_entry.submit_salary_slips()
|
|
payroll_entry.make_accrual_jv_entry()
|
|
payroll_entry.submit()
|
|
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
|
# reference_number=random_string(10))
|
|
|
|
# based on timesheet
|
|
payroll_entry = get_payroll_entry()
|
|
payroll_entry.salary_slip_based_on_timesheet = 1
|
|
payroll_entry.save()
|
|
payroll_entry.create_salary_slips()
|
|
payroll_entry.submit_salary_slips()
|
|
payroll_entry.make_accrual_jv_entry()
|
|
payroll_entry.submit()
|
|
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
|
# reference_number=random_string(10))
|
|
|
|
if frappe.db.get_global("demo_hr_user"):
|
|
make_timesheet_records()
|
|
|
|
# expense claim
|
|
expense_claim = frappe.new_doc("Expense Claim")
|
|
expense_claim.extend("expenses", get_expenses())
|
|
expense_claim.employee = get_random("Employee")
|
|
expense_claim.company = frappe.flags.company
|
|
expense_claim.payable_account = get_payable_account(expense_claim.company)
|
|
expense_claim.posting_date = frappe.flags.current_date
|
|
expense_claim.expense_approver = frappe.db.get_global("demo_hr_user")
|
|
expense_claim.save()
|
|
|
|
rand = random.random()
|
|
|
|
if rand < 0.4:
|
|
update_sanctioned_amount(expense_claim)
|
|
expense_claim.approval_status = "Approved"
|
|
expense_claim.submit()
|
|
|
|
if random.randint(0, 1):
|
|
# make journal entry against expense claim
|
|
je = frappe.get_doc(make_bank_entry("Expense Claim", expense_claim.name))
|
|
je.posting_date = frappe.flags.current_date
|
|
je.cheque_no = random_string(10)
|
|
je.cheque_date = frappe.flags.current_date
|
|
je.flags.ignore_permissions = 1
|
|
je.submit()
|
|
|
|
|
|
def get_payroll_entry():
|
|
# process payroll for previous month
|
|
payroll_entry = frappe.new_doc("Payroll Entry")
|
|
payroll_entry.company = frappe.flags.company
|
|
payroll_entry.payroll_frequency = "Monthly"
|
|
|
|
# select a posting date from the previous month
|
|
payroll_entry.posting_date = get_last_day(
|
|
getdate(frappe.flags.current_date) - datetime.timedelta(days=10)
|
|
)
|
|
payroll_entry.payment_account = frappe.get_value(
|
|
"Account",
|
|
{"account_type": "Cash", "company": erpnext.get_default_company(), "is_group": 0},
|
|
"name",
|
|
)
|
|
|
|
payroll_entry.set_start_end_dates()
|
|
return payroll_entry
|
|
|
|
|
|
def get_expenses():
|
|
expenses = []
|
|
expese_types = frappe.db.sql(
|
|
"""select ect.name, eca.default_account from `tabExpense Claim Type` ect,
|
|
`tabExpense Claim Account` eca where eca.parent=ect.name
|
|
and eca.company=%s """,
|
|
frappe.flags.company,
|
|
as_dict=1,
|
|
)
|
|
|
|
for expense_type in expese_types[: random.randint(1, 4)]:
|
|
claim_amount = random.randint(1, 20) * 10
|
|
|
|
expenses.append(
|
|
{
|
|
"expense_date": frappe.flags.current_date,
|
|
"expense_type": expense_type.name,
|
|
"default_account": expense_type.default_account or "Miscellaneous Expenses - WPL",
|
|
"amount": claim_amount,
|
|
"sanctioned_amount": claim_amount,
|
|
}
|
|
)
|
|
|
|
return expenses
|
|
|
|
|
|
def update_sanctioned_amount(expense_claim):
|
|
for expense in expense_claim.expenses:
|
|
sanctioned_amount = random.randint(1, 20) * 10
|
|
|
|
if sanctioned_amount < expense.amount:
|
|
expense.sanctioned_amount = sanctioned_amount
|
|
|
|
|
|
def get_timesheet_based_salary_slip_employee():
|
|
sal_struct = frappe.db.sql(
|
|
"""
|
|
select name from `tabSalary Structure`
|
|
where salary_slip_based_on_timesheet = 1
|
|
and docstatus != 2"""
|
|
)
|
|
if sal_struct:
|
|
employees = frappe.db.sql(
|
|
"""
|
|
select employee from `tabSalary Structure Assignment`
|
|
where salary_structure IN %(sal_struct)s""",
|
|
{"sal_struct": sal_struct},
|
|
as_dict=True,
|
|
)
|
|
return employees
|
|
else:
|
|
return []
|
|
|
|
|
|
def make_timesheet_records():
|
|
employees = get_timesheet_based_salary_slip_employee()
|
|
for e in employees:
|
|
ts = make_timesheet(
|
|
e.employee,
|
|
simulate=True,
|
|
billable=1,
|
|
activity_type=get_random("Activity Type"),
|
|
company=frappe.flags.company,
|
|
)
|
|
frappe.db.commit()
|
|
|
|
rand = random.random()
|
|
if rand >= 0.3:
|
|
make_salary_slip_for_timesheet(ts.name)
|
|
|
|
rand = random.random()
|
|
if rand >= 0.2:
|
|
make_sales_invoice_for_timesheet(ts.name)
|
|
|
|
|
|
def make_salary_slip_for_timesheet(name):
|
|
salary_slip = make_salary_slip(name)
|
|
salary_slip.insert()
|
|
salary_slip.submit()
|
|
frappe.db.commit()
|
|
|
|
|
|
def make_sales_invoice_for_timesheet(name):
|
|
sales_invoice = make_sales_invoice(name)
|
|
sales_invoice.customer = get_random("Customer")
|
|
sales_invoice.append(
|
|
"items",
|
|
{
|
|
"item_code": get_random("Item", {"has_variants": 0, "is_stock_item": 0, "is_fixed_asset": 0}),
|
|
"qty": 1,
|
|
"rate": 1000,
|
|
},
|
|
)
|
|
sales_invoice.flags.ignore_permissions = 1
|
|
sales_invoice.set_missing_values()
|
|
sales_invoice.calculate_taxes_and_totals()
|
|
sales_invoice.insert()
|
|
sales_invoice.submit()
|
|
frappe.db.commit()
|
|
|
|
|
|
def make_leave_application():
|
|
allocated_leaves = frappe.get_all("Leave Allocation", fields=["employee", "leave_type"])
|
|
|
|
for allocated_leave in allocated_leaves:
|
|
leave_balance = get_leave_balance_on(
|
|
allocated_leave.employee,
|
|
allocated_leave.leave_type,
|
|
frappe.flags.current_date,
|
|
consider_all_leaves_in_the_allocation_period=True,
|
|
)
|
|
if leave_balance != 0:
|
|
if leave_balance == 1:
|
|
to_date = frappe.flags.current_date
|
|
else:
|
|
to_date = add_days(frappe.flags.current_date, random.randint(0, leave_balance - 1))
|
|
|
|
leave_application = frappe.get_doc(
|
|
{
|
|
"doctype": "Leave Application",
|
|
"employee": allocated_leave.employee,
|
|
"from_date": frappe.flags.current_date,
|
|
"to_date": to_date,
|
|
"leave_type": allocated_leave.leave_type,
|
|
}
|
|
)
|
|
try:
|
|
leave_application.insert()
|
|
leave_application.submit()
|
|
frappe.db.commit()
|
|
except (OverlapError, AttendanceAlreadyMarkedError):
|
|
frappe.db.rollback()
|
|
|
|
|
|
def mark_attendance():
|
|
attendance_date = frappe.flags.current_date
|
|
for employee in frappe.get_all("Employee", fields=["name"], filters={"status": "Active"}):
|
|
|
|
if not frappe.db.get_value(
|
|
"Attendance", {"employee": employee.name, "attendance_date": attendance_date}
|
|
):
|
|
attendance = frappe.get_doc(
|
|
{"doctype": "Attendance", "employee": employee.name, "attendance_date": attendance_date}
|
|
)
|
|
|
|
leave = frappe.db.sql(
|
|
"""select name from `tabLeave Application`
|
|
where employee = %s and %s between from_date and to_date
|
|
and docstatus = 1""",
|
|
(employee.name, attendance_date),
|
|
)
|
|
|
|
if leave:
|
|
attendance.status = "Absent"
|
|
else:
|
|
attendance.status = "Present"
|
|
attendance.save()
|
|
attendance.submit()
|
|
frappe.db.commit()
|
|
|
|
|
|
def setup_department_approvers():
|
|
for d in frappe.get_all("Department", filters={"department_name": ["!=", "All Departments"]}):
|
|
doc = frappe.get_doc("Department", d.name)
|
|
doc.append("leave_approvers", {"approver": frappe.session.user})
|
|
doc.append("expense_approvers", {"approver": frappe.session.user})
|
|
doc.flags.ignore_mandatory = True
|
|
doc.save()
|