From 03db85f3e7e98db5021a5c47ca552544d31bbf46 Mon Sep 17 00:00:00 2001 From: 0Pranav Date: Mon, 16 Dec 2019 16:54:03 +0530 Subject: [PATCH 001/105] fix: replace sql query by orm in delete_communications and added tests --- .../company/delete_company_transactions.py | 12 +++-- erpnext/setup/doctype/company/test_company.py | 50 +++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py index 637e65578a1..3052191943c 100644 --- a/erpnext/setup/doctype/company/delete_company_transactions.py +++ b/erpnext/setup/doctype/company/delete_company_transactions.py @@ -106,7 +106,11 @@ def delete_lead_addresses(company_name): frappe.db.sql("""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(leads=",".join(leads))) def delete_communications(doctype, company_name, company_fieldname): - frappe.db.sql(""" - DELETE FROM `tabCommunication` WHERE reference_doctype = %s AND - EXISTS (SELECT name FROM `tab{0}` WHERE {1} = %s AND `tabCommunication`.reference_name = name) - """.format(doctype, company_fieldname), (doctype, company_name)) + + refrence_docs = frappe.get_all(doctype, filters={company_fieldname:company_name}) + reference_doctype_names = [r.name for r in refrence_docs] + + communications = frappe.get_all("Communication", filters={"reference_doctype":doctype,"reference_name":["in",reference_doctype_names]}) + communication_names = [c.name for c in communications] + + frappe.delete_doc("Communication",communication_names) diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py index 8d9c23a37da..524f3eb5b17 100644 --- a/erpnext/setup/doctype/company/test_company.py +++ b/erpnext/setup/doctype/company/test_company.py @@ -88,6 +88,56 @@ class TestCompany(unittest.TestCase): self.delete_mode_of_payment(template) frappe.delete_doc("Company", template) + def test_delete_communication(self): + from erpnext.setup.doctype.company.delete_company_transactions import delete_communications + company = create_child_company() + lead = create_test_lead_in_company(company) + communication = create_company_communication("Lead", lead) + delete_communications("Lead", "Test Company", "company") + self.assertFalse(frappe.db.exists("Communcation", communication)) + self.assertFalse(frappe.db.exists({"doctype":"Comunication Link", "link_name": communication})) + def delete_mode_of_payment(self, company): frappe.db.sql(""" delete from `tabMode of Payment Account` where company =%s """, (company)) + +def create_company_communication(doctype, docname): + comm = frappe.get_doc({ + "doctype": "Communication", + "communication_type": "Communication", + "content": "Deduplication of Links", + "communication_medium": "Email", + "reference_doctype":doctype, + "reference_name":docname + }) + comm.insert() + +def create_child_company(): + child_company = frappe.db.exists("Company", "Test Company") + if not child_company: + child_company = frappe.get_doc({ + "doctype":"Company", + "company_name":"Test Company", + "abbr":"test_company", + "default_currency":"INR" + }) + child_company.insert() + else: + child_company = frappe.get_doc("Company", child_company) + + return child_company.name + +def create_test_lead_in_company(company): + lead = frappe.db.exists("Lead", "Test Lead in new company") + if not lead: + lead = frappe.get_doc({ + "doctype": "Lead", + "lead_name": "Test Lead in new company", + "scompany": company + }) + lead.insert() + else: + lead = frappe.get_doc("Lead", lead) + lead.company = company + lead.save() + return lead.name From ce6923ecb6a4468298962d3f16293faaf654b51a Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 16 Dec 2019 16:56:57 +0530 Subject: [PATCH 002/105] fix: compensatory leave request creation --- .../compensatory_leave_request.js | 2 +- .../compensatory_leave_request.py | 73 ++++---- .../test_compensatory_leave_request.py | 157 ++++++++++++++---- 3 files changed, 167 insertions(+), 65 deletions(-) diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js index 1baa1e04e32..57838423d71 100644 --- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js +++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js @@ -19,4 +19,4 @@ frappe.ui.form.on('Compensatory Leave Request', { frm.set_df_property('half_day_date', 'reqd', false); } } -}); +}); \ No newline at end of file diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py index bc4a1b4034b..7a9727f18c4 100644 --- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py +++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py @@ -5,9 +5,10 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import date_diff, add_days, getdate +from frappe.utils import date_diff, add_days, getdate, cint from frappe.model.document import Document -from erpnext.hr.utils import validate_dates, validate_overlap, get_leave_period, get_holidays_for_employee +from erpnext.hr.utils import validate_dates, validate_overlap, get_leave_period, \ + get_holidays_for_employee, create_additional_leave_ledger_entry class CompensatoryLeaveRequest(Document): @@ -25,16 +26,14 @@ class CompensatoryLeaveRequest(Document): frappe.throw(_("Leave Type is madatory")) def validate_attendance(self): - query = """select attendance_date, status - from `tabAttendance` where - attendance_date between %(work_from_date)s and %(work_end_date)s - and docstatus=1 and status = 'Present' and employee=%(employee)s""" + attendance = frappe.get_all('Attendance', + filters={ + 'attendance_date': ['between', (self.work_from_date, self.work_end_date)], + 'status': 'Present', + 'docstatus': 1, + 'employee': self.employee + }, fields=['attendance_date', 'status']) - attendance = frappe.db.sql(query, { - "work_from_date": self.work_from_date, - "work_end_date": self.work_end_date, - "employee": self.employee - }, as_dict=True) if len(attendance) < date_diff(self.work_end_date, self.work_from_date) + 1: frappe.throw(_("You are not present all day(s) between compensatory leave request days")) @@ -50,13 +49,19 @@ class CompensatoryLeaveRequest(Document): date_difference -= 0.5 leave_period = get_leave_period(self.work_from_date, self.work_end_date, company) if leave_period: - leave_allocation = self.exists_allocation_for_period(leave_period) + leave_allocation = self.get_existing_allocation_for_period(leave_period) if leave_allocation: leave_allocation.new_leaves_allocated += date_difference - leave_allocation.submit() + leave_allocation.validate() + leave_allocation.db_set("new_leaves_allocated", leave_allocation.total_leaves_allocated) + leave_allocation.db_set("total_leaves_allocated", leave_allocation.total_leaves_allocated) + + # generate additional ledger entry for the new compensatory leaves off + create_additional_leave_ledger_entry(leave_allocation, date_difference, add_days(self.work_end_date, 1)) + else: leave_allocation = self.create_leave_allocation(leave_period, date_difference) - self.db_set("leave_allocation", leave_allocation.name) + self.leave_allocation=leave_allocation.name else: frappe.throw(_("There is no leave period in between {0} and {1}").format(self.work_from_date, self.work_end_date)) @@ -68,11 +73,16 @@ class CompensatoryLeaveRequest(Document): leave_allocation = frappe.get_doc("Leave Allocation", self.leave_allocation) if leave_allocation: leave_allocation.new_leaves_allocated -= date_difference - if leave_allocation.total_leaves_allocated - date_difference <= 0: - leave_allocation.total_leaves_allocated = 0 - leave_allocation.submit() + if leave_allocation.new_leaves_allocated - date_difference <= 0: + leave_allocation.new_leaves_allocated = 0 + leave_allocation.validate() + leave_allocation.db_set("new_leaves_allocated", leave_allocation.total_leaves_allocated) + leave_allocation.db_set("total_leaves_allocated", leave_allocation.total_leaves_allocated) - def exists_allocation_for_period(self, leave_period): + # create reverse entry on cancelation + create_additional_leave_ledger_entry(leave_allocation, date_difference * -1, add_days(self.work_end_date, 1)) + + def get_existing_allocation_for_period(self, leave_period): leave_allocation = frappe.db.sql(""" select name from `tabLeave Allocation` @@ -95,17 +105,18 @@ class CompensatoryLeaveRequest(Document): def create_leave_allocation(self, leave_period, date_difference): is_carry_forward = frappe.db.get_value("Leave Type", self.leave_type, "is_carry_forward") - allocation = frappe.new_doc("Leave Allocation") - allocation.employee = self.employee - allocation.employee_name = self.employee_name - allocation.leave_type = self.leave_type - allocation.from_date = add_days(self.work_end_date, 1) - allocation.to_date = leave_period[0].to_date - allocation.new_leaves_allocated = date_difference - allocation.total_leaves_allocated = date_difference - allocation.description = self.reason - if is_carry_forward == 1: - allocation.carry_forward = True - allocation.save(ignore_permissions = True) + allocation = frappe.get_doc(dict( + doctype="Leave Allocation", + employee=self.employee, + employee_name=self.employee_name, + leave_type=self.leave_type, + from_date=add_days(self.work_end_date, 1), + to_date=leave_period[0].to_date, + carry_forward=cint(is_carry_forward), + new_leaves_allocated=date_difference, + total_leaves_allocated=date_difference, + description=self.reason + )) + allocation.insert(ignore_permissions=True) allocation.submit() - return allocation + return allocation \ No newline at end of file diff --git a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py b/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py index f2ca1f4f5f0..1615ab30f1d 100644 --- a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py +++ b/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py @@ -5,37 +5,128 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import today, add_months, add_days +from erpnext.hr.doctype.attendance_request.test_attendance_request import get_employee +from erpnext.hr.doctype.leave_period.test_leave_period import create_leave_period +from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on -# class TestCompensatoryLeaveRequest(unittest.TestCase): -# def get_compensatory_leave_request(self): -# return frappe.get_doc('Compensatory Leave Request', dict( -# employee = employee, -# work_from_date = today, -# work_to_date = today, -# reason = 'test' -# )).insert() -# -# def test_creation_of_leave_allocation(self): -# employee = get_employee() -# today = get_today() -# -# compensatory_leave_request = self.get_compensatory_leave_request(today) -# -# before = get_leave_balance(employee, compensatory_leave_request.leave_type) -# -# compensatory_leave_request.submit() -# -# self.assertEqual(get_leave_balance(employee, compensatory_leave_request.leave_type), before + 1) -# -# def test_max_compensatory_leave(self): -# employee = get_employee() -# today = get_today() -# -# compensatory_leave_request = self.get_compensatory_leave_request() -# -# frappe.db.set_value('Leave Type', compensatory_leave_request.leave_type, 'max_leaves_allowed', 0) -# -# self.assertRaises(MaxLeavesLimitCrossed, compensatory_leave_request.submit) -# -# frappe.db.set_value('Leave Type', compensatory_leave_request.leave_type, 'max_leaves_allowed', 10) -# +class TestCompensatoryLeaveRequest(unittest.TestCase): + def setUp(self): + frappe.db.sql(''' delete from `tabCompensatory Leave Request`''') + frappe.db.sql(''' delete from `tabLeave Ledger Entry`''') + frappe.db.sql(''' delete from `tabLeave Allocation`''') + frappe.db.sql(''' delete from `tabAttendance` where attendance_date in {0} '''.format((today(), add_days(today(), -1)))) #nosec + create_leave_period(add_months(today(), -3), add_months(today(), 3), "_Test Company") + create_holiday_list() + + employee = get_employee() + employee.holiday_list = "_Test Compensatory Leave" + employee.save() + + def test_leave_balance_on_submit(self): + ''' check creation of leave allocation on submission of compensatory leave request ''' + employee = get_employee() + mark_attendance(employee) + compensatory_leave_request = get_compensatory_leave_request(employee.name) + + before = get_leave_balance_on(employee.name, compensatory_leave_request.leave_type, today()) + compensatory_leave_request.submit() + + self.assertEqual(get_leave_balance_on(employee.name, compensatory_leave_request.leave_type, add_days(today(), 1)), before + 1) + + def test_leave_allocation_update_on_submit(self): + employee = get_employee() + mark_attendance(employee, date=add_days(today(), -1)) + compensatory_leave_request = get_compensatory_leave_request(employee.name, leave_date=add_days(today(), -1)) + compensatory_leave_request.submit() + + # leave allocation creation on submit + leaves_allocated = frappe.db.get_value('Leave Allocation', { + 'name': compensatory_leave_request.leave_allocation + }, ['total_leaves_allocated']) + self.assertEqual(leaves_allocated, 1) + + mark_attendance(employee) + compensatory_leave_request = get_compensatory_leave_request(employee.name) + compensatory_leave_request.submit() + + # leave allocation updates on submission of second compensatory leave request + leaves_allocated = frappe.db.get_value('Leave Allocation', { + 'name': compensatory_leave_request.leave_allocation + }, ['total_leaves_allocated']) + self.assertEqual(leaves_allocated, 2) + + def test_creation_of_leave_ledger_entry_on_submit(self): + ''' check creation of leave ledger entry on submission of leave request ''' + employee = get_employee() + mark_attendance(employee) + compensatory_leave_request = get_compensatory_leave_request(employee.name) + compensatory_leave_request.submit() + + filters = dict(transaction_name=compensatory_leave_request.leave_allocation) + leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=filters) + + self.assertEquals(len(leave_ledger_entry), 1) + self.assertEquals(leave_ledger_entry[0].employee, compensatory_leave_request.employee) + self.assertEquals(leave_ledger_entry[0].leave_type, compensatory_leave_request.leave_type) + self.assertEquals(leave_ledger_entry[0].leaves, 1) + + # check reverse leave ledger entry on cancellation + compensatory_leave_request.cancel() + leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=filters, order_by = 'creation desc') + + self.assertEquals(len(leave_ledger_entry), 2) + self.assertEquals(leave_ledger_entry[0].employee, compensatory_leave_request.employee) + self.assertEquals(leave_ledger_entry[0].leave_type, compensatory_leave_request.leave_type) + self.assertEquals(leave_ledger_entry[0].leaves, -1) + +def get_compensatory_leave_request(employee, leave_date=today()): + prev_comp_leave_req = frappe.db.get_value('Compensatory Leave Request', + dict(leave_type='Compensatory Off', + work_from_date=leave_date, + work_end_date=leave_date, + employee=employee), 'name') + if prev_comp_leave_req: + return frappe.get_doc('Compensatory Leave Request', prev_comp_leave_req) + + return frappe.get_doc(dict( + doctype='Compensatory Leave Request', + employee=employee, + leave_type='Compensatory Off', + work_from_date=leave_date, + work_end_date=leave_date, + reason='test' + )).insert() + +def mark_attendance(employee, date=today(), status='Present'): + if not frappe.db.exists(dict(doctype='Attendance', employee=employee.name, attendance_date=date, status='Present')): + attendance = frappe.get_doc({ + "doctype": "Attendance", + "employee": employee.name, + "attendance_date": date, + "status": status + }) + attendance.save() + attendance.submit() + +def create_holiday_list(): + if frappe.db.exists("Holiday List", "_Test Compensatory Leave"): + return + + holiday_list = frappe.get_doc({ + "doctype": "Holiday List", + "from_date": add_months(today(), -3), + "to_date": add_months(today(), 3), + "holidays": [ + { + "description": "Test Holiday", + "holiday_date": today() + }, + { + "description": "Test Holiday 1", + "holiday_date": add_days(today(), -1) + } + ], + "holiday_list_name": "_Test Compensatory Leave" + }) + holiday_list.save() \ No newline at end of file From 215274719e2715b6bc2fae82811575cd8d7aecf4 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Mon, 16 Dec 2019 17:33:44 +0100 Subject: [PATCH 003/105] fix(regional): PY3 compatibility --- erpnext/regional/report/datev/datev.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index ee8735fb1ff..589165173ac 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -10,7 +10,9 @@ Provide a report and downloadable CSV according to the German DATEV format. from __future__ import unicode_literals import datetime import json +import six from six import string_types + import frappe from frappe import _ import pandas as pd @@ -158,7 +160,7 @@ def get_gl_entries(filters, as_dict): where gl.company = %(company)s and DATE(gl.posting_date) >= %(from_date)s and DATE(gl.posting_date) <= %(to_date)s - order by 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict) + order by 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1) return gl_entries @@ -404,7 +406,8 @@ def get_datev_csv(data, filters): header = ';'.join(header).encode('latin_1') data = result.to_csv( - sep=b';', + # Reason for str(';'): https://github.com/pandas-dev/pandas/issues/6035 + sep=str(';'), # European decimal seperator decimal=',', # Windows "ANSI" encoding @@ -412,13 +415,16 @@ def get_datev_csv(data, filters): # format date as DDMM date_format='%d%m', # Windows line terminator - line_terminator=b'\r\n', + line_terminator='\r\n', # Do not number rows index=False, # Use all columns defined above columns=columns ) + if not six.PY2: + data = data.encode('latin_1') + return header + b'\r\n' + data @frappe.whitelist() From b4d9b80fed9ee7dc38a7f45d77f4b20e963f147c Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 17 Dec 2019 12:25:25 +0530 Subject: [PATCH 004/105] fix: allow creation of additional leave ledger entry --- .../leave_allocation/leave_allocation.py | 12 ++++++---- .../leave_application/leave_application.py | 23 ++++++++++--------- .../doctype/leave_period/test_leave_period.py | 12 ++++++++-- erpnext/hr/utils.py | 11 +++++---- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py index 874ae7a1bc2..d13bb4577cd 100755 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py @@ -69,10 +69,14 @@ class LeaveAllocation(Document): def validate_allocation_overlap(self): leave_allocation = frappe.db.sql(""" - select name from `tabLeave Allocation` - where employee=%s and leave_type=%s and docstatus=1 - and to_date >= %s and from_date <= %s""", - (self.employee, self.leave_type, self.from_date, self.to_date)) + SELECT + name + FROM `tabLeave Allocation` + WHERE + employee=%s AND leave_type=%s + AND name <> %s AND docstatus=1 + AND to_date >= %s AND from_date <= %s""", + (self.employee, self.leave_type, self.name, self.from_date, self.to_date)) if leave_allocation: frappe.msgprint(_("{0} already allocated for Employee {1} for period {2} to {3}") diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 0e6630541c4..65fcbf7a999 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -549,10 +549,10 @@ def get_leaves_for_period(employee, leave_type, from_date, to_date): leave_days += leave_entry.leaves elif inclusive_period and leave_entry.transaction_type == 'Leave Allocation' \ - and not skip_expiry_leaves(leave_entry, to_date): + and leave_entry.is_expired and not skip_expiry_leaves(leave_entry, to_date): leave_days += leave_entry.leaves - else: + elif leave_entry.transaction_type == 'Leave Application': if leave_entry.from_date < getdate(from_date): leave_entry.from_date = from_date if leave_entry.to_date > getdate(to_date): @@ -579,14 +579,15 @@ def skip_expiry_leaves(leave_entry, date): def get_leave_entries(employee, leave_type, from_date, to_date): ''' Returns leave entries between from_date and to_date ''' return frappe.db.sql(""" - select employee, leave_type, from_date, to_date, leaves, transaction_type, is_carry_forward, transaction_name - from `tabLeave Ledger Entry` - where employee=%(employee)s and leave_type=%(leave_type)s - and docstatus=1 - and leaves<0 - and (from_date between %(from_date)s and %(to_date)s - or to_date between %(from_date)s and %(to_date)s - or (from_date < %(from_date)s and to_date > %(to_date)s)) + SELECT + employee, leave_type, from_date, to_date, leaves, transaction_name, transaction_type, + is_carry_forward, is_expired + FROM `tabLeave Ledger Entry` + WHERE employee=%(employee)s AND leave_type=%(leave_type)s + AND docstatus=1 AND leaves<0 + AND (from_date between %(from_date)s AND %(to_date)s + OR to_date between %(from_date)s AND %(to_date)s + OR (from_date < %(from_date)s AND to_date > %(to_date)s)) """, { "from_date": from_date, "to_date": to_date, @@ -773,4 +774,4 @@ def get_leave_approver(employee): leave_approver = frappe.db.get_value('Department Approver', {'parent': department, 'parentfield': 'leave_approvers', 'idx': 1}, 'approver') - return leave_approver + return leave_approver \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_period/test_leave_period.py b/erpnext/hr/doctype/leave_period/test_leave_period.py index 850a08dd536..1762cf917a2 100644 --- a/erpnext/hr/doctype/leave_period/test_leave_period.py +++ b/erpnext/hr/doctype/leave_period/test_leave_period.py @@ -43,10 +43,18 @@ class TestLeavePeriod(unittest.TestCase): leave_period.grant_leave_allocation(employee=employee_doc_name) self.assertEqual(get_leave_balance_on(employee_doc_name, leave_type, today()), 20) -def create_leave_period(from_date, to_date): +def create_leave_period(from_date, to_date, company=None): + leave_period = frappe.db.get_value('Leave Period', + dict(company=company or erpnext.get_default_company(), + from_date=from_date, + to_date=to_date, + is_active=1), 'name') + if leave_period: + return frappe.get_doc("Leave Period", leave_period) + leave_period = frappe.get_doc({ "doctype": "Leave Period", - "company": erpnext.get_default_company(), + "company": company or erpnext.get_default_company(), "from_date": from_date, "to_date": to_date, "is_active": 1 diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 1464a779368..9b0ca4e9a1a 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -321,11 +321,11 @@ def allocate_earned_leaves(): if new_allocation == allocation.total_leaves_allocated: continue allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False) - create_earned_leave_ledger_entry(allocation, earned_leaves, today) + create_additional_leave_ledger_entry(allocation, earned_leaves, today) -def create_earned_leave_ledger_entry(allocation, earned_leaves, date): - ''' Create leave ledger entry based on the earned leave frequency ''' - allocation.new_leaves_allocated = earned_leaves +def create_additional_leave_ledger_entry(allocation, leaves, date): + ''' Create leave ledger entry for leave types ''' + allocation.new_leaves_allocated = leaves allocation.from_date = date allocation.unused_leaves = 0 allocation.create_leave_ledger_entry() @@ -389,6 +389,7 @@ def get_sal_slip_total_benefit_given(employee, payroll_period, component=False): def get_holidays_for_employee(employee, start_date, end_date): holiday_list = get_holiday_list_for_employee(employee) + holidays = frappe.db.sql_list('''select holiday_date from `tabHoliday` where parent=%(holiday_list)s @@ -437,4 +438,4 @@ def get_previous_claimed_amount(employee, payroll_period, non_pro_rata=False, co }, as_dict=True) if sum_of_claimed_amount and flt(sum_of_claimed_amount[0].total_amount) > 0: total_claimed_amount = sum_of_claimed_amount[0].total_amount - return total_claimed_amount + return total_claimed_amount \ No newline at end of file From 764c2c7f179d53d4f54c526fe41df3580046a21d Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 17 Dec 2019 12:44:19 +0530 Subject: [PATCH 005/105] fix: incorrect outstanding amount shwoing in the AP/AR report --- .../accounts/report/accounts_receivable/accounts_receivable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 2c53f6e9971..c70a2cd1a74 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -171,7 +171,7 @@ class ReceivablePayableReport(object): row.outstanding = flt(row.invoiced - row.paid - row.credit_note, self.currency_precision) row.invoice_grand_total = row.invoiced - if abs(row.outstanding) > 0.1/10 ** self.currency_precision: + if abs(row.outstanding) > 1.0/10 ** self.currency_precision: # non-zero oustanding, we must consider this row if self.is_invoice(row) and self.filters.based_on_payment_terms: From bb42fc615eb16199865e7d0bf6bc32d60c002403 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 17 Dec 2019 18:13:54 +0530 Subject: [PATCH 006/105] fix: not able to make work order from BOM --- erpnext/manufacturing/doctype/work_order/work_order.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 767d99eda52..1cb69012083 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -619,8 +619,9 @@ def make_work_order(item, qty=0, project=None): wo_doc = frappe.new_doc("Work Order") wo_doc.production_item = item wo_doc.update(item_details) - if qty > 0: - wo_doc.qty = qty + + if flt(qty) > 0: + wo_doc.qty = flt(qty) wo_doc.get_items_and_operations_from_bom() return wo_doc From c6e098881fa8942e40e94ea50c9a63c8f11b05eb Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 17 Dec 2019 22:27:23 +0530 Subject: [PATCH 007/105] fix: Update sales register report --- .../report/sales_register/sales_register.py | 235 +++++++++++++++--- 1 file changed, 205 insertions(+), 30 deletions(-) diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 0e2821ac16d..afdd31df16d 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -38,32 +38,46 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No cost_center = list(set(invoice_cc_wh_map.get(inv.name, {}).get("cost_center", []))) warehouse = list(set(invoice_cc_wh_map.get(inv.name, {}).get("warehouse", []))) - row = [ - inv.name, inv.posting_date, inv.customer, inv.customer_name - ] + row = { + 'invoice': inv.name, + 'posting_date': inv.posting_date, + 'customer': inv.customer, + 'customer_name': inv.customer_name + } if additional_query_columns: for col in additional_query_columns: - row.append(inv.get(col)) + row.update({ + col: inv.get(col) + }) + + row.update({ + 'customer_group': inv.get("customer_group"), + 'territory': inv.get("territory"), + 'tax_id': inv.get("tax_id"), + 'receivable_account': inv.debit_to, + 'mode_of_payment': ", ".join(mode_of_payments.get(inv.name, [])), + 'project': inv.project, + 'owner': inv.owner, + 'remarks': inv.remarks, + 'sales_order': ", ".join(sales_order), + 'delivery_note': ", ".join(delivery_note), + 'cost_center': ", ".join(cost_center), + 'warehouse': ", ".join(warehouse), + 'currency': company_currency + }) - row +=[ - inv.get("customer_group"), - inv.get("territory"), - inv.get("tax_id"), - inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])), - inv.project, inv.owner, inv.remarks, - ", ".join(sales_order), ", ".join(delivery_note),", ".join(cost_center), - ", ".join(warehouse), company_currency - ] # map income values base_net_total = 0 for income_acc in income_accounts: income_amount = flt(invoice_income_map.get(inv.name, {}).get(income_acc)) base_net_total += income_amount - row.append(income_amount) + row.update({ + frappe.scrub(income_acc): income_amount + }) # net total - row.append(base_net_total or inv.base_net_total) + row.update({'net_total': base_net_total or inv.base_net_total}) # tax account total_tax = 0 @@ -72,10 +86,18 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No tax_amount_precision = get_field_precision(frappe.get_meta("Sales Taxes and Charges").get_field("tax_amount"), currency=company_currency) or 2 tax_amount = flt(invoice_tax_map.get(inv.name, {}).get(tax_acc), tax_amount_precision) total_tax += tax_amount - row.append(tax_amount) + row.update({ + frappe.scrub(tax_acc): tax_amount + }) # total tax, grand total, outstanding amount & rounded total - row += [total_tax, inv.base_grand_total, inv.base_rounded_total, inv.outstanding_amount] + + row.update({ + 'tax_total': total_tax, + 'grand_total': inv.base_grand_total, + 'rounded_total': inv.base_rounded_total, + 'outstanding_amount': inv.outstanding_amount + }) data.append(row) @@ -84,19 +106,118 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No def get_columns(invoice_list, additional_table_columns): """return columns based on filters""" columns = [ - _("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80", - _("Customer") + ":Link/Customer:120", _("Customer Name") + "::120" + { + 'label': _("Invoice"), + 'fieldname': 'invoice', + 'fieldtype': 'Link', + 'options': 'Sales Invoice', + 'width': 120 + }, + { + 'label': _("Posting Date"), + 'fieldname': 'posting_date', + 'fieldtype': 'Date', + 'width': 80 + }, + { + 'label': _("Customer"), + 'fieldname': 'customer', + 'fieldtype': 'Link', + 'options': 'Customer', + 'width': 120 + }, + { + 'label': _("Customer Name"), + 'fieldname': 'customer_name', + 'fieldtype': 'Data', + 'width': 120 + }, ] if additional_table_columns: columns += additional_table_columns columns +=[ - _("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80", - _("Tax Id") + "::80", _("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120", - _("Project") +":Link/Project:80", _("Owner") + "::150", _("Remarks") + "::150", - _("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100", - _("Cost Center") + ":Link/Cost Center:100", _("Warehouse") + ":Link/Warehouse:100", + { + 'label': _("Custmer Group"), + 'fieldname': 'customer_group', + 'fieldtype': 'Link', + 'options': 'Customer Group', + 'width': 120 + }, + { + 'label': _("Territory"), + 'fieldname': 'territory', + 'fieldtype': 'Link', + 'options': 'Territory', + 'width': 80 + }, + { + 'label': _("Tax Id"), + 'fieldname': 'tax_id', + 'fieldtype': 'Data', + 'width': 120 + }, + { + 'label': _("Receivable Account"), + 'fieldname': 'receivable_account', + 'fieldtype': 'Link', + 'options': 'Account', + 'width': 80 + }, + { + 'label': _("Mode Of Payment"), + 'fieldname': 'mode_of_payment', + 'fieldtype': 'Data', + 'width': 120 + }, + { + 'label': _("Project"), + 'fieldname': 'project', + 'fieldtype': 'Link', + 'options': 'project', + 'width': 80 + }, + { + 'label': _("Owner"), + 'fieldname': 'owner', + 'fieldtype': 'Data', + 'width': 150 + }, + { + 'label': _("Remarks"), + 'fieldname': 'remarks', + 'fieldtype': 'Data', + 'width': 150 + }, + { + 'label': _("Sales Order"), + 'fieldname': 'sales_order', + 'fieldtype': 'Link', + 'options': 'Sales Order', + 'width': 100 + }, + { + 'label': _("Delivery Note"), + 'fieldname': 'delivery_note', + 'fieldtype': 'Link', + 'options': 'Delivery Note', + 'width': 100 + }, + { + 'label': _("Cost Center"), + 'fieldname': 'cost_center', + 'fieldtype': 'Link', + 'options': 'Cost Center', + 'width': 100 + }, + { + 'label': _("Warehouse"), + 'fieldname': 'warehouse', + 'fieldtype': 'Link', + 'options': 'Warehouse', + 'width': 100 + }, { "fieldname": "currency", "label": _("Currency"), @@ -105,7 +226,10 @@ def get_columns(invoice_list, additional_table_columns): } ] - income_accounts = tax_accounts = income_columns = tax_columns = [] + income_accounts = [] + tax_accounts = [] + income_columns = [] + tax_columns = [] if invoice_list: income_accounts = frappe.db.sql_list("""select distinct income_account @@ -119,14 +243,65 @@ def get_columns(invoice_list, additional_table_columns): and parent in (%s) order by account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) - income_columns = [(account + ":Currency/currency:120") for account in income_accounts] + for account in income_accounts: + income_columns.append({ + "label": account, + "fieldname": frappe.scrub(account), + "fieldtype": "Currency", + "options": 'currency', + "width": 120 + }) + for account in tax_accounts: if account not in income_accounts: - tax_columns.append(account + ":Currency/currency:120") + tax_columns.append({ + "label": account, + "fieldname": frappe.scrub(account), + "fieldtype": "Currency", + "options": 'currency', + "width": 120 + }) - columns = columns + income_columns + [_("Net Total") + ":Currency/currency:120"] + tax_columns + \ - [_("Total Tax") + ":Currency/currency:120", _("Grand Total") + ":Currency/currency:120", - _("Rounded Total") + ":Currency/currency:120", _("Outstanding Amount") + ":Currency/currency:120"] + net_total_column = [{ + "label": _("Net Total"), + "fieldname": "net_total", + "fieldtype": "Currency", + "options": 'currency', + "width": 120 + }] + + total_columns = [ + { + "label": _("Tax Total"), + "fieldname": "tax_total", + "fieldtype": "Currency", + "options": 'currency', + "width": 120 + }, + { + "label": _("Grand Total"), + "fieldname": "grand_total", + "fieldtype": "Currency", + "options": 'currency', + "width": 120 + }, + { + "label": _("Rounded Total"), + "fieldname": "rounded_total", + "fieldtype": "Currency", + "options": 'currency', + "width": 120 + }, + { + "label": _("Outstanding Amount"), + "fieldname": "outstanding_amount", + "fieldtype": "Currency", + "options": 'currency', + "width": 120 + } + ] + + columns = columns + income_columns + net_total_column + tax_columns + total_columns return columns, income_accounts, tax_accounts From 6b00d60b4640c79feca2631b7edcd36f71a897dd Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 18 Dec 2019 17:48:39 +0530 Subject: [PATCH 008/105] fix: Pricing Rule Discount for Product --- erpnext/accounts/doctype/pricing_rule/pricing_rule.json | 9 +++------ erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 3 +++ erpnext/public/js/controllers/transaction.js | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json index f73fb10d320..29d83783d07 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json @@ -1,5 +1,4 @@ { - "actions": [], "allow_import": 1, "allow_rename": 1, "autoname": "field:title", @@ -390,8 +389,7 @@ "fieldname": "rate_or_discount", "fieldtype": "Select", "label": "Rate or Discount", - "options": "\nRate\nDiscount Percentage\nDiscount Amount", - "reqd": 1 + "options": "\nRate\nDiscount Percentage\nDiscount Amount" }, { "default": "Grand Total", @@ -440,7 +438,7 @@ }, { "default": "0", - "depends_on": "eval:!doc.mixed_conditions && doc.price_or_product_discount == 'Price'", + "depends_on": "eval:!doc.mixed_conditions && doc.apply_on != 'Transaction'", "fieldname": "same_item", "fieldtype": "Check", "label": "Same Item" @@ -556,8 +554,7 @@ ], "icon": "fa fa-gift", "idx": 1, - "links": [], - "modified": "2019-12-13 15:48:48.331495", + "modified": "2019-12-18 17:29:22.957077", "modified_by": "Administrator", "module": "Accounts", "name": "Pricing Rule", diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 03641028e6f..5fd933b3d98 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -48,6 +48,9 @@ class PricingRule(Document): if tocheck and not self.get(tocheck): throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError) + if self.price_or_product_discount == 'Price' and not self.rate_or_discount: + throw(_("Rate or Discount is required for the price discount."), frappe.MandatoryError) + def validate_applicable_for_selling_or_buying(self): if not self.selling and not self.buying: throw(_("Atleast one of the Selling or Buying must be selected")) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 877a243967c..c735f840769 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -500,6 +500,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ () => { var d = locals[cdt][cdn]; me.add_taxes_from_item_tax_template(d.item_tax_rate); + if (d.free_item_data) { + me.apply_product_discount(d.free_item_data); + } }, () => me.frm.script_manager.trigger("price_list_rate", cdt, cdn), () => me.toggle_conversion_factor(item), From 2149d7ca4fb26cea6faf4732d8f4b45cdd10bd10 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 17 Dec 2019 17:54:34 +0530 Subject: [PATCH 009/105] feat: Dynamic filters for dimensions in budget variance report --- .../budget_variance_report.js | 21 ++++++--- .../budget_variance_report.py | 43 +++++++++---------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index 24511871fdb..3ec4d306c35 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -46,13 +46,24 @@ frappe.query_reports["Budget Variance Report"] = { fieldtype: "Select", options: ["Cost Center", "Project"], default: "Cost Center", - reqd: 1 + reqd: 1, + on_change: function() { + frappe.query_report.set_filter_value("budget_against_filter", []); + frappe.query_report.refresh(); + } }, { - fieldname: "cost_center", - label: __("Cost Center"), - fieldtype: "Link", - options: "Cost Center" + fieldname:"budget_against_filter", + label: __('Dimension Filter'), + fieldtype: "MultiSelectList", + get_data: function(txt) { + if (!frappe.query_report.filters) return; + + let budget_against = frappe.query_report.get_filter_value('budget_against'); + if (!budget_against) return; + + return frappe.db.get_link_options(budget_against, txt); + } }, { fieldname:"show_cumulative", diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py index 8d65ac87148..39e218bfad2 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py @@ -12,22 +12,22 @@ from six import iteritems from pprint import pprint def execute(filters=None): if not filters: filters = {} - validate_filters(filters) + columns = get_columns(filters) - if filters.get("cost_center"): - cost_centers = [filters.get("cost_center")] + if filters.get("budget_against_filter"): + dimensions = filters.get("budget_against_filter") else: - cost_centers = get_cost_centers(filters) + dimensions = get_cost_centers(filters) period_month_ranges = get_period_month_ranges(filters["period"], filters["from_fiscal_year"]) - cam_map = get_cost_center_account_month_map(filters) + cam_map = get_dimension_account_month_map(filters) data = [] - for cost_center in cost_centers: - cost_center_items = cam_map.get(cost_center) - if cost_center_items: - for account, monthwise_data in iteritems(cost_center_items): - row = [cost_center, account] + for dimension in dimensions: + dimension_items = cam_map.get(dimension) + if dimension_items: + for account, monthwise_data in iteritems(dimension_items): + row = [dimension, account] totals = [0, 0, 0] for year in get_fiscal_years(filters): last_total = 0 @@ -55,10 +55,6 @@ def execute(filters=None): return columns, data -def validate_filters(filters): - if filters.get("budget_against") != "Cost Center" and filters.get("cost_center"): - frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center")) - def get_columns(filters): columns = [_(filters.get("budget_against")) + ":Link/%s:150"%(filters.get("budget_against")), _("Account") + ":Link/Account:150"] @@ -98,11 +94,12 @@ def get_cost_centers(filters): else: return frappe.db.sql_list("""select name from `tab{tab}`""".format(tab=filters.get("budget_against"))) #nosec -#Get cost center & target details -def get_cost_center_target_details(filters): +#Get dimension & target details +def get_dimension_target_details(filters): cond = "" - if filters.get("cost_center"): - cond += " and b.cost_center=%s" % frappe.db.escape(filters.get("cost_center")) + if filters.get("budget_against_filter"): + cond += " and b.{budget_against} in (%s)".format(budget_against = \ + frappe.scrub(filters.get('budget_against'))) % ', '.join(['%s']* len(filters.get('budget_against_filter'))) return frappe.db.sql(""" select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount,b.fiscal_year @@ -110,8 +107,8 @@ def get_cost_center_target_details(filters): where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year between %s and %s and b.budget_against = %s and b.company=%s {cond} order by b.fiscal_year """.format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond), - (filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True) - + tuple([filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company] + filters.get('budget_against_filter')), + as_dict=True) #Get target distribution details of accounts of cost center @@ -153,14 +150,14 @@ def get_actual_details(name, filters): return cc_actual_details -def get_cost_center_account_month_map(filters): +def get_dimension_account_month_map(filters): import datetime - cost_center_target_details = get_cost_center_target_details(filters) + dimension_target_details = get_dimension_target_details(filters) tdd = get_target_distribution_details(filters) cam_map = {} - for ccd in cost_center_target_details: + for ccd in dimension_target_details: actual_details = get_actual_details(ccd.budget_against, filters) for month_id in range(1, 13): From 5109b366890c93a26559f6af4087da7633d060ed Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Thu, 19 Dec 2019 13:10:57 +0530 Subject: [PATCH 010/105] fix: bad filter query --- .../purchase_invoice/purchase_invoice.js | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index d7e64cf36fd..643de7d300a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -382,21 +382,11 @@ cur_frm.fields_dict['items'].grid.get_field("item_code").get_query = function(do cur_frm.fields_dict['credit_to'].get_query = function(doc) { // filter on Account - if (doc.supplier) { - return { - filters: { - 'account_type': 'Payable', - 'is_group': 0, - 'company': doc.company - } - } - } else { - return { - filters: { - 'report_type': 'Balance Sheet', - 'is_group': 0, - 'company': doc.company - } + return { + filters: { + 'account_type': 'Payable', + 'is_group': 0, + 'company': doc.company } } } From fcb296aafbdf0c2efa10f058eba1c737c578834d Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Thu, 19 Dec 2019 13:18:46 +0530 Subject: [PATCH 011/105] fix: no role has cancelling permission for share transfer doctype --- erpnext/accounts/doctype/share_transfer/share_transfer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.json b/erpnext/accounts/doctype/share_transfer/share_transfer.json index f17bf04cafd..9e549e06858 100644 --- a/erpnext/accounts/doctype/share_transfer/share_transfer.json +++ b/erpnext/accounts/doctype/share_transfer/share_transfer.json @@ -188,7 +188,7 @@ } ], "is_submittable": 1, - "modified": "2019-11-07 13:31:17.999744", + "modified": "2019-12-19 13:15:59.001301", "modified_by": "Administrator", "module": "Accounts", "name": "Share Transfer", @@ -196,6 +196,7 @@ "permissions": [ { "amend": 1, + "cancel": 1, "create": 1, "delete": 1, "email": 1, From b13eebe657198d480b60132e317c9ea8d32bcb5e Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 19 Dec 2019 13:34:29 +0530 Subject: [PATCH 012/105] fix: Company None not found in get_valuation_rate --- erpnext/stock/doctype/stock_entry/stock_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index f81fa683ba5..34225daf764 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -372,7 +372,7 @@ class StockEntry(StockController): elif d.t_warehouse and not d.basic_rate: d.basic_rate = get_valuation_rate(d.item_code, d.t_warehouse, self.doctype, self.name, d.allow_zero_valuation_rate, - currency=erpnext.get_company_currency(self.company)) + currency=erpnext.get_company_currency(self.company), company=self.company) def set_actual_qty(self): allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")) From 59cecb29a0bbc4a808568f9130f0d2317265a808 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 20 Dec 2019 12:56:01 +0530 Subject: [PATCH 013/105] fix: incorrect consumed qty for partial purchase receipt in subcontracting --- erpnext/controllers/buying_controller.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 3ec7aff9cbb..75b896bb134 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -265,16 +265,17 @@ class BuyingController(StockController): fg_yet_to_be_received = qty_to_be_received_map.get(item_key) - raw_material_data = backflushed_raw_materials_map.get(item_key, {}) - - consumed_qty = raw_material_data.get('qty', 0) - consumed_serial_nos = raw_material_data.get('serial_nos', '') - consumed_batch_nos = raw_material_data.get('batch_nos', '') - transferred_batch_qty_map = get_transferred_batch_qty_map(item.purchase_order, item.item_code) backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code) for raw_material in transferred_raw_materials + non_stock_items: + rm_item_key = '{}{}'.format(raw_material.rm_item_code, item.purchase_order) + raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {}) + + consumed_qty = raw_material_data.get('qty', 0) + consumed_serial_nos = raw_material_data.get('serial_nos', '') + consumed_batch_nos = raw_material_data.get('batch_nos', '') + transferred_qty = raw_material.qty rm_qty_to_be_consumed = transferred_qty - consumed_qty From 3aabeb88b42cd72d435174e093d4a73e2f464b07 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Fri, 20 Dec 2019 14:49:18 +0530 Subject: [PATCH 014/105] fix: account manager doesn't have cancel submit perm for share transfer --- erpnext/accounts/doctype/share_transfer/share_transfer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.json b/erpnext/accounts/doctype/share_transfer/share_transfer.json index 9e549e06858..59a305317d8 100644 --- a/erpnext/accounts/doctype/share_transfer/share_transfer.json +++ b/erpnext/accounts/doctype/share_transfer/share_transfer.json @@ -188,7 +188,7 @@ } ], "is_submittable": 1, - "modified": "2019-12-19 13:15:59.001301", + "modified": "2019-12-20 14:48:01.990600", "modified_by": "Administrator", "module": "Accounts", "name": "Share Transfer", @@ -222,6 +222,7 @@ "write": 1 }, { + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -231,6 +232,7 @@ "report": 1, "role": "Accounts Manager", "share": 1, + "submit": 1, "write": 1 } ], From 14f624f5879458813f6e18bbdd01881a44e90183 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 20 Dec 2019 17:04:22 +0530 Subject: [PATCH 015/105] fix: patch --- erpnext/patches/v12_0/add_export_type_field_in_party_master.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/patches/v12_0/add_export_type_field_in_party_master.py b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py index c565b7ecd87..5bb6e3fb339 100644 --- a/erpnext/patches/v12_0/add_export_type_field_in_party_master.py +++ b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py @@ -27,6 +27,8 @@ def execute(): tax_category = inter_state_category.name for doctype in ('Sales Taxes and Charges Template', 'Purchase Taxes and Charges Template'): + if not frappe.get_meta(doctype).has_field('is_inter_state'): continue + template = frappe.db.get_value(doctype, {'is_inter_state': 1, 'disabled': 0}, ['name']) if template: frappe.db.set_value(doctype, template, 'tax_category', tax_category) From 9609cce7b77a8bff182c5d5ddd0f9f2554bb5f91 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 15 Dec 2019 21:21:31 +0530 Subject: [PATCH 016/105] fix: Dashboard for employee advance doctype --- .../employee_advance_dashboard.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py diff --git a/erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py b/erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py new file mode 100644 index 00000000000..c3b4a3a8894 --- /dev/null +++ b/erpnext/hr/doctype/employee_advance/employee_advance_dashboard.py @@ -0,0 +1,19 @@ +from __future__ import unicode_literals +from frappe import _ + +def get_data(): + return { + 'fieldname': 'employee_advance', + 'non_standard_fieldnames': { + 'Payment Entry': 'reference_name', + 'Journal Entry': 'reference_name' + }, + 'transactions': [ + { + 'items': ['Expense Claim'] + }, + { + 'items': ['Payment Entry', 'Journal Entry'] + } + ] + } From 8f6e989f576859f90d6d2335fb06b2e4aee674e5 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 15 Dec 2019 21:22:28 +0530 Subject: [PATCH 017/105] feat: Capture return amount against Employee advance via Journal Entry --- .../doctype/journal_entry/journal_entry.js | 1 - .../employee_advance/employee_advance.js | 2 +- .../employee_advance/employee_advance.json | 890 ++++-------------- .../employee_advance/employee_advance.py | 14 + .../hr/doctype/expense_claim/expense_claim.py | 2 +- 5 files changed, 199 insertions(+), 710 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index d6236cdb04f..3604b60b751 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -190,7 +190,6 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({ if(jvd.reference_type==="Employee Advance") { return { filters: { - 'status': ['=', 'Unpaid'], 'docstatus': 1 } }; diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js index 77a2bbcbc07..69915fa6e98 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.js +++ b/erpnext/hr/doctype/employee_advance/employee_advance.js @@ -34,7 +34,7 @@ frappe.ui.form.on('Employee Advance', { } else if ( frm.doc.docstatus === 1 - && flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount) + && flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount) - flt(frm.doc.return_amount) && frappe.model.can_create("Expense Claim") ) { frm.add_custom_button( diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json index 3597e76f1e6..a4e46765470 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.json +++ b/erpnext/hr/doctype/employee_advance/employee_advance.json @@ -1,737 +1,213 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2017-10-09 14:26:29.612365", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "allow_import": 1, + "autoname": "naming_series:", + "creation": "2017-10-09 14:26:29.612365", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "naming_series", + "employee", + "employee_name", + "column_break_4", + "posting_date", + "department", + "section_break_8", + "purpose", + "column_break_11", + "advance_amount", + "paid_amount", + "due_advance_amount", + "claimed_amount", + "return_amount", + "section_break_7", + "status", + "company", + "amended_from", + "column_break_18", + "advance_account", + "mode_of_payment" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "naming_series", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Series", - "length": 0, - "no_copy": 0, - "options": "HR-EAD-.YYYY.-", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "options": "HR-EAD-.YYYY.-" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "employee", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Employee", - "length": 0, - "no_copy": 0, - "options": "Employee", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "employee", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Employee", + "options": "Employee", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.employee_name", - "fieldname": "employee_name", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Employee Name", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "employee.employee_name", + "fieldname": "employee_name", + "fieldtype": "Read Only", + "label": "Employee Name" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fieldname": "posting_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Posting Date", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Today", + "fieldname": "posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Posting Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.department", - "fieldname": "department", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Department", - "length": 0, - "no_copy": 0, - "options": "Department", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "employee.department", + "fieldname": "department", + "fieldtype": "Link", + "label": "Department", + "options": "Department", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_8", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_8", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "purpose", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Purpose", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "purpose", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Purpose", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_11", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "advance_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Advance Amount", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "advance_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Advance Amount", + "options": "Company:company:default_currency", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "paid_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Paid Amount", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "paid_amount", + "fieldtype": "Currency", + "label": "Paid Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:cur_frm.doc.employee", - "fieldname": "due_advance_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Due Advance Amount", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:cur_frm.doc.employee", + "fieldname": "due_advance_amount", + "fieldtype": "Currency", + "label": "Due Advance Amount", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "claimed_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Claimed Amount", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "claimed_amount", + "fieldtype": "Currency", + "label": "Claimed Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_7", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_7", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 1, - "options": "Draft\nPaid\nUnpaid\nClaimed\nCancelled", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "status", + "fieldtype": "Select", + "label": "Status", + "no_copy": 1, + "options": "Draft\nPaid\nUnpaid\nClaimed\nCancelled", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Employee Advance", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Employee Advance", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_18", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_18", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "advance_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Advance Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "advance_account", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Advance Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "mode_of_payment", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "label": "Mode of Payment", + "options": "Mode of Payment" + }, + { + "fieldname": "return_amount", + "fieldtype": "Currency", + "label": "Return Amount", + "options": "Company:company:default_currency", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-01-30 11:28:15.529649", - "modified_by": "Administrator", - "module": "HR", - "name": "Employee Advance", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "links": [], + "modified": "2019-12-15 19:04:07.044505", + "modified_by": "Administrator", + "module": "HR", + "name": "Employee Advance", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Employee", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Employee", + "share": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Expense Approver", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Expense Approver", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "employee,employee_name", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "search_fields": "employee,employee_name", + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index 7813da78ca4..674e46438bf 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -53,11 +53,25 @@ class EmployeeAdvance(Document): and party = %s """, (self.name, self.employee), as_dict=1)[0].paid_amount + return_amount = frappe.db.sql(""" + select name, ifnull(sum(credit_in_account_currency), 0) as return_amount + from `tabGL Entry` + where against_voucher_type = 'Employee Advance' + and voucher_type != 'Expense Claim' + and against_voucher = %s + and party_type = 'Employee' + and party = %s + """, (self.name, self.employee), as_dict=1)[0].return_amount + if flt(paid_amount) > self.advance_amount: frappe.throw(_("Row {0}# Paid Amount cannot be greater than requested advance amount"), EmployeeAdvanceOverPayment) + if flt(return_amount) > self.paid_amount - self.claimed_amount: + frappe.throw(_("Return amount cannot be greater unclaimed amount")) + self.db_set("paid_amount", paid_amount) + self.db_set("return_amount", return_amount) self.set_status() frappe.db.set_value("Employee Advance", self.name , "status", self.status) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 59391505fa0..15153b06cb7 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -321,7 +321,7 @@ def get_expense_claim_account(expense_claim_type, company): @frappe.whitelist() def get_advances(employee, advance_id=None): if not advance_id: - condition = 'docstatus=1 and employee={0} and paid_amount > 0 and paid_amount > claimed_amount'.format(frappe.db.escape(employee)) + condition = 'docstatus=1 and employee={0} and paid_amount > 0 and paid_amount > claimed_amount + return_amount'.format(frappe.db.escape(employee)) else: condition = 'name={0}'.format(frappe.db.escape(advance_id)) From f1036c6985b3c2a9fd4e894d230cc5b935046706 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 17 Dec 2019 11:03:22 +0530 Subject: [PATCH 018/105] feat: Custom button to create return entry from Employee Advance --- .../employee_advance/employee_advance.js | 27 +++++++++++++++ .../employee_advance/employee_advance.py | 33 +++++++++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js index 69915fa6e98..54a75925daa 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.js +++ b/erpnext/hr/doctype/employee_advance/employee_advance.js @@ -45,6 +45,15 @@ frappe.ui.form.on('Employee Advance', { __('Create') ); } + + if (frm.doc.docstatus === 1 + && (flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount)) + && frappe.model.can_create("Journal Entry")) { + + frm.add_custom_button(__("Return"), function() { + frm.trigger('make_return_entry'); + }, __('Create')); + } }, make_payment_entry: function(frm) { @@ -83,6 +92,24 @@ frappe.ui.form.on('Employee Advance', { }); }, + make_return_entry: function(frm) { + frappe.call({ + method: 'erpnext.hr.doctype.employee_advance.employee_advance.make_return_entry', + args: { + 'employee_name': frm.doc.employee, + 'company': frm.doc.company, + 'employee_advance_name': frm.doc.name, + 'return_amount': flt(frm.doc.paid_amount - frm.doc.claimed_amount), + 'mode_of_payment': frm.doc.mode_of_payment, + 'advance_account': frm.doc.advance_account + }, + callback: function(r) { + const doclist = frappe.model.sync(r.message); + frappe.set_route('Form', doclist[0].doctype, doclist[0].name); + } + }) + }, + employee: function (frm) { if (frm.doc.employee) { return frappe.call({ diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index 674e46438bf..7fe2ebc79e0 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -7,6 +7,7 @@ import frappe, erpnext from frappe import _ from frappe.model.document import Document from frappe.utils import flt, nowdate +from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account class EmployeeAdvanceOverPayment(frappe.ValidationError): pass @@ -102,8 +103,6 @@ def get_due_advance_amount(employee, posting_date): @frappe.whitelist() def make_bank_entry(dt, dn): - from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account - doc = frappe.get_doc(dt, dn) payment_account = get_default_bank_cash_account(doc.company, account_type="Cash", mode_of_payment=doc.mode_of_payment) @@ -132,3 +131,33 @@ def make_bank_entry(dt, dn): }) return je.as_dict() + +@frappe.whitelist() +def make_return_entry(employee_name, company, employee_advance_name, return_amount, mode_of_payment, advance_account): + return_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment) + je = frappe.new_doc('Journal Entry') + je.posting_date = nowdate() + je.voucher_type = 'Bank Entry' + je.company = company + je.remark = 'Return against Employee Advance: ' + employee_advance_name + + je.append('accounts', { + 'account': advance_account, + 'credit_in_account_currency': return_amount, + 'reference_type': 'Employee Advance', + 'reference_name': employee_advance_name, + 'party_type': 'Employee', + 'party': employee_name, + 'is_advance': 'Yes' + }) + + je.append("accounts", { + "account": return_account.account, + "debit_in_account_currency": return_amount, + "account_currency": return_account.account_currency, + "account_type": return_account.account_type + }) + + return je.as_dict() + + From b7012a47a22406fdc19a56732bf65d594c771cba Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 17 Dec 2019 18:14:33 +0530 Subject: [PATCH 019/105] fix: Remove trailing whitespace and add semicolon --- erpnext/hr/doctype/employee_advance/employee_advance.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js index 54a75925daa..ba62853336d 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.js +++ b/erpnext/hr/doctype/employee_advance/employee_advance.js @@ -46,10 +46,10 @@ frappe.ui.form.on('Employee Advance', { ); } - if (frm.doc.docstatus === 1 + if (frm.doc.docstatus === 1 && (flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount)) && frappe.model.can_create("Journal Entry")) { - + frm.add_custom_button(__("Return"), function() { frm.trigger('make_return_entry'); }, __('Create')); @@ -107,7 +107,7 @@ frappe.ui.form.on('Employee Advance', { const doclist = frappe.model.sync(r.message); frappe.set_route('Form', doclist[0].doctype, doclist[0].name); } - }) + }); }, employee: function (frm) { From adc1b9dc0ad63d166be32263a4952dcfdabe5b81 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Mon, 23 Dec 2019 13:07:00 +0530 Subject: [PATCH 020/105] fix: bad query for debit_to field in sales invoice --- .../doctype/sales_invoice/sales_invoice.js | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 3c852106635..19302a32baf 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -556,22 +556,11 @@ cur_frm.cscript.cost_center = function(doc, cdt, cdn) { } cur_frm.set_query("debit_to", function(doc) { - // filter on Account - if (doc.customer) { - return { - filters: { - 'account_type': 'Receivable', - 'is_group': 0, - 'company': doc.company - } - } - } else { - return { - filters: { - 'report_type': 'Balance Sheet', - 'is_group': 0, - 'company': doc.company - } + return { + filters: { + 'account_type': 'Receivable', + 'is_group': 0, + 'company': doc.company } } }); From 498ebfba9da28746f02ba598a78ceac7e7d17051 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 23 Dec 2019 15:48:18 +0530 Subject: [PATCH 021/105] fix(expense-claim): update status (#20032) * fix(expense-claim): update status * fix(expense-claim): compare using grandtotal precision --- erpnext/hr/doctype/expense_claim/expense_claim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 59391505fa0..ab9a2b22102 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -43,9 +43,9 @@ class ExpenseClaim(AccountsController): }[cstr(self.docstatus or 0)] paid_amount = flt(self.total_amount_reimbursed) + flt(self.total_advance_amount) - precision = self.precision("total_sanctioned_amount") + precision = self.precision("grand_total") if (self.is_paid or (flt(self.total_sanctioned_amount) > 0 - and flt(self.total_sanctioned_amount, precision) == flt(paid_amount, precision))) \ + and flt(self.grand_total, precision) == flt(paid_amount, precision))) \ and self.docstatus == 1 and self.approval_status == 'Approved': self.status = "Paid" elif flt(self.total_sanctioned_amount) > 0 and self.docstatus == 1 and self.approval_status == 'Approved': From b139f2fc0f98b41e68c4b7a83f5440c0469b4aeb Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 23 Dec 2019 15:50:20 +0530 Subject: [PATCH 022/105] feat: fixed party and party type in Accrual journal entry (#20022) --- .../hr/doctype/payroll_entry/payroll_entry.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py index 2de01e6394d..dfd38ebbe38 100644 --- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py @@ -163,7 +163,7 @@ class PayrollEntry(Document): """ cond = self.get_filter_condition() return frappe.db.sql(""" select eld.loan_account, eld.loan, - eld.interest_income_account, eld.principal_amount, eld.interest_amount, eld.total_payment + eld.interest_income_account, eld.principal_amount, eld.interest_amount, eld.total_payment,t1.employee from `tabSalary Slip` t1, `tabSalary Slip Loan` eld where @@ -246,6 +246,7 @@ class PayrollEntry(Document): accounts.append({ "account": acc, "debit_in_account_currency": flt(amount, precision), + "party_type": '', "cost_center": self.cost_center, "project": self.project }) @@ -257,6 +258,7 @@ class PayrollEntry(Document): "account": acc, "credit_in_account_currency": flt(amount, precision), "cost_center": self.cost_center, + "party_type": '', "project": self.project }) @@ -264,7 +266,9 @@ class PayrollEntry(Document): for data in loan_details: accounts.append({ "account": data.loan_account, - "credit_in_account_currency": data.principal_amount + "credit_in_account_currency": data.principal_amount, + "party_type": "Employee", + "party": data.employee }) if data.interest_amount and not data.interest_income_account: @@ -275,14 +279,17 @@ class PayrollEntry(Document): "account": data.interest_income_account, "credit_in_account_currency": data.interest_amount, "cost_center": self.cost_center, - "project": self.project + "project": self.project, + "party_type": "Employee", + "party": data.employee }) payable_amount -= flt(data.total_payment, precision) # Payable amount accounts.append({ "account": default_payroll_payable_account, - "credit_in_account_currency": flt(payable_amount, precision) + "credit_in_account_currency": flt(payable_amount, precision), + "party_type": '', }) journal_entry.set("accounts", accounts) @@ -546,7 +553,6 @@ def submit_salary_slips_for_employees(payroll_entry, salary_slips, publish_progr count += 1 if publish_progress: frappe.publish_progress(count*100/len(salary_slips), title = _("Submitting Salary Slips...")) - if submitted_ss: payroll_entry.make_accrual_jv_entry() frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}") From f27a6528db1cf2eb27c73351f4c12f01b8fb8a8d Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 23 Dec 2019 15:52:59 +0530 Subject: [PATCH 023/105] fix: exchange rate not fetching correctly (#19985) --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index e25942ca34d..88973373ed7 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -968,7 +968,7 @@ def get_exchange_rate(posting_date, account=None, account_currency=None, company # The date used to retreive the exchange rate here is the date passed # in as an argument to this function. - elif (not exchange_rate or exchange_rate==1) and account_currency and posting_date: + elif (not exchange_rate or flt(exchange_rate)==1) and account_currency and posting_date: exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date) else: exchange_rate = 1 From 170c9d0ab827acfb9d646e79195bd31ca70f075d Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 23 Dec 2019 15:56:44 +0530 Subject: [PATCH 024/105] fix: remove mandatory purchase reference for existing asset (#19980) --- erpnext/assets/doctype/asset/asset.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 6b3f2c777cf..f6a7fa20d08 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -144,6 +144,10 @@ frappe.ui.form.on('Asset', { frm.set_df_property('purchase_invoice', 'read_only', 1); frm.set_df_property('purchase_receipt', 'read_only', 1); } + else if (frm.doc.is_existing_asset) { + frm.toggle_reqd('purchase_receipt', 0); + frm.toggle_reqd('purchase_invoice', 0); + } else if (frm.doc.purchase_receipt) { // if purchase receipt link is set then set PI disabled frm.toggle_reqd('purchase_invoice', 0); @@ -256,6 +260,7 @@ frappe.ui.form.on('Asset', { }, is_existing_asset: function(frm) { + frm.trigger("toggle_reference_doc"); // frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation)); }, From dab963aac097249ca891ddd54a0c027ebea5e708 Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 23 Dec 2019 15:56:50 +0530 Subject: [PATCH 025/105] fix: remove mandatory purchase reference for existing asset (#19981) --- erpnext/assets/doctype/asset/asset.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 6b3f2c777cf..f6a7fa20d08 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -144,6 +144,10 @@ frappe.ui.form.on('Asset', { frm.set_df_property('purchase_invoice', 'read_only', 1); frm.set_df_property('purchase_receipt', 'read_only', 1); } + else if (frm.doc.is_existing_asset) { + frm.toggle_reqd('purchase_receipt', 0); + frm.toggle_reqd('purchase_invoice', 0); + } else if (frm.doc.purchase_receipt) { // if purchase receipt link is set then set PI disabled frm.toggle_reqd('purchase_invoice', 0); @@ -256,6 +260,7 @@ frappe.ui.form.on('Asset', { }, is_existing_asset: function(frm) { + frm.trigger("toggle_reference_doc"); // frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation)); }, From 7b926f228f0c91c12519b5ecbaa9bb224c32a0c4 Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 23 Dec 2019 16:08:40 +0530 Subject: [PATCH 026/105] fix: bad condition while checking last asset movement entry (#20048) --- erpnext/assets/doctype/asset_movement/asset_movement.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py index 4e1822b2ce5..3a08baa714e 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -110,7 +110,7 @@ class AssetMovement(Document): ORDER BY asm.transaction_date asc """, (d.asset, self.company, 'Receipt'), as_dict=1) - if auto_gen_movement_entry[0].get('name') == self.name: + if auto_gen_movement_entry and auto_gen_movement_entry[0].get('name') == self.name: frappe.throw(_('{0} will be cancelled automatically on asset cancellation as it was \ auto generated for Asset {1}').format(self.name, d.asset)) From 15c8caac5720f75d10ceabc25814b181bd40646d Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 23 Dec 2019 17:58:44 +0530 Subject: [PATCH 027/105] fix: Do not validate accounting dimensions if from repost (#20043) * fix: Do not check for accounting dimensions in case of repost * fix: Do not validate accounting dimensions if from repost --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 078e05816db..041e419752b 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -29,7 +29,6 @@ class GLEntry(Document): self.validate_and_set_fiscal_year() self.pl_must_have_cost_center() self.validate_cost_center() - self.validate_dimensions_for_pl_and_bs() if not self.flags.from_repost: self.check_pl_account() @@ -39,6 +38,7 @@ class GLEntry(Document): def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False): if not from_repost: self.validate_account_details(adv_adj) + self.validate_dimensions_for_pl_and_bs() check_freezing_date(self.posting_date, adv_adj) validate_frozen_account(self.account, adv_adj) From 139bb92df928e60ec861192de8a0a2d31d5b9d3d Mon Sep 17 00:00:00 2001 From: Pranav Nachnekar Date: Mon, 23 Dec 2019 12:49:52 +0000 Subject: [PATCH 028/105] fix: wrap scheduled_time with getdate (#20046) --- erpnext/crm/doctype/appointment/appointment.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index b6c4c4707de..f50293043b1 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -11,7 +11,7 @@ from datetime import timedelta import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import get_url +from frappe.utils import get_url, getdate from frappe.utils.verified_command import verify_request, get_signed_params @@ -117,7 +117,7 @@ class Appointment(Document): if self._assign: return available_agents = _get_agents_sorted_by_asc_workload( - self.scheduled_time.date()) + getdate(self.scheduled_time)) for agent in available_agents: if(_check_agent_availability(agent, self.scheduled_time)): agent = agent[0] @@ -189,7 +189,7 @@ def _get_agents_sorted_by_asc_workload(date): assigned_to = frappe.parse_json(appointment._assign) if not assigned_to: continue - if (assigned_to[0] in agent_list) and appointment.scheduled_time.date() == date: + if (assigned_to[0] in agent_list) and getdate(appointment.scheduled_time) == date: appointment_counter[assigned_to[0]] += 1 sorted_agent_list = appointment_counter.most_common() sorted_agent_list.reverse() From 065bbc9cb3a8f1e1c16a1108dea0bd8f0dd76cbb Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 23 Dec 2019 18:24:28 +0530 Subject: [PATCH 029/105] enhancement: Added Set Reserve Warehouse field in Purchase Order. (#19992) --- .../purchase_order/purchase_order.json | 12 ++++++++++- erpnext/public/js/controllers/transaction.js | 20 ++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 5dce3497829..8cd44c789de 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-05-21 16:16:39", @@ -47,6 +48,7 @@ "ignore_pricing_rule", "sec_warehouse", "set_warehouse", + "set_reserve_warehouse", "col_break_warehouse", "is_subcontracted", "supplier_warehouse", @@ -1039,12 +1041,20 @@ "fieldtype": "Link", "label": "Tax Category", "options": "Tax Category" + }, + { + "depends_on": "supplied_items", + "fieldname": "set_reserve_warehouse", + "fieldtype": "Link", + "label": "Set Reserve Warehouse", + "options": "Warehouse" } ], "icon": "fa fa-file-text", "idx": 105, "is_submittable": 1, - "modified": "2019-07-11 18:25:49.509343", + "links": [], + "modified": "2019-12-18 13:13:22.852412", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index c735f840769..1c330be5ee6 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1767,14 +1767,28 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, + set_reserve_warehouse: function() { + this.autofill_warehouse("reserve_warehouse"); + }, + set_warehouse: function() { + this.autofill_warehouse("warehouse"); + }, + + autofill_warehouse : function (warehouse_field) { + // set warehouse in all child table rows var me = this; - if(this.frm.doc.set_warehouse) { - $.each(this.frm.doc.items || [], function(i, item) { - frappe.model.set_value(me.frm.doctype + " Item", item.name, "warehouse", me.frm.doc.set_warehouse); + let warehouse = (warehouse_field === "warehouse") ? me.frm.doc.set_warehouse : me.frm.doc.set_reserve_warehouse; + let child_table = (warehouse_field === "warehouse") ? me.frm.doc.items : me.frm.doc.supplied_items; + let doctype = (warehouse_field === "warehouse") ? (me.frm.doctype + " Item") : (me.frm.doctype + " Item Supplied"); + + if(warehouse) { + $.each(child_table || [], function(i, item) { + frappe.model.set_value(doctype, item.name, warehouse_field, warehouse); }); } }, + coupon_code: function() { var me = this; frappe.run_serially([ From 3881ce94ef1dec808537205c705184e800f37f51 Mon Sep 17 00:00:00 2001 From: DeeMysterio Date: Mon, 23 Dec 2019 19:02:44 +0530 Subject: [PATCH 030/105] fix(employee onboarding): stop showing irrelevant job offer links for a job applicant (#20054) --- .../hr/doctype/employee_onboarding/employee_onboarding.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js index 996dcdf8484..c1285675e5c 100644 --- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js +++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js @@ -7,6 +7,14 @@ frappe.ui.form.on('Employee Onboarding', { frm.add_fetch("employee_onboarding_template", "department", "department"); frm.add_fetch("employee_onboarding_template", "designation", "designation"); frm.add_fetch("employee_onboarding_template", "employee_grade", "employee_grade"); + + frm.set_query('job_offer', function () { + return { + filters: { + 'job_applicant': frm.doc.job_applicant + } + }; + }); }, refresh: function(frm) { From 34dabc715b65391fc33a0ad7741fe1aef5b370a4 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Tue, 24 Dec 2019 11:54:04 +0530 Subject: [PATCH 031/105] fix: Update return amount label --- erpnext/hr/doctype/employee_advance/employee_advance.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json index a4e46765470..d233a2bb936 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.json +++ b/erpnext/hr/doctype/employee_advance/employee_advance.json @@ -166,7 +166,7 @@ { "fieldname": "return_amount", "fieldtype": "Currency", - "label": "Return Amount", + "label": "Returned Amount", "options": "Company:company:default_currency", "read_only": 1 } @@ -210,4 +210,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} \ No newline at end of file +} From 7bbeb310155b0b94938df0fa3e97f70e85444dbf Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 24 Dec 2019 12:08:58 +0530 Subject: [PATCH 032/105] fix: Map custom job card create button with dashboard --- erpnext/manufacturing/doctype/job_card/job_card.js | 5 +++++ erpnext/manufacturing/doctype/work_order/work_order.js | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index 95549d5a248..1d9544d34f4 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -3,6 +3,11 @@ frappe.ui.form.on('Job Card', { refresh: function(frm) { + + if(frm.doc.docstatus == 0) { + frm.set_df_property("operation", "read_only", frm.doc.operation_id ? 1 : 0); + } + if(!frm.doc.__islocal && frm.doc.items && frm.doc.items.length) { if (frm.doc.for_quantity != frm.doc.transferred_qty) { frm.add_custom_button(__("Material Request"), () => { diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index 1951c271548..7e1ea3eb1d9 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -6,6 +6,7 @@ frappe.ui.form.on("Work Order", { frm.custom_make_buttons = { 'Stock Entry': 'Start', 'Pick List': 'Create Pick List', + 'Job Card': 'Create Job Card', }; // Set query for warehouses @@ -136,7 +137,7 @@ frappe.ui.form.on("Work Order", { if (frm.doc.docstatus === 1 && frm.doc.operations && frm.doc.operations.length - && frm.doc.qty != frm.doc.material_transferred_for_manufacturing) { + && frm.doc.qty != frm.doc.produced_qty) { const not_completed = frm.doc.operations.filter(d => { if(d.status != 'Completed') { From 9512e55704692de0784adc922b686568bcd0a3ec Mon Sep 17 00:00:00 2001 From: RJPvT <48353029+RJPvT@users.noreply.github.com> Date: Tue, 24 Dec 2019 07:55:05 +0100 Subject: [PATCH 033/105] Update supplier_scorecard.py (#20060) --- erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py index 9e201e31926..af109ba2848 100644 --- a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py +++ b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py @@ -138,7 +138,7 @@ def refresh_scorecards(): # Check to see if any new scorecard periods are created if make_all_scorecards(sc.name) > 0: # Save the scorecard to update the score and standings - sc.save() + frappe.get_doc('Supplier Scorecard', sc.name).save() @frappe.whitelist() From 9de6083dbffe9e218b06755b9bf4b2477b2ee383 Mon Sep 17 00:00:00 2001 From: Sun Howwrongbum Date: Tue, 24 Dec 2019 12:29:05 +0530 Subject: [PATCH 034/105] feat: consider expiry_date during Batch queries (#20064) --- erpnext/controllers/queries.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 7b4a4c92ad1..5c319008a85 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -311,6 +311,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): and sle.item_code = %(item_code)s and sle.warehouse = %(warehouse)s and (sle.batch_no like %(txt)s + or batch.expiry_date like %(txt)s or batch.manufacturing_date like %(txt)s) and batch.docstatus < 2 {cond} @@ -329,6 +330,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): where batch.disabled = 0 and item = %(item_code)s and (name like %(txt)s + or expiry_date like %(txt)s or manufacturing_date like %(txt)s) and docstatus < 2 {0} From 2d30dc583c7c974fb67e7bf49bc78335228f536c Mon Sep 17 00:00:00 2001 From: Himanshu Date: Tue, 24 Dec 2019 12:31:34 +0530 Subject: [PATCH 035/105] fix: resolve ambigious error (#20067) --- erpnext/stock/doctype/batch/batch.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 3e890b4dd4e..114925469b5 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -261,15 +261,14 @@ def get_batch_no(item_code, warehouse, qty=1, throw=False): def get_batches(item_code, warehouse, qty=1, throw=False): - batches = frappe.db.sql( - 'select batch_id, sum(actual_qty) as qty from `tabBatch` join `tabStock Ledger Entry` ignore index (item_code, warehouse) ' - 'on (`tabBatch`.batch_id = `tabStock Ledger Entry`.batch_no )' - 'where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s ' - 'and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL)' - 'group by batch_id ' - 'order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC', - (item_code, warehouse), - as_dict=True - ) - return batches + return frappe.db.sql(""" + select batch_id, sum(`tabStock Ledger Entry`.actual_qty) as qty + from `tabBatch` + join `tabStock Ledger Entry` ignore index (item_code, warehouse) + on (`tabBatch`.batch_id = `tabStock Ledger Entry`.batch_no ) + where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s + and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL) + group by batch_id + order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC' + """, (item_code, warehouse), as_dict=True) \ No newline at end of file From 2e461551d646b528fca5dd56fb19bb7d6768b6f7 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Tue, 24 Dec 2019 12:55:18 +0530 Subject: [PATCH 036/105] fix: Allow creation of multiple landed cost voucher against a Purchase Document (#20059) --- .../purchase_receipt/purchase_receipt.py | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 060175f9045..691f92ffa72 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -88,7 +88,7 @@ class PurchaseReceipt(BuyingController): if getdate(self.posting_date) > getdate(nowdate()): throw(_("Posting Date cannot be future date")) - + def validate_cwip_accounts(self): for item in self.get('items'): if item.is_fixed_asset and is_cwip_accounting_enabled(item.asset_category): @@ -362,7 +362,7 @@ class PurchaseReceipt(BuyingController): # valuation rate is total of net rate, raw mat supp cost, tax amount, lcv amount per item self.update_assets(item, item.valuation_rate) return gl_entries - + def add_asset_gl_entries(self, item, gl_entries): arbnb_account = self.get_company_default("asset_received_but_not_billed") # This returns category's cwip account if not then fallback to company's default cwip account @@ -395,7 +395,7 @@ class PurchaseReceipt(BuyingController): "credit_in_account_currency": (base_asset_amount if asset_rbnb_currency == self.company_currency else asset_amount) }, item=item)) - + def add_lcv_gl_entries(self, item, gl_entries): expenses_included_in_asset_valuation = self.get_company_default("expenses_included_in_asset_valuation") if not is_cwip_accounting_enabled(item.asset_category): @@ -404,7 +404,7 @@ class PurchaseReceipt(BuyingController): else: # This returns company's default cwip account asset_account = get_asset_account("capital_work_in_progress_account", company=self.company) - + gl_entries.append(self.get_gl_dict({ "account": expenses_included_in_asset_valuation, "against": asset_account, @@ -424,7 +424,7 @@ class PurchaseReceipt(BuyingController): }, item=item)) def update_assets(self, item, valuation_rate): - assets = frappe.db.get_all('Asset', + assets = frappe.db.get_all('Asset', filters={ 'purchase_receipt': self.name, 'item_code': item.item_code } ) @@ -610,27 +610,36 @@ def make_stock_entry(source_name,target_doc=None): return doclist def get_item_account_wise_additional_cost(purchase_document): - landed_cost_voucher = frappe.get_value("Landed Cost Purchase Receipt", - {"receipt_document": purchase_document, "docstatus": 1}, "parent") + landed_cost_vouchers = frappe.get_all("Landed Cost Purchase Receipt", fields=["parent"], + filters = {"receipt_document": purchase_document, "docstatus": 1}) - if not landed_cost_voucher: + if not landed_cost_vouchers: return total_item_cost = 0 item_account_wise_cost = {} - landed_cost_voucher_doc = frappe.get_doc("Landed Cost Voucher", landed_cost_voucher) - based_on_field = frappe.scrub(landed_cost_voucher_doc.distribute_charges_based_on) + item_cost_allocated = [] - for item in landed_cost_voucher_doc.items: - total_item_cost += item.get(based_on_field) + for lcv in landed_cost_vouchers: + landed_cost_voucher_doc = frappe.get_cached_doc("Landed Cost Voucher", lcv.parent) + based_on_field = frappe.scrub(landed_cost_voucher_doc.distribute_charges_based_on) - for item in landed_cost_voucher_doc.items: - if item.receipt_document == purchase_document: - for account in landed_cost_voucher_doc.taxes: - item_account_wise_cost.setdefault((item.item_code, item.purchase_receipt_item), {}) - item_account_wise_cost[(item.item_code, item.purchase_receipt_item)].setdefault(account.expense_account, 0.0) - item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account] += \ - account.amount * item.get(based_on_field) / total_item_cost + for item in landed_cost_voucher_doc.items: + if item.purchase_receipt_item not in item_cost_allocated: + total_item_cost += item.get(based_on_field) + item_cost_allocated.append(item.purchase_receipt_item) + + for lcv in landed_cost_vouchers: + landed_cost_voucher_doc = frappe.get_cached_doc("Landed Cost Voucher", lcv.parent) + based_on_field = frappe.scrub(landed_cost_voucher_doc.distribute_charges_based_on) + + for item in landed_cost_voucher_doc.items: + if item.receipt_document == purchase_document: + for account in landed_cost_voucher_doc.taxes: + item_account_wise_cost.setdefault((item.item_code, item.purchase_receipt_item), {}) + item_account_wise_cost[(item.item_code, item.purchase_receipt_item)].setdefault(account.expense_account, 0.0) + item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account] += \ + account.amount * item.get(based_on_field) / total_item_cost return item_account_wise_cost From 827ac91e7f52eafccee8302ec94e190fd16d3c2e Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 24 Dec 2019 13:03:41 +0530 Subject: [PATCH 037/105] fix: supplier email id field not showing in the notification for purchase cycle doctypes (#20070) --- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 5 ++++- erpnext/buying/doctype/purchase_order/purchase_order.json | 3 ++- erpnext/stock/doctype/purchase_receipt/purchase_receipt.json | 5 ++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 6fe18115c04..3715d774139 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-05-21 16:16:39", @@ -417,6 +418,7 @@ "fieldname": "contact_email", "fieldtype": "Small Text", "label": "Contact Email", + "options": "Email", "print_hide": 1, "read_only": 1 }, @@ -1287,7 +1289,8 @@ "icon": "fa fa-file-text", "idx": 204, "is_submittable": 1, - "modified": "2019-09-17 22:31:42.666601", + "links": [], + "modified": "2019-12-24 12:51:58.613538", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 8cd44c789de..d4c5acee906 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -342,6 +342,7 @@ "fieldname": "contact_email", "fieldtype": "Small Text", "label": "Contact Email", + "options": "Email", "print_hide": 1, "read_only": 1 }, @@ -1054,7 +1055,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2019-12-18 13:13:22.852412", + "modified": "2019-12-24 12:44:13.137194", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index d6bc1a9b972..27cd997bcc2 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-05-21 16:16:39", @@ -305,6 +306,7 @@ "fieldname": "contact_email", "fieldtype": "Small Text", "label": "Contact Email", + "options": "Email", "print_hide": 1, "read_only": 1 }, @@ -1056,7 +1058,8 @@ "icon": "fa fa-truck", "idx": 261, "is_submittable": 1, - "modified": "2019-09-27 14:24:49.044505", + "links": [], + "modified": "2019-12-24 12:52:17.216304", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", From 4c4da06a71fd8bd7a60897fb239f745ca1290b70 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 25 Dec 2019 13:59:24 +0530 Subject: [PATCH 038/105] fix: rounding adjustment while both inclusive tax and discount amount present --- erpnext/controllers/taxes_and_totals.py | 12 ++++++++++-- erpnext/public/js/controllers/taxes_and_totals.js | 9 +++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 66232d7ff1b..049a837eaf6 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -312,11 +312,19 @@ class calculate_taxes_and_totals(object): last_tax = self.doc.get("taxes")[-1] non_inclusive_tax_amount = sum([flt(d.tax_amount_after_discount_amount) for d in self.doc.get("taxes") if not d.included_in_print_rate]) + diff = self.doc.total + non_inclusive_tax_amount \ - flt(last_tax.total, last_tax.precision("total")) + + # If discount amount applied, deduct the discount amount + # because self.doc.total is always without discount, but last_tax.total is after discount + if self.discount_amount_applied and self.doc.discount_amount: + diff -= flt(self.doc.discount_amount) + + diff = flt(diff, self.doc.precision("rounding_adjustment")) + if diff and abs(diff) <= (5.0 / 10**last_tax.precision("tax_amount")): - self.doc.rounding_adjustment = flt(flt(self.doc.rounding_adjustment) + - flt(diff), self.doc.precision("rounding_adjustment")) + self.doc.rounding_adjustment = diff def calculate_totals(self): self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt(self.doc.rounding_adjustment) \ diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 2ece7110406..28fb6490254 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -388,9 +388,14 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ var diff = me.frm.doc.total + non_inclusive_tax_amount - flt(last_tax.total, precision("grand_total")); + if(me.discount_amount_applied && me.frm.doc.discount_amount) { + diff -= flt(me.frm.doc.discount_amount); + } + + diff = flt(diff, precision("rounding_adjustment")); + if ( diff && Math.abs(diff) <= (5.0 / Math.pow(10, precision("tax_amount", last_tax))) ) { - this.frm.doc.rounding_adjustment = flt(flt(this.frm.doc.rounding_adjustment) + diff, - precision("rounding_adjustment")); + me.frm.doc.rounding_adjustment = diff; } } } From d0e39e6fac67965e3622421078836d6cfd17f44e Mon Sep 17 00:00:00 2001 From: Himanshu Date: Wed, 25 Dec 2019 15:16:35 +0530 Subject: [PATCH 039/105] fix: remove quote (#20077) --- erpnext/stock/doctype/batch/batch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 114925469b5..0524eee2d53 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -270,5 +270,5 @@ def get_batches(item_code, warehouse, qty=1, throw=False): where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL) group by batch_id - order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC' + order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC """, (item_code, warehouse), as_dict=True) \ No newline at end of file From c522df8f9de24c24bdb6eb41ee66ab137d316680 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Thu, 26 Dec 2019 13:55:35 +0530 Subject: [PATCH 040/105] fix: only show doctypes which impact accounting in accounting period --- .../accounts/doctype/accounting_period/accounting_period.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index 180460c091c..f48d6dfc953 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -41,8 +41,8 @@ class AccountingPeriod(Document): def get_doctypes_for_closing(self): docs_for_closing = [] - doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation", - "Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"] + doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", \ + "Bank Reconciliation", "Asset", "Stock Entry"] closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes] for closed_doctype in closed_doctypes: docs_for_closing.append(closed_doctype) From ee28663836137f13a96cae44d0c057f342626ede Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Thu, 26 Dec 2019 13:15:52 +0530 Subject: [PATCH 041/105] fix: undefined dr_or_cr_notes in case of party type Employee --- .../doctype/payment_reconciliation/payment_reconciliation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index d85344e8b7a..2c04a27b0cd 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -23,6 +23,8 @@ class PaymentReconciliation(Document): if self.party_type in ["Customer", "Supplier"]: dr_or_cr_notes = self.get_dr_or_cr_notes() + else: + dr_or_cr_notes = [] self.add_payment_entries(payment_entries + journal_entries + dr_or_cr_notes) From bc15ea68b852ef6cbe0459d28f6ec2020b38f2fe Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 26 Dec 2019 14:44:47 +0530 Subject: [PATCH 042/105] fix: wrong items in table being deleted --- erpnext/public/js/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index d5a78d4f1f0..f363999ebe2 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -501,6 +501,7 @@ erpnext.utils.update_child_items = function(opts) { frm.doc[opts.child_docname].forEach(d => { dialog.fields_dict.trans_items.df.data.push({ "docname": d.name, + "name": d.name, "item_code": d.item_code, "qty": d.qty, "rate": d.rate, From 5869757860874e2fce7b3357ce9c7657af8e6131 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Thu, 26 Dec 2019 18:23:05 +0530 Subject: [PATCH 043/105] fix: travis failing for leave application test --- .../doctype/leave_application/test_leave_application.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index 38ae808f27e..5dfcad6a294 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -235,8 +235,8 @@ class TestLeaveApplication(unittest.TestCase): frappe.get_doc(dict( doctype = 'Holiday List', holiday_list_name = holiday_list, - from_date = date(date.today().year, 1, 1), - to_date = date(date.today().year, 12, 31), + from_date = add_months(today, -6), + to_date = add_months(today, 6), holidays = [ dict(holiday_date = today, description = 'Test') ] @@ -597,8 +597,8 @@ def get_leave_period(): return frappe.get_doc(dict( name = 'Test Leave Period', doctype = 'Leave Period', - from_date = "{0}-12-01".format(now_datetime().year - 1), - to_date = "{0}-12-31".format(now_datetime().year), + from_date = add_months(nowdate(), -6), + to_date = add_months(nowdate(), 6), company = "_Test Company", is_active = 1 )).insert() From 8ec1d8d5da6dcaf024e4c96177f721719592e7e6 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 27 Dec 2019 12:14:27 +0530 Subject: [PATCH 044/105] fix: fetch opening accumulated depreciation (#20096) --- .../assets/report/fixed_asset_register/fixed_asset_register.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index 57b68b4ed24..14984441d00 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -122,7 +122,7 @@ def get_data(filters): filters=conditions, fields=["name", "asset_name", "department", "cost_center", "purchase_receipt", "asset_category", "purchase_date", "gross_purchase_amount", "location", - "available_for_use_date", "status", "purchase_invoice"]) + "available_for_use_date", "status", "purchase_invoice", "opening_accumulated_depreciation"]) for asset in assets_record: asset_value = asset.gross_purchase_amount - flt(asset.opening_accumulated_depreciation) \ From 47eda0fa6d8965043b3e4f4f6c9c1c952a34ceb1 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 27 Dec 2019 12:21:10 +0530 Subject: [PATCH 045/105] fix: incorrect validation for scrap items (#20108) --- erpnext/stock/doctype/stock_entry/stock_entry.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 1b9660e6d2c..b74dbaf35c5 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -585,12 +585,18 @@ class StockEntry(StockController): def validate_finished_goods(self): """validation: finished good quantity should be same as manufacturing quantity""" + if not self.work_order: return + items_with_target_warehouse = [] allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "overproduction_percentage_for_work_order")) + production_item, wo_qty = frappe.db.get_value("Work Order", + self.work_order, ["production_item", "qty"]) + for d in self.get('items'): - if self.purpose != "Send to Subcontractor" and d.bom_no and flt(d.transfer_qty) > flt(self.fg_completed_qty) and (d.t_warehouse != getattr(self, "pro_doc", frappe._dict()).scrap_warehouse): + if (self.purpose != "Send to Subcontractor" and d.bom_no + and flt(d.transfer_qty) > flt(self.fg_completed_qty) and d.item_code == production_item): frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \ format(d.idx, d.transfer_qty, self.fg_completed_qty)) @@ -598,9 +604,6 @@ class StockEntry(StockController): items_with_target_warehouse.append(d.item_code) if self.work_order and self.purpose == "Manufacture": - production_item, wo_qty = frappe.db.get_value("Work Order", - self.work_order, ["production_item", "qty"]) - allowed_qty = wo_qty + (allowance_percentage/100 * wo_qty) if self.fg_completed_qty > allowed_qty: frappe.throw(_("For quantity {0} should not be grater than work order quantity {1}") From 3d2e61eef3b5e2c98265a7fc870d2e8b2a3702dc Mon Sep 17 00:00:00 2001 From: Rohan Date: Fri, 27 Dec 2019 12:34:43 +0530 Subject: [PATCH 046/105] fix: Add Serial No button prompt (#20098) --- erpnext/public/js/utils/serial_no_batch_selector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 41a59d0af5d..da731950b1a 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -139,7 +139,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ this.dialog.set_value('serial_no', d.serial_no); } - if (d.batch_no) { + if (d.has_batch_no && d.batch_no) { this.frm.doc.items.forEach(data => { if(data.item_code == d.item_code) { this.dialog.fields_dict.batches.df.data.push({ From b299026280e819ffde6cfdd595973d9e8a0e0e22 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 27 Dec 2019 12:36:14 +0530 Subject: [PATCH 047/105] fix: incorrect reorder level in stock balance report (#20110) --- erpnext/stock/report/stock_balance/stock_balance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index a74253e8722..ccba8b0e239 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -55,7 +55,7 @@ def execute(filters=None): 'item_code': item, 'warehouse': warehouse, 'company': company, - 'reorder_level': item_reorder_qty, + 'reorder_level': item_reorder_level, 'reorder_qty': item_reorder_qty, } report_data.update(item_map[item]) From dfdd684fbfafa374c8f066b4dc9c6693b0cf92da Mon Sep 17 00:00:00 2001 From: Sammish Thundiyil Date: Fri, 27 Dec 2019 10:22:40 +0300 Subject: [PATCH 048/105] modified: erpnext/hr/doctype/repayment_schedule/repayment_schedule.json (#20112) --- .../repayment_schedule.json | 293 +++++------------- 1 file changed, 72 insertions(+), 221 deletions(-) diff --git a/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json b/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json index a1161851d04..5bb2d370fa8 100644 --- a/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json +++ b/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json @@ -1,231 +1,82 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2016-12-20 15:32:25.078334", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "creation": "2016-12-20 15:32:25.078334", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "payment_date", + "principal_amount", + "interest_amount", + "total_payment", + "balance_loan_amount", + "paid" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "payment_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Payment Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "columns": 2, + "fieldname": "payment_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Payment Date" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "principal_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Principal Amount", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "principal_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Principal Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "interest_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Interest Amount", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "interest_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Interest Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "total_payment", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Total Payment", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "total_payment", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Total Payment", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "balance_loan_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Balance Loan Amount", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "balance_loan_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Balance Loan Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "paid", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Paid", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "default": "0", + "fieldname": "paid", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Paid", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-03-30 17:37:31.834792", - "modified_by": "Administrator", - "module": "HR", - "name": "Repayment Schedule", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 + ], + "istable": 1, + "modified": "2019-10-29 11:45:10.694557", + "modified_by": "Administrator", + "module": "HR", + "name": "Repayment Schedule", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file From 6ea509f7f4dc2463f7b0eeaa8956475eb891e6dc Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 27 Dec 2019 12:56:17 +0530 Subject: [PATCH 049/105] feat: allow adding and deleting of items in submitted SO & PO (#19912) * feat: allow adding of items after quotation submission * feat: allow deletion of items from submitted SO & PO * fix: case when items are added and deleted at once * fix: add test cases * For deletion of items while Updating Items after submitting PO & SO --- .../purchase_order/test_purchase_order.py | 67 +++++++++++++++++++ erpnext/controllers/accounts_controller.py | 21 ++++++ erpnext/public/js/utils.js | 3 +- .../doctype/sales_order/test_sales_order.py | 49 +++++++++++++- 4 files changed, 138 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index a0a1e8ed5c4..2b6367b08d1 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -116,6 +116,73 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEqual(po.get("items")[0].amount, 1400) self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3) + + def test_add_new_item_in_update_child_qty_rate(self): + po = create_purchase_order(do_not_save=1) + po.items[0].qty = 4 + po.save() + po.submit() + pr = make_pr_against_po(po.name, 2) + + po.load_from_db() + first_item_of_po = po.get("items")[0] + + trans_item = json.dumps([ + { + 'item_code': first_item_of_po.item_code, + 'rate': first_item_of_po.rate, + 'qty': first_item_of_po.qty, + 'docname': first_item_of_po.name + }, + {'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7} + ]) + update_child_qty_rate('Purchase Order', trans_item, po.name) + + po.reload() + self.assertEquals(len(po.get('items')), 2) + self.assertEqual(po.status, 'To Receive and Bill') + + + def test_remove_item_in_update_child_qty_rate(self): + po = create_purchase_order(do_not_save=1) + po.items[0].qty = 4 + po.save() + po.submit() + pr = make_pr_against_po(po.name, 2) + + po.reload() + first_item_of_po = po.get("items")[0] + # add an item + trans_item = json.dumps([ + { + 'item_code': first_item_of_po.item_code, + 'rate': first_item_of_po.rate, + 'qty': first_item_of_po.qty, + 'docname': first_item_of_po.name + }, + {'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7}]) + update_child_qty_rate('Purchase Order', trans_item, po.name) + + po.reload() + # check if can remove received item + trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': po.get("items")[1].name}]) + self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Purchase Order', trans_item, po.name) + + first_item_of_po = po.get("items")[0] + trans_item = json.dumps([ + { + 'item_code': first_item_of_po.item_code, + 'rate': first_item_of_po.rate, + 'qty': first_item_of_po.qty, + 'docname': first_item_of_po.name + } + ]) + update_child_qty_rate('Purchase Order', trans_item, po.name) + + po.reload() + self.assertEquals(len(po.get('items')), 1) + self.assertEqual(po.status, 'To Receive and Bill') + def test_update_qty(self): po = create_purchase_order() diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 6150516ac8c..86f5d53b33c 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1155,6 +1155,25 @@ def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docna child_item.base_amount = 1 # Initiallize value will update in parent validation return child_item +def check_and_delete_children(parent, data): + deleted_children = [] + updated_item_names = [d.get("docname") for d in data] + for item in parent.items: + if item.name not in updated_item_names: + deleted_children.append(item) + + for d in deleted_children: + if parent.doctype == "Sales Order" and flt(d.delivered_qty): + frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been delivered").format(d.idx, d.item_code)) + + if parent.doctype == "Purchase Order" and flt(d.received_qty): + frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been received").format(d.idx, d.item_code)) + + if flt(d.billed_amt): + frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been billed.").format(d.idx, d.item_code)) + + d.cancel() + d.delete() @frappe.whitelist() def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"): @@ -1163,6 +1182,8 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation'] parent = frappe.get_doc(parent_doctype, parent_doctype_name) + check_and_delete_children(parent, data) + for d in data: new_child_flag = False if not d.get("docname"): diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index f363999ebe2..3f444f83879 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -458,7 +458,8 @@ erpnext.utils.update_child_items = function(opts) { fieldname:"item_code", options: 'Item', in_list_view: 1, - read_only: 1, + read_only: 0, + disabled: 0, label: __('Item Code') }, { fieldtype:'Float', diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index bd078414885..9735c70830d 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -320,7 +320,12 @@ class TestSalesOrder(unittest.TestCase): create_dn_against_so(so.name, 4) make_sales_invoice(so.name) - trans_item = json.dumps([{'item_code' : '_Test Item 2', 'rate' : 200, 'qty' : 7}]) + first_item_of_so = so.get("items")[0] + trans_item = json.dumps([ + {'item_code' : first_item_of_so.item_code, 'rate' : first_item_of_so.rate, \ + 'qty' : first_item_of_so.qty, 'docname': first_item_of_so.name}, + {'item_code' : '_Test Item 2', 'rate' : 200, 'qty' : 7} + ]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() @@ -329,6 +334,48 @@ class TestSalesOrder(unittest.TestCase): self.assertEqual(so.get("items")[-1].qty, 7) self.assertEqual(so.get("items")[-1].amount, 1400) self.assertEqual(so.status, 'To Deliver and Bill') + + def test_remove_item_in_update_child_qty_rate(self): + so = make_sales_order(**{ + "item_list": [{ + "item_code": '_Test Item', + "qty": 5, + "rate":1000 + }] + }) + create_dn_against_so(so.name, 2) + make_sales_invoice(so.name) + + # add an item so as to try removing items + trans_item = json.dumps([ + {"item_code": '_Test Item', "qty": 5, "rate":1000, "docname": so.get("items")[0].name}, + {"item_code": '_Test Item 2', "qty": 2, "rate":500} + ]) + update_child_qty_rate('Sales Order', trans_item, so.name) + so.reload() + self.assertEqual(len(so.get("items")), 2) + + # check if delivered items can be removed + trans_item = json.dumps([{ + "item_code": '_Test Item 2', + "qty": 2, + "rate":500, + "docname": so.get("items")[1].name + }]) + self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Sales Order', trans_item, so.name) + + #remove last added item + trans_item = json.dumps([{ + "item_code": '_Test Item', + "qty": 5, + "rate":1000, + "docname": so.get("items")[0].name + }]) + update_child_qty_rate('Sales Order', trans_item, so.name) + + so.reload() + self.assertEqual(len(so.get("items")), 1) + self.assertEqual(so.status, 'To Deliver and Bill') def test_update_child_qty_rate(self): From 2dec92374013e90090603b4282b312e677d08406 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Fri, 27 Dec 2019 12:58:38 +0530 Subject: [PATCH 050/105] fix: Patch incorrect GST category in invoices (#20085) * fix: Patch to set GST category for unregistered invoice * fix: Move patch up in line * fix: Remove unwanted patch statements --- erpnext/patches.txt | 1 + erpnext/patches/v12_0/update_gst_category.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 erpnext/patches/v12_0/update_gst_category.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index eb686122355..f1dfb10729c 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -586,6 +586,7 @@ erpnext.patches.v11_0.add_permissions_in_gst_settings erpnext.patches.v11_1.setup_guardian_role execute:frappe.delete_doc('DocType', 'Notification Control') erpnext.patches.v12_0.set_gst_category +erpnext.patches.v12_0.update_gst_category erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants erpnext.patches.v12_0.set_task_status erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019 diff --git a/erpnext/patches/v12_0/update_gst_category.py b/erpnext/patches/v12_0/update_gst_category.py new file mode 100644 index 00000000000..963edad150e --- /dev/null +++ b/erpnext/patches/v12_0/update_gst_category.py @@ -0,0 +1,19 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + return + + frappe.db.sql(""" UPDATE `tabSales Invoice` set gst_category = 'Unregistered' + where gst_category = 'Registered Regular' + and ifnull(customer_gstin, '')='' + and ifnull(billing_address_gstin,'')='' + """) + + frappe.db.sql(""" UPDATE `tabPurchase Invoice` set gst_category = 'Unregistered' + where gst_category = 'Registered Regular' + and ifnull(supplier_gstin, '')='' + """) \ No newline at end of file From aab1fb0d6a718fb28c9b126811abb1317ba60217 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 27 Dec 2019 13:02:33 +0530 Subject: [PATCH 051/105] fix: unpaid invoices are created even if current invoice is paid (#20082) --- .../accounts/doctype/subscription/subscription.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index f13ca4c49e8..54827503759 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -338,6 +338,16 @@ class Subscription(Document): # Check invoice dates and make sure it doesn't have outstanding invoices return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice() + + def is_current_invoice_paid(self): + if self.is_new_subscription(): + return False + + last_invoice = frappe.get_doc('Sales Invoice', self.invoices[-1].invoice) + if getdate(last_invoice.posting_date) == getdate(self.current_invoice_start) and last_invoice.status == 'Paid': + return True + + return False def process_for_active(self): """ @@ -348,7 +358,7 @@ class Subscription(Document): 2. Change the `Subscription` status to 'Past Due Date' 3. Change the `Subscription` status to 'Cancelled' """ - if self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice(): + if not self.is_current_invoice_paid() and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()): self.generate_invoice() if self.current_invoice_is_past_due(): self.status = 'Past Due Date' From 65353e55903c9c84103f71f00039ce8365db8c10 Mon Sep 17 00:00:00 2001 From: Marica Date: Fri, 27 Dec 2019 15:30:47 +0530 Subject: [PATCH 052/105] fix: Show both warehouse columns in Stock Entry Grid view. (#20114) --- erpnext/stock/doctype/stock_entry/stock_entry.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index ca480f969d8..ea27c6f5d5b 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -836,8 +836,6 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ this.frm.toggle_enable("from_warehouse", doc.purpose!='Material Receipt'); this.frm.toggle_enable("to_warehouse", doc.purpose!='Material Issue'); - this.frm.fields_dict["items"].grid.set_column_disp("s_warehouse", doc.purpose!='Material Receipt'); - this.frm.fields_dict["items"].grid.set_column_disp("t_warehouse", doc.purpose!='Material Issue'); this.frm.fields_dict["items"].grid.set_column_disp("retain_sample", doc.purpose=='Material Receipt'); this.frm.fields_dict["items"].grid.set_column_disp("sample_quantity", doc.purpose=='Material Receipt'); From ed386376dc525ccbe3aff14023985f026fe44bc8 Mon Sep 17 00:00:00 2001 From: Marica Date: Fri, 27 Dec 2019 16:53:09 +0530 Subject: [PATCH 053/105] fix: Removed unneccesary Duplicate Entry Error. (#20121) --- erpnext/stock/doctype/item/item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index efcede1708d..d2e04914017 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -551,7 +551,7 @@ class Item(WebsiteGenerator): """select parent from `tabItem Barcode` where barcode = %s and parent != %s""", (item_barcode.barcode, self.name)) if duplicate: frappe.throw(_("Barcode {0} already used in Item {1}").format( - item_barcode.barcode, duplicate[0][0]), frappe.DuplicateEntryError) + item_barcode.barcode, duplicate[0][0])) item_barcode.barcode_type = "" if item_barcode.barcode_type not in options else item_barcode.barcode_type if item_barcode.barcode_type and item_barcode.barcode_type.upper() in ('EAN', 'UPC-A', 'EAN-13', 'EAN-8'): From 82c5a2bf45e4aefc05bf96d60971f363ba0ef877 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Fri, 27 Dec 2019 16:26:03 +0530 Subject: [PATCH 054/105] fix: don't allow deletion of items which has work order assigned to it --- erpnext/controllers/accounts_controller.py | 9 +++++++-- erpnext/selling/doctype/sales_order/sales_order.js | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 86f5d53b33c..7faf792d203 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1163,8 +1163,13 @@ def check_and_delete_children(parent, data): deleted_children.append(item) for d in deleted_children: - if parent.doctype == "Sales Order" and flt(d.delivered_qty): - frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been delivered").format(d.idx, d.item_code)) + if parent.doctype == "Sales Order": + if flt(d.delivered_qty): + frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been delivered").format(d.idx, d.item_code)) + if flt(d.work_order_qty): + frappe.throw(_("Row #{0}: Cannot delete item {1} which has work order assigned to it.").format(d.idx, d.item_code)) + if flt(d.ordered_qty): + frappe.throw(_("Row #{0}: Cannot delete item {1} which is assigned to customer's purchase order.").format(d.idx, d.item_code)) if parent.doctype == "Purchase Order" and flt(d.received_qty): frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been received").format(d.idx, d.item_code)) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 2dae0d8063d..cb016a1a744 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -12,7 +12,8 @@ frappe.ui.form.on("Sales Order", { 'Material Request': 'Material Request', 'Purchase Order': 'Purchase Order', 'Project': 'Project', - 'Payment Entry': "Payment" + 'Payment Entry': "Payment", + 'Work Order': "Work Order" } frm.add_fetch('customer', 'tax_id', 'tax_id'); From 2faa8f92bea5e10cf31792fff8d7df9a684dc0eb Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 27 Dec 2019 17:18:27 +0530 Subject: [PATCH 055/105] chore: Added Reports to Stock Module Desk --- erpnext/config/stock.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py index 441a3ab4ec3..4fcc12db395 100644 --- a/erpnext/config/stock.py +++ b/erpnext/config/stock.py @@ -332,6 +332,18 @@ def get_data(): "is_query_report": True, "name": "Item Variant Details", "doctype": "Item" + }, + { + "type": "report", + "is_query_report": True, + "name": "Subcontracted Raw Materials To Be Transferred", + "doctype": "Purchase Order" + }, + { + "type": "report", + "is_query_report": True, + "name": "Subcontracted Item To Be Received", + "doctype": "Purchase Order" } ] }, From 2fcc51decedb842e6f3112d0eea6c84359d2de67 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 30 Dec 2019 11:42:01 +0530 Subject: [PATCH 056/105] fix: service item's cost showing incorrect amount in stock entry (#20105) --- erpnext/manufacturing/doctype/bom/bom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 723445ad528..686b1967eb5 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -767,7 +767,7 @@ def add_additional_cost(stock_entry, work_order): items = {} for d in bom.get(table): - items.setdefault(d.item_code, d.rate) + items.setdefault(d.item_code, d.amount) non_stock_items = frappe.get_all('Item', fields="name", filters={'name': ('in', list(items.keys())), 'ifnull(is_stock_item, 0)': 0}, as_list=1) @@ -776,7 +776,7 @@ def add_additional_cost(stock_entry, work_order): stock_entry.append('additional_costs', { 'expense_account': expenses_included_in_valuation, 'description': name[0], - 'amount': items.get(name[0]) + 'amount': flt(items.get(name[0])) * flt(stock_entry.fg_completed_qty) / flt(bom.quantity) }) @frappe.whitelist() From 5c144c992e3f82e23d5efd85d6d46d54e0b1d392 Mon Sep 17 00:00:00 2001 From: ci2014 Date: Mon, 30 Dec 2019 07:20:43 +0100 Subject: [PATCH 057/105] Skip validate_duplicate_apply_on if not necessary (#20128) Skip the validation of duplicate fields if the type is transaction, for example. --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 5fd933b3d98..1d8d9dbcef5 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -34,6 +34,9 @@ class PricingRule(Document): def validate_duplicate_apply_on(self): field = apply_on_dict.get(self.apply_on) + if not field: + return False + values = [d.get(frappe.scrub(self.apply_on)) for d in self.get(field)] if len(values) != len(set(values)): @@ -419,4 +422,4 @@ def get_item_uoms(doctype, txt, searchfield, start, page_len, filters): return frappe.get_all('UOM Conversion Detail', filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))}, - fields = ["distinct uom"], as_list=1) \ No newline at end of file + fields = ["distinct uom"], as_list=1) From 55cf2477cdd5d94c12955a40cf98583d33805254 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 30 Dec 2019 13:27:10 +0530 Subject: [PATCH 058/105] fix: incorrect batch fetched for the serialized items (#20118) --- erpnext/controllers/stock_controller.py | 13 ++++++++ erpnext/stock/doctype/batch/batch.py | 30 ++++++++++++++----- .../stock/doctype/stock_entry/stock_entry.py | 1 + 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 542073ebd76..fc2128f2a42 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -20,6 +20,7 @@ class StockController(AccountsController): def validate(self): super(StockController, self).validate() self.validate_inspection() + self.validate_serialized_batch() def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False): if self.docstatus == 2: @@ -42,6 +43,18 @@ class StockController(AccountsController): gl_entries = self.get_asset_gl_entry(gl_entries) make_gl_entries(gl_entries, from_repost=from_repost) + def validate_serialized_batch(self): + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + for d in self.get("items"): + if not (hasattr(d, 'serial_no') and d.serial_no and d.batch_no): continue + + serial_nos = get_serial_nos(d.serial_no) + for serial_no_data in frappe.get_all("Serial No", + filters={"name": ("in", serial_nos)}, fields=["batch_no", "name"]): + if serial_no_data.batch_no != d.batch_no: + frappe.throw(_("Row #{0}: Serial No {1} does not belong to Batch {2}") + .format(d.idx, serial_no_data.name, d.batch_no)) + def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 0524eee2d53..8ae978eaf05 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -226,16 +226,14 @@ def set_batch_nos(doc, warehouse_field, throw=False): warehouse = d.get(warehouse_field, None) if has_batch_no and warehouse and qty > 0: if not d.batch_no: - d.batch_no = get_batch_no(d.item_code, warehouse, qty, throw) + d.batch_no = get_batch_no(d.item_code, warehouse, qty, throw, d.serial_no) else: batch_qty = get_batch_qty(batch_no=d.batch_no, warehouse=warehouse) if flt(batch_qty, d.precision("qty")) < flt(qty, d.precision("qty")): frappe.throw(_("Row #{0}: The batch {1} has only {2} qty. Please select another batch which has {3} qty available or split the row into multiple rows, to deliver/issue from multiple batches").format(d.idx, d.batch_no, batch_qty, qty)) - - @frappe.whitelist() -def get_batch_no(item_code, warehouse, qty=1, throw=False): +def get_batch_no(item_code, warehouse, qty=1, throw=False, serial_no=None): """ Get batch number using First Expiring First Out method. :param item_code: `item_code` of Item Document @@ -245,7 +243,7 @@ def get_batch_no(item_code, warehouse, qty=1, throw=False): """ batch_no = None - batches = get_batches(item_code, warehouse, qty, throw) + batches = get_batches(item_code, warehouse, qty, throw, serial_no) for batch in batches: if cint(qty) <= cint(batch.qty): @@ -260,7 +258,23 @@ def get_batch_no(item_code, warehouse, qty=1, throw=False): return batch_no -def get_batches(item_code, warehouse, qty=1, throw=False): +def get_batches(item_code, warehouse, qty=1, throw=False, serial_no=None): + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + cond = '' + if serial_no: + batch = frappe.get_all("Serial No", + fields = ["distinct batch_no"], + filters= { + "item_code": item_code, + "warehouse": warehouse, + "name": ("in", get_serial_nos(serial_no)) + } + ) + + if batch and len(batch) > 1: + return [] + + cond = " and `tabBatch`.name = %s" %(frappe.db.escape(batch[0].batch_no)) return frappe.db.sql(""" select batch_id, sum(`tabStock Ledger Entry`.actual_qty) as qty @@ -268,7 +282,7 @@ def get_batches(item_code, warehouse, qty=1, throw=False): join `tabStock Ledger Entry` ignore index (item_code, warehouse) on (`tabBatch`.batch_id = `tabStock Ledger Entry`.batch_no ) where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s - and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL) + and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL) {0} group by batch_id order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC - """, (item_code, warehouse), as_dict=True) \ No newline at end of file + """.format(cond), (item_code, warehouse), as_dict=True) \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index b74dbaf35c5..35af24c8317 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -75,6 +75,7 @@ class StockEntry(StockController): set_batch_nos(self, 's_warehouse') self.set_incoming_rate() + self.validate_serialized_batch() self.set_actual_qty() self.calculate_rate_and_amount(update_finished_item_rate=False) From efa7d5c8310fcbba55358883ed7a1480b7470742 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 30 Dec 2019 15:18:02 +0530 Subject: [PATCH 059/105] fix: format currency field in bank and cash payment voucher print format (#20138) --- .../bank_and_cash_payment_voucher.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html index 69e42c3bdbc..6fe69990513 100644 --- a/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html +++ b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html @@ -49,7 +49,7 @@ {% endfor %} Total (debit) - {{ gl | sum(attribute='debit') }} + {{ frappe.format((gl | sum(attribute="debit")), {fieldtype: "Currency"}) }} Credit @@ -69,7 +69,7 @@ {% endfor %} Total (credit) - {{ gl | sum(attribute='credit') }} + {{ frappe.format((gl | sum(attribute="credit")), {fieldtype: "Currency"}) }}
From 26e86e7576a843078ccbe383c94460df007db135 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 30 Dec 2019 16:17:10 +0530 Subject: [PATCH 060/105] fix: added extra condition (#20139) --- erpnext/hr/doctype/leave_application/leave_application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 65fcbf7a999..915cea149d8 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -351,7 +351,7 @@ class LeaveApplication(Document): pass def create_leave_ledger_entry(self, submit=True): - if self.status != 'Approved': + if self.status != 'Approved' and submit: return expiry_date = get_allocation_expiry(self.employee, self.leave_type, From 10622aee7f0bd5598a92656ad00bb2afd9a78657 Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 30 Dec 2019 22:20:27 +0530 Subject: [PATCH 061/105] fix: Field 'other_charges_calculation' column type changed. (#20142) --- .../purchase_invoice/purchase_invoice.json | 4 +- .../doctype/sales_invoice/sales_invoice.json | 6 +- .../purchase_order/purchase_order.json | 4 +- .../supplier_quotation.json | 3854 ++++------------- .../selling/doctype/quotation/quotation.json | 6 +- .../doctype/sales_order/sales_order.json | 6 +- .../doctype/delivery_note/delivery_note.json | 6 +- .../purchase_receipt/purchase_receipt.json | 4 +- 8 files changed, 852 insertions(+), 3038 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 3715d774139..7725994c6b0 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -707,7 +707,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Text", + "fieldtype": "Long Text", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -1290,7 +1290,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2019-12-24 12:51:58.613538", + "modified": "2019-12-30 19:13:49.610538", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 96aceac8cd9..33ee7a2974e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-05-24 19:29:05", @@ -774,7 +775,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Text", + "fieldtype": "Long Text", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -1567,7 +1568,8 @@ "icon": "fa fa-file-text", "idx": 181, "is_submittable": 1, - "modified": "2019-10-05 21:39:49.235990", + "links": [], + "modified": "2019-12-30 19:15:59.580414", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index d4c5acee906..9201eef9b49 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -610,7 +610,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Text", + "fieldtype": "Long Text", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -1055,7 +1055,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2019-12-24 12:44:13.137194", + "modified": "2019-12-30 19:11:54.122264", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index b17bed46c4d..82fc6285bcf 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -1,3060 +1,866 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2013-05-21 16:16:45", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 0, + "actions": [], + "allow_import": 1, + "autoname": "naming_series:", + "creation": "2013-05-21 16:16:45", + "doctype": "DocType", + "document_type": "Document", + "engine": "InnoDB", + "field_order": [ + "supplier_section", + "title", + "naming_series", + "supplier", + "supplier_name", + "column_break1", + "transaction_date", + "amended_from", + "company", + "address_section", + "supplier_address", + "contact_person", + "address_display", + "contact_display", + "contact_mobile", + "contact_email", + "currency_and_price_list", + "currency", + "conversion_rate", + "cb_price_list", + "buying_price_list", + "price_list_currency", + "plc_conversion_rate", + "ignore_pricing_rule", + "items_section", + "items", + "link_to_mrs", + "pricing_rule_details", + "pricing_rules", + "section_break_22", + "total_qty", + "base_total", + "base_net_total", + "column_break_24", + "total", + "net_total", + "total_net_weight", + "taxes_section", + "tax_category", + "column_break_36", + "shipping_rule", + "section_break_38", + "taxes_and_charges", + "taxes", + "tax_breakup", + "other_charges_calculation", + "totals", + "base_taxes_and_charges_added", + "base_taxes_and_charges_deducted", + "base_total_taxes_and_charges", + "column_break_37", + "taxes_and_charges_added", + "taxes_and_charges_deducted", + "total_taxes_and_charges", + "section_break_41", + "apply_discount_on", + "base_discount_amount", + "column_break_43", + "additional_discount_percentage", + "discount_amount", + "section_break_46", + "base_grand_total", + "base_rounding_adjustment", + "base_in_words", + "base_rounded_total", + "column_break4", + "grand_total", + "rounding_adjustment", + "rounded_total", + "in_words", + "disable_rounded_total", + "terms_section_break", + "tc_name", + "terms", + "printing_settings", + "select_print_heading", + "group_same_items", + "column_break_72", + "letter_head", + "language", + "subscription_section", + "auto_repeat", + "update_auto_repeat_reference", + "more_info", + "status", + "column_break_57", + "is_subcontracted", + "reference", + "opportunity" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "supplier_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "options": "fa fa-user", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "supplier_section", + "fieldtype": "Section Break", + "options": "fa fa-user" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "{supplier_name}", - "fieldname": "title", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Title", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "{supplier_name}", + "fieldname": "title", + "fieldtype": "Data", + "hidden": 1, + "label": "Title", + "no_copy": 1, + "print_hide": 1, + "report_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "naming_series", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Series", - "length": 0, - "no_copy": 1, - "oldfieldname": "naming_series", - "oldfieldtype": "Select", - "options": "PUR-SQTN-.YYYY.-", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "no_copy": 1, + "oldfieldname": "naming_series", + "oldfieldtype": "Select", + "options": "PUR-SQTN-.YYYY.-", + "print_hide": 1, + "reqd": 1, + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "supplier", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Supplier", - "length": 0, - "no_copy": 0, - "oldfieldname": "supplier", - "oldfieldtype": "Link", - "options": "Supplier", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "bold": 1, + "fieldname": "supplier", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Supplier", + "oldfieldname": "supplier", + "oldfieldtype": "Link", + "options": "Supplier", + "print_hide": 1, + "reqd": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fetch_from": "supplier.supplier_name", - "fieldname": "supplier_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Name", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "bold": 1, + "fetch_from": "supplier.supplier_name", + "fieldname": "supplier_name", + "fieldtype": "Data", + "in_global_search": 1, + "label": "Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "50%", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "fieldname": "column_break1", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break", + "print_width": "50%", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fieldname": "transaction_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Date", - "length": 0, - "no_copy": 0, - "oldfieldname": "transaction_date", - "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Today", + "fieldname": "transaction_date", + "fieldtype": "Date", + "label": "Date", + "oldfieldname": "transaction_date", + "oldfieldtype": "Date", + "reqd": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "oldfieldname": "amended_from", - "oldfieldtype": "Data", - "options": "Supplier Quotation", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "amended_from", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 1, + "label": "Amended From", + "no_copy": 1, + "oldfieldname": "amended_from", + "oldfieldtype": "Data", + "options": "Supplier Quotation", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Company", - "length": 0, - "no_copy": 0, - "oldfieldname": "company", - "oldfieldtype": "Link", - "options": "Company", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Company", + "oldfieldname": "company", + "oldfieldtype": "Link", + "options": "Company", + "print_hide": 1, + "remember_last_selected_value": 1, + "reqd": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "address_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address and Contact", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "address_section", + "fieldtype": "Section Break", + "label": "Address and Contact" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "supplier_address", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Supplier Address", - "length": 0, - "no_copy": 0, - "options": "Address", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "supplier_address", + "fieldtype": "Link", + "label": "Supplier Address", + "options": "Address", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_person", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact Person", - "length": 0, - "no_copy": 0, - "options": "Contact", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "contact_person", + "fieldtype": "Link", + "label": "Contact Person", + "options": "Contact", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_display", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "address_display", + "fieldtype": "Small Text", + "label": "Address", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_display", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "contact_display", + "fieldtype": "Small Text", + "in_global_search": 1, + "label": "Contact", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_mobile", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mobile No", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "contact_mobile", + "fieldtype": "Small Text", + "label": "Mobile No", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_email", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact Email", - "length": 0, - "no_copy": 0, - "options": "Email", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "contact_email", + "fieldtype": "Data", + "label": "Contact Email", + "options": "Email", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "currency_and_price_list", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency and Price List", - "length": 0, - "no_copy": 0, - "options": "fa fa-tag", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "currency_and_price_list", + "fieldtype": "Section Break", + "label": "Currency and Price List", + "options": "fa fa-tag" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency", - "length": 0, - "no_copy": 0, - "oldfieldname": "currency", - "oldfieldtype": "Select", - "options": "Currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "oldfieldname": "currency", + "oldfieldtype": "Select", + "options": "Currency", + "print_hide": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "conversion_rate", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Exchange Rate", - "length": 0, - "no_copy": 0, - "oldfieldname": "conversion_rate", - "oldfieldtype": "Currency", - "permlevel": 0, - "precision": "9", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "conversion_rate", + "fieldtype": "Float", + "label": "Exchange Rate", + "oldfieldname": "conversion_rate", + "oldfieldtype": "Currency", + "precision": "9", + "print_hide": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_price_list", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "50%", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "fieldname": "cb_price_list", + "fieldtype": "Column Break", + "print_width": "50%", "width": "50%" - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "buying_price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "options": "Price List", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "buying_price_list", - "fieldname": "price_list_currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "buying_price_list", - "fieldname": "plc_conversion_rate", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List Exchange Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "9", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ignore_pricing_rule", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Ignore Pricing Rule", - "length": 0, - "no_copy": 1, - "permlevel": 1, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "items_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-shopping-cart", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 1, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "items", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Items", - "length": 0, - "no_copy": 0, - "oldfieldname": "po_details", - "oldfieldtype": "Table", - "options": "Supplier Quotation Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.docstatus===0 && (doc.items && doc.items.length)", - "fieldname": "link_to_mrs", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Link to material requests", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "pricing_rule_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Pricing Rules", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "pricing_rules", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Pricing Rule Detail", - "length": 0, - "no_copy": 0, - "options": "Pricing Rule Detail", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_22", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_qty", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Quantity", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_net_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Net Total (Company Currency)", - "length": 0, - "no_copy": 1, - "oldfieldname": "net_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_24", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "net_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Net Total", - "length": 0, - "no_copy": 0, - "oldfieldname": "net_total_import", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_net_weight", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Net Weight", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "taxes_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes and Charges", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-money", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tax_category", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Tax Category", - "length": 0, - "no_copy": 0, - "options": "Tax Category", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_36", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "shipping_rule", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Shipping Rule", - "length": 0, - "no_copy": 0, - "options": "Shipping Rule", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_38", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "taxes_and_charges", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Purchase Taxes and Charges Template", - "length": 0, - "no_copy": 1, - "oldfieldname": "purchase_other_charges", - "oldfieldtype": "Link", - "options": "Purchase Taxes and Charges Template", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "taxes", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Purchase Taxes and Charges", - "length": 0, - "no_copy": 0, - "oldfieldname": "purchase_tax_details", - "oldfieldtype": "Table", - "options": "Purchase Taxes and Charges", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "tax_breakup", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Tax Breakup", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "other_charges_calculation", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes and Charges Calculation", - "length": 0, - "no_copy": 1, - "oldfieldtype": "HTML", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "totals", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-money", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_taxes_and_charges_added", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes and Charges Added (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "other_charges_added", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_taxes_and_charges_deducted", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes and Charges Deducted (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "other_charges_deducted", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_total_taxes_and_charges", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Taxes and Charges (Company Currency)", - "length": 0, - "no_copy": 1, - "oldfieldname": "total_tax", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_37", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "taxes_and_charges_added", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes and Charges Added", - "length": 0, - "no_copy": 0, - "oldfieldname": "other_charges_added_import", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "taxes_and_charges_deducted", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes and Charges Deducted", - "length": 0, - "no_copy": 0, - "oldfieldname": "other_charges_deducted_import", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_taxes_and_charges", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Taxes and Charges", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "discount_amount", - "columns": 0, - "fieldname": "section_break_41", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional Discount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Grand Total", - "fieldname": "apply_discount_on", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Apply Additional Discount On", - "length": 0, - "no_copy": 0, - "options": "\nGrand Total\nNet Total", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_discount_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional Discount Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_43", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "additional_discount_percentage", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional Discount Percentage", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "discount_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional Discount Amount", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_46", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_grand_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Grand Total (Company Currency)", - "length": 0, - "no_copy": 1, - "oldfieldname": "grand_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_rounding_adjustment", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rounding Adjustment (Company Currency", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "base_in_words", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "In Words (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "in_words", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_rounded_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rounded Total (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "rounded_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "grand_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Grand Total", - "length": 0, - "no_copy": 0, - "oldfieldname": "grand_total_import", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "rounding_adjustment", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rounding Adjustment", - "length": 0, - "no_copy": 1, - "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "rounded_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rounded Total", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "in_words", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "In Words", - "length": 0, - "no_copy": 0, - "oldfieldname": "in_words_import", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "disable_rounded_total", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Disable Rounded Total", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "terms", - "columns": 0, - "fieldname": "terms_section_break", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Terms and Conditions", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-legal", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tc_name", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Terms", - "length": 0, - "no_copy": 0, - "oldfieldname": "tc_name", - "oldfieldtype": "Link", - "options": "Terms and Conditions", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "terms", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Terms and Conditions", - "length": 0, - "no_copy": 0, - "oldfieldname": "terms", - "oldfieldtype": "Text Editor", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "printing_settings", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Printing Settings", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "select_print_heading", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Print Heading", - "length": 0, - "no_copy": 1, - "oldfieldname": "select_print_heading", - "oldfieldtype": "Link", - "options": "Print Heading", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "group_same_items", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Group same items", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_72", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "letter_head", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Letter Head", - "length": 0, - "no_copy": 0, - "oldfieldname": "letter_head", - "oldfieldtype": "Select", - "options": "Letter Head", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "language", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Print Language", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Auto Repeat Section", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "auto_repeat", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Auto Repeat", - "length": 0, - "no_copy": 1, - "options": "Auto Repeat", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.auto_repeat", - "fieldname": "update_auto_repeat_reference", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Update Auto Repeat Reference", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "more_info", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "More Information", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-file-text", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 1, - "oldfieldname": "status", - "oldfieldtype": "Select", - "options": "\nDraft\nSubmitted\nStopped\nCancelled", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_57", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "No", - "fieldname": "is_subcontracted", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Subcontracted", - "length": 0, - "no_copy": 0, - "options": "\nYes\nNo", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reference", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reference", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "opportunity", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Opportunity", - "length": 0, - "no_copy": 1, - "options": "Opportunity", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + }, + { + "fieldname": "buying_price_list", + "fieldtype": "Link", + "label": "Price List", + "options": "Price List", + "print_hide": 1 + }, + { + "depends_on": "buying_price_list", + "fieldname": "price_list_currency", + "fieldtype": "Link", + "label": "Price List Currency", + "options": "Currency", + "print_hide": 1, + "read_only": 1 + }, + { + "depends_on": "buying_price_list", + "fieldname": "plc_conversion_rate", + "fieldtype": "Float", + "label": "Price List Exchange Rate", + "precision": "9", + "print_hide": 1 + }, + { + "default": "0", + "fieldname": "ignore_pricing_rule", + "fieldtype": "Check", + "label": "Ignore Pricing Rule", + "no_copy": 1, + "permlevel": 1, + "print_hide": 1 + }, + { + "fieldname": "items_section", + "fieldtype": "Section Break", + "oldfieldtype": "Section Break", + "options": "fa fa-shopping-cart" + }, + { + "allow_bulk_edit": 1, + "fieldname": "items", + "fieldtype": "Table", + "label": "Items", + "oldfieldname": "po_details", + "oldfieldtype": "Table", + "options": "Supplier Quotation Item", + "reqd": 1 + }, + { + "depends_on": "eval:doc.docstatus===0 && (doc.items && doc.items.length)", + "fieldname": "link_to_mrs", + "fieldtype": "Button", + "label": "Link to material requests" + }, + { + "fieldname": "pricing_rule_details", + "fieldtype": "Section Break", + "label": "Pricing Rules" + }, + { + "fieldname": "pricing_rules", + "fieldtype": "Table", + "label": "Pricing Rule Detail", + "options": "Pricing Rule Detail", + "read_only": 1 + }, + { + "fieldname": "section_break_22", + "fieldtype": "Section Break" + }, + { + "fieldname": "total_qty", + "fieldtype": "Float", + "label": "Total Quantity", + "read_only": 1 + }, + { + "fieldname": "base_total", + "fieldtype": "Currency", + "label": "Total (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_net_total", + "fieldtype": "Currency", + "label": "Net Total (Company Currency)", + "no_copy": 1, + "oldfieldname": "net_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "column_break_24", + "fieldtype": "Column Break" + }, + { + "fieldname": "total", + "fieldtype": "Currency", + "label": "Total", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "net_total", + "fieldtype": "Currency", + "label": "Net Total", + "oldfieldname": "net_total_import", + "oldfieldtype": "Currency", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "total_net_weight", + "fieldtype": "Float", + "label": "Total Net Weight", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "taxes_section", + "fieldtype": "Section Break", + "label": "Taxes and Charges", + "oldfieldtype": "Section Break", + "options": "fa fa-money" + }, + { + "fieldname": "tax_category", + "fieldtype": "Link", + "label": "Tax Category", + "options": "Tax Category", + "print_hide": 1 + }, + { + "fieldname": "column_break_36", + "fieldtype": "Column Break" + }, + { + "fieldname": "shipping_rule", + "fieldtype": "Link", + "label": "Shipping Rule", + "options": "Shipping Rule" + }, + { + "fieldname": "section_break_38", + "fieldtype": "Section Break" + }, + { + "fieldname": "taxes_and_charges", + "fieldtype": "Link", + "label": "Purchase Taxes and Charges Template", + "no_copy": 1, + "oldfieldname": "purchase_other_charges", + "oldfieldtype": "Link", + "options": "Purchase Taxes and Charges Template", + "print_hide": 1 + }, + { + "fieldname": "taxes", + "fieldtype": "Table", + "label": "Purchase Taxes and Charges", + "oldfieldname": "purchase_tax_details", + "oldfieldtype": "Table", + "options": "Purchase Taxes and Charges" + }, + { + "collapsible": 1, + "fieldname": "tax_breakup", + "fieldtype": "Section Break", + "label": "Tax Breakup" + }, + { + "fieldname": "other_charges_calculation", + "fieldtype": "Long Text", + "label": "Taxes and Charges Calculation", + "no_copy": 1, + "oldfieldtype": "HTML", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "totals", + "fieldtype": "Section Break", + "oldfieldtype": "Section Break", + "options": "fa fa-money" + }, + { + "fieldname": "base_taxes_and_charges_added", + "fieldtype": "Currency", + "label": "Taxes and Charges Added (Company Currency)", + "oldfieldname": "other_charges_added", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_taxes_and_charges_deducted", + "fieldtype": "Currency", + "label": "Taxes and Charges Deducted (Company Currency)", + "oldfieldname": "other_charges_deducted", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_total_taxes_and_charges", + "fieldtype": "Currency", + "label": "Total Taxes and Charges (Company Currency)", + "no_copy": 1, + "oldfieldname": "total_tax", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "column_break_37", + "fieldtype": "Column Break" + }, + { + "fieldname": "taxes_and_charges_added", + "fieldtype": "Currency", + "label": "Taxes and Charges Added", + "oldfieldname": "other_charges_added_import", + "oldfieldtype": "Currency", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "taxes_and_charges_deducted", + "fieldtype": "Currency", + "label": "Taxes and Charges Deducted", + "oldfieldname": "other_charges_deducted_import", + "oldfieldtype": "Currency", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "total_taxes_and_charges", + "fieldtype": "Currency", + "label": "Total Taxes and Charges", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, + { + "collapsible": 1, + "collapsible_depends_on": "discount_amount", + "fieldname": "section_break_41", + "fieldtype": "Section Break", + "label": "Additional Discount" + }, + { + "default": "Grand Total", + "fieldname": "apply_discount_on", + "fieldtype": "Select", + "label": "Apply Additional Discount On", + "options": "\nGrand Total\nNet Total", + "print_hide": 1 + }, + { + "fieldname": "base_discount_amount", + "fieldtype": "Currency", + "label": "Additional Discount Amount (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "column_break_43", + "fieldtype": "Column Break" + }, + { + "fieldname": "additional_discount_percentage", + "fieldtype": "Float", + "label": "Additional Discount Percentage", + "print_hide": 1 + }, + { + "fieldname": "discount_amount", + "fieldtype": "Currency", + "label": "Additional Discount Amount", + "options": "currency", + "print_hide": 1 + }, + { + "fieldname": "section_break_46", + "fieldtype": "Section Break" + }, + { + "fieldname": "base_grand_total", + "fieldtype": "Currency", + "label": "Grand Total (Company Currency)", + "no_copy": 1, + "oldfieldname": "grand_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_rounding_adjustment", + "fieldtype": "Currency", + "label": "Rounding Adjustment (Company Currency", + "no_copy": 1, + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_in_words", + "fieldtype": "Data", + "label": "In Words (Company Currency)", + "oldfieldname": "in_words", + "oldfieldtype": "Data", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_rounded_total", + "fieldtype": "Currency", + "label": "Rounded Total (Company Currency)", + "oldfieldname": "rounded_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "column_break4", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break" + }, + { + "fieldname": "grand_total", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Grand Total", + "oldfieldname": "grand_total_import", + "oldfieldtype": "Currency", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "rounding_adjustment", + "fieldtype": "Currency", + "label": "Rounding Adjustment", + "no_copy": 1, + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "rounded_total", + "fieldtype": "Currency", + "label": "Rounded Total", + "read_only": 1 + }, + { + "fieldname": "in_words", + "fieldtype": "Data", + "label": "In Words", + "oldfieldname": "in_words_import", + "oldfieldtype": "Data", + "print_hide": 1, + "read_only": 1 + }, + { + "default": "0", + "fieldname": "disable_rounded_total", + "fieldtype": "Check", + "label": "Disable Rounded Total" + }, + { + "collapsible": 1, + "collapsible_depends_on": "terms", + "fieldname": "terms_section_break", + "fieldtype": "Section Break", + "label": "Terms and Conditions", + "oldfieldtype": "Section Break", + "options": "fa fa-legal" + }, + { + "fieldname": "tc_name", + "fieldtype": "Link", + "label": "Terms", + "oldfieldname": "tc_name", + "oldfieldtype": "Link", + "options": "Terms and Conditions", + "print_hide": 1 + }, + { + "fieldname": "terms", + "fieldtype": "Text Editor", + "label": "Terms and Conditions", + "oldfieldname": "terms", + "oldfieldtype": "Text Editor" + }, + { + "collapsible": 1, + "fieldname": "printing_settings", + "fieldtype": "Section Break", + "label": "Printing Settings" + }, + { + "allow_on_submit": 1, + "fieldname": "select_print_heading", + "fieldtype": "Link", + "label": "Print Heading", + "no_copy": 1, + "oldfieldname": "select_print_heading", + "oldfieldtype": "Link", + "options": "Print Heading", + "print_hide": 1, + "report_hide": 1 + }, + { + "allow_on_submit": 1, + "default": "0", + "fieldname": "group_same_items", + "fieldtype": "Check", + "label": "Group same items", + "print_hide": 1 + }, + { + "fieldname": "column_break_72", + "fieldtype": "Column Break" + }, + { + "allow_on_submit": 1, + "fieldname": "letter_head", + "fieldtype": "Link", + "label": "Letter Head", + "oldfieldname": "letter_head", + "oldfieldtype": "Select", + "options": "Letter Head", + "print_hide": 1 + }, + { + "fieldname": "language", + "fieldtype": "Data", + "label": "Print Language", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "subscription_section", + "fieldtype": "Section Break", + "label": "Auto Repeat Section" + }, + { + "fieldname": "auto_repeat", + "fieldtype": "Link", + "label": "Auto Repeat", + "no_copy": 1, + "options": "Auto Repeat", + "print_hide": 1, + "read_only": 1 + }, + { + "allow_on_submit": 1, + "depends_on": "eval: doc.auto_repeat", + "fieldname": "update_auto_repeat_reference", + "fieldtype": "Button", + "label": "Update Auto Repeat Reference" + }, + { + "collapsible": 1, + "fieldname": "more_info", + "fieldtype": "Section Break", + "label": "More Information", + "oldfieldtype": "Section Break", + "options": "fa fa-file-text" + }, + { + "fieldname": "status", + "fieldtype": "Select", + "label": "Status", + "no_copy": 1, + "oldfieldname": "status", + "oldfieldtype": "Select", + "options": "\nDraft\nSubmitted\nStopped\nCancelled", + "print_hide": 1, + "read_only": 1, + "reqd": 1, + "search_index": 1 + }, + { + "fieldname": "column_break_57", + "fieldtype": "Column Break" + }, + { + "default": "No", + "fieldname": "is_subcontracted", + "fieldtype": "Select", + "label": "Is Subcontracted", + "options": "\nYes\nNo", + "print_hide": 1 + }, + { + "fieldname": "reference", + "fieldtype": "Section Break", + "label": "Reference" + }, + { + "fieldname": "opportunity", + "fieldtype": "Link", + "label": "Opportunity", + "no_copy": 1, + "options": "Opportunity", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-shopping-cart", - "idx": 29, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "menu_index": 0, - "modified": "2019-02-13 00:52:28.602904", - "modified_by": "Administrator", - "module": "Buying", - "name": "Supplier Quotation", - "owner": "Administrator", + ], + "icon": "fa fa-shopping-cart", + "idx": 29, + "is_submittable": 1, + "links": [], + "modified": "2019-12-30 19:17:28.208693", + "modified_by": "Administrator", + "module": "Buying", + "name": "Supplier Quotation", + "owner": "Administrator", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Manufacturing Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "create": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase User", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Stock User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - }, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock User" + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 1, - "print": 0, - "read": 1, - "report": 0, - "role": "Purchase Manager", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "permlevel": 1, + "read": 1, + "role": "Purchase Manager", "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 1, - "search_fields": "status, transaction_date, supplier,grand_total", - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "timeline_field": "supplier", - "title_field": "title", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 -} + ], + "search_fields": "status, transaction_date, supplier,grand_total", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "timeline_field": "supplier", + "title_field": "title" +} \ No newline at end of file diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 64ad1b5de95..8e21927fa54 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-05-24 19:29:08", @@ -536,7 +537,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Text", + "fieldtype": "Long Text", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -927,8 +928,9 @@ "icon": "fa fa-shopping-cart", "idx": 82, "is_submittable": 1, + "links": [], "max_attachments": 1, - "modified": "2019-11-12 13:19:11.895715", + "modified": "2019-12-30 19:14:56.630270", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 0a19fada8ea..54e87f7a3b5 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-06-18 12:39:59", @@ -619,7 +620,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Text", + "fieldtype": "Long Text", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -1194,7 +1195,8 @@ "icon": "fa fa-file-text", "idx": 105, "is_submittable": 1, - "modified": "2019-10-23 14:26:42.767189", + "links": [], + "modified": "2019-12-30 19:15:28.605085", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index 3c6fb48cbf2..86200ba26b6 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-05-24 19:29:09", @@ -682,7 +683,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Text", + "fieldtype": "Long Text", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -1238,7 +1239,8 @@ "icon": "fa fa-truck", "idx": 146, "is_submittable": 1, - "modified": "2019-09-27 14:24:20.269682", + "links": [], + "modified": "2019-12-30 19:17:13.122644", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index 27cd997bcc2..63ef7ca8d82 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -616,7 +616,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Text", + "fieldtype": "Long Text", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -1059,7 +1059,7 @@ "idx": 261, "is_submittable": 1, "links": [], - "modified": "2019-12-24 12:52:17.216304", + "modified": "2019-12-30 19:12:49.709711", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", From 826989afdad79f68bdb88d7616cfff1942f3b83b Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 31 Dec 2019 13:46:39 +0530 Subject: [PATCH 062/105] fix: none type object updates AR report row (#20148) --- .../accounts/report/accounts_receivable/accounts_receivable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index c70a2cd1a74..f82146a1df8 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -285,7 +285,7 @@ class ReceivablePayableReport(object): def set_party_details(self, row): # customer / supplier name - party_details = self.get_party_details(row.party) + party_details = self.get_party_details(row.party) or {} row.update(party_details) if self.filters.get(scrub(self.filters.party_type)): row.currency = row.account_currency From 25fd2743a8758afd2ea66daddcc1f1cacf654df6 Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 31 Dec 2019 13:55:34 +0530 Subject: [PATCH 063/105] fix: party account currency not fetched from account for SO (#20147) --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 9530fc9556b..214d6088667 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -911,7 +911,10 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= else: party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company) - party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account) + if dt not in ("Sales Invoice", "Purchase Invoice"): + party_account_currency = get_account_currency(party_account) + else: + party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account) # payment type if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees") and doc.outstanding_amount > 0)) \ From fd68a682cae1afa94b60b41269385477d77e123b Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Tue, 31 Dec 2019 14:01:22 +0530 Subject: [PATCH 064/105] fix(refactor): loan in HRMS (#20023) * fix: update laon on salary slip submission and Cancelation * fix(refactor): Loan in HRMS * fix: Changes requested * Update loan.py Co-authored-by: Nabin Hait --- .../doctype/journal_entry/journal_entry.py | 5 +- erpnext/hr/doctype/loan/loan.json | 1414 +++-------------- erpnext/hr/doctype/loan/loan.py | 77 +- erpnext/hr/doctype/salary_slip/salary_slip.py | 16 +- 4 files changed, 319 insertions(+), 1193 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 88973373ed7..428b9acd150 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -9,7 +9,6 @@ from erpnext.controllers.accounts_controller import AccountsController from erpnext.accounts.utils import get_balance_on, get_account_currency from erpnext.accounts.party import get_party_account from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount -from erpnext.hr.doctype.loan.loan import update_disbursement_status, update_total_amount_paid from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting from six import string_types, iteritems @@ -606,8 +605,8 @@ class JournalEntry(AccountsController): for d in self.accounts: if d.reference_type=="Loan" and flt(d.debit) > 0: doc = frappe.get_doc("Loan", d.reference_name) - update_disbursement_status(doc) - update_total_amount_paid(doc) + doc.update_total_amount_paid() + doc.set_status() def validate_expense_claim(self): for d in self.accounts: diff --git a/erpnext/hr/doctype/loan/loan.json b/erpnext/hr/doctype/loan/loan.json index 505b601edd5..74abdc215b7 100644 --- a/erpnext/hr/doctype/loan/loan.json +++ b/erpnext/hr/doctype/loan/loan.json @@ -1,1200 +1,298 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "ACC-LOAN-.YYYY.-.#####", - "beta": 0, - "creation": "2016-12-02 10:11:49.673604", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "allow_import": 1, + "autoname": "ACC-LOAN-.YYYY.-.#####", + "creation": "2016-12-02 10:11:49.673604", + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "applicant_type", + "applicant", + "applicant_name", + "loan_application", + "loan_type", + "column_break_3", + "posting_date", + "company", + "status", + "repay_from_salary", + "section_break_8", + "loan_amount", + "rate_of_interest", + "disbursement_date", + "repayment_start_date", + "column_break_11", + "repayment_method", + "repayment_periods", + "monthly_repayment_amount", + "account_info", + "mode_of_payment", + "payment_account", + "column_break_9", + "loan_account", + "interest_income_account", + "section_break_15", + "repayment_schedule", + "section_break_17", + "total_payment", + "column_break_19", + "total_interest_payable", + "total_amount_paid", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "applicant_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Applicant Type", - "length": 0, - "no_copy": 0, - "options": "Employee\nMember", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "applicant_type", + "fieldtype": "Select", + "label": "Applicant Type", + "options": "Employee\nMember", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "applicant", - "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Applicant", - "length": 0, - "no_copy": 0, - "options": "applicant_type", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "applicant", + "fieldtype": "Dynamic Link", + "in_standard_filter": 1, + "label": "Applicant", + "options": "applicant_type", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "applicant_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Applicant Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "applicant_name", + "fieldtype": "Data", + "in_global_search": 1, + "label": "Applicant Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "loan_application", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Loan Application", - "length": 0, - "no_copy": 0, - "options": "Loan Application", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "loan_application", + "fieldtype": "Link", + "label": "Loan Application", + "options": "Loan Application" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "loan_type", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Loan Type", - "length": 0, - "no_copy": 0, - "options": "Loan Type", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "loan_type", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Loan Type", + "options": "Loan Type", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fetch_if_empty": 0, - "fieldname": "posting_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Posting Date", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Today", + "fieldname": "posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Posting Date", + "no_copy": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "remember_last_selected_value": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Sanctioned", - "fetch_if_empty": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 1, - "options": "Sanctioned\nDisbursed\nRepaid/Closed", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Draft", + "fieldname": "status", + "fieldtype": "Select", + "label": "Status", + "no_copy": 1, + "options": "Draft\nSanctioned\nDisbursed\nRepaid/Closed", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.applicant_type==\"Employee\"", - "fetch_if_empty": 0, - "fieldname": "repay_from_salary", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Repay from Salary", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "depends_on": "eval:doc.applicant_type==\"Employee\"", + "fieldname": "repay_from_salary", + "fieldtype": "Check", + "label": "Repay from Salary" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "section_break_8", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Loan Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_8", + "fieldtype": "Section Break", + "label": "Loan Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "loan_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Loan Amount", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "loan_amount", + "fieldtype": "Currency", + "label": "Loan Amount", + "options": "Company:company:default_currency", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_from": "loan_type.rate_of_interest", - "fetch_if_empty": 0, - "fieldname": "rate_of_interest", - "fieldtype": "Percent", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rate of Interest (%) / Year", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "loan_type.rate_of_interest", + "fieldname": "rate_of_interest", + "fieldtype": "Percent", + "label": "Rate of Interest (%) / Year", + "read_only": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.status==\"Disbursed\"", - "fetch_if_empty": 0, - "fieldname": "disbursement_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Disbursement Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.status==\"Disbursed\"", + "fieldname": "disbursement_date", + "fieldtype": "Date", + "label": "Disbursement Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "repayment_start_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Repayment Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "repayment_start_date", + "fieldtype": "Date", + "label": "Repayment Start Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_11", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Repay Over Number of Periods", - "fetch_if_empty": 0, - "fieldname": "repayment_method", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Repayment Method", - "length": 0, - "no_copy": 0, - "options": "\nRepay Fixed Amount per Period\nRepay Over Number of Periods", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Repay Over Number of Periods", + "fieldname": "repayment_method", + "fieldtype": "Select", + "label": "Repayment Method", + "options": "\nRepay Fixed Amount per Period\nRepay Over Number of Periods", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "depends_on": "", - "fetch_if_empty": 0, - "fieldname": "repayment_periods", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Repayment Period in Months", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "repayment_periods", + "fieldtype": "Int", + "label": "Repayment Period in Months" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "depends_on": "", - "fetch_if_empty": 0, - "fieldname": "monthly_repayment_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Monthly Repayment Amount", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "monthly_repayment_amount", + "fieldtype": "Currency", + "label": "Monthly Repayment Amount", + "options": "Company:company:default_currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "account_info", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Account Info", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "account_info", + "fieldtype": "Section Break", + "label": "Account Info" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "mode_of_payment", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "label": "Mode of Payment", + "options": "Mode of Payment", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "payment_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_account", + "fieldtype": "Link", + "label": "Payment Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_9", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_9", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "loan_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Loan Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "loan_account", + "fieldtype": "Link", + "label": "Loan Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "interest_income_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Interest Income Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "interest_income_account", + "fieldtype": "Link", + "label": "Interest Income Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "section_break_15", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Repayment Schedule", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_15", + "fieldtype": "Section Break", + "label": "Repayment Schedule" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "repayment_schedule", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Repayment Schedule", - "length": 0, - "no_copy": 1, - "options": "Repayment Schedule", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "repayment_schedule", + "fieldtype": "Table", + "label": "Repayment Schedule", + "no_copy": 1, + "options": "Repayment Schedule" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "section_break_17", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Totals", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_17", + "fieldtype": "Section Break", + "label": "Totals" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fetch_if_empty": 0, - "fieldname": "total_payment", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Payment", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "total_payment", + "fieldtype": "Currency", + "label": "Total Payment", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_19", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_19", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fetch_if_empty": 0, - "fieldname": "total_interest_payable", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Interest Payable", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "total_interest_payable", + "fieldtype": "Currency", + "label": "Total Interest Payable", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "total_amount_paid", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Amount Paid", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "total_amount_paid", + "fieldtype": "Currency", + "label": "Total Amount Paid", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Loan", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Loan", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-07-10 13:04:20.953694", - "modified_by": "Administrator", - "module": "HR", - "name": "Loan", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "links": [], + "modified": "2019-12-25 17:59:58.122823", + "modified_by": "Administrator", + "module": "HR", + "name": "Loan", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Employee", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 + "read": 1, + "role": "Employee" } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "posting_date", - "show_name_in_global_search": 0, - "sort_field": "creation", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "search_fields": "posting_date", + "sort_field": "creation", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/hr/doctype/loan/loan.py b/erpnext/hr/doctype/loan/loan.py index a803863124d..ffe71ef3c8c 100644 --- a/erpnext/hr/doctype/loan/loan.py +++ b/erpnext/hr/doctype/loan/loan.py @@ -16,6 +16,7 @@ class Loan(AccountsController): self.make_repayment_schedule() self.set_repayment_period() self.calculate_totals() + self.set_status(from_validate=True) def set_missing_fields(self): if not self.company: @@ -95,43 +96,57 @@ class Loan(AccountsController): self.total_payment = 0 self.total_interest_payable = 0 self.total_amount_paid = 0 - for data in self.repayment_schedule: - self.total_payment += data.total_payment - self.total_interest_payable +=data.interest_amount - if data.paid: - self.total_amount_paid += data.total_payment + for schedule in self.repayment_schedule: + self.total_payment += schedule.total_payment + self.total_interest_payable +=schedule.interest_amount + if schedule.paid: + self.total_amount_paid += schedule.total_payment -def update_total_amount_paid(doc): - total_amount_paid = 0 - for data in doc.repayment_schedule: - if data.paid: - total_amount_paid += data.total_payment - frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid) + def update_total_amount_paid(self): + total_amount_paid = 0 + for schedule in self.repayment_schedule: + if schedule.paid: + total_amount_paid += schedule.total_payment + frappe.db.set_value("Loan", self.name, "total_amount_paid", total_amount_paid) -def update_disbursement_status(doc): - disbursement = frappe.db.sql(""" - select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount - from `tabGL Entry` - where account = %s and against_voucher_type = 'Loan' and against_voucher = %s - """, (doc.payment_account, doc.name), as_dict=1)[0] + def set_status(self, from_validate=False): + disbursement = self.get_disbursement_entry() + disbursement_date = None - disbursement_date = None - if not disbursement or disbursement.disbursed_amount == 0: - status = "Sanctioned" - elif disbursement.disbursed_amount == doc.loan_amount: - disbursement_date = disbursement.posting_date - status = "Disbursed" - elif disbursement.disbursed_amount > doc.loan_amount: - frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount)) + self.status = "Draft" - if status == 'Disbursed' and getdate(disbursement_date) > getdate(frappe.db.get_value("Loan", doc.name, "repayment_start_date")): + if (not disbursement or disbursement.disbursed_amount == 0) and self.docstatus == 1: + self.status = "Sanctioned" + if disbursement: + self.validate_disbursed_amount_and_loan_amount(disbursement.disbursed_amount) + if disbursement.disbursed_amount == self.loan_amount and disbursement.disbursed_amount != 0: + self.status = "Disbursed" + disbursement_date = disbursement.posting_date + self.validate_disbursement_date(disbursement_date, self.status) + + if self.total_amount_paid == self.total_payment: + self.status = "Repaid/Closed" + + if not from_validate: + frappe.db.set_value("Loan", self.name, "status", self.status) + if disbursement_date: + frappe.db.set_value("Loan", self.name, "disbursement_date", disbursement_date) + + def validate_disbursement_date(self, disbursement_date, loan_status): + if loan_status == 'Disbursed' and getdate(disbursement_date) > getdate(frappe.db.get_value("Loan", self.name, "repayment_start_date")): frappe.throw(_("Disbursement Date cannot be after Loan Repayment Start Date")) - frappe.db.sql(""" - update `tabLoan` - set status = %s, disbursement_date = %s - where name = %s - """, (status, disbursement_date, doc.name)) + + def validate_disbursed_amount_and_loan_amount(self, disbursed_amount): + if disbursed_amount > self.loan_amount: + frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(self.loan_amount)) + + def get_disbursement_entry(self): + return frappe.db.sql(""" + select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount + from `tabGL Entry` + where account = %s and against_voucher_type = 'Loan' and against_voucher = %s + """, (self.payment_account, self.name), as_dict=1)[0] def validate_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods): if repayment_method == "Repay Over Number of Periods" and not repayment_periods: diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 46be4fe2873..8064539166b 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -62,6 +62,7 @@ class SalarySlip(TransactionBase): if self.net_pay < 0: frappe.throw(_("Net Pay cannot be less than 0")) else: + self.update_loans() self.set_status() self.update_status(self.name) self.update_salary_slip_in_additional_salary() @@ -69,6 +70,7 @@ class SalarySlip(TransactionBase): self.email_salary_slip() def on_cancel(self): + self.update_loans() self.set_status() self.update_status() self.update_salary_slip_in_additional_salary() @@ -764,7 +766,8 @@ class SalarySlip(TransactionBase): self.total_principal_amount += loan.principal_amount def get_loan_details(self): - return frappe.db.sql("""select rps.principal_amount, rps.interest_amount, l.name, + return frappe.db.sql("""select rps.principal_amount, + rps.name as repayment_name, rps.interest_amount, l.name, rps.total_payment, l.loan_account, l.interest_income_account from `tabRepayment Schedule` as rps, `tabLoan` as l @@ -815,6 +818,17 @@ class SalarySlip(TransactionBase): timesheet.set_status() timesheet.save() + def update_loans(self): + for loan in self.get_loan_details(): + doc = frappe.get_doc("Loan", loan.name) + + #setting repayment schedule and updating total amount to pay + repayment_status = 1 if doc.docstatus == 1 else 0 + frappe.db.set_value("Repayment Schedule", loan.repayment_name, "paid", repayment_status) + doc.reload() + doc.update_total_amount_paid() + doc.set_status() + def set_status(self, status=None): '''Get and update status''' if not status: From 8f6a6e8d2a7fa4f1c71731f363736812fb60e38a Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Tue, 31 Dec 2019 14:34:09 +0530 Subject: [PATCH 065/105] feat: added provision to disable rounded total for salary slips --- erpnext/hr/doctype/hr_settings/hr_settings.json | 12 +++++++++++- erpnext/hr/doctype/hr_settings/hr_settings.py | 11 +++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json index a41c887852e..6cb0e211f94 100644 --- a/erpnext/hr/doctype/hr_settings/hr_settings.json +++ b/erpnext/hr/doctype/hr_settings/hr_settings.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2013-08-02 13:45:23", "doctype": "DocType", "document_type": "Other", @@ -13,6 +14,7 @@ "expense_approver_mandatory_in_expense_claim", "payroll_settings", "include_holidays_in_total_working_days", + "disable_rounded_total", "max_working_hours_against_timesheet", "column_break_11", "email_salary_slip_to_employee", @@ -160,12 +162,20 @@ "fieldname": "auto_leave_encashment", "fieldtype": "Check", "label": "Auto Leave Encashment" + }, + { + "default": "0", + "description": "If checked, hides and disables Rounded Total field in Salary Slips", + "fieldname": "disable_rounded_total", + "fieldtype": "Check", + "label": "Disable Rounded Total" } ], "icon": "fa fa-cog", "idx": 1, "issingle": 1, - "modified": "2019-08-05 13:07:17.993968", + "links": [], + "modified": "2019-12-31 14:28:32.004121", "modified_by": "Administrator", "module": "HR", "name": "HR Settings", diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.py b/erpnext/hr/doctype/hr_settings/hr_settings.py index 2ee1b7bdda5..bf919067cae 100644 --- a/erpnext/hr/doctype/hr_settings/hr_settings.py +++ b/erpnext/hr/doctype/hr_settings/hr_settings.py @@ -7,6 +7,8 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document +from frappe.utils import cint +from frappe.custom.doctype.property_setter.property_setter import make_property_setter class HRSettings(Document): def validate(self): @@ -22,3 +24,12 @@ class HRSettings(Document): if self.email_salary_slip_to_employee and self.encrypt_salary_slips_in_emails: if not self.password_policy: frappe.throw(_("Password policy for Salary Slips is not set")) + + def on_update(self): + self.toggle_rounded_total() + frappe.clear_cache() + + def toggle_rounded_total(self): + self.disable_rounded_total = cint(self.disable_rounded_total) + make_property_setter("Salary Slip", "rounded_total", "hidden", self.disable_rounded_total, "Check") + make_property_setter("Salary Slip", "rounded_total", "print_hide", self.disable_rounded_total, "Check") From cd2899f4293eeab1c374cd62f556ababee60b314 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Tue, 31 Dec 2019 14:34:09 +0530 Subject: [PATCH 066/105] feat: added provision to disable rounded total for salary slips --- erpnext/hr/doctype/salary_slip/salary_slip.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 46be4fe2873..555f74c64aa 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -50,7 +50,8 @@ class SalarySlip(TransactionBase): self.calculate_net_pay() company_currency = erpnext.get_company_currency(self.company) - self.total_in_words = money_in_words(self.rounded_total, company_currency) + total = self.net_pay if self.is_rounding_total_disabled() else self.rounded_total + self.total_in_words = money_in_words(total, company_currency) if frappe.db.get_single_value("HR Settings", "max_working_hours_against_timesheet"): max_working_hours = frappe.db.get_single_value("HR Settings", "max_working_hours_against_timesheet") @@ -90,6 +91,9 @@ class SalarySlip(TransactionBase): if date_diff(self.end_date, self.start_date) < 0: frappe.throw(_("To date cannot be before From date")) + def is_rounding_total_disabled(self): + return cint(frappe.db.get_single_value("HR Settings", "disable_rounded_total")) + def check_existing(self): if not self.salary_slip_based_on_timesheet: ret_exist = frappe.db.sql("""select name from `tabSalary Slip` From adb35d87034018f0aa0291d0a7c5c73480d817d1 Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 31 Dec 2019 17:20:07 +0530 Subject: [PATCH 067/105] fix: don't show transfer button if already items are supplied (#20155) --- erpnext/buying/doctype/purchase_order/purchase_order.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 7b5e5c5cca0..7b1f1354d79 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -134,7 +134,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( if (doc.status != "On Hold") { if(flt(doc.per_received, 2) < 100 && allow_receipt) { cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create')); - if(doc.is_subcontracted==="Yes") { + if(doc.is_subcontracted==="Yes" && me.has_unsupplied_items()) { cur_frm.add_custom_button(__('Material to Supplier'), function() { me.make_stock_entry(); }, __("Transfer")); } @@ -191,6 +191,10 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( set_schedule_date(this.frm); }, + has_unsupplied_items: function() { + return this.frm.doc['supplied_items'].some(item => item.required_qty != item.supplied_qty) + }, + make_stock_entry: function() { var items = $.map(cur_frm.doc.items, function(d) { return d.bom ? d.item_code : false; }); var me = this; @@ -267,7 +271,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( if (me.frm.doc['supplied_items']) { me.frm.doc['supplied_items'].forEach((item, index) => { - if (item.rm_item_code && item.main_item_code) { + if (item.rm_item_code && item.main_item_code && item.required_qty - item.supplied_qty != 0) { me.raw_material_data.push ({ 'name':item.name, 'item_code': item.main_item_code, From a5e56dfb6fadccfe995b52ca63d14ff0577763b7 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Tue, 31 Dec 2019 17:23:25 +0530 Subject: [PATCH 068/105] fix: set currency to company default currency (#20158) --- .../salary_structure/salary_structure.json | 1209 ++++------------- .../salary_structure_assignment.json | 644 ++------- 2 files changed, 386 insertions(+), 1467 deletions(-) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.json b/erpnext/hr/doctype/salary_structure/salary_structure.json index 0e47278a3e1..fe71d0dc1a1 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.json +++ b/erpnext/hr/doctype/salary_structure/salary_structure.json @@ -1,1010 +1,283 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "Prompt", - "beta": 0, - "creation": "2013-03-07 18:50:29", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 0, + "actions": [], + "allow_import": 1, + "allow_rename": 1, + "autoname": "Prompt", + "creation": "2013-03-07 18:50:29", + "doctype": "DocType", + "document_type": "Document", + "engine": "InnoDB", + "field_order": [ + "company", + "letter_head", + "column_break1", + "is_active", + "payroll_frequency", + "is_default", + "time_sheet_earning_detail", + "salary_slip_based_on_timesheet", + "column_break_17", + "salary_component", + "hour_rate", + "leave_encashment_amount_per_day", + "max_benefits", + "earning_deduction", + "earning", + "earnings", + "deduction", + "deductions", + "net_pay_detail", + "column_break2", + "total_earning", + "total_deduction", + "net_pay", + "account", + "mode_of_payment", + "column_break_28", + "payment_account", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "remember_last_selected_value": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "letter_head", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Letter Head", - "length": 0, - "no_copy": 0, - "options": "Letter Head", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "letter_head", + "fieldtype": "Link", + "label": "Letter Head", + "options": "Letter Head" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "fieldname": "column_break1", + "fieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Yes", - "fieldname": "is_active", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Is Active", - "length": 0, - "no_copy": 0, - "oldfieldname": "is_active", - "oldfieldtype": "Select", - "options": "\nYes\nNo", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Yes", + "fieldname": "is_active", + "fieldtype": "Select", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Is Active", + "oldfieldname": "is_active", + "oldfieldtype": "Select", + "options": "\nYes\nNo", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Monthly", - "depends_on": "eval:(!doc.salary_slip_based_on_timesheet)", - "fieldname": "payroll_frequency", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payroll Frequency", - "length": 0, - "no_copy": 0, - "options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Monthly", + "depends_on": "eval:(!doc.salary_slip_based_on_timesheet)", + "fieldname": "payroll_frequency", + "fieldtype": "Select", + "label": "Payroll Frequency", + "options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "No", - "fieldname": "is_default", - "fieldtype": "Select", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Default", - "length": 0, - "no_copy": 1, - "options": "Yes\nNo", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "No", + "fieldname": "is_default", + "fieldtype": "Select", + "hidden": 1, + "label": "Is Default", + "no_copy": 1, + "options": "Yes\nNo", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "time_sheet_earning_detail", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "time_sheet_earning_detail", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "salary_slip_based_on_timesheet", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Salary Slip Based on Timesheet", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "salary_slip_based_on_timesheet", + "fieldtype": "Check", + "label": "Salary Slip Based on Timesheet" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_17", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_17", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "description": "Salary Component for timesheet based payroll.", - "fieldname": "salary_component", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Salary Component", - "length": 0, - "no_copy": 0, - "options": "Salary Component", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "description": "Salary Component for timesheet based payroll.", + "fieldname": "salary_component", + "fieldtype": "Link", + "label": "Salary Component", + "options": "Salary Component" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "hour_rate", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Hour Rate", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "hour_rate", + "fieldtype": "Currency", + "label": "Hour Rate", + "options": "Company:company:default_currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "leave_encashment_amount_per_day", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Leave Encashment Amount Per Day", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "leave_encashment_amount_per_day", + "fieldtype": "Currency", + "label": "Leave Encashment Amount Per Day", + "options": "Company:company:default_currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "max_benefits", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Max Benefits (Amount)", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "max_benefits", + "fieldtype": "Currency", + "label": "Max Benefits (Amount)", + "options": "Company:company:default_currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "description": "Salary breakup based on Earning and Deduction.", - "fieldname": "earning_deduction", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "oldfieldname": "earning_deduction", - "oldfieldtype": "Section Break", - "permlevel": 0, - "precision": "2", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "description": "Salary breakup based on Earning and Deduction.", + "fieldname": "earning_deduction", + "fieldtype": "Section Break", + "oldfieldname": "earning_deduction", + "oldfieldtype": "Section Break", + "precision": "2" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "earning", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Earning", - "length": 0, - "no_copy": 0, - "oldfieldname": "col_brk2", - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "fieldname": "earning", + "fieldtype": "Section Break", + "label": "Earning", + "oldfieldname": "col_brk2", + "oldfieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "earnings", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Earnings", - "length": 0, - "no_copy": 0, - "oldfieldname": "earning_details", - "oldfieldtype": "Table", - "options": "Salary Detail", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "earnings", + "fieldtype": "Table", + "label": "Earnings", + "oldfieldname": "earning_details", + "oldfieldtype": "Table", + "options": "Salary Detail" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "deduction", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Deduction", - "length": 0, - "no_copy": 0, - "oldfieldname": "col_brk3", - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "fieldname": "deduction", + "fieldtype": "Section Break", + "label": "Deduction", + "oldfieldname": "col_brk3", + "oldfieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "deductions", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Deductions", - "length": 0, - "no_copy": 0, - "oldfieldname": "deduction_details", - "oldfieldtype": "Table", - "options": "Salary Detail", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "deductions", + "fieldtype": "Table", + "label": "Deductions", + "oldfieldname": "deduction_details", + "oldfieldtype": "Table", + "options": "Salary Detail" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "net_pay_detail", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "options": "Simple", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "net_pay_detail", + "fieldtype": "Section Break", + "options": "Simple" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "fieldname": "column_break2", + "fieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_earning", - "fieldtype": "Currency", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Earning", - "length": 0, - "no_copy": 0, - "oldfieldname": "total_earning", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "total_earning", + "fieldtype": "Currency", + "hidden": 1, + "label": "Total Earning", + "oldfieldname": "total_earning", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_deduction", - "fieldtype": "Currency", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Total Deduction", - "length": 0, - "no_copy": 0, - "oldfieldname": "total_deduction", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "total_deduction", + "fieldtype": "Currency", + "hidden": 1, + "label": "Total Deduction", + "oldfieldname": "total_deduction", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "net_pay", - "fieldtype": "Currency", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Net Pay", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "net_pay", + "fieldtype": "Currency", + "hidden": 1, + "label": "Net Pay", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "account", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Account", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "account", + "fieldtype": "Section Break", + "label": "Account" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "mode_of_payment", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "label": "Mode of Payment", + "options": "Mode of Payment" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_28", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_28", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_account", + "fieldtype": "Link", + "label": "Payment Account", + "options": "Account" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Salary Structure", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Salary Structure", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-file-text", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-02-18 18:51:53.932518", - "modified_by": "Administrator", - "module": "HR", - "name": "Salary Structure", - "owner": "Administrator", + ], + "icon": "fa fa-file-text", + "idx": 1, + "is_submittable": 1, + "links": [], + "modified": "2019-12-31 17:05:14.118507", + "modified_by": "Administrator", + "module": "HR", + "name": "Salary Structure", + "owner": "Administrator", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR User", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "timeline_field": "", - "title_field": "", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + ], + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC" } \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json index 55e2df950b7..136eb0f8053 100644 --- a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json +++ b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json @@ -1,524 +1,170 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "HR-SSA-.YY.-.MM.-.#####", - "beta": 0, - "creation": "2018-04-13 16:38:41.769237", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "allow_import": 1, + "autoname": "HR-SSA-.YY.-.MM.-.#####", + "creation": "2018-04-13 16:38:41.769237", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "employee", + "employee_name", + "department", + "designation", + "column_break_6", + "salary_structure", + "from_date", + "company", + "section_break_7", + "base", + "column_break_9", + "variable", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "employee", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Employee", - "length": 0, - "no_copy": 0, - "options": "Employee", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "employee", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Employee", + "options": "Employee", + "reqd": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.employee_name", - "fieldname": "employee_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Employee Name", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "employee.employee_name", + "fieldname": "employee_name", + "fieldtype": "Data", + "label": "Employee Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.department", - "fieldname": "department", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Department", - "length": 0, - "no_copy": 0, - "options": "Department", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "employee.department", + "fieldname": "department", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Department", + "options": "Department", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.designation", - "fieldname": "designation", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Designation", - "length": 0, - "no_copy": 0, - "options": "Designation", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "employee.designation", + "fieldname": "designation", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Designation", + "options": "Designation", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_6", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "salary_structure", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Salary Structure", - "length": 0, - "no_copy": 0, - "options": "Salary Structure", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "salary_structure", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Salary Structure", + "options": "Salary Structure", + "reqd": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "from_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "From Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "from_date", + "fieldtype": "Date", + "label": "From Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "read_only": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_7", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_7", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Base", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "base", + "fieldtype": "Currency", + "label": "Base", + "options": "Company:company:default_currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_9", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_9", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "variable", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Variable", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "variable", + "fieldtype": "Currency", + "label": "Variable", + "options": "Company:company:default_currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Salary Structure Assignment", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Salary Structure Assignment", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-08-21 16:15:48.755450", - "modified_by": "Administrator", - "module": "HR", - "name": "Salary Structure Assignment", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "links": [], + "modified": "2019-12-31 17:05:28.637510", + "modified_by": "Administrator", + "module": "HR", + "name": "Salary Structure Assignment", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "create": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR User", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "employee_name", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "employee_name", + "track_changes": 1 } \ No newline at end of file From c5cd7cd65d617a95a53e298e105c11f8d5491f0a Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 31 Dec 2019 19:15:48 +0530 Subject: [PATCH 069/105] =?UTF-8?q?fix(Subscription):=20pass=20start=5Fdat?= =?UTF-8?q?e=20while=20computing=20next=5Fschedu=E2=80=A6=20(#20160)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- erpnext/selling/doctype/sales_order/sales_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 2112a4174b1..978dd29aebe 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -420,7 +420,7 @@ class SalesOrder(SellingController): def _get_delivery_date(ref_doc_delivery_date, red_doc_transaction_date, transaction_date): delivery_date = get_next_schedule_date(ref_doc_delivery_date, - auto_repeat_doc.frequency, cint(auto_repeat_doc.repeat_on_day)) + auto_repeat_doc.frequency, auto_repeat_doc.start_date, cint(auto_repeat_doc.repeat_on_day)) if delivery_date <= transaction_date: delivery_date_diff = frappe.utils.date_diff(ref_doc_delivery_date, red_doc_transaction_date) From f4589da80663a89b307bbab1b8a693bd692a459c Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 2 Jan 2020 12:22:04 +0530 Subject: [PATCH 070/105] fix: Show closing row in general ledger print --- erpnext/accounts/report/general_ledger/general_ledger.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html index 17da3b915f8..40469aecc1d 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.html +++ b/erpnext/accounts/report/general_ledger/general_ledger.html @@ -33,7 +33,7 @@ - {% for(var i=0, l=data.length-1; i {% if(data[i].posting_date) { %} {%= frappe.datetime.str_to_user(data[i].posting_date) %} From b6351b4ca07b5eeec39b0a3171d4ca88e1cc8e79 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 2 Jan 2020 17:29:50 +0530 Subject: [PATCH 071/105] fix: ignore pricing rule for other item group --- erpnext/accounts/doctype/pricing_rule/utils.py | 2 +- erpnext/public/js/controllers/transaction.js | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 87f68225fe5..fe68fdb6c0f 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -495,7 +495,7 @@ def get_pricing_rule_items(pr_doc): if pr_doc.apply_rule_on_other: apply_on = frappe.scrub(pr_doc.apply_rule_on_other) - apply_on_data.append(pr_doc.get(apply_on)) + apply_on_data.append(pr_doc.get("other_" + apply_on)) return list(set(apply_on_data)) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 1c330be5ee6..e8155af4d6f 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1398,7 +1398,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ remove_pricing_rule: function(item) { let me = this; - const fields = ["discount_percentage", "discount_amount", "pricing_rules"]; + const fields = ["discount_percentage", + "discount_amount", "margin_rate_or_amount", "rate_with_margin"]; if(item.remove_free_item) { var items = []; @@ -1418,6 +1419,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ fields.forEach(f => { row[f] = 0; }); + + ["pricing_rules", "margin_type"].forEach(field => { + if (row[field]) { + row[field] = ''; + } + }) } }); From 255361ba9274281191cfcf037b556dd60fa3cabf Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 2 Jan 2020 19:00:32 +0530 Subject: [PATCH 072/105] fix: Get outgoing rate of serial no from SLE if serial no already transferred to another company --- erpnext/stock/stock_ledger.py | 37 +++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 69a4b94b4ea..b100f453273 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -212,7 +212,7 @@ class update_entries_after(object): def get_serialized_values(self, sle): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) - serial_no = cstr(sle.serial_no).split("\n") + serial_nos = cstr(sle.serial_no).split("\n") if incoming_rate < 0: # wrong incoming rate @@ -224,9 +224,8 @@ class update_entries_after(object): elif actual_qty < 0: # In case of delivery/stock issue, get average purchase rate # of serial nos of current entry - stock_value_change = -1 * flt(frappe.get_all("Serial No", - fields=["sum(purchase_rate)"], - filters = {'name': ('in', serial_no)}, as_list=1)[0][0]) + outgoing_value = self.get_incoming_value_for_serial_nos(sle, serial_nos) + stock_value_change = -1 * outgoing_value new_stock_qty = self.qty_after_transaction + actual_qty @@ -244,6 +243,36 @@ class update_entries_after(object): sle.voucher_type, sle.voucher_no, self.allow_zero_rate, currency=erpnext.get_company_currency(sle.company)) + def get_incoming_value_for_serial_nos(self, sle, serial_nos): + # get rate from serial nos within same company + all_serial_nos = frappe.get_all("Serial No", + fields=["purchase_rate", "name", "company"], + filters = {'name': ('in', serial_nos)}) + + incoming_values = sum([flt(d.purchase_rate) for d in all_serial_nos if d.company==sle.company]) + + # Get rate for serial nos which has been transferred to other company + invalid_serial_nos = [d.name for d in all_serial_nos if d.company!=sle.company] + for serial_no in invalid_serial_nos: + incoming_rate = frappe.db.sql(""" + select incoming_rate + from `tabStock Ledger Entry` + where + company = %s + and actual_qty > 0 + and (serial_no = %s + or serial_no like %s + or serial_no like %s + or serial_no like %s + ) + order by posting_date desc + limit 1 + """, (sle.company, serial_no, serial_no+'\n%', '%\n'+serial_no, '%\n'+serial_no+'\n%')) + + incoming_values += flt(incoming_rate[0][0]) if incoming_rate else 0 + + return incoming_values + def get_moving_average_values(self, sle): actual_qty = flt(sle.actual_qty) new_stock_qty = flt(self.qty_after_transaction) + actual_qty From 81e2f2a45fd81e836fe0cdcb6acaaa3259162d33 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Thu, 2 Jan 2020 19:14:55 +0530 Subject: [PATCH 073/105] ux: add description for minimum purchase qty --- erpnext/stock/doctype/item/item.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index af8e13288a9..3503e7cc1c5 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_guest_to_view": 1, "allow_import": 1, "allow_rename": 1, @@ -569,6 +570,7 @@ { "default": "0.00", "depends_on": "is_stock_item", + "description": "Minimum quantity should be as per Stock UOM", "fieldname": "min_order_qty", "fieldtype": "Float", "label": "Minimum Order Qty", @@ -1041,8 +1043,9 @@ "icon": "fa fa-tag", "idx": 2, "image_field": "image", + "links": [], "max_attachments": 1, - "modified": "2019-12-13 12:15:56.197246", + "modified": "2020-01-02 19:13:59.295963", "modified_by": "Administrator", "module": "Stock", "name": "Item", From 9e0d9aa947ea8f3ab6a05da9658d83e99bef3fd4 Mon Sep 17 00:00:00 2001 From: Rohan Date: Tue, 31 Dec 2019 17:21:07 +0530 Subject: [PATCH 074/105] feat: show item name in Item Price list view (#20156) --- .../stock/doctype/item_price/item_price.json | 1164 ++++------------- 1 file changed, 220 insertions(+), 944 deletions(-) diff --git a/erpnext/stock/doctype/item_price/item_price.json b/erpnext/stock/doctype/item_price/item_price.json index 9e29ad08ee3..8456b584ca0 100644 --- a/erpnext/stock/doctype/item_price/item_price.json +++ b/erpnext/stock/doctype/item_price/item_price.json @@ -1,981 +1,257 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "", - "beta": 0, - "creation": "2013-05-02 16:29:48", - "custom": 0, - "description": "Multiple Item prices.", - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, - "engine": "InnoDB", + "actions": [], + "allow_import": 1, + "creation": "2013-05-02 16:29:48", + "description": "Multiple Item prices.", + "doctype": "DocType", + "document_type": "Setup", + "engine": "InnoDB", + "field_order": [ + "item_code", + "uom", + "packing_unit", + "min_qty", + "column_break_17", + "item_name", + "brand", + "item_description", + "price_list_details", + "price_list", + "customer", + "supplier", + "column_break_3", + "buying", + "selling", + "item_details", + "currency", + "col_br_1", + "price_list_rate", + "section_break_15", + "valid_from", + "lead_time_days", + "column_break_18", + "valid_upto", + "section_break_24", + "note", + "reference" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "item_code", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Item Code", - "length": 0, - "no_copy": 0, - "oldfieldname": "price_list_name", - "oldfieldtype": "Select", - "options": "Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "item_code", + "fieldtype": "Link", + "in_filter": 1, + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Item Code", + "oldfieldname": "price_list_name", + "oldfieldtype": "Select", + "options": "Item", + "reqd": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "uom", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "UOM", - "length": 0, - "no_copy": 0, - "options": "UOM", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "uom", + "fieldtype": "Link", + "label": "UOM", + "options": "UOM" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "description": "Quantity that must be bought or sold per UOM", - "fetch_if_empty": 0, - "fieldname": "packing_unit", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Packing Unit", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "description": "Quantity that must be bought or sold per UOM", + "fieldname": "packing_unit", + "fieldtype": "Int", + "label": "Packing Unit" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "fetch_if_empty": 0, - "fieldname": "min_qty", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Minimum Qty ", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "1", + "fieldname": "min_qty", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Minimum Qty " + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_17", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_17", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "item_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "item_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Item Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "item_code.brand", - "fetch_if_empty": 0, - "fieldname": "brand", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Brand", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "item_code.brand", + "fieldname": "brand", + "fieldtype": "Read Only", + "in_list_view": 1, + "label": "Brand", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "item_description", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "item_description", + "fieldtype": "Text", + "label": "Item Description", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "price_list_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "options": "fa fa-tags", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "price_list_details", + "fieldtype": "Section Break", + "label": "Price List", + "options": "fa fa-tags" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Price List", - "length": 0, - "no_copy": 0, - "options": "Price List", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "price_list", + "fieldtype": "Link", + "in_global_search": 1, + "in_standard_filter": 1, + "label": "Price List", + "options": "Price List", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.selling == 1", - "fetch_if_empty": 0, - "fieldname": "customer", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer", - "length": 0, - "no_copy": 0, - "options": "Customer", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "bold": 1, + "depends_on": "eval:doc.selling == 1", + "fieldname": "customer", + "fieldtype": "Link", + "label": "Customer", + "options": "Customer" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.buying == 1", - "fetch_if_empty": 0, - "fieldname": "supplier", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Supplier", - "length": 0, - "no_copy": 0, - "options": "Supplier", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.buying == 1", + "fieldname": "supplier", + "fieldtype": "Link", + "label": "Supplier", + "options": "Supplier" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "buying", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Buying", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "buying", + "fieldtype": "Check", + "label": "Buying", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "selling", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Selling", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "selling", + "fieldtype": "Check", + "label": "Selling", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "item_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "options": "fa fa-tag", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "item_details", + "fieldtype": "Section Break", + "options": "fa fa-tag" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "bold": 1, + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "col_br_1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "col_br_1", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "price_list_rate", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Rate", - "length": 0, - "no_copy": 0, - "oldfieldname": "ref_rate", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "price_list_rate", + "fieldtype": "Currency", + "in_filter": 1, + "in_global_search": 1, + "in_list_view": 1, + "label": "Rate", + "oldfieldname": "ref_rate", + "oldfieldtype": "Currency", + "options": "currency", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "section_break_15", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_15", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fetch_if_empty": 0, - "fieldname": "valid_from", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Valid From ", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Today", + "fieldname": "valid_from", + "fieldtype": "Date", + "label": "Valid From " + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fetch_if_empty": 0, - "fieldname": "lead_time_days", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Lead Time in days", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "lead_time_days", + "fieldtype": "Int", + "label": "Lead Time in days" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "column_break_18", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_18", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "valid_upto", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Valid Upto ", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "valid_upto", + "fieldtype": "Date", + "label": "Valid Upto " + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "section_break_24", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_24", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "note", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Note", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "note", + "fieldtype": "Text", + "label": "Note" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "reference", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Reference", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "reference", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Reference" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-flag", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-04-12 12:33:54.621527", - "modified_by": "Administrator", - "module": "Stock", - "name": "Item Price", - "name_case": "Title Case", - "owner": "Administrator", + ], + "icon": "fa fa-flag", + "idx": 1, + "links": [], + "modified": "2019-12-31 03:11:09.702250", + "modified_by": "Administrator", + "module": "Stock", + "name": "Item Price", + "name_case": "Title Case", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales Master Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales Master Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase Master Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase Master Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_order": "ASC", - "title_field": "item_code", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "quick_entry": 1, + "sort_order": "ASC", + "title_field": "item_name", + "track_changes": 1 } \ No newline at end of file From f276e8d6a1f5346a0ecf8f2afadbe0f984bfc327 Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 6 Jan 2020 01:01:37 +0530 Subject: [PATCH 075/105] fix(plaid): change json structure (#20190) --- .../plaid_settings/plaid_settings.json | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json index 9903048d0be..df77ad8bc93 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2018-10-25 10:02:48.656165", "doctype": "DocType", "editable_grid": 1, @@ -23,48 +24,41 @@ }, { "default": "0", - "depends_on": "eval:doc.enabled==1", + "depends_on": "enabled", "fieldname": "automatic_sync", "fieldtype": "Check", "label": "Synchronize all accounts every hour" }, { - "depends_on": "eval:doc.enabled==1", "fieldname": "plaid_client_id", "fieldtype": "Data", "in_list_view": 1, - "label": "Plaid Client ID", - "reqd": 1 + "label": "Plaid Client ID" }, { - "depends_on": "eval:doc.enabled==1", "fieldname": "plaid_secret", "fieldtype": "Password", "in_list_view": 1, - "label": "Plaid Secret", - "reqd": 1 + "label": "Plaid Secret" }, { - "depends_on": "eval:doc.enabled==1", "fieldname": "plaid_public_key", "fieldtype": "Data", "in_list_view": 1, - "label": "Plaid Public Key", - "reqd": 1 + "label": "Plaid Public Key" }, { - "depends_on": "eval:doc.enabled==1", "fieldname": "plaid_env", "fieldtype": "Data", "in_list_view": 1, - "label": "Plaid Environment", - "reqd": 1 + "label": "Plaid Environment" }, { "fieldname": "column_break_2", "fieldtype": "Column Break" }, { + "depends_on": "enabled", "fieldname": "section_break_4", "fieldtype": "Section Break" }, @@ -74,7 +68,8 @@ } ], "issingle": 1, - "modified": "2019-08-13 17:00:06.939422", + "links": [], + "modified": "2020-01-05 10:00:22.137832", "modified_by": "Administrator", "module": "ERPNext Integrations", "name": "Plaid Settings", From 3530d0d7c905f9b24fe28843fa7ea510bc0e2ca7 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 6 Jan 2020 11:51:36 +0530 Subject: [PATCH 076/105] fix: incorrect valuation rate for finished good entry (#20166) --- .../stock/doctype/stock_entry/stock_entry.py | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 35af24c8317..8f678837773 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -103,9 +103,8 @@ class StockEntry(StockController): if self.work_order and self.purpose == "Material Consumption for Manufacture": self.validate_work_order_status() - else: - self.update_work_order() + self.update_work_order() self.update_stock_ledger() self.make_gl_entries_on_cancel() self.update_cost_in_project() @@ -479,10 +478,16 @@ class StockEntry(StockController): def set_basic_rate_for_finished_goods(self, raw_material_cost, scrap_material_cost): if self.purpose in ["Manufacture", "Repack"]: for d in self.get("items"): - if d.transfer_qty and (d.bom_no or d.t_warehouse) and (getattr(self, "pro_doc", frappe._dict()).scrap_warehouse != d.t_warehouse): + if (d.transfer_qty and (d.bom_no or d.t_warehouse) and raw_material_cost + and (getattr(self, "pro_doc", frappe._dict()).scrap_warehouse != d.t_warehouse)): d.basic_rate = flt((raw_material_cost - scrap_material_cost) / flt(d.transfer_qty), d.precision("basic_rate")) d.basic_amount = flt((raw_material_cost - scrap_material_cost), d.precision("basic_amount")) + if (not d.basic_rate and self.work_order and + frappe.db.get_single_value("Manufacturing Settings", "material_consumption")): + d.basic_rate = get_valuation_rate_for_finished_good_entry(self.work_order) or 0 + d.basic_amount = d.basic_rate * d.qty + def distribute_additional_costs(self): if self.purpose == "Material Issue": self.additional_costs = [] @@ -831,7 +836,6 @@ class StockEntry(StockController): frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "BOM" and \ frappe.db.get_single_value("Manufacturing Settings", "material_consumption")== 1: self.get_unconsumed_raw_materials() - else: if not self.fg_completed_qty: frappe.throw(_("Manufacturing Quantity is mandatory")) @@ -1151,20 +1155,17 @@ class StockEntry(StockController): se_child.s_warehouse = item_dict[d].get("from_warehouse") se_child.t_warehouse = item_dict[d].get("to_warehouse") se_child.item_code = item_dict[d].get('item_code') or cstr(d) - se_child.item_name = item_dict[d]["item_name"] - se_child.description = item_dict[d]["description"] se_child.uom = item_dict[d]["uom"] if item_dict[d].get("uom") else stock_uom se_child.stock_uom = stock_uom se_child.qty = flt(item_dict[d]["qty"], se_child.precision("qty")) - se_child.expense_account = item_dict[d].get("expense_account") se_child.cost_center = item_dict[d].get("cost_center") or cost_center se_child.allow_alternative_item = item_dict[d].get("allow_alternative_item", 0) se_child.subcontracted_item = item_dict[d].get("main_item_code") - se_child.original_item = item_dict[d].get("original_item") - se_child.po_detail = item_dict[d].get("po_detail") - if item_dict[d].get("idx"): - se_child.idx = item_dict[d].get("idx") + for field in ["idx", "po_detail", "original_item", + "expense_account", "description", "item_name"]: + if item_dict[d].get(field): + se_child.set(field, item_dict[d].get(field)) if se_child.s_warehouse==None: se_child.s_warehouse = self.from_warehouse @@ -1469,6 +1470,24 @@ def get_used_alternative_items(purchase_order=None, work_order=None): return used_alternative_items +def get_valuation_rate_for_finished_good_entry(work_order): + work_order_qty = flt(frappe.get_cached_value("Work Order", + work_order, 'material_transferred_for_manufacturing')) + + field = "(SUM(total_outgoing_value) / %s) as valuation_rate" % (work_order_qty) + + stock_data = frappe.get_all("Stock Entry", + fields = field, + filters = { + "docstatus": 1, + "purpose": "Material Transfer for Manufacture", + "work_order": work_order + } + ) + + if stock_data: + return stock_data[0].valuation_rate + @frappe.whitelist() def get_uom_details(item_code, uom, qty): """Returns dict `{"conversion_factor": [value], "transfer_qty": qty * [value]}` From 3074679d7ee2fd2746b426ed25e0c7b2ecc40d51 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 6 Jan 2020 15:07:06 +0530 Subject: [PATCH 077/105] fix: party type in payment request --- .../doctype/payment_request/payment_request.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js index e2510f675f3..e1e43140c01 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.js +++ b/erpnext/accounts/doctype/payment_request/payment_request.js @@ -2,6 +2,16 @@ cur_frm.add_fetch("payment_gateway_account", "payment_account", "payment_account cur_frm.add_fetch("payment_gateway_account", "payment_gateway", "payment_gateway") cur_frm.add_fetch("payment_gateway_account", "message", "message") +frappe.ui.form.on("Payment Request", { + setup: function(frm) { + frm.set_query("party_type", function() { + return { + query: "erpnext.setup.doctype.party_type.party_type.get_party_type", + }; + }); + } +}) + frappe.ui.form.on("Payment Request", "onload", function(frm, dt, dn){ if (frm.doc.reference_doctype) { frappe.call({ From 13c29aeec461b92a9a8cb12386539614180f6bdd Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Tue, 7 Jan 2020 11:13:58 +0530 Subject: [PATCH 078/105] fix: loan deduction during creation of bank entry in payroll (#20194) --- erpnext/hr/doctype/payroll_entry/payroll_entry.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py index dfd38ebbe38..3b85c4da139 100644 --- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py @@ -329,6 +329,10 @@ class PayrollEntry(Document): statistical_component = frappe.db.get_value("Salary Component", sal_detail.salary_component, 'statistical_component') if statistical_component != 1: salary_slip_total -= sal_detail.amount + + #loan deduction from bank entry during payroll + salary_slip_total -= salary_slip.total_loan_repayment + if salary_slip_total > 0: self.create_journal_entry(salary_slip_total, "salary") From ded5a255af6da581bde0549b24c9e7bd8fb370c6 Mon Sep 17 00:00:00 2001 From: Rohan Date: Tue, 7 Jan 2020 11:24:02 +0530 Subject: [PATCH 079/105] fix: integer UOM check in transactions (#20177) --- erpnext/utilities/transaction_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index f845cef9b10..20998108467 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -164,8 +164,8 @@ def validate_uom_is_integer(doc, uom_field, qty_fields, child_dt=None): qty_fields = [qty_fields] distinct_uoms = list(set([d.get(uom_field) for d in doc.get_all_children()])) - integer_uoms = filter(lambda uom: frappe.db.get_value("UOM", uom, - "must_be_whole_number", cache=True) or None, distinct_uoms) + integer_uoms = list(filter(lambda uom: frappe.db.get_value("UOM", uom, + "must_be_whole_number", cache=True) or None, distinct_uoms)) if not integer_uoms: return From 0980ebe93e3a92446b989c7338093af33cfbfa9d Mon Sep 17 00:00:00 2001 From: Pranav Nachnekar Date: Tue, 7 Jan 2020 05:59:45 +0000 Subject: [PATCH 080/105] fix: add new delivery note button in Sales Order (#20200) * fix: add new delivery note button in Sales Order * fix: removed debugger Co-authored-by: Nabin Hait --- erpnext/selling/doctype/sales_order/sales_order.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index cb016a1a744..193938a3bb7 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -6,7 +6,7 @@ frappe.ui.form.on("Sales Order", { setup: function(frm) { frm.custom_make_buttons = { - 'Delivery Note': 'Delivery', + 'Delivery Note': 'Delivery Note', 'Pick List': 'Pick List', 'Sales Invoice': 'Invoice', 'Material Request': 'Material Request', @@ -697,4 +697,4 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( }); } }); -$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm})); \ No newline at end of file +$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm})); From 6bbfce13fedf1b7bf761168da6c2c85462bf1a1b Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Tue, 7 Jan 2020 11:30:18 +0530 Subject: [PATCH 081/105] fix(item_tax_template): fetch parent account if not set (#20197) --- .../v12_0/move_item_tax_to_item_tax_template.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py index e47344bd92c..5a127950006 100644 --- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py +++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py @@ -60,10 +60,10 @@ def execute(): 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice' ] - + for dt in doctypes: for d in frappe.db.sql("""select name, parenttype, parent, item_code, item_tax_rate from `tab{0} Item` - where ifnull(item_tax_rate, '') not in ('', '{{}}') + where ifnull(item_tax_rate, '') not in ('', '{{}}') and item_tax_template is NULL""".format(dt), as_dict=1): item_tax_map = json.loads(d.item_tax_rate) item_tax_template_name = get_item_tax_template(item_tax_templates, @@ -98,12 +98,15 @@ def get_item_tax_template(item_tax_templates, item_tax_map, item_code, parenttyp company = get_company(parts[-1], parenttype, parent) parent_account = frappe.db.get_value("Account", filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account") + if not parent_account: + parent_account = frappe.db.get_value("Account", + filters={"account_type": "Tax", "root_type": "Liability", "is_group": 1, "company": company}) filters = { "account_name": account_name, - "company": company, - "account_type": "Tax", - "parent_account": parent_account - } + "company": company, + "account_type": "Tax", + "parent_account": parent_account + } tax_type = frappe.db.get_value("Account", filters) if not tax_type: account = frappe.new_doc("Account") From 55bdaae3ee6b95da6afdf5e4840e55f681e37d40 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Tue, 7 Jan 2020 11:31:19 +0530 Subject: [PATCH 082/105] feat: Validity for Item taxes (#20136) * feat: Validity for Item taxes * fix: Add HSN wise taxes * fix: Sort taxes based on validity * fix: Validation for item tax template and filters based on validity * fix: Add missing semicolon * fix: Validate tax template only if item code available * fix: Do not validate or filter item tax template if no item taxes applied * fix: Consider item group for validating taxes * fix: Test cases for item tax validation * fix: Item tax template filtering fixes * fix: Add missing semicolon * fix: Remove unnecessary query --- .../sales_invoice/test_sales_invoice.py | 22 ++- erpnext/controllers/queries.py | 32 +++- erpnext/controllers/taxes_and_totals.py | 34 ++++ erpnext/public/js/controllers/buying.js | 6 + erpnext/public/js/controllers/transaction.js | 23 +++ .../doctype/gst_hsn_code/gst_hsn_code.js | 22 ++- .../doctype/gst_hsn_code/gst_hsn_code.json | 140 +++++------------ .../doctype/gst_hsn_code/gst_hsn_code.py | 23 +++ erpnext/selling/sales_common.js | 7 + erpnext/stock/doctype/item/item.js | 16 +- erpnext/stock/doctype/item_tax/item_tax.json | 145 ++++++------------ erpnext/stock/get_item_details.py | 41 ++++- 12 files changed, 303 insertions(+), 208 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 530bd893c0e..a2a47b3a19c 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe import unittest, copy, time -from frappe.utils import nowdate, flt, getdate, cint +from frappe.utils import nowdate, flt, getdate, cint, add_days from frappe.model.dynamic_links import get_dynamic_link_map from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice @@ -1847,6 +1847,26 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234') self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000) + def test_item_tax_validity(self): + item = frappe.get_doc("Item", "_Test Item 2") + + if item.taxes: + item.taxes = [] + item.save() + + item.append("taxes", { + "item_tax_template": "_Test Item Tax Template 1", + "valid_from": add_days(nowdate(), 1) + }) + + item.save() + + sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1) + sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1" + self.assertRaises(frappe.ValidationError, sales_invoice.save) + + item.taxes = [] + item.save() def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 5c319008a85..d18f8e54d8f 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -4,9 +4,9 @@ from __future__ import unicode_literals import frappe from frappe.desk.reportview import get_match_cond, get_filters_cond -from frappe.utils import nowdate +from frappe.utils import nowdate, getdate from collections import defaultdict - +from erpnext.stock.get_item_details import _get_item_tax_template # searches for active employees def employee_query(doctype, txt, searchfield, start, page_len, filters): @@ -486,7 +486,7 @@ def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters) @frappe.whitelist() def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters): query = """ - select pr.name + select pr.name from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pritem where pr.docstatus = 1 and pritem.parent = pr.name and pr.name like {txt}""".format(txt = frappe.db.escape('%{0}%'.format(txt))) @@ -499,7 +499,7 @@ def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters): @frappe.whitelist() def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters): query = """ - select pi.name + select pi.name from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` piitem where pi.docstatus = 1 and piitem.parent = pi.name and pi.name like {txt}""".format(txt = frappe.db.escape('%{0}%'.format(txt))) @@ -508,3 +508,27 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters): query += " and piitem.item_code = {item_code}".format(item_code = frappe.db.escape(filters.get('item_code'))) return frappe.db.sql(query, filters) + +@frappe.whitelist() +def get_tax_template(doctype, txt, searchfield, start, page_len, filters): + + item_doc = frappe.get_cached_doc('Item', filters.get('item_code')) + item_group = filters.get('item_group') + taxes = item_doc.taxes or [] + + while item_group: + item_group_doc = frappe.get_cached_doc('Item Group', item_group) + taxes += item_group_doc.taxes or [] + item_group = item_group_doc.parent_item_group + + if not taxes: + return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """) + else: + args = { + 'item_code': filters.get('item_code'), + 'posting_date': filters.get('valid_from'), + 'tax_category': filters.get('tax_category') + } + + taxes = _get_item_tax_template(args, taxes, for_validate=True) + return [(d,) for d in set(taxes)] diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 049a837eaf6..b52a07dbdf0 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -8,6 +8,7 @@ from frappe import _, scrub from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction from erpnext.controllers.accounts_controller import validate_conversion_rate, \ validate_taxes_and_charges, validate_inclusive_tax +from erpnext.stock.get_item_details import _get_item_tax_template class calculate_taxes_and_totals(object): def __init__(self, doc): @@ -34,6 +35,7 @@ class calculate_taxes_and_totals(object): def _calculate(self): self.validate_conversion_rate() self.calculate_item_values() + self.validate_item_tax_template() self.initialize_taxes() self.determine_exclusive_rate() self.calculate_net_total() @@ -43,6 +45,38 @@ class calculate_taxes_and_totals(object): self._cleanup() self.calculate_total_net_weight() + def validate_item_tax_template(self): + for item in self.doc.get('items'): + if item.item_code and item.get('item_tax_template'): + item_doc = frappe.get_cached_doc("Item", item.item_code) + args = { + 'tax_category': self.doc.get('tax_category'), + 'posting_date': self.doc.get('posting_date'), + 'bill_date': self.doc.get('bill_date'), + 'transaction_date': self.doc.get('transaction_date') + } + + item_group = item_doc.item_group + item_group_taxes = [] + + while item_group: + item_group_doc = frappe.get_cached_doc('Item Group', item_group) + item_group_taxes += item_group_doc.taxes or [] + item_group = item_group_doc.parent_item_group + + item_taxes = item_doc.taxes or [] + + if not item_group_taxes and (not item_taxes): + # No validation if no taxes in item or item group + continue + + taxes = _get_item_tax_template(args, item_taxes + item_group_taxes, for_validate=True) + + if item.item_tax_template not in taxes: + frappe.throw(_("Row {0}: Invalid Item Tax Template for item {1}").format( + item.idx, frappe.bold(item.item_code) + )) + def validate_conversion_rate(self): # validate conversion rate company_currency = erpnext.get_company_currency(self.doc.company) diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index 926227b24c8..3d4c4a64595 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -107,6 +107,12 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ filters:{ 'item_code': row.item_code } } }); + + if(this.frm.fields_dict["items"].grid.get_field('item_code')) { + this.frm.set_query("item_tax_template", "items", function(doc, cdt, cdn) { + return me.set_query_for_item_tax_template(doc, cdt, cdn) + }); + } }, refresh: function(doc) { diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index e8155af4d6f..8870d75e39a 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1700,6 +1700,29 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, + set_query_for_item_tax_template: function(doc, cdt, cdn) { + + var item = frappe.get_doc(cdt, cdn); + if(!item.item_code) { + frappe.throw(__("Please enter Item Code to get item taxes")); + } else { + + let filters = { + 'item_code': item.item_code, + 'valid_from': doc.transaction_date || doc.bill_date || doc.posting_date, + 'item_group': item.item_group, + } + + if (doc.tax_category) + filters['tax_category'] = doc.tax_category; + + return { + query: "erpnext.controllers.queries.get_tax_template", + filters: filters + } + } + }, + payment_terms_template: function() { var me = this; const doc = this.frm.doc; diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js index e7cc91952d8..347fdfe61b6 100644 --- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js +++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js @@ -3,6 +3,26 @@ frappe.ui.form.on('GST HSN Code', { refresh: function(frm) { - + if(! frm.doc.__islocal && frm.doc.taxes.length){ + frm.add_custom_button(__('Update Taxes for Items'), function(){ + frappe.confirm( + 'Are you sure? It will overwrite taxes for all items with HSN Code '+frm.doc.name+'.', + function(){ + frappe.call({ + args:{ + taxes: frm.doc.taxes, + hsn_code: frm.doc.name + }, + method: 'erpnext.regional.doctype.gst_hsn_code.gst_hsn_code.update_taxes_in_item_master', + callback: function(r) { + if(r.message){ + frappe.show_alert(__('Item taxes updated')); + } + } + }); + } + ); + }); + } } }); diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json index 2a2145c7f71..d198a034bc2 100644 --- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json +++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json @@ -1,104 +1,48 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:hsn_code", - "beta": 0, - "creation": "2017-06-21 10:48:56.422086", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "autoname": "field:hsn_code", + "creation": "2017-06-21 10:48:56.422086", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "hsn_code", + "description", + "taxes" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "hsn_code", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "HSN Code", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "hsn_code", + "fieldtype": "Data", + "in_list_view": 1, + "label": "HSN Code", + "reqd": 1, + "unique": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "description", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 + "fieldname": "description", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Description" + }, + { + "fieldname": "taxes", + "fieldtype": "Table", + "label": "Taxes", + "options": "Item Tax" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-09-29 14:38:52.220743", - "modified_by": "Administrator", - "module": "Regional", - "name": "GST HSN Code", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "hsn_code, description", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "hsn_code", - "track_changes": 1, - "track_seen": 0 + ], + "links": [], + "modified": "2019-12-29 11:32:06.849631", + "modified_by": "Administrator", + "module": "Regional", + "name": "GST HSN Code", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "search_fields": "hsn_code, description", + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "hsn_code", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py index 9637c2e502a..4791dc26753 100644 --- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py +++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py @@ -8,3 +8,26 @@ from frappe.model.document import Document class GSTHSNCode(Document): pass + +@frappe.whitelist() +def update_taxes_in_item_master(taxes, hsn_code): + items = frappe.get_list("Item", filters={ + 'gst_hsn_code': hsn_code + }) + + taxes = frappe.parse_json(taxes) + frappe.enqueue(update_item_document, items=items, taxes=taxes) + return 1 + +def update_item_document(items, taxes): + for item in items: + item_to_be_updated=frappe.get_doc("Item", item.name) + item_to_be_updated.taxes = [] + for tax in taxes: + tax = frappe._dict(tax) + item_to_be_updated.append("taxes", { + 'item_tax_template': tax.item_tax_template, + 'tax_category': tax.tax_category, + 'valid_from': tax.valid_from + }) + item_to_be_updated.save() diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 1c9b30b8289..8278745a804 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -84,6 +84,13 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ return me.set_query_for_batch(doc, cdt, cdn) }); } + + if(this.frm.fields_dict["items"].grid.get_field('item_code')) { + this.frm.set_query("item_tax_template", "items", function(doc, cdt, cdn) { + return me.set_query_for_item_tax_template(doc, cdt, cdn) + }); + } + }, refresh: function() { diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 410d9f1b45b..ff26df6a678 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -49,7 +49,7 @@ frappe.ui.form.on("Item", { if (!frm.doc.is_fixed_asset) { erpnext.item.make_dashboard(frm); } - + if (frm.doc.is_fixed_asset) { frm.trigger('is_fixed_asset'); frm.trigger('auto_create_assets'); @@ -136,6 +136,20 @@ frappe.ui.form.on("Item", { frm.toggle_reqd('customer', frm.doc.is_customer_provided_item ? 1:0); }, + gst_hsn_code: function(frm){ + if(!frm.doc.taxes.length) { + frappe.db.get_doc("GST HSN Code", frm.doc.gst_hsn_code).then(hsn_doc => { + $.each(hsn_doc.taxes || [], function(i, tax) { + let a = frappe.model.add_child(frm.doc, 'Item Tax', 'taxes'); + a.item_tax_template = tax.item_tax_template; + a.tax_category = tax.tax_category; + a.valid_from = tax.valid_from; + frm.refresh_field('taxes'); + }); + }); + } + }, + is_fixed_asset: function(frm) { // set serial no to false & toggles its visibility frm.set_value('has_serial_no', 0); diff --git a/erpnext/stock/doctype/item_tax/item_tax.json b/erpnext/stock/doctype/item_tax/item_tax.json index 37daa2938da..a93e4636add 100644 --- a/erpnext/stock/doctype/item_tax/item_tax.json +++ b/erpnext/stock/doctype/item_tax/item_tax.json @@ -1,107 +1,50 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2013-02-22 01:28:01", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "editable_grid": 1, + "actions": [], + "creation": "2013-02-22 01:28:01", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "item_tax_template", + "tax_category", + "valid_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "item_tax_template", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Item Tax Template", - "length": 0, - "no_copy": 0, - "oldfieldname": "tax_type", - "oldfieldtype": "Link", - "options": "Item Tax Template", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "item_tax_template", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Tax Template", + "oldfieldname": "tax_type", + "oldfieldtype": "Link", + "options": "Item Tax Template", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "", - "fieldname": "tax_category", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Tax Category", - "length": 0, - "no_copy": 0, - "oldfieldname": "tax_rate", - "oldfieldtype": "Currency", - "options": "Tax Category", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "tax_category", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Tax Category", + "oldfieldname": "tax_rate", + "oldfieldtype": "Currency", + "options": "Tax Category" + }, + { + "fieldname": "valid_from", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Valid From" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-12-21 23:52:40.798944", - "modified_by": "Administrator", - "module": "Stock", - "name": "Item Tax", - "owner": "Administrator", - "permissions": [], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + ], + "idx": 1, + "istable": 1, + "links": [], + "modified": "2019-12-28 21:54:40.807849", + "modified_by": "Administrator", + "module": "Stock", + "name": "Item Tax", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC" } \ No newline at end of file diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 55f4be136b6..4abd8553919 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe from frappe import _, throw -from frappe.utils import flt, cint, add_days, cstr, add_months +from frappe.utils import flt, cint, add_days, cstr, add_months, getdate import json, copy from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item, set_transaction_type from erpnext.setup.utils import get_exchange_rate @@ -52,6 +52,16 @@ def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=Tru out = get_basic_details(args, item, overwrite_warehouse) + if isinstance(doc, string_types): + doc = json.loads(doc) + + if doc and doc.get('doctype') == 'Purchase Invoice': + args['bill_date'] = doc.get('bill_date') + + if doc: + args['posting_date'] = doc.get('posting_date') + args['transaction_date'] = doc.get('transaction_date') + get_item_tax_template(args, item, out) out["item_tax_rate"] = get_item_tax_map(args.company, args.get("item_tax_template") if out.get("item_tax_template") is None \ else out.get("item_tax_template"), as_json=True) @@ -393,7 +403,34 @@ def get_item_tax_template(args, item, out): item_tax_template = _get_item_tax_template(args, item_group_doc.taxes, out) item_group = item_group_doc.parent_item_group -def _get_item_tax_template(args, taxes, out): +def _get_item_tax_template(args, taxes, out={}, for_validate=False): + taxes_with_validity = [] + taxes_with_no_validity = [] + + for tax in taxes: + if tax.valid_from: + # In purchase Invoice first preference will be given to supplier invoice date + # if supplier date is not present then posting date + validation_date = args.get('transaction_date') or args.get('bill_date') or args.get('posting_date') + + if getdate(tax.valid_from) <= getdate(validation_date): + taxes_with_validity.append(tax) + else: + taxes_with_no_validity.append(tax) + + if taxes_with_validity: + taxes = sorted(taxes_with_validity, key = lambda i: i.valid_from, reverse=True) + else: + taxes = taxes_with_no_validity + + if for_validate: + return [tax.item_tax_template for tax in taxes if (cstr(tax.tax_category) == cstr(args.get('tax_category')) \ + and (tax.item_tax_template not in taxes))] + + # all templates have validity and no template is valid + if not taxes_with_validity and (not taxes_with_no_validity): + return None + for tax in taxes: if cstr(tax.tax_category) == cstr(args.get("tax_category")): out["item_tax_template"] = tax.item_tax_template From 54f2d5352295a22f9d0819af0f175f8db7174904 Mon Sep 17 00:00:00 2001 From: Don-Leopardo <46027152+Don-Leopardo@users.noreply.github.com> Date: Tue, 7 Jan 2020 03:05:57 -0300 Subject: [PATCH 083/105] fix: get_item_price not working properly (#20206) * fix: min_qty not working without party and valid_from not being used to order results * fix: fetch price on item qty change --- erpnext/public/js/controllers/transaction.js | 2 +- erpnext/stock/get_item_details.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 8870d75e39a..512bcf9f4fb 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -968,7 +968,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ qty: function(doc, cdt, cdn) { let item = frappe.get_doc(cdt, cdn); - this.conversion_factor(doc, cdt, cdn, true); + this.conversion_factor(doc, cdt, cdn, false); this.apply_pricing_rule(item, true); }, diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 4abd8553919..6fc6990df76 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -608,7 +608,7 @@ def get_item_price(args, item_code, ignore_party=False): return frappe.db.sql(""" select name, price_list_rate, uom from `tabItem Price` {conditions} - order by uom desc, min_qty desc """.format(conditions=conditions), args) + order by uom desc, min_qty desc, valid_from desc """.format(conditions=conditions), args) def get_price_list_rate_for(args, item_code): """ @@ -641,10 +641,15 @@ def get_price_list_rate_for(args, item_code): if desired_qty and check_packing_list(price_list_rate[0][0], desired_qty, item_code): item_price_data = price_list_rate else: - for field in ["customer", "supplier", "min_qty"]: + for field in ["customer", "supplier"]: del item_price_args[field] general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party")) + + if not general_price_list_rate: + del item_price_args["min_qty"] + general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party")) + if not general_price_list_rate and args.get("uom") != args.get("stock_uom"): item_price_args["uom"] = args.get("stock_uom") general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party")) From 75b62cdd9ffe4b73473b4f61ef5d9cf0acdd8e1c Mon Sep 17 00:00:00 2001 From: Marica Date: Tue, 7 Jan 2020 13:06:13 +0530 Subject: [PATCH 084/105] fix: Added description and title to supplier selection popup in Material Request. (#20180) --- erpnext/stock/doctype/material_request/material_request.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 99195c300da..935d61310eb 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -230,7 +230,8 @@ frappe.ui.form.on('Material Request', { make_purchase_order: function(frm) { frappe.prompt( - {fieldname:'default_supplier', label: __('For Default Supplier (optional)'), fieldtype: 'Link', options: 'Supplier'}, + {fieldname:'default_supplier', label: __('For Default Supplier (optional)'), description: __('Selected Supplier\ + must be the Default Supplier of one of the items below.'), fieldtype: 'Link', options: 'Supplier'}, (values) => { frappe.model.open_mapped_doc({ method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order", @@ -238,7 +239,8 @@ frappe.ui.form.on('Material Request', { args: { default_supplier: values.default_supplier }, run_link_triggers: true }); - } + }, + __('Enter Supplier') ) }, From 07c915d00bb80baab138f90558f4207fe5e11e94 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Mon, 23 Dec 2019 13:21:33 +0530 Subject: [PATCH 085/105] fix: paid amount gets overwritten by get_outstanding_invoices --- .../accounts/doctype/payment_entry/payment_entry.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index adf47ed2764..2192b7bf989 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -652,14 +652,16 @@ frappe.ui.form.on('Payment Entry', { (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") ) { if(total_positive_outstanding > total_negative_outstanding) - frm.set_value("paid_amount", - total_positive_outstanding - total_negative_outstanding); + if (!frm.doc.paid_amount) + frm.set_value("paid_amount", + total_positive_outstanding - total_negative_outstanding); } else if ( total_negative_outstanding && total_positive_outstanding < total_negative_outstanding ) { - frm.set_value("received_amount", - total_negative_outstanding - total_positive_outstanding); + if (!frm.doc.received_amount) + frm.set_value("received_amount", + total_negative_outstanding - total_positive_outstanding); } } From da82edf711dd25f5b5bee955abf1a120a4cd95ff Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Thu, 9 Jan 2020 12:06:14 +0530 Subject: [PATCH 086/105] fix: submit salary is not showing after creating slary slip in payroll (#20225) --- erpnext/hr/doctype/payroll_entry/payroll_entry.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.js b/erpnext/hr/doctype/payroll_entry/payroll_entry.js index adc06712ef0..d25eb6d7810 100644 --- a/erpnext/hr/doctype/payroll_entry/payroll_entry.js +++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.js @@ -31,7 +31,11 @@ frappe.ui.form.on('Payroll Entry', { } if ((frm.doc.employees || []).length) { frm.page.set_primary_action(__('Create Salary Slips'), () => { - frm.save('Submit'); + frm.save('Submit').then(()=>{ + frm.page.clear_primary_action(); + frm.refresh(); + frm.events.refresh(frm); + }); }); } } From 4479b93c1a80b175e91077c7fca0b2437bc46331 Mon Sep 17 00:00:00 2001 From: Pranav Nachnekar Date: Thu, 9 Jan 2020 06:52:11 +0000 Subject: [PATCH 087/105] fix: escape % in customer name (#20203) * fix: add new delivery note button in Sales Order * fix: escape % in customer name * Update sales_order.js Co-authored-by: Nabin Hait --- .../doctype/authorization_control/authorization_control.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/setup/doctype/authorization_control/authorization_control.py b/erpnext/setup/doctype/authorization_control/authorization_control.py index 7db703fadf5..6a184b1a166 100644 --- a/erpnext/setup/doctype/authorization_control/authorization_control.py +++ b/erpnext/setup/doctype/authorization_control/authorization_control.py @@ -76,7 +76,7 @@ class AuthorizationControl(TransactionBase): add_cond = '' auth_value = av_dis - if val == 1: add_cond += " and system_user = '"+session['user'].replace("'", "\\'")+"'" + if val == 1: add_cond += " and system_user = '"+ frappe.db.escape(session['user']) +"'" elif val == 2: add_cond += " and system_role IN %s" % ("('"+"','".join(frappe.get_roles())+"')") else: add_cond += " and ifnull(system_user,'') = '' and ifnull(system_role,'') = ''" @@ -85,7 +85,7 @@ class AuthorizationControl(TransactionBase): if doc_obj: if doc_obj.doctype == 'Sales Invoice': customer = doc_obj.customer else: customer = doc_obj.customer_name - add_cond = " and master_name = '"+cstr(customer).replace("'", "\\'")+"'" + add_cond = " and master_name = '"+ frappe.db.escape(customer) +"'" if based_on == 'Itemwise Discount': if doc_obj: for t in doc_obj.get("items"): From 03c1396fc78bb6092cf04c3eac65b8797fed25b7 Mon Sep 17 00:00:00 2001 From: Pranav Nachnekar Date: Thu, 9 Jan 2020 08:01:53 +0000 Subject: [PATCH 088/105] fix: Parent Item of Product Bundle should not appear in dialog (#20222) * fix: add new delivery note button in Sales Order * fix: parent item should not appear in raw material request dialog --- erpnext/selling/doctype/sales_order/sales_order.js | 1 + erpnext/selling/doctype/sales_order/sales_order.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 193938a3bb7..45dd51891c9 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -135,6 +135,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( } if(doc.status !== 'Closed') { if(doc.status !== 'On Hold') { + debugger; allow_delivery = this.frm.doc.items.some(item => item.delivered_by_supplier === 0 && item.qty > flt(item.delivered_qty)) && !this.frm.doc.skip_delivery_note diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 978dd29aebe..4a365004da8 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -380,6 +380,9 @@ class SalesOrder(SellingController): def get_work_order_items(self, for_raw_material_request=0): '''Returns items with BOM that already do not have a linked work order''' items = [] + item_codes = [i.item_code for i in self.items] + product_bundle_parents = [pb.new_item_code for pb in frappe.get_all("Product Bundle", {"new_item_code": ["in", item_codes]}, ["new_item_code"])] + for table in [self.items, self.packed_items]: for i in table: bom = get_default_bom_item(i.item_code) @@ -391,7 +394,7 @@ class SalesOrder(SellingController): else: pending_qty = stock_qty - if pending_qty: + if pending_qty and i.item_code not in product_bundle_parents: if bom: items.append(dict( name= i.name, From ff3ff9a3c2189d0c7946d30b2471ba012df7c23e Mon Sep 17 00:00:00 2001 From: Marica Date: Thu, 9 Jan 2020 13:34:30 +0530 Subject: [PATCH 089/105] fix: Employee name in Report trial balance for party (#20224) * fix: Employee name in Report trial balance for party * fix: Add account filter in trial balance for party report Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> --- .../trial_balance_for_party.js | 15 +++++++++++++++ .../trial_balance_for_party.py | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js index 873c65ebf11..0e93035a35d 100644 --- a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js +++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js @@ -65,6 +65,21 @@ frappe.query_reports["Trial Balance for Party"] = { return party_type; } }, + { + "fieldname": "account", + "label": __("Account"), + "fieldtype": "Link", + "options": "Account", + "get_query": function() { + var company = frappe.query_report.get_filter_value('company'); + return { + "doctype": "Account", + "filters": { + "company": company, + } + } + } + }, { "fieldname": "show_zero_values", "label": __("Show zero values"), diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py index 3e47906a98b..78c7e439d38 100644 --- a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py +++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py @@ -20,7 +20,7 @@ def execute(filters=None): def get_data(filters, show_party_name): if filters.get('party_type') in ('Customer', 'Supplier', 'Employee', 'Member'): party_name_field = "{0}_name".format(frappe.scrub(filters.get('party_type'))) - if filters.get('party_type') == 'Student': + elif filters.get('party_type') == 'Student': party_name_field = 'first_name' elif filters.get('party_type') == 'Shareholder': party_name_field = 'title' @@ -96,13 +96,19 @@ def get_data(filters, show_party_name): return data def get_opening_balances(filters): + + account_filter = '' + if filters.get('account'): + account_filter = "and account = %s" % (frappe.db.escape(filters.get('account'))) + gle = frappe.db.sql(""" select party, sum(debit) as opening_debit, sum(credit) as opening_credit from `tabGL Entry` where company=%(company)s and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != '' and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes') - group by party""", { + {account_filter} + group by party""".format(account_filter=account_filter), { "company": filters.company, "from_date": filters.from_date, "party_type": filters.party_type @@ -116,6 +122,11 @@ def get_opening_balances(filters): return opening def get_balances_within_period(filters): + + account_filter = '' + if filters.get('account'): + account_filter = "and account = %s" % (frappe.db.escape(filters.get('account'))) + gle = frappe.db.sql(""" select party, sum(debit) as debit, sum(credit) as credit from `tabGL Entry` @@ -123,7 +134,8 @@ def get_balances_within_period(filters): and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != '' and posting_date >= %(from_date)s and posting_date <= %(to_date)s and ifnull(is_opening, 'No') = 'No' - group by party""", { + {account_filter} + group by party""".format(account_filter=account_filter), { "company": filters.company, "from_date": filters.from_date, "to_date": filters.to_date, From 64f3577148059c7812bcc68eb86a29cd6eb65157 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 9 Jan 2020 15:05:26 +0530 Subject: [PATCH 090/105] feat: report to show difference between stock and account value (#20226) --- erpnext/accounts/utils.py | 6 + erpnext/config/stock.py | 6 + erpnext/stock/doctype/warehouse/warehouse.py | 23 ++- .../__init__.py | 0 .../stock_and_account_value_comparison.js | 37 +++++ .../stock_and_account_value_comparison.json | 28 ++++ .../stock_and_account_value_comparison.py | 131 ++++++++++++++++++ .../report/stock_balance/stock_balance.py | 2 +- 8 files changed, 230 insertions(+), 3 deletions(-) create mode 100644 erpnext/stock/report/stock_and_account_value_comparison/__init__.py create mode 100644 erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js create mode 100644 erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.json create mode 100644 erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 89c8467da26..e01d6d5dc7f 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -891,3 +891,9 @@ def get_allow_cost_center_in_entry_of_bs_account(): def generator(): return cint(frappe.db.get_value('Accounts Settings', None, 'allow_cost_center_in_entry_of_bs_account')) return frappe.local_cache("get_allow_cost_center_in_entry_of_bs_account", (), generator, regenerate_if_none=True) + +def get_stock_accounts(company): + return frappe.get_all("Account", filters = { + "account_type": "Stock", + "company": company + }) \ No newline at end of file diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py index 03e26b2b863..dd35f5ab368 100644 --- a/erpnext/config/stock.py +++ b/erpnext/config/stock.py @@ -348,6 +348,12 @@ def get_data(): "is_query_report": True, "name": "Subcontracted Item To Be Received", "doctype": "Purchase Order" + }, + { + "type": "report", + "is_query_report": True, + "name": "Stock and Account Value Comparison", + "doctype": "Stock Ledger Entry" } ] }, diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 6cdb56be7fb..6ed6044f329 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -177,7 +177,26 @@ def convert_to_group_or_ledger(): return frappe.get_doc("Warehouse", args.docname).convert_to_group_or_ledger() def get_child_warehouses(warehouse): - p_warehouse = frappe.get_doc("Warehouse", warehouse) + lft, rgt = frappe.get_cached_value("Warehouse", warehouse, [lft, rgt]) return frappe.db.sql_list("""select name from `tabWarehouse` - where lft >= %s and rgt =< %s""", (p_warehouse.lft, p_warehouse.rgt)) + where lft >= %s and rgt =< %s""", (lft, rgt)) + +def get_warehouses_based_on_account(account, company=None): + warehouses = [] + for d in frappe.get_all("Warehouse", fields = ["name", "is_group"], + filters = {"account": account}): + if d.is_group: + warehouses.extend(get_child_warehouses(d.name)) + else: + warehouses.append(d.name) + + if (not warehouses and company and + frappe.get_cached_value("Company", company, "default_inventory_account") == account): + warehouses = [d.name for d in frappe.get_all("Warehouse", filters={'is_group': 0})] + + if not warehouses: + frappe.throw(_("Warehouse not found against the account {0}") + .format(account)) + + return warehouses \ No newline at end of file diff --git a/erpnext/stock/report/stock_and_account_value_comparison/__init__.py b/erpnext/stock/report/stock_and_account_value_comparison/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js new file mode 100644 index 00000000000..7a170beec37 --- /dev/null +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js @@ -0,0 +1,37 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Stock and Account Value Comparison"] = { + "filters": [ + { + "label": __("Company"), + "fieldname": "company", + "fieldtype": "Link", + "options": "Company", + "reqd": 1, + "default": frappe.defaults.get_user_default("Company") + }, + { + "label": __("Account"), + "fieldname": "account", + "fieldtype": "Link", + "options": "Account", + get_query: function() { + var company = frappe.query_report.get_filter_value('company'); + return { + filters: { + "account_type": "Stock", + "company": company + } + } + } + }, + { + "label": __("As On Date"), + "fieldname": "as_on_date", + "fieldtype": "Date", + "default": frappe.datetime.get_today(), + }, + ] +}; diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.json b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.json new file mode 100644 index 00000000000..021159a89d4 --- /dev/null +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.json @@ -0,0 +1,28 @@ +{ + "add_total_row": 1, + "creation": "2020-01-09 14:42:45.254751", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "", + "modified": "2020-01-09 14:42:45.254751", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock and Account Value Comparison", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Stock Ledger Entry", + "report_name": "Stock and Account Value Comparison", + "report_type": "Script Report", + "roles": [ + { + "role": "Stock User" + }, + { + "role": "Accounts Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py new file mode 100644 index 00000000000..eef121e542f --- /dev/null +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -0,0 +1,131 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe, erpnext +from frappe import _ +from erpnext.accounts.utils import get_stock_accounts +from erpnext.accounts.utils import get_currency_precision +from erpnext.stock.doctype.warehouse.warehouse import get_warehouses_based_on_account + +def execute(filters=None): + if not erpnext.is_perpetual_inventory_enabled(filters.company): + frappe.throw(_("Perpetual inventory required for the company {0} to view this report.") + .format(filters.company)) + + data = get_data(filters) + columns = get_columns(filters) + + return columns, data + +def get_data(report_filters): + data = [] + + filters = { + "company": report_filters.company, + "posting_date": ("<=", report_filters.as_on_date) + } + + currency_precision = get_currency_precision() or 2 + stock_ledger_entries = get_stock_ledger_data(report_filters, filters) + voucher_wise_gl_data = get_gl_data(report_filters, filters) + + for d in stock_ledger_entries: + key = (d.voucher_type, d.voucher_no) + gl_data = voucher_wise_gl_data.get(key) or {} + d.account_value = gl_data.get("account_value", 0) + d.difference_value = (d.stock_value - d.account_value) + if abs(d.difference_value) > 1.0/10 ** currency_precision: + data.append(d) + + return data + +def get_stock_ledger_data(report_filters, filters): + if report_filters.account: + warehouses = get_warehouses_based_on_account(report_filters.account, + report_filters.warehouse) + + filters["warehouse"] = ("in", warehouses) + + return frappe.get_all("Stock Ledger Entry", filters=filters, + fields = ["name", "voucher_type", "voucher_no", + "sum(stock_value_difference) as stock_value", "posting_date", "posting_time"], + group_by = "voucher_type, voucher_no", + order_by = "posting_date ASC, posting_time ASC") + +def get_gl_data(report_filters, filters): + if report_filters.account: + stock_accounts = [report_filters.account] + else: + stock_accounts = [k.name + for k in get_stock_accounts(report_filters.company)] + + filters.update({ + "account": ("in", stock_accounts) + }) + + if filters.get("warehouse"): + del filters["warehouse"] + + gl_entries = frappe.get_all("GL Entry", filters=filters, + fields = ["name", "voucher_type", "voucher_no", + "sum(debit_in_account_currency) - sum(credit_in_account_currency) as account_value"], + group_by = "voucher_type, voucher_no") + + voucher_wise_gl_data = {} + for d in gl_entries: + key = (d.voucher_type, d.voucher_no) + voucher_wise_gl_data[key] = d + + return voucher_wise_gl_data + +def get_columns(filters): + return [ + { + "label": _("Stock Ledger ID"), + "fieldname": "name", + "fieldtype": "Link", + "options": "Stock Ledger Entry", + "width": "80" + }, + { + "label": _("Posting Date"), + "fieldname": "posting_date", + "fieldtype": "Date" + }, + { + "label": _("Posting Time"), + "fieldname": "posting_time", + "fieldtype": "Time" + }, + { + "label": _("Voucher Type"), + "fieldname": "voucher_type", + "width": "110" + }, + { + "label": _("Voucher No"), + "fieldname": "voucher_no", + "fieldtype": "Dynamic Link", + "options": "voucher_type", + "width": "110" + }, + { + "label": _("Stock Value"), + "fieldname": "stock_value", + "fieldtype": "Currency", + "width": "120" + }, + { + "label": _("Account Value"), + "fieldname": "account_value", + "fieldtype": "Currency", + "width": "120" + }, + { + "label": _("Difference Value"), + "fieldname": "difference_value", + "fieldtype": "Currency", + "width": "120" + } + ] \ No newline at end of file diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index ccba8b0e239..ff03381389c 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -264,7 +264,7 @@ def get_item_details(items, sle, filters): `tabItem` item %s where - item.name in (%s) and ifnull(item.disabled, 0) = 0 + item.name in (%s) """ % (cf_field, cf_join, ','.join(['%s'] *len(items))), items, as_dict=1) for item in res: From f67b3f8a79811131599f6a85a20af636a73481a4 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Fri, 10 Jan 2020 15:01:50 +0530 Subject: [PATCH 091/105] fix: Item tax template fetching from HSN Code --- erpnext/stock/doctype/item/item.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index ff26df6a678..c10e62973bb 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -136,8 +136,8 @@ frappe.ui.form.on("Item", { frm.toggle_reqd('customer', frm.doc.is_customer_provided_item ? 1:0); }, - gst_hsn_code: function(frm){ - if(!frm.doc.taxes.length) { + gst_hsn_code: function(frm) { + if(!frm.doc.taxes || !frm.doc.taxes.length) { frappe.db.get_doc("GST HSN Code", frm.doc.gst_hsn_code).then(hsn_doc => { $.each(hsn_doc.taxes || [], function(i, tax) { let a = frappe.model.add_child(frm.doc, 'Item Tax', 'taxes'); From 5beee8af587f31395d633339768f67d3d165491d Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Mon, 13 Jan 2020 12:43:49 +0530 Subject: [PATCH 092/105] fix: remove default customer as party type --- .../doctype/journal_entry_account/journal_entry_account.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index ab811d81b25..dbf4e5c4b41 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -90,7 +90,6 @@ "fieldtype": "Column Break" }, { - "default": "Customer", "fieldname": "party_type", "fieldtype": "Link", "in_list_view": 1, @@ -272,7 +271,7 @@ ], "idx": 1, "istable": 1, - "modified": "2019-10-02 12:23:21.693443", + "modified": "2020-01-13 12:41:33.968025", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", From a14f72590d9b8f413586831aa017d1fe7dfd4fec Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 13 Jan 2020 15:09:16 +0530 Subject: [PATCH 093/105] fix: Remove patch to set automatic tax fetching from item tax template (#20236) * fix: Remove patch to set automatic tax fetching from item tax template * fix: Remove duplicate patch --- erpnext/patches.txt | 1 - .../set_default_for_add_taxes_from_item_tax_template.py | 5 ----- 2 files changed, 6 deletions(-) delete mode 100644 erpnext/patches/v12_0/set_default_for_add_taxes_from_item_tax_template.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index f1dfb10729c..514305e95e2 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -645,7 +645,6 @@ erpnext.patches.v12_0.set_expense_account_in_landed_cost_voucher_taxes erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings erpnext.patches.v12_0.set_payment_entry_status erpnext.patches.v12_0.update_owner_fields_in_acc_dimension_custom_fields -erpnext.patches.v12_0.set_default_for_add_taxes_from_item_tax_template erpnext.patches.v12_0.remove_denied_leaves_from_leave_ledger erpnext.patches.v12_0.update_price_or_product_discount erpnext.patches.v12_0.add_export_type_field_in_party_master diff --git a/erpnext/patches/v12_0/set_default_for_add_taxes_from_item_tax_template.py b/erpnext/patches/v12_0/set_default_for_add_taxes_from_item_tax_template.py deleted file mode 100644 index 06ee7981980..00000000000 --- a/erpnext/patches/v12_0/set_default_for_add_taxes_from_item_tax_template.py +++ /dev/null @@ -1,5 +0,0 @@ -import frappe - -def execute(): - frappe.db.set_value("Accounts Settings", None, "add_taxes_from_item_tax_template", 1) - frappe.db.set_default("add_taxes_from_item_tax_template", 1) \ No newline at end of file From d56bc81daff86c8752a925995f1c832b4b32e569 Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 14 Jan 2020 11:36:47 +0530 Subject: [PATCH 094/105] fix: gl not generated on manual asset creation (#20267) --- erpnext/assets/doctype/asset/asset.js | 51 ++++++++++++--------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index f6a7fa20d08..a53ff881777 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -338,25 +338,12 @@ frappe.ui.form.on('Asset', { }) }, - purchase_receipt: function(frm) { + purchase_receipt: (frm) => { frm.trigger('toggle_reference_doc'); - if (frm.doc.purchase_receipt) { if (frm.doc.item_code) { frappe.db.get_doc('Purchase Receipt', frm.doc.purchase_receipt).then(pr_doc => { - frm.set_value('company', pr_doc.company); - frm.set_value('purchase_date', pr_doc.posting_date); - const item = pr_doc.items.find(item => item.item_code === frm.doc.item_code); - if (!item) { - frm.set_value('purchase_receipt', ''); - frappe.msgprint({ - title: __('Invalid Purchase Receipt'), - message: __("The selected Purchase Receipt doesn't contains selected Asset Item."), - indicator: 'red' - }); - } - frm.set_value('gross_purchase_amount', item.base_net_rate); - frm.set_value('location', item.asset_location); + frm.events.set_values_from_purchase_doc(frm, 'Purchase Receipt', pr_doc) }); } else { frm.set_value('purchase_receipt', ''); @@ -368,24 +355,12 @@ frappe.ui.form.on('Asset', { } }, - purchase_invoice: function(frm) { + purchase_invoice: (frm) => { frm.trigger('toggle_reference_doc'); if (frm.doc.purchase_invoice) { if (frm.doc.item_code) { frappe.db.get_doc('Purchase Invoice', frm.doc.purchase_invoice).then(pi_doc => { - frm.set_value('company', pi_doc.company); - frm.set_value('purchase_date', pi_doc.posting_date); - const item = pi_doc.items.find(item => item.item_code === frm.doc.item_code); - if (!item) { - frm.set_value('purchase_invoice', ''); - frappe.msgprint({ - title: __('Invalid Purchase Invoice'), - message: __("The selected Purchase Invoice doesn't contains selected Asset Item."), - indicator: 'red' - }); - } - frm.set_value('gross_purchase_amount', item.base_net_rate); - frm.set_value('location', item.asset_location); + frm.events.set_values_from_purchase_doc(frm, 'Purchase Invoice', pi_doc) }); } else { frm.set_value('purchase_invoice', ''); @@ -397,6 +372,24 @@ frappe.ui.form.on('Asset', { } }, + set_values_from_purchase_doc: function(frm, doctype, purchase_doc) { + frm.set_value('company', purchase_doc.company); + frm.set_value('purchase_date', purchase_doc.posting_date); + const item = purchase_doc.items.find(item => item.item_code === frm.doc.item_code); + if (!item) { + doctype_field = frappe.scrub(doctype) + frm.set_value(doctype_field, ''); + frappe.msgprint({ + title: __(`Invalid ${doctype}`), + message: __(`The selected ${doctype} doesn't contains selected Asset Item.`), + indicator: 'red' + }); + } + frm.set_value('gross_purchase_amount', item.base_net_rate + item.item_tax_amount); + frm.set_value('purchase_receipt_amount', item.base_net_rate + item.item_tax_amount); + frm.set_value('location', item.asset_location); + }, + set_depreciation_rate: function(frm, row) { if (row.total_number_of_depreciations && row.frequency_of_depreciation && row.expected_value_after_useful_life) { From ca4789c9f7d0592473f3b9c508a32af7610ae080 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 14 Jan 2020 12:12:54 +0530 Subject: [PATCH 095/105] fix: filter issue for the stock and account value comparision report --- .../stock_and_account_value_comparison.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py index eef121e542f..94ec314e8c9 100644 --- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -43,7 +43,7 @@ def get_data(report_filters): def get_stock_ledger_data(report_filters, filters): if report_filters.account: warehouses = get_warehouses_based_on_account(report_filters.account, - report_filters.warehouse) + report_filters.company) filters["warehouse"] = ("in", warehouses) From 2d37bbedaadf4f60ad187388e04dff03fce9fec7 Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 14 Jan 2020 12:42:43 +0530 Subject: [PATCH 096/105] fix: auto cancel if movement exists (#20268) Co-authored-by: Nabin Hait --- erpnext/assets/doctype/asset/asset.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 3e7f6833a0c..86b5a11a1d1 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -132,9 +132,10 @@ class Asset(AccountsController): if len(movements) > 1: frappe.throw(_('Asset has multiple Asset Movement Entries which has to be \ cancelled manually to cancel this asset.')) - movement = frappe.get_doc('Asset Movement', movements[0].get('name')) - movement.flags.ignore_validate = True - movement.cancel() + if movements: + movement = frappe.get_doc('Asset Movement', movements[0].get('name')) + movement.flags.ignore_validate = True + movement.cancel() def make_asset_movement(self): reference_doctype = 'Purchase Receipt' if self.purchase_receipt else 'Purchase Invoice' From c50f08a23a35798340c2d50f90758d1dce79b1cd Mon Sep 17 00:00:00 2001 From: Pranav Nachnekar Date: Wed, 15 Jan 2020 09:19:42 +0000 Subject: [PATCH 097/105] fix: remove `debugger` statement (#20294) introduced in https://github.com/frappe/erpnext/pull/20222 --- erpnext/selling/doctype/sales_order/sales_order.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 45dd51891c9..fa765dfaad9 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -135,8 +135,6 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( } if(doc.status !== 'Closed') { if(doc.status !== 'On Hold') { - debugger; - allow_delivery = this.frm.doc.items.some(item => item.delivered_by_supplier === 0 && item.qty > flt(item.delivered_qty)) && !this.frm.doc.skip_delivery_note From 4872417f866cdb44c7cb84d90d0655f7f8a853e9 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 15 Jan 2020 16:35:15 +0530 Subject: [PATCH 098/105] fix: incorrect number of GL Entries error in stock entry (#20298) --- erpnext/controllers/stock_controller.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index fc2128f2a42..aa3ce9d4d04 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -67,6 +67,7 @@ class StockController(AccountsController): gl_list = [] warehouse_with_no_account = [] + precision = frappe.get_precision("GL Entry", "debit_in_account_currency") for item_row in voucher_details: sle_list = sle_map.get(item_row.name) if sle_list: @@ -92,7 +93,7 @@ class StockController(AccountsController): "against": item_row.expense_account, "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", - "debit": flt(sle.stock_value_difference, 2), + "debit": flt(sle.stock_value_difference, precision), "is_opening": item_row.get("is_opening") or self.get("is_opening") or "No", }, warehouse_account[sle.warehouse]["account_currency"], item=item_row)) @@ -102,7 +103,7 @@ class StockController(AccountsController): "against": warehouse_account[sle.warehouse]["account"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", - "credit": flt(sle.stock_value_difference, 2), + "credit": flt(sle.stock_value_difference, precision), "project": item_row.get("project") or self.get("project"), "is_opening": item_row.get("is_opening") or self.get("is_opening") or "No" }, item=item_row)) From b65b525c44d8930bcff842e6570a286e1194d456 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 15 Jan 2020 16:37:10 +0530 Subject: [PATCH 099/105] fix: incorrect required qty for subcontracting purchase receipt (#20288) --- erpnext/controllers/buying_controller.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 75b896bb134..7366ea8a607 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -261,7 +261,7 @@ class BuyingController(StockController): non_stock_items = get_non_stock_items(item.purchase_order, item.item_code) - item_key = '{}{}'.format(item.item_code, item.purchase_order) + item_key = '{}{}{}'.format(item.item_code, item.purchase_order, item.purchase_order_item) fg_yet_to_be_received = qty_to_be_received_map.get(item_key) @@ -269,7 +269,9 @@ class BuyingController(StockController): backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code) for raw_material in transferred_raw_materials + non_stock_items: - rm_item_key = '{}{}'.format(raw_material.rm_item_code, item.purchase_order) + rm_item_key = '{}{}{}'.format(raw_material.rm_item_code, + item.purchase_order, item.purchase_order_item) + raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {}) consumed_qty = raw_material_data.get('qty', 0) @@ -815,7 +817,7 @@ def get_subcontracted_raw_materials_from_se(purchase_order, fg_item): def get_backflushed_subcontracted_raw_materials(purchase_orders): common_query = """ SELECT - CONCAT(prsi.rm_item_code, pri.purchase_order) AS item_key, + CONCAT(prsi.rm_item_code, pri.purchase_order, pri.purchase_order_item) AS item_key, SUM(prsi.consumed_qty) AS qty, {serial_no_concat_syntax} AS serial_nos, {batch_no_concat_syntax} AS batch_nos @@ -826,7 +828,7 @@ def get_backflushed_subcontracted_raw_materials(purchase_orders): AND pri.purchase_order IN %s AND pri.item_code = prsi.main_item_code AND pr.docstatus = 1 - GROUP BY prsi.rm_item_code, pri.purchase_order + GROUP BY prsi.rm_item_code, pri.purchase_order, pri.purchase_order_item """ backflushed_raw_materials = frappe.db.multisql({ @@ -880,7 +882,7 @@ def validate_item_type(doc, fieldname, message): def get_qty_to_be_received(purchase_orders): return frappe._dict(frappe.db.sql(""" - SELECT CONCAT(poi.`item_code`, poi.`parent`) AS item_key, + SELECT CONCAT(poi.`item_code`, poi.`parent`, poi.`name`) AS item_key, SUM(poi.`qty`) - SUM(poi.`received_qty`) AS qty_to_be_received FROM `tabPurchase Order Item` poi WHERE From dc0ea3fdb07fbe96894708bc9323a96c68abc0f3 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Wed, 15 Jan 2020 18:57:08 +0530 Subject: [PATCH 100/105] fix(patch): do not append taxes to template if account name is not set (#20310) --- .../move_item_tax_to_item_tax_template.py | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py index 5a127950006..31d500ea2f7 100644 --- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py +++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py @@ -49,12 +49,13 @@ def execute(): item_tax_template_name = get_item_tax_template(item_tax_templates, item_tax_map, item_code) # update the item tax table - item = frappe.get_doc("Item", item_code) - item.set("taxes", []) - item.append("taxes", {"item_tax_template": item_tax_template_name, "tax_category": ""}) frappe.db.sql("delete from `tabItem Tax` where parent=%s and parenttype='Item'", item_code) - for d in item.taxes: - d.db_insert() + if item_tax_template_name: + item = frappe.get_doc("Item", item_code) + item.set("taxes", []) + item.append("taxes", {"item_tax_template": item_tax_template_name, "tax_category": ""}) + for d in item.taxes: + d.db_insert() doctypes = [ 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', @@ -95,30 +96,35 @@ def get_item_tax_template(item_tax_templates, item_tax_map, item_code, parenttyp else: parts = tax_type.strip().split(" - ") account_name = " - ".join(parts[:-1]) - company = get_company(parts[-1], parenttype, parent) - parent_account = frappe.db.get_value("Account", - filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account") - if not parent_account: + if not account_name: + tax_type = None + else: + company = get_company(parts[-1], parenttype, parent) parent_account = frappe.db.get_value("Account", - filters={"account_type": "Tax", "root_type": "Liability", "is_group": 1, "company": company}) - filters = { - "account_name": account_name, - "company": company, - "account_type": "Tax", - "parent_account": parent_account - } - tax_type = frappe.db.get_value("Account", filters) - if not tax_type: - account = frappe.new_doc("Account") - account.update(filters) - account.insert() - tax_type = account.name + filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account") + if not parent_account: + parent_account = frappe.db.get_value("Account", + filters={"account_type": "Tax", "root_type": "Liability", "is_group": 1, "company": company}) + filters = { + "account_name": account_name, + "company": company, + "account_type": "Tax", + "parent_account": parent_account + } + tax_type = frappe.db.get_value("Account", filters) + if not tax_type: + account = frappe.new_doc("Account") + account.update(filters) + account.insert() + tax_type = account.name - item_tax_template.append("taxes", {"tax_type": tax_type, "tax_rate": tax_rate}) - item_tax_templates.setdefault(item_tax_template.title, {}) - item_tax_templates[item_tax_template.title][tax_type] = tax_rate - item_tax_template.save() - return item_tax_template.name + if tax_type: + item_tax_template.append("taxes", {"tax_type": tax_type, "tax_rate": tax_rate}) + item_tax_templates.setdefault(item_tax_template.title, {}) + item_tax_templates[item_tax_template.title][tax_type] = tax_rate + if item_tax_template.get("taxes"): + item_tax_template.save() + return item_tax_template.name def get_company(company_abbr, parenttype=None, parent=None): if parenttype and parent: From ab2e52ca07125596354bb02f24a959b7723c3217 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Wed, 15 Jan 2020 18:57:40 +0530 Subject: [PATCH 101/105] fix(patch): reload tax category (#20309) --- .../doctype/tax_category/tax_category.json | 240 +++++++++--------- .../patches/v8_7/sync_india_custom_fields.py | 4 +- 2 files changed, 123 insertions(+), 121 deletions(-) diff --git a/erpnext/accounts/doctype/tax_category/tax_category.json b/erpnext/accounts/doctype/tax_category/tax_category.json index 3556e127675..d57e8f6e910 100644 --- a/erpnext/accounts/doctype/tax_category/tax_category.json +++ b/erpnext/accounts/doctype/tax_category/tax_category.json @@ -1,134 +1,134 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:title", - "beta": 0, - "creation": "2018-11-22 23:38:39.668804", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "field:title", + "beta": 0, + "creation": "2018-11-22 23:38:39.668804", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "title", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Title", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "title", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Title", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-11-22 23:38:39.668804", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Tax Category", - "name_case": "", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2020-01-15 17:14:28.951793", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Tax Category", + "name_case": "", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 0 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, + ], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/patches/v8_7/sync_india_custom_fields.py b/erpnext/patches/v8_7/sync_india_custom_fields.py index 80d66c2ab19..73e1b182e82 100644 --- a/erpnext/patches/v8_7/sync_india_custom_fields.py +++ b/erpnext/patches/v8_7/sync_india_custom_fields.py @@ -13,6 +13,8 @@ def execute(): frappe.reload_doc('hr', 'doctype', 'employee_tax_exemption_declaration_category') frappe.reload_doc('hr', 'doctype', 'employee_tax_exemption_proof_submission_detail') + frappe.reload_doc('accounts', 'doctype', 'tax_category') + for doctype in ["Sales Invoice", "Delivery Note", "Purchase Invoice"]: frappe.db.sql("""delete from `tabCustom Field` where dt = %s and fieldname in ('port_code', 'shipping_bill_number', 'shipping_bill_date')""", doctype) @@ -29,4 +31,4 @@ def execute(): update tabAddress set gst_state_number=concat("0", gst_state_number) where ifnull(gst_state_number, '') != '' and gst_state_number<10 - """) \ No newline at end of file + """) From 7e33d875e07fa92db9ea94c701ae59e73585ab94 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Jan 2020 13:02:40 +0530 Subject: [PATCH 102/105] Revert "fix: incorrect required qty for subcontracting purchase receipt (#20288)" (#20323) This reverts commit b65b525c44d8930bcff842e6570a286e1194d456. --- erpnext/controllers/buying_controller.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 7366ea8a607..75b896bb134 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -261,7 +261,7 @@ class BuyingController(StockController): non_stock_items = get_non_stock_items(item.purchase_order, item.item_code) - item_key = '{}{}{}'.format(item.item_code, item.purchase_order, item.purchase_order_item) + item_key = '{}{}'.format(item.item_code, item.purchase_order) fg_yet_to_be_received = qty_to_be_received_map.get(item_key) @@ -269,9 +269,7 @@ class BuyingController(StockController): backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code) for raw_material in transferred_raw_materials + non_stock_items: - rm_item_key = '{}{}{}'.format(raw_material.rm_item_code, - item.purchase_order, item.purchase_order_item) - + rm_item_key = '{}{}'.format(raw_material.rm_item_code, item.purchase_order) raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {}) consumed_qty = raw_material_data.get('qty', 0) @@ -817,7 +815,7 @@ def get_subcontracted_raw_materials_from_se(purchase_order, fg_item): def get_backflushed_subcontracted_raw_materials(purchase_orders): common_query = """ SELECT - CONCAT(prsi.rm_item_code, pri.purchase_order, pri.purchase_order_item) AS item_key, + CONCAT(prsi.rm_item_code, pri.purchase_order) AS item_key, SUM(prsi.consumed_qty) AS qty, {serial_no_concat_syntax} AS serial_nos, {batch_no_concat_syntax} AS batch_nos @@ -828,7 +826,7 @@ def get_backflushed_subcontracted_raw_materials(purchase_orders): AND pri.purchase_order IN %s AND pri.item_code = prsi.main_item_code AND pr.docstatus = 1 - GROUP BY prsi.rm_item_code, pri.purchase_order, pri.purchase_order_item + GROUP BY prsi.rm_item_code, pri.purchase_order """ backflushed_raw_materials = frappe.db.multisql({ @@ -882,7 +880,7 @@ def validate_item_type(doc, fieldname, message): def get_qty_to_be_received(purchase_orders): return frappe._dict(frappe.db.sql(""" - SELECT CONCAT(poi.`item_code`, poi.`parent`, poi.`name`) AS item_key, + SELECT CONCAT(poi.`item_code`, poi.`parent`) AS item_key, SUM(poi.`qty`) - SUM(poi.`received_qty`) AS qty_to_be_received FROM `tabPurchase Order Item` poi WHERE From 37c51f5913912b66f0a59ea9a17261d52cb14edc Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Jan 2020 13:37:30 +0530 Subject: [PATCH 103/105] fix: Multiple fixes based on testing on pre-release branch (#20300) * fix: Multiple fixes based on testing on pre-release branch * fix: reload hr settings --- .../purchase_order/purchase_order.json | 6 +- .../employee_advance/employee_advance.js | 8 +- .../employee_advance/employee_advance.py | 7 +- .../hr/doctype/expense_claim/expense_claim.js | 12 +- .../hr/doctype/expense_claim/expense_claim.py | 1 + .../expense_claim_advance.json | 305 +++++------------- erpnext/manufacturing/doctype/bom/bom.py | 44 ++- .../doctype/work_order/work_order.py | 5 - erpnext/patches.txt | 2 +- .../stock/doctype/stock_entry/stock_entry.py | 40 +-- erpnext/stock/get_item_details.py | 9 +- 11 files changed, 148 insertions(+), 291 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 9201eef9b49..d82e128735e 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1,5 +1,4 @@ { - "actions": [], "allow_import": 1, "autoname": "naming_series:", "creation": "2013-05-21 16:16:39", @@ -48,7 +47,6 @@ "ignore_pricing_rule", "sec_warehouse", "set_warehouse", - "set_reserve_warehouse", "col_break_warehouse", "is_subcontracted", "supplier_warehouse", @@ -58,6 +56,7 @@ "section_break_48", "pricing_rules", "raw_material_details", + "set_reserve_warehouse", "supplied_items", "sb_last_purchase", "total_qty", @@ -1054,8 +1053,7 @@ "icon": "fa fa-file-text", "idx": 105, "is_submittable": 1, - "links": [], - "modified": "2019-12-30 19:11:54.122264", + "modified": "2020-01-14 18:54:39.694448", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js index ba62853336d..389660387b7 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.js +++ b/erpnext/hr/doctype/employee_advance/employee_advance.js @@ -47,7 +47,7 @@ frappe.ui.form.on('Employee Advance', { } if (frm.doc.docstatus === 1 - && (flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount)) + && (flt(frm.doc.claimed_amount) + flt(frm.doc.return_amount) < flt(frm.doc.paid_amount)) && frappe.model.can_create("Journal Entry")) { frm.add_custom_button(__("Return"), function() { @@ -96,12 +96,12 @@ frappe.ui.form.on('Employee Advance', { frappe.call({ method: 'erpnext.hr.doctype.employee_advance.employee_advance.make_return_entry', args: { - 'employee_name': frm.doc.employee, + 'employee': frm.doc.employee, 'company': frm.doc.company, 'employee_advance_name': frm.doc.name, 'return_amount': flt(frm.doc.paid_amount - frm.doc.claimed_amount), - 'mode_of_payment': frm.doc.mode_of_payment, - 'advance_account': frm.doc.advance_account + 'advance_account': frm.doc.advance_account, + 'mode_of_payment': frm.doc.mode_of_payment }, callback: function(r) { const doclist = frappe.model.sync(r.message); diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index 7fe2ebc79e0..f10e3b6ce26 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -133,7 +133,8 @@ def make_bank_entry(dt, dn): return je.as_dict() @frappe.whitelist() -def make_return_entry(employee_name, company, employee_advance_name, return_amount, mode_of_payment, advance_account): +def make_return_entry(employee, company, employee_advance_name, + return_amount, advance_account, mode_of_payment=None): return_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment) je = frappe.new_doc('Journal Entry') je.posting_date = nowdate() @@ -147,7 +148,7 @@ def make_return_entry(employee_name, company, employee_advance_name, return_amou 'reference_type': 'Employee Advance', 'reference_name': employee_advance_name, 'party_type': 'Employee', - 'party': employee_name, + 'party': employee, 'is_advance': 'Yes' }) @@ -159,5 +160,5 @@ def make_return_entry(employee_name, company, employee_advance_name, return_amou }) return je.as_dict() - + diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 0d37c10e9cc..3194007f231 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -213,13 +213,14 @@ frappe.ui.form.on("Expense Claim", { }, update_employee_advance_claimed_amount: function(frm) { + console.log("update_employee_advance_claimed_amount") let amount_to_be_allocated = frm.doc.grand_total; $.each(frm.doc.advances || [], function(i, advance){ if (amount_to_be_allocated >= advance.unclaimed_amount){ - frm.doc.advances[i].allocated_amount = frm.doc.advances[i].unclaimed_amount; + advance.allocated_amount = frm.doc.advances[i].unclaimed_amount; amount_to_be_allocated -= advance.allocated_amount; } else{ - frm.doc.advances[i].allocated_amount = amount_to_be_allocated; + advance.allocated_amount = amount_to_be_allocated; amount_to_be_allocated = 0; } frm.refresh_field("advances"); @@ -295,6 +296,7 @@ frappe.ui.form.on("Expense Claim", { doc: frm.doc, callback: () => { refresh_field("taxes"); + frm.trigger("update_employee_advance_claimed_amount"); } }); } @@ -331,16 +333,12 @@ frappe.ui.form.on("Expense Claim", { frappe.ui.form.on("Expense Claim Detail", { amount: function(frm, cdt, cdn) { var child = locals[cdt][cdn]; - var doc = frm.doc; frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.amount); - cur_frm.cscript.calculate_total(doc,cdt,cdn); }, sanctioned_amount: function(frm, cdt, cdn) { - var doc = frm.doc; - cur_frm.cscript.calculate_total(doc,cdt,cdn); + cur_frm.cscript.calculate_total(frm.doc, cdt, cdn); frm.trigger("get_taxes"); - frm.trigger("calculate_grand_total"); } }); diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 4519fdc20b2..d29b3f75879 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -243,6 +243,7 @@ class ExpenseClaim(AccountsController): precision = self.precision("total_advance_amount") if flt(self.total_advance_amount, precision) > flt(self.total_claimed_amount, precision): frappe.throw(_("Total advance amount cannot be greater than total claimed amount")) + if self.total_sanctioned_amount \ and flt(self.total_advance_amount, precision) > flt(self.total_sanctioned_amount, precision): frappe.throw(_("Total advance amount cannot be greater than total sanctioned amount")) diff --git a/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.json b/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.json index b5e4fd16f8e..64eb3095b3d 100644 --- a/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.json +++ b/erpnext/hr/doctype/expense_claim_advance/expense_claim_advance.json @@ -1,238 +1,93 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2017-10-09 16:53:26.410762", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 1, - "engine": "InnoDB", + "creation": "2017-10-09 16:53:26.410762", + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "employee_advance", + "posting_date", + "advance_paid", + "unclaimed_amount", + "allocated_amount", + "advance_account" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "employee_advance", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Employee Advance", - "length": 0, - "no_copy": 1, - "oldfieldname": "journal_voucher", - "oldfieldtype": "Link", - "options": "Employee Advance", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "250px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "columns": 2, + "fieldname": "employee_advance", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Employee Advance", + "no_copy": 1, + "oldfieldname": "journal_voucher", + "oldfieldtype": "Link", + "options": "Employee Advance", + "print_width": "250px", + "reqd": 1, "width": "250px" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "posting_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Posting Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Posting Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "advance_paid", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Advance Paid", - "length": 0, - "no_copy": 0, - "options": "Company:company.default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "advance_paid", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Advance Paid", + "options": "Company:company:default_currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "unclaimed_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Unclaimed amount", - "length": 0, - "no_copy": 1, - "oldfieldname": "advance_amount", - "oldfieldtype": "Currency", - "options": "Company:company.default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "120px", - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "columns": 2, + "fieldname": "unclaimed_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Unclaimed amount", + "no_copy": 1, + "oldfieldname": "advance_amount", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_width": "120px", + "read_only": 1, + "reqd": 1, "width": "120px" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "allocated_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Allocated amount", - "length": 0, - "no_copy": 1, - "oldfieldname": "allocated_amount", - "oldfieldtype": "Currency", - "options": "Company:company.default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "120px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "columns": 2, + "fieldname": "allocated_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Allocated amount", + "no_copy": 1, + "oldfieldname": "allocated_amount", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_width": "120px", "width": "120px" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "advance_account", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Advance Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 + "fieldname": "advance_account", + "fieldtype": "Link", + "hidden": 1, + "label": "Advance Account", + "options": "Account" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2017-10-09 19:59:48.818139", - "modified_by": "Administrator", - "module": "HR", - "name": "Expense Claim Advance", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0 + ], + "istable": 1, + "modified": "2020-01-14 17:49:17.968373", + "modified_by": "Administrator", + "module": "HR", + "name": "Expense Claim Advance", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC" } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 686b1967eb5..98f10059712 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -633,7 +633,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite is_stock_item=is_stock_item, qty_field="stock_qty", select_columns = """, bom_item.source_warehouse, bom_item.operation, - bom_item.include_item_in_manufacturing, bom_item.description, + bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate, (Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""") items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True) @@ -647,7 +647,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty", select_columns = """, bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing, - bom_item.description """) + bom_item.description, bom_item.base_rate as rate """) items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) for item in items: @@ -760,11 +760,17 @@ def get_boms_in_bottom_up_order(bom_no=None): def add_additional_cost(stock_entry, work_order): # Add non stock items cost in the additional cost - bom = frappe.get_doc('BOM', work_order.bom_no) - table = 'exploded_items' if work_order.get('use_multi_level_bom') else 'items' + stock_entry.additional_costs = [] expenses_included_in_valuation = frappe.get_cached_value("Company", work_order.company, "expenses_included_in_valuation") + add_non_stock_items_cost(stock_entry, work_order, expenses_included_in_valuation) + add_operations_cost(stock_entry, work_order, expenses_included_in_valuation) + +def add_non_stock_items_cost(stock_entry, work_order, expense_account): + bom = frappe.get_doc('BOM', work_order.bom_no) + table = 'exploded_items' if work_order.get('use_multi_level_bom') else 'items' + items = {} for d in bom.get(table): items.setdefault(d.item_code, d.amount) @@ -772,11 +778,35 @@ def add_additional_cost(stock_entry, work_order): non_stock_items = frappe.get_all('Item', fields="name", filters={'name': ('in', list(items.keys())), 'ifnull(is_stock_item, 0)': 0}, as_list=1) + non_stock_items_cost = 0.0 for name in non_stock_items: + non_stock_items_cost += flt(items.get(name[0])) * flt(stock_entry.fg_completed_qty) / flt(bom.quantity) + + stock_entry.append('additional_costs', { + 'expense_account': expense_account, + 'description': _("Non stock items"), + 'amount': non_stock_items_cost + }) + +def add_operations_cost(stock_entry, work_order=None, expense_account=None): + from erpnext.stock.doctype.stock_entry.stock_entry import get_operating_cost_per_unit + operating_cost_per_unit = get_operating_cost_per_unit(work_order, stock_entry.bom_no) + + if operating_cost_per_unit: stock_entry.append('additional_costs', { - 'expense_account': expenses_included_in_valuation, - 'description': name[0], - 'amount': flt(items.get(name[0])) * flt(stock_entry.fg_completed_qty) / flt(bom.quantity) + "expense_account": expense_account, + "description": _("Operating Cost as per Work Order / BOM"), + "amount": operating_cost_per_unit * flt(stock_entry.fg_completed_qty) + }) + + if work_order and work_order.additional_operating_cost and work_order.qty: + additional_operating_cost_per_unit = \ + flt(work_order.additional_operating_cost) / flt(work_order.qty) + + stock_entry.append('additional_costs', { + "expense_account": expense_account, + "description": "Additional Operating Cost", + "amount": additional_operating_cost_per_unit * flt(stock_entry.fg_completed_qty) }) @frappe.whitelist() diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 1cb69012083..b4dc3a55699 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -13,7 +13,6 @@ from dateutil.relativedelta import relativedelta from erpnext.stock.doctype.item.item import validate_end_of_life from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError from erpnext.projects.doctype.timesheet.timesheet import OverlapError -from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty from frappe.utils.csvutils import getlink @@ -671,10 +670,6 @@ def make_stock_entry(work_order_id, purpose, qty=None): stock_entry.from_warehouse = wip_warehouse stock_entry.to_warehouse = work_order.fg_warehouse stock_entry.project = work_order.project - if purpose=="Manufacture": - additional_costs = get_additional_costs(work_order, fg_qty=stock_entry.fg_completed_qty, - company=work_order.company) - stock_entry.set("additional_costs", additional_costs) stock_entry.set_stock_entry_type() stock_entry.get_items() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 514305e95e2..17c9a20766d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -13,6 +13,7 @@ erpnext.patches.v4_0.apply_user_permissions erpnext.patches.v4_0.move_warehouse_user_to_restrictions erpnext.patches.v4_0.global_defaults_to_system_settings erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule +execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16 execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24 execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31 execute:frappe.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-29 @@ -513,7 +514,6 @@ erpnext.patches.v11_0.rename_employee_loan_to_loan erpnext.patches.v11_0.move_leave_approvers_from_employee #13-06-2018 erpnext.patches.v11_0.update_department_lft_rgt erpnext.patches.v11_0.add_default_email_template_for_leave -execute:frappe.reload_doc("HR", "doctype", "HR Settings") erpnext.patches.v11_0.set_default_email_template_in_hr #08-06-2018 erpnext.patches.v11_0.uom_conversion_data #30-06-2018 erpnext.patches.v10_0.taxes_issue_with_pos diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 8f678837773..996727042e3 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -478,15 +478,17 @@ class StockEntry(StockController): def set_basic_rate_for_finished_goods(self, raw_material_cost, scrap_material_cost): if self.purpose in ["Manufacture", "Repack"]: for d in self.get("items"): - if (d.transfer_qty and (d.bom_no or d.t_warehouse) and raw_material_cost + if (d.transfer_qty and (d.bom_no or d.t_warehouse) and (getattr(self, "pro_doc", frappe._dict()).scrap_warehouse != d.t_warehouse)): - d.basic_rate = flt((raw_material_cost - scrap_material_cost) / flt(d.transfer_qty), d.precision("basic_rate")) - d.basic_amount = flt((raw_material_cost - scrap_material_cost), d.precision("basic_amount")) - if (not d.basic_rate and self.work_order and - frappe.db.get_single_value("Manufacturing Settings", "material_consumption")): - d.basic_rate = get_valuation_rate_for_finished_good_entry(self.work_order) or 0 - d.basic_amount = d.basic_rate * d.qty + if self.work_order \ + and frappe.db.get_single_value("Manufacturing Settings", "material_consumption"): + bom_items = self.get_bom_raw_materials(d.transfer_qty) + raw_material_cost = sum([flt(d.qty)*flt(d.rate) for d in bom_items.values()]) + + if raw_material_cost: + d.basic_rate = flt((raw_material_cost - scrap_material_cost) / flt(d.transfer_qty), d.precision("basic_rate")) + d.basic_amount = flt((raw_material_cost - scrap_material_cost), d.precision("basic_amount")) def distribute_additional_costs(self): if self.purpose == "Material Issue": @@ -1402,30 +1404,6 @@ def get_work_order_details(work_order, company): "additional_costs": get_additional_costs(work_order, fg_qty=pending_qty_to_produce, company=company) } -def get_additional_costs(work_order=None, bom_no=None, fg_qty=None, company=None): - additional_costs = [] - operating_cost_per_unit = get_operating_cost_per_unit(work_order, bom_no) - expenses_included_in_valuation = frappe.get_cached_value("Company", company, "expenses_included_in_valuation") - - if operating_cost_per_unit: - additional_costs.append({ - "expense_account": expenses_included_in_valuation, - "description": "Operating Cost as per Work Order / BOM", - "amount": operating_cost_per_unit * flt(fg_qty) - }) - - if work_order and work_order.additional_operating_cost and work_order.qty: - additional_operating_cost_per_unit = \ - flt(work_order.additional_operating_cost) / flt(work_order.qty) - - additional_costs.append({ - "expense_account": expenses_included_in_valuation, - "description": "Additional Operating Cost", - "amount": additional_operating_cost_per_unit * flt(fg_qty) - }) - - return additional_costs - def get_operating_cost_per_unit(work_order=None, bom_no=None): operating_cost_per_unit = 0 if work_order: diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 6fc6990df76..dec3801feaa 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -608,7 +608,7 @@ def get_item_price(args, item_code, ignore_party=False): return frappe.db.sql(""" select name, price_list_rate, uom from `tabItem Price` {conditions} - order by uom desc, min_qty desc, valid_from desc """.format(conditions=conditions), args) + order by valid_from desc, min_qty desc, uom desc """.format(conditions=conditions), args) def get_price_list_rate_for(args, item_code): """ @@ -630,7 +630,8 @@ def get_price_list_rate_for(args, item_code): "customer": args.get('customer'), "supplier": args.get('supplier'), "uom": args.get('uom'), - "min_qty": args.get('qty'), + "min_qty": args.get('qty') if args.get('price_list_uom_dependant')\ + else flt(args.get('qty')) * flt(args.get("conversion_factor", 1)), "transaction_date": args.get('transaction_date'), } @@ -644,8 +645,8 @@ def get_price_list_rate_for(args, item_code): for field in ["customer", "supplier"]: del item_price_args[field] - general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party")) - + general_price_list_rate = get_item_price(item_price_args, item_code, + ignore_party=args.get("ignore_party")) if not general_price_list_rate: del item_price_args["min_qty"] general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party")) From 9fef6e1b680fa89fcb19ab8b32faf3103d7ad8ef Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Jan 2020 13:37:46 +0530 Subject: [PATCH 104/105] docs: Added change log for v12.4.0 (#20326) --- erpnext/change_log/v12/v12_4_0.md | 89 +++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 erpnext/change_log/v12/v12_4_0.md diff --git a/erpnext/change_log/v12/v12_4_0.md b/erpnext/change_log/v12/v12_4_0.md new file mode 100644 index 00000000000..3c8297368e2 --- /dev/null +++ b/erpnext/change_log/v12/v12_4_0.md @@ -0,0 +1,89 @@ +# Version 12.4.0 Release Note + +### Accounts + +- Validity of item tax. [#20135](https://github.com/frappe/erpnext/pull/20135) + +- Dynamic filters for dimensions in the budget variance report. [#19973](https://github.com/frappe/erpnext/pull/19973) + +- Purchase Receipt and Purchase Invoice is not mandatory for an existing asset. [19980](https://github.com/frappe/erpnext/pull/19980) + +- Allowed multiple Landed Cost Vouchers against a Purchase Receipt / Purchase Invoice. [#20058](https://github.com/frappe/erpnext/pull/20058) + +- Rounding adjustment while both inclusive tax and additional discount amount are applied. [#20078](https://github.com/frappe/erpnext/pull/20078) + +- Fixed an error while doing payment reconciliation for party type Employee. [#20088](https://github.com/frappe/erpnext/pull/20088) + +- Show Closing row in General Ledger print. [#20161](https://github.com/frappe/erpnext/pull/20161) + +- New report - Stock and Account Balance Comparison. [#20226](https://github.com/frappe/erpnext/pull/20226) + +- Paid amount should not be over-written on clicking "Get Outstanding Invoices" button in Payment Entry. [#20050](https://github.com/frappe/erpnext/pull/20050) + +- Currency symbol in Sales / Purchase Register report + +- Currency symbol in "Bank and Cash Payment Voucher" print format. + + +### Human Resource + +- Fixed leave allocation on the compensatory leave request submission. [#19961](https://github.com/frappe/erpnext/pull/19961) + +- Create Payment Entry against Employee Advance to return any unclaimed amount and update returned amount in Employee Advance. [#19955](https://github.com/frappe/erpnext/pull/19955) + +- Set Party against loan accounts in an accrual journal entry for salary. [#20022](https://github.com/frappe/erpnext/pull/20022) + +- Editable loan repayment schedule after submission [#20122](https://github.com/frappe/erpnext/pull/20112) + +- Update the paid amount and status of a loan after processing salary slip against it. [#20023](https://github.com/frappe/erpnext/pull/20023) + +- Settings to disable rounded total in salary slip via HR Settings. [#20150](https://github.com/frappe/erpnext/pull/20150) + +- Submit Salary button was not showing after creating salary slip in payroll entry. [#19753](https://github.com/frappe/erpnext/pull/19753) + +- Payment Entry against payroll entry should deduct loan amount (if there are any loan deductions in salary slip). [#20194](https://github.com/frappe/erpnext/pull/20194) + +- Show only relevant "Job Offer" in Employee Onboarding based on Job Applicant + +- Added dashboard in Employee Advance + + +### Manufacturing + +- Fixed backflushed qty for partial receipt against a subcontracted purchase order. [#20026](https://github.com/frappe/erpnext/pull/20026) + +- Added "Set Reserve Warehouse" field in sub-contracted Purchase Order. [19992](https://github.com/frappe/erpnext/pull/19992) + - Only shows if the supplied items table is not empty + - On entering a warehouse in the field, it sets / overwrites reserve warehouse in Supplied Raw Materials table. + +- In Backflush Stock Entry against Work Order, additional cost for service items (defined in BOM) should come proportionately based on finished goods qty. [#20105](https://github.com/frappe/erpnext/pull/20105) + +- Hide transfer button in a subcontracted PO if full qty is already transferred. [#20155](https://github.com/frappe/erpnext/pull/20155) + +- Set correct valuation rate of finished goods item in case of multiple material consumptions. [#20165](https://github.com/frappe/erpnext/pull/20165) + +- Job Card creation from Work Order dashboard + + +### Stock + +- Fixed ambiguous column name in the Batch query. Test by searching in any Batch link field. + +- Fixed incorrect reorder level in Stock balance report + +- Validate Batch for serialized items + +- Get the outgoing rate of serial no from SLE if serial no already transferred to another company. [#20171](https://github.com/frappe/erpnext/pull/20171) + +- Deliver Note creation from Sales Order dashboard. [#20199](https://github.com/frappe/erpnext/pull/20199) + + +### Others + +- Addition and deletion of items in submitted Sales Order / Purchase Order. [#19911](https://github.com/frappe/erpnext/pull/19911) + +- Get item price based on price list considering minimum qty. [#20206](https://github.com/frappe/erpnext/pull/20206) + +- Product Bundle item should not appear in dialog on click of "Create Material Request" button. [#20216](https://github.com/frappe/erpnext/pull/20216) + +- Delete linked communications on the deletion of company transactions. [#19928](https://github.com/frappe/erpnext/pull/19928) \ No newline at end of file From e8476ef42a1bea9c0485063749901363110df8a6 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Thu, 16 Jan 2020 14:50:35 +0550 Subject: [PATCH 105/105] bumped to version 12.4.0 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 16d84979539..358758366a6 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.3.1' +__version__ = '12.4.0' def get_default_company(user=None): '''Get default company for user'''