diff --git a/hrms/hr/doctype/expense_claim/test_expense_claim.py b/hrms/hr/doctype/expense_claim/test_expense_claim.py index 3d6ded9a53..cd1f724368 100644 --- a/hrms/hr/doctype/expense_claim/test_expense_claim.py +++ b/hrms/hr/doctype/expense_claim/test_expense_claim.py @@ -589,13 +589,6 @@ def test_rounding(self): self.assertEqual(expense_claim.status, "Unpaid") def test_repost(self): - # Update repost settings - allowed_types = ["Expense Claim"] - repost_settings = frappe.get_doc("Repost Accounting Ledger Settings") - for x in allowed_types: - repost_settings.append("allowed_types", {"document_type": x, "allowed": True}) - repost_settings.save() - payable_account = get_payable_account(company_name) taxes = generate_taxes(rate=10) expense_claim = make_expense_claim( diff --git a/hrms/hr/doctype/leave_allocation/test_earned_leaves.py b/hrms/hr/doctype/leave_allocation/test_earned_leaves.py index 139cbc9c9f..d65b60a2e2 100644 --- a/hrms/hr/doctype/leave_allocation/test_earned_leaves.py +++ b/hrms/hr/doctype/leave_allocation/test_earned_leaves.py @@ -1103,24 +1103,80 @@ def test_allocating_earned_leave_when_schedule_doesnt_exist(self): frappe.delete_doc_if_exists("Employee", employee2.name, force=1) + def test_exceed_newly_allocated_leaves(self): + this_year_start = get_year_start(getdate()) + this_year_end = get_year_ending(getdate()) + last_year_start = add_months(this_year_start, -12) + last_year_end = add_months(this_year_end, -12) + + make_policy_assignment( + self.employee, + allocate_on_day="Last Day", + start_date=last_year_start, + end_date=last_year_end, + earned_leave_frequency="Monthly", + annual_allocation=11, + ) + frappe.flags.current_date = this_year_start + # 11 leaves get carried forward from last year with this assignment + make_policy_assignment( + self.employee, + allocate_on_day="Last Day", + start_date=this_year_start, + end_date=this_year_end, + earned_leave_frequency="Monthly", + annual_allocation=24, + carry_forward=1, + ) + # max leave allowed is 12 + frappe.db.set_value("Leave Type", "Test Earned Leave", "max_leaves_allowed", 12) + frappe.flags.current_date = get_last_day(this_year_start) + # earned leave according to policy is 2 but allocates 1 due to max leave limit + allocate_earned_leaves() + leave_balance = get_leave_balance_on(self.employee.name, self.leave_type, frappe.flags.current_date) + leave_allocation = frappe.get_value( + "Leave Allocation", + {"employee": self.employee.name, "leave_type": "Test Earned Leave", "from_date": this_year_start}, + ["total_leaves_allocated", "name"], + as_dict=1, + ) + self.assertEqual(leave_allocation.total_leaves_allocated, 12) + self.assertEqual(leave_balance, 12) + + # schedule shows 1 leave instead of 2 + earned_leaves_allocated = frappe.get_value( + "Earned Leave Schedule", + {"parent": leave_allocation.name, "allocation_date": frappe.flags.current_date}, + "number_of_leaves", + ) + self.assertEqual(earned_leaves_allocated, 1) + def create_earned_leave_type( leave_type, allocate_on_day="Last Day", rounding=0.5, earned_leave_frequency="Monthly" ): - frappe.delete_doc_if_exists("Leave Type", leave_type, force=1) - frappe.delete_doc_if_exists("Leave Type", "Test Earned Leave Type", force=1) - frappe.delete_doc_if_exists("Leave Type", "Test Earned Leave Type 2", force=1) - - return frappe.get_doc( - leave_type_name=leave_type, - doctype="Leave Type", - is_earned_leave=1, - earned_leave_frequency=earned_leave_frequency, - rounding=rounding, - is_carry_forward=1, - allocate_on_day=allocate_on_day, - max_leaves_allowed=0, - ).insert() + if frappe.db.exists("Leave Type", leave_type): + doc = frappe.get_doc("Leave Type", leave_type) + doc.update( + { + "allocate_on_day": allocate_on_day, + "rounding": rounding, + "earned_leave_frequency": earned_leave_frequency, + } + ) + doc.save() + return doc + else: + return frappe.get_doc( + leave_type_name=leave_type, + doctype="Leave Type", + is_earned_leave=1, + earned_leave_frequency=earned_leave_frequency, + rounding=rounding, + is_carry_forward=1, + allocate_on_day=allocate_on_day, + max_leaves_allowed=0, + ).insert() def create_leave_period(name, start_date=None, end_date=None): diff --git a/hrms/hr/utils.py b/hrms/hr/utils.py index 34ab3c0415..f6e667ca8f 100644 --- a/hrms/hr/utils.py +++ b/hrms/hr/utils.py @@ -417,38 +417,48 @@ def calculate_upcoming_earned_leave(allocation, e_leave_type, date_of_joining): def update_previous_leave_allocation(allocation, annual_allocation, e_leave_type, earned_leaves, today): allocation = frappe.get_doc("Leave Allocation", allocation.name) - annual_allocation = flt(annual_allocation, allocation.precision("total_leaves_allocated")) - - new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves) - new_allocation_without_cf = flt( - flt(allocation.get_existing_leave_count()) + flt(earned_leaves), - allocation.precision("total_leaves_allocated"), + precision = allocation.precision("total_leaves_allocated") + annual_allocation = flt(annual_allocation, precision) + earned_leaves = flt(earned_leaves, precision) + new_leaves_to_allocate_without_cf = flt( + flt(allocation.get_existing_leave_count()) + earned_leaves, + precision, ) - - if new_allocation > e_leave_type.max_leaves_allowed and e_leave_type.max_leaves_allowed > 0: - frappe.throw( - _( - "Allocation was skipped due to maximum leave allocation limit set in leave type. Please increase the limit and retry failed allocation." - ), - OverAllocationError, - ) if ( # annual allocation as per policy should not be exceeded except for yearly leaves - new_allocation_without_cf > annual_allocation and e_leave_type.earned_leave_frequency != "Yearly" + new_leaves_to_allocate_without_cf > annual_allocation + and e_leave_type.earned_leave_frequency != "Yearly" ): frappe.throw( _("Allocation was skipped due to exceeding annual allocation set in leave policy"), OverAllocationError, ) - allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False) + if e_leave_type.max_leaves_allowed: + leaves_quota = flt(e_leave_type.max_leaves_allowed - allocation.total_leaves_allocated, precision) + if leaves_quota <= 0: + frappe.throw( + _( + "Allocation was skipped due to maximum leave allocation limit set in leave type. Please increase the limit and retry failed allocation." + ), + OverAllocationError, + ) + else: + if leaves_quota < earned_leaves: + earned_leaves = leaves_quota + + allocation.db_set( + "total_leaves_allocated", + earned_leaves + allocation.total_leaves_allocated, + update_modified=False, + ) create_additional_leave_ledger_entry(allocation, earned_leaves, today) earned_leave_schedule = qb.DocType("Earned Leave Schedule") qb.update(earned_leave_schedule).where( (earned_leave_schedule.parent == allocation.name) & (earned_leave_schedule.allocation_date == today) ).set(earned_leave_schedule.is_allocated, 1).set(earned_leave_schedule.attempted, 1).set( earned_leave_schedule.allocated_via, "Scheduler" - ).run() + ).set(earned_leave_schedule.number_of_leaves, earned_leaves).run() def log_allocation_error(allocation_name, error): diff --git a/hrms/setup.py b/hrms/setup.py index bedbb31327..aeb161fb91 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -18,6 +18,7 @@ def after_install(): update_hr_defaults() add_non_standard_user_types() set_single_defaults() + setup_repost_defaults() create_default_role_profiles() run_post_install_patches() @@ -855,3 +856,10 @@ def get_salary_slip_loan_fields(): def make_people_workspace_standard(): if frappe.db.exists("Workspace Sidebar", "People"): frappe.db.set_value("Workspace Sidebar", "People", "standard", 1) + + +def setup_repost_defaults(): + accounts_settings = frappe.get_doc("Accounts Settings") + for x in frappe.get_hooks("repost_allowed_doctypes"): + accounts_settings.append("repost_allowed_types", {"document_type": x}) + accounts_settings.save()