From 3d6ed4ebdea5db3935dfcaeaa9ad8710ca2f9b1b Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 8 Feb 2022 17:36:28 +0530 Subject: [PATCH 01/10] fix: Fetch valuation rate (cherry picked from commit df71907be453a481a43d2c62a5c076602ab8af07) --- .../doctype/asset_repair/asset_repair.js | 17 ++++++++++ .../doctype/asset_repair/asset_repair.py | 33 +++++++++++++++++++ .../asset_repair_consumed_item.json | 3 +- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.js b/erpnext/assets/doctype/asset_repair/asset_repair.js index d554d52a71..7bd3a7246d 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.js +++ b/erpnext/assets/doctype/asset_repair/asset_repair.js @@ -68,6 +68,23 @@ frappe.ui.form.on('Asset Repair', { }); frappe.ui.form.on('Asset Repair Consumed Item', { + item_code: function(frm, cdt, cdn) { + var row = locals[cdt][cdn]; + + frappe.call ({ + method: "erpnext.assets.doctype.asset_repair.asset_repair.get_valuation_rate", + args: { + "item_code": row.item_code, + "warehouse": frm.doc.warehouse + }, + callback: function(r) { + if(r.message) { + frappe.model.set_value(cdt, cdn, 'valuation_rate', r.message[0]); + } + } + }); + }, + consumed_quantity: function(frm, cdt, cdn) { var row = locals[cdt][cdn]; frappe.model.set_value(cdt, cdn, 'total_value', row.consumed_quantity * row.valuation_rate); diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 36848e9f15..86a63fd1bc 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -256,3 +256,36 @@ class AssetRepair(AccountsController): def get_downtime(failure_date, completion_date): downtime = time_diff_in_hours(completion_date, failure_date) return round(downtime, 2) + +@frappe.whitelist() +def get_valuation_rate(item_code, warehouse): + last_valuation_rate = frappe.get_all( + "Stock Ledger Entry", + filters = { + "item_code": item_code, + "warehouse": warehouse, + "valuation_rate": [">=", 0], + "docstatus": ["<", 2] + }, + pluck = "valuation_rate", + order_by = "posting_date desc, posting_time desc, name desc" + ) + + if last_valuation_rate: + return last_valuation_rate + else: + valuation_rate = frappe.db.get_value("Item", item_code, "valuation_rate") + + if not valuation_rate: + # try Item Standard rate + valuation_rate = frappe.db.get_value("Item", item_code, "standard_rate") + + if not valuation_rate: + # try in price list + valuation_rate = frappe.db.get_value( + "Item Price", + dict(item_code=item_code, buying=1), + "price_list_rate" + ) + + return valuation_rate diff --git a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json index f63add1235..3c850c8265 100644 --- a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json +++ b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json @@ -13,7 +13,6 @@ ], "fields": [ { - "fetch_from": "item.valuation_rate", "fieldname": "valuation_rate", "fieldtype": "Currency", "in_list_view": 1, @@ -49,7 +48,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-11-11 18:23:00.492483", + "modified": "2022-02-08 17:37:20.028290", "modified_by": "Administrator", "module": "Assets", "name": "Asset Repair Consumed Item", From 5d3b65b9447d241b391eb73fd008007621ceb569 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 8 Feb 2022 17:59:06 +0530 Subject: [PATCH 02/10] fix: Pass value instead of array (cherry picked from commit e1a9b61103e27099696ae4b186a6575b28c16b06) --- erpnext/assets/doctype/asset_repair/asset_repair.js | 2 +- erpnext/assets/doctype/asset_repair/asset_repair.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.js b/erpnext/assets/doctype/asset_repair/asset_repair.js index 7bd3a7246d..18454fe367 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.js +++ b/erpnext/assets/doctype/asset_repair/asset_repair.js @@ -79,7 +79,7 @@ frappe.ui.form.on('Asset Repair Consumed Item', { }, callback: function(r) { if(r.message) { - frappe.model.set_value(cdt, cdn, 'valuation_rate', r.message[0]); + frappe.model.set_value(cdt, cdn, 'valuation_rate', r.message); } } }); diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 86a63fd1bc..d5e3d3c811 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -272,7 +272,7 @@ def get_valuation_rate(item_code, warehouse): ) if last_valuation_rate: - return last_valuation_rate + return last_valuation_rate[0] else: valuation_rate = frappe.db.get_value("Item", item_code, "valuation_rate") From 414c3b8dd2507318f78b42eea507a2eb1a2e80bb Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 21 Feb 2022 13:58:01 +0530 Subject: [PATCH 03/10] fix: remove redundant method (cherry picked from commit 57d5a027fb929803ffd62463da3e5b4611b17ff4) --- .../doctype/asset_repair/asset_repair.js | 21 +++++++----- .../doctype/asset_repair/asset_repair.py | 33 ------------------- 2 files changed, 13 insertions(+), 41 deletions(-) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.js b/erpnext/assets/doctype/asset_repair/asset_repair.js index 18454fe367..1e4c4e082d 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.js +++ b/erpnext/assets/doctype/asset_repair/asset_repair.js @@ -69,18 +69,23 @@ frappe.ui.form.on('Asset Repair', { frappe.ui.form.on('Asset Repair Consumed Item', { item_code: function(frm, cdt, cdn) { - var row = locals[cdt][cdn]; + var item = locals[cdt][cdn]; - frappe.call ({ - method: "erpnext.assets.doctype.asset_repair.asset_repair.get_valuation_rate", + let item_args = { + 'item_code': item.item_code, + 'warehouse': frm.doc.warehouse, + 'qty': item.consumed_quantity, + 'serial_no': item.serial_no, + 'company': frm.doc.company + } + + frappe.call({ + method: 'erpnext.stock.utils.get_incoming_rate', args: { - "item_code": row.item_code, - "warehouse": frm.doc.warehouse + args: item_args }, callback: function(r) { - if(r.message) { - frappe.model.set_value(cdt, cdn, 'valuation_rate', r.message); - } + frappe.model.set_value(cdt, cdn, 'valuation_rate', r.message); } }); }, diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index d5e3d3c811..36848e9f15 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -256,36 +256,3 @@ class AssetRepair(AccountsController): def get_downtime(failure_date, completion_date): downtime = time_diff_in_hours(completion_date, failure_date) return round(downtime, 2) - -@frappe.whitelist() -def get_valuation_rate(item_code, warehouse): - last_valuation_rate = frappe.get_all( - "Stock Ledger Entry", - filters = { - "item_code": item_code, - "warehouse": warehouse, - "valuation_rate": [">=", 0], - "docstatus": ["<", 2] - }, - pluck = "valuation_rate", - order_by = "posting_date desc, posting_time desc, name desc" - ) - - if last_valuation_rate: - return last_valuation_rate[0] - else: - valuation_rate = frappe.db.get_value("Item", item_code, "valuation_rate") - - if not valuation_rate: - # try Item Standard rate - valuation_rate = frappe.db.get_value("Item", item_code, "standard_rate") - - if not valuation_rate: - # try in price list - valuation_rate = frappe.db.get_value( - "Item Price", - dict(item_code=item_code, buying=1), - "price_list_rate" - ) - - return valuation_rate From 3dcc3a349ee63d04840fc7432a17a16d83d957fe Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 21 Feb 2022 14:01:12 +0530 Subject: [PATCH 04/10] fix: cannot edit valutaion_rate in asset repair (cherry picked from commit 2aba6c38b36e5fce373800eb129a93eb010c691f) --- .../asset_repair_consumed_item/asset_repair_consumed_item.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json index 3c850c8265..4685a09db6 100644 --- a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json +++ b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json @@ -16,8 +16,7 @@ "fieldname": "valuation_rate", "fieldtype": "Currency", "in_list_view": 1, - "label": "Valuation Rate", - "read_only": 1 + "label": "Valuation Rate" }, { "fieldname": "consumed_quantity", From 8743e394698b3d136a19507042556971ed2234a1 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 21 Feb 2022 14:26:21 +0530 Subject: [PATCH 05/10] fix: sider (cherry picked from commit bc28755978c17d7e85cdc5ffd4a45a629183e2c8) --- erpnext/assets/doctype/asset_repair/asset_repair.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.js b/erpnext/assets/doctype/asset_repair/asset_repair.js index 1e4c4e082d..3fe6b2d0d5 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.js +++ b/erpnext/assets/doctype/asset_repair/asset_repair.js @@ -77,7 +77,7 @@ frappe.ui.form.on('Asset Repair Consumed Item', { 'qty': item.consumed_quantity, 'serial_no': item.serial_no, 'company': frm.doc.company - } + }; frappe.call({ method: 'erpnext.stock.utils.get_incoming_rate', From e2c144e9e3e6bd71f6040dc81e698ffe2f0f37d2 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 6 Mar 2022 19:05:02 +0530 Subject: [PATCH 06/10] fix: Item-wise sales history report --- .../item_wise_sales_history.py | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py index 4a245e1f77..56e1eb57b8 100644 --- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py +++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py @@ -156,24 +156,24 @@ def get_data(filters): customer_record = customer_details.get(record.customer) item_record = item_details.get(record.item_code) row = { - "item_code": record.item_code, - "item_name": item_record.item_name, - "item_group": item_record.item_group, - "description": record.description, - "quantity": record.qty, - "uom": record.uom, - "rate": record.base_rate, - "amount": record.base_amount, - "sales_order": record.name, - "transaction_date": record.transaction_date, - "customer": record.customer, - "customer_name": customer_record.customer_name, - "customer_group": customer_record.customer_group, - "territory": record.territory, - "project": record.project, - "delivered_quantity": flt(record.delivered_qty), - "billed_amount": flt(record.billed_amt), - "company": record.company + "item_code": record.get('item_code'), + "item_name": item_record.get('item_name'), + "item_group": item_record.get('item_group'), + "description": record.get('description'), + "quantity": record.get('qty'), + "uom": record.get('uom'), + "rate": record.get('base_rate'), + "amount": record.get('base_amount'), + "sales_order": record.get('name'), + "transaction_date": record.get('transaction_date'), + "customer": record.get('customer'), + "customer_name": customer_record.get('customer_name'), + "customer_group": customer_record.get('customer_group'), + "territory": record.get('territory'), + "project": record.get('project'), + "delivered_quantity": flt(record.get('delivered_qty')), + "billed_amount": flt(record.get('billed_amt')), + "company": record.get('company') } data.append(row) From 517fbf1d1f0a7d44e817b3f22ae30142e7bdf4c8 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 7 Mar 2022 22:31:42 +0530 Subject: [PATCH 07/10] fix: Ambigous column in picklist query --- erpnext/stock/doctype/pick_list/pick_list.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 5484a117dd..86f24c2427 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -9,6 +9,7 @@ from frappe import _ from frappe.model.document import Document from frappe.model.mapper import map_child_doc from frappe.utils import cint, floor, flt, today +from six import iteritems from erpnext.selling.doctype.sales_order.sales_order import ( make_delivery_note as create_delivery_note_from_sales_order, @@ -245,7 +246,7 @@ def get_available_item_locations_for_serialized_item(item_code, from_warehouses, warehouse_serial_nos_map.setdefault(warehouse, []).append(serial_no) locations = [] - for warehouse, serial_nos in warehouse_serial_nos_map.items(): + for warehouse, serial_nos in iteritems(warehouse_serial_nos_map): locations.append({ 'qty': len(serial_nos), 'warehouse': warehouse, @@ -272,9 +273,9 @@ def get_available_item_locations_for_batched_item(item_code, from_warehouses, re and IFNULL(batch.`expiry_date`, '2200-01-01') > %(today)s {warehouse_condition} GROUP BY - `warehouse`, - `batch_no`, - `item_code` + sle.`warehouse`, + sle.`batch_no`, + sle.`item_code` HAVING `qty` > 0 ORDER BY IFNULL(batch.`expiry_date`, '2200-01-01'), batch.`creation` """.format(warehouse_condition=warehouse_condition), { #nosec From d9d4c2ce792304a528a7b8a27d50259a04bdd7ca Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 8 Mar 2022 07:56:20 +0530 Subject: [PATCH 08/10] fix: Remove unintentional changes --- erpnext/stock/doctype/pick_list/pick_list.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 86f24c2427..b2eaecb586 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -9,7 +9,6 @@ from frappe import _ from frappe.model.document import Document from frappe.model.mapper import map_child_doc from frappe.utils import cint, floor, flt, today -from six import iteritems from erpnext.selling.doctype.sales_order.sales_order import ( make_delivery_note as create_delivery_note_from_sales_order, @@ -246,7 +245,7 @@ def get_available_item_locations_for_serialized_item(item_code, from_warehouses, warehouse_serial_nos_map.setdefault(warehouse, []).append(serial_no) locations = [] - for warehouse, serial_nos in iteritems(warehouse_serial_nos_map): + for warehouse, serial_nos in warehouse_serial_nos_map.items(): locations.append({ 'qty': len(serial_nos), 'warehouse': warehouse, From ce27cdb121e523c00ee0846a9715d72e3efed694 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Tue, 8 Mar 2022 23:07:23 +0530 Subject: [PATCH 09/10] test: Fix flaky tests (#30107) --- erpnext/hr/doctype/attendance/test_attendance.py | 15 ++++++++------- .../leave_application/test_leave_application.py | 2 +- .../test_project_profitability.py | 8 ++------ 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/erpnext/hr/doctype/attendance/test_attendance.py b/erpnext/hr/doctype/attendance/test_attendance.py index 118cc987ef..c74967d213 100644 --- a/erpnext/hr/doctype/attendance/test_attendance.py +++ b/erpnext/hr/doctype/attendance/test_attendance.py @@ -1,10 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors # See license.txt -import unittest - import frappe -from frappe.utils import add_days, get_first_day, getdate, nowdate +from frappe.tests.utils import FrappeTestCase +from frappe.utils import add_days, get_first_day, getdate, now_datetime, nowdate from erpnext.hr.doctype.attendance.attendance import ( get_month_map, @@ -16,7 +15,7 @@ from erpnext.hr.doctype.leave_application.test_leave_application import get_firs test_records = frappe.get_test_records('Attendance') -class TestAttendance(unittest.TestCase): +class TestAttendance(FrappeTestCase): def test_mark_absent(self): employee = make_employee("test_mark_absent@example.com") date = nowdate() @@ -74,12 +73,14 @@ class TestAttendance(unittest.TestCase): self.assertNotIn(first_sunday, unmarked_days) def test_unmarked_days_as_per_joining_and_relieving_dates(self): - first_day = get_first_day(getdate()) + now = now_datetime() + previous_month = now.month - 1 + first_day = now.replace(day=1).replace(month=previous_month).date() doj = add_days(first_day, 1) relieving_date = add_days(first_day, 5) employee = make_employee('test_unmarked_days_as_per_doj@example.com', date_of_joining=doj, - date_of_relieving=relieving_date) + relieving_date=relieving_date) frappe.db.delete('Attendance', {'employee': employee}) attendance_date = add_days(first_day, 2) @@ -104,4 +105,4 @@ def get_month_name(date): month_number = date.month for month, number in get_month_map().items(): if number == month_number: - return month \ No newline at end of file + return month diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index 6d27f4abef..7b3aa49729 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -792,4 +792,4 @@ def get_first_sunday(holiday_list): order by holiday_date """, (holiday_list, month_start_date, month_end_date))[0][0] - return first_sunday \ No newline at end of file + return first_sunday diff --git a/erpnext/projects/report/project_profitability/test_project_profitability.py b/erpnext/projects/report/project_profitability/test_project_profitability.py index 1eb3d0d717..3ca28c1ce0 100644 --- a/erpnext/projects/report/project_profitability/test_project_profitability.py +++ b/erpnext/projects/report/project_profitability/test_project_profitability.py @@ -1,6 +1,5 @@ -import unittest - import frappe +from frappe.tests.utils import FrappeTestCase from frappe.utils import add_days, getdate from erpnext.hr.doctype.employee.test_employee import make_employee @@ -12,7 +11,7 @@ from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_ from erpnext.projects.report.project_profitability.project_profitability import execute -class TestProjectProfitability(unittest.TestCase): +class TestProjectProfitability(FrappeTestCase): def setUp(self): frappe.db.sql('delete from `tabTimesheet`') emp = make_employee('test_employee_9@salary.com', company='_Test Company') @@ -67,6 +66,3 @@ class TestProjectProfitability(unittest.TestCase): fractional_cost = self.salary_slip.base_gross_pay * utilization self.assertEqual(fractional_cost, row.fractional_cost) - - def tearDown(self): - frappe.db.rollback() From 096092f1731d5a8025462317384c7d19772f024c Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 8 Mar 2022 23:16:40 +0530 Subject: [PATCH 10/10] fix: leave allocation records query (#30118) --- .../leave_application/leave_application.py | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 70250f5bcf..ef5f4bcb0f 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -4,6 +4,7 @@ import frappe from frappe import _ +from frappe.query_builder.functions import Max, Min, Sum from frappe.utils import ( add_days, cint, @@ -567,28 +568,39 @@ def get_leave_balance_on(employee, leave_type, date, to_date=None, consider_all_ return get_remaining_leaves(allocation, leaves_taken, date, expiry) def get_leave_allocation_records(employee, date, leave_type=None): - ''' returns the total allocated leaves and carry forwarded leaves based on ledger entries ''' + """Returns the total allocated leaves and carry forwarded leaves based on ledger entries""" + Ledger = frappe.qb.DocType("Leave Ledger Entry") - conditions = ("and leave_type='%s'" % leave_type) if leave_type else "" - allocation_details = frappe.db.sql(""" - SELECT - SUM(CASE WHEN is_carry_forward = 1 THEN leaves ELSE 0 END) as cf_leaves, - SUM(CASE WHEN is_carry_forward = 0 THEN leaves ELSE 0 END) as new_leaves, - MIN(from_date) as from_date, - MAX(to_date) as to_date, - leave_type - FROM `tabLeave Ledger Entry` - WHERE - from_date <= %(date)s - AND to_date >= %(date)s - AND docstatus=1 - AND transaction_type="Leave Allocation" - AND employee=%(employee)s - AND is_expired=0 - AND is_lwp=0 - {0} - GROUP BY employee, leave_type - """.format(conditions), dict(date=date, employee=employee), as_dict=1) #nosec + cf_leave_case = frappe.qb.terms.Case().when(Ledger.is_carry_forward == "1", Ledger.leaves).else_(0) + sum_cf_leaves = Sum(cf_leave_case).as_("cf_leaves") + + new_leaves_case = frappe.qb.terms.Case().when(Ledger.is_carry_forward == "0", Ledger.leaves).else_(0) + sum_new_leaves = Sum(new_leaves_case).as_("new_leaves") + + query = ( + frappe.qb.from_(Ledger) + .select( + sum_cf_leaves, + sum_new_leaves, + Min(Ledger.from_date).as_("from_date"), + Max(Ledger.to_date).as_("to_date"), + Ledger.leave_type + ).where( + (Ledger.from_date <= date) + & (Ledger.to_date >= date) + & (Ledger.docstatus == 1) + & (Ledger.transaction_type == "Leave Allocation") + & (Ledger.employee == employee) + & (Ledger.is_expired == 0) + & (Ledger.is_lwp == 0) + ) + ) + + if leave_type: + query = query.where((Ledger.leave_type == leave_type)) + query = query.groupby(Ledger.employee, Ledger.leave_type) + + allocation_details = query.run(as_dict=True) allocated_leaves = frappe._dict() for d in allocation_details: