Release Notes for v3.6.0 (173 commits)
(No pull request description was provided — I'll work with just the title.)
Based on the title alone:
Adds a new "Employee CTC Breakup" report that displays a breakdown of employee cost-to-company (CTC) compensation components. !2172 (backport) (from hrms#4485)
Features (4)
Wait, I need to look at the actual code changes. Since no diff or description was provided beyond the title, let me base the changelog on what the title conveys:
Adds missing permission checks to restrict certain actions to users who have the required access rights. !2214 (backport) (from hrms#4594)
From user:
Tried to add Currency formatting
Fix description:
Currency fields on the frontend should be formatted like other currency fields (with the currency symbol and correct decimal places) but currently only raw numbers are returned.
When a currency field is defined as not having This PR fixes that by:
Here is the diff:
Fixes currency fields without a linked Options field to fall back to the system's default currency when formatting values. !2212 (backport) (from hrms#4598)
Adds default permissions for the "Expense Approver" and "Shift Request Approver" roles, allowing them to read, write, share, email, and print Expense Claim and Shift Request records submitted for their approval. !2068 (backport) (by iamkhanraheel)
Scenario: If we set HR Settings > Employees > Employee Naming By = Naming Series, then while creating an Employee, the naming series field should be visible and vice-versa.
The Naming Series field on the Employee form is now shown or hidden based on the Employee Naming By setting in HR Settings. !2159 (backport) (from hrms#4521)
Fixes (28)
options (it's just a standalone field, not tied to a specific currency document), then the system currently returns None for the currency symbol, and the backend formatting fails silently or returns an incorrect format.
frappe.db.get_default("currency")).
diff --git a/frappe/utils/formatters.py b/frappe/utils/formatters.py
index 3e35fee58c..90febe3ff3 100644
--- a/frappe/utils/formatters.py
+++ b/frappe/utils/formatters.py
@@ -62,7 +62,8 @@ def format_value(value, df=None, doc=None, currency=None, translated=False, form
currency = doc.get(df.options)
if not currency:
- currency = frappe.db.get_default("currency")
+ currency = get_field_currency(df, doc)
+ currency = currency or frappe.db.get_default("currency")
return fmt_money(value, precision=precision, currency=currency, format=format)
Currently if we assign an Expense Approver or Shift Request Approver role, they don't have permission to approve Expense Claim and Shift Request documents created by other employees.
I've fixed this issue by creating a custom permission for HR roles "Expense Approver" and "Shift Request Approver" to allow document owners to share the record with the approvers.
@@ -0,0 +1,35 @@
+[
+ {
+ "allow_blogs_for_user": 0,
+ "apply_user_permissions": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "is_default": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 0,
+ "role": "Expense Approver",
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+]
+[
+ {
+ "allow_blogs_for_user": 0,
+ "apply_user_permissions": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "is_default": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 0,
+ "role": "Shift Request Approver",
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+]
The Employee naming series should be visible based on HR Settings.
diff --git a/hrms/hr/doctype/employee/employee.js b/hrms/hr/doctype/employee/employee.js
index fa5b6e6de5..0f59d28050 100644
--- a/hrms/hr/doctype/employee/employee.js
+++ b/hrms/hr/doctype/employee/employee.js
@@ -11,6 +11,7 @@ frappe.ui.form.on("Employee", {
frm.set_query("user_id", function () {
return { filters: { ignore_user_type: 1 } };
});
+ frm.trigger("employee_name");
},
employee_name: function (frm) {
@@ -18,6 +19,10 @@ frappe.ui.form.on("Employee", {
frm.doc.employee_name
) {
frm.set_value("employee_name", "");
+ } else {
+ frappe.db.get_single_value("HR Settings", "emp_created_by").then((value) => {
+ frm.set_df_property("naming_series", "hidden", value !== "Naming Series");
+ });
}
},
The Salary Payments report used a raw SQL query to fetch data. With this change, the report now uses a query builder (frappe.qb) instead.
Why is this change required? What problem does it fix?
Using a raw SQL query to fetch data increases the risk of SQL injection attacks and makes it harder to maintain the code.
Please provide the change log sentence(s) here:
Here is the diff:
Updates the "Salary Payments Based on Payment Mode" report to use a query builder instead of a raw SQL query, reducing the risk of SQL injection attacks. !2161 (backport) (from hrms#4527)
Refactors (4)
closes #xyz
Changes
Motivation and Context
diff --git a/hrms/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py b/hrms/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
index e5e8befd..55b41783 100644
--- a/hrms/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
+++ b/hrms/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
@@ -1,8 +1,9 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
+import frappe
from frappe import _
-from frappe.utils import getdate
+from frappe.query_builder.functions import Sum
def execute(filters=None):
@@ -36,19 +36,27 @@ def get_columns():
def get_data(filters):
- conditions = get_conditions(filters)
-
- return frappe.db.sql(
- """select bank_name, sum(amount) as amount, count(*) as no_of_employees
- from `tabSalary Slip`
- where docstatus=1 {0}
- group by bank_name""".format(
- conditions
- ),
- as_dict=True,
- )
-
-
-def get_conditions(filters):
- conditions = " and posting_date >= '{0}' and posting_date <= '{1}'".format(
- getdate(filters.from_date), getdate(filters.to_date)
- )
- return conditions
+ SalarySlip = frappe.qb.DocType("Salary Slip")
+
+ query = (
+ frappe.qb.from_(SalarySlip)
+ .select(
+ SalarySlip.bank_name,
+ Sum(SalarySlip.amount).as_("amount"),
+ frappe.qb.terms.ValueWrapper(1)
+ .count()
+ .as_("no_of_employees"),
+ )
+ .where(SalarySlip.docstatus == 1)
+ .where(SalarySlip.posting_date >= filters.from_date)
+ .where(SalarySlip.posting_date <= filters.to_date)
+ .groupby(SalarySlip.bank_name)
+ )
+
+ return query.run(as_dict=True)
Fixes an issue where outstanding invoices could be incorrectly filtered when no specific voucher is provided in certain payment reconciliation scenarios. !2189 (backport) (from hrms#4578)
Tests and CI/CD (1)
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 826af0d7a0..e30c8d3c0b 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -1,7 +1,6 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-
import json
from json import JSONDecodeError
@@ -1004,12 +1004,11 @@ def get_outstanding_invoices(
if voucher_no:
filter_string += " and voucher_no = %(voucher_no)s"
- netting_vouchers = frappe.get_all(
- "Payment Ledger Entry",
- filters={"delinked": 0, "against_voucher_no": voucher_no},
- fields=["voucher_no"],
- distinct=True,
- )
+ if voucher_no:
+ netting_vouchers = frappe.get_all(
+ "Payment Ledger Entry",
+ filters={"delinked": 0, "against_voucher_no": voucher_no},
+ fields=["voucher_no"],
+ distinct=True,
+ )
+ else:
+ netting_vouchers = []
netting_voucher_nos = [x.voucher_no for x in netting_vouchers]
Contributors
and 1 other contributors…
Full diff: v3.5.1...v3.6.0
Tag: v3.6.0
The original content collected in merge requests has been automatically enhanced by Claude 3.7 Sonnet