Merge branch 'develop' into payment-terms
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json
index 76e66d0..e27eaab 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.json
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json
@@ -80,6 +80,36 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "due_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Due Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
@@ -718,7 +748,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-08-03 12:40:09.611951",
+ "modified": "2017-08-10 18:06:44.904081",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 7bb9a52..762fa99 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -410,7 +410,8 @@
gle = party_gl_dict.copy()
gle.update({
"against_voucher_type": d.reference_doctype,
- "against_voucher": d.reference_name
+ "against_voucher": d.reference_name,
+ "due_date": d.due_date
})
allocated_amount_in_company_currency = flt(flt(d.allocated_amount) * flt(d.exchange_rate),
@@ -742,18 +743,53 @@
pe.allocate_payment_amount = 1
pe.letter_head = doc.get("letter_head")
- pe.append("references", {
- "reference_doctype": dt,
- "reference_name": dn,
- "due_date": doc.get("due_date"),
- "total_amount": grand_total,
- "outstanding_amount": outstanding_amount,
- "allocated_amount": outstanding_amount
- })
+ if doc.get("payment_schedule"):
+ for d in doc.get("payment_schedule"):
+ invoice_amount = d.payment_amount * doc.conversion_rate \
+ if party_account_currency == doc.company_currency else d.payment_amount
+ paid_amount = get_paid_amount(dt, dn, party_type, pe.party, party_account, d.due_date)
+ outstanding_amount = invoice_amount - paid_amount
+ pe.append("references", {
+ "reference_doctype": dt,
+ "reference_name": dn,
+ "due_date": d.due_date,
+ "total_amount": invoice_amount,
+ "outstanding_amount": outstanding_amount,
+ "allocated_amount": outstanding_amount
+ })
+ else:
+ pe.append("references", {
+ "reference_doctype": dt,
+ "reference_name": dn,
+ "due_date": doc.get("due_date"),
+ "total_amount": grand_total,
+ "outstanding_amount": outstanding_amount,
+ "allocated_amount": outstanding_amount
+ })
pe.setup_party_account_field()
pe.set_missing_values()
if party_account and bank:
pe.set_exchange_rate()
pe.set_amounts()
- return pe
\ No newline at end of file
+ return pe
+
+def get_paid_amount(dt, dn, party_type, party, account, due_date):
+ if party_type=="Customer":
+ dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
+ else:
+ dr_or_cr = "debit_in_account_currency - credit_in_account_currency"
+
+ paid_amount = frappe.db.sql("""
+ select ifnull(sum({dr_or_cr}), 0) as paid_amount
+ from `tabGL Entry`
+ where against_voucher_type = %s
+ and against_voucher = %s
+ and party_type = %s
+ and party = %s
+ and account = %s
+ and due_date = %s
+ and {dr_or_cr} > 0
+ """.format(dr_or_cr=dr_or_cr), (dt, dn, party_type, party, account, due_date))
+
+ return paid_amount[0][0] if paid_amount else 0
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_schedule/__init__.py b/erpnext/accounts/doctype/payment_schedule/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_schedule/__init__.py
diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
new file mode 100644
index 0000000..45a81b0
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
@@ -0,0 +1,197 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "",
+ "beta": 0,
+ "creation": "2017-08-10 15:38:00.080575",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "payment_term",
+ "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": "Payment Term",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Term",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "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": "Description",
+ "length": 0,
+ "no_copy": 0,
+ "options": "payment_term.description",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "due_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Due Date",
+ "length": 0,
+ "no_copy": 0,
+ "options": "payment_term.due_date",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "invoice_portion",
+ "fieldtype": "Percent",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Invoice Portion",
+ "length": 0,
+ "no_copy": 0,
+ "options": "payment_term.invoice_portion",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "payment_amount",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Payment Amount",
+ "length": 0,
+ "no_copy": 0,
+ "options": "currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2017-08-10 18:09:42.122027",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Schedule",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.py b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py
new file mode 100644
index 0000000..4174017
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+
+class PaymentSchedule(Document):
+ pass
diff --git a/erpnext/accounts/doctype/payment_term/__init__.py b/erpnext/accounts/doctype/payment_term/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_term/__init__.py
diff --git a/erpnext/accounts/doctype/payment_term/payment_term.js b/erpnext/accounts/doctype/payment_term/payment_term.js
new file mode 100644
index 0000000..054c2d1
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_term/payment_term.js
@@ -0,0 +1,2 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
diff --git a/erpnext/accounts/doctype/payment_term/payment_term.json b/erpnext/accounts/doctype/payment_term/payment_term.json
new file mode 100644
index 0000000..702319b
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_term/payment_term.json
@@ -0,0 +1,344 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:payment_term_name",
+ "beta": 0,
+ "creation": "2017-08-10 15:24:54.876365",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 1,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_term_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": "Payment Term Name",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 1,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "invoice_portion",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Invoice Portion",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 1,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "due_date_based_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": "Due Date Based On",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Day(s) after invoice date\nDay(s) after the end of the invoice month\nMonth(s) after the end of the invoice month",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 1,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:in_list(['Day(s) after invoice date', 'Day(s) after the end of the invoice month'], doc.due_date_based_on)",
+ "fieldname": "credit_days",
+ "fieldtype": "Int",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Credit Days",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.due_date_based_on=='Month(s) after the end of the invoice month'",
+ "fieldname": "credit_months",
+ "fieldtype": "Int",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Credit Months",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 1,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Description",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2017-08-10 16:26:03.581501",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Term",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_term/payment_term.py b/erpnext/accounts/doctype/payment_term/payment_term.py
new file mode 100644
index 0000000..5d4df05
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_term/payment_term.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+
+class PaymentTerm(Document):
+ pass
diff --git a/erpnext/accounts/doctype/payment_term/test_payment_term.js b/erpnext/accounts/doctype/payment_term/test_payment_term.js
new file mode 100644
index 0000000..b26e42a
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_term/test_payment_term.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Payment Term", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Payment Term
+ () => frappe.tests.make('Payment Term', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/accounts/doctype/payment_term/test_payment_term.py b/erpnext/accounts/doctype/payment_term/test_payment_term.py
new file mode 100644
index 0000000..d9baa59
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_term/test_payment_term.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+import unittest
+
+
+class TestPaymentTerm(unittest.TestCase):
+ pass
diff --git a/erpnext/accounts/doctype/payment_terms_template/__init__.py b/erpnext/accounts/doctype/payment_terms_template/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template/__init__.py
diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.js b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.js
new file mode 100644
index 0000000..558297f
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.js
@@ -0,0 +1,12 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Payment Terms Template', {
+ setup: function(frm) {
+ frm.add_fetch("payment_term", "description", "description");
+ frm.add_fetch("payment_term", "invoice_portion", "invoice_portion");
+ frm.add_fetch("payment_term", "due_date_based_on", "due_date_based_on");
+ frm.add_fetch("payment_term", "credit_days", "credit_days");
+ frm.add_fetch("payment_term", "credit_months", "credit_months");
+ }
+});
diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
new file mode 100644
index 0000000..0959658
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
@@ -0,0 +1,164 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:template_name",
+ "beta": 0,
+ "creation": "2017-08-10 15:34:28.058054",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "template_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": "Template Name",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "terms",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Terms",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Terms Template Detail",
+ "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,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2017-08-10 15:46:33.877884",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Terms Template",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
new file mode 100644
index 0000000..d2344d6
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+
+class PaymentTermsTemplate(Document):
+ pass
diff --git a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.js b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.js
new file mode 100644
index 0000000..494a0ed
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Payment Terms Template", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Payment Terms Template
+ () => frappe.tests.make('Payment Terms Template', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py
new file mode 100644
index 0000000..ec37066
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+import unittest
+
+
+class TestPaymentTermsTemplate(unittest.TestCase):
+ pass
diff --git a/erpnext/accounts/doctype/payment_terms_template_detail/__init__.py b/erpnext/accounts/doctype/payment_terms_template_detail/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template_detail/__init__.py
diff --git a/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.json b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.json
new file mode 100644
index 0000000..88babd5
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.json
@@ -0,0 +1,229 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "PTTD.#####",
+ "beta": 0,
+ "creation": "2017-08-10 15:34:09.409562",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "payment_term",
+ "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": "Payment Term",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Term",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "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": "Description",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "invoice_portion",
+ "fieldtype": "Percent",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Invoice Portion",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "due_date_based_on",
+ "fieldtype": "Select",
+ "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": "Due Date Based On",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Day(s) after invoice date\nDay(s) after the end of the invoice month\nMonth(s) after the end of the invoice month",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "depends_on": "eval:in_list(['Day(s) after invoice date', 'Day(s) after the end of the invoice month'], doc.due_date_based_on)",
+ "fieldname": "credit_days",
+ "fieldtype": "Int",
+ "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": "Credit Days",
+ "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,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.due_date_based_on=='Month(s) after the end of the invoice month'",
+ "fieldname": "credit_months",
+ "fieldtype": "Int",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Credit Months",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2017-08-10 16:27:31.401380",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Terms Template Detail",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py
new file mode 100644
index 0000000..54c0fda
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+
+class PaymentTermsTemplateDetail(Document):
+ pass
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 82a3d65..9ec69c3 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -252,6 +252,7 @@
self.assertEquals(so.items[0].rate, 100)
def test_pricing_rule_with_margin_and_discount(self):
+ frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10)
si = create_sales_invoice(do_not_save=True)
si.items[0].price_list_rate = 1000
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 8ea48f6..691ee45 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -2731,6 +2731,98 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
+ "columns": 0,
+ "fieldname": "payment_schedule_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": "Payment Terms Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_terms_template",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Terms Template",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Terms Template",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_schedule",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Schedule",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
"collapsible_depends_on": "terms",
"columns": 0,
"fieldname": "terms_section_break",
@@ -3797,7 +3889,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2017-07-19 13:53:48.673757",
+ "modified": "2017-08-16 17:10:30.248741",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 7ab7901..bf620ab 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -357,7 +357,27 @@
return gl_entries
def make_supplier_gl_entry(self, gl_entries):
- if self.grand_total:
+ if self.get("payment_schedule"):
+ for d in self.get("payment_schedule"):
+ payment_amount_in_company_currency = flt(d.payment_amount * self.conversion_rate,
+ d.precision("payment_amount"))
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": self.credit_to,
+ "party_type": "Supplier",
+ "party": self.supplier,
+ "due_date": d.due_date,
+ "against": self.against_expense_account,
+ "credit": payment_amount_in_company_currency,
+ "credit_in_account_currency": payment_amount_in_company_currency \
+ if self.party_account_currency==self.company_currency else d.payment_amount,
+ "against_voucher": self.return_against if cint(self.is_return) else self.name,
+ "against_voucher_type": self.doctype
+ }, self.party_account_currency)
+ )
+
+ elif self.grand_total:
# Didnot use base_grand_total to book rounding loss gle
grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate,
self.precision("grand_total"))
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 3454a2e..f189bf8 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -6,7 +6,7 @@
import unittest
import frappe, erpnext
import frappe.model
-from frappe.utils import cint, flt, today, nowdate
+from frappe.utils import cint, flt, today, nowdate, getdate, add_days
import frappe.defaults
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
test_records as pr_test_records
@@ -551,6 +551,38 @@
#check outstanding after advance cancellation
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
+ def test_gl_entry_based_on_payment_schedule(self):
+ pi = make_purchase_invoice(do_not_save=True, supplier="_Test Supplier P")
+ pi.append("payment_schedule", {
+ "due_date": add_days(nowdate(), 15),
+ "payment_amount": 100
+ })
+ pi.append("payment_schedule", {
+ "due_date": add_days(nowdate(), 45),
+ "payment_amount": 150
+ })
+
+ pi.save()
+ pi.submit()
+
+ gl_entries = frappe.db.sql("""select account, debit, credit, due_date
+ from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
+ order by account asc, debit asc""", pi.name, as_dict=1)
+ self.assertTrue(gl_entries)
+
+ expected_gl_entries = sorted([
+ [pi.credit_to, 0.0, 100.0, add_days(nowdate(), 15)],
+ [pi.credit_to, 0.0, 150.0, add_days(nowdate(), 45)],
+ ["_Test Account Cost for Goods Sold - _TC", 250.0, 0.0, None]
+ ])
+
+ for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
+ self.assertEquals(expected_gl_entries[i][0], gle.account)
+ self.assertEquals(expected_gl_entries[i][1], gle.debit)
+ self.assertEquals(expected_gl_entries[i][2], gle.credit)
+ self.assertEquals(getdate(expected_gl_entries[i][3]), getdate(gle.due_date))
+
+
def unlink_payment_on_cancel_of_invoice(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")
accounts_settings.unlink_payment_on_cancellation_of_invoice = enable
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 260c05e..0af1733 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -2689,6 +2689,101 @@
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
+ "collapsible": 1,
+ "collapsible_depends_on": "eval:(!doc.is_pos && !doc.is_return)",
+ "columns": 0,
+ "fieldname": "payment_schedule_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": "Payment Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:(!doc.is_pos && !doc.is_return)",
+ "fieldname": "payment_terms_template",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Terms Template",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Terms Template",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:(!doc.is_pos && !doc.is_return)",
+ "fieldname": "payment_schedule",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Schedule",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
@@ -2939,6 +3034,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "depends_on": "is_pos",
"fieldname": "base_change_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -2999,6 +3095,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "depends_on": "is_pos",
"fieldname": "change_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -3030,6 +3127,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "depends_on": "is_pos",
"fieldname": "account_for_change_amount",
"fieldtype": "Link",
"hidden": 0,
@@ -4688,7 +4786,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2017-07-07 13:05:37.469682",
+ "modified": "2017-08-10 18:02:44.286951",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 96d617e..6002590 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -629,7 +629,27 @@
return gl_entries
def make_customer_gl_entry(self, gl_entries):
- if self.grand_total:
+ if self.get("payment_schedule"):
+ for d in self.get("payment_schedule"):
+ payment_amount_in_company_currency = flt(d.payment_amount * self.conversion_rate,
+ d.precision("payment_amount"))
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": self.debit_to,
+ "party_type": "Customer",
+ "party": self.customer,
+ "due_date": d.due_date,
+ "against": self.against_income_account,
+ "debit": payment_amount_in_company_currency,
+ "debit_in_account_currency": payment_amount_in_company_currency \
+ if self.party_account_currency==self.company_currency else d.payment_amount,
+ "against_voucher": self.return_against if cint(self.is_return) else self.name,
+ "against_voucher_type": self.doctype
+ }, self.party_account_currency)
+ )
+
+ elif self.grand_total:
# Didnot use base_grand_total to book rounding loss gle
grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate,
self.precision("grand_total"))
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js
index 35b2558..f7a4488 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js
@@ -40,4 +40,3 @@
() => done()
]);
});
-
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index e0a453c..23007fb 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -4,7 +4,7 @@
import frappe
import unittest, copy
-from frappe.utils import nowdate, add_days, flt
+from frappe.utils import nowdate, add_days, flt, getdate
from frappe.model.dynamic_links import get_dynamic_link_map
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
@@ -1271,6 +1271,38 @@
})
si.insert()
return si
+
+ def test_gl_entry_based_on_payment_schedule(self):
+ si = create_sales_invoice(do_not_save=True, customer="_Test Customer P")
+ si.append("payment_schedule", {
+ "due_date": add_days(nowdate(), 15),
+ "payment_amount": 20
+ })
+ si.append("payment_schedule", {
+ "due_date": add_days(nowdate(), 45),
+ "payment_amount": 80
+ })
+
+ si.save()
+ si.submit()
+
+ gl_entries = frappe.db.sql("""select account, debit, credit, due_date
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ order by account asc, debit asc""", si.name, as_dict=1)
+ self.assertTrue(gl_entries)
+
+ expected_gl_entries = sorted([
+ [si.debit_to, 20.0, 0.0, add_days(nowdate(), 15)],
+ [si.debit_to, 80.0, 0.0, add_days(nowdate(), 45)],
+ ["Sales - _TC", 0.0, 100.0, None]
+ ])
+
+ for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
+ self.assertEquals(expected_gl_entries[i][0], gle.account)
+ self.assertEquals(expected_gl_entries[i][1], gle.debit)
+ self.assertEquals(expected_gl_entries[i][2], gle.credit)
+ self.assertEquals(getdate(expected_gl_entries[i][3]), getdate(gle.due_date))
+
def test_company_monthly_sales(self):
existing_current_month_sales = frappe.db.get_value("Company", "_Test Company", "total_monthly_sales")
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index ceae61c..45d2ef2 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe, erpnext
-from frappe.utils import flt, cstr, cint
+from frappe.utils import flt, cstr, cint, getdate
from frappe import _
from frappe.model.meta import get_field_precision
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
@@ -75,7 +75,8 @@
and cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
and cstr(e.get('against_voucher_type')) == cstr(gle.get('against_voucher_type')) \
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')) \
- and cstr(e.get('project')) == cstr(gle.get('project')):
+ and cstr(e.get('project')) == cstr(gle.get('project')) \
+ and getdate(e.get('due_date')) == getdate(gle.get('due_date')):
return e
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 9906893..b72a669 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -113,7 +113,7 @@
row += [self.get_party_name(gle.party_type, gle.party)]
# get due date
- due_date = voucher_details.get(gle.voucher_no, {}).get("due_date", "")
+ due_date = gle.due_date or voucher_details.get(gle.voucher_no, {}).get("due_date", "")
row += [gle.voucher_type, gle.voucher_no, due_date]
@@ -162,8 +162,7 @@
def get_entries_till(self, report_date, party_type):
# returns a generator
- return (e for e in self.get_gl_entries(party_type)
- if getdate(e.posting_date) <= report_date)
+ return (e for e in self.get_gl_entries(party_type) if getdate(e.posting_date) <= report_date)
def is_receivable_or_payable(self, gle, dr_or_cr, future_vouchers):
return (
@@ -189,7 +188,8 @@
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:
+ if getdate(e.posting_date) <= report_date and e.name!=gle.name \
+ and (not gle.due_date or getdate(e.due_date) == getdate(gle.due_date)):
amount = flt(e.get(reverse_dr_or_cr)) - flt(e.get(dr_or_cr))
if e.voucher_no not in return_entries:
payment_amount += amount
@@ -251,11 +251,11 @@
select_fields = "sum(debit) as debit, sum(credit) as credit"
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
- voucher_type, voucher_no, against_voucher_type, against_voucher,
+ voucher_type, voucher_no, against_voucher_type, against_voucher, due_date,
account_currency, remarks, {0}
from `tabGL Entry`
where docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
- group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
+ group by voucher_type, voucher_no, against_voucher_type, against_voucher, party, due_date
order by posting_date, party"""
.format(select_fields, conditions), values, as_dict=True)
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 50530f5..6d6aced 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -583,7 +583,7 @@
invoice = 'Sales Invoice' if party_type == 'Customer' else 'Purchase Invoice'
invoice_list = frappe.db.sql("""
select
- voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount,
+ voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount, due_date,
(
case when (voucher_type = 'Sales Invoice' or voucher_type = 'Purchase Invoice')
then (select due_date from `tab{invoice}` where name = voucher_no)
@@ -597,6 +597,7 @@
and payment_gl_entry.party_type = invoice_gl_entry.party_type
and payment_gl_entry.party = invoice_gl_entry.party
and payment_gl_entry.account = invoice_gl_entry.account
+ and payment_gl_entry.due_date = invoice_gl_entry.due_date
and {payment_dr_or_cr} > 0
) as payment_amount
from
@@ -608,9 +609,9 @@
and ((voucher_type = 'Journal Entry'
and (against_voucher = '' or against_voucher is null))
or (voucher_type not in ('Journal Entry', 'Payment Entry')))
- group by voucher_type, voucher_no
+ group by voucher_type, voucher_no, due_date
having (invoice_amount - payment_amount) > 0.005
- order by posting_date, name""".format(
+ order by posting_date, name, due_date""".format(
dr_or_cr = dr_or_cr,
invoice = invoice,
payment_dr_or_cr = payment_dr_or_cr,
@@ -622,6 +623,8 @@
}, as_dict=True)
for d in invoice_list:
+ due_date = d.due_date or (frappe.db.get_value(d.voucher_type, d.voucher_no,
+ "posting_date" if party_type=="Employee" else "due_date"))
outstanding_invoices.append(frappe._dict({
'voucher_no': d.voucher_no,
'voucher_type': d.voucher_type,
@@ -630,8 +633,7 @@
'invoice_amount': flt(d.invoice_amount),
'payment_amount': flt(d.payment_amount),
'outstanding_amount': flt(d.invoice_amount - d.payment_amount, precision),
- 'due_date': frappe.db.get_value(d.voucher_type, d.voucher_no,
- "posting_date" if party_type=="Employee" else "due_date"),
+ 'due_date': due_date
}))
outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k['due_date'] or getdate(nowdate()))
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 09c987f..16b12ea 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -2293,6 +2293,98 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
+ "columns": 0,
+ "fieldname": "payment_schedule_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": "Payment Terms Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_terms_template",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Terms Template",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Terms Template",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_schedule",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Schedule",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
"collapsible_depends_on": "terms",
"columns": 0,
"fieldname": "terms_section_break",
@@ -3335,7 +3427,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-07-19 14:03:51.838328",
+ "modified": "2017-08-16 16:57:51.320375",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/buying/doctype/supplier/test_records.json b/erpnext/buying/doctype/supplier/test_records.json
index d2b3995..fa728be 100644
--- a/erpnext/buying/doctype/supplier/test_records.json
+++ b/erpnext/buying/doctype/supplier/test_records.json
@@ -1,6 +1,12 @@
[
{
"doctype": "Supplier",
+ "supplier_name": "_Test Supplier P",
+ "supplier_type": "_Test Supplier Type",
+ "credit_days_based_on": "Fixed Days"
+ },
+ {
+ "doctype": "Supplier",
"supplier_name": "_Test Supplier with Country",
"supplier_type": "_Test Supplier Type",
"country": "Greece"
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index b24e047..25ec863 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _, throw
-from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate
+from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate, add_days, add_months, get_last_day
from erpnext.setup.utils import get_exchange_rate
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase
@@ -44,6 +44,9 @@
self.set_total_in_words()
if self.doctype in ("Sales Invoice", "Purchase Invoice") and not self.is_return:
+ if self.get("payment_schedule"):
+ self.set_due_date()
+ self.validate_payment_schedule()
self.validate_due_date()
self.validate_advance_entries()
@@ -614,6 +617,35 @@
for item in duplicate_list:
self.remove(item)
+ def _set_payment_schedule(self):
+ if not self.get("payment_schedule"):
+ if self.due_date:
+ self.append("payment_schedule", {
+ "due_date": self.due_date,
+ "invoice_portion": 100,
+ "payment_amount": self.grand_total
+ })
+ else:
+ self.due_date = max([d.due_date for d in self.get("payment_schedule")])
+
+ def set_due_date(self):
+ self.due_date = max([d.due_date for d in self.get("payment_schedule")])
+
+ def validate_payment_schedule(self):
+ if self.due_date and getdate(self.due_date) < getdate(self.posting_date):
+ frappe.throw(_("Due Date cannot be before posting date"))
+
+ total = 0
+ for d in self.get("payment_schedule"):
+ if getdate(d.due_date) < getdate(self.posting_date):
+ frappe.throw(_("Row {0}: Due Date cannot be before posting date").format(d.idx))
+
+ total += flt(d.payment_amount)
+
+ if total != self.grand_total:
+ frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand Total"))
+
+
@frappe.whitelist()
def get_tax_rate(account_head):
return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
@@ -782,4 +814,43 @@
where due_date < CURDATE() and docstatus = 1 and outstanding_amount > 0""")
frappe.db.sql(""" update `tabPurchase Invoice` set status = 'Overdue'
- where due_date < CURDATE() and docstatus = 1 and outstanding_amount > 0""")
\ No newline at end of file
+ where due_date < CURDATE() and docstatus = 1 and outstanding_amount > 0""")
+
+@frappe.whitelist()
+def get_payment_terms(terms_template, posting_date=None, grand_total=None):
+ if not terms_template:
+ return
+
+ terms_doc = frappe.get_doc("Payment Terms Template", terms_template)
+
+ schedule = []
+ for d in terms_doc.get("terms"):
+ term_details = get_payment_term_details(d, posting_date, grand_total)
+ schedule.append(term_details)
+
+ return schedule
+
+@frappe.whitelist()
+def get_payment_term_details(term, posting_date=None, grand_total=None):
+ term_details = frappe._dict()
+ if isinstance(term, unicode):
+ term = frappe.get_doc("Payment Term", term)
+ else:
+ term_details.payment_term = term.payment_term
+ term_details.description = term.description
+ term_details.invoice_portion = term.invoice_portion
+ term_details.payment_amount = flt(term.invoice_portion) * flt(grand_total) / 100
+ if posting_date:
+ term_details.due_date = get_due_date(posting_date, term)
+ return term_details
+
+def get_due_date(posting_date, term):
+ due_date = None
+ if term.due_date_based_on == "Day(s) after invoice date":
+ due_date = add_days(posting_date, term.credit_days)
+ elif term.due_date_based_on == "Day(s) after the end of the invoice month":
+ due_date = add_days(get_last_day(posting_date), term.credit_days)
+ elif term.due_date_based_on == "Month(s) after the end of the invoice month":
+ due_date = add_months(get_last_day(posting_date), term.credit_months)
+
+ return due_date
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 3a8ddb5..f72a929 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1100,6 +1100,46 @@
}
}
},
+
+ payment_terms_template: function() {
+ var me = this;
+ if(this.frm.doc.payment_terms_template) {
+ frappe.call({
+ method: "erpnext.controllers.accounts_controller.get_payment_terms",
+ args: {
+ terms_template: this.frm.doc.payment_terms_template,
+ posting_date: this.frm.doc.posting_date || this.frm.doc.transaction_date,
+ grand_total: this.frm.doc.grand_total
+ },
+ callback: function(r) {
+ if(r.message && !r.exc) {
+ me.frm.set_value("payment_schedule", r.message);
+ }
+ }
+ })
+ }
+ },
+
+ payment_term: function(doc, cdt, cdn) {
+ var row = locals[cdt][cdn];
+ if(row.payment_term) {
+ frappe.call({
+ method: "erpnext.controllers.accounts_controller.get_payment_term_details",
+ args: {
+ term: row.payment_term,
+ posting_date: this.frm.doc.posting_date || this.frm.doc.transaction_date,
+ grand_total: this.frm.doc.grand_total
+ },
+ callback: function(r) {
+ if(r.message && !r.exc) {
+ for (var d in r.message) {
+ frappe.model.set_value(cdt, cdn, d, r.message[d]);
+ }
+ }
+ }
+ })
+ }
+ }
});
erpnext.show_serial_batch_selector = function(frm, d) {
diff --git a/erpnext/selling/doctype/customer/test_records.json b/erpnext/selling/doctype/customer/test_records.json
index 94f14ed..43d6beb 100644
--- a/erpnext/selling/doctype/customer/test_records.json
+++ b/erpnext/selling/doctype/customer/test_records.json
@@ -1,6 +1,14 @@
[
{
"customer_group": "_Test Customer Group",
+ "customer_name": "_Test Customer P",
+ "customer_type": "Individual",
+ "doctype": "Customer",
+ "territory": "_Test Territory",
+ "credit_days_based_on": "Fixed Days"
+ },
+ {
+ "customer_group": "_Test Customer Group",
"customer_name": "_Test Customer",
"customer_type": "Individual",
"doctype": "Customer",
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 0afc5ca..bd9814b 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -2094,6 +2094,100 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
+ "collapsible_depends_on": "eval:!doc.__islocal",
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "payment_schedule_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": "Payment Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_terms_template",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Terms Template",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Terms Template",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_schedule",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Schedule",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
"collapsible_depends_on": "terms",
"columns": 0,
"fieldname": "terms_section_break",
@@ -2633,7 +2727,7 @@
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
- "modified": "2017-08-09 06:35:48.691648",
+ "modified": "2017-08-16 15:31:23.079739",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index b69b3fd..94d33f0 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -2255,10 +2255,9 @@
"label": "Packed Items",
"length": 0,
"no_copy": 0,
- "oldfieldname": "packing_details",
- "oldfieldtype": "Table",
"options": "Packed Item",
"permlevel": 0,
+ "precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
@@ -2274,6 +2273,99 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
+ "collapsible_depends_on": "eval:!doc.__islocal||doc.payment_schedule",
+ "columns": 0,
+ "fieldname": "payment_schedule_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": "Payment Terms Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_terms_template",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Terms Template",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Terms Template",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "payment_schedule",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payment Schedule",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Schedule",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
"collapsible_depends_on": "terms",
"columns": 0,
"fieldname": "terms_section_break",
@@ -3659,7 +3751,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-08-07 21:27:10.073581",
+ "modified": "2017-08-16 16:00:08.404180",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",