Merge pull request #30987 from ankush/internal_transfer_with_margin
fix: prevent bypassing forced valuation rate
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 418bf3c..607e42d 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -12,10 +12,18 @@
1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
- For questions and general support, checkout the manual https://erpnext.com/docs/user/manual/en or use https://discuss.erpnext.com
- - For documentation issues, refer to https://github.com/frappe/erpnext_com
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
the original discussion.
-3. When making a feature request, make sure to be as verbose as possible. The better you convey your message, the greater the drive to make it happen.
+3. When making a feature request, make sure to be as verbose as possible. The better you convey your message, the greater the drive to make it happen.
+
+
+Please keep in mind that we get many many requests and we can't possibly work on all of them, we prioritize development based on the goals of the product and organization. Feature requests are still welcome as it helps us in research when we do decide to work on the requested feature.
+
+If you're in urgent need to a feature, please try the following channels to get paid developments done quickly:
+1. Certified ERPNext partners: https://erpnext.com/partners
+2. Developer community on ERPNext forums: https://discuss.erpnext.com/c/developers/5
+3. Telegram group for ERPNext/Frappe development work: https://t.me/erpnext_opps
+
-->
**Is your feature request related to a problem? Please describe.**
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 3f1998a..ce1ed33 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -234,17 +234,19 @@
return dimensions
-def get_dimension_with_children(doctype, dimension):
+def get_dimension_with_children(doctype, dimensions):
- if isinstance(dimension, list):
- dimension = dimension[0]
+ if isinstance(dimensions, str):
+ dimensions = [dimensions]
all_dimensions = []
- lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
- children = frappe.get_all(
- doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft"
- )
- all_dimensions += [c.name for c in children]
+
+ for dimension in dimensions:
+ lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
+ children = frappe.get_all(
+ doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft"
+ )
+ all_dimensions += [c.name for c in children]
return all_dimensions
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 7257e6d..a3a7be2 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -346,6 +346,12 @@
)
)
+ if ref_doc.doctype == "Purchase Invoice" and ref_doc.get("on_hold"):
+ frappe.throw(
+ _("{0} {1} is on hold").format(d.reference_doctype, d.reference_name),
+ title=_("Invalid Invoice"),
+ )
+
if ref_doc.docstatus != 1:
frappe.throw(_("{0} {1} must be submitted").format(d.reference_doctype, d.reference_name))
diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
index 5b70b51..a8211c8 100644
--- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
@@ -743,6 +743,21 @@
flt(payment_entry.total_taxes_and_charges, 2), flt(10 / payment_entry.target_exchange_rate, 2)
)
+ def test_payment_entry_against_onhold_purchase_invoice(self):
+ pi = make_purchase_invoice()
+
+ pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank USD - _TC")
+ pe.reference_no = "1"
+ pe.reference_date = "2016-01-01"
+
+ # block invoice after creating payment entry
+ # since `get_payment_entry` will not attach blocked invoice to payment
+ pi.block_invoice()
+ with self.assertRaises(frappe.ValidationError) as err:
+ pe.save()
+
+ self.assertTrue("is on hold" in str(err.exception).lower())
+
def create_payment_entry(**args):
payment_entry = frappe.new_doc("Payment Entry")
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
index 264d4a6..572410f 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
@@ -64,13 +64,15 @@
pos_opening_entry(frm) {
if (frm.doc.pos_opening_entry && frm.doc.period_start_date && frm.doc.period_end_date && frm.doc.user) {
reset_values(frm);
- frm.trigger("set_opening_amounts");
- frm.trigger("get_pos_invoices");
+ frappe.run_serially([
+ () => frm.trigger("set_opening_amounts"),
+ () => frm.trigger("get_pos_invoices")
+ ]);
}
},
set_opening_amounts(frm) {
- frappe.db.get_doc("POS Opening Entry", frm.doc.pos_opening_entry)
+ return frappe.db.get_doc("POS Opening Entry", frm.doc.pos_opening_entry)
.then(({ balance_details }) => {
balance_details.forEach(detail => {
frm.add_child("payment_reconciliation", {
@@ -83,7 +85,7 @@
},
get_pos_invoices(frm) {
- frappe.call({
+ return frappe.call({
method: 'erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices',
args: {
start: frappe.datetime.get_datetime_as_string(frm.doc.period_start_date),
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index a0c0ecc..b8154dd 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -3140,6 +3140,39 @@
si.reload()
self.assertTrue(si.items[0].serial_no)
+ def test_sales_invoice_with_disabled_account(self):
+ try:
+ account = frappe.get_doc("Account", "VAT 5% - _TC")
+ account.disabled = 1
+ account.save()
+
+ si = create_sales_invoice(do_not_save=True)
+ si.posting_date = add_days(getdate(), 1)
+ si.taxes = []
+
+ si.append(
+ "taxes",
+ {
+ "charge_type": "On Net Total",
+ "account_head": "VAT 5% - _TC",
+ "cost_center": "Main - _TC",
+ "description": "VAT @ 5.0",
+ "rate": 9,
+ },
+ )
+ si.save()
+
+ with self.assertRaises(frappe.ValidationError) as err:
+ si.submit()
+
+ self.assertTrue(
+ "Cannot create accounting entries against disabled accounts" in str(err.exception)
+ )
+
+ finally:
+ account.disabled = 0
+ account.save()
+
def test_gain_loss_with_advance_entry(self):
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 89034eb..1598d91 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -31,6 +31,7 @@
if gl_map:
if not cancel:
validate_accounting_period(gl_map)
+ validate_disabled_accounts(gl_map)
gl_map = process_gl_map(gl_map, merge_entries)
if gl_map and len(gl_map) > 1:
save_entries(gl_map, adv_adj, update_outstanding, from_repost)
@@ -45,6 +46,26 @@
make_reverse_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
+def validate_disabled_accounts(gl_map):
+ accounts = [d.account for d in gl_map if d.account]
+
+ Account = frappe.qb.DocType("Account")
+
+ disabled_accounts = (
+ frappe.qb.from_(Account)
+ .where(Account.name.isin(accounts) & Account.disabled == 1)
+ .select(Account.name, Account.disabled)
+ ).run(as_dict=True)
+
+ if disabled_accounts:
+ account_list = "<br>"
+ account_list += ", ".join([frappe.bold(d.name) for d in disabled_accounts])
+ frappe.throw(
+ _("Cannot create accounting entries against disabled accounts: {0}").format(account_list),
+ title=_("Disabled Account Selected"),
+ )
+
+
def validate_accounting_period(gl_map):
accounting_periods = frappe.db.sql(
""" SELECT
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 56d68e1..3682577 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -507,7 +507,7 @@
)
additional_conditions.append("{0} in %({0})s".format(dimension.fieldname))
else:
- additional_conditions.append("{0} in (%({0})s)".format(dimension.fieldname))
+ additional_conditions.append("{0} in %({0})s".format(dimension.fieldname))
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 865cf14..e4b561e 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -275,7 +275,7 @@
)
conditions.append("{0} in %({0})s".format(dimension.fieldname))
else:
- conditions.append("{0} in (%({0})s)".format(dimension.fieldname))
+ conditions.append("{0} in %({0})s".format(dimension.fieldname))
return "and {}".format(" and ".join(conditions)) if conditions else ""
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index a73c72c..e8a1e79 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -237,7 +237,7 @@
else:
conditions += (
common_condition
- + "and ifnull(`tabPurchase Invoice Item`.{0}, '') in (%({0})s))".format(dimension.fieldname)
+ + "and ifnull(`tabPurchase Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname)
)
return conditions
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index fc48dd2..34b3f03 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -405,7 +405,7 @@
else:
conditions += (
common_condition
- + "and ifnull(`tabSales Invoice Item`.{0}, '') in (%({0})s))".format(dimension.fieldname)
+ + "and ifnull(`tabSales Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname)
)
return conditions
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py
index dd0ac75..e5a4ed2 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.py
+++ b/erpnext/accounts/report/trial_balance/trial_balance.py
@@ -188,9 +188,9 @@
filters[dimension.fieldname] = get_dimension_with_children(
dimension.document_type, filters.get(dimension.fieldname)
)
- additional_conditions += "and {0} in %({0})s".format(dimension.fieldname)
+ additional_conditions += " and {0} in %({0})s".format(dimension.fieldname)
else:
- additional_conditions += "and {0} in (%({0})s)".format(dimension.fieldname)
+ additional_conditions += " and {0} in %({0})s".format(dimension.fieldname)
query_filters.update({dimension.fieldname: filters.get(dimension.fieldname)})
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index e7049fd..4e29ee5 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -31,7 +31,7 @@
if (frm.doc.docstatus === 1) {
frm.add_custom_button(__('Supplier Quotation'),
- function(){ frm.trigger("make_suppplier_quotation") }, __("Create"));
+ function(){ frm.trigger("make_supplier_quotation") }, __("Create"));
frm.add_custom_button(__("Send Emails to Suppliers"), function() {
@@ -87,16 +87,24 @@
},
- make_suppplier_quotation: function(frm) {
+ make_supplier_quotation: function(frm) {
var doc = frm.doc;
var dialog = new frappe.ui.Dialog({
title: __("Create Supplier Quotation"),
fields: [
- { "fieldtype": "Select", "label": __("Supplier"),
+ { "fieldtype": "Link",
+ "label": __("Supplier"),
"fieldname": "supplier",
- "options": doc.suppliers.map(d => d.supplier),
+ "options": 'Supplier',
"reqd": 1,
- "default": doc.suppliers.length === 1 ? doc.suppliers[0].supplier_name : "" },
+ get_query: () => {
+ return {
+ filters: [
+ ["Supplier", "name", "in", frm.doc.suppliers.map((row) => {return row.supplier;})]
+ ]
+ }
+ }
+ }
],
primary_action_label: __("Create"),
primary_action: (args) => {
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
index 4993df9..083cab7 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
@@ -32,7 +32,9 @@
"terms",
"printing_settings",
"select_print_heading",
- "letter_head"
+ "letter_head",
+ "more_info",
+ "opportunity"
],
"fields": [
{
@@ -194,6 +196,23 @@
"print_hide": 1
},
{
+ "collapsible": 1,
+ "fieldname": "more_info",
+ "fieldtype": "Section Break",
+ "label": "More Information",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-file-text",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "opportunity",
+ "fieldtype": "Link",
+ "label": "Opportunity",
+ "options": "Opportunity",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
@@ -258,7 +277,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-11-24 17:47:49.909000",
+ "modified": "2022-04-06 17:47:49.909000",
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation",
@@ -327,4 +346,4 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC"
-}
\ No newline at end of file
+}
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index abe9977..eeb5a7f 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -162,6 +162,7 @@
{account_type_condition}
AND is_group = 0
AND company = %(company)s
+ AND disabled = %(disabled)s
AND (account_currency = %(currency)s or ifnull(account_currency, '') = '')
AND `{searchfield}` LIKE %(txt)s
{mcond}
@@ -175,6 +176,7 @@
dict(
account_types=filters.get("account_type"),
company=filters.get("company"),
+ disabled=filters.get("disabled", 0),
currency=company_currency,
txt="%{}%".format(txt),
offset=start,
diff --git a/erpnext/crm/doctype/opportunity/opportunity_dashboard.py b/erpnext/crm/doctype/opportunity/opportunity_dashboard.py
index d4c5e02..d3a10bc 100644
--- a/erpnext/crm/doctype/opportunity/opportunity_dashboard.py
+++ b/erpnext/crm/doctype/opportunity/opportunity_dashboard.py
@@ -2,6 +2,6 @@
return {
"fieldname": "opportunity",
"transactions": [
- {"items": ["Quotation", "Supplier Quotation"]},
+ {"items": ["Quotation", "Request for Quotation", "Supplier Quotation"]},
],
}
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js
index 7d1c7cb..37ae75a 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.js
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.js
@@ -65,9 +65,10 @@
);
}
- if (frm.doc.docstatus === 1 &&
- (flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount) && flt(frm.doc.paid_amount) != flt(frm.doc.return_amount))) {
-
+ if (
+ frm.doc.docstatus === 1
+ && (flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount) - flt(frm.doc.return_amount))
+ ) {
if (frm.doc.repay_unclaimed_amount_from_salary == 0 && frappe.model.can_create("Journal Entry")) {
frm.add_custom_button(__("Return"), function() {
frm.trigger('make_return_entry');
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js
index 8bb3457..2339350 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js
@@ -4,21 +4,21 @@
frappe.query_reports["Employee Leave Balance"] = {
"filters": [
{
- "fieldname":"from_date",
+ "fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"reqd": 1,
"default": frappe.defaults.get_default("year_start_date")
},
{
- "fieldname":"to_date",
+ "fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"reqd": 1,
"default": frappe.defaults.get_default("year_end_date")
},
{
- "fieldname":"company",
+ "fieldname": "company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
@@ -26,16 +26,29 @@
"default": frappe.defaults.get_user_default("Company")
},
{
- "fieldname":"department",
+ "fieldname": "department",
"label": __("Department"),
"fieldtype": "Link",
"options": "Department",
},
{
- "fieldname":"employee",
+ "fieldname": "employee",
"label": __("Employee"),
"fieldtype": "Link",
"options": "Employee",
+ },
+ {
+ "fieldname": "employee_status",
+ "label": __("Employee Status"),
+ "fieldtype": "Select",
+ "options": [
+ "",
+ { "value": "Active", "label": __("Active") },
+ { "value": "Inactive", "label": __("Inactive") },
+ { "value": "Suspended", "label": __("Suspended") },
+ { "value": "Left", "label": __("Left") },
+ ],
+ "default": "Active",
}
],
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
index ca352f1..1f7ade2 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
@@ -168,9 +168,8 @@
def get_conditions(filters: Filters) -> Dict:
- conditions = {
- "status": "Active",
- }
+ conditions = {}
+
if filters.get("employee"):
conditions["name"] = filters.get("employee")
@@ -180,6 +179,9 @@
if filters.get("department"):
conditions["department"] = filters.get("department")
+ if filters.get("employee_status"):
+ conditions["status"] = filters.get("employee_status")
+
return conditions
diff --git a/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py
index dc0f4d2..5354abf 100644
--- a/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py
@@ -207,3 +207,40 @@
allocation1.new_leaves_allocated - leave_application.total_leave_days
)
self.assertEqual(report[1][0].opening_balance, opening_balance)
+
+ @set_holiday_list("_Test Emp Balance Holiday List", "_Test Company")
+ def test_employee_status_filter(self):
+ frappe.get_doc(test_records[0]).insert()
+ inactive_emp = make_employee("test_emp_status@example.com", company="_Test Company")
+
+ allocation = make_allocation_record(
+ employee=inactive_emp,
+ from_date=self.year_start,
+ to_date=self.year_end,
+ leaves=5,
+ )
+
+ # set employee as inactive
+ frappe.db.set_value("Employee", inactive_emp, "status", "Inactive")
+
+ filters = frappe._dict(
+ {
+ "from_date": allocation.from_date,
+ "to_date": allocation.to_date,
+ "employee": inactive_emp,
+ "employee_status": "Active",
+ }
+ )
+ report = execute(filters)
+ self.assertEqual(len(report[1]), 0)
+
+ filters = frappe._dict(
+ {
+ "from_date": allocation.from_date,
+ "to_date": allocation.to_date,
+ "employee": inactive_emp,
+ "employee_status": "Inactive",
+ }
+ )
+ report = execute(filters)
+ self.assertEqual(len(report[1]), 1)
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
index cb05d11..26dd782 100644
--- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
@@ -30,6 +30,19 @@
label: __('Department'),
fieldtype: 'Link',
options: 'Department',
+ },
+ {
+ fieldname: "employee_status",
+ label: __("Employee Status"),
+ fieldtype: "Select",
+ options: [
+ "",
+ { "value": "Active", "label": __("Active") },
+ { "value": "Inactive", "label": __("Inactive") },
+ { "value": "Suspended", "label": __("Suspended") },
+ { "value": "Left", "label": __("Left") },
+ ],
+ default: "Active",
}
]
};
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
index 2a16dc4..82878db 100644
--- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
@@ -35,9 +35,10 @@
def get_conditions(filters):
conditions = {
- "status": "Active",
"company": filters.company,
}
+ if filters.get("employee_status"):
+ conditions.update({"status": filters.get("employee_status")})
if filters.get("department"):
conditions.update({"department": filters.get("department")})
if filters.get("employee"):
diff --git a/erpnext/hr/report/employee_leave_balance_summary/test_employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/test_employee_leave_balance_summary.py
index 34b665f..2fd74b7 100644
--- a/erpnext/hr/report/employee_leave_balance_summary/test_employee_leave_balance_summary.py
+++ b/erpnext/hr/report/employee_leave_balance_summary/test_employee_leave_balance_summary.py
@@ -37,7 +37,6 @@
frappe.set_user("Administrator")
self.employee_id = make_employee("test_emp_leave_balance@example.com", company="_Test Company")
- self.employee_id = make_employee("test_emp_leave_balance@example.com", company="_Test Company")
self.date = getdate()
self.year_start = getdate(get_year_start(self.date))
@@ -146,3 +145,37 @@
]
self.assertEqual(report[1], expected_data)
+
+ @set_holiday_list("_Test Emp Balance Holiday List", "_Test Company")
+ def test_employee_status_filter(self):
+ frappe.get_doc(test_records[0]).insert()
+
+ inactive_emp = make_employee("test_emp_status@example.com", company="_Test Company")
+ allocation = make_allocation_record(
+ employee=inactive_emp, from_date=self.year_start, to_date=self.year_end
+ )
+
+ # set employee as inactive
+ frappe.db.set_value("Employee", inactive_emp, "status", "Inactive")
+
+ filters = frappe._dict(
+ {
+ "date": allocation.from_date,
+ "company": "_Test Company",
+ "employee": inactive_emp,
+ "employee_status": "Active",
+ }
+ )
+ report = execute(filters)
+ self.assertEqual(len(report[1]), 0)
+
+ filters = frappe._dict(
+ {
+ "date": allocation.from_date,
+ "company": "_Test Company",
+ "employee": inactive_emp,
+ "employee_status": "Inactive",
+ }
+ )
+ report = execute(filters)
+ self.assertEqual(len(report[1]), 1)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 1fef240..06229bb 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -313,7 +313,6 @@
erpnext.patches.v12_0.update_production_plan_status
erpnext.patches.v13_0.healthcare_deprecation_warning
erpnext.patches.v13_0.item_naming_series_not_mandatory
-erpnext.patches.v14_0.delete_healthcare_doctypes
erpnext.patches.v13_0.update_category_in_ltds_certificate
erpnext.patches.v13_0.create_pan_field_for_india #2
erpnext.patches.v13_0.fetch_thumbnail_in_website_items
@@ -324,7 +323,6 @@
erpnext.patches.v13_0.wipe_serial_no_field_for_0_qty
erpnext.patches.v13_0.disable_ksa_print_format_for_others # 16-12-2021
erpnext.patches.v13_0.update_tax_category_for_rcm
-execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')
erpnext.patches.v14_0.set_payroll_cost_centers
erpnext.patches.v13_0.agriculture_deprecation_warning
erpnext.patches.v13_0.hospitality_deprecation_warning
@@ -333,15 +331,17 @@
erpnext.patches.v13_0.enable_provisional_accounting
erpnext.patches.v13_0.non_profit_deprecation_warning
erpnext.patches.v13_0.enable_ksa_vat_docs #1
-erpnext.patches.v14_0.delete_education_doctypes
[post_model_sync]
+execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')
erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents
erpnext.patches.v14_0.add_default_exit_questionnaire_notification_template
erpnext.patches.v14_0.delete_shopify_doctypes
+erpnext.patches.v14_0.delete_healthcare_doctypes
erpnext.patches.v14_0.delete_hub_doctypes
erpnext.patches.v14_0.delete_hospitality_doctypes # 20-01-2022
erpnext.patches.v14_0.delete_agriculture_doctypes
+erpnext.patches.v14_0.delete_education_doctypes
erpnext.patches.v14_0.delete_datev_doctypes
erpnext.patches.v14_0.rearrange_company_fields
erpnext.patches.v14_0.update_leave_notification_template
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index 84c7176..c1fe72b 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -27,7 +27,8 @@
query: "erpnext.controllers.queries.tax_account_query",
filters: {
"account_type": account_type,
- "company": doc.company
+ "company": doc.company,
+ "disabled": 0
}
}
});
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index c3812f3..05a401b 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -923,12 +923,12 @@
}
currency() {
- /* manqala 19/09/2016: let the translation date be whichever of the transaction_date or posting_date is available */
- var transaction_date = this.frm.doc.transaction_date || this.frm.doc.posting_date;
- /* end manqala */
- var me = this;
+ // The transaction date be either transaction_date (from orders) or posting_date (from invoices)
+ let transaction_date = this.frm.doc.transaction_date || this.frm.doc.posting_date;
+
+ let me = this;
this.set_dynamic_labels();
- var company_currency = this.get_company_currency();
+ let company_currency = this.get_company_currency();
// Added `ignore_price_list` to determine if document is loading after mapping from another doc
if(this.frm.doc.currency && this.frm.doc.currency !== company_currency
&& !(this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list)) {
@@ -942,7 +942,9 @@
}
});
} else {
- this.conversion_rate();
+ // company currency and doc currency is same
+ // this will prevent unnecessary conversion rate triggers
+ this.frm.set_value("conversion_rate", 1.0);
}
}
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index eded165..e8db097 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -213,8 +213,10 @@
filters.splice(index, 0, {
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
+ "fieldtype": "MultiSelectList",
+ get_data: function(txt) {
+ return frappe.db.get_link_options(dimension["document_type"], txt);
+ },
});
}
});
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 1bfce66..bc235d9 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -64,13 +64,18 @@
se = frappe.qb.DocType("Stock Entry")
se_item = frappe.qb.DocType("Stock Entry Detail")
+ if frappe.db.field_exists("Stock Entry", "is_return"):
+ qty_field = (
+ Case().when(se.is_return == 1, se_item.transfer_qty * -1).else_(se_item.transfer_qty)
+ )
+ else:
+ qty_field = se_item.transfer_qty
+
materials_transferred = (
frappe.qb.from_(se)
.from_(se_item)
.from_(po)
- .select(
- Sum(Case().when(se.is_return == 1, se_item.transfer_qty * -1).else_(se_item.transfer_qty))
- )
+ .select(Sum(qty_field))
.where(
(se.docstatus == 1)
& (se.purpose == "Send to Subcontractor")
diff --git a/erpnext/tests/test_init.py b/erpnext/tests/test_init.py
index 6fbfbf4..4d5fced 100644
--- a/erpnext/tests/test_init.py
+++ b/erpnext/tests/test_init.py
@@ -40,3 +40,8 @@
enc_name == expected_names[i],
"{enc} is not same as {exp}".format(enc=enc_name, exp=expected_names[i]),
)
+
+ def test_translation_files(self):
+ from frappe.tests.test_translate import verify_translation_files
+
+ verify_translation_files("erpnext")
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index d1c2146..ccd613d 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -5063,7 +5063,7 @@
Rejected Qty,Abgelehnt Menge,
UOM Conversion Factor,Maßeinheit-Umrechnungsfaktor,
Discount on Price List Rate (%),Rabatt auf die Preisliste (%),
-Price List Rate (Company Currency),Preisliste (Unternehmenswährung),
+Price List Rate (Company Currency),Preisliste (Unternehmenswährung),
Rate ,Preis,
Rate (Company Currency),Preis (Unternehmenswährung),
Amount (Company Currency),Betrag (Unternehmenswährung),
@@ -6517,20 +6517,20 @@
HR-EMP-,HR-EMP-,
Employment Type,Art der Beschäftigung,
Emergency Contact,Notfallkontakt,
-Emergency Contact Name,Notfall Kontaktname,
-Emergency Phone,Notruf,
+Emergency Contact Name,Name des Notfallkontakts,
+Emergency Phone,Telefonnummer des Notfallkontakts,
ERPNext User,ERPNext Benutzer,
"System User (login) ID. If set, it will become default for all HR forms.","Systembenutzer-ID (Anmeldung). Wenn gesetzt, wird sie standardmäßig für alle HR-Formulare verwendet.",
Create User Permission,Benutzerberechtigung Erstellen,
This will restrict user access to other employee records,Dies schränkt den Benutzerzugriff auf andere Mitarbeiterdatensätze ein,
Joining Details,Details des Beitritts,
Offer Date,Angebotsdatum,
-Confirmation Date,Datum bestätigen,
+Confirmation Date,Bestätigungsdatum,
Contract End Date,Vertragsende,
-Notice (days),Meldung(s)(-Tage),
+Notice (days),Kündigungsfrist (Tage),
Date Of Retirement,Zeitpunkt der Pensionierung,
Department and Grade,Abteilung und Klasse,
-Reports to,Berichte an,
+Reports to,Vorgesetzter,
Attendance and Leave Details,Anwesenheits- und Urlaubsdetails,
Leave Policy,Urlaubsrichtlinie,
Attendance Device ID (Biometric/RF tag ID),Anwesenheitsgeräte-ID (biometrische / RF-Tag-ID),
@@ -6553,8 +6553,8 @@
Provide Email Address registered in company,Geben Sie E-Mail-Adresse in Unternehmen registriert,
Current Address Is,Aktuelle Adresse ist,
Current Address,Aktuelle Adresse,
-Personal Bio,Persönliches Bio,
-Bio / Cover Letter,Bio / Anschreiben,
+Personal Bio,Lebenslauf,
+Bio / Cover Letter,Lebenslauf / Anschreiben,
Short biography for website and other publications.,Kurzbiographie für die Webseite und andere Publikationen.,
Passport Number,Passnummer,
Date of Issue,Ausstellungsdatum,
@@ -9542,7 +9542,7 @@
Please select a Supplier,Bitte wählen Sie einen Lieferanten aus,
Supplier Lead Time (days),Vorlaufzeit des Lieferanten (Tage),
"Home, Work, etc.","Zuhause, Arbeit usw.",
-Exit Interview Held On,Beenden Sie das Interview,
+Exit Interview Held On,Entlassungsgespräch am,
Condition and formula,Zustand und Formel,
Sets 'Target Warehouse' in each row of the Items table.,Legt 'Ziellager' in jeder Zeile der Elementtabelle fest.,
Sets 'Source Warehouse' in each row of the Items table.,Legt 'Source Warehouse' in jeder Zeile der Items-Tabelle fest.,