Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: release v15 #2718

Merged
merged 13 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts

- name: Cache pip
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
Expand All @@ -79,7 +79,7 @@ jobs:
${{ runner.os }}-

- name: Cache node modules
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
Expand All @@ -94,7 +94,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"

- uses: actions/cache@v2
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
Expand Down
25 changes: 15 additions & 10 deletions hrms/hr/doctype/employee_checkin/employee_checkin.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,27 @@ frappe.ui.form.on("Employee Checkin", {
add_fetch_shift_button(frm) {
if (frm.doc.attendace) return;
frm.add_custom_button(__("Fetch Shift"), function () {
const previous_shift = frm.doc.shift;
frappe.call({
method: "fetch_shift",
doc: frm.doc,
freeze: true,
freeze_message: __("Fetching Shift"),
callback: function () {
if (previous_shift === frm.doc.shift) return;
frm.dirty();
frm.save();
frappe.show_alert({
message: __("Shift has been successfully updated to {0}.", [
frm.doc.shift,
]),
indicator: "green",
});
if (frm.doc.shift) {
frappe.show_alert({
message: __("Shift has been successfully updated to {0}.", [
frm.doc.shift,
]),
indicator: "green",
});
frm.dirty();
frm.save();
} else {
frappe.show_alert({
message: __("No valid shift found for log time"),
indicator: "orange",
});
}
},
});
});
Expand Down
28 changes: 28 additions & 0 deletions hrms/hr/doctype/employee_checkin/test_employee_checkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,34 @@ def test_bulk_fetch_shift(self):
# shift does not change since attendance is already marked
self.assertEqual(log2.shift, shift1.name)

def test_bulk_fetch_shift_if_shift_settings_change_for_the_same_shift(self):
emp1 = make_employee("[email protected]", company="_Test Company")
emp2 = make_employee("[email protected]", company="_Test Company")

# 8 - 12,
shift = setup_shift_type(shift_type="Test Bulk Shift")
date = getdate()
make_shift_assignment(shift.name, emp1, date)
make_shift_assignment(shift.name, emp2, date)

timestamp = datetime.combine(date, get_time("08:00:00"))
# shift actual start is `current date 07:00:00`
log1 = make_checkin(emp1, timestamp)
self.assertEqual(log1.shift_actual_start, datetime.combine(date, get_time("07:00:00")))
log2 = make_checkin(emp2, timestamp)
self.assertEqual(log2.shift_actual_start, datetime.combine(date, get_time("07:00:00")))

# change shift settings like check in buffer from 60 minutes to 120 minutes
# so now shift actual start is `current date 06:00:00`
shift.begin_check_in_before_shift_start_time = 120
shift.save()
bulk_fetch_shift([log1.name, log2.name])
# shift changes according to the new assignment
log1.reload()
self.assertEqual(log1.shift_actual_start, datetime.combine(date, get_time("06:00:00")))
log2.reload()
self.assertEqual(log2.shift_actual_start, datetime.combine(date, get_time("06:00:00")))


def make_n_checkins(employee, n, hours_to_reverse=1):
logs = [make_checkin(employee, now_datetime() - timedelta(hours=hours_to_reverse, minutes=n + 1))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
from frappe.model.document import Document
from frappe.utils import flt, get_link_to_form, today

from hrms.hr.doctype.full_and_final_statement.full_and_final_statement_loan_utils import (
cancel_loan_repayment,
process_loan_accrual,
)


class FullandFinalStatement(Document):
def before_insert(self):
Expand All @@ -22,8 +27,12 @@ def before_submit(self):
self.validate_settlement("receivables")
self.validate_assets()

def on_submit(self):
process_loan_accrual(self)

def on_cancel(self):
self.ignore_linked_doctypes = ("GL Entry",)
cancel_loan_repayment(self)

def validate_relieving_date(self):
if not self.relieving_date:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from typing import TYPE_CHECKING

import frappe
from frappe import _

from hrms.payroll.doctype.salary_slip.salary_slip_loan_utils import if_lending_app_installed

if TYPE_CHECKING:
from hrms.payroll.doctype.full_and_final_statement.full_and_final_statement import FullandFinalStatement


@if_lending_app_installed
def process_loan_accrual(doc: "FullandFinalStatement"):
from lending.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import (
make_loan_interest_accrual_entry,
)
from lending.loan_management.doctype.loan_repayment.loan_repayment import (
calculate_amounts,
create_repayment_entry,
get_pending_principal_amount,
)

loan_receivables = []
for receivable in doc.receivables:
if receivable.component != "Loan":
continue

loan_receivables.append(receivable.reference_document)

for loan in loan_receivables:
loan_doc = frappe.get_doc("Loan", loan)
loan_repayment_schedule = frappe.get_doc("Loan Repayment Schedule", {"loan": loan, "docstatus": 1})
if loan_repayment_schedule.repayment_schedule:
amounts = []
for repayment_schedule in loan_repayment_schedule.repayment_schedule:
amounts = calculate_amounts(loan, doc.transaction_date, "Normal Repayment")
pending_principal_amount = get_pending_principal_amount(loan_doc)
if not repayment_schedule.is_accrued:
args = frappe._dict(
{
"loan": loan,
"applicant_type": loan_doc.applicant_type,
"applicant": loan_doc.applicant,
"interest_income_account": loan_doc.interest_income_account,
"loan_account": loan_doc.loan_account,
"pending_principal_amount": amounts["pending_principal_amount"],
"payable_principal": repayment_schedule.principal_amount,
"interest_amount": repayment_schedule.interest_amount,
"total_pending_interest_amount": pending_principal_amount,
"penalty_amount": amounts["penalty_amount"],
"posting_date": doc.transaction_date,
"repayment_schedule_name": repayment_schedule.name,
"accrual_type": "Regular",
"due_date": doc.transaction_date,
}
)
make_loan_interest_accrual_entry(args)
frappe.db.set_value("Repayment Schedule", repayment_schedule.name, "is_accrued", 1)

repayment_entry = create_repayment_entry(
loan,
doc.employee,
doc.company,
doc.transaction_date,
loan_doc.loan_product,
"Normal Repayment",
amounts["interest_amount"],
amounts["pending_principal_amount"],
receivable.amount,
)

repayment_entry.save()
repayment_entry.submit()


@if_lending_app_installed
def cancel_loan_repayment(doc: "FullandFinalStatement"):
loan_receivables = []
for receivable in doc.receivables:
if receivable.component != "Loan":
continue

loan_receivables.append(receivable.reference_document)

for loan in loan_receivables:
posting_date = frappe.utils.getdate(doc.transaction_date)
loan_repayment = frappe.get_doc(
"Loan Repayment", {"against_loan": loan, "docstatus": 1, "posting_date": posting_date}
)

if loan_repayment:
loan_repayment.cancel()

loan_interest_accruals = frappe.get_all(
"Loan Interest Accrual", filters={"loan": loan, "docstatus": 1, "posting_date": posting_date}
)
for accrual in loan_interest_accruals:
frappe.get_doc("Loan Interest Accrual", accrual.name).cancel()
1 change: 1 addition & 0 deletions hrms/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ def remove_lending_docperms_from_ess():
if row.document_type in loan_docperms:
doc.user_doctypes.remove(row)

doc.flags.ignore_links = True
doc.save(ignore_permissions=True)


Expand Down
Loading