diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index 8566eadad4..8a9a7c58d2 100644
--- a/erpnext/accounts/desk_page/accounting/accounting.json
+++ b/erpnext/accounts/desk_page/accounting/accounting.json
@@ -47,8 +47,8 @@
},
{
"hidden": 0,
- "label": "Banking and Payments",
- "links": "[\n {\n \"description\": \"Match non-linked Invoices and Payments.\",\n \"label\": \"Match Payments with Invoices\",\n \"name\": \"Payment Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update bank payment dates with journals.\",\n \"label\": \"Update Bank Transaction Dates\",\n \"name\": \"Bank Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Invoice Discounting\",\n \"name\": \"Invoice Discounting\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Reconciliation Statement\",\n \"name\": \"Bank Reconciliation Statement\",\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Bank Reconciliation\",\n \"name\": \"bank-reconciliation\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Clearance Summary\",\n \"name\": \"Bank Clearance Summary\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Bank Guarantee\",\n \"name\": \"Bank Guarantee\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup cheque dimensions for printing\",\n \"label\": \"Cheque Print Template\",\n \"name\": \"Cheque Print Template\",\n \"type\": \"doctype\"\n }\n]"
+ "links": "[\n {\n \"description\": \"Match non-linked Invoices and Payments.\",\n \"label\": \"Match Payments with Invoices\",\n \"name\": \"Payment Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update bank payment dates with journals.\",\n \"label\": \"Update Bank Clearance Dates\",\n \"name\": \"Bank Clearance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Invoice Discounting\",\n \"name\": \"Invoice Discounting\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Reconciliation Statement\",\n \"name\": \"Bank Reconciliation Statement\",\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Bank Reconciliation\",\n \"name\": \"bank-reconciliation\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Clearance Summary\",\n \"name\": \"Bank Clearance Summary\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Bank Guarantee\",\n \"name\": \"Bank Guarantee\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup cheque dimensions for printing\",\n \"label\": \"Cheque Print Template\",\n \"name\": \"Cheque Print Template\",\n \"type\": \"doctype\"\n }\n]",
+ "title": "Banking and Payments"
},
{
"hidden": 0,
diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py
index f48d6dfc95..df6cedd7cf 100644
--- a/erpnext/accounts/doctype/accounting_period/accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py
@@ -42,7 +42,7 @@ class AccountingPeriod(Document):
def get_doctypes_for_closing(self):
docs_for_closing = []
doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", \
- "Bank Reconciliation", "Asset", "Stock Entry"]
+ "Bank Clearance", "Asset", "Stock Entry"]
closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
for closed_doctype in closed_doctypes:
docs_for_closing.append(closed_doctype)
diff --git a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json
index f85bc52713..e3f2d59c06 100644
--- a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json
+++ b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json
@@ -1,74 +1,32 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-04-16 21:50:05.860195",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "creation": "2018-04-16 21:50:05.860195",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "company"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Company",
+ "options": "Company",
+ "reqd": 1
}
- ],
- "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": "2018-04-20 14:00:46.014502",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Allowed To Transact With",
- "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
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-01 12:32:34.044911",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Allowed To Transact With",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation/README.md b/erpnext/accounts/doctype/bank_clearance/README.md
similarity index 100%
rename from erpnext/accounts/doctype/bank_reconciliation/README.md
rename to erpnext/accounts/doctype/bank_clearance/README.md
diff --git a/erpnext/education/doctype/video/__init__.py b/erpnext/accounts/doctype/bank_clearance/__init__.py
similarity index 100%
rename from erpnext/education/doctype/video/__init__.py
rename to erpnext/accounts/doctype/bank_clearance/__init__.py
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js b/erpnext/accounts/doctype/bank_clearance/bank_clearance.js
similarity index 97%
rename from erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js
rename to erpnext/accounts/doctype/bank_clearance/bank_clearance.js
index 19fadbf6de..ba3f2face6 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-frappe.ui.form.on("Bank Reconciliation", {
+frappe.ui.form.on("Bank Clearance", {
setup: function(frm) {
frm.add_fetch("account", "account_currency", "account_currency");
},
diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.json b/erpnext/accounts/doctype/bank_clearance/bank_clearance.json
new file mode 100644
index 0000000000..a436d1effb
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.json
@@ -0,0 +1,130 @@
+{
+ "allow_copy": 1,
+ "creation": "2013-01-10 16:34:05",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+ "account",
+ "account_currency",
+ "from_date",
+ "to_date",
+ "column_break_5",
+ "bank_account",
+ "include_reconciled_entries",
+ "include_pos_transactions",
+ "get_payment_entries",
+ "section_break_10",
+ "payment_entries",
+ "update_clearance_date",
+ "total_amount"
+ ],
+ "fields": [
+ {
+ "fetch_from": "bank_account.account",
+ "fetch_if_empty": 1,
+ "fieldname": "account",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Account",
+ "options": "Account",
+ "reqd": 1
+ },
+ {
+ "fieldname": "account_currency",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Account Currency",
+ "options": "Currency",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "from_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "From Date",
+ "reqd": 1
+ },
+ {
+ "fieldname": "to_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "To Date",
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break"
+ },
+ {
+ "description": "Select the Bank Account to reconcile.",
+ "fieldname": "bank_account",
+ "fieldtype": "Link",
+ "label": "Bank Account",
+ "options": "Bank Account"
+ },
+ {
+ "default": "0",
+ "fieldname": "include_reconciled_entries",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Include Reconciled Entries"
+ },
+ {
+ "default": "0",
+ "fieldname": "include_pos_transactions",
+ "fieldtype": "Check",
+ "label": "Include POS Transactions"
+ },
+ {
+ "fieldname": "get_payment_entries",
+ "fieldtype": "Button",
+ "label": "Get Payment Entries"
+ },
+ {
+ "fieldname": "section_break_10",
+ "fieldtype": "Section Break"
+ },
+ {
+ "allow_bulk_edit": 1,
+ "fieldname": "payment_entries",
+ "fieldtype": "Table",
+ "label": "Payment Entries",
+ "options": "Bank Clearance Detail"
+ },
+ {
+ "fieldname": "update_clearance_date",
+ "fieldtype": "Button",
+ "label": "Update Clearance Date"
+ },
+ {
+ "fieldname": "total_amount",
+ "fieldtype": "Currency",
+ "label": "Total Amount",
+ "options": "account_currency",
+ "read_only": 1
+ }
+ ],
+ "hide_toolbar": 1,
+ "icon": "fa fa-check",
+ "idx": 1,
+ "issingle": 1,
+ "modified": "2020-04-06 16:12:06.628008",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank Clearance",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "read": 1,
+ "role": "Accounts User",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
similarity index 99%
rename from erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
rename to erpnext/accounts/doctype/bank_clearance/bank_clearance.py
index 48fd154a4d..6fec3ab368 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
@@ -11,7 +11,7 @@ form_grid_templates = {
"journal_entries": "templates/form_grid/bank_reconciliation_grid.html"
}
-class BankReconciliation(Document):
+class BankClearance(Document):
def get_payment_entries(self):
if not (self.from_date and self.to_date):
frappe.throw(_("From Date and To Date are Mandatory"))
diff --git a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py
new file mode 100644
index 0000000000..833abde5ce
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestBankClearance(unittest.TestCase):
+ pass
diff --git a/erpnext/accounts/doctype/bank_clearance_detail/README.md b/erpnext/accounts/doctype/bank_clearance_detail/README.md
new file mode 100644
index 0000000000..ee83a44765
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_clearance_detail/README.md
@@ -0,0 +1 @@
+Detail of transaction for parent Bank Clearance.
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation/__init__.py b/erpnext/accounts/doctype/bank_clearance_detail/__init__.py
similarity index 100%
rename from erpnext/accounts/doctype/bank_reconciliation/__init__.py
rename to erpnext/accounts/doctype/bank_clearance_detail/__init__.py
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.json
similarity index 99%
rename from erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json
rename to erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.json
index 183068c3ae..04988bf66d 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json
+++ b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.json
@@ -326,7 +326,7 @@
"modified": "2019-01-07 16:52:07.174687",
"modified_by": "Administrator",
"module": "Accounts",
- "name": "Bank Reconciliation Detail",
+ "name": "Bank Clearance Detail",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.py b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py
similarity index 84%
rename from erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.py
rename to erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py
index 990b2a640f..ecc536733f 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.py
+++ b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py
@@ -5,5 +5,5 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
-class BankReconciliationDetail(Document):
+class BankClearanceDetail(Document):
pass
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json
deleted file mode 100644
index b85ef3e9c4..0000000000
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json
+++ /dev/null
@@ -1,484 +0,0 @@
-{
- "allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2013-01-10 16:34:05",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 0,
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "bank_account.account",
- "fetch_if_empty": 1,
- "fieldname": "account",
- "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": "Account",
- "length": 0,
- "no_copy": 0,
- "options": "Account",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "account_currency",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Account Currency",
- "length": 0,
- "no_copy": 0,
- "options": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "from_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": "From Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "to_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": "To Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_5",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Select the Bank Account to reconcile.",
- "fetch_if_empty": 0,
- "fieldname": "bank_account",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Bank Account",
- "length": 0,
- "no_copy": 0,
- "options": "Bank Account",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "include_reconciled_entries",
- "fieldtype": "Check",
- "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": "Include Reconciled Entries",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "include_pos_transactions",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Include POS Transactions",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "get_payment_entries",
- "fieldtype": "Button",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Get Payment Entries",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_10",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 1,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "payment_entries",
- "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 Entries",
- "length": 0,
- "no_copy": 0,
- "options": "Bank Reconciliation Detail",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "update_clearance_date",
- "fieldtype": "Button",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Update Clearance Date",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "total_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Total Amount",
- "length": 0,
- "no_copy": 0,
- "options": "account_currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_toolbar": 1,
- "icon": "fa fa-check",
- "idx": 1,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 1,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2020-01-22 00:00:00.000000",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Bank Reconciliation",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 1,
- "show_name_in_global_search": 0,
- "sort_order": "ASC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
-}
diff --git a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js b/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js
deleted file mode 100644
index f52f6fb431..0000000000
--- a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js
+++ /dev/null
@@ -1,22 +0,0 @@
-QUnit.module('Account');
-
-QUnit.test("test Bank Reconciliation", function(assert) {
- assert.expect(0);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.set_route('Form', 'Bank Reconciliation'),
- () => cur_frm.set_value('bank_account','Cash - FT'),
- () => frappe.click_button('Get Payment Entries'),
- () => {
- for(var i=0;i<=cur_frm.doc.payment_entries.length-1;i++){
- cur_frm.doc.payment_entries[i].clearance_date = frappe.datetime.add_days(frappe.datetime.now_date(), 2);
- }
- },
- () => {cur_frm.refresh_fields('payment_entries');},
- () => frappe.click_button('Update Clearance Date'),
- () => frappe.timeout(0.5),
- () => frappe.click_button('Close'),
- () => done()
- ]);
-});
-
diff --git a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py
deleted file mode 100644
index 932fb3384c..0000000000
--- a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-from __future__ import unicode_literals
-import unittest
-
-class TestBankReconciliation(unittest.TestCase):
- pass
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/README.md b/erpnext/accounts/doctype/bank_reconciliation_detail/README.md
deleted file mode 100644
index 07d0731ed2..0000000000
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Detail of transaction for parent Bank Reconciliation.
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/__init__.py b/erpnext/accounts/doctype/bank_reconciliation_detail/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
index 9c19791d29..61c48c7499 100644
--- a/erpnext/accounts/doctype/budget/test_budget.py
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
import unittest
-from frappe.utils import nowdate
+from frappe.utils import nowdate, now_datetime
from erpnext.accounts.utils import get_fiscal_year
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError
@@ -13,27 +13,28 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ
class TestBudget(unittest.TestCase):
def test_monthly_budget_crossed_ignore(self):
- set_total_expense_zero("2013-02-28", "cost_center")
+ set_total_expense_zero(nowdate(), "cost_center")
budget = make_budget(budget_against="Cost Center")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
+ "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
budget.cancel()
+ jv.cancel()
def test_monthly_budget_crossed_stop1(self):
- set_total_expense_zero("2013-02-28", "cost_center")
+ set_total_expense_zero(nowdate(), "cost_center")
budget = make_budget(budget_against="Cost Center")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28")
+ "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate())
self.assertRaises(BudgetError, jv.submit)
@@ -41,14 +42,14 @@ class TestBudget(unittest.TestCase):
budget.cancel()
def test_exception_approver_role(self):
- set_total_expense_zero("2013-02-28", "cost_center")
+ set_total_expense_zero(nowdate(), "cost_center")
budget = make_budget(budget_against="Cost Center")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-03-02")
+ "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate())
self.assertRaises(BudgetError, jv.submit)
@@ -112,16 +113,17 @@ class TestBudget(unittest.TestCase):
budget.load_from_db()
budget.cancel()
+ po.cancel()
def test_monthly_budget_crossed_stop2(self):
- set_total_expense_zero("2013-02-28", "project")
+ set_total_expense_zero(nowdate(), "project")
budget = make_budget(budget_against="Project")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-02-28")
+ "_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
self.assertRaises(BudgetError, jv.submit)
@@ -129,86 +131,76 @@ class TestBudget(unittest.TestCase):
budget.cancel()
def test_yearly_budget_crossed_stop1(self):
- set_total_expense_zero("2013-02-28", "cost_center")
+ set_total_expense_zero(nowdate(), "cost_center")
budget = make_budget(budget_against="Cost Center")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 150000, "_Test Cost Center - _TC", posting_date="2013-03-28")
+ "_Test Bank - _TC", 250000, "_Test Cost Center - _TC", posting_date=nowdate())
self.assertRaises(BudgetError, jv.submit)
budget.cancel()
def test_yearly_budget_crossed_stop2(self):
- set_total_expense_zero("2013-02-28", "project")
+ set_total_expense_zero(nowdate(), "project")
budget = make_budget(budget_against="Project")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 150000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-03-28")
+ "_Test Bank - _TC", 250000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
self.assertRaises(BudgetError, jv.submit)
budget.cancel()
def test_monthly_budget_on_cancellation1(self):
- set_total_expense_zero("2013-02-28", "cost_center")
+ set_total_expense_zero(nowdate(), "cost_center")
budget = make_budget(budget_against="Cost Center")
- jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
+ for i in range(now_datetime().month):
+ jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
+ "_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
- self.assertTrue(frappe.db.get_value("GL Entry",
- {"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
-
- jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
-
- self.assertTrue(frappe.db.get_value("GL Entry",
- {"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
+ self.assertTrue(frappe.db.get_value("GL Entry",
+ {"voucher_type": "Journal Entry", "voucher_no": jv.name}))
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
- self.assertRaises(BudgetError, jv1.cancel)
+ self.assertRaises(BudgetError, jv.cancel)
budget.load_from_db()
budget.cancel()
def test_monthly_budget_on_cancellation2(self):
- set_total_expense_zero("2013-02-28", "project")
+ set_total_expense_zero(nowdate(), "project")
budget = make_budget(budget_against="Project")
- jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True, project="_Test Project")
+ for i in range(now_datetime().month):
+ jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
+ "_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True, project="_Test Project")
- self.assertTrue(frappe.db.get_value("GL Entry",
- {"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
-
- jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True, project="_Test Project")
-
- self.assertTrue(frappe.db.get_value("GL Entry",
- {"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
+ self.assertTrue(frappe.db.get_value("GL Entry",
+ {"voucher_type": "Journal Entry", "voucher_no": jv.name}))
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
- self.assertRaises(BudgetError, jv1.cancel)
+ self.assertRaises(BudgetError, jv.cancel)
budget.load_from_db()
budget.cancel()
def test_monthly_budget_against_group_cost_center(self):
- set_total_expense_zero("2013-02-28", "cost_center")
- set_total_expense_zero("2013-02-28", "cost_center", "_Test Cost Center 2 - _TC")
+ set_total_expense_zero(nowdate(), "cost_center")
+ set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC")
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 40000, "_Test Cost Center 2 - _TC", posting_date="2013-02-28")
+ "_Test Bank - _TC", 40000, "_Test Cost Center 2 - _TC", posting_date=nowdate())
self.assertRaises(BudgetError, jv.submit)
@@ -231,7 +223,7 @@ class TestBudget(unittest.TestCase):
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", 40000, cost_center, posting_date="2013-02-28")
+ "_Test Bank - _TC", 40000, cost_center, posting_date=nowdate())
self.assertRaises(BudgetError, jv.submit)
@@ -246,12 +238,14 @@ def set_total_expense_zero(posting_date, budget_against_field=None, budget_again
else:
budget_against = budget_against_CC or "_Test Cost Center - _TC"
+ fiscal_year = get_fiscal_year(nowdate())[0]
+
args = frappe._dict({
"account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"monthly_end_date": posting_date,
"company": "_Test Company",
- "fiscal_year": "_Test Fiscal Year 2013",
+ "fiscal_year": fiscal_year,
"budget_against_field": budget_against_field,
})
@@ -263,10 +257,10 @@ def set_total_expense_zero(posting_date, budget_against_field=None, budget_again
if existing_expense:
if budget_against_field == "cost_center":
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
+ "_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
elif budget_against_field == "project":
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
- "_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True, project="_Test Project", posting_date="2013-02-28")
+ "_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True, project="_Test Project", posting_date=nowdate())
def make_budget(**args):
args = frappe._dict(args)
@@ -274,10 +268,13 @@ def make_budget(**args):
budget_against=args.budget_against
cost_center=args.cost_center
+ fiscal_year = get_fiscal_year(nowdate())[0]
+
if budget_against == "Project":
- budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Project/_Test Fiscal Year 2013%")})
+ project_name = "{0}%".format("_Test Project/" + fiscal_year)
+ budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", project_name)})
else:
- cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/_Test Fiscal Year 2013")
+ cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", cost_center_name)})
for d in budget_list:
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
@@ -290,8 +287,10 @@ def make_budget(**args):
else:
budget.cost_center =cost_center or "_Test Cost Center - _TC"
+ monthly_distribution = frappe.get_doc("Monthly Distribution", "_Test Distribution")
+ monthly_distribution.fiscal_year = fiscal_year
- budget.fiscal_year = "_Test Fiscal Year 2013"
+ budget.fiscal_year = fiscal_year
budget.monthly_distribution = "_Test Distribution"
budget.company = "_Test Company"
budget.applicable_on_booking_actual_expenses = 1
@@ -300,7 +299,7 @@ def make_budget(**args):
budget.budget_against = budget_against
budget.append("accounts", {
"account": "_Test Account Cost for Goods Sold - _TC",
- "budget_amount": 100000
+ "budget_amount": 200000
})
if args.applicable_on_material_request:
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.js b/erpnext/accounts/doctype/cost_center/cost_center.js
index 96ec57dcb0..9e2f6eed3b 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.js
+++ b/erpnext/accounts/doctype/cost_center/cost_center.js
@@ -18,7 +18,7 @@ frappe.ui.form.on('Cost Center', {
},
refresh: function(frm) {
if (!frm.is_new()) {
- frm.add_custom_button(__('Update Cost Center Number'), function () {
+ frm.add_custom_button(__('Update Cost Center Name / Number'), function () {
frm.trigger("update_cost_center_number");
});
}
@@ -47,35 +47,45 @@ frappe.ui.form.on('Cost Center', {
},
update_cost_center_number: function(frm) {
var d = new frappe.ui.Dialog({
- title: __('Update Cost Center Number'),
+ title: __('Update Cost Center Name / Number'),
fields: [
{
- "label": 'Cost Center Number',
+ "label": "Cost Center Name",
+ "fieldname": "cost_center_name",
+ "fieldtype": "Data",
+ "reqd": 1,
+ "default": frm.doc.cost_center_name
+ },
+ {
+ "label": "Cost Center Number",
"fieldname": "cost_center_number",
"fieldtype": "Data",
- "reqd": 1
+ "reqd": 1,
+ "default": frm.doc.cost_center_number
}
],
primary_action: function() {
var data = d.get_values();
- if(data.cost_center_number === frm.doc.cost_center_number) {
+ if(data.cost_center_name === frm.doc.cost_center_name && data.cost_center_number === frm.doc.cost_center_number) {
d.hide();
return;
}
+ frappe.dom.freeze();
frappe.call({
- method: "erpnext.accounts.utils.update_number_field",
+ method: "erpnext.accounts.utils.update_cost_center",
args: {
- doctype_name: frm.doc.doctype,
- name: frm.doc.name,
- field_name: d.fields[0].fieldname,
- number_value: data.cost_center_number,
+ docname: frm.doc.name,
+ cost_center_name: data.cost_center_name,
+ cost_center_number: data.cost_center_number,
company: frm.doc.company
},
callback: function(r) {
+ frappe.dom.unfreeze();
if(!r.exc) {
if(r.message) {
frappe.set_route("Form", "Cost Center", r.message);
} else {
+ me.frm.set_value("cost_center_name", data.cost_center_name);
me.frm.set_value("cost_center_number", data.cost_center_number);
}
d.hide();
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.json b/erpnext/accounts/doctype/cost_center/cost_center.json
index 99b89d1516..5013c92a32 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.json
+++ b/erpnext/accounts/doctype/cost_center/cost_center.json
@@ -2,7 +2,6 @@
"actions": [],
"allow_copy": 1,
"allow_import": 1,
- "allow_rename": 1,
"creation": "2013-01-23 19:57:17",
"description": "Track separate Income and Expense for product verticals or divisions.",
"doctype": "DocType",
@@ -126,7 +125,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
- "modified": "2020-03-18 17:59:04.321637",
+ "modified": "2020-04-29 16:09:30.025214",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json
index 2214811d8b..0d75329039 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.json
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json
@@ -30,7 +30,8 @@
"company",
"finance_book",
"to_rename",
- "due_date"
+ "due_date",
+ "is_cancelled"
],
"fields": [
{
@@ -245,12 +246,18 @@
"fieldname": "due_date",
"fieldtype": "Date",
"label": "Due Date"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_cancelled",
+ "fieldtype": "Check",
+ "label": "Is Cancelled"
}
],
"icon": "fa fa-list",
"idx": 1,
"in_create": 1,
- "modified": "2020-03-28 16:22:33.766994",
+ "modified": "2020-04-07 16:22:33.766994",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 14d0531271..efab5801e8 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -30,23 +30,20 @@ class GLEntry(Document):
self.pl_must_have_cost_center()
self.validate_cost_center()
- if not self.flags.from_repost:
- self.check_pl_account()
- self.validate_party()
- self.validate_currency()
+ self.check_pl_account()
+ self.validate_party()
+ self.validate_currency()
- def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False):
- if not from_repost:
- self.validate_account_details(adv_adj)
- self.validate_dimensions_for_pl_and_bs()
- check_freezing_date(self.posting_date, adv_adj)
+ def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
+ self.validate_account_details(adv_adj)
+ self.validate_dimensions_for_pl_and_bs()
validate_frozen_account(self.account, adv_adj)
validate_balance_type(self.account, adv_adj)
# Update outstanding amt on against voucher
if self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice', 'Fees'] \
- and self.against_voucher and update_outstanding == 'Yes' and not from_repost:
+ and self.against_voucher and update_outstanding == 'Yes':
update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type,
self.against_voucher)
@@ -159,7 +156,6 @@ class GLEntry(Document):
if self.party_type and self.party:
validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
-
def validate_and_set_fiscal_year(self):
if not self.fiscal_year:
self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
@@ -176,19 +172,6 @@ def validate_balance_type(account, adv_adj=False):
(balance_must_be=="Credit" and flt(balance) > 0):
frappe.throw(_("Balance for Account {0} must always be {1}").format(account, _(balance_must_be)))
-def check_freezing_date(posting_date, adv_adj=False):
- """
- Nobody can do GL Entries where posting date is before freezing date
- except authorized person
- """
- if not adv_adj:
- acc_frozen_upto = frappe.db.get_value('Accounts Settings', None, 'acc_frozen_upto')
- if acc_frozen_upto:
- frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
- if getdate(posting_date) <= getdate(acc_frozen_upto) \
- and not frozen_accounts_modifier in frappe.get_roles():
- frappe.throw(_("You are not authorized to add or update entries before {0}").format(formatdate(acc_frozen_upto)))
-
def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False):
if party_type and party:
party_condition = " and party_type={0} and party={1}"\
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index eb3017a46b..d6ffdb69ed 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -57,6 +57,7 @@ class JournalEntry(AccountsController):
from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
unlink_ref_doc_from_payment_entries(self)
unlink_ref_doc_from_salary_slip(self.name)
+ self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
self.make_gl_entries(1)
self.update_advance_paid()
self.update_expense_claim()
@@ -594,7 +595,7 @@ class JournalEntry(AccountsController):
for d in self.accounts:
if d.reference_type=="Expense Claim" and d.reference_name:
doc = frappe.get_doc("Expense Claim", d.reference_name)
- update_reimbursed_amount(doc)
+ update_reimbursed_amount(doc, jv=self.name)
def validate_expense_claim(self):
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index b53e68ff73..bcb22f0e57 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -60,6 +60,7 @@ class PaymentEntry(AccountsController):
self.set_remarks()
self.validate_duplicate_entry()
self.validate_allocated_amount()
+ self.validate_paid_invoices()
self.ensure_supplier_is_not_blocked()
self.set_status()
@@ -75,6 +76,7 @@ class PaymentEntry(AccountsController):
self.set_status()
def on_cancel(self):
+ self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
self.setup_party_account_field()
self.make_gl_entries(cancel=1)
self.update_outstanding_amounts()
@@ -265,6 +267,25 @@ class PaymentEntry(AccountsController):
frappe.throw(_("{0} {1} must be submitted")
.format(d.reference_doctype, d.reference_name))
+ def validate_paid_invoices(self):
+ no_oustanding_refs = {}
+
+ for d in self.get("references"):
+ if not d.allocated_amount:
+ continue
+
+ if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Fees"):
+ outstanding_amount, is_return = frappe.get_cached_value(d.reference_doctype, d.reference_name, ["outstanding_amount", "is_return"])
+ if outstanding_amount <= 0 and not is_return:
+ no_oustanding_refs.setdefault(d.reference_doctype, []).append(d)
+
+ for k, v in no_oustanding_refs.items():
+ frappe.msgprint(_("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.
\
+ If this is undesirable please cancel the corresponding Payment Entry.")
+ .format(k, frappe.bold(", ".join([d.reference_name for d in v])), frappe.bold("negative outstanding amount")),
+ title=_("Warning"), indicator="orange")
+
+
def validate_journal_entry(self):
for d in self.get("references"):
if d.allocated_amount and d.reference_doctype == "Journal Entry":
@@ -571,7 +592,7 @@ class PaymentEntry(AccountsController):
for d in self.get("references"):
if d.reference_doctype=="Expense Claim" and d.reference_name:
doc = frappe.get_doc("Expense Claim", d.reference_name)
- update_reimbursed_amount(doc)
+ update_reimbursed_amount(doc, self.name)
def on_recurring(self, reference_doc, auto_repeat_doc):
self.reference_no = reference_doc.name
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry_list.js b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
new file mode 100644
index 0000000000..7ea60bb48e
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
@@ -0,0 +1,12 @@
+frappe.listview_settings['Payment Entry'] = {
+
+ onload: function(listview) {
+ listview.page.fields_dict.party_type.get_query = function() {
+ return {
+ "filters": {
+ "name": ["in", Object.keys(frappe.boot.party_account_types)],
+ }
+ };
+ };
+ }
+};
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
index 4c7d933476..8bb741f0b2 100644
--- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
@@ -35,8 +35,6 @@ class TestPaymentEntry(unittest.TestCase):
pe.cancel()
- self.assertFalse(self.get_gle(pe.name))
-
so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
self.assertEqual(so_advance_paid, 0)
@@ -124,7 +122,6 @@ class TestPaymentEntry(unittest.TestCase):
self.assertEqual(outstanding_amount, 0)
pe.cancel()
- self.assertFalse(self.get_gle(pe.name))
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 100)
@@ -381,7 +378,6 @@ class TestPaymentEntry(unittest.TestCase):
self.assertEqual(outstanding_amount, 0)
pe3.cancel()
- self.assertFalse(self.get_gle(pe3.name))
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, -100)
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 53ff2225d3..68aeb6d1d6 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -326,7 +326,7 @@ def make_payment_request(**args):
"reference_doctype": args.dt,
"reference_name": args.dn,
"party_type": args.get("party_type") or "Customer",
- "party": args.get("party") or ref_doc.customer,
+ "party": args.get("party") or ref_doc.get("customer"),
"bank_account": bank_account
})
@@ -420,7 +420,7 @@ def make_payment_entry(docname):
def update_payment_req_status(doc, method):
from erpnext.accounts.doctype.payment_entry.payment_entry import get_reference_details
-
+
for ref in doc.references:
payment_request_name = frappe.db.get_value("Payment Request",
{"reference_doctype": ref.reference_doctype, "reference_name": ref.reference_name,
@@ -430,7 +430,7 @@ def update_payment_req_status(doc, method):
ref_details = get_reference_details(ref.reference_doctype, ref.reference_name, doc.party_account_currency)
pay_req_doc = frappe.get_doc('Payment Request', payment_request_name)
status = pay_req_doc.status
-
+
if status != "Paid" and not ref_details.outstanding_amount:
status = 'Paid'
elif status != "Partially Paid" and ref_details.outstanding_amount != ref_details.total_amount:
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
index 03b8f932a9..87e02fef1b 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
@@ -5,7 +5,7 @@ frappe.ui.form.on('Period Closing Voucher', {
onload: function(frm) {
if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
},
-
+
setup: function(frm) {
frm.set_query("closing_account_head", function() {
return {
@@ -18,9 +18,9 @@ frappe.ui.form.on('Period Closing Voucher', {
}
});
},
-
+
refresh: function(frm) {
- if(frm.doc.docstatus==1) {
+ if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
@@ -33,5 +33,5 @@ frappe.ui.form.on('Period Closing Voucher', {
}, "fa fa-table");
}
}
-
+
})
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
index eb95e458dc..0bd9a90b3e 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
@@ -17,8 +17,9 @@ class PeriodClosingVoucher(AccountsController):
self.make_gl_entries()
def on_cancel(self):
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name)
+ self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+ from erpnext.accounts.general_ledger import make_reverse_gl_entries
+ make_reverse_gl_entries(voucher_type="Period Closing Voucher", voucher_no=self.name, cancel=True)
def validate_account_head(self):
closing_account_type = frappe.db.get_value("Account", self.closing_account_head, "root_type")
diff --git a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
index 2fb66d227b..59a673e3a5 100644
--- a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
+++ b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
@@ -1,123 +1,39 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-10-27 16:46:06.060930",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "creation": "2017-10-27 16:46:06.060930",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "default",
+ "user"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "default",
- "fieldtype": "Check",
- "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": "Default",
- "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
- },
+ "default": "0",
+ "fieldname": "default",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Default"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "user",
- "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": "User",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "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
+ "fieldname": "user",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "User",
+ "options": "User"
}
- ],
- "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-11-23 17:13:16.005475",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "POS Profile User",
- "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
- }
- ],
- "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
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-01 09:46:47.599173",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Profile User",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 3cf4d5994a..4f6be59c65 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -382,11 +382,6 @@ function hide_fields(doc) {
cur_frm.refresh_fields();
}
-cur_frm.cscript.update_stock = function(doc, dt, dn) {
- hide_fields(doc, dt, dn);
- this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
-}
-
cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
return {
filters: [
@@ -528,5 +523,10 @@ frappe.ui.form.on("Purchase Invoice", {
erpnext.buying.get_default_bom(frm);
}
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
+ },
+
+ update_stock: function(frm) {
+ hide_fields(frm.doc);
+ frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock? true: false);
}
})
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index b1ae194301..3aa24df16d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -14,7 +14,7 @@ from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po
from erpnext.stock import get_warehouse_account_map
-from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, delete_gl_entries
+from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, make_reverse_gl_entries
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
from erpnext.buying.utils import check_on_hold_or_closed_status
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
@@ -382,7 +382,7 @@ class PurchaseInvoice(BuyingController):
self.update_project()
update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference)
- def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
+ def make_gl_entries(self, gl_entries=None):
if not self.grand_total:
return
if not gl_entries:
@@ -391,21 +391,17 @@ class PurchaseInvoice(BuyingController):
if gl_entries:
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
- make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
- update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
+ if self.docstatus == 1:
+ make_gl_entries(gl_entries, update_outstanding=update_outstanding, merge_entries=False)
+ elif self.docstatus == 2:
+ make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if update_outstanding == "No":
update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
- if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) and self.auto_accounting_for_stock:
- from erpnext.controllers.stock_controller import update_gl_entries_after
- items, warehouses = self.get_items_and_warehouses()
- update_gl_entries_after(self.posting_date, self.posting_time,
- warehouses, items, company = self.company)
-
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
- delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+ make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
def get_gl_entries(self, warehouse_account=None):
self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
@@ -934,6 +930,7 @@ class PurchaseInvoice(BuyingController):
frappe.db.set(self, 'status', 'Cancelled')
unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference)
+ self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
def update_project(self):
project_list = []
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_records.json b/erpnext/accounts/doctype/purchase_invoice/test_records.json
index 171927c182..7030faf2b7 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_records.json
+++ b/erpnext/accounts/doctype/purchase_invoice/test_records.json
@@ -138,13 +138,12 @@
"row_id": 7
}
],
- "posting_date": "2013-02-03",
"supplier": "_Test Supplier",
"supplier_name": "_Test Supplier"
},
-
-
-
+
+
+
{
"bill_no": "NA",
"buying_price_list": "_Test Price List",
@@ -204,7 +203,6 @@
"tax_amount": 150.0
}
],
- "posting_date": "2013-02-03",
"supplier": "_Test Supplier",
"supplier_name": "_Test Supplier"
}
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 60e41f9553..f248276e5b 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -345,7 +345,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
set_dynamic_labels: function() {
this._super();
- this.hide_fields(this.frm.doc);
+ this.frm.events.hide_fields(this.frm)
},
items_on_form_rendered: function() {
@@ -404,7 +404,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
if(r.message && r.message.print_format) {
me.frm.pos_print_format = r.message.print_format;
}
- me.frm.script_manager.trigger("update_stock");
+ me.frm.trigger("update_stock");
if(me.frm.doc.taxes_and_charges) {
me.frm.script_manager.trigger("taxes_and_charges");
}
@@ -446,35 +446,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm}));
-// Hide Fields
-// ------------
-cur_frm.cscript.hide_fields = function(doc) {
- var parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
- 'advances', 'from_date', 'to_date'];
-
- if(cint(doc.is_pos) == 1) {
- hide_field(parent_fields);
- } else {
- for (var i in parent_fields) {
- var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
- if(!docfield.hidden) unhide_field(parent_fields[i]);
- }
- }
-
- // India related fields
- if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
- else hide_field(['c_form_applicable', 'c_form_no']);
-
- this.frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
-
- cur_frm.refresh_fields();
-}
-
-cur_frm.cscript.update_stock = function(doc, dt, dn) {
- cur_frm.cscript.hide_fields(doc, dt, dn);
- this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
-}
-
cur_frm.cscript['Make Delivery Note'] = function() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_delivery_note",
@@ -719,6 +690,12 @@ frappe.ui.form.on('Sales Invoice', {
frm.redemption_conversion_factor = null;
},
+ update_stock: function(frm, dt, dn) {
+ frm.events.hide_fields(frm);
+ frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock);
+ frm.trigger('reset_posting_time');
+ },
+
redeem_loyalty_points: function(frm) {
frm.events.get_loyalty_details(frm);
},
@@ -742,6 +719,29 @@ frappe.ui.form.on('Sales Invoice', {
}
},
+ hide_fields: function(frm) {
+ let doc = frm.doc;
+ var parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
+ 'advances', 'from_date', 'to_date'];
+
+ if(cint(doc.is_pos) == 1) {
+ hide_field(parent_fields);
+ } else {
+ for (var i in parent_fields) {
+ var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
+ if(!docfield.hidden) unhide_field(parent_fields[i]);
+ }
+ }
+
+ // India related fields
+ if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
+ else hide_field(['c_form_applicable', 'c_form_no']);
+
+ frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
+
+ frm.refresh_fields();
+ },
+
get_loyalty_details: function(frm) {
if (frm.doc.customer && frm.doc.redeem_loyalty_points) {
frappe.call({
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 918fa140b2..db20589144 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -149,9 +149,9 @@
"edit_printing_settings",
"letter_head",
"group_same_items",
- "language",
- "column_break_84",
"select_print_heading",
+ "column_break_84",
+ "language",
"more_information",
"inter_company_invoice_reference",
"is_internal_customer",
@@ -1579,7 +1579,7 @@
"idx": 181,
"is_submittable": 1,
"links": [],
- "modified": "2020-04-17 12:38:41.435728",
+ "modified": "2020-04-29 13:37:09.355300",
"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 3c40112ae6..3b0fade0e5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -7,7 +7,6 @@ import frappe.defaults
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
from frappe import _, msgprint, throw
from erpnext.accounts.party import get_party_account, get_due_date
-from erpnext.controllers.stock_controller import update_gl_entries_after
from frappe.model.mapper import get_mapped_doc
from erpnext.accounts.doctype.sales_invoice.pos import update_multi_mode_option
@@ -282,6 +281,8 @@ class SalesInvoice(SellingController):
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_cancel")
+ self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+
def update_status_updater_args(self):
if cint(self.update_stock):
self.status_updater.append({
@@ -717,7 +718,9 @@ class SalesInvoice(SellingController):
if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
- def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
+ def make_gl_entries(self, gl_entries=None):
+ from erpnext.accounts.general_ledger import make_reverse_gl_entries
+
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
if not gl_entries:
gl_entries = self.get_gl_entries()
@@ -729,23 +732,19 @@ class SalesInvoice(SellingController):
update_outstanding = "No" if (cint(self.is_pos) or self.write_off_account or
cint(self.redeem_loyalty_points)) else "Yes"
- make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
- update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
+ if self.docstatus == 1:
+ make_gl_entries(gl_entries, update_outstanding=update_outstanding, merge_entries=False)
+ elif self.docstatus == 2:
+ make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if update_outstanding == "No":
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
update_outstanding_amt(self.debit_to, "Customer", self.customer,
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
- if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) \
- and cint(auto_accounting_for_stock):
- items, warehouses = self.get_items_and_warehouses()
- update_gl_entries_after(self.posting_date, self.posting_time,
- warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) \
and cint(auto_accounting_for_stock):
- from erpnext.accounts.general_ledger import delete_gl_entries
- delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+ make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
def get_gl_entries(self, warehouse_account=None):
from erpnext.accounts.general_ledger import merge_similar_entries
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 88b54fec8f..dd727a49b0 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -364,7 +364,7 @@ class TestSalesInvoice(unittest.TestCase):
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
- self.assertFalse(gle)
+ self.assertTrue(gle)
def test_tax_calculation_with_multiple_items(self):
si = create_sales_invoice(qty=84, rate=4.6, do_not_save=True)
@@ -678,14 +678,15 @@ class TestSalesInvoice(unittest.TestCase):
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
- self.assertFalse(gle)
+ self.assertTrue(gle)
def test_pos_gl_entry_with_perpetual_inventory(self):
make_pos_profile()
- pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
+ pr = make_purchase_receipt(company= "_Test Company with perpetual inventory", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
- pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
+ pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
+ income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
pos.is_pos = 1
pos.update_stock = 1
@@ -766,9 +767,13 @@ class TestSalesInvoice(unittest.TestCase):
def test_pos_change_amount(self):
make_pos_profile()
- pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
+ pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
+ item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
- pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
+ pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
+ debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
+ income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
+ cost_center = "Main - TCP1", do_not_save=True)
pos.is_pos = 1
pos.update_stock = 1
@@ -787,8 +792,15 @@ class TestSalesInvoice(unittest.TestCase):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
pos_profile = make_pos_profile()
- pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
- pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
+
+ pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
+ item_code= "_Test FG Item",
+ warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
+
+ pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
+ debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
+ income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
+ cost_center = "Main - TCP1", do_not_save=True)
pos.is_pos = 1
pos.update_stock = 1
@@ -891,11 +903,9 @@ class TestSalesInvoice(unittest.TestCase):
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
- self.assertFalse(gle)
-
+ self.assertTrue(gle)
frappe.db.sql("delete from `tabPOS Profile`")
- si.delete()
def test_pos_si_without_payment(self):
set_perpetual_inventory()
@@ -1012,9 +1022,6 @@ class TestSalesInvoice(unittest.TestCase):
si.cancel()
- self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
- where reference_name=%s""", si.name))
-
def test_serialized(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -1230,7 +1237,7 @@ class TestSalesInvoice(unittest.TestCase):
gle = frappe.db.sql("""select name from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
- self.assertFalse(gle)
+ self.assertTrue(gle)
def test_invalid_currency(self):
# Customer currency = USD
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 5ba455c131..fb1a4f4dba 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, comma_and
+from frappe.utils import flt, cstr, cint, comma_and, today, getdate, formatdate, now
from frappe import _
from erpnext.accounts.utils import get_stock_and_account_balance
from frappe.model.meta import get_field_precision
@@ -15,17 +15,17 @@ class ClosedAccountingPeriod(frappe.ValidationError): pass
class StockAccountInvalidTransaction(frappe.ValidationError): pass
class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
-def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False):
+def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes'):
if gl_map:
if not cancel:
validate_accounting_period(gl_map)
gl_map = process_gl_map(gl_map, merge_entries)
if gl_map and len(gl_map) > 1:
- save_entries(gl_map, adv_adj, update_outstanding, from_repost)
+ save_entries(gl_map, adv_adj, update_outstanding)
else:
frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction."))
else:
- delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
+ make_reverse_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
def validate_accounting_period(gl_map):
accounting_periods = frappe.db.sql(""" SELECT
@@ -119,33 +119,36 @@ def check_if_in_list(gle, gl_map, dimensions=None):
if same_head:
return e
-def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
- if not from_repost:
- validate_cwip_accounts(gl_map)
+def save_entries(gl_map, adv_adj, update_outstanding):
+ validate_cwip_accounts(gl_map)
round_off_debit_credit(gl_map)
+
+ if gl_map:
+ check_freezing_date(gl_map[0]["posting_date"], adv_adj)
+
for entry in gl_map:
- make_entry(entry, adv_adj, update_outstanding, from_repost)
+ make_entry(entry, adv_adj, update_outstanding)
# check against budget
- if not from_repost:
- validate_expense_against_budget(entry)
+ validate_expense_against_budget(entry)
- if not from_repost:
- validate_account_for_perpetual_inventory(gl_map)
+ validate_account_for_perpetual_inventory(gl_map)
-def make_entry(args, adv_adj, update_outstanding, from_repost=False):
+def make_entry(args, adv_adj, update_outstanding):
gle = frappe.new_doc("GL Entry")
gle.update(args)
gle.flags.ignore_permissions = 1
- gle.flags.from_repost = from_repost
gle.validate()
gle.db_insert()
- gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost)
+ gle.run_method("on_update_with_args", adv_adj, update_outstanding)
gle.flags.ignore_validate = True
gle.submit()
+ # check against budget
+ validate_expense_against_budget(args)
+
def validate_account_for_perpetual_inventory(gl_map):
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
account_list = [gl_entries.account for gl_entries in gl_map]
@@ -169,33 +172,33 @@ def validate_account_for_perpetual_inventory(gl_map):
.format(account), StockAccountInvalidTransaction)
# This has been comment for a temporary, will add this code again on release of immutable ledger
- # elif account_bal != stock_bal:
- # precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
- # currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
+ elif account_bal != stock_bal:
+ precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
+ currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
- # diff = flt(stock_bal - account_bal, precision)
- # error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
- # stock_bal, account_bal, frappe.bold(account))
- # error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
- # stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
+ diff = flt(stock_bal - account_bal, precision)
+ error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
+ stock_bal, account_bal, frappe.bold(account))
+ error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
+ stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
- # db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
- # db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
+ db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
+ db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
- # journal_entry_args = {
- # 'accounts':[
- # {'account': account, db_or_cr_warehouse_account : abs(diff)},
- # {'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
- # }
+ journal_entry_args = {
+ 'accounts':[
+ {'account': account, db_or_cr_warehouse_account : abs(diff)},
+ {'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
+ }
- # frappe.msgprint(msg="""{0}
{1}
""".format(error_reason, error_resolution),
- # raise_exception=StockValueAndAccountBalanceOutOfSync,
- # title=_('Values Out Of Sync'),
- # primary_action={
- # 'label': _('Make Journal Entry'),
- # 'client_action': 'erpnext.route_to_adjustment_jv',
- # 'args': journal_entry_args
- # })
+ frappe.msgprint(msg="""{0}
{1}
""".format(error_reason, error_resolution),
+ raise_exception=StockValueAndAccountBalanceOutOfSync,
+ title=_('Values Out Of Sync'),
+ primary_action={
+ 'label': _('Make Journal Entry'),
+ 'client_action': 'erpnext.route_to_adjustment_jv',
+ 'args': journal_entry_args
+ })
def validate_cwip_accounts(gl_map):
cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")])
@@ -282,31 +285,64 @@ def get_round_off_account_and_cost_center(company):
return round_off_account, round_off_cost_center
-def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
- adv_adj=False, update_outstanding="Yes"):
-
- from erpnext.accounts.doctype.gl_entry.gl_entry import validate_balance_type, \
- check_freezing_date, update_outstanding_amt, validate_frozen_account
+def make_reverse_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
+ adv_adj=False, update_outstanding="Yes"):
+ """
+ Get original gl entries of the voucher
+ and make reverse gl entries by swapping debit and credit
+ """
if not gl_entries:
- gl_entries = frappe.db.sql("""
- select account, posting_date, party_type, party, cost_center, fiscal_year,voucher_type,
- voucher_no, against_voucher_type, against_voucher, cost_center, company
- from `tabGL Entry`
- where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
+ gl_entries = frappe.get_all("GL Entry",
+ fields = ["*"],
+ filters = {
+ "voucher_type": voucher_type,
+ "voucher_no": voucher_no
+ })
if gl_entries:
+ set_as_cancel(gl_entries[0]['voucher_type'], gl_entries[0]['voucher_no'])
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
- frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
- (voucher_type or gl_entries[0]["voucher_type"], voucher_no or gl_entries[0]["voucher_no"]))
+ for entry in gl_entries:
+ entry['name'] = None
+ debit = entry.get('debit', 0)
+ credit = entry.get('credit', 0)
- for entry in gl_entries:
- validate_frozen_account(entry["account"], adv_adj)
- validate_balance_type(entry["account"], adv_adj)
- if not adv_adj:
- validate_expense_against_budget(entry)
+ debit_in_account_currency = entry.get('debit_in_account_currency', 0)
+ credit_in_account_currency = entry.get('credit_in_account_currency', 0)
- if entry.get("against_voucher") and update_outstanding == 'Yes' and not adv_adj:
- update_outstanding_amt(entry["account"], entry.get("party_type"), entry.get("party"), entry.get("against_voucher_type"),
- entry.get("against_voucher"), on_cancel=True)
+ entry['debit'] = credit
+ entry['credit'] = debit
+ entry['debit_in_account_currency'] = credit_in_account_currency
+ entry['credit_in_account_currency'] = debit_in_account_currency
+
+ entry['remarks'] = "On cancellation of " + entry['voucher_no']
+ entry['is_cancelled'] = 1
+ entry['posting_date'] = today()
+
+ if entry['debit'] or entry['credit']:
+ make_entry(entry, adv_adj, "Yes")
+
+
+def check_freezing_date(posting_date, adv_adj=False):
+ """
+ Nobody can do GL Entries where posting date is before freezing date
+ except authorized person
+ """
+ if not adv_adj:
+ acc_frozen_upto = frappe.db.get_value('Accounts Settings', None, 'acc_frozen_upto')
+ if acc_frozen_upto:
+ frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
+ if getdate(posting_date) <= getdate(acc_frozen_upto) \
+ and not frozen_accounts_modifier in frappe.get_roles():
+ frappe.throw(_("You are not authorized to add or update entries before {0}").format(formatdate(acc_frozen_upto)))
+
+def set_as_cancel(voucher_type, voucher_no):
+ """
+ Set is_cancelled=1 in all original gl entries for the voucher
+ """
+ frappe.db.sql("""update `tabGL Entry` set is_cancelled = 1,
+ modified=%s, modified_by=%s
+ where voucher_type=%s and voucher_no=%s and is_cancelled = 0""",
+ (now(), frappe.session.user, voucher_type, voucher_no))
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index ac49d373d4..1188beaa0f 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -154,8 +154,12 @@ frappe.query_reports["General Ledger"] = {
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
- "fieldtype": "Check",
- "default": 1
+ "fieldtype": "Check"
+ },
+ {
+ "fieldname": "show_cancelled_entries",
+ "label": __("Show Cancelled Entries"),
+ "fieldtype": "Check"
}
]
}
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index f776d93301..7af5fa8eaa 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -188,6 +188,9 @@ def get_conditions(filters):
else:
conditions.append("finance_book in (%(finance_book)s)")
+ if not filters.get("show_cancelled_entries"):
+ conditions.append("is_cancelled = 0")
+
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")
diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py
index 260f35f270..1c458107d4 100644
--- a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py
+++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py
@@ -35,6 +35,12 @@ def execute(filters=None):
})
return columns, data
+ # to avoid error eg: gross_income[0] : list index out of range
+ if not gross_income:
+ gross_income = [{}]
+ if not gross_expense:
+ gross_expense = [{}]
+
data.append({
"account_name": "'" + _("Included in Gross Profit") + "'",
"account": "'" + _("Included in Gross Profit") + "'"
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index 127f3133f5..1f78c7a006 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -102,7 +102,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
data.append(row)
- if filters.get('group_by'):
+ if filters.get('group_by') and item_list:
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
data.append(total_row)
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index 0c8957ae44..92a22e62f1 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -111,7 +111,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
data.append(row)
- if filters.get('group_by'):
+ if filters.get('group_by') and item_list:
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
data.append(total_row)
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 4789063ba5..5165495786 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -817,48 +817,37 @@ def create_payment_gateway_account(gateway):
pass
@frappe.whitelist()
-def update_number_field(doctype_name, name, field_name, number_value, company):
+def update_cost_center(docname, cost_center_name, cost_center_number, company):
'''
- doctype_name = Name of the DocType
- name = Docname being referred
- field_name = Name of the field thats holding the 'number' attribute
- number_value = Numeric value entered in field_name
-
- Stores the number entered in the dialog to the DocType's field.
-
Renames the document by adding the number as a prefix to the current name and updates
all transaction where it was present.
'''
- doc_title = frappe.db.get_value(doctype_name, name, frappe.scrub(doctype_name)+"_name")
+ validate_field_number("Cost Center", docname, cost_center_number, company, "cost_center_number")
- validate_field_number(doctype_name, name, number_value, company, field_name)
+ if cost_center_number:
+ frappe.db.set_value("Cost Center", docname, "cost_center_number", cost_center_number.strip())
+ else:
+ frappe.db.set_value("Cost Center", docname, "cost_center_number", "")
- frappe.db.set_value(doctype_name, name, field_name, number_value)
+ frappe.db.set_value("Cost Center", docname, "cost_center_name", cost_center_name.strip())
- if doc_title[0].isdigit():
- separator = " - " if " - " in doc_title else " "
- doc_title = doc_title.split(separator, 1)[1]
-
- frappe.db.set_value(doctype_name, name, frappe.scrub(doctype_name)+"_name", doc_title)
-
- new_name = get_autoname_with_number(number_value, doc_title, name, company)
-
- if name != new_name:
- frappe.rename_doc(doctype_name, name, new_name)
+ new_name = get_autoname_with_number(cost_center_number, cost_center_name, docname, company)
+ if docname != new_name:
+ frappe.rename_doc("Cost Center", docname, new_name, force=1)
return new_name
-def validate_field_number(doctype_name, name, number_value, company, field_name):
+def validate_field_number(doctype_name, docname, number_value, company, field_name):
''' Validate if the number entered isn't already assigned to some other document. '''
if number_value:
+ filters = {field_name: number_value, "name": ["!=", docname]}
if company:
- doctype_with_same_number = frappe.db.get_value(doctype_name,
- {field_name: number_value, "company": company, "name": ["!=", name]})
- else:
- doctype_with_same_number = frappe.db.get_value(doctype_name,
- {field_name: number_value, "name": ["!=", name]})
+ filters["company"] = company
+
+ doctype_with_same_number = frappe.db.get_value(doctype_name, filters)
+
if doctype_with_same_number:
- frappe.throw(_("{0} Number {1} already used in account {2}")
- .format(doctype_name, number_value, doctype_with_same_number))
+ frappe.throw(_("{0} Number {1} is already used in {2} {3}")
+ .format(doctype_name, number_value, doctype_name.lower(), doctype_with_same_number))
def get_autoname_with_number(number_value, doc_title, name, company):
''' append title with prefix as number and suffix as company's abbreviation separated by '-' '''
@@ -897,4 +886,60 @@ def get_stock_accounts(company):
return frappe.get_all("Account", filters = {
"account_type": "Stock",
"company": company
- })
\ No newline at end of file
+ })
+
+def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
+ warehouse_account=None, company=None):
+ def _delete_gl_entries(voucher_type, voucher_no):
+ frappe.db.sql("""delete from `tabGL Entry`
+ where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
+
+ if not warehouse_account:
+ warehouse_account = get_warehouse_account_map(company)
+
+ future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
+ gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
+
+ for voucher_type, voucher_no in future_stock_vouchers:
+ existing_gle = gle.get((voucher_type, voucher_no), [])
+ voucher_obj = frappe.get_doc(voucher_type, voucher_no)
+ expected_gle = voucher_obj.get_gl_entries(warehouse_account)
+ if expected_gle:
+ if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle):
+ _delete_gl_entries(voucher_type, voucher_no)
+ voucher_obj.make_gl_entries(gl_entries=expected_gle, repost_future_gle=False, from_repost=True)
+ else:
+ _delete_gl_entries(voucher_type, voucher_no)
+
+def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None):
+ future_stock_vouchers = []
+
+ values = []
+ condition = ""
+ if for_items:
+ condition += " and item_code in ({})".format(", ".join(["%s"] * len(for_items)))
+ values += for_items
+
+ if for_warehouses:
+ condition += " and warehouse in ({})".format(", ".join(["%s"] * len(for_warehouses)))
+ values += for_warehouses
+
+ for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
+ from `tabStock Ledger Entry` sle
+ where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
+ order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
+ tuple([posting_date, posting_time] + values), as_dict=True):
+ future_stock_vouchers.append([d.voucher_type, d.voucher_no])
+
+ return future_stock_vouchers
+
+def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
+ gl_entries = {}
+ if future_stock_vouchers:
+ for d in frappe.db.sql("""select * from `tabGL Entry`
+ where posting_date >= %s and voucher_no in (%s)""" %
+ ('%s', ', '.join(['%s']*len(future_stock_vouchers))),
+ tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
+ gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
+
+ return gl_entries
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 759d42a542..ecbfeb7f14 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -11,7 +11,7 @@ from frappe.model.document import Document
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.assets.doctype.asset.depreciation \
import get_disposal_account_and_cost_center, get_depreciation_accounts
-from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries
+from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
from erpnext.accounts.utils import get_account_currency
from erpnext.controllers.accounts_controller import AccountsController
@@ -41,7 +41,8 @@ class Asset(AccountsController):
self.validate_cancellation()
self.delete_depreciation_entries()
self.set_status()
- delete_gl_entries(voucher_type='Asset', voucher_no=self.name)
+ self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+ make_reverse_gl_entries(voucher_type='Asset', voucher_no=self.name)
self.db_set('booked_fixed_asset', 0)
def validate_asset_and_reference(self):
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index a56440de3d..050b30d89a 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -66,9 +66,6 @@ class TestAsset(unittest.TestCase):
pr.cancel()
self.assertEqual(asset.docstatus, 2)
- self.assertFalse(frappe.db.get_value("GL Entry",
- {"voucher_type": "Purchase Invoice", "voucher_no": pi.name}))
-
def test_is_fixed_asset_set(self):
asset = create_asset(is_existing_asset = 1)
doc = frappe.new_doc('Purchase Invoice')
diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 9bf4df423c..9a33fc14ac 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -11,7 +11,8 @@ from frappe.model.document import Document
class AssetCategory(Document):
def validate(self):
self.validate_finance_books()
- self.validate_accounts()
+ self.validate_account_types()
+ self.validate_account_currency()
def validate_finance_books(self):
for d in self.finance_books:
@@ -19,7 +20,26 @@ class AssetCategory(Document):
if cint(d.get(frappe.scrub(field)))<1:
frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError)
- def validate_accounts(self):
+ def validate_account_currency(self):
+ account_types = [
+ 'fixed_asset_account', 'accumulated_depreciation_account', 'depreciation_expense_account', 'capital_work_in_progress_account'
+ ]
+ invalid_accounts = []
+ for d in self.accounts:
+ company_currency = frappe.get_value('Company', d.get('company_name'), 'default_currency')
+ for type_of_account in account_types:
+ if d.get(type_of_account):
+ account_currency = frappe.get_value("Account", d.get(type_of_account), "account_currency")
+ if account_currency != company_currency:
+ invalid_accounts.append(frappe._dict({ 'type': type_of_account, 'idx': d.idx, 'account': d.get(type_of_account) }))
+
+ for d in invalid_accounts:
+ frappe.throw(_("Row #{}: Currency of {} - {} doesn't matches company currency.")
+ .format(d.idx, frappe.bold(frappe.unscrub(d.type)), frappe.bold(d.account)),
+ title=_("Invalid Account"))
+
+
+ def validate_account_types(self):
account_type_map = {
'fixed_asset_account': { 'account_type': 'Fixed Asset' },
'accumulated_depreciation_account': { 'account_type': 'Accumulated Depreciation' },
diff --git a/erpnext/buying/doctype/supplier/supplier_dashboard.py b/erpnext/buying/doctype/supplier/supplier_dashboard.py
index d0d5b73984..16251035bd 100644
--- a/erpnext/buying/doctype/supplier/supplier_dashboard.py
+++ b/erpnext/buying/doctype/supplier/supplier_dashboard.py
@@ -23,15 +23,11 @@ def get_data():
},
{
'label': _('Payments'),
- 'items': ['Payment Entry']
- },
- {
- 'label': _('Bank'),
- 'items': ['Bank Account']
+ 'items': ['Payment Entry', 'Bank Account']
},
{
'label': _('Pricing'),
'items': ['Pricing Rule']
}
]
- }
\ No newline at end of file
+ }
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index 08711fc09e..b9b0da48c9 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -183,8 +183,8 @@ def get_data():
},
{
"type": "doctype",
- "label": _("Update Bank Transaction Dates"),
- "name": "Bank Reconciliation",
+ "label": _("Update Bank Clearance Dates"),
+ "name": "Bank Clearance",
"description": _("Update bank payment dates with journals.")
},
{
diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py
index 7b3b4660f5..9855a115a6 100644
--- a/erpnext/config/hr.py
+++ b/erpnext/config/hr.py
@@ -170,6 +170,10 @@ def get_data():
"type": "doctype",
"name": "Payroll Period",
},
+ {
+ "type": "doctype",
+ "name": "Income Tax Slab",
+ },
{
"type": "doctype",
"name": "Salary Component",
@@ -209,6 +213,10 @@ def get_data():
"name": "Employee Tax Exemption Proof Submission",
"dependencies": ["Employee"]
},
+ {
+ "type": "doctype",
+ "name": "Employee Other Income",
+ },
{
"type": "doctype",
"name": "Employee Benefit Application",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 3e97f76f7b..eecb143d55 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -664,23 +664,26 @@ class AccountsController(TransactionBase):
def set_total_advance_paid(self):
if self.doctype == "Sales Order":
dr_or_cr = "credit_in_account_currency"
+ rev_dr_or_cr = "debit_in_account_currency"
party = self.customer
else:
dr_or_cr = "debit_in_account_currency"
+ rev_dr_or_cr = "credit_in_account_currency"
party = self.supplier
advance = frappe.db.sql("""
select
- account_currency, sum({dr_or_cr}) as amount
+ account_currency, sum({dr_or_cr}) - sum({rev_dr_cr}) as amount
from
`tabGL Entry`
where
against_voucher_type = %s and against_voucher = %s and party=%s
and docstatus = 1
- """.format(dr_or_cr=dr_or_cr), (self.doctype, self.name, party), as_dict=1)
+ """.format(dr_or_cr=dr_or_cr, rev_dr_cr=rev_dr_or_cr), (self.doctype, self.name, party), as_dict=1) #nosec
if advance:
advance = advance[0]
+
advance_paid = flt(advance.amount, self.precision("advance_paid"))
formatted_advance_paid = fmt_money(advance_paid, precision=self.precision("advance_paid"),
currency=advance.account_currency)
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 9d453af2ac..86de80815d 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -7,7 +7,7 @@ from frappe.utils import cint, flt, cstr, get_link_to_form, today, getdate
from frappe import _
import frappe.defaults
from erpnext.accounts.utils import get_fiscal_year
-from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
+from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries, process_gl_map
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.stock.stock_ledger import get_valuation_rate
from erpnext.stock import get_warehouse_account_map
@@ -23,9 +23,9 @@ class StockController(AccountsController):
self.validate_serialized_batch()
self.validate_customer_provided_item()
- def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
+ def make_gl_entries(self, gl_entries=None):
if self.docstatus == 2:
- delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+ make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if cint(erpnext.is_perpetual_inventory_enabled(self.company)):
warehouse_account = get_warehouse_account_map(self.company)
@@ -33,16 +33,12 @@ class StockController(AccountsController):
if self.docstatus==1:
if not gl_entries:
gl_entries = self.get_gl_entries(warehouse_account)
- make_gl_entries(gl_entries, from_repost=from_repost)
+ make_gl_entries(gl_entries)
- if (repost_future_gle or self.flags.repost_future_gle):
- items, warehouses = self.get_items_and_warehouses()
- update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
- warehouse_account, company=self.company)
elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1:
gl_entries = []
gl_entries = self.get_asset_gl_entry(gl_entries)
- make_gl_entries(gl_entries, from_repost=from_repost)
+ make_gl_entries(gl_entries)
def validate_serialized_batch(self):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -274,21 +270,21 @@ class StockController(AccountsController):
"batch_no": cstr(d.get("batch_no")).strip(),
"serial_no": d.get("serial_no"),
"project": d.get("project") or self.get('project'),
- "is_cancelled": self.docstatus==2 and "Yes" or "No"
+ "is_cancelled": 1 if self.docstatus==2 else 0
})
sl_dict.update(args)
return sl_dict
- def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False,
+ def make_sl_entries(self, sl_entries, allow_negative_stock=False,
via_landed_cost_voucher=False):
from erpnext.stock.stock_ledger import make_sl_entries
- make_sl_entries(sl_entries, is_amended, allow_negative_stock, via_landed_cost_voucher)
+ make_sl_entries(sl_entries, allow_negative_stock, via_landed_cost_voucher)
- def make_gl_entries_on_cancel(self, repost_future_gle=True):
+ def make_gl_entries_on_cancel(self):
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
and voucher_no=%s""", (self.doctype, self.name)):
- self.make_gl_entries(repost_future_gle=repost_future_gle)
+ self.make_gl_entries()
def get_serialized_items(self):
serialized_items = []
@@ -391,29 +387,6 @@ class StockController(AccountsController):
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
d.allow_zero_valuation_rate = 1
-def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
- warehouse_account=None, company=None):
- def _delete_gl_entries(voucher_type, voucher_no):
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
-
- if not warehouse_account:
- warehouse_account = get_warehouse_account_map(company)
-
- future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
- gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
-
- for voucher_type, voucher_no in future_stock_vouchers:
- existing_gle = gle.get((voucher_type, voucher_no), [])
- voucher_obj = frappe.get_doc(voucher_type, voucher_no)
- expected_gle = voucher_obj.get_gl_entries(warehouse_account)
- if expected_gle:
- if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle):
- _delete_gl_entries(voucher_type, voucher_no)
- voucher_obj.make_gl_entries(gl_entries=expected_gle, repost_future_gle=False, from_repost=True)
- else:
- _delete_gl_entries(voucher_type, voucher_no)
-
def compare_existing_and_expected_gle(existing_gle, expected_gle):
matched = True
for entry in expected_gle:
@@ -430,36 +403,3 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle):
matched = False
break
return matched
-
-def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None):
- future_stock_vouchers = []
-
- values = []
- condition = ""
- if for_items:
- condition += " and item_code in ({})".format(", ".join(["%s"] * len(for_items)))
- values += for_items
-
- if for_warehouses:
- condition += " and warehouse in ({})".format(", ".join(["%s"] * len(for_warehouses)))
- values += for_warehouses
-
- for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
- from `tabStock Ledger Entry` sle
- where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
- order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
- tuple([posting_date, posting_time] + values), as_dict=True):
- future_stock_vouchers.append([d.voucher_type, d.voucher_no])
-
- return future_stock_vouchers
-
-def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
- gl_entries = {}
- if future_stock_vouchers:
- for d in frappe.db.sql("""select * from `tabGL Entry`
- where posting_date >= %s and voucher_no in (%s)""" %
- ('%s', ', '.join(['%s']*len(future_stock_vouchers))),
- tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
- gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
-
- return gl_entries
diff --git a/erpnext/crm/utils.py b/erpnext/crm/utils.py
new file mode 100644
index 0000000000..38bf79e5fc
--- /dev/null
+++ b/erpnext/crm/utils.py
@@ -0,0 +1,24 @@
+import frappe
+
+
+def update_lead_phone_numbers(contact, method):
+ if contact.phone_nos:
+ contact_lead = contact.get_link_for("Lead")
+ if contact_lead:
+ phone = mobile_no = contact.phone_nos[0].phone
+
+ if len(contact.phone_nos) > 1:
+ # get the default phone number
+ primary_phones = [phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_phone]
+ if primary_phones:
+ phone = primary_phones[0]
+
+ # get the default mobile number
+ primary_mobile_nos = [phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_mobile_no]
+ if primary_mobile_nos:
+ mobile_no = primary_mobile_nos[0]
+
+ lead = frappe.get_doc("Lead", contact_lead)
+ lead.phone = phone
+ lead.mobile_no = mobile_no
+ lead.save()
diff --git a/erpnext/education/doctype/fees/fees.js b/erpnext/education/doctype/fees/fees.js
index e2c6f1d856..17ef44954b 100644
--- a/erpnext/education/doctype/fees/fees.js
+++ b/erpnext/education/doctype/fees/fees.js
@@ -112,6 +112,8 @@ frappe.ui.form.on("Fees", {
args: {
"dt": frm.doc.doctype,
"dn": frm.doc.name,
+ "party_type": "Student",
+ "party": frm.doc.student,
"recipient_id": frm.doc.student_email
},
callback: function(r) {
diff --git a/erpnext/education/doctype/fees/fees.py b/erpnext/education/doctype/fees/fees.py
index aa616e6206..01f7b87249 100644
--- a/erpnext/education/doctype/fees/fees.py
+++ b/erpnext/education/doctype/fees/fees.py
@@ -10,7 +10,7 @@ from frappe.utils import money_in_words
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
from frappe.utils.csvutils import getlink
from erpnext.controllers.accounts_controller import AccountsController
-from erpnext.accounts.general_ledger import delete_gl_entries
+from erpnext.accounts.general_ledger import make_reverse_gl_entries
class Fees(AccountsController):
@@ -75,12 +75,14 @@ class Fees(AccountsController):
self.make_gl_entries()
if self.send_payment_request and self.student_email:
- pr = make_payment_request(dt="Fees", dn=self.name, recipient_id=self.student_email,
+ pr = make_payment_request(party_type="Student", party=self.student, dt="Fees",
+ dn=self.name, recipient_id=self.student_email,
submit_doc=True, use_dummy_message=True)
frappe.msgprint(_("Payment request {0} created").format(getlink("Payment Request", pr.name)))
def on_cancel(self):
- delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+ self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+ make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name, cancel=True)
# frappe.db.set(self, 'status', 'Cancelled')
diff --git a/erpnext/education/doctype/student/student_dashboard.py b/erpnext/education/doctype/student/student_dashboard.py
index 0cbd17b8a4..d2614628b1 100644
--- a/erpnext/education/doctype/student/student_dashboard.py
+++ b/erpnext/education/doctype/student/student_dashboard.py
@@ -6,6 +6,9 @@ def get_data():
'heatmap': True,
'heatmap_message': _('This is based on the attendance of this Student'),
'fieldname': 'student',
+ 'non_standard_fieldnames': {
+ 'Bank Account': 'party'
+ },
'transactions': [
{
'label': _('Admission'),
@@ -29,7 +32,7 @@ def get_data():
},
{
'label': _('Fee'),
- 'items': ['Fees']
+ 'items': ['Fees', 'Bank Account']
}
]
- }
\ No newline at end of file
+ }
diff --git a/erpnext/education/doctype/video/test_video.js b/erpnext/education/doctype/video/test_video.js
deleted file mode 100644
index a82a221319..0000000000
--- a/erpnext/education/doctype/video/test_video.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Video", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Video
- () => frappe.tests.make('Video', [
- // values to be set
- {key: 'value'}
- ]),
- () => {
- assert.equal(cur_frm.doc.key, 'value');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/education/doctype/video/test_video.py b/erpnext/education/doctype/video/test_video.py
deleted file mode 100644
index ecb09a2f9e..0000000000
--- a/erpnext/education/doctype/video/test_video.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import frappe
-import unittest
-
-class TestVideo(unittest.TestCase):
- pass
diff --git a/erpnext/education/doctype/video/video.js b/erpnext/education/doctype/video/video.js
deleted file mode 100644
index c35c19b0c1..0000000000
--- a/erpnext/education/doctype/video/video.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Video', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/education/doctype/video/video.json b/erpnext/education/doctype/video/video.json
deleted file mode 100644
index e912eb32cb..0000000000
--- a/erpnext/education/doctype/video/video.json
+++ /dev/null
@@ -1,112 +0,0 @@
-{
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:title",
- "creation": "2018-10-17 05:47:13.087395",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "title",
- "provider",
- "url",
- "column_break_4",
- "publish_date",
- "duration",
- "section_break_7",
- "description"
- ],
- "fields": [
- {
- "fieldname": "title",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Title",
- "reqd": 1,
- "unique": 1
- },
- {
- "fieldname": "description",
- "fieldtype": "Text Editor",
- "in_list_view": 1,
- "label": "Description",
- "reqd": 1
- },
- {
- "fieldname": "duration",
- "fieldtype": "Data",
- "label": "Duration"
- },
- {
- "fieldname": "url",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "URL",
- "reqd": 1
- },
- {
- "fieldname": "publish_date",
- "fieldtype": "Date",
- "label": "Publish Date"
- },
- {
- "fieldname": "provider",
- "fieldtype": "Select",
- "in_list_view": 1,
- "label": "Provider",
- "options": "YouTube\nVimeo",
- "reqd": 1
- },
- {
- "fieldname": "column_break_4",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "section_break_7",
- "fieldtype": "Section Break"
- }
- ],
- "modified": "2019-06-12 12:36:48.753092",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Video",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Academics User",
- "share": 1,
- "write": 1
- },
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Instructor",
- "share": 1,
- "write": 1
- },
- {
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "LMS User",
- "share": 1
- }
- ],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/education/doctype/video/video.py b/erpnext/education/doctype/video/video.py
deleted file mode 100644
index b19f81258c..0000000000
--- a/erpnext/education/doctype/video/video.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, 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 Video(Document):
-
-
- def get_video(self):
- pass
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
index 5f36bdd95c..87c22ccf6f 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
@@ -80,6 +80,7 @@ frappe.ui.form.on('Clinical Procedure', {
frappe.call({
method: 'complete_procedure',
doc: frm.doc,
+ freeze: true,
callback: function(r) {
if (r.message) {
frappe.show_alert({
@@ -87,8 +88,8 @@ frappe.ui.form.on('Clinical Procedure', {
['' + r.message + '']),
indicator: 'green'
});
- frm.reload_doc();
}
+ frm.reload_doc();
}
});
}
@@ -111,9 +112,10 @@ frappe.ui.form.on('Clinical Procedure', {
frappe.call({
doc: frm.doc,
method: 'make_material_receipt',
+ freeze: true,
callback: function(r) {
if (!r.exc) {
- cur_frm.reload_doc();
+ frm.reload_doc();
let doclist = frappe.model.sync(r.message);
frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
}
@@ -122,7 +124,7 @@ frappe.ui.form.on('Clinical Procedure', {
}
);
} else {
- cur_frm.reload_doc();
+ frm.reload_doc();
}
}
}
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
index db3afc8807..b7d7a62a95 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
@@ -87,7 +87,8 @@ class ClinicalProcedure(Document):
else:
frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
- frappe.db.set_value('Clinical Procedure', self.name, 'status', 'Completed')
+ self.db_set('status', 'Completed')
+
if self.consume_stock and self.items:
return stock_entry
@@ -245,9 +246,9 @@ def make_procedure(source_name, target_doc=None):
def insert_clinical_procedure_to_medical_record(doc):
- subject = cstr(doc.procedure_template)
+ subject = frappe.bold(_("Clinical Procedure conducted: ")) + cstr(doc.procedure_template) + "
"
if doc.practitioner:
- subject += ' ' + doc.practitioner
+ subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
if subject and doc.notes:
subject += '
' + doc.notes
diff --git a/erpnext/healthcare/doctype/exercise_type/exercise_type.js b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
index f450c9bccb..68db0477c2 100644
--- a/erpnext/healthcare/doctype/exercise_type/exercise_type.js
+++ b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
@@ -24,6 +24,8 @@ erpnext.ExerciseEditor = Class.extend({
this.exercise_cards = $('