diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json index 6befedcfd8..26519ac5ff 100644 --- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json +++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json @@ -17,6 +17,7 @@ "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Mode of Payment", @@ -26,6 +27,7 @@ "oldfieldtype": "Data", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -33,6 +35,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Type", + "length": 0, + "no_copy": 0, + "options": "Cash\nBank\nGeneral", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -41,6 +69,7 @@ "fieldtype": "Table", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Accounts", @@ -50,6 +79,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -68,7 +98,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2015-11-16 06:29:50.335559", + "modified": "2016-04-26 11:48:17.411796", "modified_by": "Administrator", "module": "Accounts", "name": "Mode of Payment", @@ -115,6 +145,9 @@ "write": 0 } ], + "quick_entry": 1, "read_only": 0, - "read_only_onload": 0 + "read_only_onload": 0, + "sort_order": "ASC", + "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/payments/__init__.py b/erpnext/accounts/doctype/payments/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/doctype/payments/payments.json b/erpnext/accounts/doctype/payments/payments.json new file mode 100644 index 0000000000..d52fb1519c --- /dev/null +++ b/erpnext/accounts/doctype/payments/payments.json @@ -0,0 +1,191 @@ +{ + "allow_copy": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2016-05-08 23:49:38.842621", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "fields": [ + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "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, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "0.0", + "depends_on": "eval:parent.doctype == 'Sales Invoice'", + "fieldname": "amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Amount", + "length": 0, + "no_copy": 0, + "options": "currency", + "permlevel": 0, + "precision": "2", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_3", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "type", + "fieldtype": "Read Only", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Type", + "length": 0, + "no_copy": 0, + "options": "mode_of_payment.type", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "base_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Base Amount (Company Currency)", + "length": 0, + "no_copy": 1, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + } + ], + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "in_create": 0, + "in_dialog": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2016-05-09 00:14:18.975568", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payments", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/payments/payments.py b/erpnext/accounts/doctype/payments/payments.py new file mode 100644 index 0000000000..15cf0b26a7 --- /dev/null +++ b/erpnext/accounts/doctype/payments/payments.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document + +class Payments(Document): + pass diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index 6d395affd6..8f25ba90b3 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -3,6 +3,7 @@ "allow_import": 0, "allow_rename": 0, "autoname": "hash", + "beta": 0, "creation": "2013-05-24 12:15:51", "custom": 0, "docstatus": 0, @@ -16,6 +17,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Applicable for User", @@ -26,6 +28,7 @@ "options": "User", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -41,6 +44,7 @@ "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Series", @@ -51,6 +55,7 @@ "options": "[Select]", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -58,31 +63,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "warehouse", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Warehouse", - "length": 0, - "no_copy": 0, - "oldfieldname": "warehouse", - "oldfieldtype": "Link", - "options": "Warehouse", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -93,6 +73,7 @@ "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Update Stock", @@ -100,6 +81,60 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "update_stock", + "fieldname": "warehouse", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 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, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "ignore_pricing_rule", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 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, "report_hide": 0, "reqd": 0, @@ -115,6 +150,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -122,6 +158,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -137,6 +174,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Customer", @@ -147,6 +185,7 @@ "options": "Customer", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -162,6 +201,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Company", @@ -172,6 +212,7 @@ "options": "Company", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -187,6 +228,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Currency", @@ -197,6 +239,7 @@ "options": "Currency", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -208,19 +251,70 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "fieldname": "mode_of_payment", - "fieldtype": "Link", + "fieldname": "allow_partial_payment", + "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "label": "Mode of Payment", + "label": "Allow Partial 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, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "section_break_11", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "payments", + "fieldtype": "Table", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Payments", + "length": 0, + "no_copy": 0, + "options": "Payments", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -236,6 +330,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -243,6 +338,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -258,6 +354,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Print Format", @@ -267,6 +364,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -282,6 +380,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Letter Head", @@ -292,6 +391,7 @@ "options": "Letter Head", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -307,6 +407,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Print Heading", @@ -317,6 +418,7 @@ "options": "Print Heading", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -332,6 +434,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Terms and Conditions", @@ -342,6 +445,7 @@ "options": "Terms and Conditions", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -357,6 +461,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -364,6 +469,33 @@ "oldfieldtype": "Column Break", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "customer_group", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Customer Group", + "length": 0, + "no_copy": 0, + "options": "Customer Group", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -380,6 +512,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Territory", @@ -390,6 +523,7 @@ "options": "Territory", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -405,6 +539,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Price List", @@ -415,6 +550,60 @@ "options": "Price List", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "apply_discount", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Apply Discount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "Grand Total", + "depends_on": "apply_discount", + "fieldname": "apply_discount_on", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 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, "report_hide": 0, "reqd": 0, @@ -430,6 +619,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -437,6 +627,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -448,10 +639,12 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "depends_on": "", "fieldname": "write_off_account", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Write Off Account", @@ -461,6 +654,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -476,6 +670,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Write Off Cost Center", @@ -485,6 +680,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -500,6 +696,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Taxes and Charges", @@ -510,6 +707,7 @@ "options": "Sales Taxes and Charges Template", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -525,6 +723,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -532,6 +731,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -547,6 +747,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Cash/Bank Account", @@ -557,6 +758,7 @@ "options": "Account", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -572,6 +774,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Income Account", @@ -582,6 +785,7 @@ "options": "Account", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -598,6 +802,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Expense Account", @@ -606,6 +811,7 @@ "options": "Account", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -621,6 +827,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Cost Center", @@ -631,6 +838,7 @@ "options": "Cost Center", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -649,7 +857,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2015-11-16 06:29:51.741253", + "modified": "2016-05-09 00:00:30.610878", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", @@ -696,9 +904,11 @@ "write": 0 } ], + "quick_entry": 1, "read_only": 0, "read_only_onload": 0, "sort_field": "modified", "sort_order": "DESC", - "title_field": "user" + "title_field": "user", + "track_seen": 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 98a8509792..634d63c190 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import msgprint, _ from frappe.utils import cint +from erpnext.accounts.doctype.sales_invoice.sales_invoice import set_account_for_mode_of_payment from frappe.model.document import Document @@ -36,6 +37,9 @@ class POSProfile(Document): "company": self.company, "name": link_dn}): frappe.throw(_("{0} does not belong to Company {1}").format(link_dn, self.company)) + def before_save(self): + set_account_for_mode_of_payment(self) + def on_update(self): self.set_defaults() diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index c534415d72..923514da5b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -129,7 +129,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ paid_amount: function() { this.set_in_company_currency(this.frm.doc, ["paid_amount"]); - this.write_off_outstanding_amount(); + this.write_off_amount(); this.frm.refresh_fields(); }, diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 62a9f526e6..0cf17da1c9 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -2,50 +2,186 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe, json +from frappe import _ +from frappe.utils import nowdate +from erpnext.setup.utils import get_exchange_rate +from erpnext.stock.get_item_details import get_pos_profile +from erpnext.controllers.accounts_controller import get_taxes_and_charges @frappe.whitelist() -def get_items(price_list, sales_or_purchase, item=None): - condition = "" - order_by = "" - args = {"price_list": price_list} +def get_pos_data(): + doc = frappe.new_doc('Sales Invoice') + doc.update_stock = 1; + doc.is_pos = 1; + pos_profile = get_pos_profile(doc.company) - if item: - # search serial no - item_code = frappe.db.sql("""select name as serial_no, item_code - from `tabSerial No` where name=%s""", (item), as_dict=1) - if item_code: - item_code[0]["name"] = item_code[0]["item_code"] - return item_code + if not pos_profile: + frappe.throw(_("Create pos profile first")) - # search barcode - item_code = frappe.db.sql("""select name, item_code from `tabItem` - where barcode=%s""", - (item), as_dict=1) - if item_code: - item_code[0]["barcode"] = item - return item_code + pos_profile = frappe.get_doc('POS Profile', pos_profile.name) + update_pos_profile_data(doc, pos_profile) + update_multi_mode_option(doc, pos_profile) - condition += " and ((CONCAT(i.name, i.item_name) like %(name)s) or (i.variant_of like %(name)s) or (i.item_group like %(name)s))" - order_by = """if(locate(%(_name)s, i.name), locate(%(_name)s, i.name), 99999), - if(locate(%(_name)s, i.item_name), locate(%(_name)s, i.item_name), 99999), - if(locate(%(_name)s, i.variant_of), locate(%(_name)s, i.variant_of), 99999), - if(locate(%(_name)s, i.item_group), locate(%(_name)s, i.item_group), 99999),""" - args["name"] = "%%%s%%" % frappe.db.escape(item) - args["_name"] = item.replace("%", "") + return { + 'doc': doc, + 'items': get_items(doc, pos_profile), + 'customers': get_customers(pos_profile), + 'pricing_rules': get_pricing_rules(doc), + 'mode_of_payment': get_mode_of_payment(doc), + 'print_template': frappe.db.get_value('Print Format', pos_profile.print_format, 'html') or '', + 'meta': { + 'invoice': frappe.get_meta('Sales Invoice'), + 'items': frappe.get_meta('Sales Invoice Item'), + 'taxes': frappe.get_meta('Sales Taxes and Charges') + } + } - # locate function is used to sort by closest match from the beginning of the value - return frappe.db.sql("""select i.name, i.item_name, i.image, - item_det.price_list_rate, item_det.currency - from `tabItem` i LEFT JOIN - (select item_code, price_list_rate, currency from - `tabItem Price` where price_list=%(price_list)s) item_det - ON - (item_det.item_code=i.name or item_det.item_code=i.variant_of) - where - i.has_variants = 0 and - {condition} - order by - {order_by} - i.name - limit 24""".format(condition=condition, order_by=order_by), args, as_dict=1) +def update_pos_profile_data(doc, pos_profile): + company_data = frappe.db.get_value('Company', doc.company, '*', as_dict=1) + + doc.taxes_and_charges = pos_profile.taxes_and_charges + if doc.taxes_and_charges: + update_tax_table(doc) + + doc.currency = pos_profile.currency or company_data.default_currency + doc.conversion_rate = 1.0 + if doc.currency != company_data.default_currency: + doc.conversion_rate = get_exchange_rate(doc.currency, company_data.default_currency) + doc.selling_price_list = pos_profile.selling_price_list or frappe.db.get_value('Selling Settings', None, 'selling_price_list') + doc.naming_series = pos_profile.naming_series or 'SINV-' + doc.letter_head = pos_profile.letter_head or company_data.default_letter_head + doc.ignore_pricing_rule = pos_profile.ignore_pricing_rule + doc.apply_discount_on = pos_profile.apply_discount_on + doc.customer_group = pos_profile.customer_group or get_root('Customer Group') + doc.territory = pos_profile.territory or get_root('Territory') + +def get_root(table): + root = frappe.db.sql(""" select name from `tab%(table)s` having + min(lft)"""%{'table': table}, as_dict=1) + + return root[0].name + +def update_multi_mode_option(doc, pos_profile): + from frappe.model import default_fields + + for payment_mode in pos_profile.payments: + payment_mode = payment_mode.as_dict() + + for fieldname in default_fields: + if fieldname in payment_mode: + del payment_mode[fieldname] + + doc.append('payments', payment_mode) + +def update_tax_table(doc): + taxes = get_taxes_and_charges('Sales Taxes and Charges Template', doc.taxes_and_charges) + for tax in taxes: + doc.append('taxes', tax) + +def get_items(doc, pos_profile): + item_list = [] + for item in frappe.get_all("Item", fields=["*"], filters={'disabled': 0, 'has_variants': 0}): + item_doc = frappe.get_doc('Item', item.name) + if item_doc.taxes: + item.taxes = json.dumps(dict(([d.tax_type, d.tax_rate] for d in + item_doc.get("taxes")))) + + item.price_list_rate = frappe.db.get_value('Item Price', {'item_code': item.name, + 'price_list': doc.selling_price_list}, 'price_list_rate') or 0 + item.default_warehouse = pos_profile.warehouse or item.default_warehouse or None + item.expense_account = pos_profile.expense_account or item.expense_account + item.income_account = pos_profile.income_account or item_doc.income_account + item.cost_center = pos_profile.cost_center or item_doc.selling_cost_center + item.actual_qty = frappe.db.get_value('Bin', {'item_code': item.name, + 'warehouse': item.default_warehouse}, 'actual_qty') or 0 + item.serial_nos = frappe.db.sql_list("""select name from `tabSerial No` where warehouse= %(warehouse)s + and item_code = %(item_code)s""", {'warehouse': item.default_warehouse, 'item_code': item.item_code}) + item_list.append(item) + + return item_list + +def get_customers(pos_profile): + filters = {'disabled': 0} + if pos_profile.customer: + filters.update({'name': pos_profile.customer}) + + return frappe.get_all("Customer", fields=["*"], filters = filters) + +def get_pricing_rules(doc): + if doc.ignore_pricing_rule == 0: + return frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2 and disable = 0 + and selling = 1 and ifnull(company, '') in (%(company)s, '') and + ifnull(for_price_list, '') in (%(price_list)s, '') and %(date)s between + ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31') order by priority desc, name desc""", + {'company': doc.company, 'price_list': doc.selling_price_list, 'date': nowdate()}, as_dict=1) + +def get_mode_of_payment(doc): + return frappe.get_all('Mode of Payment Account', fields = ['distinct parent'], filters={'company': doc.company}) + +@frappe.whitelist() +def make_invoice(doc_list): + if isinstance(doc_list, basestring): + doc_list = json.loads(doc_list) + + name_list = [] + + for docs in doc_list: + for name, doc in docs.items(): + validate_customer(doc) + validate_item(doc) + si_doc = frappe.new_doc('Sales Invoice') + si_doc.offline_pos_name = name + si_doc.update(doc) + submit_invoice(si_doc) + name_list.append(name) + + return name_list + +def validate_customer(doc): + if not frappe.db.get_value('Customer', doc.get('customer')): + customer_doc = frappe.new_doc('Customer') + customer_doc.customer_name = doc.get('customer') + customer_doc.customer_type = 'Company' + customer_doc.customer_group = doc.get('customer_group') + customer_doc.territory = doc.get('territory') + customer_doc.save(ignore_permissions = True) + frappe.db.commit() + doc['customer'] = customer_doc.name + + return doc + +def validate_item(doc): + for item in doc.get('items'): + if not frappe.db.exists('Item', item.get('item_code')): + item_doc = frappe.new_doc('Item') + item_doc.name = item.get('item_code') + item_doc.item_code = item.get('item_code') + item_doc.item_name = item.get('item_name') + item_doc.description = item.get('description') + item_doc.default_warehouse = item.get('warehouse') + item_doc.stock_uom = item.get('stock_uom') + item_doc.item_group = item.get('item_group') + item_doc.save(ignore_permissions=True) + frappe.db.commit() + +def submit_invoice(si_doc): + try: + si_doc.insert() + si_doc.submit() + except Exception, e: + if frappe.message_log: frappe.message_log.pop() + frappe.db.rollback() + save_invoice(e, si_doc) + +def save_invoice(e, si_doc): + si_doc.docstatus = 0 + si_doc.name = '' + si_doc.save(ignore_permissions=True) + make_scheduler_log(e, si_doc.name) + +def make_scheduler_log(e, sales_invoice): + scheduler_log = frappe.new_doc('Scheduler Log') + scheduler_log.error = e + scheduler_log.sales_invoice = sales_invoice + scheduler_log.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index c3c91a0764..45c918ca8c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -17,17 +17,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.frm.set_df_property("debit_to", "print_hide", 0); } - // toggle to pos view if is_pos is 1 in user_defaults - if ((is_null(this.frm.doc.is_pos) && cint(frappe.defaults.get_user_default("is_pos"))===1) || this.frm.doc.is_pos) { - if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) { - this.frm.set_value("is_pos", 1); - this.is_pos(function() { - if (cint(frappe.defaults.get_user_defaults("fs_pos_view"))===1) - erpnext.pos.toggle(me.frm, true); - }); - } - } - erpnext.queries.setup_queries(this.frm, "Warehouse", function() { return erpnext.queries.warehouse(me.frm.doc); }); @@ -149,39 +138,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.get_terms(); }, - is_pos: function(doc, dt, dn, callback_fn) { - cur_frm.cscript.hide_fields(this.frm.doc); - if(cur_frm.doc.__missing_values_set) return; - if(cint(this.frm.doc.is_pos)) { - if(!this.frm.doc.company) { - this.frm.set_value("is_pos", 0); - msgprint(__("Please specify Company to proceed")); - } else { - var me = this; - return this.frm.call({ - doc: me.frm.doc, - method: "set_missing_values", - callback: function(r) { - if(!r.exc) { - if(r.message && r.message.print_format) { - cur_frm.pos_print_format = r.message.print_format; - } - cur_frm.doc.__missing_values_set = true; - me.frm.script_manager.trigger("update_stock"); - frappe.model.set_default_values(me.frm.doc); - me.set_dynamic_labels(); - me.calculate_taxes_and_totals(); - if(callback_fn) callback_fn(); - frappe.after_ajax(function() { - cur_frm.doc.__missing_values_set = false; - }) - } - } - }); - } - } - }, - customer: function() { var me = this; if(this.frm.updating_party_details) return; @@ -245,11 +201,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.write_off_outstanding_amount_automatically(); }, - paid_amount: function() { - this.set_in_company_currency(this.frm.doc, ["paid_amount"]); - this.write_off_outstanding_amount_automatically(); - }, - items_add: function(doc, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); this.frm.script_manager.copy_from_first_row("items", row, ["income_account", "cost_center"]); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 6678583932..9da4aaef0d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -3,6 +3,7 @@ "allow_import": 1, "allow_rename": 0, "autoname": "naming_series:", + "beta": 0, "creation": "2013-05-24 19:29:05", "custom": 0, "default_print_format": "Standard", @@ -194,6 +195,31 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "offline_pos_name", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Offline POS Name", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -653,6 +679,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "territory", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Territory", + "length": 0, + "no_copy": 0, + "options": "Territory", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -1941,7 +1993,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 1, - "collapsible_depends_on": "paid_amount", + "collapsible_depends_on": "", "depends_on": "eval:doc.is_pos===1||(doc.advances && doc.advances.length>0)", "fieldname": "payments_section", "fieldtype": "Section Break", @@ -1971,7 +2023,7 @@ "depends_on": "is_pos", "fieldname": "cash_bank_account", "fieldtype": "Link", - "hidden": 0, + "hidden": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -1996,9 +2048,34 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "depends_on": "is_pos", - "fieldname": "column_break3", - "fieldtype": "Column Break", + "fieldname": "payments", + "fieldtype": "Table", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Payments", + "length": 0, + "no_copy": 0, + "options": "Payments", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "section_break_84", + "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -2007,6 +2084,7 @@ "length": 0, "no_copy": 0, "permlevel": 0, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -2014,35 +2092,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "unique": 0, - "width": "50%" - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "is_pos", - "fieldname": "paid_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Paid Amount", - "length": 0, - "no_copy": 1, - "oldfieldname": "paid_amount", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, "unique": 0 }, { @@ -2071,6 +2120,110 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "base_change_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Base Change Amount (Company Currency)", + "length": 0, + "no_copy": 1, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_86", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "is_pos", + "fieldname": "paid_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Paid Amount", + "length": 0, + "no_copy": 1, + "oldfieldname": "paid_amount", + "oldfieldtype": "Currency", + "options": "currency", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "change_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Change Amount", + "length": 0, + "no_copy": 1, + "options": "currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -3443,7 +3596,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-04-14 13:01:01.748816", + "modified": "2016-05-09 15:03:33.236351", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", @@ -3530,6 +3683,7 @@ "write": 0 } ], + "quick_entry": 1, "read_only": 0, "read_only_onload": 1, "search_fields": "posting_date, due_date, customer, base_grand_total, outstanding_amount", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 3120e73176..952cce6a00 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -64,8 +64,8 @@ class SalesInvoice(SellingController): self.validate_fixed_asset() self.set_income_account_for_fixed_assets() - if cint(self.is_pos): - self.validate_pos() + # if cint(self.is_pos): + # self.validate_pos() if cint(self.update_stock): self.validate_dropship_item() @@ -83,6 +83,18 @@ class SalesInvoice(SellingController): self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items") self.update_packing_list() + def before_save(self): + set_account_for_mode_of_payment(self) + + def update_change_amount(self): + self.base_paid_amount = 0.0 + if self.paid_amount: + self.base_paid_amount = flt(self.paid_amount * self.conversion_rate, self.precision("base_paid_amount")) + self.change_amount = self.base_change_amount = 0.0 + if self.paid_amount > self.grand_total: + self.change_amount = flt(self.paid_amount - self.grand_total, self.precision("change_amount")) + self.base_change_amount = flt(self.change_amount * self.conversion_rate, self.precision("base_change_amount")) + def on_submit(self): if not self.recurring_id: frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, @@ -588,8 +600,7 @@ class SalesInvoice(SellingController): gl_entries += super(SalesInvoice, self).get_gl_entries() def make_pos_gl_entries(self, gl_entries): - if cint(self.is_pos) and self.cash_bank_account and self.paid_amount: - bank_account_currency = get_account_currency(self.cash_bank_account) + if cint(self.is_pos) and self.paid_amount: # POS, make payment entries gl_entries.append( self.get_gl_dict({ @@ -597,22 +608,43 @@ class SalesInvoice(SellingController): "party_type": "Customer", "party": self.customer, "against": self.cash_bank_account, - "credit": self.base_paid_amount, - "credit_in_account_currency": self.base_paid_amount \ - if self.party_account_currency==self.company_currency else self.paid_amount, + "credit": flt(self.base_paid_amount - self.base_change_amount), + "credit_in_account_currency": flt(self.base_paid_amount - self.base_change_amount) \ + if self.party_account_currency==self.company_currency else flt(self.paid_amount - self.change_amount), "against_voucher": self.return_against if cint(self.is_return) else self.name, "against_voucher_type": self.doctype, }, self.party_account_currency) ) - gl_entries.append( - self.get_gl_dict({ - "account": self.cash_bank_account, - "against": self.customer, - "debit": self.base_paid_amount, - "debit_in_account_currency": self.base_paid_amount \ - if bank_account_currency==self.company_currency else self.paid_amount - }, bank_account_currency) - ) + + cash_account = '' + for payment_mode in self.payments: + if payment_mode.type == 'Cash': + cash_account = payment_mode.account + + if payment_mode.base_amount > 0: + payment_mode_account_currency = get_account_currency(payment_mode.account) + gl_entries.append( + self.get_gl_dict({ + "account": payment_mode.account, + "against": self.customer, + "debit": payment_mode.base_amount, + "debit_in_account_currency": payment_mode.base_amount \ + if payment_mode_account_currency==self.company_currency else payment_mode.amount + }, payment_mode_account_currency) + ) + + if self.change_amount: + cash_account = cash_account or self.payments[0].account + cash_account_currency = get_account_currency(cash_account) + gl_entries.append( + self.get_gl_dict({ + "account": cash_account, + "against": self.customer, + "credit": self.base_change_amount, + "credit_in_account_currency": self.base_change_amount \ + if payment_mode_account_currency==self.company_currency else self.change_amount + }, payment_mode_account_currency) + ) def make_write_off_gl_entry(self, gl_entries): # write off entries, applicable if only pos @@ -680,7 +712,7 @@ def get_bank_cash_account(mode_of_payment, company): account = frappe.db.get_value("Mode of Payment Account", {"parent": mode_of_payment, "company": company}, "default_account") if not account: - frappe.msgprint(_("Please set default Cash or Bank account in Mode of Payment {0}").format(mode_of_payment)) + frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}").format(mode_of_payment)) return { "account": account } @@ -737,4 +769,9 @@ def make_delivery_note(source_name, target_doc=None): @frappe.whitelist() def make_sales_return(source_name, target_doc=None): from erpnext.controllers.sales_and_purchase_return import make_return_doc - return make_return_doc("Sales Invoice", source_name, target_doc) \ No newline at end of file + return make_return_doc("Sales Invoice", source_name, target_doc) + +def set_account_for_mode_of_payment(self): + for data in self.payments: + if not data.account: + data.account = get_bank_cash_account(data.mode_of_payment, self.company).get("account") \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index bac24d8027..7208c2af74 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -441,17 +441,45 @@ class TestSalesInvoice(unittest.TestCase): self.make_pos_profile() self._insert_purchase_receipt() - pos = copy.deepcopy(test_records[1]) pos["is_pos"] = 1 pos["update_stock"] = 1 - pos["cash_bank_account"] = "_Test Bank - _TC" - pos["paid_amount"] = 600.0 + pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, + {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300}] si = frappe.copy_doc(pos) si.insert() si.submit() + + self.assertEquals(si.paid_amount, 600.0) + self.pos_gl_entry(si, pos, 300) + + def test_make_pos_invoice(self): + from erpnext.accounts.doctype.sales_invoice.pos import make_invoice + + set_perpetual_inventory() + + self.make_pos_profile() + self._insert_purchase_receipt() + + pos = copy.deepcopy(test_records[1]) + pos["is_pos"] = 1 + pos["update_stock"] = 1 + pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, + {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}] + + invoice_data = [{'09052016142': pos}] + si = make_invoice(invoice_data) + self.assertEquals(si[0], '09052016142') + + sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1}) + si = frappe.get_doc('Sales Invoice', sales_invoice[0].name) + self.assertEquals(si.grand_total, 630.0) + + self.pos_gl_entry(si, pos, 330) + + def pos_gl_entry(self, si, pos, cash_amount): # check stock ledger entries sle = frappe.db.sql("""select * from `tabStock Ledger Entry` where voucher_type = 'Sales Invoice' and voucher_no = %s""", @@ -467,7 +495,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(gl_entries) stock_in_hand = frappe.db.get_value("Account", {"warehouse": "_Test Warehouse - _TC"}) - + expected_gl_entries = sorted([ [si.debit_to, 630.0, 0.0], [pos["items"][0]["income_account"], 0.0, 500.0], @@ -475,8 +503,9 @@ class TestSalesInvoice(unittest.TestCase): [pos["taxes"][1]["account_head"], 0.0, 50.0], [stock_in_hand, 0.0, abs(sle.stock_value_difference)], [pos["items"][0]["expense_account"], abs(sle.stock_value_difference), 0.0], - [si.debit_to, 0.0, 600.0], - ["_Test Bank - _TC", 600.0, 0.0] + [si.debit_to, 0.0, si.paid_amount], + ["_Test Bank - _TC", 300.0, 0.0], + ["Cash - _TC", cash_amount, 0.0] ]) for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)): diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index df7757b842..04dd5804d2 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -1,46 +1,843 @@ +frappe.provide("erpnext.pos"); +{% include "erpnext/public/js/controllers/taxes_and_totals.js" %} + frappe.pages['pos'].on_page_load = function(wrapper) { var page = frappe.ui.make_app_page({ parent: wrapper, - title: __('Start Point-of-Sale (POS)'), + title: 'Point of Sale', single_column: true }); - - page.main.html(frappe.render_template("pos_page", {})); - - var pos_type = frappe.ui.form.make_control({ - parent: page.main.find(".select-type"), - df: { - fieldtype: "Select", - options: [ - {label: __("Billing (Sales Invoice)"), value:"Sales Invoice"}, - {value:"Sales Order"}, - {value:"Delivery Note"}, - {value:"Quotation"}, - {value:"Purchase Order"}, - {value:"Purchase Receipt"}, - {value:"Purchase Invoice"}, - ], - fieldname: "pos_type" - }, - only_input: true - }); - - pos_type.refresh(); - - pos_type.set_input("Sales Invoice"); - - page.main.find(".btn-primary").on("click", function() { - erpnext.open_as_pos = true; - new_doc(pos_type.get_value()); - }); - - $.ajax({ - url: "/api/resource/POS Profile", - success: function(data) { - if(!data.data.length) { - page.main.find(".pos-setting-message").removeClass('hide'); - } - } - }) - + + wrapper = $(wrapper).find('.page-content') + new erpnext.pos.PointOfSale(page, wrapper) } + +erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ + init: function(page, wrapper){ + this.page = page; + this.wrapper = wrapper; + this.set_indicator(); + this.onload(); + this.make_menu_list(); + this.set_interval_for_si_sync(); + this.si_docs = this.get_doc_from_localstorage(); + }, + + check_internet_connection: function(){ + var me = this; + //Check Internet connection after every 30 seconds + setInterval(function(){ + me.set_indicator(); + }, 30000) + }, + + set_indicator: function(){ + var me = this; + // navigator.onLine + this.page.set_indicator("Offline", "grey") + frappe.call({ + method:"frappe.handler.ping", + callback: function(r){ + if(r.message){ + me.connection_status = true; + me.page.set_indicator("Online", "green") + } + } + }) + }, + + onload: function(){ + var me = this; + + this.get_data_from_server(function(){ + me.create_new(); + }); + + this.check_internet_connection(); + }, + + make_menu_list: function(){ + var me = this; + + this.page.add_menu_item(__("Unsync Records"), function(){ + me.show_unsync_invoice_list() + }); + + this.page.add_menu_item(__("Sync Master Data"), function(){ + me.get_data_from_server() + }); + + this.page.add_menu_item(__("New Sales Invoice"), function() { + me.create_new() + }) + }, + + show_unsync_invoice_list: function(){ + var me = this; + this.si_docs = this.get_doc_from_localstorage(); + + this.list_dialog = new frappe.ui.Dialog({ + title: 'Invoice List' + }); + + this.list_dialog.show(); + this.list_body = this.list_dialog.body; + $(this.list_body).append('
No payment mode selected in pos profile
").appendTo(multimode_payments) + } + }, + + bind_keyboard_event: function(){ + var me = this; + this.payment_val = ''; + this.bind_payment_mode_keys_event(); + this.bind_keyboard_keys_event(); + }, + + bind_payment_mode_keys_event: function(){ + var me = this; + $(this.$body).find('.pos-payment-row').click(function(){ + me.idx = $(this).attr("idx"); + me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']",{'idx': me.idx})); + me.highlight_selected_row() + me.payment_val = 0.0 + if(me.frm.doc.outstanding_amount > 0 && flt(me.selected_mode.val()) == 0.0){ + //When user first time click on row + me.payment_val = flt(me.frm.doc.outstanding_amount) + me.selected_mode.val(format_number(me.payment_val, 2)); + me.update_paid_amount() + me.bind_amount_change_event(); + }else if(flt(me.selected_mode.val()) > 0){ + //If user click on existing row which has value + me.payment_val = flt(me.selected_mode.val()); + } + me.selected_mode.select() + }) + }, + + highlight_selected_row: function(){ + var me = this; + selected_row = $(this.$body).find(repl(".pos-payment-row[idx='%(idx)s']",{'idx': this.idx})); + $(this.$body).find('.pos-payment-row').removeClass('selected-payment-mode') + selected_row.addClass('selected-payment-mode') + $(this.$body).find('.amount').attr('disabled', true); + this.selected_mode.attr('disabled', false); + }, + + bind_keyboard_keys_event: function(){ + var me = this; + $(this.$body).find('.pos-keyboard-key').click(function(){ + me.payment_val += $(this).text(); + me.selected_mode.val(format_number(me.payment_val, 2)) + me.idx = me.selected_mode.attr("idx") + me.update_paid_amount() + }) + + $(this.$body).find('.delete-btn').click(function(){ + me.payment_val = cstr(flt(me.selected_mode.val())).slice(0, -1); + me.selected_mode.val(format_number(me.payment_val, 2)); + me.idx = me.selected_mode.attr("idx") + me.update_paid_amount(); + }) + + }, + + bind_amount_change_event: function(){ + var me = this; + me.selected_mode.change(function(){ + me.payment_val = $(this).val() || 0.0; + me.selected_mode.val(format_number(me.payment_val, 2)) + me.idx = me.selected_mode.attr("idx") + me.update_paid_amount() + }) + }, + + update_paid_amount: function(){ + var me = this; + $.each(this.frm.doc.payments, function(index, data){ + if(cint(me.idx) == cint(data.idx)){ + data.amount = flt(me.selected_mode.val(), 2) + } + }) + this.calculate_outstanding_amount(); + this.show_amounts(); + }, + + show_amounts: function(){ + var me = this; + $(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency)); + $(this.$body).find('.change_amount').text(format_currency(this.frm.doc.change_amount, this.frm.doc.currency)) + $(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, this.frm.doc.currency)) + this.update_invoice(); + } +}) \ No newline at end of file diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 1a234a3b38..f775f292f0 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -1,13 +1,30 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt -erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ +erpnext.taxes_and_totals = erpnext.payments.extend({ + apply_pricing_rule_on_item: function(item){ + if(!item.margin_type){ + item.margin_rate_or_amount = 0.0; + } + + if(item.margin_type == "Percentage"){ + item.total_margin = item.price_list_rate + item.price_list_rate * ( item.margin_rate_or_amount / 100); + }else{ + item.total_margin = item.price_list_rate + item.margin_rate_or_amount; + } + + item.rate = flt(item.total_margin , 2); + + if(item.discount_percentage){ + discount_value = flt(item.total_margin) * flt(item.discount_percentage) / 100; + item.rate = flt((item.total_margin) - (discount_value), precision('rate')); + } + }, + calculate_taxes_and_totals: function(update_paid_amount) { this.discount_amount_applied = false; this._calculate_taxes_and_totals(); - - if (frappe.meta.get_docfield(this.frm.doc.doctype, "discount_amount")) - this.apply_discount_amount(); + this.calculate_discount_amount(); // Advance calculation applicable to Sales /Purchase Invoice if(in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype) @@ -24,6 +41,11 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ this.frm.refresh_fields(); }, + calculate_discount_amount: function(){ + if (frappe.meta.get_docfield(this.frm.doc.doctype, "discount_amount")) + this.apply_discount_amount(); + }, + _calculate_taxes_and_totals: function() { this.validate_conversion_rate(); this.calculate_item_values(); @@ -98,7 +120,7 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); - if (!this.discount_amount_applied) { + if (!this.discount_amount_applied && cur_frm) { cur_frm.cscript.validate_taxes_and_charges(tax.doctype, tax.name); me.validate_inclusive_tax(tax); } @@ -433,13 +455,14 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ apply_discount_amount: function() { var me = this; var distributed_amount = 0.0; + this.frm.doc.base_discount_amount = 0.0; if (this.frm.doc.discount_amount) { if(!this.frm.doc.apply_discount_on) frappe.throw(__("Please select Apply Discount On")); - - this.frm.set_value("base_discount_amount", - flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate, precision("base_discount_amount"))) + + this.frm.doc.base_discount_amount = flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate, + precision("base_discount_amount")); var total_for_discount_amount = this.get_total_for_discount_amount(); // calculate item amount after Discount Amount @@ -455,8 +478,6 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ this.discount_amount_applied = true; this._calculate_taxes_and_totals(); } - } else { - this.frm.set_value("base_discount_amount", 0); } }, @@ -524,18 +545,59 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ this.frm.doc.paid_amount = 0 } this.set_in_company_currency(this.frm.doc, ["paid_amount"]); - this.frm.refresh_field("paid_amount"); - this.frm.refresh_field("base_paid_amount"); + + if(this.frm.refresh_field){ + this.frm.refresh_field("paid_amount"); + this.frm.refresh_field("base_paid_amount"); + } + + if(this.frm.doc.doctype == "Sales Invoice"){ + this.calculate_paid_amount() + } + + var outstanding_amount = 0.0 var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ? this.frm.doc.paid_amount : this.frm.doc.base_paid_amount; - var outstanding_amount = flt(total_amount_to_pay - flt(paid_amount), - precision("outstanding_amount")); + if (total_amount_to_pay > paid_amount){ + outstanding_amount = flt(total_amount_to_pay - flt(paid_amount), + precision("outstanding_amount")); + } } else if(this.frm.doc.doctype == "Purchase Invoice") { var outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount")); } - this.frm.set_value("outstanding_amount", outstanding_amount); - } + + this.frm.doc.outstanding_amount = outstanding_amount; + this.calculate_change_amount() + }, + + calculate_paid_amount: function(){ + var me = this; + var paid_amount = base_paid_amount = 0.0; + $.each(this.frm.doc['payments'] || [], function(index, data){ + if(data.amount > 0){ + data.base_amount = flt(data.amount * me.frm.doc.conversion_rate); + paid_amount += data.amount; + base_paid_amount += data.base_amount; + } + }) + + this.frm.doc.paid_amount = flt(paid_amount, precision("paid_amount")); + this.frm.doc.base_paid_amount = flt(base_paid_amount, precision("base_paid_amount")); + }, + + calculate_change_amount: function(){ + var change_amount = 0.0; + if(this.frm.doc.paid_amount > this.frm.doc.grand_total){ + change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total, + precision("change_amount")) + } + + this.frm.doc.change_amount = flt(change_amount, + precision("change_amount")) + this.frm.doc.base_change_amount = flt(change_amount * this.frm.doc.conversion_rate, + precision("base_change_amount")) + }, }) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 3f6ea5ae9c..c6224668bc 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -165,7 +165,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ erpnext.hide_company(); this.show_item_wise_taxes(); this.set_dynamic_labels(); - erpnext.pos.make_pos_btn(this.frm); + // erpnext.pos.make_pos_btn(this.frm); this.setup_sms(); this.make_show_payments_btn(); }, @@ -550,7 +550,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ setup_field_label_map(["base_total", "base_net_total", "base_total_taxes_and_charges", "base_discount_amount", "base_grand_total", "base_rounded_total", "base_in_words", "base_taxes_and_charges_added", "base_taxes_and_charges_deducted", "total_amount_to_pay", - "base_paid_amount", "base_write_off_amount" + "base_paid_amount", "base_write_off_amount", "base_change_amount" ], company_currency); setup_field_label_map(["total", "net_total", "total_taxes_and_charges", "discount_amount", diff --git a/erpnext/public/js/payment/payment_details.html b/erpnext/public/js/payment/payment_details.html new file mode 100644 index 0000000000..b0f61d81f7 --- /dev/null +++ b/erpnext/public/js/payment/payment_details.html @@ -0,0 +1,4 @@ +Total
Paid
Outstanding
Change
+ {{ company }}
+
+ {{currency}} +
+{% for item in items %} +{{item.item_code}}
+{% endfor %} \ No newline at end of file diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 5906a4fba4..e613daf84a 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -122,7 +122,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ // check if child doctype is Sales Order Item/Qutation Item and calculate the rate if(in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item"]), cdt) - this.calculate_revised_margin_and_rate(item, doc,cdt, cdn); + this.apply_pricing_rule_on_item(item); else item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0), precision("rate", item)); @@ -320,7 +320,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ margin_rate_or_amount: function(doc, cdt, cdn) { // calculated the revised total margin and rate on margin rate changes item = locals[cdt][cdn]; - this.calculate_revised_margin_and_rate(item) + this.apply_pricing_rule_on_item(item) this.calculate_taxes_and_totals(); cur_frm.refresh_fields(); }, @@ -328,26 +328,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ margin_type: function(doc, cdt, cdn){ // calculate the revised total margin and rate on margin type changes item = locals[cdt][cdn]; - this.calculate_revised_margin_and_rate(item, doc,cdt, cdn) + this.apply_pricing_rule_on_item(item, doc,cdt, cdn) this.calculate_taxes_and_totals(); cur_frm.refresh_fields(); - }, - - calculate_revised_margin_and_rate: function(item){ - if(in_list(["Percentage", "Amount"], item.margin_type)){ - if(item.margin_type == "Percentage") - item.total_margin = item.price_list_rate + item.price_list_rate * ( item.margin_rate_or_amount / 100); - else - item.total_margin = item.price_list_rate + item.margin_rate_or_amount; - item.rate = flt(item.total_margin * (1 - item.discount_percentage / 100.0), - precision("rate", item)); - } - else{ - item.rate_or_amount = 0.0; - item.total_margin = 0.0; - item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0), - precision("rate", item)); - } } });