From 4448e2d66bb224deee3a6dda181a358223d3c480 Mon Sep 17 00:00:00 2001 From: NahuelOperto Date: Fri, 21 Jun 2019 08:50:37 -0300 Subject: [PATCH 01/21] fix order in general ledger --- erpnext/accounts/report/general_ledger/general_ledger.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 1c5e089534..2924907e8f 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -11,6 +11,7 @@ from erpnext.accounts.utils import get_account_currency from erpnext.accounts.report.financial_statements import get_cost_centers_with_children from six import iteritems from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +from collections import OrderedDict def execute(filters=None): if not filters: @@ -267,7 +268,7 @@ def group_by_field(group_by): return 'voucher_no' def initialize_gle_map(gl_entries, filters): - gle_map = frappe._dict() + gle_map = OrderedDict() group_by = group_by_field(filters.get('group_by')) for gle in gl_entries: From 126a02e2084cd7c5e9d3035d38692a068e2ff8f8 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 2 Jul 2019 15:28:57 +0530 Subject: [PATCH 02/21] fix: set invoice status considering invoice discounting --- .../discounted_invoice.json | 147 +--- .../invoice_discounting.json | 674 ++---------------- .../invoice_discounting.py | 33 +- .../doctype/journal_entry/journal_entry.py | 18 +- .../doctype/sales_invoice/sales_invoice.js | 13 +- .../doctype/sales_invoice/sales_invoice.json | 13 +- .../doctype/sales_invoice/sales_invoice.py | 66 +- .../sales_invoice/sales_invoice_list.js | 23 +- .../doctype/purchase_order/purchase_order.py | 1 - erpnext/controllers/status_updater.py | 2 + 10 files changed, 206 insertions(+), 784 deletions(-) diff --git a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json index 0d04b19fd1..8d7ed74eb9 100644 --- a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json +++ b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json @@ -1,177 +1,64 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, "creation": "2019-03-07 12:07:09.416101", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "sales_invoice", + "customer", + "column_break_3", + "posting_date", + "outstanding_amount" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "sales_invoice", "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": "Invoice", - "length": 0, - "no_copy": 0, "options": "Sales Invoice", - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fetch_from": "sales_invoice.customer", "fieldname": "customer", "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": "Customer", - "length": 0, - "no_copy": 0, "options": "Customer", - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fetch_from": "sales_invoice.posting_date", "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": "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, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fetch_from": "sales_invoice.grand_total", "fieldname": "outstanding_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": "Outstanding 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 + "read_only": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" } ], - "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": "2019-03-07 16:38:03.622666", + "modified": "2019-05-30 19:27:29.436153", "modified_by": "Administrator", "module": "Accounts", "name": "Discounted Invoice", - "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, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.json b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.json index 8927ca708d..3bfe259432 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.json +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.json @@ -1,744 +1,177 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, "allow_import": 1, - "allow_rename": 0, "autoname": "ACC-INV-DISC-.YYYY.-.#####", - "beta": 0, "creation": "2019-03-07 12:01:56.296952", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "posting_date", + "loan_start_date", + "loan_period", + "loan_end_date", + "column_break_3", + "status", + "company", + "section_break_5", + "invoices", + "section_break_7", + "total_amount", + "column_break_9", + "bank_charges", + "section_break_6", + "short_term_loan", + "bank_account", + "bank_charges_account", + "column_break_15", + "accounts_receivable_credit", + "accounts_receivable_discounted", + "accounts_receivable_unpaid", + "amended_from" + ], "fields": [ { - "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, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "loan_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": "Loan 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": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Loan Start Date" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "loan_period", "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": "Loan Period", - "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 + "label": "Loan Period (Days)" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "loan_end_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": "Loan End Date", - "length": 0, "no_copy": 1, - "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 + "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_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 + "fieldtype": "Column 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\nSanctioned\nDisbursed\nSettled\nCancelled", - "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 + "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": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "section_break_5", - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "invoices", "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": "Invoices", - "length": 0, - "no_copy": 0, "options": "Discounted Invoice", - "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 + "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "total_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": "Total 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 + "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_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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "bank_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": "Bank Charges", - "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 + "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": "section_break_6", - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "short_term_loan", "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": "Short Term 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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "bank_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": "Bank 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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "bank_charges_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": "Bank Charges 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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break_15", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "accounts_receivable_credit", "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": "Accounts Receivable Credit 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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "accounts_receivable_discounted", "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": "Accounts Receivable Discounted 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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "accounts_receivable_unpaid", "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": "Accounts Receivable Unpaid 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 + "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": "Invoice Discounting", - "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 + "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-03-08 14:24:31.222027", + "modified": "2019-05-30 19:08:21.199759", "modified_by": "Administrator", "module": "Accounts", "name": "Invoice Discounting", - "name_case": "", "owner": "Administrator", "permissions": [ { @@ -748,26 +181,17 @@ "delete": 1, "email": 1, "export": 1, - "if_owner": 0, "import": 1, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 0, "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", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py index c8756af7d7..29475d5644 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py @@ -28,18 +28,39 @@ class InvoiceDiscounting(AccountsController): self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices]) def on_submit(self): + self.update_sales_invoice() self.make_gl_entries() def on_cancel(self): self.set_status() + self.update_sales_invoice() self.make_gl_entries() - def set_status(self): - self.status = "Draft" - if self.docstatus == 1: - self.status = "Sanctioned" - elif self.docstatus == 2: - self.status = "Cancelled" + def set_status(self, status=None): + if status: + self.status = status + self.db_set("status", status) + for d in self.invoices: + frappe.get_doc("Sales Invoice", d.sales_invoice).set_status(update=True, update_modified=False) + else: + self.status = "Draft" + if self.docstatus == 1: + self.status = "Sanctioned" + elif self.docstatus == 2: + self.status = "Cancelled" + + def update_sales_invoice(self): + for d in self.invoices: + if self.docstatus == 1: + is_discounted = 1 + else: + discounted_invoice = frappe.db.exists({ + "doctype": "Discounted Invoice", + "sales_invoice": d.sales_invoice, + "docstatus": 1 + }) + is_discounted = 1 if discounted_invoice else 0 + frappe.db.set_value("Sales Invoice", d.sales_invoice, "is_discounted", is_discounted) def make_gl_entries(self): company_currency = frappe.get_cached_value('Company', self.company, "default_currency") diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index d082b60211..a9929c379d 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -105,24 +105,28 @@ class JournalEntry(AccountsController): invoice_discounting_list = list(set([d.reference_name for d in self.accounts if d.reference_type=="Invoice Discounting"])) for inv_disc in invoice_discounting_list: - short_term_loan_account, id_status = frappe.db.get_value("Invoice Discounting", inv_disc, ["short_term_loan", "status"]) + inv_disc_doc = frappe.get_doc("Invoice Discounting", inv_disc) + status = None for d in self.accounts: - if d.account == short_term_loan_account and d.reference_name == inv_disc: + if d.account == inv_disc_doc.short_term_loan and d.reference_name == inv_disc: if self.docstatus == 1: if d.credit > 0: - _validate_invoice_discounting_status(inv_disc, id_status, "Sanctioned", d.idx) + _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Sanctioned", d.idx) status = "Disbursed" elif d.debit > 0: - _validate_invoice_discounting_status(inv_disc, id_status, "Disbursed", d.idx) + _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Disbursed", d.idx) status = "Settled" else: if d.credit > 0: - _validate_invoice_discounting_status(inv_disc, id_status, "Disbursed", d.idx) + _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Disbursed", d.idx) status = "Sanctioned" elif d.debit > 0: - _validate_invoice_discounting_status(inv_disc, id_status, "Settled", d.idx) + _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Settled", d.idx) status = "Disbursed" - frappe.db.set_value("Invoice Discounting", inv_disc, "status", status) + break + if status: + inv_disc_doc.set_status(status=status) + def unlink_advance_entry_reference(self): for d in self.get("accounts"): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 07494a27d6..eaf59d3bf5 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -83,10 +83,14 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte } } - if (doc.outstanding_amount>0 && !cint(doc.is_return)) { + if (doc.outstanding_amount>0) { cur_frm.add_custom_button(__('Payment Request'), function() { me.make_payment_request(); }, __('Create')); + + cur_frm.add_custom_button(__('Invoice Discounting'), function() { + cur_frm.events.create_invoice_discounting(cur_frm); + }, __('Create')); } if (doc.docstatus === 1) { @@ -804,6 +808,13 @@ frappe.ui.form.on('Sales Invoice', { frm.set_df_property("patient_name", "hidden", 1); frm.set_df_property("ref_practitioner", "hidden", 1); } + }, + + create_invoice_discounting: function(frm) { + frappe.model.open_mapped_doc({ + method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_invoice_discounting", + frm: frm + }); } }) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 292d95d7b6..c0a1abd785 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -155,6 +155,7 @@ "inter_company_invoice_reference", "customer_group", "campaign", + "is_discounted", "col_break23", "status", "source", @@ -1336,7 +1337,7 @@ "in_standard_filter": 1, "label": "Status", "no_copy": 1, - "options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled", + "options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nUnpaid and Discounted\nOverdue and Discounted\nOverdue\nOverdue\nCancelled", "print_hide": 1, "read_only": 1 }, @@ -1553,12 +1554,20 @@ { "fieldname": "dimension_col_break", "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "is_discounted", + "fieldtype": "Check", + "label": "Is Discounted", + "no_copy": 1, + "read_only": 1 } ], "icon": "fa fa-file-text", "idx": 181, "is_submittable": 1, - "modified": "2019-05-25 22:05:03.474745", + "modified": "2019-07-02 15:21:40.257028", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index d6cf5d8b90..54e127d2f4 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1174,6 +1174,56 @@ class SalesInvoice(SellingController): self.set_missing_values(for_validate = True) + def get_discounting_status(self): + status = None + if self.is_discounted: + invoice_discounting_list = frappe.db.sql(""" + select status + from `tabInvoice Discounting` id, `tabDiscounted Invoice` d + where + id.name = d.parent + and d.sales_invoice=%s + and id.docstatus=1 + and status in ('Disbursed', 'Settled') + """, self.name) + for d in invoice_discounting_list: + status = d[0] + if status == "Disbursed": + break + return status + + def set_status(self, update=False, status=None, update_modified=True): + if self.is_new(): + if self.get('amended_from'): + self.status = 'Draft' + return + + if not status: + if self.docstatus == 2: + status = "Cancelled" + elif self.docstatus == 1: + if flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed': + self.status = "Overdue and Discounted" + elif self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()): + self.status = "Overdue" + elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed': + self.status = "Unpaid and Discounted" + elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()): + self.status = "Unpaid" + elif self.outstanding_amount < 0 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): + self.status = "Credit Note Issued" + elif self.outstanding_amount<=0 and self.is_return==0: + self.status = "Paid" + elif self.is_return == 1: + self.status = "Return" + else: + self.status = "Submitted" + else: + self.status = "Draft" + + if update: + self.db_set('status', self.status, update_modified = update_modified) + def validate_inter_company_party(doctype, party, company, inter_company_reference): if not party: return @@ -1428,4 +1478,18 @@ def get_loyalty_programs(customer): frappe.db.set(customer, 'loyalty_program', lp_details[0]) return [] else: - return lp_details \ No newline at end of file + return lp_details + +@frappe.whitelist() +def create_invoice_discounting(source_name, target_doc=None): + invoice = frappe.get_doc("Sales Invoice", source_name) + invoice_discounting = frappe.new_doc("Invoice Discounting") + invoice_discounting.company = invoice.company + invoice_discounting.append("invoices", { + "sales_invoice": source_name, + "customer": invoice.customer, + "posting_date": invoice.posting_date, + "outstanding_amount": invoice.outstanding_amount + }) + + return invoice_discounting \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js index 3c9c4b428d..05d49df711 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js @@ -6,17 +6,18 @@ frappe.listview_settings['Sales Invoice'] = { add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company", "currency", "is_return"], get_indicator: function(doc) { - if(cint(doc.is_return)==1) { - return [__("Return"), "darkgrey", "is_return,=,Yes"]; - } else if(flt(doc.outstanding_amount)==0) { - return [__("Paid"), "green", "outstanding_amount,=,0"] - } else if(flt(doc.outstanding_amount) < 0) { - return [__("Credit Note Issued"), "darkgrey", "outstanding_amount,<,0"] - }else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) { - return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"] - } else if (flt(doc.outstanding_amount) > 0 && doc.due_date < frappe.datetime.get_today()) { - return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<=,Today"] - } + var status_color = { + "Draft": "grey", + "Unpaid": "orange", + "Paid": "green", + "Return": "darkgrey", + "Credit Note Issued": "darkgrey", + "Unpaid and Discounted": "orange", + "Overdue and Discounted": "red", + "Overdue": "red" + + }; + return [__(doc.status), status_color[doc.status], "status,=,"+doc.status]; }, right_column: "grand_total" }; diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index a9a2094f08..8117d9d514 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -510,4 +510,3 @@ def update_status(status, name): def make_inter_company_sales_order(source_name, target_doc=None): from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction return make_inter_company_transaction("Purchase Order", source_name, target_doc) - diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 42e0a43e6e..c7542a8951 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -50,7 +50,9 @@ status_map = { ["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"], ["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"], ["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], + ["Unpaid and Discounted", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1 and self.is_discounted and self.discounting_status=='Disbursed'"], ["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], + ["Overdue and Discounted", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1 and self.is_discounted and self.discounting_status=='Disbursed'"], ["Cancelled", "eval:self.docstatus==2"], ], "Purchase Invoice": [ From 3bbcd491e4e1ccabddef3051796beae93834c16c Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 2 Jul 2019 15:31:24 +0530 Subject: [PATCH 03/21] fix: set invoice status considering invoice discounting --- erpnext/controllers/status_updater.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index c7542a8951..db6460f00c 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -43,18 +43,6 @@ status_map = { ["Closed", "eval:self.status=='Closed'"], ["On Hold", "eval:self.status=='On Hold'"], ], - "Sales Invoice": [ - ["Draft", None], - ["Submitted", "eval:self.docstatus==1"], - ["Return", "eval:self.is_return==1 and self.docstatus==1"], - ["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"], - ["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"], - ["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], - ["Unpaid and Discounted", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1 and self.is_discounted and self.discounting_status=='Disbursed'"], - ["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], - ["Overdue and Discounted", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1 and self.is_discounted and self.discounting_status=='Disbursed'"], - ["Cancelled", "eval:self.docstatus==2"], - ], "Purchase Invoice": [ ["Draft", None], ["Submitted", "eval:self.docstatus==1"], From 05fee62314957890b0772c2d2fa3f4f8266303a5 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 2 Jul 2019 17:55:26 +0530 Subject: [PATCH 04/21] fix: inv status --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 54e127d2f4..43bbfab130 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1210,7 +1210,7 @@ class SalesInvoice(SellingController): self.status = "Unpaid and Discounted" elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()): self.status = "Unpaid" - elif self.outstanding_amount < 0 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): + elif self.outstanding_amount < 0 and self.is_return==0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): self.status = "Credit Note Issued" elif self.outstanding_amount<=0 and self.is_return==0: self.status = "Paid" From 8412f847d4ae0e7e8836ca14e4758fcfef012ffa Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 12 Jul 2019 15:44:58 +0530 Subject: [PATCH 05/21] fix: dr / cr label for balance of the ledgers in the account tree --- erpnext/accounts/doctype/account/account_tree.js | 2 +- erpnext/accounts/utils.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index dc4c69d9e8..b70c6d2b27 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -121,7 +121,7 @@ frappe.treeview_settings["Account"] = { }, onrender: function(node) { if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){ - var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr"; + var dr_or_cr = in_list(["Liability", "Income", "Equity"], node.data.root_type) ? "Cr" : "Dr"; if (node.data && node.data.balance!==undefined) { $('' + (node.data.balance_in_account_currency ? diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 542c7e4e52..e75dd957db 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -734,6 +734,7 @@ def get_children(doctype, parent, company, is_root=False): parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_') fields = [ 'name as value', + 'root_type', 'is_group as expandable' ] filters = [['docstatus', '<', 2]] @@ -741,7 +742,7 @@ def get_children(doctype, parent, company, is_root=False): filters.append(['ifnull(`{0}`,"")'.format(parent_fieldname), '=', '' if is_root else parent]) if is_root: - fields += ['root_type', 'report_type', 'account_currency'] if doctype == 'Account' else [] + fields += ['report_type', 'account_currency'] if doctype == 'Account' else [] filters.append(['company', '=', company]) else: From dc02f4d07d2f002247811f0138755e1f1bc31d16 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sat, 13 Jul 2019 20:00:25 +0530 Subject: [PATCH 06/21] fix: miscellaneous fixes --- .../quality_feedback_parameter.json | 4 ++-- .../doctype/quality_meeting/quality_meeting.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json index d0b368f293..5bd8920a32 100644 --- a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json +++ b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json @@ -28,7 +28,7 @@ "fieldtype": "Select", "in_list_view": 1, "label": "Rating", - "options": "1\n2\n3\n4\n5", + "options": "\n1\n2\n3\n4\n5", "reqd": 1 }, { @@ -44,7 +44,7 @@ } ], "istable": 1, - "modified": "2019-05-26 21:50:48.951264", + "modified": "2019-07-13 19:58:08.966141", "modified_by": "Administrator", "module": "Quality Management", "name": "Quality Feedback Parameter", diff --git a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json index 6985632e49..0849fd7aeb 100644 --- a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json +++ b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json @@ -26,7 +26,7 @@ "fieldname": "status", "fieldtype": "Select", "label": "Status", - "options": "Open\nClose" + "options": "Open\nClosed" }, { "fieldname": "minutes", @@ -55,7 +55,7 @@ "label": "Minutes" } ], - "modified": "2019-05-26 23:12:23.364357", + "modified": "2019-07-13 19:57:40.500541", "modified_by": "Administrator", "module": "Quality Management", "name": "Quality Meeting", From d5fcab5f8197325c775eebd3a24ead49713f8a25 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 15 Jul 2019 12:44:11 +0530 Subject: [PATCH 07/21] fix: Set taxes fix for lead --- erpnext/public/js/utils/party.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index 35185c90b6..a8d3888ba0 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -145,7 +145,7 @@ erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billi erpnext.utils.set_taxes = function(frm, triggered_from_field) { if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) { if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier", - frm.doc.customer || frm.doc.supplier || frm.doc.lead, triggered_from_field)) { + frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) { return; } From eac54612296dc3cd02dc5711dc24fa1bfb11bcce Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 15 Jul 2019 13:55:08 +0530 Subject: [PATCH 08/21] fix: Address filtering fix in opportunity --- erpnext/crm/doctype/opportunity/opportunity.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js index 9dcd0c493a..90a12b7dbd 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.js +++ b/erpnext/crm/doctype/opportunity/opportunity.js @@ -19,6 +19,10 @@ frappe.ui.form.on("Opportunity", { } } }); + + if (frm.doc.opportunity_from && frm.doc.party_name){ + frm.trigger('set_contact_link'); + } }, onload_post_render: function(frm) { From 5435b7e9eb0326ffa9f866567e95fc3f0726ab3a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 15 Jul 2019 13:56:09 +0530 Subject: [PATCH 09/21] fix: Null issue --- .../accounts/doctype/sales_invoice/sales_invoice.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index b686c67fee..7d2861b230 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1203,17 +1203,17 @@ class SalesInvoice(SellingController): elif self.docstatus == 1: if flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed': self.status = "Overdue and Discounted" - elif self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()): + elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()): self.status = "Overdue" - elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed': + elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed': self.status = "Unpaid and Discounted" - elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()): + elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()): self.status = "Unpaid" - elif self.outstanding_amount < 0 and self.is_return==0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): + elif flt(self.outstanding_amount) < 0 and self.is_return==0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): self.status = "Credit Note Issued" elif self.is_return == 1: self.status = "Return" - elif self.outstanding_amount<=0: + elif flt(self.outstanding_amount)<=0: self.status = "Paid" else: self.status = "Submitted" From 6abb63b445ffbd867686fd436eeef97e834ab7c6 Mon Sep 17 00:00:00 2001 From: Michelle Alva <50285544+michellealva@users.noreply.github.com> Date: Mon, 15 Jul 2019 14:00:00 +0530 Subject: [PATCH 10/21] refactor: Refactor module links of Accounting, HR, Project (#18160) --- erpnext/config/accounting.py | 608 +++++++++++++++++------------------ erpnext/config/buying.py | 26 +- erpnext/config/hr.py | 514 ++++++++++++++--------------- erpnext/config/projects.py | 12 +- erpnext/config/selling.py | 38 +-- erpnext/config/stock.py | 42 +-- 6 files changed, 565 insertions(+), 675 deletions(-) diff --git a/erpnext/config/accounting.py b/erpnext/config/accounting.py index ce1384aae7..ab75f211c0 100644 --- a/erpnext/config/accounting.py +++ b/erpnext/config/accounting.py @@ -6,11 +6,12 @@ import frappe def get_data(): config = [ { - "label": _("Masters and Accounts"), + "label": _("Accounts Receivable"), "items": [ { "type": "doctype", - "name": "Item", + "name": "Sales Invoice", + "description": _("Bills raised to Customers."), "onboard": 1, }, { @@ -19,12 +20,115 @@ def get_data(): "description": _("Customer database."), "onboard": 1, }, + { + "type": "doctype", + "name": "Payment Entry", + "description": _("Bank/Cash transactions against party or for internal transfer") + }, + { + "type": "doctype", + "name": "Payment Request", + "description": _("Payment Request"), + }, + { + "type": "report", + "name": "Accounts Receivable", + "doctype": "Sales Invoice", + "is_query_report": True + }, + { + "type": "report", + "name": "Accounts Receivable Summary", + "doctype": "Sales Invoice", + "is_query_report": True + }, + { + "type": "report", + "name": "Sales Register", + "doctype": "Sales Invoice", + "is_query_report": True + }, + { + "type": "report", + "name": "Item-wise Sales Register", + "is_query_report": True, + "doctype": "Sales Invoice" + }, + { + "type": "report", + "name": "Ordered Items To Be Billed", + "is_query_report": True, + "doctype": "Sales Invoice" + }, + { + "type": "report", + "name": "Delivered Items To Be Billed", + "is_query_report": True, + "doctype": "Sales Invoice" + }, + ] + }, + { + "label": _("Accounts Payable"), + "items": [ + { + "type": "doctype", + "name": "Purchase Invoice", + "description": _("Bills raised by Suppliers."), + "onboard": 1 + }, { "type": "doctype", "name": "Supplier", "description": _("Supplier database."), "onboard": 1, }, + { + "type": "doctype", + "name": "Payment Entry", + "description": _("Bank/Cash transactions against party or for internal transfer") + }, + { + "type": "report", + "name": "Accounts Payable", + "doctype": "Purchase Invoice", + "is_query_report": True + }, + { + "type": "report", + "name": "Accounts Payable Summary", + "doctype": "Purchase Invoice", + "is_query_report": True + }, + { + "type": "report", + "name": "Purchase Register", + "doctype": "Purchase Invoice", + "is_query_report": True + }, + { + "type": "report", + "name": "Item-wise Purchase Register", + "is_query_report": True, + "doctype": "Purchase Invoice" + }, + { + "type": "report", + "name": "Purchase Order Items To Be Billed", + "is_query_report": True, + "doctype": "Purchase Invoice" + }, + { + "type": "report", + "name": "Received Items To Be Billed", + "is_query_report": True, + "doctype": "Purchase Invoice" + }, + ] + }, + { + "label": _("Accounting Masters"), + "items": [ { "type": "doctype", "name": "Company", @@ -40,201 +144,31 @@ def get_data(): "description": _("Tree of financial accounts."), "onboard": 1, }, - ] - }, - { - "label": _("Billing"), - "items": [ - { - "type": "doctype", - "name": "Sales Invoice", - "description": _("Bills raised to Customers."), - "onboard": 1, - }, - { - "type": "doctype", - "name": "Purchase Invoice", - "description": _("Bills raised by Suppliers."), - "onboard": 1 - }, - { - "type": "doctype", - "name": "Payment Request", - "description": _("Payment Request"), - }, - { - "type": "doctype", - "name": "Payment Term", - "description": _("Payment Terms based on conditions") - }, - - # Reports - { - "type": "report", - "name": "Ordered Items To Be Billed", - "is_query_report": True, - "reference_doctype": "Sales Invoice" - }, - { - "type": "report", - "name": "Delivered Items To Be Billed", - "is_query_report": True, - "reference_doctype": "Sales Invoice" - }, - { - "type": "report", - "name": "Purchase Order Items To Be Billed", - "is_query_report": True, - "reference_doctype": "Purchase Invoice" - }, - { - "type": "report", - "name": "Received Items To Be Billed", - "is_query_report": True, - "reference_doctype": "Purchase Invoice" - }, - ] - - }, - { - "label": _("Settings"), - "icon": "fa fa-cog", - "items": [ { "type": "doctype", "name": "Accounts Settings", - "description": _("Default settings for accounting transactions.") }, { "type": "doctype", "name": "Fiscal Year", "description": _("Financial / accounting year.") }, - { - "type": "doctype", - "name": "Currency", - "description": _("Enable / disable currencies.") - }, - { - "type": "doctype", - "name": "Currency Exchange", - "description": _("Currency exchange rate master.") - }, - { - "type": "doctype", - "name": "Exchange Rate Revaluation", - "description": _("Exchange Rate Revaluation master.") - }, - { - "type": "doctype", - "name": "Payment Gateway Account", - "description": _("Setup Gateway accounts.") - }, - { - "type": "doctype", - "name": "Terms and Conditions", - "label": _("Terms and Conditions Template"), - "description": _("Template of terms or contract.") - }, - { - "type": "doctype", - "name": "Mode of Payment", - "description": _("e.g. Bank, Cash, Credit Card") - }, - { - "type": "doctype", - "name": "Auto Repeat", - "label": _("Auto Repeat"), - "description": _("To make recurring documents") - }, - { - "type": "doctype", - "name": "C-Form", - "description": _("C-Form records"), - "country": "India" - }, - { - "type": "doctype", - "name": "Cheque Print Template", - "description": _("Setup cheque dimensions for printing") - }, { "type": "doctype", "name": "Accounting Dimension", - "description": _("Setup custom dimensions for accounting") }, { "type": "doctype", - "name": "Opening Invoice Creation Tool", - "description": _("Create Opening Sales and Purchase Invoices") - } - ] - }, - { - "label": _("Accounting Entries"), - "items": [ - { - "type": "doctype", - "name": "Payment Entry", - "description": _("Bank/Cash transactions against party or for internal transfer") + "name": "Finance Book", }, { "type": "doctype", - "name": "Journal Entry", - "description": _("Accounting journal entries.") - } - ] - }, - { - "label": _("Financial Statements"), - "items": [ - { - "type": "report", - "name": "General Ledger", - "doctype": "GL Entry", - "is_query_report": True, + "name": "Accounting Period", }, { - "type": "report", - "name": "Accounts Receivable", - "doctype": "Sales Invoice", - "is_query_report": True - }, - { - "type": "report", - "name": "Accounts Payable", - "doctype": "Purchase Invoice", - "is_query_report": True - }, - { - "type": "report", - "name": "Trial Balance", - "doctype": "GL Entry", - "is_query_report": True, - }, - { - "type": "report", - "name": "Balance Sheet", - "doctype": "GL Entry", - "is_query_report": True - }, - { - "type": "report", - "name": "Cash Flow", - "doctype": "GL Entry", - "is_query_report": True - }, - { - "type": "report", - "name": "Profit and Loss Statement", - "doctype": "GL Entry", - "is_query_report": True - }, - { - "type": "report", - "name": "Consolidated Financial Statement", - "doctype": "GL Entry", - "is_query_report": True + "type": "doctype", + "name": "Payment Term", + "description": _("Payment Terms based on conditions") }, ] }, @@ -243,43 +177,10 @@ def get_data(): "items": [ { "type": "doctype", - "label": _("Bank"), - "name": "Bank", + "label": _("Match Payments with Invoices"), + "name": "Payment Reconciliation", + "description": _("Match non-linked Invoices and Payments.") }, - { - "type": "page", - "label": _("Reconcile payments and bank transactions"), - "name": "bank-reconciliation", - "description": _("Link bank transactions with payments.") - }, - { - "type": "doctype", - "label": _("Bank Account"), - "name": "Bank Account", - }, - { - "type": "doctype", - "label": _("Invoice Discounting"), - "name": "Invoice Discounting", - }, - { - "type": "doctype", - "label": _("Bank Statement Transaction Entry List"), - "name": "Bank Statement Transaction Entry", - "route": "#List/Bank Statement Transaction Entry", - }, - { - "type": "doctype", - "label": _("Bank Statement Transaction Entry Report"), - "name": "Bank Statement Transaction Entry", - "route": "#Report/Bank Statement Transaction Entry", - }, - { - "type": "doctype", - "label": _("Bank Statement Settings"), - "name": "Bank Statement Settings", - }, - { "type": "doctype", "label": _("Update Bank Transaction Dates"), @@ -288,9 +189,8 @@ def get_data(): }, { "type": "doctype", - "label": _("Match Payments with Invoices"), - "name": "Payment Reconciliation", - "description": _("Match non-linked Invoices and Payments.") + "label": _("Invoice Discounting"), + "name": "Invoice Discounting", }, { "type": "report", @@ -306,8 +206,75 @@ def get_data(): }, { "type": "doctype", - "name": "Bank Guarantee", - "doctype": "Bank Guarantee" + "name": "Bank Guarantee" + }, + { + "type": "doctype", + "name": "Cheque Print Template", + "description": _("Setup cheque dimensions for printing") + }, + ] + }, + { + "label": _("General Ledger"), + "items": [ + { + "type": "doctype", + "name": "Journal Entry", + "description": _("Accounting journal entries.") + }, + { + "type": "report", + "name": "General Ledger", + "doctype": "GL Entry", + "is_query_report": True, + }, + { + "type": "report", + "name": "Customer Ledger Summary", + "doctype": "Sales Invoice", + "is_query_report": True, + }, + { + "type": "report", + "name": "Supplier Ledger Summary", + "doctype": "Sales Invoice", + "is_query_report": True, + } + ] + }, + { + "label": _("Taxes"), + "items": [ + { + "type": "doctype", + "name": "Sales Taxes and Charges Template", + "description": _("Tax template for selling transactions.") + }, + { + "type": "doctype", + "name": "Purchase Taxes and Charges Template", + "description": _("Tax template for buying transactions.") + }, + { + "type": "doctype", + "name": "Item Tax Template", + "description": _("Tax template for item tax rates.") + }, + { + "type": "doctype", + "name": "Tax Category", + "description": _("Tax Category for overriding tax rates.") + }, + { + "type": "doctype", + "name": "Tax Rule", + "description": _("Tax Rule for transactions.") + }, + { + "type": "doctype", + "name": "Tax Withholding Category", + "description": _("Tax Withholding rates to be applied on transactions.") }, ] }, @@ -327,6 +294,10 @@ def get_data(): "name": "Budget", "description": _("Define budget for a financial year.") }, + { + "type": "doctype", + "name": "Accounting Dimension", + }, { "type": "report", "name": "Budget Variance Report", @@ -338,51 +309,106 @@ def get_data(): "name": "Monthly Distribution", "description": _("Seasonality for setting budgets, targets etc.") }, + ] + }, + { + "label": _("Financial Statements"), + "items": [ + { + "type": "report", + "name": "Trial Balance", + "doctype": "GL Entry", + "is_query_report": True, + }, + { + "type": "report", + "name": "Profit and Loss Statement", + "doctype": "GL Entry", + "is_query_report": True + }, + { + "type": "report", + "name": "Balance Sheet", + "doctype": "GL Entry", + "is_query_report": True + }, + { + "type": "report", + "name": "Cash Flow", + "doctype": "GL Entry", + "is_query_report": True + }, + { + "type": "report", + "name": "Consolidated Financial Statement", + "doctype": "GL Entry", + "is_query_report": True + }, + ] + }, + { + "label": _("Opening and Closing"), + "items": [ + { + "type": "doctype", + "name": "Opening Invoice Creation Tool", + }, + { + "type": "doctype", + "name": "Chart of Accounts Importer", + }, { "type": "doctype", "name": "Period Closing Voucher", "description": _("Close Balance Sheet and book Profit or Loss.") }, ] + }, { - "label": _("Taxes"), + "label": _("Multi Currency"), "items": [ { "type": "doctype", - "name": "Tax Category", - "description": _("Tax Category for overriding tax rates.") + "name": "Currency", + "description": _("Enable / disable currencies.") }, { "type": "doctype", - "name": "Sales Taxes and Charges Template", - "description": _("Tax template for selling transactions.") + "name": "Currency Exchange", + "description": _("Currency exchange rate master.") }, { "type": "doctype", - "name": "Purchase Taxes and Charges Template", - "description": _("Tax template for buying transactions.") + "name": "Exchange Rate Revaluation", + "description": _("Exchange Rate Revaluation master.") + }, + ] + }, + { + "label": _("Settings"), + "icon": "fa fa-cog", + "items": [ + { + "type": "doctype", + "name": "Payment Gateway Account", + "description": _("Setup Gateway accounts.") }, { "type": "doctype", - "name": "Item Tax Template", - "description": _("Tax template for item tax rates.") + "name": "Terms and Conditions", + "label": _("Terms and Conditions Template"), + "description": _("Template of terms or contract.") }, { "type": "doctype", - "name": "Tax Rule", - "description": _("Tax Rule for transactions.") - }, - { - "type": "doctype", - "name": "Tax Withholding Category", - "description": _("Tax Withholding rates to be applied on transactions.") + "name": "Mode of Payment", + "description": _("e.g. Bank, Cash, Credit Card") }, ] }, { "label": _("Subscription Management"), - "icon": "fa fa-microchip ", "items": [ { "type": "doctype", @@ -403,7 +429,31 @@ def get_data(): ] }, { - "label": _("Key Reports"), + "label": _("Bank Statement"), + "items": [ + { + "type": "doctype", + "label": _("Bank"), + "name": "Bank", + }, + { + "type": "doctype", + "label": _("Bank Account"), + "name": "Bank Account", + }, + { + "type": "doctype", + "name": "Bank Statement Transaction Entry", + }, + { + "type": "doctype", + "label": _("Bank Statement Settings"), + "name": "Bank Statement Settings", + }, + ] + }, + { + "label": _("Profitability"), "items": [ { "type": "report", @@ -413,21 +463,9 @@ def get_data(): }, { "type": "report", - "name": "Sales Register", - "doctype": "Sales Invoice", - "is_query_report": True - }, - { - "type": "report", - "name": "Purchase Register", - "doctype": "Purchase Invoice", - "is_query_report": True - }, - { - "type": "report", - "name": "Purchase Invoice Trends", + "name": "Profitability Analysis", + "doctype": "GL Entry", "is_query_report": True, - "doctype": "Purchase Invoice" }, { "type": "report", @@ -437,38 +475,14 @@ def get_data(): }, { "type": "report", - "name": "Item-wise Sales Register", - "is_query_report": True, - "doctype": "Sales Invoice" - }, - { - "type": "report", - "name": "Item-wise Purchase Register", + "name": "Purchase Invoice Trends", "is_query_report": True, "doctype": "Purchase Invoice" }, - { - "type": "report", - "name": "Profitability Analysis", - "doctype": "GL Entry", - "is_query_report": True, - }, - { - "type": "report", - "name": "Customer Ledger Summary", - "doctype": "Sales Invoice", - "is_query_report": True, - }, - { - "type": "report", - "name": "Supplier Ledger Summary", - "doctype": "Sales Invoice", - "is_query_report": True, - } ] }, { - "label": _("Other Reports"), + "label": _("Reports"), "icon": "fa fa-table", "items": [ { @@ -489,18 +503,6 @@ def get_data(): "is_query_report": True, "doctype": "Sales Invoice" }, - { - "type": "report", - "name": "Accounts Receivable Summary", - "doctype": "Sales Invoice", - "is_query_report": True - }, - { - "type": "report", - "name": "Accounts Payable Summary", - "doctype": "Purchase Invoice", - "is_query_report": True - }, { "type": "report", "is_query_report": True, @@ -549,27 +551,7 @@ def get_data(): } ] }, - { - "label": _("Help"), - "icon": "fa fa-facetime-video", - "items": [ - { - "type": "help", - "label": _("Chart of Accounts"), - "youtube_id": "DyR-DST-PyA" - }, - { - "type": "help", - "label": _("Opening Accounting Balance"), - "youtube_id": "kdgM20Q-q68" - }, - { - "type": "help", - "label": _("Setting up Taxes"), - "youtube_id": "nQ1zZdPgdaQ" - } - ] - } + ] gst = { @@ -617,6 +599,12 @@ def get_data(): "name": "GST Itemised Purchase Register", "is_query_report": True }, + { + "type": "doctype", + "name": "C-Form", + "description": _("C-Form records"), + "country": "India" + }, ] } @@ -624,6 +612,6 @@ def get_data(): countries = frappe.get_all("Company", fields="country") countries = [country["country"] for country in countries] if "India" in countries: - config.insert(7, gst) + config.insert(9, gst) domains = frappe.get_active_domains() return config diff --git a/erpnext/config/buying.py b/erpnext/config/buying.py index ba3492330e..e0f4be9233 100644 --- a/erpnext/config/buying.py +++ b/erpnext/config/buying.py @@ -228,29 +228,5 @@ def get_data(): } ] }, - { - "label": _("Help"), - "items": [ - { - "type": "help", - "label": _("Customer and Supplier"), - "youtube_id": "anoGi_RpQ20" - }, - { - "type": "help", - "label": _("Material Request to Purchase Order"), - "youtube_id": "4TN9kPyfIqM" - }, - { - "type": "help", - "label": _("Purchase Order to Payment"), - "youtube_id": "EK65tLdVUDk" - }, - { - "type": "help", - "label": _("Managing Subcontracting"), - "youtube_id": "ThiMCC2DtKo" - }, - ] - }, + ] diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py index 21e6a505a8..261edaf942 100644 --- a/erpnext/config/hr.py +++ b/erpnext/config/hr.py @@ -4,127 +4,13 @@ from frappe import _ def get_data(): return [ { - "label": _("Employee and Attendance"), + "label": _("Employee"), "items": [ { "type": "doctype", "name": "Employee", "onboard": 1, }, - { - "type": "doctype", - "name": "Employee Attendance Tool", - "hide_count": True, - "onboard": 1, - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Employee Group", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Attendance", - "onboard": 1, - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Attendance Request", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Upload Attendance", - "hide_count": True, - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Employee Checkin", - "hide_count": True, - "onboard": 1, - "dependencies": ["Employee"] - }, - ] - }, - { - "label": _("Payroll"), - "items": [ - { - "type": "doctype", - "name": "Salary Structure", - "onboard": 1, - }, - { - "type": "doctype", - "name": "Salary Structure Assignment", - "onboard": 1, - "dependencies": ["Salary Structure", "Employee"], - }, - { - "type": "doctype", - "name": "Salary Slip", - "onboard": 1, - }, - { - "type": "doctype", - "name": "Payroll Entry", - "onboard": 1, - }, - { - "type": "doctype", - "name": "Employee Benefit Application", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Employee Benefit Claim", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Additional Salary", - }, - { - "type": "doctype", - "name": "Employee Tax Exemption Declaration", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Employee Tax Exemption Proof Submission", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Employee Incentive", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Retention Bonus", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Payroll Period", - }, - { - "type": "doctype", - "name": "Salary Component", - }, - ] - }, - { - "label": _("Settings"), - "icon": "fa fa-cog", - "items": [ - { - "type": "doctype", - "name": "HR Settings", - }, { "type": "doctype", "name": "Employment Type", @@ -147,19 +33,56 @@ def get_data(): }, { "type": "doctype", - "name": "Daily Work Summary Group" + "name": "Employee Group", + "dependencies": ["Employee"] }, { "type": "doctype", "name": "Employee Health Insurance" }, - { - "type": "doctype", - "name": "Staffing Plan", - } ] }, - + { + "label": _("Attendance"), + "items": [ + { + "type": "doctype", + "name": "Employee Attendance Tool", + "hide_count": True, + "onboard": 1, + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Attendance", + "onboard": 1, + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Attendance Request", + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Upload Attendance", + "hide_count": True, + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Employee Checkin", + "hide_count": True, + "dependencies": ["Employee"] + }, + { + "type": "report", + "is_query_report": True, + "name": "Monthly Attendance Sheet", + "doctype": "Attendance" + }, + ] + }, { "label": _("Leaves"), "items": [ @@ -175,13 +98,8 @@ def get_data(): }, { "type": "doctype", - "name": "Compensatory Leave Request", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Leave Encashment", - "dependencies": ["Employee"] + "name": "Leave Policy", + "dependencies": ["Leave Type"] }, { "type": "doctype", @@ -194,37 +112,167 @@ def get_data(): }, { "type": "doctype", - "name": "Leave Policy", - "dependencies": ["Leave Type"] + "name": "Holiday List", }, { "type": "doctype", - "name": "Holiday List", + "name": "Compensatory Leave Request", + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Leave Encashment", + "dependencies": ["Employee"] }, { "type": "doctype", "name": "Leave Block List", }, + { + "type": "report", + "is_query_report": True, + "name": "Employee Leave Balance", + "doctype": "Leave Application" + }, ] }, { - "label": _("Recruitment and Training"), + "label": _("Payroll"), "items": [ { "type": "doctype", - "name": "Job Applicant", + "name": "Salary Structure", "onboard": 1, }, + { + "type": "doctype", + "name": "Salary Structure Assignment", + "onboard": 1, + "dependencies": ["Salary Structure", "Employee"], + }, + { + "type": "doctype", + "name": "Payroll Entry", + "onboard": 1, + }, + { + "type": "doctype", + "name": "Salary Slip", + "onboard": 1, + }, + { + "type": "doctype", + "name": "Salary Component", + }, + { + "type": "doctype", + "name": "Additional Salary", + }, + { + "type": "doctype", + "name": "Retention Bonus", + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Employee Incentive", + "dependencies": ["Employee"] + }, + { + "type": "report", + "is_query_report": True, + "name": "Salary Register", + "doctype": "Salary Slip" + }, + ] + }, + { + "label": _("Employee Tax and Benefits"), + "items": [ + { + "type": "doctype", + "name": "Employee Tax Exemption Declaration", + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Employee Tax Exemption Proof Submission", + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Employee Benefit Application", + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Employee Benefit Claim", + "dependencies": ["Employee"] + }, + ] + }, + { + "label": _("Employee Lifecycle"), + "items": [ + { + "type": "doctype", + "name": "Employee Onboarding", + "dependencies": ["Job Applicant"], + }, + { + "type": "doctype", + "name": "Employee Promotion", + "dependencies": ["Employee"], + }, + { + "type": "doctype", + "name": "Employee Transfer", + "dependencies": ["Employee"], + }, + { + "type": "doctype", + "name": "Employee Separation", + "dependencies": ["Employee"], + }, + { + "type": "doctype", + "name": "Employee Onboarding Template", + "dependencies": ["Employee"] + }, + { + "type": "doctype", + "name": "Employee Separation Template", + "dependencies": ["Employee"] + }, + ] + }, + { + "label": _("Recruitment"), + "items": [ { "type": "doctype", "name": "Job Opening", "onboard": 1, }, + { + "type": "doctype", + "name": "Job Applicant", + "onboard": 1, + }, { "type": "doctype", "name": "Job Offer", "onboard": 1, }, + { + "type": "doctype", + "name": "Staffing Plan", + }, + ] + }, + { + "label": _("Training"), + "items": [ { "type": "doctype", "name": "Training Program" @@ -244,42 +292,7 @@ def get_data(): ] }, { - "label": _("Employee Lifecycle"), - "items": [ - { - "type": "doctype", - "name": "Employee Transfer", - "dependencies": ["Employee"], - }, - { - "type": "doctype", - "name": "Employee Promotion", - "dependencies": ["Employee"], - }, - { - "type": "doctype", - "name": "Employee Separation", - "dependencies": ["Employee"], - }, - { - "type": "doctype", - "name": "Employee Onboarding", - "dependencies": ["Job Applicant"], - }, - { - "type": "doctype", - "name": "Employee Separation Template", - "dependencies": ["Employee"] - }, - { - "type": "doctype", - "name": "Employee Onboarding Template", - "dependencies": ["Employee"] - } - ] - }, - { - "label": _("Appraisals, Expense Claims and Loans"), + "label": _("Performance"), "items": [ { "type": "doctype", @@ -290,15 +303,24 @@ def get_data(): "name": "Appraisal Template", }, { - "type": "page", - "name": "team-updates", - "label": _("Team Updates") + "type": "doctype", + "name": "Energy Point Rule", }, { "type": "doctype", - "name": "Employee Advance", - "dependencies": ["Employee"] + "name": "Energy Point Log", }, + { + "type": "link", + "doctype": "Energy Point Log", + "label": _("Energy Point Leaderboard"), + "route": "#social/users" + }, + ] + }, + { + "label": _("Expense Claims"), + "items": [ { "type": "doctype", "name": "Expense Claim", @@ -306,8 +328,14 @@ def get_data(): }, { "type": "doctype", - "name": "Loan Type", + "name": "Employee Advance", + "dependencies": ["Employee"] }, + ] + }, + { + "label": _("Loans"), + "items": [ { "type": "doctype", "name": "Loan Application", @@ -316,19 +344,72 @@ def get_data(): { "type": "doctype", "name": "Loan" - } + }, + { + "type": "doctype", + "name": "Loan Type", + }, + ] + }, + { + "label": _("Shift Management"), + "items": [ + { + "type": "doctype", + "name": "Shift Type", + }, + { + "type": "doctype", + "name": "Shift Request", + }, + { + "type": "doctype", + "name": "Shift Assignment", + }, + ] + }, + { + "label": _("Fleet Management"), + "items": [ + { + "type": "doctype", + "name": "Vehicle" + }, + { + "type": "doctype", + "name": "Vehicle Log" + }, + { + "type": "report", + "is_query_report": True, + "name": "Vehicle Expenses", + "doctype": "Vehicle" + }, + ] + }, + { + "label": _("Settings"), + "icon": "fa fa-cog", + "items": [ + { + "type": "doctype", + "name": "HR Settings", + }, + { + "type": "doctype", + "name": "Daily Work Summary Group" + }, + { + "type": "page", + "name": "team-updates", + "label": _("Team Updates") + }, ] }, { "label": _("Reports"), "icon": "fa fa-list", "items": [ - { - "type": "report", - "is_query_report": True, - "name": "Employee Leave Balance", - "doctype": "Leave Application" - }, { "type": "report", "is_query_report": True, @@ -341,29 +422,6 @@ def get_data(): "name": "Employees working on a holiday", "doctype": "Employee" }, - { - "type": "report", - "name": "Employee Information", - "doctype": "Employee" - }, - { - "type": "report", - "is_query_report": True, - "name": "Salary Register", - "doctype": "Salary Slip" - }, - { - "type": "report", - "is_query_report": True, - "name": "Monthly Attendance Sheet", - "doctype": "Attendance" - }, - { - "type": "report", - "is_query_report": True, - "name": "Vehicle Expenses", - "doctype": "Vehicle" - }, { "type": "report", "is_query_report": True, @@ -372,50 +430,4 @@ def get_data(): }, ] }, - { - "label": _("Shifts and Fleet Management"), - "items": [ - { - "type": "doctype", - "name": "Shift Type", - }, - { - "type": "doctype", - "name": "Shift Request", - }, - { - "type": "doctype", - "name": "Shift Assignment", - }, - { - "type": "doctype", - "name": "Vehicle" - }, - { - "type": "doctype", - "name": "Vehicle Log" - }, - ] - }, - # { - # "label": _("Help"), - # "icon": "fa fa-facetime-video", - # "items": [ - # { - # "type": "help", - # "label": _("Setting up Employees"), - # "youtube_id": "USfIUdZlUhw" - # }, - # { - # "type": "help", - # "label": _("Leave Management"), - # "youtube_id": "fc0p_AXebc8" - # }, - # { - # "type": "help", - # "label": _("Expense Claims"), - # "youtube_id": "5SZHJF--ZFY" - # } - # ] - # }, ] diff --git a/erpnext/config/projects.py b/erpnext/config/projects.py index 5a907fff48..40960e6778 100644 --- a/erpnext/config/projects.py +++ b/erpnext/config/projects.py @@ -90,15 +90,5 @@ def get_data(): }, ] }, - { - "label": _("Help"), - "icon": "fa fa-facetime-video", - "items": [ - { - "type": "help", - "label": _("Managing Projects"), - "youtube_id": "egxIGwtoKI4" - }, - ] - }, + ] diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py index f18aadb9ef..844710d47c 100644 --- a/erpnext/config/selling.py +++ b/erpnext/config/selling.py @@ -318,41 +318,5 @@ def get_data(): } ] }, - { - "label": _("SMS"), - "icon": "fa fa-wrench", - "items": [ - { - "type": "doctype", - "name": "SMS Center", - "description":_("Send mass SMS to your contacts"), - }, - { - "type": "doctype", - "name": "SMS Log", - "description":_("Logs for maintaining sms delivery status"), - }, - - ] - }, - { - "label": _("Help"), - "items": [ - { - "type": "help", - "label": _("Customer and Supplier"), - "youtube_id": "anoGi_RpQ20" - }, - { - "type": "help", - "label": _("Sales Order to Payment"), - "youtube_id": "1eP90MWoDQM" - }, - { - "type": "help", - "label": _("Point-of-Sale"), - "youtube_id": "4WkelWkbP_c" - }, - ] - }, + ] diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py index f5e48b3b14..7d66df2360 100644 --- a/erpnext/config/stock.py +++ b/erpnext/config/stock.py @@ -329,45 +329,5 @@ def get_data(): } ] }, - { - "label": _("Help"), - "icon": "fa fa-facetime-video", - "items": [ - { - "type": "help", - "label": _("Items and Pricing"), - "youtube_id": "qXaEwld4_Ps" - }, - { - "type": "help", - "label": _("Item Variants"), - "youtube_id": "OGBETlCzU5o" - }, - { - "type": "help", - "label": _("Opening Stock Balance"), - "youtube_id": "0yPgrtfeCTs" - }, - { - "type": "help", - "label": _("Making Stock Entries"), - "youtube_id": "Njt107hlY3I" - }, - { - "type": "help", - "label": _("Serialized Inventory"), - "youtube_id": "gvOVlEwFDAk" - }, - { - "type": "help", - "label": _("Batch Inventory"), - "youtube_id": "J0QKl7ABPKM" - }, - { - "type": "help", - "label": _("Managing Subcontracting"), - "youtube_id": "ThiMCC2DtKo" - }, - ] - } + ] From 94a0d45b7792d766db95238e3ff303f6a26d89da Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 15 Jul 2019 08:36:50 +0000 Subject: [PATCH 11/21] fix: do not add an extra day (#18311) --- erpnext/support/doctype/issue/issue.py | 3 ++- erpnext/www/lms/macros/__init__.py | 0 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 erpnext/www/lms/macros/__init__.py diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index ce9fb12145..98d8c99809 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -270,7 +270,8 @@ def get_expected_time_for(parameter, service_level, start_date_time): allotted_days -= 1 expected_time_is_set = allotted_days <= 0 - current_date_time = add_to_date(current_date_time, days=1) + if not expected_time_is_set: + current_date_time = add_to_date(current_date_time, days=1) if end_time and time_period != 'Hour': current_date_time = datetime.combine(getdate(current_date_time), get_time(end_time)) diff --git a/erpnext/www/lms/macros/__init__.py b/erpnext/www/lms/macros/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 1ac9a8e82ed92e72455f4f6c761faeb4c121f210 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 15 Jul 2019 14:08:47 +0530 Subject: [PATCH 12/21] fix(bin): update requested qty in bin (#18297) --- erpnext/patches.txt | 3 ++- ...t_requested_qty_for_non_stock_uom_items.py | 21 +++++++++++++++++++ erpnext/stock/stock_balance.py | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index a29378547e..f5666dfc60 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -505,6 +505,7 @@ erpnext.patches.v10_0.update_hub_connector_domain erpnext.patches.v10_0.set_student_party_type erpnext.patches.v10_0.update_project_in_sle erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract +erpnext.patches.v10_0.repost_requested_qty_for_non_stock_uom_items erpnext.patches.v11_0.merge_land_unit_with_location erpnext.patches.v11_0.add_index_on_nestedset_doctypes erpnext.patches.v11_0.remove_modules_setup_page @@ -619,4 +620,4 @@ erpnext.patches.v12_0.delete_priority_property_setter execute:frappe.delete_doc("DocType", "Project Task") erpnext.patches.v11_1.update_default_supplier_in_item_defaults erpnext.patches.v12_0.update_due_date_in_gle -erpnext.patches.v12_0.add_default_buying_selling_terms_in_company +erpnext.patches.v12_0.add_default_buying_selling_terms_in_company \ No newline at end of file diff --git a/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py b/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py new file mode 100644 index 0000000000..4fe4e97cf5 --- /dev/null +++ b/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py @@ -0,0 +1,21 @@ +# Copyright (c) 2019, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty + + count=0 + for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse + from `tabMaterial Request Item` where docstatus = 1 and stock_uom<>uom"""): + try: + count += 1 + update_bin_qty(item_code, warehouse, { + "indented_qty": get_indented_qty(item_code, warehouse), + }) + if count % 200 == 0: + frappe.db.commit() + except: + frappe.db.rollback() diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index 4d07a0e857..d68f97917f 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -110,7 +110,7 @@ def get_reserved_qty(item_code, warehouse): return flt(reserved_qty[0][0]) if reserved_qty else 0 def get_indented_qty(item_code, warehouse): - indented_qty = frappe.db.sql("""select sum(mr_item.qty - mr_item.ordered_qty) + indented_qty = frappe.db.sql("""select sum((mr_item.qty - mr_item.ordered_qty) * mr_item.conversion_factor) from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr where mr_item.item_code=%s and mr_item.warehouse=%s and mr_item.qty > mr_item.ordered_qty and mr_item.parent=mr.name From e37ff3983675524210160c9db403e0346ad3a2d8 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 15 Jul 2019 14:16:52 +0530 Subject: [PATCH 13/21] fix: Validate loan repayment amount in Loan Application (#18169) * fix: validate loan repayment amount * fix: test for loan application --- .../loan_application/loan_application.py | 9 +++++--- .../loan_application/test_loan_application.py | 21 ++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/erpnext/hr/doctype/loan_application/loan_application.py b/erpnext/hr/doctype/loan_application/loan_application.py index 5dbcf15eac..67be9f2a1c 100644 --- a/erpnext/hr/doctype/loan_application/loan_application.py +++ b/erpnext/hr/doctype/loan_application/loan_application.py @@ -29,9 +29,12 @@ class LoanApplication(Document): if self.repayment_method == "Repay Fixed Amount per Period": monthly_interest_rate = flt(self.rate_of_interest) / (12 *100) if monthly_interest_rate: - self.repayment_periods = math.ceil((math.log(self.repayment_amount) - - math.log(self.repayment_amount - (self.loan_amount*monthly_interest_rate))) / - (math.log(1 + monthly_interest_rate))) + min_repayment_amount = self.loan_amount*monthly_interest_rate + if self.repayment_amount - min_repayment_amount < 0: + frappe.throw(_("Repayment Amount must be greater than " \ + + str(flt(min_repayment_amount, 2)))) + self.repayment_periods = math.ceil(math.log(self.repayment_amount) - + math.log(self.repayment_amount - min_repayment_amount) /(math.log(1 + monthly_interest_rate))) else: self.repayment_periods = self.loan_amount / self.repayment_amount diff --git a/erpnext/hr/doctype/loan_application/test_loan_application.py b/erpnext/hr/doctype/loan_application/test_loan_application.py index 7644dd0c9f..b08b522503 100644 --- a/erpnext/hr/doctype/loan_application/test_loan_application.py +++ b/erpnext/hr/doctype/loan_application/test_loan_application.py @@ -31,21 +31,22 @@ class TestLoanApplication(unittest.TestCase): "rate_of_interest": 9.2, "loan_amount": 250000, "repayment_method": "Repay Over Number of Periods", - "repayment_periods": 24 + "repayment_periods": 18 }) loan_application.insert() - + def test_loan_totals(self): loan_application = frappe.get_doc("Loan Application", {"applicant":self.applicant}) - self.assertEquals(loan_application.repayment_amount, 11445) - self.assertEquals(loan_application.total_payable_interest, 24657) - self.assertEquals(loan_application.total_payable_amount, 274657) - loan_application.repayment_method = "Repay Fixed Amount per Period" - loan_application.repayment_amount = 15000 + self.assertEqual(loan_application.total_payable_interest, 18599) + self.assertEqual(loan_application.total_payable_amount, 268599) + self.assertEqual(loan_application.repayment_amount, 14923) + + loan_application.repayment_periods = 24 loan_application.save() + loan_application.reload() - self.assertEqual(loan_application.repayment_periods, 18) - self.assertEqual(loan_application.total_payable_interest, 18506) - self.assertEqual(loan_application.total_payable_amount, 268506) \ No newline at end of file + self.assertEqual(loan_application.total_payable_interest, 24657) + self.assertEqual(loan_application.total_payable_amount, 274657) + self.assertEqual(loan_application.repayment_amount, 11445) From 280fe396b9891f19cc45a6ee8fe007e499b33649 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 15 Jul 2019 14:30:21 +0530 Subject: [PATCH 14/21] fix: Dont rebuild cache on cache bust (#18319) - Results in a lot of stale background jobs - Cache will be built when needed --- 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 6484b93485..03e903c06f 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -1007,7 +1007,7 @@ def invalidate_item_variants_cache_for_website(doc): if item_code: item_cache = ItemVariantsCacheManager(item_code) - item_cache.rebuild_cache() + item_cache.clear_cache() def check_stock_uom_with_bin(item, stock_uom): From 1abd1e79a9763b5187e5c4eb4f9df37e9e9f894a Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 15 Jul 2019 14:34:10 +0530 Subject: [PATCH 15/21] fix: Module Links (#18318) * fix: Add Project Billing Summary link * fix: Bank Guarantee shouldn't depend on Bank Guarantee --- erpnext/config/projects.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/config/projects.py b/erpnext/config/projects.py index 40960e6778..47700d10b2 100644 --- a/erpnext/config/projects.py +++ b/erpnext/config/projects.py @@ -88,6 +88,13 @@ def get_data(): "doctype": "Project", "dependencies": ["Project"], }, + { + "type": "report", + "is_query_report": True, + "name": "Project Billing Summary", + "doctype": "Project", + "dependencies": ["Project"], + }, ] }, From ec810a4a55eb9b3036f04716f805584e081fe07f Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Mon, 15 Jul 2019 16:54:41 +0530 Subject: [PATCH 16/21] fix(product_page): compare type as well and provide base class for parseInt (#18332) --- erpnext/templates/includes/product_page.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js index af98fc7987..65949bb18c 100644 --- a/erpnext/templates/includes/product_page.js +++ b/erpnext/templates/includes/product_page.js @@ -29,10 +29,10 @@ frappe.ready(function() { .html(r.message.product_info.price.formatted_price_sales_uom + "
\ (" + r.message.product_info.price.formatted_price + " / " + r.message.product_info.uom + ")
"); - if(r.message.product_info.in_stock==0) { + if(r.message.product_info.in_stock===0) { $(".item-stock").html("
{{ _("Not in stock") }}
"); } - else if(r.message.product_info.in_stock==1) { + else if(r.message.product_info.in_stock===1) { var qty_display = "{{ _("In stock") }}"; if (r.message.product_info.show_stock_qty) { qty_display += " ("+r.message.product_info.stock_qty+")"; @@ -75,13 +75,13 @@ frappe.ready(function() { newVal = 0; if (btn.attr('data-dir') == 'up') { - newVal = parseInt(oldValue) + 1; + newVal = Number.parseInt(oldValue) + 1; } else if (btn.attr('data-dir') == 'dwn') { - if (parseInt(oldValue) > 1) { - newVal = parseInt(oldValue) - 1; + if (Number.parseInt(oldValue) > 1) { + newVal = Number.parseInt(oldValue) - 1; } else { - newVal = parseInt(oldValue); + newVal = Number.parseInt(oldValue); } } input.val(newVal); From 7697066cc2b0d493138fb8cfae1d6a70f80f1371 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Mon, 15 Jul 2019 16:55:06 +0530 Subject: [PATCH 17/21] fix(sales_order_list): compare type as well (#18331) * fix(sales_order_list): compare type as well * fix(sales_order_list): compare type as well --- erpnext/selling/doctype/sales_order/sales_order_list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js index 15c9eb550f..301ecde638 100644 --- a/erpnext/selling/doctype/sales_order/sales_order_list.js +++ b/erpnext/selling/doctype/sales_order/sales_order_list.js @@ -34,7 +34,7 @@ frappe.listview_settings['Sales Order'] = { "per_delivered,<,100|per_billed,=,100|status,!=,Closed"]; } - } else if ((flt(doc.per_delivered, 6) == 100) + } else if ((flt(doc.per_delivered, 6) === 100) && flt(doc.grand_total) !== 0 && flt(doc.per_billed, 6) < 100 && doc.status !== "Closed") { // to bill @@ -48,7 +48,7 @@ frappe.listview_settings['Sales Order'] = { if(flt(doc.per_billed, 6) < 100 ){ return [__("To Deliver and Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Closed"]; - }else if(flt(doc.per_billed, 6) == 100){ + }else if(flt(doc.per_billed, 6) === 100){ return [__("To Deliver"), "orange", "per_delivered,=,100|per_billed,=,100|status,!=,Closed"]; } } From 39c3cfa25dbb0a5e93c08baf5902799849092839 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Mon, 15 Jul 2019 16:55:26 +0530 Subject: [PATCH 18/21] fix(hr_setting): fix translation method call (#18328) --- erpnext/hr/doctype/hr_settings/hr_settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.js b/erpnext/hr/doctype/hr_settings/hr_settings.js index 9e5effe6a3..4004c1cc2d 100644 --- a/erpnext/hr/doctype/hr_settings/hr_settings.js +++ b/erpnext/hr/doctype/hr_settings/hr_settings.js @@ -15,7 +15,7 @@ frappe.ui.form.on('HR Settings', { let policy = frm.doc.password_policy; if (policy) { if (policy.includes(' ') || policy.includes('--')) { - frappe.msgprint(_("Password policy cannot contain spaces or simultaneous hyphens. The format will be restructured automatically")); + frappe.msgprint(__("Password policy cannot contain spaces or simultaneous hyphens. The format will be restructured automatically")); } frm.set_value('password_policy', policy.split(new RegExp(" |-", 'g')).filter((token) => token).join('-')); } From 868766ddf082f176f8ee1d4b8cf6c55e5a81d35f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 15 Jul 2019 18:02:58 +0530 Subject: [PATCH 19/21] refactor: Refactored over delivery/receipt/billing fields (#17788) * refact: Refactored over delivery/receipt/billing fields * fix: test case --- .../accounts_settings/accounts_settings.json | 11 ++- .../purchase_order/test_purchase_order.py | 14 +++- erpnext/controllers/accounts_controller.py | 59 +++++++------- erpnext/controllers/status_updater.py | 79 ++++++++++++------- erpnext/patches.txt | 1 + .../patches/v12_0/rename_tolerance_fields.py | 15 ++++ erpnext/public/js/queries.js | 2 +- .../doctype/sales_order/test_sales_order.py | 13 +-- .../doctype/delivery_note/delivery_note.py | 2 +- erpnext/stock/doctype/item/item.json | 33 +++++--- .../stock_settings/stock_settings.json | 6 +- 11 files changed, 152 insertions(+), 83 deletions(-) create mode 100644 erpnext/patches/v12_0/rename_tolerance_fields.py diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index c2372bd111..4ff4212920 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -10,6 +10,7 @@ "acc_frozen_upto", "frozen_accounts_modifier", "determine_address_tax_category_from", + "over_billing_allowance", "column_break_4", "credit_controller", "check_supplier_invoice_uniqueness", @@ -168,12 +169,18 @@ "fieldname": "automatically_fetch_payment_terms", "fieldtype": "Check", "label": "Automatically Fetch Payment Terms" + }, + { + "description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.", + "fieldname": "over_billing_allowance", + "fieldtype": "Currency", + "label": "Over Billing Allowance (%)" } ], "icon": "icon-cog", "idx": 1, "issingle": 1, - "modified": "2019-04-28 18:20:55.789946", + "modified": "2019-07-04 18:20:55.789946", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", @@ -200,4 +207,4 @@ "quick_entry": 1, "sort_order": "ASC", "track_changes": 1 - } \ No newline at end of file + } diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index be68594d29..ff0b65b7be 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import unittest import frappe +import json import frappe.defaults from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from frappe.utils import flt, add_days, nowdate, getdate @@ -15,7 +16,7 @@ from erpnext.stock.doctype.material_request.test_material_request import make_ma from erpnext.stock.doctype.material_request.material_request import make_purchase_order from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.controllers.accounts_controller import update_child_qty_rate -import json +from erpnext.controllers.status_updater import OverAllowanceError class TestPurchaseOrder(unittest.TestCase): def test_make_purchase_receipt(self): @@ -41,7 +42,7 @@ class TestPurchaseOrder(unittest.TestCase): po.load_from_db() self.assertEqual(po.get("items")[0].received_qty, 4) - frappe.db.set_value('Item', '_Test Item', 'tolerance', 50) + frappe.db.set_value('Item', '_Test Item', 'over_delivery_receipt_allowance', 50) pr = create_pr_against_po(po.name, received_qty=8) self.assertEqual(get_ordered_qty(), existing_ordered_qty) @@ -57,12 +58,12 @@ class TestPurchaseOrder(unittest.TestCase): def test_ordered_qty_against_pi_with_update_stock(self): existing_ordered_qty = get_ordered_qty() - po = create_purchase_order() self.assertEqual(get_ordered_qty(), existing_ordered_qty + 10) - frappe.db.set_value('Item', '_Test Item', 'tolerance', 50) + frappe.db.set_value('Item', '_Test Item', 'over_delivery_receipt_allowance', 50) + frappe.db.set_value('Item', '_Test Item', 'over_billing_allowance', 20) pi = make_pi_from_po(po.name) pi.update_stock = 1 @@ -81,6 +82,11 @@ class TestPurchaseOrder(unittest.TestCase): po.load_from_db() self.assertEqual(po.get("items")[0].received_qty, 0) + frappe.db.set_value('Item', '_Test Item', 'over_delivery_receipt_allowance', 0) + frappe.db.set_value('Item', '_Test Item', 'over_billing_allowance', 0) + frappe.db.set_value("Accounts Settings", None, "over_billing_allowance", 0) + + def test_update_child_qty_rate(self): mr = make_material_request(qty=10) po = make_purchase_order(mr.name) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index f5ecaeb286..47f56cbfb1 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -475,21 +475,20 @@ class AccountsController(TransactionBase): order_doctype = "Purchase Order" order_list = list(set([d.get(order_field) - for d in self.get("items") if d.get(order_field)])) + for d in self.get("items") if d.get(order_field)])) journal_entries = get_advance_journal_entries(party_type, party, party_account, - amount_field, order_doctype, order_list, include_unallocated) + amount_field, order_doctype, order_list, include_unallocated) payment_entries = get_advance_payment_entries(party_type, party, party_account, - order_doctype, order_list, include_unallocated) + order_doctype, order_list, include_unallocated) res = journal_entries + payment_entries return res def is_inclusive_tax(self): - is_inclusive = cint(frappe.db.get_single_value("Accounts Settings", - "show_inclusive_tax_in_print")) + is_inclusive = cint(frappe.db.get_single_value("Accounts Settings", "show_inclusive_tax_in_print")) if is_inclusive: is_inclusive = 0 @@ -501,7 +500,7 @@ class AccountsController(TransactionBase): def validate_advance_entries(self): order_field = "sales_order" if self.doctype == "Sales Invoice" else "purchase_order" order_list = list(set([d.get(order_field) - for d in self.get("items") if d.get(order_field)])) + for d in self.get("items") if d.get(order_field)])) if not order_list: return @@ -513,7 +512,7 @@ class AccountsController(TransactionBase): if not advance_entries_against_si or d.reference_name not in advance_entries_against_si: frappe.msgprint(_( "Payment Entry {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.") - .format(d.reference_name, d.against_order)) + .format(d.reference_name, d.against_order)) def update_against_document_in_jv(self): """ @@ -551,9 +550,9 @@ class AccountsController(TransactionBase): 'unadjusted_amount': flt(d.advance_amount), 'allocated_amount': flt(d.allocated_amount), 'exchange_rate': (self.conversion_rate - if self.party_account_currency != self.company_currency else 1), + if self.party_account_currency != self.company_currency else 1), 'grand_total': (self.base_grand_total - if self.party_account_currency == self.company_currency else self.grand_total), + if self.party_account_currency == self.company_currency else self.grand_total), 'outstanding_amount': self.outstanding_amount }) lst.append(args) @@ -576,36 +575,37 @@ class AccountsController(TransactionBase): unlink_ref_doc_from_payment_entries(self) def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield): - from erpnext.controllers.status_updater import get_tolerance_for - item_tolerance = {} - global_tolerance = None + from erpnext.controllers.status_updater import get_allowance_for + item_allowance = {} + global_qty_allowance, global_amount_allowance = None, None for item in self.get("items"): if item.get(item_ref_dn): ref_amt = flt(frappe.db.get_value(ref_dt + " Item", - item.get(item_ref_dn), based_on), self.precision(based_on, item)) + item.get(item_ref_dn), based_on), self.precision(based_on, item)) if not ref_amt: frappe.msgprint( - _("Warning: System will not check overbilling since amount for Item {0} in {1} is zero").format( - item.item_code, ref_dt)) + _("Warning: System will not check overbilling since amount for Item {0} in {1} is zero") + .format(item.item_code, ref_dt)) else: - already_billed = frappe.db.sql("""select sum(%s) from `tab%s` - where %s=%s and docstatus=1 and parent != %s""" % - (based_on, self.doctype + " Item", item_ref_dn, '%s', '%s'), - (item.get(item_ref_dn), self.name))[0][0] + already_billed = frappe.db.sql(""" + select sum(%s) + from `tab%s` + where %s=%s and docstatus=1 and parent != %s + """ % (based_on, self.doctype + " Item", item_ref_dn, '%s', '%s'), + (item.get(item_ref_dn), self.name))[0][0] total_billed_amt = flt(flt(already_billed) + flt(item.get(based_on)), - self.precision(based_on, item)) + self.precision(based_on, item)) - tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code, - item_tolerance, global_tolerance) + allowance, item_allowance, global_qty_allowance, global_amount_allowance = \ + get_allowance_for(item.item_code, item_allowance, global_qty_allowance, global_amount_allowance, "amount") - max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100) + max_allowed_amt = flt(ref_amt * (100 + allowance) / 100) if total_billed_amt - max_allowed_amt > 0.01: - frappe.throw(_( - "Cannot overbill for Item {0} in row {1} more than {2}. To allow over-billing, please set in Stock Settings").format( - item.item_code, item.idx, max_allowed_amt)) + frappe.throw(_("Cannot overbill for Item {0} in row {1} more than {2}. To allow over-billing, please set in Stock Settings") + .format(item.item_code, item.idx, max_allowed_amt)) def get_company_default(self, fieldname): from erpnext.accounts.utils import get_company_default @@ -615,9 +615,10 @@ class AccountsController(TransactionBase): stock_items = [] item_codes = list(set(item.item_code for item in self.get("items"))) if item_codes: - stock_items = [r[0] for r in frappe.db.sql("""select name - from `tabItem` where name in (%s) and is_stock_item=1""" % \ - (", ".join((["%s"] * len(item_codes))),), item_codes)] + stock_items = [r[0] for r in frappe.db.sql(""" + select name from `tabItem` + where name in (%s) and is_stock_item=1 + """ % (", ".join((["%s"] * len(item_codes))),), item_codes)] return stock_items diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index b193ac2b6d..a7ec73ad9d 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -7,6 +7,8 @@ from frappe.utils import flt, comma_or, nowdate, getdate from frappe import _ from frappe.model.document import Document +class OverAllowanceError(frappe.ValidationError): pass + def validate_status(status, options): if status not in options: frappe.throw(_("Status must be one of {0}").format(comma_or(options))) @@ -154,8 +156,9 @@ class StatusUpdater(Document): def validate_qty(self): """Validates qty at row level""" - self.tolerance = {} - self.global_tolerance = None + self.item_allowance = {} + self.global_qty_allowance = None + self.global_amount_allowance = None for args in self.status_updater: if "target_ref_field" not in args: @@ -186,32 +189,41 @@ class StatusUpdater(Document): # if not item[args['target_ref_field']]: # msgprint(_("Note: System will not check over-delivery and over-booking for Item {0} as quantity or amount is 0").format(item.item_code)) - if args.get('no_tolerance'): + if args.get('no_allowance'): item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']] if item['reduce_by'] > .01: self.limits_crossed_error(args, item) elif item[args['target_ref_field']]: - self.check_overflow_with_tolerance(item, args) + self.check_overflow_with_allowance(item, args) - def check_overflow_with_tolerance(self, item, args): + def check_overflow_with_allowance(self, item, args): """ - Checks if there is overflow condering a relaxation tolerance + Checks if there is overflow condering a relaxation allowance """ - # check if overflow is within tolerance - tolerance, self.tolerance, self.global_tolerance = get_tolerance_for(item['item_code'], - self.tolerance, self.global_tolerance) + qty_or_amount = "qty" if "qty" in args['target_ref_field'] else "amount" + + # check if overflow is within allowance + allowance, self.item_allowance, self.global_qty_allowance, self.global_amount_allowance = \ + get_allowance_for(item['item_code'], self.item_allowance, + self.global_qty_allowance, self.global_amount_allowance, qty_or_amount) + overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) / item[args['target_ref_field']]) * 100 - if overflow_percent - tolerance > 0.01: - item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100) + if overflow_percent - allowance > 0.01: + item['max_allowed'] = flt(item[args['target_ref_field']] * (100+allowance)/100) item['reduce_by'] = item[args['target_field']] - item['max_allowed'] - self.limits_crossed_error(args, item) + self.limits_crossed_error(args, item, qty_or_amount) - def limits_crossed_error(self, args, item): + def limits_crossed_error(self, args, item, qty_or_amount): '''Raise exception for limits crossed''' + if qty_or_amount == "qty": + action_msg = _('To allow over receipt / delivery, update "Over Receipt/Delivery Allowance" in Stock Settings or the Item.') + else: + action_msg = _('To allow over billing, update "Over Billing Allowance" in Accounts Settings or the Item.') + frappe.throw(_('This document is over limit by {0} {1} for item {4}. Are you making another {3} against the same {2}?') .format( frappe.bold(_(item["target_ref_field"].title())), @@ -219,9 +231,7 @@ class StatusUpdater(Document): frappe.bold(_(args.get('target_dt'))), frappe.bold(_(self.doctype)), frappe.bold(item.get('item_code')) - ) + '

' + - _('To allow over-billing or over-ordering, update "Allowance" in Stock Settings or the Item.'), - title = _('Limit Crossed')) + ) + '

' + action_msg, OverAllowanceError, title = _('Limit Crossed')) def update_qty(self, update_modified=True): """Updates qty or amount at row level @@ -358,19 +368,34 @@ class StatusUpdater(Document): ref_doc.db_set("per_billed", per_billed) ref_doc.set_status(update=True) -def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None): +def get_allowance_for(item_code, item_allowance={}, global_qty_allowance=None, global_amount_allowance=None, qty_or_amount="qty"): """ - Returns the tolerance for the item, if not set, returns global tolerance + Returns the allowance for the item, if not set, returns global allowance """ - if item_tolerance.get(item_code): - return item_tolerance[item_code], item_tolerance, global_tolerance + if qty_or_amount == "qty": + if item_allowance.get(item_code, frappe._dict()).get("qty"): + return item_allowance[item_code].qty, item_allowance, global_qty_allowance, global_amount_allowance + else: + if item_allowance.get(item_code, frappe._dict()).get("amount"): + return item_allowance[item_code].amount, item_allowance, global_qty_allowance, global_amount_allowance - tolerance = flt(frappe.db.get_value('Item',item_code,'tolerance') or 0) + qty_allowance, over_billing_allowance = \ + frappe.db.get_value('Item', item_code, ['over_delivery_receipt_allowance', 'over_billing_allowance']) - if not tolerance: - if global_tolerance == None: - global_tolerance = flt(frappe.db.get_value('Stock Settings', None, 'tolerance')) - tolerance = global_tolerance + if qty_or_amount == "qty" and not qty_allowance: + if global_qty_allowance == None: + global_qty_allowance = flt(frappe.db.get_single_value('Stock Settings', 'over_delivery_receipt_allowance')) + qty_allowance = global_qty_allowance + elif qty_or_amount == "amount" and not over_billing_allowance: + if global_amount_allowance == None: + global_amount_allowance = flt(frappe.db.get_single_value('Accounts Settings', 'over_billing_allowance')) + over_billing_allowance = global_amount_allowance - item_tolerance[item_code] = tolerance - return tolerance, item_tolerance, global_tolerance + if qty_or_amount == "qty": + allowance = qty_allowance + item_allowance.setdefault(item_code, frappe._dict()).setdefault("qty", qty_allowance) + else: + allowance = over_billing_allowance + item_allowance.setdefault(item_code, frappe._dict()).setdefault("amount", over_billing_allowance) + + return allowance, item_allowance, global_qty_allowance, global_amount_allowance diff --git a/erpnext/patches.txt b/erpnext/patches.txt index f5666dfc60..e5975443cc 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -603,6 +603,7 @@ erpnext.patches.v11_1.set_salary_details_submittable erpnext.patches.v11_1.rename_depends_on_lwp execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool +erpnext.patches.v12_0.rename_tolerance_fields erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019 execute:frappe.delete_doc_if_exists("Page", "support-analytics") erpnext.patches.v12_0.make_item_manufacturer diff --git a/erpnext/patches/v12_0/rename_tolerance_fields.py b/erpnext/patches/v12_0/rename_tolerance_fields.py new file mode 100644 index 0000000000..aa2fff4ca7 --- /dev/null +++ b/erpnext/patches/v12_0/rename_tolerance_fields.py @@ -0,0 +1,15 @@ +import frappe +from frappe.model.utils.rename_field import rename_field + +def execute(): + frappe.reload_doc("stock", "doctype", "item") + frappe.reload_doc("stock", "doctype", "stock_settings") + frappe.reload_doc("accounts", "doctype", "accounts_settings") + + rename_field('Stock Settings', "tolerance", "over_delivery_receipt_allowance") + rename_field('Item', "tolerance", "over_delivery_receipt_allowance") + + qty_allowance = frappe.db.get_single_value("Stock Settings", "over_delivery_receipt_allowance") + frappe.db.set_value("Accounts Settings", None, "over_delivery_receipt_allowance", qty_allowance) + + frappe.db.sql("update tabItem set over_billing_allowance=over_delivery_receipt_allowance") \ No newline at end of file diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js index 560a5617da..84d2113c06 100644 --- a/erpnext/public/js/queries.js +++ b/erpnext/public/js/queries.js @@ -65,7 +65,7 @@ $.extend(erpnext.queries, { frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))])); } - + console.log(frappe.dynamic_link) return { query: 'frappe.contacts.doctype.address.address.address_query', filters: { diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 569c53f628..bd07841488 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -192,8 +192,8 @@ class TestSalesOrder(unittest.TestCase): def test_reserved_qty_for_over_delivery(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) - # set over-delivery tolerance - frappe.db.set_value('Item', "_Test Item", 'tolerance', 50) + # set over-delivery allowance + frappe.db.set_value('Item', "_Test Item", 'over_delivery_receipt_allowance', 50) existing_reserved_qty = get_reserved_qty() @@ -209,8 +209,9 @@ class TestSalesOrder(unittest.TestCase): def test_reserved_qty_for_over_delivery_via_sales_invoice(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) - # set over-delivery tolerance - frappe.db.set_value('Item', "_Test Item", 'tolerance', 50) + # set over-delivery allowance + frappe.db.set_value('Item', "_Test Item", 'over_delivery_receipt_allowance', 50) + frappe.db.set_value('Item', "_Test Item", 'over_billing_allowance', 20) existing_reserved_qty = get_reserved_qty() @@ -291,8 +292,8 @@ class TestSalesOrder(unittest.TestCase): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) - # set over-delivery tolerance - frappe.db.set_value('Item', "_Test Product Bundle Item", 'tolerance', 50) + # set over-delivery allowance + frappe.db.set_value('Item', "_Test Product Bundle Item", 'over_delivery_receipt_allowance', 50) existing_reserved_qty_item1 = get_reserved_qty("_Test Item") existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index ec7df2da6d..2de9b975da 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -51,7 +51,7 @@ class DeliveryNote(SellingController): 'source_field': 'qty', 'percent_join_field': 'against_sales_invoice', 'overflow_type': 'delivery', - 'no_tolerance': 1 + 'no_allowance': 1 }] if cint(self.is_return): self.status_updater.append({ diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 164ffa443b..a142bb9035 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -29,7 +29,8 @@ "is_fixed_asset", "asset_category", "asset_naming_series", - "tolerance", + "over_delivery_receipt_allowance", + "over_billing_allowance", "image", "section_break_11", "brand", @@ -284,14 +285,6 @@ "fieldtype": "Select", "label": "Asset Naming Series" }, - { - "depends_on": "eval:!doc.__islocal", - "fieldname": "tolerance", - "fieldtype": "Float", - "label": "Allow over delivery or receipt upto this percent", - "oldfieldname": "tolerance", - "oldfieldtype": "Currency" - }, { "fieldname": "image", "fieldtype": "Attach Image", @@ -1021,6 +1014,26 @@ "fieldtype": "Check", "label": "Synced With Hub", "read_only": 1 + }, + { + "fieldname": "manufacturers", + "fieldtype": "Table", + "label": "Manufacturers", + "options": "Item Manufacturer" + }, + { + "depends_on": "eval:!doc.__islocal", + "fieldname": "over_delivery_receipt_allowance", + "fieldtype": "Float", + "label": "Over Delivery/Receipt Allowance (%)", + "oldfieldname": "tolerance", + "oldfieldtype": "Currency" + }, + { + "fieldname": "over_billing_allowance", + "fieldtype": "Float", + "label": "Over Billing Allowance (%)", + "depends_on": "eval:!doc.__islocal" } ], "has_web_view": 1, @@ -1028,7 +1041,7 @@ "idx": 2, "image_field": "image", "max_attachments": 1, - "modified": "2019-07-05 12:18:13.977931", + "modified": "2019-07-12 12:18:13.977931", "modified_by": "Administrator", "module": "Stock", "name": "Item", diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json index c989907639..f43390f19d 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.json +++ b/erpnext/stock/doctype/stock_settings/stock_settings.json @@ -255,7 +255,7 @@ "columns": 0, "description": "Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.", "fetch_if_empty": 0, - "fieldname": "tolerance", + "fieldname": "over_delivery_receipt_allowance", "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, @@ -264,7 +264,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Limit Percent", + "label": "Over Delivery/Receipt Allowance (%)", "length": 0, "no_copy": 0, "permlevel": 0, @@ -918,7 +918,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2019-06-18 01:19:07.738045", + "modified": "2019-07-04 01:19:07.738045", "modified_by": "Administrator", "module": "Stock", "name": "Stock Settings", From e9f0e88f9bc4bd58a3e278401856e2285140fa48 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 15 Jul 2019 18:57:25 +0530 Subject: [PATCH 20/21] fix: taxes sequence if shipping rule is set in the sales invoice (#18329) --- erpnext/public/js/controllers/transaction.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 11fdb8b178..844db996a2 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1424,11 +1424,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, callback: function(r) { if(!r.exc) { - me.frm.set_value("taxes", r.message); + if(me.frm.doc.shipping_rule && me.frm.doc.taxes) { + for (let tax of r.message) { + me.frm.add_child("taxes", tax); + } - if(me.frm.doc.shipping_rule) { - me.frm.script_manager.trigger("shipping_rule"); + refresh_field("taxes"); } else { + me.frm.set_value("taxes", r.message); me.calculate_taxes_and_totals(); } } From 4c0dffe6871521eb39cb8b073b57a660d229ebfe Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 16 Jul 2019 01:52:03 +0530 Subject: [PATCH 21/21] feat: added payment terms filter in the accounts payable summary --- .../accounts/report/accounts_payable/accounts_payable.js | 6 ++++++ .../accounts_payable_summary/accounts_payable_summary.js | 6 ++++++ .../report/accounts_receivable/accounts_receivable.py | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index f6a561f04f..cfcc575718 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -88,6 +88,12 @@ frappe.query_reports["Accounts Payable"] = { } } }, + { + "fieldname":"payment_terms_template", + "label": __("Payment Terms Template"), + "fieldtype": "Link", + "options": "Payment Terms Template" + }, { "fieldname":"supplier_group", "label": __("Supplier Group"), diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js index ec4f0c983f..006068a266 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -77,6 +77,12 @@ frappe.query_reports["Accounts Payable Summary"] = { "fieldtype": "Link", "options": "Supplier" }, + { + "fieldname":"payment_terms_template", + "label": __("Payment Terms Template"), + "fieldtype": "Link", + "options": "Payment Terms Template" + }, { "fieldname":"supplier_group", "label": __("Supplier Group"), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 0cda2c15dd..ecf149b335 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -541,6 +541,10 @@ class ReceivablePayableReport(object): where supplier_group=%s)""") values.append(self.filters.get("supplier_group")) + if self.filters.get("payment_terms_template"): + conditions.append("party in (select name from tabSupplier where payment_terms=%s)") + values.append(self.filters.get("payment_terms_template")) + if self.filters.get("cost_center"): lft, rgt = frappe.get_cached_value("Cost Center", self.filters.get("cost_center"), ['lft', 'rgt'])