diff --git a/.github/stale.yml b/.github/stale.yml index 3ad0bff5d7..dabc66eb73 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,7 +1,7 @@ # Configuration for probot-stale - https://github.com/probot/stale # Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 10 +daysUntilStale: 30 # Number of days of inactivity before a stale Issue or Pull Request is closed. # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. diff --git a/.travis.yml b/.travis.yml index d77f9ef5ae..f20128d2cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ before_script: - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR - bench use test_site - - bench reinstall --yes + - bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes - bench build - bench scheduler disable - sed -i 's/9000/9001/g' sites/common_site_config.json diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 92efe8e302..0d5ac9d512 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.1.72' +__version__ = '10.1.74' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py index 86023aa666..eb95e458dc 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -70,12 +70,14 @@ class PeriodClosingVoucher(AccountsController): net_pl_balance += flt(acc.balance_in_company_currency) if net_pl_balance: + cost_center = frappe.db.get_value("Company", self.company, "cost_center") gl_entries.append(self.get_gl_dict({ "account": self.closing_account_head, "debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0, "debit": abs(net_pl_balance) if net_pl_balance > 0 else 0, "credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0, - "credit": abs(net_pl_balance) if net_pl_balance < 0 else 0 + "credit": abs(net_pl_balance) if net_pl_balance < 0 else 0, + "cost_center": cost_center })) from erpnext.accounts.general_ledger import make_gl_entries diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index 9ef66edc34..eb02d97b78 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -72,6 +72,7 @@ class TestPeriodClosingVoucher(unittest.TestCase): "company": "_Test Company", "fiscal_year": get_fiscal_year(today(), company="_Test Company")[0], "posting_date": today(), + "cost_center": "_Test Cost Center - _TC", "remarks": "test" }) pcv.insert() diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js index b62d9b0b60..13d53d1f6a 100755 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.js +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js @@ -37,11 +37,25 @@ frappe.ui.form.on('POS Profile', { return { filters: { doc_type: "Sales Invoice", print_format_type: "Js"} }; }); - frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'use_pos_in_offline_mode', (r) => { - is_offline = r && cint(r.use_pos_in_offline_mode) + frappe.db.get_value('POS Settings', 'POS Settings', 'use_pos_in_offline_mode', (r) => { + const is_offline = r && cint(r.use_pos_in_offline_mode) frm.toggle_display('offline_pos_section', is_offline); frm.toggle_display('print_format_for_online', !is_offline); }); + + frm.set_query('company_address', function(doc) { + if(!doc.company) { + frappe.throw(__('Please set Company')); + } + + return { + query: 'frappe.contacts.doctype.address.address.address_query', + filters: { + link_doctype: 'Company', + link_name: doc.company + } + }; + }); }, refresh: function(frm) { @@ -49,11 +63,11 @@ frappe.ui.form.on('POS Profile', { frm.trigger("toggle_display_account_head"); } }, - + company: function(frm) { frm.trigger("toggle_display_account_head"); }, - + toggle_display_account_head: function(frm) { frm.toggle_display('expense_account', erpnext.is_perpetual_inventory_enabled(frm.doc.company)); diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index 610ed51dd7..077c396c71 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -1,9 +1,10 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 1, - "autoname": "field:pos_profile_name", + "autoname": "Prompt", "beta": 0, "creation": "2013-05-24 12:15:51", "custom": 0, @@ -13,6 +14,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -40,15 +42,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "", "fieldname": "section_break_2", "fieldtype": "Section Break", "hidden": 0, @@ -70,42 +74,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "pos_profile_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "POS Profile Name", - "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, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -134,258 +108,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "description": "", - "fieldname": "update_stock", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Update Stock", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ignore_pricing_rule", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Ignore Pricing Rule", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "allow_delete", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Delete", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "allow_user_to_edit_rate", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow user to edit Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "allow_user_to_edit_discount", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow user to edit Discount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "allow_print_before_pay", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Print Before Pay", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "display_items_in_stock", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Display Items In Stock", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -414,11 +142,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -447,16 +176,17 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "company.country", + "fetch_from": "company.country", "fieldname": "country", "fieldtype": "Read Only", "hidden": 0, @@ -480,11 +210,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -514,11 +245,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -546,15 +278,306 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "fieldname": "company_address", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Company Address", + "length": 0, + "no_copy": 0, + "options": "Address", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "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 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "description": "", + "fieldname": "update_stock", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Update Stock", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "ignore_pricing_rule", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Ignore Pricing Rule", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_delete", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allow Delete", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_user_to_edit_rate", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allow user to edit Rate", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_user_to_edit_discount", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allow user to edit Discount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_print_before_pay", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allow Print Before Pay", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "display_items_in_stock", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Display Items In Stock", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", "fieldname": "section_break_15", "fieldtype": "Section Break", "hidden": 0, @@ -577,11 +600,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -609,11 +633,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -627,6 +652,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, + "label": "Mode of Payment", "length": 0, "no_copy": 0, "permlevel": 0, @@ -639,11 +665,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -671,11 +698,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -690,6 +718,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, + "label": "", "length": 0, "no_copy": 0, "permlevel": 0, @@ -702,15 +731,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "description": "Only show Items from these Item Groups", "fieldname": "item_groups", "fieldtype": "Table", "hidden": 0, @@ -734,11 +765,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -764,15 +796,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "description": "Only show Customer of these Customer Groups", "fieldname": "customer_groups", "fieldtype": "Table", "hidden": 0, @@ -796,11 +830,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -815,6 +850,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, + "label": "Print Settings", "length": 0, "no_copy": 0, "permlevel": 0, @@ -827,11 +863,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -859,11 +896,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -892,44 +930,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "select_print_heading", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Print Heading", - "length": 0, - "no_copy": 0, - "oldfieldname": "select_print_heading", - "oldfieldtype": "Select", - "options": "Print Heading", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -955,44 +961,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "selling_price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "oldfieldname": "price_list_name", - "oldfieldtype": "Select", - "options": "Price List", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1021,50 +995,18 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, - "allow_on_submit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "apply_discount", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Apply Discount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Grand Total", - "depends_on": "", - "fieldname": "apply_discount_on", - "fieldtype": "Select", + "fieldname": "select_print_heading", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1072,12 +1014,13 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Apply Discount On", + "label": "Print Heading", "length": 0, "no_copy": 0, - "options": "Grand Total\nNet Total", + "oldfieldname": "select_print_heading", + "oldfieldtype": "Select", + "options": "Print Heading", "permlevel": 0, - "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -1086,11 +1029,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1105,7 +1049,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Offline POS Section", + "label": "Offline POS Settings", "length": 0, "no_copy": 0, "permlevel": 0, @@ -1118,11 +1062,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1152,11 +1097,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1182,11 +1128,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1215,11 +1162,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1247,11 +1195,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1279,11 +1228,46 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "selling_price_list", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Price List", + "length": 0, + "no_copy": 0, + "oldfieldname": "price_list_name", + "oldfieldtype": "Select", + "options": "Price List", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1312,11 +1296,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1345,11 +1330,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1377,11 +1363,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1409,11 +1396,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1439,11 +1427,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1472,11 +1461,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1504,11 +1494,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1537,11 +1528,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1570,7 +1562,42 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Grand Total", + "depends_on": "", + "fieldname": "apply_discount_on", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Apply Discount On", + "length": 0, + "no_copy": 0, + "options": "Grand Total\nNet Total", + "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 } ], @@ -1585,7 +1612,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-09-05 12:43:37.272875", + "modified": "2018-12-13 13:36:22.045519", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", @@ -1633,11 +1660,12 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, - "search_fields": "pos_profile_name", + "search_fields": "", "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", - "title_field": "pos_profile_name", + "title_field": "", "track_changes": 0, - "track_seen": 0 -} + "track_seen": 0, + "track_views": 0 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index bf2e20c248..723ef4366a 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -127,25 +127,26 @@ def pos_profile_query(doctype, txt, searchfield, start, page_len, filters): 'txt': '%%%s%%' % txt } - pos_profile = frappe.db.sql("""select pf.name, pf.pos_profile_name + pos_profile = frappe.db.sql("""select pf.name from `tabPOS Profile` pf, `tabPOS Profile User` pfu where pfu.parent = pf.name and pfu.user = %(user)s and pf.company = %(company)s - and (pf.name like %(txt)s or pf.pos_profile_name like %(txt)s) + and (pf.name like %(txt)s) and pf.disabled = 0 limit %(start)s, %(page_len)s""", args) if not pos_profile: del args['user'] - pos_profile = frappe.db.sql("""select pf.name, pf.pos_profile_name + pos_profile = frappe.db.sql("""select pf.name from `tabPOS Profile` pf left join `tabPOS Profile User` pfu on pf.name = pfu.parent where - ifnull(pfu.user, '') = '' and pf.company = %(company)s and - (pf.name like %(txt)s or pf.pos_profile_name like %(txt)s) + ifnull(pfu.user, '') = '' + and pf.company = %(company)s + and pf.name like %(txt)s and pf.disabled = 0""", args) return pos_profile diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py index c1b033cdda..58f12162d1 100644 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py @@ -40,7 +40,6 @@ def make_pos_profile(): "expense_account": "_Test Account Cost for Goods Sold - _TC", "income_account": "Sales - _TC", "name": "_Test POS Profile", - "pos_profile_name": "_Test POS Profile", "naming_series": "_T-POS Profile-", "selling_price_list": "_Test Price List", "territory": "_Test Territory", diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 995efee2c0..e4f37c44ff 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -21,8 +21,6 @@ class TestPricingRule(unittest.TestCase): from erpnext.stock.get_item_details import get_item_details from frappe import MandatoryError - - test_record = { "doctype": "Pricing Rule", "title": "_Test Pricing Rule", @@ -93,7 +91,7 @@ class TestPricingRule(unittest.TestCase): args.item_code = "_Test Item 2" details = get_item_details(args) - self.assertEqual(details.get("discount_percentage"), 15) + self.assertEquals(details.get("discount_percentage"), 15) def test_pricing_rule_for_margin(self): from erpnext.stock.get_item_details import get_item_details @@ -137,8 +135,8 @@ class TestPricingRule(unittest.TestCase): "name": None }) details = get_item_details(args) - self.assertEqual(details.get("margin_type"), "Percentage") - self.assertEqual(details.get("margin_rate_or_amount"), 10) + self.assertEquals(details.get("margin_type"), "Percentage") + self.assertEquals(details.get("margin_rate_or_amount"), 10) def test_pricing_rule_for_variants(self): from erpnext.stock.get_item_details import get_item_details @@ -253,6 +251,7 @@ class TestPricingRule(unittest.TestCase): self.assertEqual(so.items[0].rate, 100) def test_pricing_rule_with_margin_and_discount(self): + frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule') make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10, discount_percentage=10) si = create_sales_invoice(do_not_save=True) si.items[0].price_list_rate = 1000 @@ -260,12 +259,11 @@ class TestPricingRule(unittest.TestCase): si.insert(ignore_permissions=True) item = si.items[0] - self.assertEqual(item.margin_rate_or_amount, 10) - self.assertEqual(item.rate_with_margin, 1100) + self.assertEquals(item.margin_rate_or_amount, 10) + self.assertEquals(item.rate_with_margin, 1100) self.assertEqual(item.discount_percentage, 10) - self.assertEqual(item.discount_amount, 110) - self.assertEqual(item.rate, 990) - + self.assertEquals(item.discount_amount, 110) + self.assertEquals(item.rate, 990) def make_pricing_rule(**args): args = frappe._dict(args) @@ -295,4 +293,4 @@ def make_pricing_rule(**args): applicable_for = doc.applicable_for.replace(' ', '_').lower() if args.get(applicable_for): - doc.db_set(applicable_for, args.get(applicable_for)) \ No newline at end of file + doc.db_set(applicable_for, args.get(applicable_for)) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 83698f887c..1bb7c97b0d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -226,7 +226,7 @@ class PurchaseInvoice(BuyingController): item.expense_account = warehouse_account[item.warehouse]["account"] else: item.expense_account = stock_not_billed_account - + elif not item.expense_account and for_validate: throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name)) @@ -379,7 +379,7 @@ class PurchaseInvoice(BuyingController): return gl_entries def make_supplier_gl_entry(self, gl_entries): - # Checked both rounding_adjustment and rounded_total + # Checked both rounding_adjustment and rounded_total # because rounded_total had value even before introcution of posting GLE based on rounded total grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total @@ -859,7 +859,8 @@ def make_stock_entry(source_name, target_doc=None): "Purchase Invoice Item": { "doctype": "Stock Entry Detail", "field_map": { - "stock_qty": "transfer_qty" + "stock_qty": "transfer_qty", + "batch_no": "batch_no" }, } }, target_doc) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index a4588b3dd8..91a44b377d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -313,6 +313,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte erpnext.setup_serial_no(); }, + packed_items_on_form_rendered: function(doc, grid_row) { + erpnext.setup_serial_no(); + }, + make_sales_return: function() { frappe.model.open_mapped_doc({ method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_sales_return", @@ -585,7 +589,7 @@ frappe.ui.form.on('Sales Invoice', { frm.set_query('company_address', function(doc) { if(!doc.company) { - frappe.throw(_('Please set Company')); + frappe.throw(__('Please set Company')); } return { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 6387003f01..f3ec775d54 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -131,7 +131,7 @@ class SalesInvoice(SellingController): #validate amount in mode of payments for returned invoices for pos must be negative if self.is_pos and self.is_return: self.verify_payment_amount_is_negative() - + if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points: validate_loyalty_points(self, self.loyalty_points) @@ -397,7 +397,7 @@ class SalesInvoice(SellingController): self.account_for_change_amount = pos.get('account_for_change_amount') for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name', - 'selling_price_list', 'company', 'select_print_heading', 'cash_bank_account', + 'selling_price_list', 'company', 'select_print_heading', 'cash_bank_account', 'company_address', 'write_off_account', 'write_off_cost_center', 'apply_discount_on'): if (not for_validate) or (for_validate and not self.get(fieldname)): self.set(fieldname, pos.get(fieldname)) @@ -713,7 +713,7 @@ class SalesInvoice(SellingController): return gl_entries def make_customer_gl_entry(self, gl_entries): - # Checked both rounding_adjustment and rounded_total + # Checked both rounding_adjustment and rounded_total # because rounded_total had value even before introcution of posting GLE based on rounded total grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total if grand_total: @@ -1026,7 +1026,7 @@ class SalesInvoice(SellingController): def verify_payment_amount_is_negative(self): for entry in self.payments: if entry.amount > 0: - frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx)) + frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx)) # collection of the loyalty points, create the ledger entry for that. def make_loyalty_point_entry(self): diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.py b/erpnext/accounts/doctype/share_transfer/share_transfer.py index 50ce9f2bfd..1a1f036278 100644 --- a/erpnext/accounts/doctype/share_transfer/share_transfer.py +++ b/erpnext/accounts/doctype/share_transfer/share_transfer.py @@ -189,7 +189,7 @@ class ShareTransfer(Document): if (shareholder == 'from_shareholder') else self.to_folio_no; doc.save() else: - if doc.folio_no != (self.from_folio_no if (shareholder == 'from_shareholder') else self.to_folio_no): + if doc.folio_no and doc.folio_no != (self.from_folio_no if (shareholder == 'from_shareholder') else self.to_folio_no): frappe.throw(_('The folio numbers are not matching')) def autoname_folio(self, shareholder, is_company=False): diff --git a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py index 44ab09999b..f1cf31b820 100644 --- a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py +++ b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py @@ -79,7 +79,8 @@ class TestShareTransfer(unittest.TestCase): } ] for d in share_transfers: - frappe.get_doc(d).submit() + st = frappe.get_doc(d) + st.submit() def test_invalid_share_transfer(self): doc = frappe.get_doc({ diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index e3235f006f..d72a7a6b65 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -333,7 +333,7 @@ def get_due_date_from_template(template_name, posting_date, bill_date): def validate_due_date(posting_date, due_date, party_type, party, company=None, bill_date=None, template_name=None): if getdate(due_date) < getdate(posting_date): - frappe.throw(_("Due Date cannot be before Posting Date")) + frappe.throw(_("Due Date cannot be before Posting / Supplier Invoice Date")) else: if not template_name: return @@ -457,38 +457,65 @@ def get_timeline_data(doctype, name): def get_dashboard_info(party_type, party): current_fiscal_year = get_fiscal_year(nowdate(), as_dict=True) - company = frappe.db.get_default("company") or frappe.get_all("Company")[0].name - party_account_currency = get_party_account_currency(party_type, party, company) - company_default_currency = get_default_currency() \ - or frappe.get_cached_value('Company', company, 'default_currency') - - if party_account_currency==company_default_currency: - total_field = "base_grand_total" - else: - total_field = "grand_total" doctype = "Sales Invoice" if party_type=="Customer" else "Purchase Invoice" - billing_this_year = frappe.db.sql(""" - select sum({0}) - from `tab{1}` - where {2}=%s and docstatus=1 and posting_date between %s and %s - """.format(total_field, doctype, party_type.lower()), - (party, current_fiscal_year.year_start_date, current_fiscal_year.year_end_date)) + companies = frappe.get_all(doctype, filters={ + 'docstatus': 1, + party_type.lower(): party + }, distinct=1, fields=['company']) - total_unpaid = frappe.db.sql(""" - select sum(debit_in_account_currency) - sum(credit_in_account_currency) + company_wise_info = [] + + company_wise_grand_total = frappe.get_all(doctype, + filters={ + 'docstatus': 1, + party_type.lower(): party, + 'posting_date': ('between', [current_fiscal_year.year_start_date, current_fiscal_year.year_end_date]) + }, + group_by="company", + fields=["company", "sum(grand_total) as grand_total", "sum(base_grand_total) as base_grand_total"] + ) + + company_wise_billing_this_year = frappe._dict() + + for d in company_wise_grand_total: + company_wise_billing_this_year.setdefault( + d.company,{ + "grand_total": d.grand_total, + "base_grand_total": d.base_grand_total + }) + + + company_wise_total_unpaid = frappe._dict(frappe.db.sql(""" + select company, sum(debit_in_account_currency) - sum(credit_in_account_currency) from `tabGL Entry` - where party_type = %s and party=%s""", (party_type, party)) + where party_type = %s and party=%s + group by company""", (party_type, party))) - info = {} - info["billing_this_year"] = flt(billing_this_year[0][0]) if billing_this_year else 0 - info["currency"] = party_account_currency - info["total_unpaid"] = flt(total_unpaid[0][0]) if total_unpaid else 0 - if party_type == "Supplier": - info["total_unpaid"] = -1 * info["total_unpaid"] + for d in companies: + company_default_currency = frappe.db.get_value("Company", d.company, 'default_currency') + party_account_currency = get_party_account_currency(party_type, party, d.company) - return info + if party_account_currency==company_default_currency: + billing_this_year = flt(company_wise_billing_this_year.get(d.company,{}).get("base_grand_total")) + else: + billing_this_year = flt(company_wise_billing_this_year.get(d.company,{}).get("grand_total")) + + total_unpaid = flt(company_wise_total_unpaid.get(d.company)) + + info = {} + info["billing_this_year"] = flt(billing_this_year) if billing_this_year else 0 + info["currency"] = party_account_currency + info["total_unpaid"] = flt(total_unpaid) if total_unpaid else 0 + info["company"] = d.company + + if party_type == "Supplier": + info["total_unpaid"] = -1 * info["total_unpaid"] + + company_wise_info.append(info) + + return company_wise_info def get_party_shipping_address(doctype, name): """ @@ -508,7 +535,7 @@ def get_party_shipping_address(doctype, name): 'dl.link_doctype=%s ' 'and dl.link_name=%s ' 'and dl.parenttype="Address" ' - 'and ' + 'and ifnull(ta.disabled, 0) = 0 and' '(ta.address_type="Shipping" or ta.is_shipping_address=1) ' 'order by ta.is_shipping_address desc, ta.address_type desc limit 1', (doctype, name) diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index 9370f0453e..0a025f68d5 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -10,36 +10,6 @@ frappe.query_reports["Accounts Payable"] = { "options": "Company", "default": frappe.defaults.get_user_default("Company") }, - { - "fieldname":"finance_book", - "label": __("Finance Book"), - "fieldtype": "Link", - "options": "Finance Book" - }, - { - "fieldname":"supplier", - "label": __("Supplier"), - "fieldtype": "Link", - "options": "Supplier", - on_change: () => { - var supplier = frappe.query_report.get_filter_value('supplier'); - frappe.db.get_value('Supplier', supplier, "tax_id", function(value) { - frappe.query_report.set_filter_value('tax_id', value["tax_id"]); - }); - } - }, - { - "fieldname":"supplier_group", - "label": __("Supplier Group"), - "fieldtype": "Link", - "options": "Supplier Group" - }, - { - "fieldname":"report_date", - "label": __("As on Date"), - "fieldtype": "Date", - "default": frappe.datetime.get_today() - }, { "fieldname":"ageing_based_on", "label": __("Ageing Based On"), @@ -48,7 +18,10 @@ frappe.query_reports["Accounts Payable"] = { "default": "Posting Date" }, { - "fieldtype": "Break", + "fieldname":"report_date", + "label": __("As on Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today() }, { "fieldname":"range1", @@ -71,6 +44,34 @@ frappe.query_reports["Accounts Payable"] = { "default": "90", "reqd": 1 }, + { + "fieldname":"finance_book", + "label": __("Finance Book"), + "fieldtype": "Link", + "options": "Finance Book" + }, + { + "fieldname":"supplier", + "label": __("Supplier"), + "fieldtype": "Link", + "options": "Supplier", + on_change: () => { + var supplier = frappe.query_report.get_filter_value('supplier'); + if (supplier) { + frappe.db.get_value('Supplier', supplier, "tax_id", function(value) { + frappe.query_report.set_filter_value('tax_id', value["tax_id"]); + }); + } else { + frappe.query_report.set_filter_value('tax_id', ""); + } + } + }, + { + "fieldname":"supplier_group", + "label": __("Supplier Group"), + "fieldtype": "Link", + "options": "Supplier Group" + }, { "fieldname":"tax_id", "label": __("Tax Id"), 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 77b099fd07..7823cac89c 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -10,24 +10,6 @@ frappe.query_reports["Accounts Payable Summary"] = { "options": "Company", "default": frappe.defaults.get_user_default("Company") }, - { - "fieldname":"supplier", - "label": __("Supplier"), - "fieldtype": "Link", - "options": "Supplier" - }, - { - "fieldname":"supplier_group", - "label": __("Supplier Group"), - "fieldtype": "Link", - "options": "Supplier Group" - }, - { - "fieldname":"report_date", - "label": __("Date"), - "fieldtype": "Date", - "default": frappe.datetime.get_today() - }, { "fieldname":"ageing_based_on", "label": __("Ageing Based On"), @@ -36,7 +18,10 @@ frappe.query_reports["Accounts Payable Summary"] = { "default": "Posting Date" }, { - "fieldtype": "Break", + "fieldname":"report_date", + "label": __("Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today() }, { "fieldname":"range1", @@ -58,6 +43,24 @@ frappe.query_reports["Accounts Payable Summary"] = { "fieldtype": "Int", "default": "90", "reqd": 1 + }, + { + "fieldname":"finance_book", + "label": __("Finance Book"), + "fieldtype": "Link", + "options": "Finance Book" + }, + { + "fieldname":"supplier", + "label": __("Supplier"), + "fieldtype": "Link", + "options": "Supplier" + }, + { + "fieldname":"supplier_group", + "label": __("Supplier Group"), + "fieldtype": "Link", + "options": "Supplier Group" } ], diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index dfcf64c797..fd462a628e 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -1,24 +1,14 @@ -{% if(filters.show_pdc_in_print) { %} - -{% } %} - -

{%= __(report.report_name) %}

+

{%= __(report.report_name) %}

{% if (filters.customer_name) { %} {%= filters.customer_name %} @@ -36,7 +26,20 @@ {%= __("Until") %} {%= frappe.datetime.str_to_user(filters.report_date) %}

-
+ +
+
+ {% if(filters.payment_terms) { %} + {%= __("Payment Terms") %}: {%= filters.payment_terms %} + {% } %} +
+
+ {% if(filters.credit_limit) { %} + {%= __("Credit Limit") %}: {%= format_currency(filters.credit_limit) %} + {% } %} +
+
+ {% if(filters.show_pdc_in_print) { %} {% var balance_row = data.slice(-1).pop(); var range1 = report.columns[11].label; @@ -104,17 +107,21 @@ {% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %} - {%= __("Date") %} - {%= __("Reference") %} + {%= __("Date") %} + {%= __("Age (Days)") %} + {%= __("Reference") %} + {% if(report.report_name === "Accounts Receivable") { %} + {%= __("Sales Person") %} + {% } %} {% if(!filters.show_pdc_in_print) { %} {%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %} {% } %} - {%= __("Invoiced Amount") %} + {%= __("Invoiced Amount") %} {% if(!filters.show_pdc_in_print) { %} - {%= __("Paid Amount") %} - {%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %} + {%= __("Paid Amount") %} + {%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %} {% } %} - {%= __("Outstanding Amount") %} + {%= __("Outstanding Amount") %} {% if(filters.show_pdc_in_print) { %} {% if(report.report_name === "Accounts Receivable") { %} {%= __("Customer LPO No.") %} @@ -139,6 +146,7 @@ {% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %} {% if(data[i][__("Customer")] || data[i][__("Supplier")]) { %} {%= frappe.datetime.str_to_user(data[i]["posting_date"]) %} + {%= data[i][__("Age (Days)")] %} {% if(!filters.show_pdc_in_print) { %} {%= data[i]["voucher_type"] %} @@ -146,6 +154,11 @@ {% } %} {%= data[i]["voucher_no"] %} + + {% if(report.report_name === "Accounts Receivable") { %} + {%= data[i]["sales_person"] %} + {% } %} + {% if(!filters.show_pdc_in_print) { %} {% if(!(filters.customer || filters.supplier)) { %} @@ -156,10 +169,15 @@
{%= data[i][__("Supplier Name")] %} {% } %} {% } %} -
{%= __("Remarks") %}: - {%= data[i][__("Remarks")] %} +
+ {% if data[i][__("Remarks")] %} + {%= __("Remarks") %}: + {%= data[i][__("Remarks")] %} + {% } %} +
{% } %} + {%= format_currency(data[i]["invoiced_amount"], data[i]["currency"]) %} @@ -187,14 +205,18 @@ {% if(!filters.show_pdc_in_print) { %} {% } %} - {%= __("Total") %} + {% if(report.report_name === "Accounts Receivable") { %} + + {% } %} + + {%= __("Total") %} {%= format_currency(data[i]["invoiced_amount"], data[i]["currency"] ) %} {% if(!filters.show_pdc_in_print) { %} {%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %} - {%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} + {%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %} {% } %} {%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %} diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index fda496057f..b1bdce95c8 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -10,6 +10,40 @@ frappe.query_reports["Accounts Receivable"] = { "options": "Company", "default": frappe.defaults.get_user_default("Company") }, + { + "fieldname":"ageing_based_on", + "label": __("Ageing Based On"), + "fieldtype": "Select", + "options": 'Posting Date\nDue Date', + "default": "Posting Date" + }, + { + "fieldname":"report_date", + "label": __("As on Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today() + }, + { + "fieldname":"range1", + "label": __("Ageing Range 1"), + "fieldtype": "Int", + "default": "30", + "reqd": 1 + }, + { + "fieldname":"range2", + "label": __("Ageing Range 2"), + "fieldtype": "Int", + "default": "60", + "reqd": 1 + }, + { + "fieldname":"range3", + "label": __("Ageing Range 3"), + "fieldtype": "Int", + "default": "90", + "reqd": 1 + }, { "fieldname":"finance_book", "label": __("Finance Book"), @@ -23,10 +57,19 @@ frappe.query_reports["Accounts Receivable"] = { "options": "Customer", on_change: () => { var customer = frappe.query_report.get_filter_value('customer'); - frappe.db.get_value('Customer', customer, ["tax_id", "customer_name"], function(value) { - frappe.query_report.set_filter_value('tax_id', value["tax_id"]); - frappe.query_report.set_filter_value('customer_name', value["customer_name"]); - }); + if (customer) { + frappe.db.get_value('Customer', customer, ["tax_id", "customer_name", "credit_limit", "payment_terms"], function(value) { + frappe.query_report.set_filter_value('tax_id', value["tax_id"]); + frappe.query_report.set_filter_value('customer_name', value["customer_name"]); + frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]); + frappe.query_report.set_filter_value('payment_terms', value["payment_terms"]); + }); + } else { + frappe.query_report.set_filter_value('tax_id', ""); + frappe.query_report.set_filter_value('customer_name', ""); + frappe.query_report.set_filter_value('credit_limit', ""); + frappe.query_report.set_filter_value('payment_terms', ""); + } } }, { @@ -59,43 +102,6 @@ frappe.query_reports["Accounts Receivable"] = { "fieldtype": "Link", "options": "Sales Person" }, - { - "fieldtype": "Break", - }, - { - "fieldname":"report_date", - "label": __("As on Date"), - "fieldtype": "Date", - "default": frappe.datetime.get_today() - }, - { - "fieldname":"ageing_based_on", - "label": __("Ageing Based On"), - "fieldtype": "Select", - "options": 'Posting Date\nDue Date', - "default": "Posting Date" - }, - { - "fieldname":"range1", - "label": __("Ageing Range 1"), - "fieldtype": "Int", - "default": "30", - "reqd": 1 - }, - { - "fieldname":"range2", - "label": __("Ageing Range 2"), - "fieldtype": "Int", - "default": "60", - "reqd": 1 - }, - { - "fieldname":"range3", - "label": __("Ageing Range 3"), - "fieldtype": "Int", - "default": "90", - "reqd": 1 - }, { "fieldname":"show_pdc_in_print", "label": __("Show PDC in Print"), @@ -112,6 +118,18 @@ frappe.query_reports["Accounts Receivable"] = { "label": __("Customer Name"), "fieldtype": "Data", "hidden": 1 + }, + { + "fieldname":"payment_terms", + "label": __("Payment Tems"), + "fieldtype": "Data", + "hidden": 1 + }, + { + "fieldname":"credit_limit", + "label": __("Credit Limit"), + "fieldtype": "Currency", + "hidden": 1 } ], diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 572f81dc35..8e05a087af 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -125,17 +125,22 @@ class ReceivablePayableReport(object): }] if args.get('party_type') == 'Customer': - columns.append({ - "label": _("Customer LPO"), - "fieldtype": "Data", - "fieldname": "po_no", - "width": 100, - }) - columns += [_("Delivery Note") + ":Data:100"] - if args.get("party_type") == "Customer": columns += [ + { + "label": _("Customer LPO"), + "fieldtype": "Data", + "fieldname": "po_no", + "width": 100, + }, + _("Delivery Note") + ":Data:100", _("Territory") + ":Link/Territory:80", - _("Customer Group") + ":Link/Customer Group:120" + _("Customer Group") + ":Link/Customer Group:120", + { + "label": _("Sales Person"), + "fieldtype": "Data", + "fieldname": "sales_person", + "width": 120, + } ] if args.get("party_type") == "Supplier": columns += [_("Supplier Group") + ":Link/Supplier Group:80"] @@ -238,7 +243,8 @@ class ReceivablePayableReport(object): # customer territory / supplier group if args.get("party_type") == "Customer": - row += [self.get_territory(gle.party), self.get_customer_group(gle.party)] + row += [self.get_territory(gle.party), self.get_customer_group(gle.party), + voucher_details.get(gle.voucher_no, {}).get("sales_person")] if args.get("party_type") == "Supplier": row += [self.get_supplier_group(gle.party)] @@ -395,9 +401,14 @@ class ReceivablePayableReport(object): values.append(self.filters.get("sales_partner")) if self.filters.get("sales_person"): - conditions.append("""party in (select parent - from `tabSales Team` where sales_person=%s and parenttype = 'Customer')""") - values.append(self.filters.get("sales_person")) + lft, rgt = frappe.db.get_value("Sales Person", + self.filters.get("sales_person"), ["lft", "rgt"]) + + conditions.append("""exists(select name from `tabSales Team` steam where + steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1}) + and ((steam.parent = voucher_no and steam.parenttype = voucher_type) + or (steam.parent = against_voucher and steam.parenttype = against_voucher_type) + or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt)) if party_type_field=="supplier": if self.filters.get("supplier_group"): @@ -550,8 +561,12 @@ def get_voucher_details(party_type, voucher_nos, dn_details): voucher_details = frappe._dict() if party_type == "Customer": - for si in frappe.db.sql("""select name, due_date, po_no - from `tabSales Invoice` where docstatus=1 and name in (%s) + for si in frappe.db.sql(""" + select inv.name, inv.due_date, inv.po_no, GROUP_CONCAT(steam.sales_person SEPARATOR ', ') as sales_person + from `tabSales Invoice` inv + left join `tabSales Team` steam on steam.parent = inv.name and steam.parenttype = 'Sales Invoice' + where inv.docstatus=1 and inv.name in (%s) + group by inv.name """ %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1): si['delivery_note'] = dn_details.get(si.name) voucher_details.setdefault(si.name, si) diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js index 96e5d18093..a6f1457954 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js @@ -11,25 +11,11 @@ frappe.query_reports["Accounts Receivable Summary"] = { "default": frappe.defaults.get_user_default("Company") }, { - "fieldname":"customer", - "label": __("Customer"), - "fieldtype": "Link", - "options": "Customer" - }, - { - "fieldname":"customer_group", - "label": __("Customer Group"), - "fieldtype": "Link", - "options": "Customer Group" - }, - { - "fieldname":"payment_terms_template", - "label": __("Payment Terms Template"), - "fieldtype": "Link", - "options": "Payment Terms Template" - }, - { - "fieldtype": "Break", + "fieldname":"ageing_based_on", + "label": __("Ageing Based On"), + "fieldtype": "Select", + "options": 'Posting Date\nDue Date', + "default": "Posting Date" }, { "fieldname":"report_date", @@ -37,13 +23,6 @@ frappe.query_reports["Accounts Receivable Summary"] = { "fieldtype": "Date", "default": frappe.datetime.get_today() }, - { - "fieldname":"ageing_based_on", - "label": __("Ageing Based On"), - "fieldtype": "Select", - "options": 'Posting Date\nDue Date', - "default": "Posting Date" - }, { "fieldname":"range1", "label": __("Ageing Range 1"), @@ -64,6 +43,48 @@ frappe.query_reports["Accounts Receivable Summary"] = { "fieldtype": "Int", "default": "90", "reqd": 1 + }, + { + "fieldname":"finance_book", + "label": __("Finance Book"), + "fieldtype": "Link", + "options": "Finance Book" + }, + { + "fieldname":"customer", + "label": __("Customer"), + "fieldtype": "Link", + "options": "Customer" + }, + { + "fieldname":"customer_group", + "label": __("Customer Group"), + "fieldtype": "Link", + "options": "Customer Group" + }, + { + "fieldname":"payment_terms_template", + "label": __("Payment Terms Template"), + "fieldtype": "Link", + "options": "Payment Terms Template" + }, + { + "fieldname":"territory", + "label": __("Territory"), + "fieldtype": "Link", + "options": "Territory" + }, + { + "fieldname":"sales_partner", + "label": __("Sales Partner"), + "fieldtype": "Link", + "options": "Sales Partner" + }, + { + "fieldname":"sales_person", + "label": __("Sales Person"), + "fieldtype": "Link", + "options": "Sales Person" } ], diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 7b0072cd15..190031abb8 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -22,7 +22,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): columns += [ args.get("party_type") + " Name::140"] credit_debit_label = "Credit Note Amt" if args.get('party_type') == 'Customer' else "Debit Note Amt" - + columns += [{ "label": _("Total Invoiced Amt"), "fieldname": "total_invoiced_amt", @@ -97,6 +97,12 @@ class AccountsReceivableSummary(ReceivablePayableReport): "fieldtype": "Link", "options": "Customer Group", "width": 80 + }, + { + "label": _("Sales Person"), + "fieldtype": "Data", + "fieldname": "sales_person", + "width": 120, }] if args.get("party_type") == "Supplier": @@ -107,7 +113,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): "options": "Supplier Group", "width": 80 }] - + columns.append({ "fieldname": "currency", "label": _("Currency"), @@ -135,10 +141,10 @@ class AccountsReceivableSummary(ReceivablePayableReport): ] if args.get("party_type") == "Customer": - row += [self.get_territory(party), self.get_customer_group(party)] + row += [self.get_territory(party), self.get_customer_group(party), ", ".join(set(party_dict.sales_person))] if args.get("party_type") == "Supplier": row += [self.get_supplier_group(party)] - + row.append(party_dict.currency) data.append(row) @@ -156,15 +162,19 @@ class AccountsReceivableSummary(ReceivablePayableReport): "range1": 0, "range2": 0, "range3": 0, - "range4": 0 + "range4": 0, + "sales_person": [] }) ) for k in list(party_total[d.party]): - if k != "currency": + if k not in ["currency", "sales_person"]: party_total[d.party][k] += flt(d.get(k, 0)) - + party_total[d.party].currency = d.currency + if d.sales_person: + party_total[d.party].sales_person.append(d.sales_person) + return party_total def get_voucherwise_data(self, party_naming_by, args): @@ -181,12 +191,13 @@ class AccountsReceivableSummary(ReceivablePayableReport): cols += ["bill_no", "bill_date"] cols += ["invoiced_amt", "paid_amt", "credit_amt", - "outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency"] + "outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref", + "pdc/lc_amount", "remaining_balance"] if args.get("party_type") == "Supplier": cols += ["supplier_group", "remarks"] if args.get("party_type") == "Customer": - cols += ["territory", "customer_group", "remarks"] + cols += ["po_no", "do_no", "territory", "customer_group", "sales_person", "remarks"] return self.make_data_dict(cols, voucherwise_data) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 524f5f70d7..7e50d9be61 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -16,8 +16,6 @@ def execute(filters=None): return [], [] account_details = {} - if not filters.get("group_by"): - filters['group_by'] = _('Group by Voucher (Consolidated)') if filters and filters.get('print_in_account_currency') and \ not filters.get('account'): diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 19075d35ae..2ed664c9bf 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -236,7 +236,7 @@ class GrossProfitGenerator(object): previous_stock_value = len(my_sle) > i+1 and \ flt(my_sle[i+1].stock_value) or 0.0 if previous_stock_value: - return previous_stock_value - flt(sle.stock_value) + return (previous_stock_value - flt(sle.stock_value)) * flt(row.qty) / abs(flt(sle.qty)) else: return flt(row.qty) * self.get_average_buying_rate(row, item_code) else: diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 0a3f56ab8e..07dcd4e7a9 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -231,6 +231,13 @@ def get_columns(): "options": "Account", "width": 300 }, + { + "fieldname": "currency", + "label": _("Currency"), + "fieldtype": "Link", + "options": "Currency", + "hidden": 1 + }, { "fieldname": "opening_debit", "label": _("Opening (Dr)"), @@ -272,13 +279,6 @@ def get_columns(): "fieldtype": "Currency", "options": "currency", "width": 120 - }, - { - "fieldname": "currency", - "label": _("Currency"), - "fieldtype": "Link", - "options": "Currency", - "hidden": 1 } ] diff --git a/erpnext/accounts/report/trial_balance_simple/trial_balance_simple.json b/erpnext/accounts/report/trial_balance_simple/trial_balance_simple.json new file mode 100644 index 0000000000..ea5a97b106 --- /dev/null +++ b/erpnext/accounts/report/trial_balance_simple/trial_balance_simple.json @@ -0,0 +1,30 @@ +{ + "add_total_row": 1, + "creation": "2018-11-22 16:53:19.167935", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2018-11-22 17:40:11.317567", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Trial Balance (Simple)", + "owner": "Administrator", + "prepared_report": 0, + "query": "select fiscal_year as \"Fiscal Year:Data:80\",\n\tcompany as \"Company:Data:220\",\n\tposting_date as \"Posting Date:Date:100\",\n\taccount as \"Account:Data:380\",\n\tsum(debit) as \"Debit:Currency:140\",\n\tsum(credit) as \"Credit:Currency:140\"\nfrom `tabGL Entry`\ngroup by fiscal_year, company, posting_date, account\norder by fiscal_year, company, posting_date, account", + "ref_doctype": "GL Entry", + "report_name": "Trial Balance (Simple)", + "report_type": "Query Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + }, + { + "role": "Auditor" + } + ] +} \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index a505e4976a..019d0de470 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -315,7 +315,6 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order", source_doctype: "Material Request", target: me.frm, - args: args, setters: { company: me.frm.doc.company }, diff --git a/erpnext/buying/page/purchase_analytics/README.md b/erpnext/buying/page/purchase_analytics/README.md deleted file mode 100644 index 332e4c2c05..0000000000 --- a/erpnext/buying/page/purchase_analytics/README.md +++ /dev/null @@ -1 +0,0 @@ -Trends of purchases across Items, Item Groups, Suppliers. \ No newline at end of file diff --git a/erpnext/buying/page/purchase_analytics/__init__.py b/erpnext/buying/page/purchase_analytics/__init__.py deleted file mode 100644 index baffc48825..0000000000 --- a/erpnext/buying/page/purchase_analytics/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/buying/page/purchase_analytics/purchase_analytics.js b/erpnext/buying/page/purchase_analytics/purchase_analytics.js deleted file mode 100644 index 06764a3c60..0000000000 --- a/erpnext/buying/page/purchase_analytics/purchase_analytics.js +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -frappe.pages['purchase-analytics'].on_page_load = function(wrapper) { - frappe.ui.make_app_page({ - parent: wrapper, - title: __('Purchase Analytics'), - single_column: true - }); - - new erpnext.PurchaseAnalytics(wrapper); - - frappe.breadcrumbs.add("Buying"); -} - -erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({ - init: function(wrapper) { - this._super({ - title: __("Purchase Analytics"), - parent: $(wrapper).find('.layout-main'), - page: wrapper.page, - doctypes: ["Item", "Item Group", "Supplier", "Supplier Group", "Company", "Fiscal Year", - "Purchase Invoice", "Purchase Invoice Item", - "Purchase Order", "Purchase Order Item[Purchase Analytics]", - "Purchase Receipt", "Purchase Receipt Item[Purchase Analytics]"], - tree_grid: { show: true } - }); - - this.tree_grids = { - "Supplier Group": { - label: __("Supplier Group / Supplier"), - show: true, - item_key: "supplier", - parent_field: "parent_supplier_group", - formatter: function(item) { - return item.supplier_name ? item.supplier_name + " (" + item.name + ")" : item.name; - } - }, - "Supplier": { - label: __("Supplier"), - show: false, - item_key: "supplier", - formatter: function(item) { - return item.supplier_name ? item.supplier_name + " (" + item.name + ")" : item.name; - } - }, - "Item Group": { - label: "Item", - show: true, - parent_field: "parent_item_group", - item_key: "item_code", - formatter: function(item) { - return item.name; - } - }, - "Item": { - label: "Item", - show: false, - item_key: "item_code", - formatter: function(item) { - return item.name; - } - }, - } - }, - setup_columns: function() { - this.tree_grid = this.tree_grids[this.tree_type]; - - var std_columns = [ - {id: "name", name: this.tree_grid.label, field: "name", width: 300}, - {id: "total", name: "Total", field: "total", plot: false, - formatter: this.currency_formatter} - ]; - - this.make_date_range_columns(); - this.columns = std_columns.concat(this.columns); - }, - filters: [ - {fieldtype:"Select", label: __("Tree Type"), fieldname: "tree_type", - options:["Supplier Group", "Supplier", "Item Group", "Item"], - filter: function(val, item, opts, me) { - return me.apply_zero_filter(val, item, opts, me); - }}, - {fieldtype:"Select", label: __("Based On"), fieldname: "based_on", - options:["Purchase Invoice", "Purchase Order", "Purchase Receipt"]}, - {fieldtype:"Select", label: __("Value or Qty"), fieldname: "value_or_qty", - options:["Value", "Quantity"]}, - {fieldtype:"Select", label: __("Company"), link:"Company", fieldname: "company", - default_value: __("Select Company...")}, - {fieldtype:"Date", label: __("From Date"), fieldname: "from_date"}, - {fieldtype:"Date", label: __("To Date"), fieldname: "to_date"}, - {fieldtype:"Select", label: __("Range"), fieldname: "range", - options:[{label: __("Daily"), value: "Daily"}, {label: __("Weekly"), value: "Weekly"}, - {label: __("Monthly"), value: "Monthly"}, {label: __("Quarterly"), value: "Quarterly"}, - {label: __("Yearly"), value: "Yearly"}]} - ], - setup_filters: function() { - var me = this; - this._super(); - - this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on", "company"]); - - this.show_zero_check(); - }, - init_filter_values: function() { - this._super(); - this.filter_inputs.range.val('Monthly'); - }, - prepare_data: function() { - var me = this; - if (!this.tl) { - // add 'Not Set' Supplier & Item - // (Supplier / Item are not mandatory!!) - frappe.report_dump.data["Supplier"].push({ - name: __("Not Set"), - parent_supplier_group: __("All Supplier Groups"), - id: "Not Set", - }); - - frappe.report_dump.data["Item"].push({ - name: __("Not Set"), - parent_item_group: "All Item Groups", - id: "Not Set", - }); - } - - if (!this.tl || !this.tl[this.based_on]) { - this.make_transaction_list(this.based_on, this.based_on + " Item"); - } - - - if(!this.data || me.item_type != me.tree_type) { - var items; - if(me.tree_type=='Supplier') { - items = frappe.report_dump.data["Supplier"]; - } else if(me.tree_type=='Supplier Group') { - items = this.prepare_tree("Supplier", "Supplier Group"); - } else if(me.tree_type=="Item Group") { - items = this.prepare_tree("Item", "Item Group"); - } else if(me.tree_type=="Item") { - items = frappe.report_dump.data["Item"]; - } - - me.item_type = me.tree_type - me.parent_map = {}; - me.item_by_name = {}; - me.data = []; - - $.each(items, function(i, v) { - var d = copy_dict(v); - - me.data.push(d); - me.item_by_name[d.name] = d; - if(d[me.tree_grid.parent_field]) { - me.parent_map[d.name] = d[me.tree_grid.parent_field]; - } - me.reset_item_values(d); - }); - - this.set_indent(); - - } else { - // otherwise, only reset values - $.each(this.data, function(i, d) { - me.reset_item_values(d); - }); - } - - this.prepare_balances(); - if(me.tree_grid.show) { - this.set_totals(false); - this.update_groups(); - } else { - this.set_totals(true); - } - }, - prepare_balances: function() { - var me = this; - var from_date = frappe.datetime.str_to_obj(this.from_date); - var to_date = frappe.datetime.str_to_obj(this.to_date); - var is_val = this.value_or_qty == 'Value'; - - $.each(this.tl[this.based_on], function(i, tl) { - if (me.is_default('company') ? true : tl.company === me.company) { - var posting_date = frappe.datetime.str_to_obj(tl.posting_date); - if (posting_date >= from_date && posting_date <= to_date) { - var item = me.item_by_name[tl[me.tree_grid.item_key]] || - me.item_by_name['Not Set']; - item[me.column_map[tl.posting_date].field] += (is_val ? tl.base_net_amount : tl.qty); - } - } - }); - }, - update_groups: function() { - var me = this; - - $.each(this.data, function(i, item) { - var parent = me.parent_map[item.name]; - while(parent) { - var parent_group = me.item_by_name[parent]; - - $.each(me.columns, function(c, col) { - if (col.formatter == me.currency_formatter) { - parent_group[col.field] = - flt(parent_group[col.field]) - + flt(item[col.field]); - } - }); - parent = me.parent_map[parent]; - } - }); - }, - set_totals: function(sort) { - var me = this; - var checked = false; - $.each(this.data, function(i, d) { - d.total = 0.0; - $.each(me.columns, function(i, col) { - if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total") - d.total += d[col.field]; - if(d.checked) checked = true; - }) - }); - - if(sort)this.data = this.data.sort(function(a, b) { return b.total - a.total; }); - - if(!this.checked) { - this.data[0].checked = true; - } - } -}); diff --git a/erpnext/buying/page/purchase_analytics/purchase_analytics.json b/erpnext/buying/page/purchase_analytics/purchase_analytics.json deleted file mode 100644 index ad13c7d415..0000000000 --- a/erpnext/buying/page/purchase_analytics/purchase_analytics.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "creation": "2012-09-21 20:15:16.000000", - "docstatus": 0, - "doctype": "Page", - "icon": "fa fa-bar-chart", - "idx": 1, - "modified": "2013-07-11 14:43:52.000000", - "modified_by": "Administrator", - "module": "Buying", - "name": "purchase-analytics", - "owner": "Administrator", - "page_name": "purchase-analytics", - "roles": [ - { - "role": "Analytics" - }, - { - "role": "Purchase Manager" - } - ], - "standard": "Yes", - "title": "Purchase Analytics" -} \ No newline at end of file diff --git a/erpnext/buying/report/purchase_analytics/purchase_analytics.js b/erpnext/buying/report/purchase_analytics/purchase_analytics.js index 297ec51cb1..b55046e065 100644 --- a/erpnext/buying/report/purchase_analytics/purchase_analytics.js +++ b/erpnext/buying/report/purchase_analytics/purchase_analytics.js @@ -68,11 +68,8 @@ frappe.query_reports["Purchase Analytics"] = { } ], - "formatter": function(value, row, column, data) { - if(!value){ - value = 0 - } - return value; + after_datatable_render: function(datatable_obj) { + $(datatable_obj.wrapper).find(".dt-row-0").find('input[type=checkbox]').click(); }, get_datatable_options(options) { return Object.assign(options, { @@ -110,19 +107,19 @@ frappe.query_reports["Purchase Analytics"] = { labels: raw_data.labels, datasets: new_datasets } - + setTimeout(() => { frappe.query_report.chart.update(new_data) - },200) - - + },500) + + setTimeout(() => { frappe.query_report.chart.draw(true); - }, 800) + }, 1000) frappe.query_report.raw_chart_data = new_data; }, } - }) - }, + }); + } } diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index d9ffced547..15996c3a44 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals from frappe import _ +import frappe + def get_data(): - return [ + config = [ { "label": _("Billing"), "items": [ @@ -25,48 +27,7 @@ def get_data(): "type": "doctype", "name": "Payment Entry", "description": _("Bank/Cash transactions against party or for internal transfer") - }, - { - "type": "page", - "name": "pos", - "label": _("POS"), - "description": _("Point of Sale") - }, - { - "type": "doctype", - "name": "Cashier Closing", - "description": _("Cashier Closing") - }, - { - "type": "doctype", - "name": "Auto Repeat", - "label": _("Auto Repeat"), - "description": _("To make recurring documents") - }, - { - "type": "doctype", - "name": "Loyalty Program", - "label": _("Loyalty Program"), - "description": _("To make Customer based incentive schemes.") - }, - { - "type": "doctype", - "name": "Loyalty Point Entry", - "label": _("Loyalty Point Entry"), - "description": _("To view logs of Loyalty Points assigned to a Customer.") - }, - { - "type": "report", - "name": "Accounts Receivable", - "doctype": "Sales Invoice", - "is_query_report": True - }, - { - "type": "report", - "name": "Accounts Payable", - "doctype": "Purchase Invoice", - "is_query_report": True - }, + } ] }, @@ -93,7 +54,7 @@ def get_data(): }, { "type": "report", - "name":"General Ledger", + "name": "General Ledger", "doctype": "GL Entry", "is_query_report": True, }, @@ -121,6 +82,18 @@ def get_data(): { "label": _("Accounting Statements"), "items": [ + { + "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", @@ -224,49 +197,6 @@ def get_data(): }, ] }, - { - "label": _("Goods and Services Tax (GST India)"), - "items": [ - { - "type": "doctype", - "name": "GST Settings", - }, - { - "type": "doctype", - "name": "GST HSN Code", - }, - { - "type": "report", - "name": "GSTR-1", - "is_query_report": True - }, - { - "type": "report", - "name": "GSTR-2", - "is_query_report": True - }, - { - "type": "report", - "name": "GST Sales Register", - "is_query_report": True - }, - { - "type": "report", - "name": "GST Purchase Register", - "is_query_report": True - }, - { - "type": "report", - "name": "GST Itemised Sales Register", - "is_query_report": True - }, - { - "type": "report", - "name": "GST Itemised Purchase Register", - "is_query_report": True - }, - ] - }, { "label": _("Budget and Cost Center"), "items": [ @@ -290,7 +220,7 @@ def get_data(): "doctype": "Cost Center" }, { - "type":"doctype", + "type": "doctype", "name": "Monthly Distribution", "description": _("Seasonality for setting budgets, targets etc.") }, @@ -347,29 +277,24 @@ def get_data(): }, { "type": "doctype", - "name": "POS Settings", - "description": _("Setup mode of POS (Online / Offline)") - }, - { - "type": "doctype", - "name": "POS Profile", - "label": _("Point-of-Sale Profile"), - "description": _("Setup default values for POS Invoices") - }, - { - "type": "doctype", - "name":"Terms and Conditions", + "name": "Terms and Conditions", "label": _("Terms and Conditions Template"), "description": _("Template of terms or contract.") }, { "type": "doctype", - "name":"Mode of Payment", + "name": "Mode of Payment", "description": _("e.g. Bank, Cash, Credit Card") }, { "type": "doctype", - "name":"C-Form", + "name": "Auto Repeat", + "label": _("Auto Repeat"), + "description": _("To make recurring documents") + }, + { + "type": "doctype", + "name": "C-Form", "description": _("C-Form records"), "country": "India" } @@ -506,12 +431,12 @@ def get_data(): "items": [ { "type": "doctype", - "name":"Shareholder", + "name": "Shareholder", "description": _("List of available Shareholders with folio numbers") }, { "type": "doctype", - "name":"Share Transfer", + "name": "Share Transfer", "description": _("List of all share transactions"), }, { @@ -528,28 +453,6 @@ def get_data(): } ] }, - { - "label": _("Subscription Management"), - "icon": "fa fa-microchip ", - "items": [ - { - "type": "doctype", - "name":"Subscriber", - }, - { - "type": "doctype", - "name":"Subscription Plan", - }, - { - "type": "doctype", - "name":"Subscription" - }, - { - "type": "doctype", - "name": "Subscription Settings" - } - ] - }, { "label": _("Help"), "icon": "fa fa-facetime-video", @@ -572,3 +475,121 @@ def get_data(): ] } ] + gst = { + "label": _("Goods and Services Tax (GST India)"), + "items": [ + { + "type": "doctype", + "name": "GST Settings", + }, + { + "type": "doctype", + "name": "GST HSN Code", + }, + { + "type": "report", + "name": "GSTR-1", + "is_query_report": True + }, + { + "type": "report", + "name": "GSTR-2", + "is_query_report": True + }, + { + "type": "report", + "name": "GST Sales Register", + "is_query_report": True + }, + { + "type": "report", + "name": "GST Purchase Register", + "is_query_report": True + }, + { + "type": "report", + "name": "GST Itemised Sales Register", + "is_query_report": True + }, + { + "type": "report", + "name": "GST Itemised Purchase Register", + "is_query_report": True + }, + ] + } + retail = { + "label": _("Retail Operations"), + "items": [ + { + "type": "page", + "name": "pos", + "label": _("POS"), + "description": _("Point of Sale") + }, + { + "type": "doctype", + "name": "Cashier Closing", + "description": _("Cashier Closing") + }, + { + "type": "doctype", + "name": "POS Settings", + "description": _("Setup mode of POS (Online / Offline)") + }, + { + "type": "doctype", + "name": "POS Profile", + "label": _("Point-of-Sale Profile"), + "description": _("Setup default values for POS Invoices") + }, + { + "type": "doctype", + "name": "Loyalty Program", + "label": _("Loyalty Program"), + "description": _("To make Customer based incentive schemes.") + }, + { + "type": "doctype", + "name": "Loyalty Point Entry", + "label": _("Loyalty Point Entry"), + "description": _("To view logs of Loyalty Points assigned to a Customer.") + } + ] + } + subscriptions = { + "label": _("Subscription Management"), + "icon": "fa fa-microchip ", + "items": [ + { + "type": "doctype", + "name": "Subscriber", + }, + { + "type": "doctype", + "name": "Subscription Plan", + }, + { + "type": "doctype", + "name": "Subscription" + }, + { + "type": "doctype", + "name": "Subscription Settings" + } + ] + } + countries = frappe.get_all("Company", fields="country") + countries = [country["country"] for country in countries] + if "India" in countries: + config.insert(7, gst) + domains = frappe.get_active_domains() + if "Retail" in domains: + config.insert(2, retail) + else: + config.insert(7, retail) + if "Services" in domains: + config.insert(2, subscriptions) + else: + config.insert(7, subscriptions) + return config diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 51747f67ae..86ceb2e4ab 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -57,6 +57,8 @@ class AccountsController(TransactionBase): _('{0} is blocked so this transaction cannot proceed'.format(supplier_name)), raise_exception=1) def validate(self): + + self.validate_qty_is_not_zero() if self.get("_action") and self._action != "update_after_submit": self.set_missing_values(for_validate=True) @@ -179,7 +181,7 @@ class AccountsController(TransactionBase): validate_due_date(self.posting_date, self.due_date, "Customer", self.customer, self.company, self.payment_terms_template) elif self.doctype == "Purchase Invoice": - validate_due_date(self.posting_date, self.due_date, + validate_due_date(self.bill_date or self.posting_date, self.due_date, "Supplier", self.supplier, self.company, self.bill_date, self.payment_terms_template) def set_price_list_currency(self, buying_or_selling): @@ -359,6 +361,11 @@ class AccountsController(TransactionBase): return gl_dict + def validate_qty_is_not_zero(self): + for item in self.items: + if not item.qty: + frappe.throw("Item quantity can not be zero") + def validate_account_currency(self, account, account_currency=None): valid_currency = [self.company_currency] if self.get("currency") and self.currency != self.company_currency: @@ -405,7 +412,8 @@ class AccountsController(TransactionBase): if d.against_order: allocated_amount = flt(d.amount) else: - allocated_amount = min(self.grand_total - advance_allocated, d.amount) + amount = self.rounded_total or self.grand_total + allocated_amount = min(amount - advance_allocated, d.amount) advance_allocated += flt(allocated_amount) self.append("advances", { diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index dbde30410c..ee6dc2a473 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -12,6 +12,7 @@ from erpnext.buying.utils import validate_for_items, update_last_purchase_rate from erpnext.stock.stock_ledger import get_valuation_rate from erpnext.stock.doctype.stock_entry.stock_entry import get_used_alternative_items from erpnext.stock.doctype.serial_no.serial_no import get_auto_serial_nos, auto_make_serial_nos, get_serial_nos +from frappe.contacts.doctype.address.address import get_address_display from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget from erpnext.controllers.stock_controller import StockController @@ -42,6 +43,7 @@ class BuyingController(StockController): self.set_qty_as_per_stock_uom() self.validate_stock_or_nonstock_items() self.validate_warehouse() + self.set_supplier_address() if self.doctype=="Purchase Invoice": self.validate_purchase_receipt_if_update_stock() @@ -113,6 +115,16 @@ class BuyingController(StockController): if not d.cost_center and lc_voucher_data and lc_voucher_data[0][1]: d.db_set('cost_center', lc_voucher_data[0][1]) + def set_supplier_address(self): + address_dict = { + 'supplier_address': 'address_display', + 'shipping_address': 'shipping_address_display' + } + + for address_field, address_display_field in address_dict.items(): + if self.get(address_field): + self.set(address_display_field, get_address_display(self.get(address_field))) + def set_total_in_words(self): from frappe.utils import money_in_words if self.meta.get_field("base_in_words"): diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 719f4c732a..684a2cdbcb 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -9,6 +9,7 @@ from erpnext.stock.get_item_details import get_bin_details from erpnext.stock.utils import get_incoming_rate from erpnext.stock.get_item_details import get_conversion_factor from erpnext.stock.doctype.item.item import get_item_defaults, set_item_default +from frappe.contacts.doctype.address.address import get_address_display from erpnext.controllers.stock_controller import StockController @@ -16,7 +17,7 @@ class SellingController(StockController): def __setup__(self): if hasattr(self, "taxes"): self.flags.print_taxes_with_zero_amount = cint(frappe.db.get_single_value("Print Settings", - "print_taxes_with_zero_amount")) + "print_taxes_with_zero_amount")) self.flags.show_inclusive_tax_in_print = self.is_inclusive_tax() self.print_templates = { @@ -41,7 +42,9 @@ class SellingController(StockController): self.validate_selling_price() self.set_qty_as_per_stock_uom() self.set_po_nos() + self.set_gross_profit() set_default_income_account_for_item(self) + self.set_customer_address() def set_missing_values(self, for_validate=False): @@ -348,6 +351,23 @@ class SellingController(StockController): if po_nos and po_nos[0].get('po_no'): self.po_no = ', '.join(list(set([d.po_no for d in po_nos if d.po_no]))) + def set_gross_profit(self): + if self.doctype == "Sales Order": + for item in self.items: + item.gross_profit = flt(((item.base_rate - item.valuation_rate) * item.stock_qty), self.precision("amount", item)) + + + def set_customer_address(self): + address_dict = { + 'customer_address': 'address_display', + 'shipping_address_name': 'shipping_address', + 'company_address': 'company_address_display' + } + + for address_field, address_display_field in address_dict.items(): + if self.get(address_field): + self.set(address_display_field, get_address_display(self.get(address_field))) + def validate_items(self): # validate items to see if they have is_sales_item enabled from erpnext.controllers.buying_controller import validate_item_type diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index a4410256f6..5bbef1831a 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -65,6 +65,7 @@ class calculate_taxes_and_totals(object): if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']: item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item) + if flt(item.rate_with_margin) > 0: item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")) item.discount_amount = item.rate_with_margin - item.rate @@ -647,4 +648,4 @@ def get_rounded_tax_amount(itemised_tax, precision): # Rounding based on tax_amount precision for taxes in itemised_tax.values(): for tax_account in taxes: - taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision) \ No newline at end of file + taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision) diff --git a/erpnext/demo/setup/setup_data.py b/erpnext/demo/setup/setup_data.py index 0fd7bb7ac8..48dcdbe863 100644 --- a/erpnext/demo/setup/setup_data.py +++ b/erpnext/demo/setup/setup_data.py @@ -376,7 +376,7 @@ def setup_pos_profile(): company_abbr = frappe.get_cached_value('Company', erpnext.get_default_company(), "abbr") pos = frappe.new_doc('POS Profile') pos.user = frappe.db.get_global('demo_accounts_user') - pos.pos_profile_name = "Demo POS Profile" + pos.name = "Demo POS Profile" pos.naming_series = 'SINV-' pos.update_stock = 0 pos.write_off_account = 'Cost of Goods Sold - '+ company_abbr diff --git a/erpnext/education/doctype/assessment_result/assessment_result.js b/erpnext/education/doctype/assessment_result/assessment_result.js index 5f13e3e628..84865ca8ec 100644 --- a/erpnext/education/doctype/assessment_result/assessment_result.js +++ b/erpnext/education/doctype/assessment_result/assessment_result.js @@ -38,6 +38,12 @@ frappe.ui.form.on("Assessment Result", { frappe.ui.form.on("Assessment Result Detail", { score: function(frm, cdt, cdn) { var d = locals[cdt][cdn]; + + if(!d.maximum_score || !frm.doc.grading_scale) { + d.score = ""; + frappe.throw(__("Please fill in all the details to generate Assessment Result.")); + } + if (d.score > d.maximum_score) { frappe.throw(__("Score cannot be greater than Maximum Score")); } diff --git a/erpnext/education/doctype/fees/fees.json b/erpnext/education/doctype/fees/fees.json index ac32717721..2413967442 100644 --- a/erpnext/education/doctype/fees/fees.json +++ b/erpnext/education/doctype/fees/fees.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -991,39 +992,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fieldname": "paid_amount", - "fieldtype": "Currency", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Paid Amount", - "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 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1360,7 +1328,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2018-08-21 14:44:48.968839", + "modified": "2018-11-26 20:42:14.467284", "modified_by": "Administrator", "module": "Education", "name": "Fees", diff --git a/erpnext/education/doctype/fees/fees.py b/erpnext/education/doctype/fees/fees.py index bfe6af4bdb..aa616e6206 100644 --- a/erpnext/education/doctype/fees/fees.py +++ b/erpnext/education/doctype/fees/fees.py @@ -112,7 +112,10 @@ def get_fee_list(doctype, txt, filters, limit_start, limit_page_length=20, order user = frappe.session.user student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user) if student: - return frappe. db.sql('''select name, program, due_date, paid_amount, outstanding_amount, grand_total from `tabFees` + return frappe. db.sql(''' + select name, program, due_date, grand_total - outstanding_amount as paid_amount, + outstanding_amount, grand_total, currency + from `tabFees` where student= %s and docstatus=1 order by due_date asc limit {0} , {1}''' .format(limit_start, limit_page_length), student, as_dict = True) diff --git a/erpnext/education/report/student_fee_collection/student_fee_collection.json b/erpnext/education/report/student_fee_collection/student_fee_collection.json index 07fc27c7a0..eb945cfffb 100644 --- a/erpnext/education/report/student_fee_collection/student_fee_collection.json +++ b/erpnext/education/report/student_fee_collection/student_fee_collection.json @@ -1,18 +1,18 @@ { "add_total_row": 0, - "apply_user_permissions": 1, "creation": "2016-06-22 02:58:41.024538", "disabled": 0, "docstatus": 0, "doctype": "Report", "idx": 3, "is_standard": "Yes", - "modified": "2017-11-10 19:41:37.320224", + "modified": "2018-12-17 16:46:46.176620", "modified_by": "Administrator", "module": "Education", "name": "Student Fee Collection", "owner": "Administrator", - "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(paid_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student", + "prepared_report": 0, + "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(grand_total) - sum(outstanding_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student", "ref_doctype": "Fees", "report_name": "Student Fee Collection", "report_type": "Query Report", diff --git a/erpnext/healthcare/doctype/patient/patient.js b/erpnext/healthcare/doctype/patient/patient.js index d0ab94c792..de5bce0aa6 100644 --- a/erpnext/healthcare/doctype/patient/patient.js +++ b/erpnext/healthcare/doctype/patient/patient.js @@ -120,3 +120,16 @@ var btn_invoice_registration = function (frm) { } }); }; + +frappe.ui.form.on('Patient Relation', { + patient_relation_add: function(frm){ + frm.fields_dict['patient_relation'].grid.get_field('patient').get_query = function(frm){ + var patient_list = []; + if(!frm.doc.__islocal) patient_list.push(frm.doc.name); + $.each(frm.doc.patient_relation, function(idx, val){ + if (val.patient) patient_list.push(val.patient); + }); + return { filters: [['Patient', 'name', 'not in', patient_list]] }; + }; + } +}); \ No newline at end of file diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js index 71c8212412..2f328de1bc 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js @@ -39,7 +39,9 @@ frappe.ui.form.on('Patient Appointment', { frm.add_custom_button(__('Cancel'), function() { btn_update_status(frm, "Cancelled"); }); - + frm.add_custom_button(__('Reschedule'), function() { + check_and_set_availability(frm); + }); if(frm.doc.procedure_template){ frm.add_custom_button(__("Procedure"),function(){ btn_create_procedure(frm); @@ -59,7 +61,9 @@ frappe.ui.form.on('Patient Appointment', { frm.add_custom_button(__('Cancel'), function() { btn_update_status(frm, "Cancelled"); }); - + frm.add_custom_button(__('Reschedule'), function() { + check_and_set_availability(frm); + }); if(frm.doc.procedure_template){ frm.add_custom_button(__("Procedure"),function(){ btn_create_procedure(frm); @@ -100,117 +104,7 @@ frappe.ui.form.on('Patient Appointment', { }); }, check_availability: function(frm) { - var { practitioner, appointment_date } = frm.doc; - if(!(practitioner && appointment_date)) { - frappe.throw(__("Please select Healthcare Practitioner and Date")); - } - - // show booking modal - frm.call({ - method: 'get_availability_data', - args: { - practitioner: practitioner, - date: appointment_date - }, - callback: (r) => { - var data = r.message; - if(data.slot_details.length > 0){ - show_availability(data); - }else{ - show_empty_state(); - } - } - }); - - function show_empty_state() { - frappe.msgprint({ - title: __('Not Available'), - message: __("Healthcare Practitioner {0} not available on {1}", [practitioner.bold(), appointment_date.bold()]), - indicator: 'red' - }); - } - - function show_availability(data) { - var d = new frappe.ui.Dialog({ - title: __("Available slots"), - fields: [{ fieldtype: 'HTML', fieldname: 'available_slots'}], - primary_action_label: __("Book"), - primary_action: function() { - // book slot - var btn_selected = $wrapper.find('button.btn-selected-slot'); - frm.set_value('appointment_time', btn_selected.attr('data-name')); - frm.set_value('service_unit', btn_selected.attr('data-service-unit') || ''); - frm.set_value('duration', btn_selected.attr('data-duration')); - d.hide(); - frm.enable_save(); - frm.save(); - frm.enable_save(); - } - }); - var $wrapper = d.fields_dict.available_slots.$wrapper; - - // disable dialog action initially - d.get_primary_btn().attr('disabled', true); - - var slot_details = data.slot_details; - var slot_html = ""; - var duration = frm.doc.duration | 0; - $.each(slot_details, function(i, slot_detail){ - slot_html = slot_html + ``; - slot_html = slot_html + `
` + slot_detail['avail_slot'].map(slot => { - let disabled = ''; - let start_str = slot.from_time; - let slot_start_time = moment(slot.from_time, 'HH:mm:ss'); - let slot_to_time = moment(slot.to_time, 'HH:mm:ss'); - let interval = (slot_to_time - slot_start_time)/60000 | 0; - // iterate in all booked appointments, update the start time and duration - slot_detail['appointments'].forEach(function(booked) { - let booked_moment = moment(booked.appointment_time, 'HH:mm:ss'); - let end_time = booked_moment.clone().add(booked.duration, 'minutes'); - // Deal with 0 duration appointments - if(booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)){ - if(booked.duration == 0){ - disabled = 'disabled="disabled"'; - return false; - } - } - // Check for overlaps considering appointment duration - if(slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)){ - // There is an overlap - disabled = 'disabled="disabled"'; - return false; - } - }); - - return ``; - }).join(""); - slot_html = slot_html + `
`; - }); - - $wrapper - .css('margin-bottom', 0) - .addClass('text-center') - .html(slot_html); - - // blue button when clicked - $wrapper.on('click', 'button', function() { - var $btn = $(this); - $wrapper.find('button').removeClass('btn-primary'); - $wrapper.find('button').removeClass('btn-selected-slot'); - $btn.addClass('btn-primary'); - $btn.addClass('btn-selected-slot'); - // enable dialog action - d.get_primary_btn().attr('disabled', null); - }); - - d.show(); - } + check_and_set_availability(frm); }, onload:function(frm){ if(frm.is_new()) { @@ -223,6 +117,176 @@ frappe.ui.form.on('Patient Appointment', { } }); +var check_and_set_availability = function(frm) { + var selected_slot = null; + var service_unit = null; + var duration = null; + + show_availability(); + + function show_empty_state(practitioner, appointment_date) { + frappe.msgprint({ + title: __('Not Available'), + message: __("Healthcare Practitioner {0} not available on {1}", [practitioner.bold(), appointment_date.bold()]), + indicator: 'red' + }); + } + + function show_availability() { + let selected_practitioner = ''; + var d = new frappe.ui.Dialog({ + title: __("Available slots"), + fields: [ + { fieldtype: 'Link', options: 'Medical Department', reqd:1, fieldname: 'department', label: 'Medical Department'}, + { fieldtype: 'Column Break'}, + { fieldtype: 'Link', options: 'Healthcare Practitioner', reqd:1, fieldname: 'practitioner', label: 'Healthcare Practitioner'}, + { fieldtype: 'Column Break'}, + { fieldtype: 'Date', reqd:1, fieldname: 'appointment_date', label: 'Date'}, + { fieldtype: 'Section Break'}, + { fieldtype: 'HTML', fieldname: 'available_slots'} + ], + primary_action_label: __("Book"), + primary_action: function() { + frm.set_value('appointment_time', selected_slot); + frm.set_value('service_unit', service_unit || ''); + frm.set_value('duration', duration); + frm.set_value('practitioner', d.get_value('practitioner')); + frm.set_value('department', d.get_value('department')); + frm.set_value('appointment_date', d.get_value('appointment_date')); + d.hide(); + frm.enable_save(); + frm.save(); + frm.enable_save(); + d.get_primary_btn().attr('disabled', true); + } + }); + + d.set_values({ + 'department': frm.doc.department, + 'practitioner': frm.doc.practitioner, + 'appointment_date': frm.doc.appointment_date + }); + + d.fields_dict["department"].df.onchange = () => { + d.set_values({ + 'practitioner': '' + }); + var department = d.get_value('department'); + if(department){ + d.fields_dict.practitioner.get_query = function() { + return { + filters: { + "department": department + } + }; + }; + } + }; + + // disable dialog action initially + d.get_primary_btn().attr('disabled', true); + + // Field Change Handler + + var fd = d.fields_dict; + + d.fields_dict["appointment_date"].df.onchange = () => { + show_slots(d, fd); + }; + d.fields_dict["practitioner"].df.onchange = () => { + if(d.get_value('practitioner') && d.get_value('practitioner') != selected_practitioner){ + selected_practitioner = d.get_value('practitioner'); + show_slots(d, fd); + } + }; + d.show(); + } + + function show_slots(d, fd) { + if (d.get_value('appointment_date') && d.get_value('practitioner')){ + fd.available_slots.html(""); + frappe.call({ + method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_availability_data', + args: { + practitioner: d.get_value('practitioner'), + date: d.get_value('appointment_date') + }, + callback: (r) => { + var data = r.message; + if(data.slot_details.length > 0) { + var $wrapper = d.fields_dict.available_slots.$wrapper; + + // make buttons for each slot + var slot_details = data.slot_details; + var slot_html = ""; + for (let i = 0; i < slot_details.length; i++) { + slot_html = slot_html + ``; + slot_html = slot_html + `
` + slot_details[i].avail_slot.map(slot => { + let disabled = ''; + let start_str = slot.from_time; + let slot_start_time = moment(slot.from_time, 'HH:mm:ss'); + let slot_to_time = moment(slot.to_time, 'HH:mm:ss'); + let interval = (slot_to_time - slot_start_time)/60000 | 0; + // iterate in all booked appointments, update the start time and duration + slot_details[i].appointments.forEach(function(booked) { + let booked_moment = moment(booked.appointment_time, 'HH:mm:ss'); + let end_time = booked_moment.clone().add(booked.duration, 'minutes'); + // Deal with 0 duration appointments + if(booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)){ + if(booked.duration == 0){ + disabled = 'disabled="disabled"'; + return false; + } + } + // Check for overlaps considering appointment duration + if(slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)){ + // There is an overlap + disabled = 'disabled="disabled"'; + return false; + } + }); + return ``; + }).join(""); + slot_html = slot_html + `
`; + } + + $wrapper + .css('margin-bottom', 0) + .addClass('text-center') + .html(slot_html); + + // blue button when clicked + $wrapper.on('click', 'button', function() { + var $btn = $(this); + $wrapper.find('button').removeClass('btn-primary'); + $btn.addClass('btn-primary'); + selected_slot = $btn.attr('data-name'); + service_unit = $btn.attr('data-service-unit'); + duration = $btn.attr('data-duration'); + // enable dialog action + d.get_primary_btn().attr('disabled', null); + }); + + }else { + // fd.available_slots.html("Please select a valid date.".bold()) + show_empty_state(d.get_value('practitioner'), d.get_value('appointment_date')); + } + }, + freeze: true, + freeze_message: __("Fetching records......") + }); + }else{ + fd.available_slots.html("Appointment date and Healthcare Practitioner are Mandatory".bold()); + } + } +}; + var get_procedure_prescribed = function(frm){ if(frm.doc.patient){ frappe.call({ diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json index cef49d730b..ee9f013084 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json @@ -1,1058 +1,1184 @@ { - "allow_copy": 1, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "HLC-APP-.YYYY.-.#####", - "beta": 1, - "creation": "2017-05-04 11:52:40.941507", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 0, - "engine": "InnoDB", + "allow_copy": 1, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 0, + "autoname": "OP-.######", + "beta": 1, + "creation": "2017-05-04 11:52:40.941507", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 0, + "engine": "InnoDB", "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.inpatient_record", - "fieldname": "inpatient_record", - "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": "Inpatient Record", - "length": 0, - "no_copy": 0, - "options": "Inpatient Record", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "patient.inpatient_record", + "fieldname": "inpatient_record", + "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": "Inpatient Record", + "length": 0, + "no_copy": 0, + "options": "Inpatient Record", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "inpatient_record.patient", - "fieldname": "patient", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Patient", - "length": 0, - "no_copy": 0, - "options": "Patient", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "inpatient_record.patient", + "fieldname": "patient", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Patient", + "length": 0, + "no_copy": 0, + "options": "Patient", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 1, + "set_only_once": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "department", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Department", - "length": 0, - "no_copy": 0, - "options": "Medical Department", - "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": 1, - "set_only_once": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "appointment_type", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Appointment Type", + "length": 0, + "no_copy": 0, + "options": "Appointment Type", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "practitioner", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Healthcare Practitioner", - "length": 0, - "no_copy": 0, - "options": "Healthcare Practitioner", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "In Minutes", + "fieldname": "duration", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Duration", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "get_procedure_from_encounter", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Get prescribed procedures", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_1", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "", + "length": 0, + "no_copy": 0, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "procedure_prescription", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Procedure Prescription", - "length": 0, - "no_copy": 1, - "options": "Procedure Prescription", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Scheduled", + "depends_on": "eval:!doc.__islocal", + "fieldname": "status", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Status", + "length": 0, + "no_copy": 0, + "options": "\nScheduled\nOpen\nClosed\nPending\nCancelled", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "procedure_template", - "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": "Procedure", - "length": 0, - "no_copy": 0, - "options": "Clinical Procedure Template", - "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": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "procedure_template", + "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": "Procedure", + "length": 0, + "no_copy": 0, + "options": "Clinical Procedure Template", + "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": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "appointment_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": 1, - "label": "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": 1, - "set_only_once": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "get_procedure_from_encounter", + "fieldtype": "Button", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Get prescribed procedures", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "appointment_time", - "fieldtype": "Time", - "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": "Time", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "procedure_prescription", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Procedure Prescription", + "length": 0, + "no_copy": 1, + "options": "Procedure Prescription", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "In Minutes", - "fieldname": "duration", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Duration", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "service_unit", + "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": "Service Unit", + "length": 0, + "no_copy": 0, + "options": "Healthcare Service Unit", + "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": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.__islocal", - "fieldname": "check_availability", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Check availability", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.__islocal", + "fieldname": "check_availability", + "fieldtype": "Button", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Check availability", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_12", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "service_unit", - "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": "Service Unit", - "length": 0, - "no_copy": 0, - "options": "Healthcare Service Unit", - "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": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "practitioner", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 1, + "label": "Healthcare Practitioner", + "length": 0, + "no_copy": 0, + "options": "Healthcare Practitioner", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 1, + "set_only_once": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_from": "patient.patient_name", - "fieldname": "patient_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Patient Name", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "department", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Department", + "length": 0, + "no_copy": 0, + "options": "Medical Department", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.sex", - "fieldname": "patient_sex", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Gender", - "length": 0, - "no_copy": 1, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_17", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "patient_age", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Patient Age", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "appointment_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": 1, + "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": 1, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Scheduled", - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "\nScheduled\nOpen\nClosed\nPending\nCancelled", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "appointment_time", + "fieldtype": "Time", + "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": "Time", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "appointment_type", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Type", - "length": 0, - "no_copy": 0, - "options": "Appointment Type", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_16", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "section_break_1", - "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": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_from": "patient.patient_name", + "fieldname": "patient_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Patient Name", + "length": 0, + "no_copy": 0, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "appointment_datetime", - "fieldtype": "Datetime", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Date TIme", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "patient.sex", + "fieldname": "patient_sex", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Gender", + "length": 0, + "no_copy": 1, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "mode_of_payment", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_21", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "paid_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Paid Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "patient_age", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Patient Age", + "length": 0, + "no_copy": 0, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_2", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fieldname": "section_break_1", + "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": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fieldname": "invoiced", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoiced", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "appointment_datetime", + "fieldtype": "Datetime", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Date TIme", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 1, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Mode of Payment", + "length": 0, + "no_copy": 0, + "options": "Mode of Payment", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "section_break_3", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "More Info", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "paid_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Paid Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "notes", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 1, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Notes", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "referring_practitioner", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Referring Practitioner", - "length": 0, - "no_copy": 0, - "options": "Healthcare Practitioner", - "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": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "fieldname": "invoiced", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Invoiced", + "length": 0, + "no_copy": 0, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fieldname": "reminded", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reminded", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "company", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Company", + "length": 0, + "no_copy": 1, + "options": "Company", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "columns": 0, + "fieldname": "section_break_3", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "More Info", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "notes", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 1, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Notes", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "referring_practitioner", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Referring Practitioner", + "length": 0, + "no_copy": 0, + "options": "Healthcare Practitioner", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "fieldname": "reminded", + "fieldtype": "Check", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Reminded", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-09-13 10:15:45.704550", - "modified_by": "Administrator", - "module": "Healthcare", - "name": "Patient Appointment", - "name_case": "", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2018-11-14 13:24:01.529536", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Patient Appointment", + "name_case": "", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Healthcare Administrator", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Healthcare Administrator", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Physician", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Physician", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Nursing User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Nursing User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Healthcare", - "search_fields": "patient, practitioner, department, appointment_date, appointment_time", - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "patient", - "track_changes": 1, - "track_seen": 1, + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "restrict_to_domain": "Healthcare", + "search_fields": "patient, practitioner, department, appointment_date, appointment_time", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "patient", + "track_changes": 1, + "track_seen": 1, "track_views": 0 } diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 43afa2ae28..cf8c06d700 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -12,7 +12,7 @@ app_license = "GNU General Public License (v3)" source_link = "https://github.com/frappe/erpnext" develop_version = '12.x.x-develop' -staging_version = '11.0.3-beta.24' +staging_version = '11.0.3-beta.30' error_report_email = "support@erpnext.com" diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index 75247a4585..bf150b1232 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -36,10 +36,13 @@ class EmployeeBenefitClaim(Document): frappe.throw(_("Maximum benefit amount of employee {0} exceeds {1}").format(self.employee, max_benefits)) def validate_max_benefit_for_component(self, payroll_period): - claimed_amount = self.claimed_amount - claimed_amount += get_previous_claimed_amount(self.employee, payroll_period, component = self.earning_component) - if claimed_amount > self.max_amount_eligible: - frappe.throw(_("Maximum amount eligible for the component {0} exceeds {1}").format(self.earning_component, self.max_amount_eligible)) + if self.max_amount_eligible: + claimed_amount = self.claimed_amount + claimed_amount += get_previous_claimed_amount(self.employee, + payroll_period, component = self.earning_component) + if claimed_amount > self.max_amount_eligible: + frappe.throw(_("Maximum amount eligible for the component {0} exceeds {1}") + .format(self.earning_component, self.max_amount_eligible)) def validate_non_pro_rata_benefit_claim(self, max_benefits, payroll_period): claimed_amount = self.claimed_amount @@ -75,12 +78,17 @@ def get_benefit_pro_rata_ratio_amount(employee, on_date, sal_struct): total_pro_rata_max = 0 benefit_amount_total = 0 for sal_struct_row in sal_struct.get("earnings"): - pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"]) + try: + pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"]) + except TypeError: + # show the error in tests? + frappe.throw("Unable to find Salary Component {0}".format(sal_struct_row.salary_component)) if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1: total_pro_rata_max += max_benefit_amount if total_pro_rata_max > 0: for sal_struct_row in sal_struct.get("earnings"): pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"]) + if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1: component_max = max_benefit_amount benefit_amount = component_max * sal_struct.max_benefits / total_pro_rata_max diff --git a/erpnext/hr/doctype/employee_separation/employee_separation_list.js b/erpnext/hr/doctype/employee_separation/employee_separation_list.js index 11487cc6f0..76c58f5632 100644 --- a/erpnext/hr/doctype/employee_separation/employee_separation_list.js +++ b/erpnext/hr/doctype/employee_separation/employee_separation_list.js @@ -1,5 +1,5 @@ frappe.listview_settings['Employee Separation'] = { - add_fields: ["boarding_status", "employee_name", "date_of_joining", "department"], + add_fields: ["boarding_status", "employee_name", "department"], filters:[["boarding_status","=", "Pending"]], get_indicator: function(doc) { return [__(doc.boarding_status), frappe.utils.guess_colour(doc.boarding_status), "status,=," + doc.boarding_status]; diff --git a/erpnext/hr/doctype/holiday_list/holiday_list.js b/erpnext/hr/doctype/holiday_list/holiday_list.js index b4c56da649..462bd8bb67 100644 --- a/erpnext/hr/doctype/holiday_list/holiday_list.js +++ b/erpnext/hr/doctype/holiday_list/holiday_list.js @@ -3,7 +3,9 @@ frappe.ui.form.on('Holiday List', { refresh: function(frm) { - frm.set_value('total_holidays', frm.doc.holidays.length); + if (frm.doc.holidays) { + frm.set_value('total_holidays', frm.doc.holidays.length); + } }, from_date: function(frm) { if (frm.doc.from_date && !frm.doc.to_date) { diff --git a/erpnext/hr/doctype/job_offer/job_offer.js b/erpnext/hr/doctype/job_offer/job_offer.js index 367ce38318..4217a782a8 100755 --- a/erpnext/hr/doctype/job_offer/job_offer.js +++ b/erpnext/hr/doctype/job_offer/job_offer.js @@ -14,7 +14,7 @@ frappe.ui.form.on("Job Offer", { refresh: function (frm) { if ((!frm.doc.__islocal) && (frm.doc.status == 'Accepted') - && (frm.doc.docstatus === 1) && (!frm.doc.__onload.employee)) { + && (frm.doc.docstatus === 1) && (!frm.doc.__onload || !frm.doc.__onload.employee)) { frm.add_custom_button(__('Make Employee'), function () { erpnext.job_offer.make_employee(frm); @@ -22,7 +22,7 @@ frappe.ui.form.on("Job Offer", { ); } - if(frm.doc.__onload.employee) { + if(frm.doc.__onload && frm.doc.__onload.employee) { frm.add_custom_button(__('Show Employee'), function () { frappe.set_route("Form", "Employee", frm.doc.__onload.employee); diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index aca277effd..6b7c0f7e79 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -187,7 +187,7 @@ class LeaveApplication(Document): self.total_leave_days = get_number_of_leave_days(self.employee, self.leave_type, self.from_date, self.to_date, self.half_day, self.half_day_date) - if self.total_leave_days == 0: + if self.total_leave_days <= 0: frappe.throw(_("The day(s) on which you are applying for leave are holidays. You need not apply for leave.")) if not is_lwp(self.leave_type): diff --git a/erpnext/hr/doctype/leave_application/leave_application_list.js b/erpnext/hr/doctype/leave_application/leave_application_list.js index d7588da4dd..f69b182737 100644 --- a/erpnext/hr/doctype/leave_application/leave_application_list.js +++ b/erpnext/hr/doctype/leave_application/leave_application_list.js @@ -1,3 +1,10 @@ frappe.listview_settings['Leave Application'] = { - add_fields: ["leave_type", "employee", "employee_name", "total_leave_days", "from_date", "to_date"] + add_fields: ["leave_type", "employee", "employee_name", "total_leave_days", "from_date", "to_date"], + get_indicator: function (doc) { + if (doc.status === "Approved") { + return [__("Approved"), "green", "status,=,Approved"]; + } else if (doc.status === "Rejected") { + return [__("Rejected"), "red", "status,=,Rejected"]; + } + } }; diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.js b/erpnext/hr/doctype/salary_slip/salary_slip.js index affbb552f7..86c50d08ba 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.js +++ b/erpnext/hr/doctype/salary_slip/salary_slip.js @@ -177,7 +177,7 @@ var calculate_earning_total = function(doc, dt, dn, reset_amount) { if(cint(tbl[i].depends_on_lwp) == 1) { tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days) / cint(doc.total_working_days)*100)/100; - } else if(reset_amount) { + } else if(reset_amount && tbl[i].default_amount) { tbl[i].amount = tbl[i].default_amount; } if(!tbl[i].do_not_include_in_total) { @@ -198,7 +198,7 @@ var calculate_ded_total = function(doc, dt, dn, reset_amount) { for(var i = 0; i < tbl.length; i++){ if(cint(tbl[i].depends_on_lwp) == 1) { tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days)/cint(doc.total_working_days)*100)/100; - } else if(reset_amount) { + } else if(reset_amount && tbl[i].default_amount) { tbl[i].amount = tbl[i].default_amount; } if(!tbl[i].do_not_include_in_total) { diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py index 73ab67dd6f..079bec51b2 100644 --- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py @@ -26,6 +26,7 @@ class TestSalarySlip(unittest.TestCase): self.make_holiday_list() frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List") + frappe.db.set_value("HR Settings", None, "email_salary_slip_to_employee", 0) def tearDown(self): frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0) @@ -255,6 +256,9 @@ class TestSalarySlip(unittest.TestCase): raise frappe.db.sql("""delete from `tabAdditional Salary` where employee=%s""", (employee)) + # undelete fixture data + frappe.db.rollback() + def make_holiday_list(self): fiscal_year = get_fiscal_year(nowdate(), company=erpnext.get_default_company()) if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"): diff --git a/erpnext/manufacturing/doctype/bom/test_records.json b/erpnext/manufacturing/doctype/bom/test_records.json index cc9564276a..1a7e594e87 100644 --- a/erpnext/manufacturing/doctype/bom/test_records.json +++ b/erpnext/manufacturing/doctype/bom/test_records.json @@ -10,7 +10,8 @@ "rate": 5000.0, "uom": "_Test UOM", "stock_uom": "_Test UOM", - "source_warehouse": "_Test Warehouse - _TC" + "source_warehouse": "_Test Warehouse - _TC", + "allow_transfer_for_manufacture": 1 }, { "amount": 2000.0, @@ -21,7 +22,8 @@ "rate": 1000.0, "uom": "_Test UOM", "stock_uom": "_Test UOM", - "source_warehouse": "_Test Warehouse - _TC" + "source_warehouse": "_Test Warehouse - _TC", + "allow_transfer_for_manufacture": 1 } ], "docstatus": 1, @@ -54,7 +56,8 @@ "rate": 5000.0, "uom": "_Test UOM", "stock_uom": "_Test UOM", - "source_warehouse": "_Test Warehouse - _TC" + "source_warehouse": "_Test Warehouse - _TC", + "allow_transfer_for_manufacture": 1 }, { "amount": 2000.0, @@ -65,7 +68,8 @@ "rate": 1000.0, "uom": "_Test UOM", "stock_uom": "_Test UOM", - "source_warehouse": "_Test Warehouse - _TC" + "source_warehouse": "_Test Warehouse - _TC", + "allow_transfer_for_manufacture": 1 } ], "docstatus": 1, @@ -97,7 +101,8 @@ "rate": 5000.0, "uom": "_Test UOM", "stock_uom": "_Test UOM", - "source_warehouse": "_Test Warehouse - _TC" + "source_warehouse": "_Test Warehouse - _TC", + "allow_transfer_for_manufacture": 1 }, { "amount": 3000.0, @@ -109,7 +114,8 @@ "rate": 1000.0, "uom": "_Test UOM", "stock_uom": "_Test UOM", - "source_warehouse": "_Test Warehouse - _TC" + "source_warehouse": "_Test Warehouse - _TC", + "allow_transfer_for_manufacture": 1 } ], "docstatus": 1, @@ -143,7 +149,8 @@ "rate": 3000.0, "uom": "_Test UOM", "stock_uom": "_Test UOM", - "source_warehouse": "_Test Warehouse - _TC" + "source_warehouse": "_Test Warehouse - _TC", + "allow_transfer_for_manufacture": 1 } ], "docstatus": 1, diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json index de079751a7..cc69471eba 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.json +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json @@ -1,1051 +1,1053 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2013-02-22 01:27:49", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 1, + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2013-02-22 01:27:49", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 3, - "fieldname": "item_code", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Item Code", - "length": 0, - "no_copy": 0, - "oldfieldname": "item_code", - "oldfieldtype": "Link", - "options": "Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 3, + "fieldname": "item_code", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Item Code", + "length": 0, + "no_copy": 0, + "oldfieldname": "item_code", + "oldfieldtype": "Link", + "options": "Item", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 3, - "fieldname": "item_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 3, + "fieldname": "item_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Item Name", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "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, + "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bom_no", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "BOM No", - "length": 0, - "no_copy": 0, - "oldfieldname": "bom_no", - "oldfieldtype": "Link", - "options": "BOM", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "150px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "bom_no", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "BOM No", + "length": 0, + "no_copy": 0, + "oldfieldname": "bom_no", + "oldfieldtype": "Link", + "options": "BOM", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, + "unique": 0, "width": "150px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "source_warehouse", - "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": "Source Warehouse", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "source_warehouse", + "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": "Source Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "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, - "label": "Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "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, + "label": "Description", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "description", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item Description", - "length": 0, - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "250px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "description", + "fieldtype": "Text Editor", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Item Description", + "length": 0, + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "250px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0, "width": "250px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "col_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "col_break1", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "image", - "fieldtype": "Attach", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Image", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "image", + "fieldtype": "Attach", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Image", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "image_view", - "fieldtype": "Image", - "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": "Image View", - "length": 0, - "no_copy": 0, - "options": "image", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "image_view", + "fieldtype": "Image", + "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": "Image View", + "length": 0, + "no_copy": 0, + "options": "image", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "quantity_and_rate", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Quantity and Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "quantity_and_rate", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Quantity and Rate", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "qty", - "fieldtype": "Float", - "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": "Qty", - "length": 0, - "no_copy": 0, - "oldfieldname": "qty", - "oldfieldtype": "Currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 2, + "fieldname": "qty", + "fieldtype": "Float", + "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": "Qty", + "length": 0, + "no_copy": 0, + "oldfieldname": "qty", + "oldfieldtype": "Currency", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 1, - "fieldname": "uom", - "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": "UOM", - "length": 0, - "no_copy": 0, - "options": "UOM", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 1, + "fieldname": "uom", + "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": "UOM", + "length": 0, + "no_copy": 0, + "options": "UOM", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "col_break2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "col_break2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "stock_qty", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Stock Qty", - "length": 0, - "no_copy": 0, - "oldfieldname": "stock_qty", - "oldfieldtype": "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "stock_qty", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Stock Qty", + "length": 0, + "no_copy": 0, + "oldfieldname": "stock_qty", + "oldfieldtype": "Currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "stock_uom", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Stock UOM", - "length": 0, - "no_copy": 0, - "oldfieldname": "stock_uom", - "oldfieldtype": "Data", - "options": "UOM", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "stock_uom", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Stock UOM", + "length": 0, + "no_copy": 0, + "oldfieldname": "stock_uom", + "oldfieldtype": "Data", + "options": "UOM", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "conversion_factor", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Conversion Factor", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "conversion_factor", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Conversion Factor", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "rate_amount_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rate & Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "rate_amount_section", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rate & Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "rate", - "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": "Rate", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "rate", + "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": "Rate", + "length": 0, + "no_copy": 0, + "options": "currency", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_rate", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Basic Rate (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "base_rate", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Basic Rate (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_21", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_21", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "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": "Amount", - "length": 0, - "no_copy": 0, - "oldfieldname": "amount_as_per_mar", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "150px", - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "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": "Amount", + "length": 0, + "no_copy": 0, + "oldfieldname": "amount_as_per_mar", + "oldfieldtype": "Currency", + "options": "currency", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0, "width": "150px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_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": "Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "base_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": "Amount (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_18", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_18", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 1, - "fieldname": "scrap", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Scrap %", - "length": 0, - "no_copy": 0, - "oldfieldname": "scrap", - "oldfieldtype": "Currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 1, + "fieldname": "scrap", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Scrap %", + "length": 0, + "no_copy": 0, + "oldfieldname": "scrap", + "oldfieldtype": "Currency", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "qty_consumed_per_unit", - "fieldtype": "Float", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Qty Consumed Per Unit", - "length": 0, - "no_copy": 0, - "oldfieldname": "qty_consumed_per_unit", - "oldfieldtype": "Float", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "qty_consumed_per_unit", + "fieldtype": "Float", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Qty Consumed Per Unit", + "length": 0, + "no_copy": 0, + "oldfieldname": "qty_consumed_per_unit", + "oldfieldtype": "Float", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_27", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_27", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "allow_alternative_item", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Alternative Item", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_alternative_item", + "fieldtype": "Check", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allow Alternative Item", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "allow_transfer_for_manufacture", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Transfer for Manufacture", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "item_code.allow_transfer_for_manufacture", + "fieldname": "allow_transfer_for_manufacture", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allow Transfer for Manufacture", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "original_item", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Original Item", - "length": 0, - "no_copy": 0, - "options": "Item", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "original_item", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Original Item", + "length": 0, + "no_copy": 0, + "options": "Item", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "operation", - "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": "Item operation", - "length": 0, - "no_copy": 0, - "options": "Operation", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "operation", + "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": "Item operation", + "length": 0, + "no_copy": 0, + "options": "Operation", + "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 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-09-16 19:59:36.636884", - "modified_by": "clarkejjm@gmail.com", - "module": "Manufacturing", - "name": "BOM Item", - "owner": "Administrator", - "permissions": [], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 1, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2018-11-22 15:04:55.187136", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "BOM Item", + "owner": "Administrator", + "permissions": [], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 0, + "track_seen": 0, "track_views": 0 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 81c5eb9550..bc745350a7 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -110,7 +110,7 @@ class JobCard(Document): if self.items: self.transferred_qty = frappe.db.get_value('Stock Entry', {'job_card': self.name, - 'work_order': self.work_order, 'docstatus': 1}, 'sum(fg_completed_qty)') + 'work_order': self.work_order, 'docstatus': 1}, 'sum(fg_completed_qty)') or 0 self.db_set("transferred_qty", self.transferred_qty) diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py index b80b0beba3..e88164f917 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py @@ -13,3 +13,11 @@ class ManufacturingSettings(Document): def get_mins_between_operations(): return relativedelta(minutes=cint(frappe.db.get_single_value("Manufacturing Settings", "mins_between_operations")) or 10) + +@frappe.whitelist() +def is_material_consumption_enabled(): + if not hasattr(frappe.local, 'material_consumption'): + frappe.local.material_consumption = cint(frappe.db.get_single_value('Manufacturing Settings', + 'material_consumption')) + + return frappe.local.material_consumption \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 7d11ae4993..24ce7d41f7 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -514,7 +514,7 @@ def get_items_for_material_requests(doc, company=None): doc = frappe._dict(json.loads(doc)) doc['mr_items'] = [] - po_items = doc['po_items'] if doc.get('po_items') else doc['items'] + po_items = doc.get('po_items') if doc.get('po_items') else doc.get('items') for data in po_items: warehouse = None @@ -533,10 +533,10 @@ def get_items_for_material_requests(doc, company=None): else: planned_qty = data.get('planned_qty') bom_no = data.get('bom_no') - include_subcontracted_items = doc['include_subcontracted_items'] - company = doc['company'] - include_non_stock_items = doc['include_non_stock_items'] - ignore_existing_ordered_qty = doc['ignore_existing_ordered_qty'] + include_subcontracted_items = doc.get('include_subcontracted_items') + company = doc.get('company') + include_non_stock_items = doc.get('include_non_stock_items') + ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty') if not planned_qty: frappe.throw(_("For row {0}: Enter Planned Qty").format(data.get('idx'))) diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index a33d42b7d0..8eade98ecb 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -48,7 +48,7 @@ class TestProductionPlan(unittest.TestCase): filters = {'production_plan': pln.name}, as_list=1) self.assertTrue(len(work_orders), len(pln.po_items)) - + for name in material_requests: mr = frappe.get_doc('Material Request', name[0]) mr.cancel() @@ -164,7 +164,7 @@ def create_production_plan(**args): mr_items = get_items_for_material_requests(pln.as_dict()) for d in mr_items: pln.append('mr_items', d) - + if not args.do_not_save: pln.insert() if not args.do_not_submit: @@ -182,7 +182,7 @@ def make_bom(**args): 'quantity': args.quantity or 1, 'company': args.company or '_Test Company' }) - + for item in args.raw_materials: item_doc = frappe.get_doc('Item', item) @@ -191,8 +191,8 @@ def make_bom(**args): 'qty': 1, 'uom': item_doc.stock_uom, 'stock_uom': item_doc.stock_uom, - 'rate': item_doc.valuation_rate or args.rate + 'rate': item_doc.valuation_rate or args.rate, }) - + bom.insert(ignore_permissions=True) bom.submit() \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index fb8fd26206..431ad32558 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -292,6 +292,7 @@ class TestWorkOrder(unittest.TestCase): make_bom(item=fg_item, rate=1000, raw_materials = ['_Test FG Item', '_Test FG Non Stock Item']) wo = make_wo_order_test_record(production_item = fg_item) + se = frappe.get_doc(make_stock_entry(wo.name, "Material Transfer for Manufacture", 1)) se.insert() se.submit() diff --git a/erpnext/manufacturing/page/production_analytics/__init__.py b/erpnext/manufacturing/page/production_analytics/__init__.py deleted file mode 100644 index baffc48825..0000000000 --- a/erpnext/manufacturing/page/production_analytics/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/manufacturing/page/production_analytics/production_analytics.js b/erpnext/manufacturing/page/production_analytics/production_analytics.js deleted file mode 100644 index 1647313036..0000000000 --- a/erpnext/manufacturing/page/production_analytics/production_analytics.js +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -frappe.pages['production-analytics'].on_page_load = function(wrapper) { - frappe.ui.make_app_page({ - parent: wrapper, - title: __('Production Analytics'), - single_column: true - }); - - new erpnext.ProductionAnalytics(wrapper); - - frappe.breadcrumbs.add("Manufacturing"); -} - -erpnext.ProductionAnalytics = frappe.views.GridReportWithPlot.extend({ - init: function(wrapper) { - this._super({ - title: __("Production Analytics"), - parent: $(wrapper).find('.layout-main'), - page: wrapper.page, - doctypes: ["Item", "Company", "Fiscal Year", "Work Order"] - }); - - }, - setup_columns: function() { - - var std_columns = [ - {id: "name", name: __("Status"), field: "name", width: 100} - ]; - - this.make_date_range_columns(); - this.columns = std_columns.concat(this.columns); - }, - filters: [ - {fieldtype:"Select", label: __("Company"), link:"Company", fieldname: "company", - default_value: __("Select Company...")}, - {fieldtype:"Date", label: __("From Date"), fieldname: "from_date"}, - {fieldtype:"Date", label: __("To Date"), fieldname: "to_date"}, - {fieldtype:"Select", label: __("Range"), fieldname: "range", - options:[{label: __("Daily"), value: "Daily"}, {label: __("Weekly"), value: "Weekly"}, - {label: __("Monthly"), value: "Monthly"}, {label: __("Quarterly"), value: "Quarterly"}, - {label: __("Yearly"), value: "Yearly"}]} - ], - setup_filters: function() { - var me = this; - this._super(); - - this.trigger_refresh_on_change(["company"]); - this.trigger_refresh_on_change(["range"]); - - this.show_zero_check(); - - }, - init_filter_values: function() { - this._super(); - this.filter_inputs.range.val('Monthly'); - }, - setup_chart: function() { - var me = this; - - var chart_data = this.get_chart_data ? this.get_chart_data() : null; - - const parent = this.wrapper.find('.chart')[0]; - this.chart = new Chart(parent, { - height: 200, - data: chart_data, - type: 'line' - }); - }, - set_default_values: function() { - var values = { - from_date: frappe.datetime.str_to_user(frappe.datetime.add_months(frappe.datetime.now_datetime(),-12) ), - to_date: frappe.datetime.str_to_user(frappe.datetime.add_months(frappe.datetime.now_datetime(),1)) - } - - var me = this; - $.each(values, function(i, v) { - if(me.filter_inputs[i] && !me.filter_inputs[i].val()) - me.filter_inputs[i].val(v); - }) - }, - - prepare_data: function() { - // add Opening, Closing, Totals rows - // if filtered by account and / or voucher - var me = this; - var all_open_orders = {name:"All Work Orders", "id": "all-open-pos", - checked:true}; - var not_started = {name:"Not Started", "id":"not-started-pos", - checked:true}; - var overdue = {name:"Overdue (Not Started)", "id":"overdue-pos", - checked:true}; - var pending = {name:"Pending", "id":"pending-pos", - checked:true}; - var completed = {name:"Completed", "id":"completed-pos", - checked:true}; - - $.each(frappe.report_dump.data["Work Order"], function(i, d) { - var dateobj = frappe.datetime.str_to_obj(d.creation); - var date = frappe.datetime.str_to_user(d.creation.split(" ")[0]); - - $.each(me.columns, function(i,col) { - if (i > 1){ - var start_period = frappe.datetime.user_to_obj(frappe.datetime.str_to_user(col.id)); - var end_period = frappe.datetime.user_to_obj(frappe.datetime.str_to_user(col.name)); - var astart_date = frappe.datetime.user_to_obj(frappe.datetime.str_to_user(d.actual_start_date)); - var planned_start_date = frappe.datetime.user_to_obj(frappe.datetime.str_to_user(d.planned_start_date)); - var aend_date = frappe.datetime.user_to_obj(frappe.datetime.str_to_user(d.actual_end_date)); - var modified = frappe.datetime.user_to_obj(frappe.datetime.str_to_user(d.modified)); - - if (dateobj <= start_period || dateobj <= end_period) { - all_open_orders[col.field] = flt(all_open_orders[col.field]) + 1; - - if(d.status=="Completed") { - if(aend_date < start_period || modified < start_period) { - completed[col.field] = flt(completed[col.field]) + 1; - } - else if (astart_date < start_period) { - pending[col.field] = flt(pending[col.field]) + 1; - } - else if (planned_start_date < start_period) { - overdue[col.field] = flt(overdue[col.field]) + 1; - } else { - not_started[col.field] = flt(not_started[col.field]) + 1; - } - }else if(d.status == "In Process") - { - if (astart_date < start_period || modified < start_period){ - pending[col.field] = flt(pending[col.field]) + 1; - }else if (planned_start_date < start_period) { - overdue[col.field] = flt(overdue[col.field]) + 1; - }else{ - not_started[col.field] = flt(not_started[col.field]) + 1; - } - }else if(d.status == "Not Started") { - if (planned_start_date < start_period){ - overdue[col.field] = flt(overdue[col.field]) + 1; - }else{ - not_started[col.field] = flt(not_started[col.field]) + 1; - } - } - } - } - }); - }); - if(me.columns.length < 30){ - this.chart_area.toggle(true); - }else { - this.chart_area.toggle(false); - } - this.data = [all_open_orders, not_started, overdue, pending, completed]; - - } -}); diff --git a/erpnext/manufacturing/page/production_analytics/production_analytics.json b/erpnext/manufacturing/page/production_analytics/production_analytics.json deleted file mode 100644 index cd73bc826f..0000000000 --- a/erpnext/manufacturing/page/production_analytics/production_analytics.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "content": null, - "creation": "2012-09-21 20:15:16", - "docstatus": 0, - "doctype": "Page", - "icon": "fa fa-bar-chart", - "idx": 1, - "modified": "2017-02-20 17:33:05.913097", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "production-analytics", - "owner": "Administrator", - "page_name": "production-analytics", - "roles": [ - { - "role": "Analytics" - }, - { - "role": "Manufacturing Manager" - } - ], - "script": null, - "standard": "Yes", - "style": null, - "title": "Production Analytics" -} \ No newline at end of file diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.js b/erpnext/manufacturing/report/production_analytics/production_analytics.js index b7b8f05d89..99f9b1260a 100644 --- a/erpnext/manufacturing/report/production_analytics/production_analytics.js +++ b/erpnext/manufacturing/report/production_analytics/production_analytics.js @@ -39,8 +39,5 @@ frappe.query_reports["Production Analytics"] = { default: "Monthly", reqd: 1 } - ], - "formatter": function(value, row, column, data) { - return value; - } + ] } diff --git a/erpnext/patches.txt b/erpnext/patches.txt index f771181f8d..4a67eb4e47 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -568,10 +568,10 @@ erpnext.patches.v11_0.remove_land_unit_icon erpnext.patches.v11_0.add_default_dispatch_notification_template erpnext.patches.v11_0.add_market_segments erpnext.patches.v11_0.add_sales_stages -execute:frappe.delete_doc("Page", "Sales Analytics") -execute:frappe.delete_doc("Page", "Purchase Analytics") -execute:frappe.delete_doc("Page", "Stock Analytics") -execute:frappe.delete_doc("Page", "Production Analytics") +execute:frappe.delete_doc_if_exists("Page", "sales-analytics") +execute:frappe.delete_doc_if_exists("Page", "purchase-analytics") +execute:frappe.delete_doc_if_exists("Page", "stock-analytics") +execute:frappe.delete_doc_if_exists("Page", "production-analytics") erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 erpnext.patches.v11_0.drop_column_max_days_allowed erpnext.patches.v11_0.change_healthcare_desktop_icons diff --git a/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py b/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py index 0c4209ac9a..029ea8738b 100644 --- a/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py +++ b/erpnext/patches/v11_0/add_healthcare_service_unit_tree_root.py @@ -3,12 +3,18 @@ from frappe import _ def execute(): """ assign lft and rgt appropriately """ + if "Healthcare" not in frappe.get_active_domains(): + return + frappe.reload_doc("healthcare", "doctype", "healthcare_service_unit") frappe.reload_doc("healthcare", "doctype", "healthcare_service_unit_type") + company = frappe.get_value("Company", {"domain": "Healthcare"}, "name") - if not frappe.db.exists("Healthcare Service Unit", _('All Healthcare Service Units')): + if company: frappe.get_doc({ 'doctype': 'Healthcare Service Unit', 'healthcare_service_unit_name': _('All Healthcare Service Units'), - 'is_group': 1 + 'is_group': 1, + 'company': company }).insert(ignore_permissions=True) + diff --git a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py b/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py index 942f089bce..8a8c8064dd 100644 --- a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py +++ b/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py @@ -32,7 +32,7 @@ def execute(): 'user': user, 'default': 1 }) - _doc.pos_profile_name = user + ' - ' + _doc.company + _doc.flags.ignore_validate = True _doc.flags.ignore_mandatory = True _doc.save() \ No newline at end of file diff --git a/erpnext/patches/v9_0/set_pos_profile_name.py b/erpnext/patches/v9_0/set_pos_profile_name.py index 1958e2c777..a3a9735215 100644 --- a/erpnext/patches/v9_0/set_pos_profile_name.py +++ b/erpnext/patches/v9_0/set_pos_profile_name.py @@ -11,14 +11,14 @@ def execute(): for pos in frappe.get_all(doctype, filters={'disabled': 0}): doc = frappe.get_doc(doctype, pos.name) - if not doc.user or doc.pos_profile_name: continue + if not doc.user: continue try: - doc.pos_profile_name = doc.user + ' - ' + doc.company + pos_profile_name = doc.user + ' - ' + doc.company doc.flags.ignore_validate = True doc.flags.ignore_mandatory = True doc.save() - frappe.rename_doc(doctype, doc.name, doc.pos_profile_name, force=True) + frappe.rename_doc(doctype, doc.name, pos_profile_name, force=True) except frappe.LinkValidationError: frappe.db.set_value("POS Profile", doc.name, 'disabled', 1) diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js index 40b065ddff..faa445af94 100644 --- a/erpnext/projects/doctype/project/project.js +++ b/erpnext/projects/doctype/project/project.js @@ -120,28 +120,3 @@ frappe.ui.form.on("Project Task", { frm.trigger('tasks_refresh'); }, }); - -frappe.ui.form.on("Project", "validate", function (frm) { - if (frm.doc.collect_progress == 1) { - frappe.call({ - method: "erpnext.projects.doctype.project.project.times_check", - args: { - "from1": frm.doc.from, - "to": frm.doc.to, - "first_email": frm.doc.first_email, - "second_email": frm.doc.second_email, - "daily_time_to_send": frm.doc.daily_time_to_send, - "weekly_time_to_send": frm.doc.weekly_time_to_send - - }, - callback: function (r) { - frm.set_value("from", r.message.from1); - frm.set_value("to", r.message.to); - frm.set_value("first_email", r.message.first_email); - frm.set_value("second_email", r.message.second_email); - frm.set_value("daily_time_to_send", r.message.daily_time_to_send); - frm.set_value("weekly_time_to_send", r.message.weekly_time_to_send); - } - }); - } -}); \ No newline at end of file diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index ff698704f0..942593a948 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -427,23 +427,6 @@ def weekly(): project = frappe.db.sql("""SELECT `tabProject User`.user FROM `tabProject User` INNER JOIN `tabProject` ON `tabProject`.project_name = `tabProject User`.parent WHERE (`tabProject`.frequency = "Weekly") AND (`tabProject`.day_to_send = %s) AND (`tabProject`.weekly_time_to_send BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE)) AND `tabProject`.collect_progress = 1""", today) create_project_update(project) -@frappe.whitelist() -def times_check(from1, to, first_email, second_email, daily_time_to_send, weekly_time_to_send): - from1 = datetime.datetime.strptime(from1, "%H:%M:%S.%f") - from1 = from1.strftime("%H:00:00") - to = datetime.datetime.strptime(to, "%H:%M:%S.%f") - to = to.strftime("%H:00:00") - first_email = datetime.datetime.strptime(first_email, "%H:%M:%S.%f") - first_email = first_email.strftime("%H:00:00") - second_email = datetime.datetime.strptime(second_email, "%H:%M:%S.%f") - second_email = second_email.strftime("%H:00:00") - daily_time_to_send = datetime.datetime.strptime(daily_time_to_send, "%H:%M:%S.%f") - daily_time_to_send = daily_time_to_send.strftime("%H:00:00") - weekly_time_to_send = datetime.datetime.strptime(weekly_time_to_send, "%H:%M:%S.%f") - weekly_time_to_send = weekly_time_to_send.strftime("%H:00:00") - return {"from1": from1, "to": to, "first_email": first_email, "second_email": second_email,"daily_time_to_send": daily_time_to_send, "weekly_time_to_send": weekly_time_to_send} - - #Call this function in order to generate the Project Update for a specific project def create_project_update(project): data = [] diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js index b8f324a85f..c1a9c448b4 100644 --- a/erpnext/projects/doctype/task/task.js +++ b/erpnext/projects/doctype/task/task.js @@ -80,15 +80,15 @@ frappe.ui.form.on("Task", { } }, - is_group: function(frm) { + is_group: function (frm) { frappe.call({ - method:"erpnext.projects.doctype.task.task.check_if_child_exists", + method: "erpnext.projects.doctype.task.task.check_if_child_exists", args: { name: frm.doc.name }, - callback: function(r){ - if(r.message){ - frappe.msgprint(__('Cannot convert it to non-group. Child Tasks exist.')); + callback: function (r) { + if (r.message.length > 0) { + frappe.msgprint(__(`Cannot convert it to non-group. The following child Tasks exist: ${r.message.join(", ")}.`)); frm.reload_doc(); } } diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 3dc52d4ebe..649d73a63f 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -2,12 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils import getdate, date_diff, add_days, cstr +import json + +import frappe from frappe import _, throw +from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate from frappe.utils.nestedset import NestedSet + class CircularReferenceError(frappe.ValidationError): pass class Task(NestedSet): @@ -157,8 +160,10 @@ class Task(NestedSet): @frappe.whitelist() def check_if_child_exists(name): - return frappe.db.sql("""select name from `tabTask` - where parent_task = %s""", name) + child_tasks = frappe.get_all("Task", filters={"parent_task": name}) + child_tasks = [get_link_to_form("Task", task.name) for task in child_tasks] + return child_tasks + def get_project(doctype, txt, searchfield, start, page_len, filters): from erpnext.controllers.queries import get_match_cond @@ -237,4 +242,4 @@ def add_multiple_tasks(data, parent): new_task.insert() def on_doctype_update(): - frappe.db.add_index("Task", ["lft", "rgt"]) \ No newline at end of file + frappe.db.add_index("Task", ["lft", "rgt"]) diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json index e5198dea63..0be147bfb1 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.json +++ b/erpnext/projects/doctype/timesheet/timesheet.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -444,39 +445,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "start_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "User", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1032,7 +1000,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-28 14:44:32.912004", + "modified": "2018-11-15 07:58:42.629845", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet", diff --git a/erpnext/public/css/erpnext.css b/erpnext/public/css/erpnext.css index 460efbfe9f..c55e422151 100644 --- a/erpnext/public/css/erpnext.css +++ b/erpnext/public/css/erpnext.css @@ -346,6 +346,11 @@ body[data-route="pos"] .btn-more { body[data-route="pos"] .collapse-btn { cursor: pointer; } +@media (max-width: 767px) { + body[data-route="pos"] .page-actions { + max-width: 110px; + } +} .price-info { position: absolute; left: 0; diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index 08f8d43e50..32081550e6 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -26,8 +26,8 @@ $(document).bind('toolbar_setup', function() { $('
  • '+__('User Forum')+'
  • ').insertBefore($help_menu); - $('
  • '+__('Chat')+'
  • ').insertBefore($help_menu); + $('').insertBefore($help_menu); $('
  • '+__('Report an Issue')+'
  • ').insertBefore($help_menu); diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index a33b87f619..035c58d6d2 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -33,7 +33,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ item.margin_rate_or_amount = 0; item.rate_with_margin = 0; } - item.base_rate_with_margin = item.rate_with_margin * flt(this.frm.doc.conversion_rate); + item.base_rate_with_margin = item.rate_with_margin * flt(frm.doc.conversion_rate); cur_frm.cscript.set_gross_profit(item); cur_frm.cscript.calculate_taxes_and_totals(); @@ -185,6 +185,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, + is_return: function() { + if(!this.frm.doc.is_return && this.frm.doc.return_against) { + this.frm.set_value('return_against', ''); + } + }, + setup_quality_inspection: function() { if(!in_list(["Delivery Note", "Sales Invoice", "Purchase Receipt", "Purchase Invoice"], this.frm.doc.doctype)) { return; diff --git a/erpnext/public/js/projects/timer.js b/erpnext/public/js/projects/timer.js index 8b1d1b158b..26be997d48 100644 --- a/erpnext/public/js/projects/timer.js +++ b/erpnext/public/js/projects/timer.js @@ -44,8 +44,8 @@ erpnext.timesheet.timer = function(frm, row, timestamp=0) { }; erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) { - var $btn_start = $(".playpause .btn-start"); - var $btn_complete = $(".playpause .btn-complete"); + var $btn_start = dialog.$wrapper.find(".playpause .btn-start"); + var $btn_complete = dialog.$wrapper.find(".playpause .btn-complete"); var interval = null; var currentIncrement = timestamp; var initialised = row ? true : false; diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js old mode 100644 new mode 100755 index 3c14cb449b..adb7c6dd68 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -103,12 +103,32 @@ $.extend(erpnext, { $.extend(erpnext.utils, { set_party_dashboard_indicators: function(frm) { if(frm.doc.__onload && frm.doc.__onload.dashboard_info) { - var info = frm.doc.__onload.dashboard_info; - frm.dashboard.add_indicator(__('Annual Billing: {0}', - [format_currency(info.billing_this_year, info.currency)]), 'blue'); - frm.dashboard.add_indicator(__('Total Unpaid: {0}', - [format_currency(info.total_unpaid, info.currency)]), - info.total_unpaid ? 'orange' : 'green'); + var company_wise_info = frm.doc.__onload.dashboard_info; + if(company_wise_info.length > 1) { + frm.dashboard.stats_area.removeClass('hidden'); + frm.dashboard.stats_area_row.addClass('flex'); + frm.dashboard.stats_area_row.css('flex-wrap', 'wrap'); + company_wise_info.forEach(function(info) { + frm.dashboard.stats_area_row.append( + '
    '+ + '
    '+info.company+'
    '+ + ''+ + ''+ + '
    ' + ); + }); + } + else if (company_wise_info.length === 1) { + frm.dashboard.stats_area.removeClass('hidden'); + frm.dashboard.stats_area_row.append( + '
    Annual Billing: ' + +format_currency(company_wise_info[0].billing_this_year, company_wise_info[0].currency)+'
    ' + + '
    Total Unpaid: ' + +format_currency(company_wise_info[0].total_unpaid, company_wise_info[0].currency)+'
    ' + ); + } } }, diff --git a/erpnext/public/js/utils/item_quick_entry.js b/erpnext/public/js/utils/item_quick_entry.js index b12e3b8633..62b82ac012 100644 --- a/erpnext/public/js/utils/item_quick_entry.js +++ b/erpnext/public/js/utils/item_quick_entry.js @@ -320,7 +320,7 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({ ["attribute_value", "like", e.target.value + "%"] ], fields: ["attribute_value"], - parent: "Item" + parent: "Item Attribute" }, callback: function(r) { if (r.message) { diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index d282f5c3fd..7813cc0fd6 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -11,14 +11,18 @@ from erpnext.accounts.utils import get_fiscal_year from frappe.utils import today def setup(company=None, patch=True): + setup_company_independent_fixtures() + if not patch: + update_address_template() + make_fixtures(company) + +# TODO: for all countries +def setup_company_independent_fixtures(): make_custom_fields() add_permissions() add_custom_roles_for_reports() frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test) add_print_formats() - if not patch: - update_address_template() - make_fixtures(company) def update_address_template(): with open(os.path.join(os.path.dirname(__file__), 'address_template.html'), 'r') as f: @@ -350,12 +354,17 @@ def set_tax_withholding_category(company): def set_tds_account(docs, company): abbr = frappe.get_value("Company", company, "abbr") - docs.extend([ - { - "doctype": "Account", "account_name": "TDS Payable", "account_type": "Tax", - "parent_account": "Duties and Taxes - {0}".format(abbr), "company": company - } - ]) + parent_account = frappe.db.get_value("Account", filters = {"account_name": "Duties and Taxes", "company": company}) + if parent_account: + docs.extend([ + { + "doctype": "Account", + "account_name": "TDS Payable", + "account_type": "Tax", + "parent_account": parent_account, + "company": company + } + ]) def get_tds_details(accounts, fiscal_year): # bootstrap default tax withholding sections diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index c708de037f..6f7bfb3feb 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -206,7 +206,7 @@ cur_frm.cscript['Declare Order Lost'] = function(){ } -frappe.ui.form.on("Quotation Item", "items_on_form_rendered", function(frm, cdt, cdn) { +frappe.ui.form.on("Quotation Item", "items_on_form_rendered", "packed_items_on_form_rendered", function(frm, cdt, cdn) { // enable tax_amount field if Actual }) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 5f435ced74..9a35aedb72 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -32,7 +32,6 @@ class SalesOrder(SellingController): def validate(self): super(SalesOrder, self).validate() - self.validate_order_type() self.validate_delivery_date() self.validate_proj_cust() @@ -342,9 +341,11 @@ class SalesOrder(SellingController): delivered_qty += item.delivered_qty tot_qty += item.qty - - self.db_set("per_delivered", flt(delivered_qty/tot_qty) * 100, - update_modified=False) + + if tot_qty != 0: + self.db_set("per_delivered", flt(delivered_qty/tot_qty) * 100, + update_modified=False) + def set_indicator(self): """Set indicator for portal""" diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index daec5b5a21..56d91518d8 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -125,6 +125,8 @@ def search_serial_or_batch_or_barcode_number(search_value): if batch_no_data: return batch_no_data + return {} + def get_conditions(item_code, serial_no, batch_no, barcode): if serial_no or batch_no or barcode: return frappe.db.escape(item_code), "i.name = %(item_code)s" diff --git a/erpnext/selling/page/sales_analytics/README.md b/erpnext/selling/page/sales_analytics/README.md deleted file mode 100644 index 11994c26b9..0000000000 --- a/erpnext/selling/page/sales_analytics/README.md +++ /dev/null @@ -1 +0,0 @@ -Trends of sales by Item, Item Group, Customer etc. \ No newline at end of file diff --git a/erpnext/selling/page/sales_analytics/__init__.py b/erpnext/selling/page/sales_analytics/__init__.py deleted file mode 100644 index baffc48825..0000000000 --- a/erpnext/selling/page/sales_analytics/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/selling/page/sales_analytics/sales_analytics.js b/erpnext/selling/page/sales_analytics/sales_analytics.js deleted file mode 100644 index f5caf1d591..0000000000 --- a/erpnext/selling/page/sales_analytics/sales_analytics.js +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -frappe.pages['sales-analytics'].on_page_load = function(wrapper) { - frappe.ui.make_app_page({ - parent: wrapper, - title: __('Sales Analytics'), - single_column: true - }); - new erpnext.SalesAnalytics(wrapper); - - - frappe.breadcrumbs.add("Selling") - -}; - -erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({ - init: function(wrapper) { - this._super({ - title: __("Sales Analytics"), - parent: $(wrapper).find('.layout-main'), - page: wrapper.page, - doctypes: ["Item", "Item Group", "Customer", "Customer Group", "Company", "Territory", - "Fiscal Year", "Sales Invoice", "Sales Invoice Item", - "Sales Order", "Sales Order Item[Sales Analytics]", - "Delivery Note", "Delivery Note Item[Sales Analytics]"], - tree_grid: { show: true } - }); - - this.tree_grids = { - "Customer Group": { - label: __("Customer Group / Customer"), - show: true, - item_key: "customer", - parent_field: "parent_customer_group", - formatter: function(item) { - return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name; - } - }, - "Customer": { - label: __("Customer"), - show: false, - item_key: "customer", - formatter: function(item) { - return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name; - } - }, - "Item Group": { - label: __("Item"), - show: true, - parent_field: "parent_item_group", - item_key: "item_code", - formatter: function(item) { - return item.name; - } - }, - "Item": { - label: __("Item"), - show: false, - item_key: "item_code", - formatter: function(item) { - return item.name; - } - }, - "Territory": { - label: __("Territory / Customer"), - show: true, - item_key: "customer", - parent_field: "parent_territory", - formatter: function(item) { - return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name; - } - } - } - }, - setup_columns: function() { - this.tree_grid = this.tree_grids[this.tree_type]; - - var std_columns = [ - {id: "name", name: this.tree_grid.label, field: "name", width: 300}, - {id: "total", name: "Total", field: "total", plot: false, - formatter: this.currency_formatter} - ]; - - this.make_date_range_columns(); - this.columns = std_columns.concat(this.columns); - }, - filters: [ - {fieldtype:"Select", fieldname: "tree_type", label: __("Tree Type"), options:["Customer Group", "Customer", - "Item Group", "Item", "Territory"], - filter: function(val, item, opts, me) { - return me.apply_zero_filter(val, item, opts, me); - }}, - {fieldtype:"Select", fieldname: "based_on", label: __("Based On"), options:["Sales Invoice", - "Sales Order", "Delivery Note"]}, - {fieldtype:"Select", fieldname: "value_or_qty", label: __("Value or Qty"), - options:[{label: __("Value"), value: "Value"}, {label: __("Quantity"), value: "Quantity"}]}, - {fieldtype:"Date", fieldname: "from_date", label: __("From Date")}, - {fieldtype:"Label", fieldname: "to", label: __("To")}, - {fieldtype:"Date", fieldname: "to_date", label: __("To Date")}, - {fieldtype:"Select", fieldname: "company", label: __("Company"), link:"Company", - default_value: __("Select Company...")}, - {fieldtype:"Select", label: __("Range"), fieldname: "range", - options:[{label: __("Daily"), value: "Daily"}, {label: __("Weekly"), value: "Weekly"}, - {label: __("Monthly"), value: "Monthly"}, {label: __("Quarterly"), value: "Quarterly"}, - {label: __("Yearly"), value: "Yearly"}]} - ], - setup_filters: function() { - var me = this; - this._super(); - - this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on", "company"]); - - this.show_zero_check(); - }, - init_filter_values: function() { - this._super(); - this.filter_inputs.range.val('Monthly'); - }, - prepare_data: function() { - var me = this; - if (!this.tl) { - // add 'Not Set' Customer & Item - // (Customer / Item are not mandatory!!) - frappe.report_dump.data["Customer"].push({ - name: "Not Set", - parent_customer_group: "All Customer Groups", - parent_territory: "All Territories", - id: "Not Set", - }); - - frappe.report_dump.data["Item"].push({ - name: "Not Set", - parent_item_group: "All Item Groups", - id: "Not Set", - }); - } - - if (!this.tl || !this.tl[this.based_on]) { - this.make_transaction_list(this.based_on, this.based_on + " Item"); - } - - if(!this.data || me.item_type != me.tree_type) { - if(me.tree_type=='Customer') { - var items = frappe.report_dump.data["Customer"]; - } if(me.tree_type=='Customer Group') { - var items = this.prepare_tree("Customer", "Customer Group"); - } else if(me.tree_type=="Item Group") { - var items = this.prepare_tree("Item", "Item Group"); - } else if(me.tree_type=="Item") { - var items = frappe.report_dump.data["Item"]; - } else if(me.tree_type=="Territory") { - var items = this.prepare_tree("Customer", "Territory"); - } - - me.item_type = me.tree_type - me.parent_map = {}; - me.item_by_name = {}; - me.data = []; - - $.each(items, function(i, v) { - var d = copy_dict(v); - - me.data.push(d); - me.item_by_name[d.name] = d; - if(d[me.tree_grid.parent_field]) { - me.parent_map[d.name] = d[me.tree_grid.parent_field]; - } - me.reset_item_values(d); - }); - - this.set_indent(); - - } else { - // otherwise, only reset values - $.each(this.data, function(i, d) { - me.reset_item_values(d); - }); - } - - this.prepare_balances(); - if(me.tree_grid.show) { - this.set_totals(false); - this.update_groups(); - } else { - this.set_totals(true); - } - - }, - prepare_balances: function() { - var me = this; - var from_date = frappe.datetime.str_to_obj(this.from_date); - var to_date = frappe.datetime.str_to_obj(this.to_date); - var is_val = this.value_or_qty == 'Value'; - - $.each(this.tl[this.based_on], function(i, tl) { - if (me.is_default('company') ? true : tl.company === me.company) { - var posting_date = frappe.datetime.str_to_obj(tl.posting_date); - if (posting_date >= from_date && posting_date <= to_date) { - var item = me.item_by_name[tl[me.tree_grid.item_key]] || - me.item_by_name['Not Set']; - if(item){ - item[me.column_map[tl.posting_date].field] += (is_val ? tl.base_net_amount : tl.qty); - } - } - } - }); - }, - update_groups: function() { - var me = this; - - $.each(this.data, function(i, item) { - var parent = me.parent_map[item.name]; - while(parent) { - var parent_group = me.item_by_name[parent]; - - $.each(me.columns, function(c, col) { - if (col.formatter == me.currency_formatter) { - parent_group[col.field] = - flt(parent_group[col.field]) - + flt(item[col.field]); - } - }); - parent = me.parent_map[parent]; - } - }); - }, - set_totals: function(sort) { - var me = this; - var checked = false; - $.each(this.data, function(i, d) { - d.total = 0.0; - $.each(me.columns, function(i, col) { - if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total") - d.total += d[col.field]; - if(d.checked) checked = true; - }) - }); - - if(sort)this.data = this.data.sort(function(a, b) { return a.total < b.total; }); - - if(!this.checked) { - this.data[0].checked = true; - } - } -}); diff --git a/erpnext/selling/page/sales_analytics/sales_analytics.json b/erpnext/selling/page/sales_analytics/sales_analytics.json deleted file mode 100644 index 4a7761ebaf..0000000000 --- a/erpnext/selling/page/sales_analytics/sales_analytics.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "creation": "2012-09-21 20:15:12.000000", - "docstatus": 0, - "doctype": "Page", - "icon": "fa fa-bar-chart", - "idx": 1, - "modified": "2013-07-11 14:43:59.000000", - "modified_by": "Administrator", - "module": "Selling", - "name": "sales-analytics", - "owner": "Administrator", - "page_name": "sales-analytics", - "roles": [ - { - "role": "Analytics" - }, - { - "role": "Sales Manager" - }, - { - "role": "Maintenance Manager" - } - ], - "standard": "Yes", - "title": "Sales Analytics" -} \ No newline at end of file diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.json b/erpnext/selling/report/address_and_contacts/address_and_contacts.json index da38babbdc..876c39c0cf 100644 --- a/erpnext/selling/report/address_and_contacts/address_and_contacts.json +++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.json @@ -6,8 +6,7 @@ "docstatus": 0, "doctype": "Report", "idx": 0, - "is_standard": "Yes", - "letter_head": "Test", + "is_standard": "Yes", "modified": "2018-06-01 09:39:39.604944", "modified_by": "Administrator", "module": "Selling", @@ -30,4 +29,4 @@ "role": "Accounts User" } ] -} \ No newline at end of file +} diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.js b/erpnext/selling/report/sales_analytics/sales_analytics.js index 7c9e3ec35a..0df425d1cd 100644 --- a/erpnext/selling/report/sales_analytics/sales_analytics.js +++ b/erpnext/selling/report/sales_analytics/sales_analytics.js @@ -67,11 +67,8 @@ frappe.query_reports["Sales Analytics"] = { reqd: 1 } ], - "formatter": function(value, row, column, data) { - if(!value){ - value = 0 - } - return value; + after_datatable_render: function(datatable_obj) { + $(datatable_obj.wrapper).find(".dt-row-0").find('input[type=checkbox]').click(); }, get_datatable_options(options) { return Object.assign(options, { @@ -79,11 +76,11 @@ frappe.query_reports["Sales Analytics"] = { events: { onCheckRow: function(data) { row_name = data[2].content; - row_values = data.slice(5).map(function (column) { + length = data.length + row_values = data.slice(4,length-1).map(function (column) { return column.content; }) - - entry = { + entry = { 'name':row_name, 'values':row_values } @@ -109,15 +106,15 @@ frappe.query_reports["Sales Analytics"] = { labels: raw_data.labels, datasets: new_datasets } - + setTimeout(() => { frappe.query_report.chart.update(new_data) - },200) - - + }, 500) + + setTimeout(() => { frappe.query_report.chart.draw(true); - }, 800) + }, 1000) frappe.query_report.raw_chart_data = new_data; }, diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.py b/erpnext/selling/report/sales_analytics/sales_analytics.py index ef9e66656a..9cc6c404a6 100644 --- a/erpnext/selling/report/sales_analytics/sales_analytics.py +++ b/erpnext/selling/report/sales_analytics/sales_analytics.py @@ -166,7 +166,7 @@ class Analytics(object): for entity, period_data in iteritems(self.entity_periodic_data): row = { "entity": entity, - "entity_name": self.entity_names.get(entity) + "entity_name": self.entity_names.get(entity) } total = 0 for dummy, end_date in self.periodic_daterange: @@ -177,7 +177,7 @@ class Analytics(object): row["total"] = total self.data.append(row) - + def get_rows_by_group(self): self.get_periodic_data() out = [] @@ -185,7 +185,7 @@ class Analytics(object): for d in reversed(self.group_entries): row = { "entity": d.name, - "indent": self.depth_map.get(d.name) + "indent": self.depth_map.get(d.name) } total = 0 for dummy, end_date in self.periodic_daterange: @@ -212,11 +212,11 @@ class Analytics(object): def get_period(self, posting_date): if self.filters.range == 'Weekly': - period = "Week " + str(posting_date.isocalendar()[1]) + period = "Week " + str(posting_date.isocalendar()[1]) + " " + str(posting_date.year) elif self.filters.range == 'Monthly': - period = self.months[posting_date.month - 1] + period = str(self.months[posting_date.month - 1]) + " " + str(posting_date.year) elif self.filters.range == 'Quarterly': - period = "Quarter " + str(((posting_date.month-1)//3)+1) + period = "Quarter " + str(((posting_date.month-1)//3)+1) +" " + str(posting_date.year) else: year = get_fiscal_year(posting_date, company=self.filters.company) period = str(year[2]) @@ -275,12 +275,12 @@ class Analytics(object): self.parent_child_map = frappe._dict(frappe.db.sql(""" select name, supplier_group from `tabSupplier`""")) def get_chart_data(self): - labels = [d.get("label") for d in self.columns[3:]] + length = len(self.columns) + labels = [d.get("label") for d in self.columns[2:length-1]] self.chart = { "data": { 'labels': labels, - 'datasets':[ - ] + 'datasets':[] }, "type": "line" } \ No newline at end of file diff --git a/erpnext/selling/report/sales_analytics/test_analytics.py b/erpnext/selling/report/sales_analytics/test_analytics.py index c9a00fad15..5d68b06b6d 100644 --- a/erpnext/selling/report/sales_analytics/test_analytics.py +++ b/erpnext/selling/report/sales_analytics/test_analytics.py @@ -8,19 +8,23 @@ from erpnext.selling.report.sales_analytics.sales_analytics import execute from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order class TestAnalytics(unittest.TestCase): + def test_sales_analytics(self): + frappe.db.sql("delete from `tabSales Order` where company='_Test Company 2'") - def tearDown(self): - frappe.db.sql(""" DELETE FROM `tabSales Order` """) + create_sales_orders() - def test_by_entity(self): - create_sales_order() + self.compare_result_for_customer() + self.compare_result_for_customer_group() + self.compare_result_for_customer_based_on_quantity() + + def compare_result_for_customer(self): filters = { 'doc_type': 'Sales Order', 'range': 'Monthly', 'to_date': '2018-03-31', 'tree_type': 'Customer', - 'company': '_Test Company', + 'company': '_Test Company 2', 'from_date': '2017-04-01', 'value_quantity': 'Value' } @@ -31,153 +35,97 @@ class TestAnalytics(unittest.TestCase): { "entity": "_Test Customer 1", "entity_name": "_Test Customer 1", - "apr": 0.0, - "may": 0.0, - "jun": 0.0, - "jul": 0.0, - "aug": 0.0, - "sep": 0.0, - "oct": 0.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 2000.0, - "mar": 0.0, + "apr_2017": 0.0, + "may_2017": 0.0, + "jun_2017": 0.0, + "jul_2017": 0.0, + "aug_2017": 0.0, + "oct_2017": 0.0, + "sep_2017": 0.0, + "nov_2017": 0.0, + "dec_2017": 0.0, + "jan_2018": 0.0, + "feb_2018": 2000.0, + "mar_2018": 0.0, "total":2000.0 }, - { - "entity": "_Test Customer 3", - "entity_name": "_Test Customer 3", - "apr": 0.0, - "may": 0.0, - "jun": 2000.0, - "jul": 1000.0, - "aug": 0.0, - "sep": 0.0, - "oct": 0.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 0.0, - "mar": 0.0, - "total": 3000.0 - }, { "entity": "_Test Customer 2", "entity_name": "_Test Customer 2", - "apr": 0.0, - "may": 0.0, - "jun": 0.0, - "jul": 0.0, - "aug": 0.0, - "sep": 1500.0, - "oct": 1000.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 0.0, - "mar": 0.0, + "apr_2017": 0.0, + "may_2017": 0.0, + "jun_2017": 0.0, + "jul_2017": 0.0, + "aug_2017": 0.0, + "sep_2017": 1500.0, + "oct_2017": 1000.0, + "nov_2017": 0.0, + "dec_2017": 0.0, + "jan_2018": 0.0, + "feb_2018": 0.0, + "mar_2018": 0.0, "total":2500.0 + }, + { + "entity": "_Test Customer 3", + "entity_name": "_Test Customer 3", + "apr_2017": 0.0, + "may_2017": 0.0, + "jun_2017": 2000.0, + "jul_2017": 1000.0, + "aug_2017": 0.0, + "sep_2017": 0.0, + "oct_2017": 0.0, + "nov_2017": 0.0, + "dec_2017": 0.0, + "jan_2018": 0.0, + "feb_2018": 0.0, + "mar_2018": 0.0, + "total": 3000.0 } ] - self.assertEqual(expected_data, report[1]) - - def test_by_group(self): - create_sales_order() + result = sorted(report[1], key=lambda k: k['entity']) + self.assertEqual(expected_data, result) + def compare_result_for_customer_group(self): filters = { 'doc_type': 'Sales Order', 'range': 'Monthly', 'to_date': '2018-03-31', 'tree_type': 'Customer Group', - 'company': '_Test Company', + 'company': '_Test Company 2', 'from_date': '2017-04-01', 'value_quantity': 'Value' } report = execute(filters) - expected_data = [ - { - "entity": "All Customer Groups", - "indent": 0, - "apr": 0.0, - "may": 0.0, - "jun": 2000.0, - "jul": 1000.0, - "aug": 0.0, - "sep": 1500.0, - "oct": 1000.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 2000.0, - "mar": 0.0, - "total":7500.0 - }, - { - "entity": "Individual", - "indent": 1, - "apr": 0.0, - "may": 0.0, - "jun": 0.0, - "jul": 0.0, - "aug": 0.0, - "sep": 0.0, - "oct": 0.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 0.0, - "mar": 0.0, - "total": 0.0 - }, - { - "entity": "_Test Customer Group", - "indent": 1, - "apr": 0.0, - "may": 0.0, - "jun": 0.0, - "jul": 0.0, - "aug": 0.0, - "sep": 0.0, - "oct": 0.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 0.0, - "mar": 0.0, - "total":0.0 - }, - { - "entity": "_Test Customer Group 1", - "indent": 1, - "apr": 0.0, - "may": 0.0, - "jun": 0.0, - "jul": 0.0, - "aug": 0.0, - "sep": 0.0, - "oct": 0.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 0.0, - "mar": 0.0, - "total":0.0 - } - ] - self.assertEqual(expected_data, report[1]) - - def test_by_quantity(self): - create_sales_order() + expected_first_row = { + "entity": "All Customer Groups", + "indent": 0, + "apr_2017": 0.0, + "may_2017": 0.0, + "jun_2017": 2000.0, + "jul_2017": 1000.0, + "aug_2017": 0.0, + "sep_2017": 1500.0, + "oct_2017": 1000.0, + "nov_2017": 0.0, + "dec_2017": 0.0, + "jan_2018": 0.0, + "feb_2018": 2000.0, + "mar_2018": 0.0, + "total":7500.0 + } + self.assertEqual(expected_first_row, report[1][0]) + def compare_result_for_customer_based_on_quantity(self): filters = { 'doc_type': 'Sales Order', 'range': 'Monthly', 'to_date': '2018-03-31', 'tree_type': 'Customer', - 'company': '_Test Company', + 'company': '_Test Company 2', 'from_date': '2017-04-01', 'value_quantity': 'Quantity' } @@ -188,63 +136,93 @@ class TestAnalytics(unittest.TestCase): { "entity": "_Test Customer 1", "entity_name": "_Test Customer 1", - "apr": 0.0, - "may": 0.0, - "jun": 0.0, - "jul": 0.0, - "aug": 0.0, - "sep": 0.0, - "oct": 0.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 20.0, - "mar": 0.0, + "apr_2017": 0.0, + "may_2017": 0.0, + "jun_2017": 0.0, + "jul_2017": 0.0, + "aug_2017": 0.0, + "sep_2017": 0.0, + "oct_2017": 0.0, + "nov_2017": 0.0, + "dec_2017": 0.0, + "jan_2018": 0.0, + "feb_2018": 20.0, + "mar_2018": 0.0, "total":20.0 }, - { - "entity": "_Test Customer 3", - "entity_name": "_Test Customer 3", - "apr": 0.0, - "may": 0.0, - "jun": 20.0, - "jul": 10.0, - "aug": 0.0, - "sep": 0.0, - "oct": 0.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 0.0, - "mar": 0.0, - "total": 30.0 - }, { "entity": "_Test Customer 2", "entity_name": "_Test Customer 2", - "apr": 0.0, - "may": 0.0, - "jun": 0.0, - "jul": 0.0, - "aug": 0.0, - "sep": 15.0, - "oct": 10.0, - "nov": 0.0, - "dec": 0.0, - "jan": 0.0, - "feb": 0.0, - "mar": 0.0, + "apr_2017": 0.0, + "may_2017": 0.0, + "jun_2017": 0.0, + "jul_2017": 0.0, + "aug_2017": 0.0, + "sep_2017": 15.0, + "oct_2017": 10.0, + "nov_2017": 0.0, + "dec_2017": 0.0, + "jan_2018": 0.0, + "feb_2018": 0.0, + "mar_2018": 0.0, "total":25.0 + }, + { + "entity": "_Test Customer 3", + "entity_name": "_Test Customer 3", + "apr_2017": 0.0, + "may_2017": 0.0, + "jun_2017": 20.0, + "jul_2017": 10.0, + "aug_2017": 0.0, + "sep_2017": 0.0, + "oct_2017": 0.0, + "nov_2017": 0.0, + "dec_2017": 0.0, + "jan_2018": 0.0, + "feb_2018": 0.0, + "mar_2018": 0.0, + "total": 30.0 } ] - self.assertEqual(expected_data, report[1]) + result = sorted(report[1], key=lambda k: k['entity']) + self.assertEqual(expected_data, result) -def create_sales_order(): +def create_sales_orders(): frappe.set_user("Administrator") - make_sales_order(qty=10, customer = "_Test Customer 1", transaction_date='2018-02-10') - make_sales_order(qty=10, customer = "_Test Customer 1", transaction_date='2018-02-15') - make_sales_order(qty=15, customer = "_Test Customer 2", transaction_date='2017-09-23') - make_sales_order(qty=10, customer = "_Test Customer 2", transaction_date='2017-10-10') - make_sales_order(qty=20, customer = "_Test Customer 3", transaction_date='2017-06-15') - make_sales_order(qty=10, customer = "_Test Customer 3", transaction_date='2017-07-10') + make_sales_order(company="_Test Company 2", qty=10, + customer = "_Test Customer 1", + transaction_date = '2018-02-10', + warehouse = 'Finished Goods - _TC2', + currency = 'EUR') + + make_sales_order(company="_Test Company 2", + qty=10, customer = "_Test Customer 1", + transaction_date = '2018-02-15', + warehouse = 'Finished Goods - _TC2', + currency = 'EUR') + + make_sales_order(company = "_Test Company 2", + qty=10, customer = "_Test Customer 2", + transaction_date = '2017-10-10', + warehouse='Finished Goods - _TC2', + currency = 'EUR') + + make_sales_order(company="_Test Company 2", + qty=15, customer = "_Test Customer 2", + transaction_date='2017-09-23', + warehouse='Finished Goods - _TC2', + currency = 'EUR') + + make_sales_order(company="_Test Company 2", + qty=20, customer = "_Test Customer 3", + transaction_date='2017-06-15', + warehouse='Finished Goods - _TC2', + currency = 'EUR') + + make_sales_order(company="_Test Company 2", + qty=10, customer = "_Test Customer 3", + transaction_date='2017-07-10', + warehouse='Finished Goods - _TC2', + currency = 'EUR') diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 0c58fb2679..09ff5a83fd 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -97,7 +97,7 @@ class Company(NestedSet): if not frappe.db.get_value("Department", {"company": self.name}): from erpnext.setup.setup_wizard.operations.install_fixtures import install_post_company_fixtures - install_post_company_fixtures(self.name) + install_post_company_fixtures(frappe._dict({'company_name': self.name})) if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": self.name}): self.create_default_cost_center() @@ -363,7 +363,8 @@ def replace_abbr(company, old, new): for d in doc: _rename_record(d) - for dt in ["Warehouse", "Account", "Cost Center"]: + for dt in ["Warehouse", "Account", "Cost Center", "Department", "Location", + "Sales Taxes and Charges Template", "Purchase Taxes and Charges Template"]: _rename_records(dt) frappe.db.commit() diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index f7e2906da7..c732c4b479 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -6,6 +6,9 @@ from __future__ import unicode_literals import frappe, os, json from frappe import _ +from frappe.desk.page.setup_wizard.setup_wizard import make_records +from frappe.utils import cstr, getdate +from erpnext.accounts.doctype.account.account import RootNotEditable default_lead_sources = ["Existing Customer", "Reference", "Advertisement", "Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing", @@ -26,34 +29,6 @@ def install(country=None): { 'doctype': 'Domain', 'domain': 'Agriculture'}, { 'doctype': 'Domain', 'domain': 'Non Profit'}, - # Setup Progress - {'doctype': "Setup Progress", "actions": [ - {"action_name": "Add Company", "action_doctype": "Company", "min_doc_count": 1, "is_completed": 1, - "domains": '[]' }, - {"action_name": "Set Sales Target", "action_doctype": "Company", "min_doc_count": 99, - "action_document": frappe.defaults.get_defaults().get("company") or '', - "action_field": "monthly_sales_target", "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Customers", "action_doctype": "Customer", "min_doc_count": 1, "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Suppliers", "action_doctype": "Supplier", "min_doc_count": 1, "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Products", "action_doctype": "Item", "min_doc_count": 1, "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Programs", "action_doctype": "Program", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Instructors", "action_doctype": "Instructor", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Courses", "action_doctype": "Course", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Rooms", "action_doctype": "Room", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Users", "action_doctype": "User", "min_doc_count": 4, "is_completed": 0, - "domains": '[]' }, - {"action_name": "Add Letterhead", "action_doctype": "Letter Head", "min_doc_count": 1, "is_completed": 0, - "domains": '[]' } - ]}, - # address template {'doctype':"Address Template", "country": country}, @@ -124,8 +99,10 @@ def install(country=None): {'doctype': 'Designation', 'designation_name': _('Designer')}, {'doctype': 'Designation', 'designation_name': _('Researcher')}, - # territory + # territory: with two default territories, one for home country and one named Rest of the World {'doctype': 'Territory', 'territory_name': _('All Territories'), 'is_group': 1, 'name': _('All Territories'), 'parent_territory': ''}, + {'doctype': 'Territory', 'territory_name': country.replace("'", ""), 'is_group': 0, 'parent_territory': _('All Territories')}, + {'doctype': 'Territory', 'territory_name': _("Rest Of The World"), 'is_group': 0, 'parent_territory': _('All Territories')}, # customer group {'doctype': 'Customer Group', 'customer_group_name': _('All Customer Groups'), 'is_group': 1, 'name': _('All Customer Groups'), 'parent_customer_group': ''}, @@ -231,7 +208,22 @@ def install(country=None): # Share Management {"doctype": "Share Type", "title": _("Equity")}, - {"doctype": "Share Type", "title": _("Preference")} + {"doctype": "Share Type", "title": _("Preference")}, + + # Market Segments + {"doctype": "Market Segment", "market_segment": _("Lower Income")}, + {"doctype": "Market Segment", "market_segment": _("Middle Income")}, + {"doctype": "Market Segment", "market_segment": _("Upper Income")}, + + # Sales Stages + {"doctype": "Sales Stage", "stage_name": _("Prospecting")}, + {"doctype": "Sales Stage", "stage_name": _("Qualification")}, + {"doctype": "Sales Stage", "stage_name": _("Needs Analysis")}, + {"doctype": "Sales Stage", "stage_name": _("Value Proposition")}, + {"doctype": "Sales Stage", "stage_name": _("Identifying Decision Makers")}, + {"doctype": "Sales Stage", "stage_name": _("Perception Analysis")}, + {"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")}, + {"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")} ] from erpnext.setup.setup_wizard.data.industry_type import get_industry_types @@ -260,7 +252,17 @@ def install(country=None): from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records make_default_records() - make_fixture_records(records) + make_records(records, True) + + set_more_defaults() + + # path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country)) + # if os.path.exists(path.encode("utf-8")): + # frappe.get_attr("erpnext.regional.{0}.setup.setup_company_independent_fixtures".format(frappe.scrub(country)))() + + +def set_more_defaults(): + # Do more setup stuff that can be done here with no dependencies # set default customer group and territory selling_settings = frappe.get_doc("Selling Settings") @@ -269,6 +271,33 @@ def install(country=None): add_uom_data() + # set no copy fields of an item doctype to item variant settings + doc = frappe.get_doc('Item Variant Settings') + doc.set_default_fields() + doc.save() + + selling_settings = frappe.get_doc("Selling Settings") + selling_settings.cust_master_name = "Customer Name" + selling_settings.so_required = "No" + selling_settings.dn_required = "No" + selling_settings.allow_multiple_items = 1 + selling_settings.sales_update_frequency = "Each Transaction" + selling_settings.save() + + buying_settings = frappe.get_doc("Buying Settings") + buying_settings.supp_master_name = "Supplier Name" + buying_settings.po_required = "No" + buying_settings.pr_required = "No" + buying_settings.maintain_same_rate = 1 + buying_settings.allow_multiple_items = 1 + buying_settings.save() + + hr_settings = frappe.get_doc("HR Settings") + hr_settings.emp_created_by = "Naming Series" + hr_settings.leave_approval_notification_template = _("Leave Approval Notification") + hr_settings.leave_status_notification_template = _("Leave Status Notification") + hr_settings.save() + def add_uom_data(): # add UOMs uoms = json.loads(open(frappe.get_app_path("erpnext", "setup", "setup_wizard", "data", "uom_data.json")).read()) @@ -306,7 +335,7 @@ def add_market_segments(): {"doctype": "Market Segment", "market_segment": _("Upper Income")} ] - make_fixture_records(records) + make_records(records) def add_sale_stages(): # Sale Stages @@ -320,46 +349,143 @@ def add_sale_stages(): {"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")}, {"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")} ] - make_fixture_records(records) -def make_fixture_records(records): - from frappe.modules import scrub - for r in records: - doc = frappe.new_doc(r.get("doctype")) - doc.update(r) + make_records(records) - # ignore mandatory for root - parent_link_field = ("parent_" + scrub(doc.doctype)) - if doc.meta.get_field(parent_link_field) and not doc.get(parent_link_field): - doc.flags.ignore_mandatory = True +def install_company(args): + records = [ + # Fiscal Year + { "doctype": "Fiscal Year", 'year': get_fy_details(args.fy_start_date, args.fy_end_date), 'year_start_date': args.fy_start_date, 'year_end_date': args.fy_end_date }, - try: - doc.insert(ignore_permissions=True) - except frappe.DuplicateEntryError as e: - # pass DuplicateEntryError and continue - if e.args and e.args[0]==doc.doctype and e.args[1]==doc.name: - # make sure DuplicateEntryError is for the exact same doc and not a related doc - pass - else: - raise + # Company + { + "doctype":"Company", + 'company_name': args.company_name, + 'enable_perpetual_inventory': 1, + 'abbr': args.company_abbr, + 'default_currency': args.currency, + 'country': args.country, + 'create_chart_of_accounts_based_on': 'Standard Template', + 'chart_of_accounts': args.chart_of_accounts, + 'domain': args.domain + } + ] -def install_post_company_fixtures(company=None): + make_records(records, True) + + +def install_post_company_fixtures(args=None): records = [ # Department {'doctype': 'Department', 'department_name': _('All Departments'), 'is_group': 1, 'parent_department': ''}, - {'doctype': 'Department', 'department_name': _('Accounts'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Marketing'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Sales'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Purchase'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Operations'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Production'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Dispatch'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Customer Service'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Human Resources'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Management'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Quality Management'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Research & Development'), 'parent_department': _('All Departments'), 'company': company}, - {'doctype': 'Department', 'department_name': _('Legal'), 'parent_department': _('All Departments'), 'company': company}, + {'doctype': 'Department', 'department_name': _('Accounts'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Marketing'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Sales'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Purchase'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Operations'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Production'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Dispatch'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Customer Service'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Human Resources'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Management'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Quality Management'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Research & Development'), 'parent_department': _('All Departments'), 'company': args.company_name}, + {'doctype': 'Department', 'department_name': _('Legal'), 'parent_department': _('All Departments'), 'company': args.company_name}, ] - make_fixture_records(records) \ No newline at end of file + make_records(records) + + +def install_defaults(args=None): + records = [ + # Price Lists + { "doctype": "Price List", "price_list_name": _("Standard Buying"), "enabled": 1, "buying": 1, "selling": 0, "currency": args.currency }, + { "doctype": "Price List", "price_list_name": _("Standard Selling"), "enabled": 1, "buying": 0, "selling": 1, "currency": args.currency }, + ] + + make_records(records) + + # enable default currency + frappe.db.set_value("Currency", args.get("currency"), "enabled", 1) + + global_defaults = frappe.get_doc("Global Defaults", "Global Defaults") + current_fiscal_year = frappe.get_all("Fiscal Year")[0] + + global_defaults.update({ + 'current_fiscal_year': current_fiscal_year.name, + 'default_currency': args.get('currency'), + 'default_company':args.get('company_name') , + "country": args.get("country"), + }) + + global_defaults.save() + + system_settings = frappe.get_doc("System Settings") + system_settings.email_footer_address = args.get("company_name") + system_settings.save() + + domain_settings = frappe.get_single('Domain Settings') + domain_settings.set_active_domains(args.get('domains')) + + stock_settings = frappe.get_doc("Stock Settings") + stock_settings.item_naming_by = "Item Code" + stock_settings.valuation_method = "FIFO" + stock_settings.default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}) + stock_settings.stock_uom = _("Nos") + stock_settings.auto_indent = 1 + stock_settings.auto_insert_price_list_rate_if_missing = 1 + stock_settings.automatically_set_serial_nos_based_on_fifo = 1 + stock_settings.set_qty_in_transactions_based_on_serial_no_input = 1 + stock_settings.save() + + if args.bank_account: + company_name = args.company_name + bank_account_group = frappe.db.get_value("Account", + {"account_type": "Bank", "is_group": 1, "root_type": "Asset", + "company": company_name}) + if bank_account_group: + bank_account = frappe.get_doc({ + "doctype": "Account", + 'account_name': args.bank_account, + 'parent_account': bank_account_group, + 'is_group':0, + 'company': company_name, + "account_type": "Bank", + }) + try: + doc = bank_account.insert() + + frappe.db.set_value("Company", args.company_name, "default_bank_account", bank_account.name, update_modified=False) + + return doc + except RootNotEditable: + frappe.throw(_("Bank account cannot be named as {0}").format(args.bank_account)) + except frappe.DuplicateEntryError: + # bank account same as a CoA entry + pass + + # Now, with fixtures out of the way, onto concrete stuff + records = [ + + # Shopping cart: needs price lists + { + "doctype": "Shopping Cart Settings", + "enabled": 1, + 'company': args.company_name, + # uh oh + 'price_list': frappe.db.get_value("Price List", {"selling": 1}), + 'default_customer_group': _("Individual"), + 'quotation_series': "QTN-", + }, + ] + + make_records(records, True) + + +def get_fy_details(fy_start_date, fy_end_date): + start_year = getdate(fy_start_date).year + if start_year == getdate(fy_end_date).year: + fy = cstr(start_year) + else: + fy = cstr(start_year) + '-' + cstr(start_year + 1) + return fy diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index af28e4f586..e062e280b9 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -5,7 +5,8 @@ from __future__ import unicode_literals import frappe from frappe import _ -from .operations import install_fixtures, taxes_setup, defaults_setup, company_setup, sample_data + +from .operations import install_fixtures as fixtures, company_setup, taxes_setup, sample_data def get_setup_stages(args=None): if frappe.db.sql("select name from tabCompany"): @@ -61,16 +62,10 @@ def get_setup_stages(args=None): 'fail_msg': _("Failed to setup post company fixtures") }, { - 'fn': stage_three, + 'fn': setup_defaults, 'args': args, - 'fail_msg': _("Failed to set defaults") - } - ] - }, - { - 'status': _('Making website'), - 'fail_msg': _('Failed to create website'), - 'tasks': [ + 'fail_msg': _("Failed to setup defaults") + }, { 'fn': stage_four, 'args': args, @@ -93,38 +88,20 @@ def get_setup_stages(args=None): return stages -def setup_complete(args=None): - stage_fixtures(args) - setup_company(args) - setup_taxes(args) - setup_post_company_fixtures(args) - stage_three(args) - stage_four(args) - fin(args) - def stage_fixtures(args): - install_fixtures.install(args.get("country")) - install_fixtures.add_market_segments() - install_fixtures.add_sale_stages() + fixtures.install(args.get('country')) def setup_company(args): - defaults_setup.create_price_lists(args) - company_setup.create_fiscal_year_and_company(args) - company_setup.enable_shopping_cart(args) - company_setup.create_bank_account(args) + fixtures.install_company(args) def setup_taxes(args): taxes_setup.create_sales_tax(args) def setup_post_company_fixtures(args): - install_fixtures.install_post_company_fixtures(args.get("company_name")) + fixtures.install_post_company_fixtures(args) -def stage_three(args): - defaults_setup.create_employee_for_self(args) - defaults_setup.set_default_settings(args) - defaults_setup.create_territories() - defaults_setup.create_feed_and_todo() - defaults_setup.set_no_copy_fields_in_variant_settings() +def setup_defaults(args): + fixtures.install_defaults(frappe._dict(args)) def stage_four(args): company_setup.create_website(args) @@ -149,3 +126,14 @@ def make_sample_data(domains): def login_as_first_user(args): if args.get("email") and hasattr(frappe.local, "login_manager"): frappe.local.login_manager.login_as(args.get("email")) + + +# Only for programmatical use +def setup_complete(args=None): + stage_fixtures(args) + setup_company(args) + setup_taxes(args) + setup_post_company_fixtures(args) + setup_defaults(args) + stage_four(args) + fin(args) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 9a154846e5..f8a34972b7 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -223,6 +223,10 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( erpnext.setup_serial_no(); }, + packed_items_on_form_rendered: function(doc, grid_row) { + erpnext.setup_serial_no(); + }, + close_delivery_note: function(doc){ this.update_status("Closed") }, diff --git a/erpnext/stock/doctype/delivery_note/delivery_note_list.js b/erpnext/stock/doctype/delivery_note/delivery_note_list.js index 9631264f20..6a50c5a9f7 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note_list.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note_list.js @@ -1,5 +1,5 @@ frappe.listview_settings['Delivery Note'] = { - add_fields: ["grand_total", "is_return", "per_billed", "status"], + add_fields: ["grand_total", "is_return", "per_billed", "status", "currency"], get_indicator: function (doc) { if (cint(doc.is_return) == 1) { return [__("Return"), "darkgrey", "is_return,=,Yes"]; diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index b3141e87fa..388b64325d 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -513,7 +513,7 @@ $.extend(erpnext.item, { fields: ["attribute_value"], limit_start: 0, limit_page_length: 500, - parent: "Item", + parent: "Item Attribute", order_by: "idx" } }).then((r) => { diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 17cf044074..566b6386fe 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -32,6 +32,10 @@ class StockExistsForTemplate(frappe.ValidationError): pass +class InvalidBarcode(frappe.ValidationError): + pass + + class Item(WebsiteGenerator): website = frappe._dict( page_title_field="item_name", @@ -502,19 +506,19 @@ class Item(WebsiteGenerator): from stdnum import ean if len(self.barcodes) > 0: for item_barcode in self.barcodes: - options = frappe.get_meta("Item Barcode").get_options("barcode_type").split() + options = frappe.get_meta("Item Barcode").get_options("barcode_type").split('\n') if item_barcode.barcode: duplicate = frappe.db.sql( """select parent from `tabItem Barcode` where barcode = %s and parent != %s""", (item_barcode.barcode, self.name)) if duplicate: frappe.throw(_("Barcode {0} already used in Item {1}").format( - item_barcode.barcode, duplicate[0][0])) + item_barcode.barcode, duplicate[0][0]), frappe.DuplicateEntryError) item_barcode.barcode_type = "" if item_barcode.barcode_type not in options else item_barcode.barcode_type - if item_barcode.barcode_type: + if item_barcode.barcode_type and item_barcode.barcode_type.upper() in ('EAN', 'UPC-A', 'EAN-13', 'EAN-8'): if not ean.is_valid(item_barcode.barcode): frappe.throw(_("Barcode {0} is not a valid {1} code").format( - item_barcode.barcode, item_barcode.barcode_type)) + item_barcode.barcode, item_barcode.barcode_type), InvalidBarcode) def validate_warehouse_for_reorder(self): '''Validate Reorder level table for duplicate and conditional mandatory''' diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 7ef4f8cecc..24292f7b4f 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -8,7 +8,7 @@ import frappe from frappe.test_runner import make_test_objects from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError, InvalidItemAttributeValueError, get_variant) -from erpnext.stock.doctype.item.item import StockExistsForTemplate +from erpnext.stock.doctype.item.item import StockExistsForTemplate, InvalidBarcode from erpnext.stock.doctype.item.item import get_uom_conv_factor from frappe.model.rename_doc import rename_doc from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry @@ -305,6 +305,65 @@ class TestItem(unittest.TestCase): item_doc.has_variants = 1 self.assertRaises(StockExistsForTemplate, item_doc.save) + def test_add_item_barcode(self): + # Clean up + frappe.db.sql("""delete from `tabItem Barcode`""") + item_code = "Test Item Barcode" + if frappe.db.exists("Item", item_code): + frappe.delete_doc("Item", item_code) + + # Create new item and add barcodes + barcode_properties_list = [ + { + "barcode": "0012345678905", + "barcode_type": "EAN" + }, + { + "barcode": "012345678905", + "barcode_type": "UAN" + }, + { + "barcode": "ARBITRARY_TEXT", + } + ] + create_item(item_code) + for barcode_properties in barcode_properties_list: + item_doc = frappe.get_doc('Item', item_code) + new_barcode = item_doc.append('barcodes') + new_barcode.update(barcode_properties) + item_doc.save() + + # Check values saved correctly + barcodes = frappe.get_list( + 'Item Barcode', + fields=['barcode', 'barcode_type'], + filters={'parent': item_code}) + + for barcode_properties in barcode_properties_list: + barcode_to_find = barcode_properties['barcode'] + matching_barcodes = [ + x for x in barcodes + if x['barcode'] == barcode_to_find + ] + self.assertEqual(len(matching_barcodes), 1) + details = matching_barcodes[0] + + for key, value in iteritems(barcode_properties): + self.assertEqual(value, details.get(key)) + + # Add barcode again - should cause DuplicateEntryError + item_doc = frappe.get_doc('Item', item_code) + new_barcode = item_doc.append('barcodes') + new_barcode.update(barcode_properties_list[0]) + self.assertRaises(frappe.DuplicateEntryError, item_doc.save) + + # Add invalid barcode - should cause InvalidBarcode + item_doc = frappe.get_doc('Item', item_code) + new_barcode = item_doc.append('barcodes') + new_barcode.barcode = '9999999999999' + new_barcode.barcode_type = 'EAN' + self.assertRaises(InvalidBarcode, item_doc.save) + def set_item_variant_settings(fields): doc = frappe.get_doc('Item Variant Settings') doc.set('fields', fields) diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json index dbb9b59254..18e2910126 100644 --- a/erpnext/stock/doctype/item/test_records.json +++ b/erpnext/stock/doctype/item/test_records.json @@ -57,6 +57,7 @@ "stock_uom": "_Test UOM", "show_in_website": 1, "website_warehouse": "_Test Warehouse - _TC", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -78,6 +79,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test Item Home Desktop 100", "valuation_rate": 100, + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -107,6 +109,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test Item Home Desktop 200", "stock_uom": "_Test UOM 1", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -128,6 +131,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test Product Bundle Item", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -149,6 +153,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test FG Item", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -170,6 +175,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test Non Stock Item", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -191,6 +197,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test Serialized Item", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -213,6 +220,7 @@ "item_name": "_Test Serialized Item With Series", "serial_no_series": "ABCD.#####", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -234,6 +242,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test Item Home Desktop Manufactured", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -255,6 +264,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test FG Item 2", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC", @@ -276,6 +286,7 @@ "item_group": "_Test Item Group Desktops", "item_name": "_Test Variant Item", "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", "has_variants": 1, "item_defaults": [{ "company": "_Test Company", @@ -312,6 +323,7 @@ "item_group": "_Test Item Group", "item_name": "_Test Item Warehouse Group Wise Reorder", "apply_warehouse_wise_reorder_level": 1, + "gst_hsn_code": "999800", "item_defaults": [{ "company": "_Test Company", "default_warehouse": "_Test Warehouse Group-C1 - _TC", diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 5fd7a6a2c8..2b0ed38e93 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -102,7 +102,7 @@ frappe.ui.form.on('Material Request', { update_status: function(frm, stop_status) { frappe.call({ - method: 'erpnext.stock.material_request.material_request.update_status', + method: 'erpnext.stock.doctype.material_request.material_request.update_status', args: { name: frm.doc.name, status: stop_status }, callback(r) { if (!r.exc) { diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index fc53794093..cf72527205 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -53,8 +53,9 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip pi.qty = flt(qty) pi.description = description if not pi.warehouse: - pi.warehouse = (main_item_row.warehouse - if (doc.get('is_pos') or not item.default_warehouse) else item.default_warehouse) + pi.warehouse = (main_item_row.warehouse if ((doc.get('is_pos') + or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse) + if not pi.batch_no: pi.batch_no = cstr(main_item_row.get("batch_no")) if not pi.target_warehouse: diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 36f6405ae4..e0b738202c 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -61,7 +61,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): if filters.get("from"): from frappe.desk.reportview import get_match_cond mcond = get_match_cond(filters["from"]) - cond = "" + cond, qi_condition = "", "and (quality_inspection is null or quality_inspection = '')" if filters.get('from') in ['Purchase Invoice Item', 'Purchase Receipt Item']: cond = """and item_code in (select name from `tabItem` where @@ -72,9 +72,13 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): elif filters.get('from') == 'Stock Entry Detail': cond = """and s_warehouse is null""" + if filters.get('from') in ['Supplier Quotation Item']: + qi_condition = "" + return frappe.db.sql(""" select item_code from `tab{doc}` where parent=%(parent)s and docstatus < 2 and item_code like %(txt)s - and (quality_inspection is null or quality_inspection = '') - {cond} {mcond} order by item_code limit {start}, {page_len}""".format(doc=filters.get('from'), - parent=filters.get('parent'), cond=cond, mcond=mcond, start=start, page_len = page_len), + {qi_condition} {cond} {mcond} + order by item_code limit {start}, {page_len}""".format(doc=filters.get('from'), + parent=filters.get('parent'), cond = cond, mcond = mcond, start = start, + page_len = page_len, qi_condition = qi_condition), {'parent': filters.get('parent'), 'txt': "%%%s%%" % txt}) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index a26992a5ae..ccd5f363a4 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -199,12 +199,15 @@ frappe.ui.form.on('Stock Entry', { }, validate_purpose_consumption: function(frm) { - frappe.model.get_value('Manufacturing Settings', {'name': 'Manufacturing Settings'}, 'material_consumption', function(d) { - if (d.material_consumption==0 && frm.doc.purpose=="Material Consumption for Manufacture") { + frappe.call({ + method: "erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings.is_material_consumption_enabled", + }).then(r => { + if (cint(r.message) == 0 + && frm.doc.purpose=="Material Consumption for Manufacture") { frm.set_value("purpose", 'Manufacture'); frappe.throw(__('Material Consumption is not set in Manufacturing Settings.')); } - }) + }); }, company: function(frm) { diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 3b20b1cf64..6b5bb2825f 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -181,7 +181,7 @@ class StockReconciliation(StockController): frappe.throw(_("Valuation Rate required for Item in row {0}").format(row.idx)) if ((previous_sle and row.qty == previous_sle.get("qty_after_transaction") - and row.valuation_rate == previous_sle.get("valuation_rate")) + and (row.valuation_rate == previous_sle.get("valuation_rate") or row.qty == 0)) or (not previous_sle and not row.qty)): continue diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index d90db56e2c..01ee9db1ca 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -594,22 +594,21 @@ def get_pos_profile(company, pos_profile=None, user=None): if not user: user = frappe.session['user'] - pos_profile = frappe.db.sql("""select pf.* - from - `tabPOS Profile` pf, `tabPOS Profile User` pfu - where - pfu.parent = pf.name and pfu.user = %s and pf.company = %s - and pf.disabled = 0 and pfu.default=1""", (user, company), as_dict=1) - - if not pos_profile: - pos_profile = frappe.db.sql("""select pf.* - from - `tabPOS Profile` pf left join `tabPOS Profile User` pfu - on + pos_profile = frappe.db.sql("""SELECT pf.* + FROM + `tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu + ON pf.name = pfu.parent - where - ifnull(pfu.user, '') = '' and pf.company = %s - and pf.disabled = 0""", (company), as_dict=1) + WHERE + ( + (pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1) + OR (pfu.user = %(user)s AND pfu.default=1) + OR (ifnull(pfu.user, '') = '' AND pf.company = %(company)s) + ) AND pf.disabled = 0 + """, { + 'user': user, + 'company': company + }, as_dict=1) return pos_profile and pos_profile[0] or None diff --git a/erpnext/stock/page/stock_analytics/README.md b/erpnext/stock/page/stock_analytics/README.md deleted file mode 100644 index 86c3644322..0000000000 --- a/erpnext/stock/page/stock_analytics/README.md +++ /dev/null @@ -1 +0,0 @@ -Trends of Items quantities and values. \ No newline at end of file diff --git a/erpnext/stock/page/stock_analytics/__init__.py b/erpnext/stock/page/stock_analytics/__init__.py deleted file mode 100644 index baffc48825..0000000000 --- a/erpnext/stock/page/stock_analytics/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/stock/page/stock_analytics/stock_analytics.js b/erpnext/stock/page/stock_analytics/stock_analytics.js deleted file mode 100644 index 6deeb7a1f4..0000000000 --- a/erpnext/stock/page/stock_analytics/stock_analytics.js +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -frappe.pages['stock-analytics'].on_page_load = function(wrapper) { - frappe.ui.make_app_page({ - parent: wrapper, - title: __('Stock Analytics'), - single_column: true - }); - - frappe.require(["assets/erpnext/js/stock_grid_report.js", - "assets/erpnext/js/stock_analytics.js"], function() { - new erpnext.StockAnalytics(wrapper); - frappe.breadcrumbs.add("Stock") - }); -}; diff --git a/erpnext/stock/page/stock_analytics/stock_analytics.json b/erpnext/stock/page/stock_analytics/stock_analytics.json deleted file mode 100644 index 90e9f2e56b..0000000000 --- a/erpnext/stock/page/stock_analytics/stock_analytics.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "creation": "2012-09-21 20:15:14.000000", - "docstatus": 0, - "doctype": "Page", - "icon": "fa fa-bar-chart", - "idx": 1, - "modified": "2013-07-11 14:44:10.000000", - "modified_by": "Administrator", - "module": "Stock", - "name": "stock-analytics", - "owner": "Administrator", - "page_name": "stock-analytics", - "roles": [ - { - "role": "Analytics" - }, - { - "role": "Material Manager" - } - ], - "standard": "Yes", - "title": "Stock Analytics" -} \ No newline at end of file diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.js b/erpnext/stock/report/stock_analytics/stock_analytics.js index 6010ea9ee2..6b384e2861 100644 --- a/erpnext/stock/report/stock_analytics/stock_analytics.js +++ b/erpnext/stock/report/stock_analytics/stock_analytics.js @@ -71,16 +71,8 @@ frappe.query_reports["Stock Analytics"] = { reqd: 1 } ], - "formatter": function(value, row, column, data) { - if(!value && (column.fieldname == 'brand' || column.fieldname == 'uom')){ - value = "" - } - - if(Number(value)){ - value = value.toFixed(2) - } - - return value; + after_datatable_render: function(datatable_obj) { + $(datatable_obj.wrapper).find(".dt-row-0").find('input[type=checkbox]').click(); }, get_datatable_options(options) { return Object.assign(options, { @@ -88,10 +80,9 @@ frappe.query_reports["Stock Analytics"] = { events: { onCheckRow: function(data) { row_name = data[2].content; - row_values = data.slice(6).map(function (column) { + row_values = data.slice(7).map(function (column) { return column.content; }) - entry = { 'name':row_name, 'values':row_values @@ -118,19 +109,19 @@ frappe.query_reports["Stock Analytics"] = { labels: raw_data.labels, datasets: new_datasets } - + setTimeout(() => { frappe.query_report.chart.update(new_data) - },200) - - + },500) + + setTimeout(() => { frappe.query_report.chart.draw(true); - }, 800) + }, 1000) frappe.query_report.raw_chart_data = new_data; }, } - }) - }, + }); + } } diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.py b/erpnext/stock/report/stock_analytics/stock_analytics.py index 5a8a672b63..54eefdfaaa 100644 --- a/erpnext/stock/report/stock_analytics/stock_analytics.py +++ b/erpnext/stock/report/stock_analytics/stock_analytics.py @@ -99,11 +99,11 @@ def get_period(posting_date, filters): months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] if filters.range == 'Weekly': - period = "Week " + str(posting_date.isocalendar()[1]) + period = "Week " + str(posting_date.isocalendar()[1]) + " " + str(posting_date.year) elif filters.range == 'Monthly': - period = months[posting_date.month - 1] + period = str(months[posting_date.month - 1]) + " " + str(posting_date.year) elif filters.range == 'Quarterly': - period = "Quarter " + str(((posting_date.month-1)//3)+1) + period = "Quarter " + str(((posting_date.month-1)//3)+1) +" " + str(posting_date.year) else: year = get_fiscal_year(posting_date, company=filters.company) period = str(year[2]) @@ -167,13 +167,11 @@ def get_data(filters): return data def get_chart_data(columns): - labels = [d.get("label") for d in columns[4:]] + labels = [d.get("label") for d in columns[5:]] chart = { "data": { 'labels': labels, - 'datasets':[ - { "values": ['0' for d in columns[4:]] } - ] + 'datasets':[] } } chart["type"] = "line" diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js index 6589688d1a..babc6dc960 100644 --- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js +++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js @@ -7,7 +7,8 @@ frappe.query_reports["Stock Projected Qty"] = { "fieldname":"company", "label": __("Company"), "fieldtype": "Link", - "options": "Company" + "options": "Company", + "default": frappe.defaults.get_user_default("Company") }, { "fieldname":"warehouse", diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 928dd8854a..0ef2afa4a8 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -178,7 +178,11 @@ class update_entries_after(object): # rounding as per precision self.stock_value = flt(self.stock_value, self.precision) - stock_value_difference = self.stock_value - self.prev_stock_value + if self.prev_stock_value < 0 and self.stock_value >= 0 and sle.voucher_type != 'Stock Reconciliation': + stock_value_difference = sle.actual_qty * self.valuation_rate + else: + stock_value_difference = self.stock_value - self.prev_stock_value + self.prev_stock_value = self.stock_value # update current sle diff --git a/erpnext/templates/includes/fee/fee_row.html b/erpnext/templates/includes/fee/fee_row.html index ac2b1006ad..d5fd682236 100644 --- a/erpnext/templates/includes/fee/fee_row.html +++ b/erpnext/templates/includes/fee/fee_row.html @@ -5,13 +5,13 @@ {{ doc.program }}
    - {{ doc.get_formatted("total_amount") }} + {{ frappe.utils.fmt_money(doc.grand_total, currency=doc.currency) }}
    - {{ doc.get_formatted("paid_amount") }} + {{ frappe.utils.fmt_money(doc.paid_amount, currency=doc.currency) }}
    - {{ doc.get_formatted("outstanding_amount") }} + {{ frappe.utils.fmt_money(doc.outstanding_amount, currency=doc.currency) }}
    diff --git a/erpnext/templates/pages/product_search.py b/erpnext/templates/pages/product_search.py index d503490eb7..c34001bacf 100644 --- a/erpnext/templates/pages/product_search.py +++ b/erpnext/templates/pages/product_search.py @@ -26,7 +26,6 @@ def get_product_list(search=None, start=0, limit=12): left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse where (I.show_in_website = 1) and I.disabled = 0 - and (I.variant_of is null or I.variant_of='') and (I.end_of_life is null or I.end_of_life='0000-00-00' or I.end_of_life > %(today)s)""" # search term condition