diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js index 5162c29604..13d53d1f6a 100755 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.js +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js @@ -37,8 +37,8 @@ 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); }); diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index a089b4c91b..077c396c71 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -4,7 +4,7 @@ "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, @@ -52,6 +52,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "", "fieldname": "section_break_2", "fieldtype": "Section Break", "hidden": 0, @@ -76,38 +77,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": "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, - "unique": 1 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -142,6 +111,240 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "customer", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Customer", + "length": 0, + "no_copy": 0, + "oldfieldname": "customer_account", + "oldfieldtype": "Link", + "options": "Customer", + "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": "company", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Company", + "length": 0, + "no_copy": 0, + "oldfieldname": "company", + "oldfieldtype": "Link", + "options": "Company", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 1, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "company.country", + "fieldname": "country", + "fieldtype": "Read Only", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Country", + "length": 0, + "no_copy": 0, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "update_stock", + "fieldname": "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": "Warehouse", + "length": 0, + "no_copy": 0, + "oldfieldname": "warehouse", + "oldfieldtype": "Link", + "options": "Warehouse", + "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": "campaign", + "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": "Campaign", + "length": 0, + "no_copy": 0, + "options": "Campaign", + "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": "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, @@ -374,207 +577,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "column_break_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer", - "length": 0, - "no_copy": 0, - "oldfieldname": "customer_account", - "oldfieldtype": "Link", - "options": "Customer", - "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": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "oldfieldname": "company", - "oldfieldtype": "Link", - "options": "Company", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "company.country", - "fieldname": "country", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Country", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "update_stock", - "fieldname": "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": "Warehouse", - "length": 0, - "no_copy": 0, - "oldfieldname": "warehouse", - "oldfieldtype": "Link", - "options": "Warehouse", - "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": "campaign", - "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": "Campaign", - "length": 0, - "no_copy": 0, - "options": "Campaign", - "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, @@ -649,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, @@ -714,6 +718,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, + "label": "", "length": 0, "no_copy": 0, "permlevel": 0, @@ -736,6 +741,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "description": "Only show Items from these Item Groups", "fieldname": "item_groups", "fieldtype": "Table", "hidden": 0, @@ -800,6 +806,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "description": "Only show Customer of these Customer Groups", "fieldname": "customer_groups", "fieldtype": "Table", "hidden": 0, @@ -843,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, @@ -925,40 +933,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "select_print_heading", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Print Heading", - "length": 0, - "no_copy": 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, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -990,40 +964,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": "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, @@ -1061,110 +1001,11 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 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_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 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company_address_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company Address", - "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": "company_address", + "fieldname": "select_print_heading", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -1173,12 +1014,13 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Company Address Name", + "label": "Print Heading", "length": 0, "no_copy": 0, - "options": "Address", + "oldfieldname": "select_print_heading", + "oldfieldtype": "Select", + "options": "Print Heading", "permlevel": 0, - "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -1207,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, @@ -1389,6 +1231,40 @@ "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, @@ -1688,6 +1564,41 @@ "set_only_once": 0, "translatable": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Grand Total", + "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 } ], "has_web_view": 0, @@ -1701,7 +1612,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-12-03 14:16:08.589778", + "modified": "2018-12-13 13:36:22.045519", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", @@ -1749,11 +1660,11 @@ "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_views": 0 diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index 9e4006cf3c..e64ad28cda 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/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 94037c7d0a..68cc500004 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -375,7 +375,7 @@ class TestSalesInvoice(unittest.TestCase): si.insert() self.assertEqual(si.net_total, 4600) - + self.assertEqual(si.get("taxes")[0].tax_amount, 874.0) self.assertEqual(si.get("taxes")[0].total, 5474.0) @@ -405,12 +405,12 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(si.total, 975) self.assertEqual(si.net_total, 900) - + self.assertEqual(si.get("taxes")[0].tax_amount, 216.0) self.assertEqual(si.get("taxes")[0].total, 1116.0) self.assertEqual(si.grand_total, 1116.0) - + def test_inclusive_rate_validations(self): si = frappe.copy_doc(test_records[2]) for i, tax in enumerate(si.get("taxes")): @@ -552,7 +552,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(si.grand_total, 1215.90) self.assertEqual(si.rounding_adjustment, 0.01) self.assertEqual(si.base_rounding_adjustment, 0.50) - + def test_outstanding(self): w = self.make() @@ -923,7 +923,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertRaises(SerialNoWarehouseError, si.submit) def test_serial_numbers_against_delivery_note(self): - """ + """ check if the sales invoice item serial numbers and the delivery note items serial numbers are same """ @@ -1238,7 +1238,7 @@ class TestSalesInvoice(unittest.TestCase): def test_item_wise_tax_breakup_india(self): frappe.flags.country = "India" - + si = self.create_si_to_test_tax_breakup() itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(si) @@ -1256,12 +1256,12 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(itemised_tax, expected_itemised_tax) self.assertEqual(itemised_taxable_amount, expected_itemised_taxable_amount) - + frappe.flags.country = None def test_item_wise_tax_breakup_outside_india(self): frappe.flags.country = "United States" - + si = self.create_si_to_test_tax_breakup() itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(si) @@ -1287,7 +1287,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(itemised_tax, expected_itemised_tax) self.assertEqual(itemised_taxable_amount, expected_itemised_taxable_amount) - + frappe.flags.country = None def create_si_to_test_tax_breakup(self): @@ -1375,7 +1375,7 @@ class TestSalesInvoice(unittest.TestCase): shipping_rule = create_shipping_rule(shipping_rule_type = "Selling", shipping_rule_name = "Shipping Rule - Sales Invoice Test") si = frappe.copy_doc(test_records[2]) - + si.shipping_rule = shipping_rule.name si.insert() @@ -1392,14 +1392,14 @@ class TestSalesInvoice(unittest.TestCase): "cost_center": shipping_rule.cost_center, "tax_amount": shipping_amount, "description": shipping_rule.name - } + } si.append("taxes", shipping_charge) si.save() self.assertEqual(si.net_total, 1250) self.assertEqual(si.total_taxes_and_charges, 577.05) - self.assertEqual(si.grand_total, 1827.05) + self.assertEqual(si.grand_total, 1827.05) def test_create_invoice_without_terms(self): si = create_sales_invoice(do_not_save=1) @@ -1496,7 +1496,7 @@ class TestSalesInvoice(unittest.TestCase): for gle in gl_entries: self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) - + accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.save() @@ -1524,9 +1524,9 @@ def create_sales_invoice(**args): "warehouse": args.warehouse or "_Test Warehouse - _TC", "qty": args.qty or 1, "rate": args.rate or 100, - "income_account": "Sales - _TC", - "expense_account": "Cost of Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC", + "income_account": args.income_account or "Sales - _TC", + "expense_account": args.expense_account or "Cost of Goods Sold - _TC", + "cost_center": args.cost_center or "_Test Cost Center - _TC", "serial_no": args.serial_no }) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index b1bdce95c8..bbfee1112f 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -107,6 +107,11 @@ frappe.query_reports["Accounts Receivable"] = { "label": __("Show PDC in Print"), "fieldtype": "Check", }, + { + "fieldname":"based_on_payment_terms", + "label": __("Based On Payment Terms"), + "fieldtype": "Check", + }, { "fieldname":"tax_id", "label": __("Tax Id"), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 8e05a087af..121d5b0213 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe, erpnext from frappe import _, scrub -from frappe.utils import getdate, nowdate, flt, cint +from frappe.utils import getdate, nowdate, flt, cint, formatdate, cstr class ReceivablePayableReport(object): def __init__(self, filters=None): @@ -57,6 +57,21 @@ class ReceivablePayableReport(object): credit_or_debit_note = "Credit Note" if args.get("party_type") == "Customer" else "Debit Note" + if self.filters.based_on_payment_terms: + columns.append({ + "label": "Payment Term", + "fieldname": "payment_term", + "fieldtype": "Data", + "width": 120 + }) + columns.append({ + "label": "Invoice Grand Total", + "fieldname": "invoice_grand_total", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }) + for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"): columns.append({ "label": label, @@ -97,12 +112,6 @@ class ReceivablePayableReport(object): "options": "Currency", "width": 100 }, - { - "fieldname": "pdc/lc_date", - "label": _("PDC/LC Date"), - "fieldtype": "Date", - "width": 110 - }, { "fieldname": "pdc/lc_ref", "label": _("PDC/LC Ref"), @@ -113,14 +122,14 @@ class ReceivablePayableReport(object): "fieldname": "pdc/lc_amount", "label": _("PDC/LC Amount"), "fieldtype": "Currency", - "options": "Currency", + "options": "currency", "width": 130 }, { "fieldname": "remaining_balance", "label": _("Remaining Balance"), "fieldtype": "Currency", - "options": "Currency", + "options": "currency", "width": 130 }] @@ -151,108 +160,203 @@ class ReceivablePayableReport(object): def get_data(self, party_naming_by, args): from erpnext.accounts.utils import get_currency_precision - currency_precision = get_currency_precision() or 2 - dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit" + self.currency_precision = get_currency_precision() or 2 + self.dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit" future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type")) if not self.filters.get("company"): self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company') - company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency") + self.company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency") return_entries = self.get_return_entries(args.get("party_type")) data = [] - pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date) + self.pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date) gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type")) if gl_entries_data: voucher_nos = [d.voucher_no for d in gl_entries_data] or [] dn_details = get_dn_details(args.get("party_type"), voucher_nos) - voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details) + self.voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details) + + if self.filters.based_on_payment_terms: + self.payment_term_map = self.get_payment_term_detail(voucher_nos) for gle in gl_entries_data: - if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers): - outstanding_amount, credit_note_amount = self.get_outstanding_amount(gle, - self.filters.report_date, dr_or_cr, return_entries, currency_precision) - if abs(outstanding_amount) > 0.1/10**currency_precision: - row = [gle.posting_date, gle.party] + if self.is_receivable_or_payable(gle, self.dr_or_cr, future_vouchers): + outstanding_amount, credit_note_amount, payment_amount = self.get_outstanding_amount( + gle,self.filters.report_date, self.dr_or_cr, return_entries) - # customer / supplier name - if party_naming_by == "Naming Series": - row += [self.get_party_name(gle.party_type, gle.party)] + temp_outstanding_amt = outstanding_amount + temp_credit_note_amt = credit_note_amount - # get due date - due_date = voucher_details.get(gle.voucher_no, {}).get("due_date", "") - bill_date = voucher_details.get(gle.voucher_no, {}).get("bill_date", "") + if abs(outstanding_amount) > 0.1/10**self.currency_precision: + if self.filters.based_on_payment_terms and self.payment_term_map.get(gle.voucher_no): + for d in self.payment_term_map.get(gle.voucher_no): + # Allocate payment amount based on payment terms(FIFO order) + payment_amount, d.payment_amount = self.allocate_based_on_fifo(payment_amount, d.payment_term_amount) - row += [gle.voucher_type, gle.voucher_no, due_date] + term_outstanding_amount = d.payment_term_amount - d.payment_amount - # get supplier bill details - if args.get("party_type") == "Supplier": - row += [ - voucher_details.get(gle.voucher_no, {}).get("bill_no", ""), - voucher_details.get(gle.voucher_no, {}).get("bill_date", "") - ] + # Allocate credit note based on payment terms(FIFO order) + credit_note_amount, d.credit_note_amount = self.allocate_based_on_fifo(credit_note_amount, term_outstanding_amount) - # invoiced and paid amounts - invoiced_amount = gle.get(dr_or_cr) if (gle.get(dr_or_cr) > 0) else 0 - paid_amt = invoiced_amount - outstanding_amount - credit_note_amount - row += [invoiced_amount, paid_amt, credit_note_amount, outstanding_amount] + term_outstanding_amount -= d.credit_note_amount + + row_outstanding = term_outstanding_amount + # Allocate PDC based on payment terms(FIFO order) + d.pdc_details, d.pdc_amount = self.allocate_pdc_amount_in_fifo(gle, row_outstanding) + + if term_outstanding_amount > 0: + row = self.prepare_row(party_naming_by, args, gle, term_outstanding_amount, + d.credit_note_amount, d.due_date, d.payment_amount , d.payment_term_amount, + d.description, d.pdc_amount, d.pdc_details) + data.append(row) + + if credit_note_amount: + row = self.prepare_row_without_payment_terms(party_naming_by, args, gle, temp_outstanding_amt, + temp_credit_note_amt) + data.append(row) - # ageing data - if self.filters.ageing_based_on == "Due Date": - entry_date = due_date - elif self.filters.ageing_based_on == "Supplier Invoice Date": - entry_date = bill_date else: - entry_date = gle.posting_date - - row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2), - cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount) - - - # issue 6371-Ageing buckets should not have amounts if due date is not reached - if self.filters.ageing_based_on == "Due Date" \ - and getdate(due_date) > getdate(self.filters.report_date): - row[-1]=row[-2]=row[-3]=row[-4]=0 - - if self.filters.ageing_based_on == "Supplier Invoice Date" \ - and getdate(bill_date) > getdate(self.filters.report_date): - - row[-1]=row[-2]=row[-3]=row[-4]=0 - - if self.filters.get(scrub(args.get("party_type"))): - row.append(gle.account_currency) - else: - row.append(company_currency) - - pdc = pdc_details.get((gle.voucher_no, gle.party), {}) - - remaining_balance = outstanding_amount - flt(pdc.get("pdc_amount")) - row += [pdc.get("pdc_date"), pdc.get("pdc_ref"), - flt(pdc.get("pdc_amount")), remaining_balance] - - if args.get('party_type') == 'Customer': - # customer LPO - row += [voucher_details.get(gle.voucher_no, {}).get("po_no")] - - # Delivery Note - row += [voucher_details.get(gle.voucher_no, {}).get("delivery_note")] - - # customer territory / supplier group - if args.get("party_type") == "Customer": - 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)] - - row.append(gle.remarks) - data.append(row) - + row = self.prepare_row_without_payment_terms(party_naming_by, args, gle, outstanding_amount, + credit_note_amount) + data.append(row) return data + def allocate_pdc_amount_in_fifo(self, gle, row_outstanding): + pdc_list = self.pdc_details.get((gle.voucher_no, gle.party), []) + + pdc_details = [] + pdc_amount = 0 + for pdc in pdc_list: + if row_outstanding <= pdc.pdc_amount: + pdc_amount += row_outstanding + pdc.pdc_amount -= row_outstanding + if row_outstanding and pdc.pdc_ref and pdc.pdc_date: + pdc_details.append(cstr(pdc.pdc_ref) + "/" + formatdate(pdc.pdc_date)) + row_outstanding = 0 + + else: + pdc_amount = pdc.pdc_amount + if pdc.pdc_amount and pdc.pdc_ref and pdc.pdc_date: + pdc_details.append(cstr(pdc.pdc_ref) + "/" + formatdate(pdc.pdc_date)) + pdc.pdc_amount = 0 + row_outstanding -= pdc_amount + + return pdc_details, pdc_amount + + def prepare_row_without_payment_terms(self, party_naming_by, args, gle, outstanding_amount, credit_note_amount): + pdc_list = self.pdc_details.get((gle.voucher_no, gle.party), []) + pdc_amount = 0 + pdc_details = [] + for d in pdc_list: + pdc_amount += flt(d.pdc_amount) + if pdc_amount and d.pdc_ref and d.pdc_date: + pdc_details.append(cstr(d.pdc_ref) + "/" + formatdate(d.pdc_date)) + + row = self.prepare_row(party_naming_by, args, gle, outstanding_amount, + credit_note_amount, pdc_amount=pdc_amount, pdc_details=pdc_details) + + return row + + + def allocate_based_on_fifo(self, total_amount, row_amount): + allocated_amount = 0 + if row_amount <= total_amount: + allocated_amount = row_amount + total_amount -= row_amount + else: + allocated_amount = total_amount + total_amount = 0 + + return total_amount, allocated_amount + + def prepare_row(self, party_naming_by, args, gle, outstanding_amount, credit_note_amount, + due_date=None, paid_amt=None, payment_term_amount=None, payment_term=None, pdc_amount=None, pdc_details=None): + row = [gle.posting_date, gle.party] + + # customer / supplier name + if party_naming_by == "Naming Series": + row += [self.get_party_name(gle.party_type, gle.party)] + + # get due date + if not due_date: + due_date = self.voucher_details.get(gle.voucher_no, {}).get("due_date", "") + bill_date = self.voucher_details.get(gle.voucher_no, {}).get("bill_date", "") + + row += [gle.voucher_type, gle.voucher_no, due_date] + + # get supplier bill details + if args.get("party_type") == "Supplier": + row += [ + self.voucher_details.get(gle.voucher_no, {}).get("bill_no", ""), + self.voucher_details.get(gle.voucher_no, {}).get("bill_date", "") + ] + + # invoiced and paid amounts + invoiced_amount = gle.get(self.dr_or_cr) if (gle.get(self.dr_or_cr) > 0) else 0 + + if self.filters.based_on_payment_terms: + row+=[payment_term, invoiced_amount] + if payment_term_amount: + invoiced_amount = payment_term_amount + + if not payment_term_amount: + paid_amt = invoiced_amount - outstanding_amount - credit_note_amount + row += [invoiced_amount, paid_amt, credit_note_amount, outstanding_amount] + + # ageing data + if self.filters.ageing_based_on == "Due Date": + entry_date = due_date + elif self.filters.ageing_based_on == "Supplier Invoice Date": + entry_date = bill_date + else: + entry_date = gle.posting_date + + row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2), + cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount) + + + # issue 6371-Ageing buckets should not have amounts if due date is not reached + if self.filters.ageing_based_on == "Due Date" \ + and getdate(due_date) > getdate(self.filters.report_date): + row[-1]=row[-2]=row[-3]=row[-4]=0 + + if self.filters.ageing_based_on == "Supplier Invoice Date" \ + and getdate(bill_date) > getdate(self.filters.report_date): + + row[-1]=row[-2]=row[-3]=row[-4]=0 + + if self.filters.get(scrub(args.get("party_type"))): + row.append(gle.account_currency) + else: + row.append(self.company_currency) + + remaining_balance = outstanding_amount - flt(pdc_amount) + pdc_details = ", ".join(pdc_details) + row += [pdc_details, pdc_amount, remaining_balance] + + if args.get('party_type') == 'Customer': + # customer LPO + row += [self.voucher_details.get(gle.voucher_no, {}).get("po_no")] + + # Delivery Note + row += [self.voucher_details.get(gle.voucher_no, {}).get("delivery_note")] + + # customer territory / supplier group + if args.get("party_type") == "Customer": + row += [self.get_territory(gle.party), self.get_customer_group(gle.party), + self.voucher_details.get(gle.voucher_no, {}).get("sales_person")] + if args.get("party_type") == "Supplier": + row += [self.get_supplier_group(gle.party)] + + row.append(gle.remarks) + + return row + def get_entries_after(self, report_date, party_type): # returns a distinct list return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries(party_type, report_date, for_future=True)])) @@ -280,25 +384,25 @@ class ReceivablePayableReport(object): doctype = "Sales Invoice" if party_type=="Customer" else "Purchase Invoice" return [d.name for d in frappe.get_all(doctype, filters={"is_return": 1, "docstatus": 1})] - def get_outstanding_amount(self, gle, report_date, dr_or_cr, return_entries, currency_precision): + def get_outstanding_amount(self, gle, report_date, dr_or_cr, return_entries): payment_amount, credit_note_amount = 0.0, 0.0 reverse_dr_or_cr = "credit" if dr_or_cr=="debit" else "debit" for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no): if getdate(e.posting_date) <= report_date and e.name!=gle.name: - amount = flt(e.get(reverse_dr_or_cr), currency_precision) - flt(e.get(dr_or_cr), currency_precision) + amount = flt(e.get(reverse_dr_or_cr), self.currency_precision) - flt(e.get(dr_or_cr), self.currency_precision) if e.voucher_no not in return_entries: payment_amount += amount else: credit_note_amount += amount - outstanding_amount = (flt((flt(gle.get(dr_or_cr), currency_precision) - - flt(gle.get(reverse_dr_or_cr), currency_precision) - - payment_amount - credit_note_amount), currency_precision)) + outstanding_amount = (flt((flt(gle.get(dr_or_cr), self.currency_precision) + - flt(gle.get(reverse_dr_or_cr), self.currency_precision) + - payment_amount - credit_note_amount), self.currency_precision)) - credit_note_amount = flt(credit_note_amount, currency_precision) + credit_note_amount = flt(credit_note_amount, self.currency_precision) - return outstanding_amount, credit_note_amount + return outstanding_amount, credit_note_amount, payment_amount def get_party_name(self, party_type, party_name): return self.get_party_map(party_type).get(party_name, {}).get("customer_name" if party_type == "Customer" else "supplier_name") or "" @@ -383,7 +487,7 @@ class ReceivablePayableReport(object): conditions.append("""party in (select name from tabCustomer where exists(select name from `tabCustomer Group` where lft >= {0} and rgt <= {1} and name=tabCustomer.customer_group))""".format(lft, rgt)) - + if self.filters.get("territory"): lft, rgt = frappe.db.get_value("Territory", self.filters.get("territory"), ["lft", "rgt"]) @@ -415,7 +519,7 @@ class ReceivablePayableReport(object): conditions.append("""party in (select name from tabSupplier where supplier_group=%s)""") values.append(self.filters.get("supplier_group")) - + return " and ".join(conditions), values def get_gl_entries_for(self, party, party_type, against_voucher_type, against_voucher): @@ -432,6 +536,31 @@ class ReceivablePayableReport(object): .get(against_voucher_type, {})\ .get(against_voucher, []) + def get_payment_term_detail(self, voucher_nos): + payment_term_map = frappe._dict() + payment_terms_details = frappe.db.sql(""" select si.name, + party_account_currency, currency, si.conversion_rate, + ps.due_date, ps.payment_amount, ps.description + from `tabSales Invoice` si, `tabPayment Schedule` ps + where si.name = ps.parent and + si.docstatus = 1 and si.company = '%s' and + si.name in (%s) order by ps.due_date + """ % (frappe.db.escape(self.filters.company), ','.join(['%s'] *len(voucher_nos))), + (tuple(voucher_nos)), as_dict = 1) + + for d in payment_terms_details: + if self.filters.get("customer") and d.currency == d.party_account_currency: + payment_term_amount = d.payment_amount + else: + payment_term_amount = flt(flt(d.payment_amount) * flt(d.conversion_rate), self.currency_precision) + + payment_term_map.setdefault(d.name, []).append(frappe._dict({ + "due_date": d.due_date, + "payment_term_amount": payment_term_amount, + "description": d.description + })) + return payment_term_map + def get_chart_data(self, columns, data): ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+4] @@ -479,12 +608,11 @@ def get_ageing_data(first_range, second_range, third_range, age_as_on, entry_dat def get_pdc_details(party_type, report_date): pdc_details = frappe._dict() - - for pdc in frappe.db.sql(""" + pdc_via_pe = frappe.db.sql(""" select pref.reference_name as invoice_no, pent.party, pent.party_type, - max(pent.posting_date) as pdc_date, sum(ifnull(pref.allocated_amount,0)) as pdc_amount, - GROUP_CONCAT(pent.reference_no SEPARATOR ', ') as pdc_ref + pent.posting_date as pdc_date, ifnull(pref.allocated_amount,0) as pdc_amount, + pent.reference_no as pdc_ref from `tabPayment Entry` as pent inner join `tabPayment Entry Reference` as pref on @@ -492,19 +620,22 @@ def get_pdc_details(party_type, report_date): where pent.docstatus < 2 and pent.posting_date > %s and pent.party_type = %s - group by pent.party, pref.reference_name""", (report_date, party_type), as_dict=1): - pdc_details.setdefault((pdc.invoice_no, pdc.party), pdc) + """, (report_date, party_type), as_dict=1) + + for pdc in pdc_via_pe: + pdc_details.setdefault((pdc.invoice_no, pdc.party), []).append(pdc) + if scrub(party_type): amount_field = ("jea.debit_in_account_currency" if party_type == 'Supplier' else "jea.credit_in_account_currency") else: amount_field = "jea.debit + jea.credit" - for pdc in frappe.db.sql(""" + pdc_via_je = frappe.db.sql(""" select jea.reference_name as invoice_no, jea.party, jea.party_type, - max(je.posting_date) as pdc_date, sum(ifnull({0},0)) as pdc_amount, - GROUP_CONCAT(je.cheque_no SEPARATOR ', ') as pdc_ref + je.posting_date as pdc_date, ifnull({0},0) as pdc_amount, + je.cheque_no as pdc_ref from `tabJournal Entry` as je inner join `tabJournal Entry Account` as jea on @@ -512,16 +643,10 @@ def get_pdc_details(party_type, report_date): where je.docstatus < 2 and je.posting_date > %s and jea.party_type = %s - group by jea.party, jea.reference_name""".format(amount_field), (report_date, party_type), as_dict=1): - if (pdc.invoice_no, pdc.party) in pdc_details: - key = (pdc.invoice_no, pdc.party) - pdc_details[key]["pdc_amount"] += pdc.pdc_amount - if pdc.pdc_ref: - pdc_details[key]["pdc_ref"] += ", " + pdc.pdc_ref - if pdc.pdc_date: - pdc_details[key]["pdc_date"] = max(pdc_details[key]["pdc_date"], pdc.pdc_date) - else: - pdc_details.setdefault((pdc.invoice_no, pdc.party), pdc) + """.format(amount_field), (report_date, party_type), as_dict=1) + + for pdc in pdc_via_je: + pdc_details.setdefault((pdc.invoice_no, pdc.party), []).append(pdc) return pdc_details diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py new file mode 100644 index 0000000000..34e6c83e01 --- /dev/null +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -0,0 +1,84 @@ +import frappe +import frappe.defaults +import unittest +from frappe.utils import today, getdate, add_days +from erpnext.accounts.report.accounts_receivable.accounts_receivable import execute +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry + +class TestAccountsReceivable(unittest.TestCase): + def test_accounts_receivable(self): + frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company 2'") + frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 2'") + + filters = { + 'company': '_Test Company 2', + 'based_on_payment_terms': 1 + } + + name = make_sales_invoice() + report = execute(filters) + + expected_data = [[100,30], [100,50], [100,20]] + + self.assertEqual(expected_data[0], report[1][0][6:8]) + self.assertEqual(expected_data[1], report[1][1][6:8]) + self.assertEqual(expected_data[2], report[1][2][6:8]) + + make_payment(name) + report = execute(filters) + + expected_data_after_payment = [[100,50], [100,20]] + + self.assertEqual(expected_data_after_payment[0], report[1][0][6:8]) + self.assertEqual(expected_data_after_payment[1], report[1][1][6:8]) + + make_credit_note(name) + report = execute(filters) + + expected_data_after_credit_note = [[100,100,30,100,-30]] + + self.assertEqual(expected_data_after_credit_note[0], report[1][0][6:11]) + + +def make_sales_invoice(): + frappe.set_user("Administrator") + + si = create_sales_invoice(company="_Test Company 2", + customer = '_Test Customer 2', + currency = 'EUR', + warehouse = 'Finished Goods - _TC2', + debit_to = 'Debtors - _TC2', + income_account = 'Sales - _TC2', + expense_account = 'Cost of Goods Sold - _TC2', + cost_center = '_Test Company 2 - _TC2', + do_not_save=1) + + si.append('payment_schedule', dict(due_date=getdate(add_days(today(), 30)), invoice_portion=30.00, payment_amount=30)) + si.append('payment_schedule', dict(due_date=getdate(add_days(today(), 60)), invoice_portion=50.00, payment_amount=50)) + si.append('payment_schedule', dict(due_date=getdate(add_days(today(), 90)), invoice_portion=20.00, payment_amount=20)) + + si.submit() + + return si.name + +def make_payment(docname): + pe = get_payment_entry("Sales Invoice", docname, bank_account="Cash - _TC2", party_amount=30) + pe.paid_from = "Debtors - _TC2" + pe.insert() + pe.submit() + + +def make_credit_note(docname): + create_sales_invoice(company="_Test Company 2", + customer = '_Test Customer 2', + currency = 'EUR', + qty = -1, + warehouse = 'Finished Goods - _TC2', + debit_to = 'Debtors - _TC2', + income_account = 'Sales - _TC2', + expense_account = 'Cost of Goods Sold - _TC2', + cost_center = '_Test Company 2 - _TC2', + is_return = 1, + return_against = docname) + diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 4b0789567d..e658e22052 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -316,7 +316,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/report/purchase_analytics/purchase_analytics.js b/erpnext/buying/report/purchase_analytics/purchase_analytics.js index b55046e065..e17973c337 100644 --- a/erpnext/buying/report/purchase_analytics/purchase_analytics.js +++ b/erpnext/buying/report/purchase_analytics/purchase_analytics.js @@ -77,9 +77,20 @@ frappe.query_reports["Purchase Analytics"] = { events: { onCheckRow: function(data) { row_name = data[2].content; - row_values = data.slice(5).map(function (column) { - return column.content; - }) + length = data.length; + + var tree_type = frappe.query_report.filters[0].value; + + if(tree_type == "Supplier" || tree_type == "Item") { + row_values = data.slice(4,length-1).map(function (column) { + return column.content; + }) + } + else { + row_values = data.slice(3,length-1).map(function (column) { + return column.content; + }) + } entry = { 'name':row_name, 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/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/hooks.py b/erpnext/hooks.py index bddbb578a4..b3a2061092 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.30' +staging_version = '11.0.3-beta.31' error_report_email = "support@erpnext.com" 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/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/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 63cdf573ff..7cd3f6b093 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -515,7 +515,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 @@ -534,10 +534,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/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/public/js/utils.js b/erpnext/public/js/utils.js old mode 100644 new mode 100755 index 0f52c992e5..4b332e98ac --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -126,7 +126,7 @@ $.extend(erpnext.utils, { '