diff --git a/erpnext/__init__.py b/erpnext/__init__.py index ccb7e8f936d..7f8dde3fc31 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__ = '10.1.18' +__version__ = '10.1.19' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/cost_center/cost_center_tree.js b/erpnext/accounts/doctype/cost_center/cost_center_tree.js index f409d648fee..50436698105 100644 --- a/erpnext/accounts/doctype/cost_center/cost_center_tree.js +++ b/erpnext/accounts/doctype/cost_center/cost_center_tree.js @@ -48,5 +48,10 @@ frappe.treeview_settings["Cost Center"] = { }, __('Budget')); }, + onrender: function(node) { + if(node.is_root){ + node.hide_add = true; + } + } } \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 1f09e8153a3..f983868a0f0 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -769,6 +769,8 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= party_account = doc.receivable_account elif dt == "Employee Advance": party_account = doc.advance_account + elif dt == "Expense Claim": + party_account = doc.payable_account else: party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 3884bef1a46..9f0f574b14a 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -667,7 +667,9 @@ class AccountsController(TransactionBase): self.remove(item) def set_payment_schedule(self): - if self.doctype == 'Sales Invoice' and self.is_pos: return + if self.doctype == 'Sales Invoice' and self.is_pos: + self.payment_terms_template = '' + return posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date") date = self.get("due_date") diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 9a93633ad84..a174ce2a2ff 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -152,6 +152,11 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters): def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False): conditions = [] + description_cond = '' + if frappe.db.count('Item', cache=True) < 50000: + # scan description only if items are less than 50000 + description_cond = 'or tabItem.description LIKE %(txt)s' + return frappe.db.sql("""select tabItem.name, tabItem.item_group, if(length(tabItem.item_name) > 40, concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name, @@ -165,8 +170,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals and (tabItem.`{key}` LIKE %(txt)s or tabItem.item_group LIKE %(txt)s or tabItem.item_name LIKE %(txt)s - or tabItem.description LIKE %(txt)s) - or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s) + or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s + {description_cond}) {fcond} {mcond} order by if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999), @@ -176,7 +181,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals limit %(start)s, %(page_len)s """.format( key=searchfield, fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'), - mcond=get_match_cond(doctype).replace('%', '%%')), + mcond=get_match_cond(doctype).replace('%', '%%'), + description_cond = description_cond), { "today": nowdate(), "txt": "%%%s%%" % txt, diff --git a/erpnext/demo/user/hr.py b/erpnext/demo/user/hr.py index 9b83584d65e..6c6a7d4e937 100644 --- a/erpnext/demo/user/hr.py +++ b/erpnext/demo/user/hr.py @@ -34,14 +34,14 @@ def work(): payroll_entry.salary_slip_based_on_timesheet = 0 payroll_entry.create_salary_slips() payroll_entry.submit_salary_slips() - payroll_entry.make_accural_jv_entry() + payroll_entry.make_accrual_jv_entry() # payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date, # reference_number=random_string(10)) payroll_entry.salary_slip_based_on_timesheet = 1 payroll_entry.create_salary_slips() payroll_entry.submit_salary_slips() - payroll_entry.make_accural_jv_entry() + payroll_entry.make_accrual_jv_entry() # payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date, # reference_number=random_string(10)) diff --git a/erpnext/docs/user/manual/en/stock/tools/landed-cost-voucher.md b/erpnext/docs/user/manual/en/stock/tools/landed-cost-voucher.md index 979b1554d19..5188ed5bd5f 100644 --- a/erpnext/docs/user/manual/en/stock/tools/landed-cost-voucher.md +++ b/erpnext/docs/user/manual/en/stock/tools/landed-cost-voucher.md @@ -24,7 +24,7 @@ In the document, you can select multiple Purchase Receipts and fetch all items f Landed Cost Vouher -### What happend on submission? +### What happens on submission? 1. On submission of Landed Cost Voucher, the applicable landed cost charges are updated in Purchase Receipt Item table. diff --git a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py index e15be5001d3..0b134493dd8 100644 --- a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py +++ b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py @@ -26,7 +26,7 @@ class ProgramEnrollmentTool(Document): elif self.get_students_from == "Program Enrollment": condition2 = 'and student_batch_name=%(student_batch)s' if self.student_batch else " " students = frappe.db.sql('''select student, student_name, student_batch_name from `tabProgram Enrollment` - where program=%(program)s and academic_year=%(academic_year)s {0} {1}''' + where program=%(program)s and academic_year=%(academic_year)s {0} {1} and docstatus != 2''' .format(condition, condition2), self.as_dict(), as_dict=1) student_list = [d.student for d in students] diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 72007fc05a7..57e83e63be7 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -199,7 +199,6 @@ doc_events = { "validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products" }, "Sales Invoice": { - 'validate': 'erpnext.regional.india.utils.set_place_of_supply', "on_submit": "erpnext.regional.france.utils.create_transaction_log", "on_trash": "erpnext.regional.check_deletion_permission" }, @@ -210,7 +209,7 @@ doc_events = { 'Address': { 'validate': 'erpnext.regional.india.utils.validate_gstin_for_india' }, - 'Purchase Invoice': { + ('Sales Invoice', 'Purchase Invoice', 'Delivery Note'): { 'validate': 'erpnext.regional.india.utils.set_place_of_supply' } } diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 841fd4b59e5..7e2db6ec74f 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -82,9 +82,9 @@ cur_frm.cscript.refresh = function(doc) { if (cint(doc.total_amount_reimbursed) > 0 && frappe.model.can_read(entry_doctype)) { cur_frm.add_custom_button(__('Bank Entries'), function() { frappe.route_options = { - entry_route_doctype: me.frm.doc.doctype, - entry_route_name: me.frm.doc.name, - company: me.frm.doc.company + party_type: "Employee", + party: doc.employee, + company: doc.company }; frappe.set_route("List", entry_doctype); }, __("View")); @@ -181,7 +181,7 @@ frappe.ui.form.on("Expense Claim", { make_payment_entry: function(frm) { var method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry"; if(frm.doc.__onload && frm.doc.__onload.make_payment_via_journal_entry) { - method = "erpnext.hr.doctype.expense_claim.expense_claim.make_bank_entry" + method = "erpnext.hr.doctype.expense_claim.expense_claim.make_bank_entry"; } return frappe.call({ method: method, diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py index c6e531438f7..8437ec2471e 100644 --- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py @@ -164,7 +164,7 @@ class PayrollEntry(Document): except frappe.ValidationError: not_submitted_ss.append(ss_dict) if submitted_ss: - jv_name = self.make_accural_jv_entry() + jv_name = self.make_accrual_jv_entry() frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}") .format(ss_obj.start_date, ss_obj.end_date)) @@ -237,7 +237,7 @@ class PayrollEntry(Document): return payroll_payable_account - def make_accural_jv_entry(self): + def make_accrual_jv_entry(self): self.check_permission('write') earnings = self.get_salary_component_total(component_type = "earnings") or {} deductions = self.get_salary_component_total(component_type = "deductions") or {} @@ -249,7 +249,7 @@ class PayrollEntry(Document): if earnings or deductions: journal_entry = frappe.new_doc('Journal Entry') journal_entry.voucher_type = 'Journal Entry' - journal_entry.user_remark = _('Accural Journal Entry for salaries from {0} to {1}')\ + journal_entry.user_remark = _('Accrual Journal Entry for salaries from {0} to {1}')\ .format(self.start_date, self.end_date) journal_entry.company = self.company journal_entry.posting_date = self.posting_date diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py index 35d274cd604..9108f31f9b7 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.py +++ b/erpnext/hr/doctype/salary_component/salary_component.py @@ -17,6 +17,5 @@ class SalaryComponent(Document): self.salary_component.split()]).upper() self.salary_component_abbr = self.salary_component_abbr.strip() - - self.salary_component_abbr = append_number_if_name_exists('Salary Component', - self.salary_component_abbr, 'salary_component_abbr', separator='_') \ No newline at end of file + self.salary_component_abbr = append_number_if_name_exists('Salary Component', self.salary_component_abbr, + 'salary_component_abbr', separator='_', filters={"name": ["!=", self.name]}) \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js index 68c5f25fd26..8e6b69bd9e3 100755 --- a/erpnext/hr/doctype/salary_structure/salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/salary_structure.js @@ -39,6 +39,16 @@ frappe.ui.form.on('Salary Structure', { } } }); + frm.set_query("payment_account", function () { + var account_types = ["Bank", "Cash"]; + return { + filters: { + "account_type": ["in", account_types], + "is_group": 0, + "company": frm.doc.company + } + }; + }); }, refresh: function(frm) { diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 04e1bf37394..1551b1dfc30 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -106,7 +106,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } if( - this.frm.fields_dict["payment_terms_template"] + this.frm.docstatus < 2 + && this.frm.fields_dict["payment_terms_template"] && this.frm.fields_dict["payment_schedule"] && this.frm.doc.payment_terms_template && !this.frm.doc.payment_schedule.length diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 1b912183b10..fb2fabace40 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -64,7 +64,7 @@ def get_itemised_tax_breakup_data(doc): def set_place_of_supply(doc, method): if not frappe.get_meta('Address').has_field('gst_state'): return - if doc.doctype == "Sales Invoice": + if doc.doctype in ("Sales Invoice", "Delivery Note"): address_name = doc.shipping_address_name or doc.customer_address elif doc.doctype == "Purchase Invoice": address_name = doc.shipping_address or doc.supplier_address diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py index d975a9ee8da..247445da5dc 100644 --- a/erpnext/setup/doctype/company/delete_company_transactions.py +++ b/erpnext/setup/doctype/company/delete_company_transactions.py @@ -85,7 +85,7 @@ def delete_lead_addresses(company_name): in ({leads})""".format(leads=",".join(leads))) if addresses: - addresses = ["'%s'"%addr for addr in addresses] + addresses = ["'%s'"%frappe.db.escape(addr) for addr in addresses] frappe.db.sql("""delete from tabAddress where name in ({addresses}) and name not in (select distinct dl1.parent from `tabDynamic Link` dl1 diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 305702e755b..ef198f0d23c 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -7,8 +7,9 @@ from frappe import _ def execute(filters=None): columns = get_columns() - sl_entries = get_stock_ledger_entries(filters) - item_details = get_item_details(filters) + item_conditions = get_item_conditions(filters) + item_details = get_item_details(filters, item_conditions) + sl_entries = get_stock_ledger_entries(filters, item_conditions, item_details) opening_row = get_opening_balance(filters, columns) data = [] @@ -52,7 +53,12 @@ def get_columns(): return columns -def get_stock_ledger_entries(filters): +def get_stock_ledger_entries(filters, item_conditions, item_details): + item_conditions_sql = '' + if item_conditions: + items = ['"' + frappe.db.escape(i) + '"' for i in item_details.keys()] + if items: + item_conditions_sql = 'and sle.item_code in ({})'.format(', '.join(items)) return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date, item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate, stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project @@ -60,14 +66,18 @@ def get_stock_ledger_entries(filters): where company = %(company)s and posting_date between %(from_date)s and %(to_date)s {sle_conditions} + {item_conditions_sql} order by posting_date asc, posting_time asc, name asc"""\ - .format(sle_conditions=get_sle_conditions(filters)), filters, as_dict=1) + .format( + sle_conditions=get_sle_conditions(filters), + item_conditions_sql = item_conditions_sql + ), filters, as_dict=1) -def get_item_details(filters): +def get_item_details(filters, item_conditions): item_details = {} for item in frappe.db.sql("""select name, item_name, description, item_group, brand, stock_uom from `tabItem` item {item_conditions}"""\ - .format(item_conditions=get_item_conditions(filters)), filters, as_dict=1): + .format(item_conditions=item_conditions), filters, as_dict=1): item_details.setdefault(item.name, item) return item_details @@ -85,10 +95,6 @@ def get_item_conditions(filters): def get_sle_conditions(filters): conditions = [] - item_conditions=get_item_conditions(filters) - if item_conditions: - conditions.append("""sle.item_code in (select item.name from tabItem item - {item_conditions})""".format(item_conditions=item_conditions)) if filters.get("warehouse"): warehouse_condition = get_warehouse_condition(filters.get("warehouse")) if warehouse_condition: diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 26b4a24bbdb..fe465120905 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -444,7 +444,7 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no, last_valuation_rate = frappe.db.sql("""select valuation_rate from `tabStock Ledger Entry` where item_code = %s and warehouse = %s - and valuation_rate > 0 + and valuation_rate >= 0 order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, warehouse)) if not last_valuation_rate: