diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000..5e1113d34f --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,19 @@ +# Each line is a file pattern followed by one or more owners. + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, + +* @nabinhait +manufacturing/ @rohitwaghchaure +accounts/ @deepeshgarg007 @nextchamp-saqib +loan_management/ @deepeshgarg007 +pos* @nextchamp-saqib +assets/ @nextchamp-saqib +stock/ @marination @rohitwaghchaure +buying/ @marination @rohitwaghchaure +hr/ @Anurag810 +projects/ @hrwX +support/ @hrwX +healthcare/ @ruchamahabal +erpnext_integrations/ @Mangesh-Khairnar +requirements.txt @gavindsouza diff --git a/erpnext/__init__.py b/erpnext/__init__.py index f40b957563..786b9cfd16 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.2.0' +__version__ = '12.0.0-dev' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json index 7a777f9fd2..8566eadad4 100644 --- a/erpnext/accounts/desk_page/accounting/accounting.json +++ b/erpnext/accounts/desk_page/accounting/accounting.json @@ -1,83 +1,96 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"Company (not Customer or Supplier) master.\",\n \"label\": \"Company\",\n \"name\": \"Company\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of financial accounts.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Accounts\",\n \"name\": \"Account\",\n \"onboard\": 1,\n \"route\": \"#Tree/Account\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounts Settings\",\n \"name\": \"Accounts Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Financial / accounting year.\",\n \"label\": \"Fiscal Year\",\n \"name\": \"Fiscal Year\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Dimension\",\n \"name\": \"Accounting Dimension\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Finance Book\",\n \"name\": \"Finance Book\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Period\",\n \"name\": \"Accounting Period\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Terms based on conditions\",\n \"label\": \"Payment Term\",\n \"name\": \"Payment Term\",\n \"type\": \"doctype\"\n }\n]", - "title": "Accounting Masters" + "hidden": 0, + "label": "Accounting Masters", + "links": "[\n {\n \"description\": \"Company (not Customer or Supplier) master.\",\n \"label\": \"Company\",\n \"name\": \"Company\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of financial accounts.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Accounts\",\n \"name\": \"Account\",\n \"onboard\": 1,\n \"route\": \"#Tree/Account\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounts Settings\",\n \"name\": \"Accounts Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Financial / accounting year.\",\n \"label\": \"Fiscal Year\",\n \"name\": \"Fiscal Year\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Dimension\",\n \"name\": \"Accounting Dimension\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Finance Book\",\n \"name\": \"Finance Book\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Period\",\n \"name\": \"Accounting Period\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Terms based on conditions\",\n \"label\": \"Payment Term\",\n \"name\": \"Payment Term\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Accounting journal entries.\",\n \"label\": \"Journal Entry\",\n \"name\": \"Journal Entry\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"General Ledger\",\n \"name\": \"General Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Customer Ledger Summary\",\n \"name\": \"Customer Ledger Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Supplier Ledger Summary\",\n \"name\": \"Supplier Ledger Summary\",\n \"type\": \"report\"\n }\n]", - "title": "General Ledger" + "hidden": 0, + "label": "General Ledger", + "links": "[\n {\n \"description\": \"Accounting journal entries.\",\n \"label\": \"Journal Entry\",\n \"name\": \"Journal Entry\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"General Ledger\",\n \"name\": \"General Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Customer Ledger Summary\",\n \"name\": \"Customer Ledger Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Supplier Ledger Summary\",\n \"name\": \"Supplier Ledger Summary\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Bills raised to Customers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Request\",\n \"label\": \"Payment Request\",\n \"name\": \"Payment Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable\",\n \"name\": \"Accounts Receivable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable Summary\",\n \"name\": \"Accounts Receivable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Register\",\n \"name\": \"Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales Register\",\n \"name\": \"Item-wise Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Billed\",\n \"name\": \"Ordered Items To Be Billed\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Delivered Items To Be Billed\",\n \"name\": \"Delivered Items To Be Billed\",\n \"type\": \"report\"\n }\n]", - "title": "Accounts Receivable" + "hidden": 0, + "label": "Accounts Receivable", + "links": "[\n {\n \"description\": \"Bills raised to Customers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Request\",\n \"label\": \"Payment Request\",\n \"name\": \"Payment Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable\",\n \"name\": \"Accounts Receivable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable Summary\",\n \"name\": \"Accounts Receivable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Register\",\n \"name\": \"Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales Register\",\n \"name\": \"Item-wise Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Billed\",\n \"name\": \"Ordered Items To Be Billed\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Delivered Items To Be Billed\",\n \"name\": \"Delivered Items To Be Billed\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Bills raised by Suppliers.\",\n \"label\": \"Purchase Invoice\",\n \"name\": \"Purchase Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable\",\n \"name\": \"Accounts Payable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable Summary\",\n \"name\": \"Accounts Payable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Register\",\n \"name\": \"Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase Register\",\n \"name\": \"Item-wise Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Items To Be Billed\",\n \"name\": \"Purchase Order Items To Be Billed\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Received Items To Be Billed\",\n \"name\": \"Received Items To Be Billed\",\n \"type\": \"report\"\n }\n]", - "title": "Accounts Payable" + "hidden": 0, + "label": "Accounts Payable", + "links": "[\n {\n \"description\": \"Bills raised by Suppliers.\",\n \"label\": \"Purchase Invoice\",\n \"name\": \"Purchase Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable\",\n \"name\": \"Accounts Payable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable Summary\",\n \"name\": \"Accounts Payable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Register\",\n \"name\": \"Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase Register\",\n \"name\": \"Item-wise Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Items To Be Billed\",\n \"name\": \"Purchase Order Items To Be Billed\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Received Items To Be Billed\",\n \"name\": \"Received Items To Be Billed\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-table", - "links": "[\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Trial Balance for Party\",\n \"name\": \"Trial Balance for Party\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Payment Period Based On Invoice Date\",\n \"name\": \"Payment Period Based On Invoice Date\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Payment Summary\",\n \"name\": \"Sales Payment Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Address And Contacts\",\n \"name\": \"Address And Contacts\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Trial Balance for Party\",\n \"name\": \"Trial Balance for Party\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Payment Period Based On Invoice Date\",\n \"name\": \"Payment Period Based On Invoice Date\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Payment Summary\",\n \"name\": \"Sales Payment Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Address And Contacts\",\n \"name\": \"Address And Contacts\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Trial Balance\",\n \"name\": \"Trial Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Profit and Loss Statement\",\n \"name\": \"Profit and Loss Statement\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Balance Sheet\",\n \"name\": \"Balance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Cash Flow\",\n \"name\": \"Cash Flow\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Consolidated Financial Statement\",\n \"name\": \"Consolidated Financial Statement\",\n \"type\": \"report\"\n }\n]", - "title": "Financial Statements" + "hidden": 0, + "label": "Financial Statements", + "links": "[\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Trial Balance\",\n \"name\": \"Trial Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Profit and Loss Statement\",\n \"name\": \"Profit and Loss Statement\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Balance Sheet\",\n \"name\": \"Balance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Cash Flow\",\n \"name\": \"Cash Flow\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Consolidated Financial Statement\",\n \"name\": \"Consolidated Financial Statement\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Enable / disable currencies.\",\n \"label\": \"Currency\",\n \"name\": \"Currency\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Currency exchange rate master.\",\n \"label\": \"Currency Exchange\",\n \"name\": \"Currency Exchange\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Exchange Rate Revaluation master.\",\n \"label\": \"Exchange Rate Revaluation\",\n \"name\": \"Exchange Rate Revaluation\",\n \"type\": \"doctype\"\n }\n]", - "title": "Multi Currency" + "hidden": 0, + "label": "Multi Currency", + "links": "[\n {\n \"description\": \"Enable / disable currencies.\",\n \"label\": \"Currency\",\n \"name\": \"Currency\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Currency exchange rate master.\",\n \"label\": \"Currency Exchange\",\n \"name\": \"Currency Exchange\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Exchange Rate Revaluation master.\",\n \"label\": \"Exchange Rate Revaluation\",\n \"name\": \"Exchange Rate Revaluation\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-cog", - "links": "[\n {\n \"description\": \"Setup Gateway accounts.\",\n \"label\": \"Payment Gateway Account\",\n \"name\": \"Payment Gateway Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Template of terms or contract.\",\n \"label\": \"Terms and Conditions Template\",\n \"name\": \"Terms and Conditions\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"e.g. Bank, Cash, Credit Card\",\n \"label\": \"Mode of Payment\",\n \"name\": \"Mode of Payment\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"description\": \"Setup Gateway accounts.\",\n \"label\": \"Payment Gateway Account\",\n \"name\": \"Payment Gateway Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Template of terms or contract.\",\n \"label\": \"Terms and Conditions Template\",\n \"name\": \"Terms and Conditions\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"e.g. Bank, Cash, Credit Card\",\n \"label\": \"Mode of Payment\",\n \"name\": \"Mode of Payment\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Bank\",\n \"name\": \"Bank\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Account\",\n \"name\": \"Bank Account\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Transaction Entry\",\n \"name\": \"Bank Statement Transaction Entry\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Settings\",\n \"name\": \"Bank Statement Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Bank Statement" + "hidden": 0, + "label": "Bank Statement", + "links": "[\n {\n \"label\": \"Bank\",\n \"name\": \"Bank\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Account\",\n \"name\": \"Bank Account\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Transaction Entry\",\n \"name\": \"Bank Statement Transaction Entry\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Settings\",\n \"name\": \"Bank Statement Settings\",\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 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]", - "title": "Banking and Payments" + "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 \"label\": \"Subscription Plan\",\n \"name\": \"Subscription Plan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Subscription\",\n \"name\": \"Subscription\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Subscription Settings\",\n \"name\": \"Subscription Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Subscription Management" + "hidden": 0, + "label": "Subscription Management", + "links": "[\n {\n \"label\": \"Subscription Plan\",\n \"name\": \"Subscription Plan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Subscription\",\n \"name\": \"Subscription\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Subscription Settings\",\n \"name\": \"Subscription Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n }\n]", - "title": "Goods and Services Tax (GST India)" + "hidden": 0, + "label": "Goods and Services Tax (GST India)", + "links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-microchip ", - "links": "[\n {\n \"description\": \"List of available Shareholders with folio numbers\",\n \"label\": \"Shareholder\",\n \"name\": \"Shareholder\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of all share transactions\",\n \"label\": \"Share Transfer\",\n \"name\": \"Share Transfer\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Share Transfer\"\n ],\n \"doctype\": \"Share Transfer\",\n \"is_query_report\": true,\n \"label\": \"Share Ledger\",\n \"name\": \"Share Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Share Transfer\"\n ],\n \"doctype\": \"Share Transfer\",\n \"is_query_report\": true,\n \"label\": \"Share Balance\",\n \"name\": \"Share Balance\",\n \"type\": \"report\"\n }\n]", - "title": "Share Management" + "hidden": 0, + "label": "Share Management", + "links": "[\n {\n \"description\": \"List of available Shareholders with folio numbers\",\n \"label\": \"Shareholder\",\n \"name\": \"Shareholder\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of all share transactions\",\n \"label\": \"Share Transfer\",\n \"name\": \"Share Transfer\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Share Transfer\"\n ],\n \"doctype\": \"Share Transfer\",\n \"is_query_report\": true,\n \"label\": \"Share Ledger\",\n \"name\": \"Share Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Share Transfer\"\n ],\n \"doctype\": \"Share Transfer\",\n \"is_query_report\": true,\n \"label\": \"Share Balance\",\n \"name\": \"Share Balance\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Tree of financial Cost Centers.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Cost Centers\",\n \"name\": \"Cost Center\",\n \"route\": \"#Tree/Cost Center\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define budget for a financial year.\",\n \"label\": \"Budget\",\n \"name\": \"Budget\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Dimension\",\n \"name\": \"Accounting Dimension\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Cost Center\"\n ],\n \"doctype\": \"Cost Center\",\n \"is_query_report\": true,\n \"label\": \"Budget Variance Report\",\n \"name\": \"Budget Variance Report\",\n \"type\": \"report\"\n },\n {\n \"description\": \"Seasonality for setting budgets, targets etc.\",\n \"label\": \"Monthly Distribution\",\n \"name\": \"Monthly Distribution\",\n \"type\": \"doctype\"\n }\n]", - "title": "Cost Center and Budgeting" + "hidden": 0, + "label": "Cost Center and Budgeting", + "links": "[\n {\n \"description\": \"Tree of financial Cost Centers.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Cost Centers\",\n \"name\": \"Cost Center\",\n \"route\": \"#Tree/Cost Center\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define budget for a financial year.\",\n \"label\": \"Budget\",\n \"name\": \"Budget\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Dimension\",\n \"name\": \"Accounting Dimension\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Cost Center\"\n ],\n \"doctype\": \"Cost Center\",\n \"is_query_report\": true,\n \"label\": \"Budget Variance Report\",\n \"name\": \"Budget Variance Report\",\n \"type\": \"report\"\n },\n {\n \"description\": \"Seasonality for setting budgets, targets etc.\",\n \"label\": \"Monthly Distribution\",\n \"name\": \"Monthly Distribution\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Opening Invoice Creation Tool\",\n \"name\": \"Opening Invoice Creation Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Chart of Accounts Importer\",\n \"name\": \"Chart of Accounts Importer\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Close Balance Sheet and book Profit or Loss.\",\n \"label\": \"Period Closing Voucher\",\n \"name\": \"Period Closing Voucher\",\n \"type\": \"doctype\"\n }\n]", - "title": "Opening and Closing" + "hidden": 0, + "label": "Opening and Closing", + "links": "[\n {\n \"label\": \"Opening Invoice Creation Tool\",\n \"name\": \"Opening Invoice Creation Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Chart of Accounts Importer\",\n \"name\": \"Chart of Accounts Importer\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Close Balance Sheet and book Profit or Loss.\",\n \"label\": \"Period Closing Voucher\",\n \"name\": \"Period Closing Voucher\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Tax template for selling transactions.\",\n \"label\": \"Sales Taxes and Charges Template\",\n \"name\": \"Sales Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for buying transactions.\",\n \"label\": \"Purchase Taxes and Charges Template\",\n \"name\": \"Purchase Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for item tax rates.\",\n \"label\": \"Item Tax Template\",\n \"name\": \"Item Tax Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Category for overriding tax rates.\",\n \"label\": \"Tax Category\",\n \"name\": \"Tax Category\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Rule for transactions.\",\n \"label\": \"Tax Rule\",\n \"name\": \"Tax Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Withholding rates to be applied on transactions.\",\n \"label\": \"Tax Withholding Category\",\n \"name\": \"Tax Withholding Category\",\n \"type\": \"doctype\"\n }\n]", - "title": "Taxes" + "hidden": 0, + "label": "Taxes", + "links": "[\n {\n \"description\": \"Tax template for selling transactions.\",\n \"label\": \"Sales Taxes and Charges Template\",\n \"name\": \"Sales Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for buying transactions.\",\n \"label\": \"Purchase Taxes and Charges Template\",\n \"name\": \"Purchase Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for item tax rates.\",\n \"label\": \"Item Tax Template\",\n \"name\": \"Item Tax Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Category for overriding tax rates.\",\n \"label\": \"Tax Category\",\n \"name\": \"Tax Category\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Rule for transactions.\",\n \"label\": \"Tax Rule\",\n \"name\": \"Tax Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Withholding rates to be applied on transactions.\",\n \"label\": \"Tax Withholding Category\",\n \"name\": \"Tax Withholding Category\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Gross Profit\",\n \"name\": \"Gross Profit\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Profitability Analysis\",\n \"name\": \"Profitability Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Invoice Trends\",\n \"name\": \"Sales Invoice Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Invoice Trends\",\n \"name\": \"Purchase Invoice Trends\",\n \"type\": \"report\"\n }\n]", - "title": "Profitability" + "hidden": 0, + "label": "Profitability", + "links": "[\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Gross Profit\",\n \"name\": \"Gross Profit\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Profitability Analysis\",\n \"name\": \"Profitability Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Invoice Trends\",\n \"name\": \"Sales Invoice Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Invoice Trends\",\n \"name\": \"Purchase Invoice Trends\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", "charts": [ { "chart_name": "Bank Balance", - "label": "Bank Balance", - "size": "Full" + "label": "Bank Balance" } ], "creation": "2020-03-02 15:41:59.515192", @@ -90,7 +103,7 @@ "idx": 0, "is_standard": 1, "label": "Accounting", - "modified": "2020-03-12 16:30:35.580450", + "modified": "2020-04-01 11:28:50.925719", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting", @@ -99,37 +112,37 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Account", "link_to": "Account", "type": "DocType" }, { - "is_query_report": 0, + "label": "Journal Entry", "link_to": "Journal Entry", "type": "DocType" }, { - "is_query_report": 0, + "label": "Payment Entry", "link_to": "Payment Entry", "type": "DocType" }, { - "is_query_report": 1, + "label": "Accounts Receivable", "link_to": "Accounts Receivable", "type": "Report" }, { - "is_query_report": 0, + "label": "General Ledger", "link_to": "General Ledger", "type": "Report" }, { - "is_query_report": 0, + "label": "Profit and Loss Statement", "link_to": "Profit and Loss Statement", "type": "Report" }, { - "is_query_report": 0, + "label": "Trial Balance", "link_to": "Trial Balance", "type": "Report" } diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index d5a36b8259..0a72d4fa4e 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -102,7 +102,7 @@ class Account(NestedSet): if not frappe.db.get_value("Account", {'account_name': self.account_name, 'company': ancestors[0]}, 'name'): frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0])) - else: + elif self.parent_account: descendants = get_descendants_of('Company', self.company) if not descendants: return parent_acc_name_map = {} diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index efac1af551..f62d07668d 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -1,7 +1,7 @@ frappe.provide("frappe.treeview_settings") frappe.treeview_settings["Account"] = { - breadcrumbs: "Accounts", + breadcrumb: "Accounts", title: __("Chart Of Accounts"), get_tree_root: false, filters: [ diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json index ff95c5ae19..3fc109bfd6 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json @@ -2433,29 +2433,26 @@ "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen (bei Buchgewinn)": { "account_number": "4849" }, - "Erl\u00f6se aus Verk\u00e4ufen immaterieller VG (bei Buchgewinn) (Gruppe)": { - "is_group": 1, - "Erl\u00f6se aus Verk\u00e4ufen immaterieller VG (bei Buchgewinn)": { - "account_number": "4850" - }, - "Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (bei Buchgewinn)": { - "account_number": "4851" - }, - "Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (inl\u00e4ndische Kap.Ges., bei Buchgewinn)": { - "account_number": "4852" - }, - "Anlagenabg\u00e4nge Sachanlagen (Restbuchwert bei Buchvergewinn)": { - "account_number": "4855" - }, - "Anlagenabg\u00e4nge immaterielle VG (Restbuchwert bei Buchgewinn)": { - "account_number": "4856" - }, - "Anlagenabg\u00e4nge Finanzanlagen (Restbuchwert bei Buchgewinn)": { - "account_number": "4857" - }, - "Anlagenabg\u00e4nge Finanzanlagen (inl\u00e4ndische Kap.Ges., Restbuchwert bei Buchgewinn)": { - "account_number": "4858" - } + "Erl\u00f6se aus Verk\u00e4ufen immaterieller VG (bei Buchgewinn)": { + "account_number": "4850" + }, + "Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (bei Buchgewinn)": { + "account_number": "4851" + }, + "Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (inl\u00e4ndische Kap.Ges., bei Buchgewinn)": { + "account_number": "4852" + }, + "Anlagenabg\u00e4nge Sachanlagen (Restbuchwert bei Buchvergewinn)": { + "account_number": "4855" + }, + "Anlagenabg\u00e4nge immaterielle VG (Restbuchwert bei Buchgewinn)": { + "account_number": "4856" + }, + "Anlagenabg\u00e4nge Finanzanlagen (Restbuchwert bei Buchgewinn)": { + "account_number": "4857" + }, + "Anlagenabg\u00e4nge Finanzanlagen (inl\u00e4ndische Kap.Ges., Restbuchwert bei Buchgewinn)": { + "account_number": "4858" }, "Ertr\u00e4ge aus Zuschreibungen des Sachanlageverm\u00f6gens": { "account_number": "4910", @@ -2578,20 +2575,17 @@ "Entnahme von Gegenst\u00e4nden ohne USt": { "account_number": "4605" }, - "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 7 % USt (Gruppe)": { - "is_group": 1, - "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 7 % USt": { - "account_number": "4630" - }, - "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt": { - "account_number": "4637" - }, - "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternnehmens ohne USt (Telefon-Nutzung)": { - "account_number": "4638" - }, - "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt (Kfz-Nutzung)": { - "account_number": "4639" - } + "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 7 % USt": { + "account_number": "4630" + }, + "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt": { + "account_number": "4637" + }, + "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternnehmens ohne USt (Telefon-Nutzung)": { + "account_number": "4638" + }, + "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens ohne USt (Kfz-Nutzung)": { + "account_number": "4639" }, "Verwendung von Gegenst\u00e4nden f. Zwecke au\u00dferhalb des Unternehmens 19 % USt (Gruppe)": { "is_group": 1, @@ -2629,14 +2623,11 @@ "Unentgeltliche Zuwendung von Gegenst\u00e4nden ohne USt": { "account_number": "4689" }, - "Nicht steuerbare Ums\u00e4tze (Innenums\u00e4tze) (Gruppe)": { - "is_group": 1, - "Nicht steuerbare Ums\u00e4tze (Innenums\u00e4tze)": { - "account_number": "4690" - }, - "Umsatzsteuerverg\u00fctungen, z.B. nach \u00a7 24 UStG": { - "account_number": "4695" - } + "Nicht steuerbare Ums\u00e4tze (Innenums\u00e4tze)": { + "account_number": "4690" + }, + "Umsatzsteuerverg\u00fctungen, z.B. nach \u00a7 24 UStG": { + "account_number": "4695" }, "Au\u00dferordentliche Ertr\u00e4ge (Gruppe)": { "is_group": 1, @@ -2646,41 +2637,35 @@ "Au\u00dferordentliche Ertr\u00e4ge finanzwirksam": { "account_number": "7401" }, - "Au\u00dferordentliche Ertr\u00e4ge nicht finanzwirksam (Gruppe)": { - "is_group": 1, - "Au\u00dferordentliche Ertr\u00e4ge nicht finanzwirksam": { - "account_number": "7450" - }, - "Ertr\u00e4ge durch Verschmelzung und Umwandlung": { - "account_number": "7451" - }, - "Ertr\u00e4ge durch den Verkauf von bedeutenden Beteiligungen": { - "account_number": "7452" - }, - "Ert\u00e4ge durch den Verkauf von bedeutenden Grundst\u00fccken": { - "account_number": "7453" - }, - "Gewinn aus der Ver\u00e4u\u00dferung oder der Aufgabe von Gesch\u00e4ftsaktivit\u00e4ten nach Steuern": { - "account_number": "7454" - } + "Au\u00dferordentliche Ertr\u00e4ge nicht finanzwirksam": { + "account_number": "7450" }, - "Au\u00dferordentliche Ertr\u00e4ge aus der Anwendung von \u00dcbergangsvorschriften (Gruppe)": { - "is_group": 1, - "Au\u00dferordentliche Ertr\u00e4ge aus der Anwendung von \u00dcbergangsvorschriften": { - "account_number": "7460" - }, - "Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Sachanlageverm\u00f6gen": { - "account_number": "7461" - }, - "Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Finanzanlageverm\u00f6gen": { - "account_number": "7462" - }, - "Au\u00dferordentliche Ertr\u00e4ge: Wertpapiere im Umlaufverm\u00f6gen": { - "account_number": "7463" - }, - "Au\u00dferordentliche Ertr\u00e4ge: latente Steuern": { - "account_number": "7464" - } + "Ertr\u00e4ge durch Verschmelzung und Umwandlung": { + "account_number": "7451" + }, + "Ertr\u00e4ge durch den Verkauf von bedeutenden Beteiligungen": { + "account_number": "7452" + }, + "Ert\u00e4ge durch den Verkauf von bedeutenden Grundst\u00fccken": { + "account_number": "7453" + }, + "Gewinn aus der Ver\u00e4u\u00dferung oder der Aufgabe von Gesch\u00e4ftsaktivit\u00e4ten nach Steuern": { + "account_number": "7454" + }, + "Au\u00dferordentliche Ertr\u00e4ge aus der Anwendung von \u00dcbergangsvorschriften": { + "account_number": "7460" + }, + "Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Sachanlageverm\u00f6gen": { + "account_number": "7461" + }, + "Au\u00dferordentliche Ertr\u00e4ge: Zuschreibung f. Finanzanlageverm\u00f6gen": { + "account_number": "7462" + }, + "Au\u00dferordentliche Ertr\u00e4ge: Wertpapiere im Umlaufverm\u00f6gen": { + "account_number": "7463" + }, + "Au\u00dferordentliche Ertr\u00e4ge: latente Steuern": { + "account_number": "7464" } } }, @@ -2718,40 +2703,43 @@ }, "Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 16 % USt": { "account_number": "4729" + } + }, + "Gew\u00e4hrte Skonti (Gruppe)": { + "is_group": 1, + "Gew. Skonti": { + "account_number": "4730" }, - "Gew\u00e4hrte Skonti (Gruppe)": { - "is_group": 1, - "Gew. Skonti": { - "account_number": "4730" - }, - "Gew. Skonti 7 % USt": { - "account_number": "4731" - }, - "Gew. Skonti 19 % USt": { - "account_number": "4736" - }, - "Gew. Skonti aus Lieferungen von Mobilfunkger./Schaltkr., f. die der Leistungsempf. die Ust. schuldet": { - "account_number": "4738" - }, - "Gew. Skonti aus Leistungen, f. die der Leistungsempf. die Umsatzsteuer nach \u00a7 13b UStG schuldet": { - "account_number": "4741" - }, - "Gew. Skonti aus Erl\u00f6sen aus im anderen EU-Land steuerpfl. Leistungen, f. die der Leistungsempf. die Ust. schuldet": { - "account_number": "4742" - }, - "Gew. Skonti aus steuerfreien innergem. Lieferungen \u00a7 4 Nr. 1b UStG": { - "account_number": "4743" - }, - "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen": { - "account_number": "4745" - }, - "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 7% USt": { - "account_number": "4746" - }, - "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 19% USt": { - "account_number": "4748" - } + "Gew. Skonti 7 % USt": { + "account_number": "4731" }, + "Gew. Skonti 19 % USt": { + "account_number": "4736" + }, + "Gew. Skonti aus Lieferungen von Mobilfunkger./Schaltkr., f. die der Leistungsempf. die Ust. schuldet": { + "account_number": "4738" + }, + "Gew. Skonti aus Leistungen, f. die der Leistungsempf. die Umsatzsteuer nach \u00a7 13b UStG schuldet": { + "account_number": "4741" + }, + "Gew. Skonti aus Erl\u00f6sen aus im anderen EU-Land steuerpfl. Leistungen, f. die der Leistungsempf. die Ust. schuldet": { + "account_number": "4742" + }, + "Gew. Skonti aus steuerfreien innergem. Lieferungen \u00a7 4 Nr. 1b UStG": { + "account_number": "4743" + }, + "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen": { + "account_number": "4745" + }, + "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 7% USt": { + "account_number": "4746" + }, + "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 19% USt": { + "account_number": "4748" + } + }, + "Gew\u00e4hrte Boni (Gruppe)": { + "is_group": 1, "Gew\u00e4hrte Boni 7 % USt": { "account_number": "4750" }, @@ -2864,103 +2852,79 @@ "account_number": "6398" } }, - "Versicherungen (Gruppe)": { - "is_group": 1, - "Versicherungen": { - "account_number": "6400" - }, - "Versicherungen f. Geb\u00e4ude, die zum Betriebsverm\u00f6gen geh\u00f6ren": { - "account_number": "6405" - }, - "Netto-Pr\u00e4mie f. R\u00fcckdeckung k\u00fcnftiger Versorgungsleistungen": { - "account_number": "6410" - }, - "Beitr\u00e4ge": { - "account_number": "6420" - }, - "Sonstige Abgaben": { - "account_number": "6430" - }, - "Steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": { - "account_number": "6436" - }, - "Steuerlich nicht abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": { - "account_number": "6437" - }, - "Ausgleichsabgabe i. S. d. Schwerbehindertengesetzes": { - "account_number": "6440" - }, - "Reparaturen und Instandhaltung von Bauten": { - "account_number": "6450" - }, - "Reparaturen und Instandhaltung von technischenAnlagen und Maschinen": { - "account_number": "6460" - }, - "Reparaturen und Instandhaltung von anderen Anlagen und Betriebs- und Gesch\u00e4ftsausstattung": { - "account_number": "6470" - }, - "Zuf\u00fchrung zu Aufwandsr\u00fcckstellungen": { - "account_number": "6475" - }, - "Reparaturen und Instandhaltung von anderen Anlagen": { - "account_number": "6485" - }, - "Sonstige Reparaturen und Instandhaltungen": { - "account_number": "6490" - }, - "Wartungskosten f. Hard- und Software": { - "account_number": "6495" - }, - "Mietleasing (bewegliche Wirtschaftsg\u00fcter)": { - "account_number": "6498" - } + "Versicherungen": { + "account_number": "6400" + }, + "Versicherungen f. Geb\u00e4ude, die zum Betriebsverm\u00f6gen geh\u00f6ren": { + "account_number": "6405" + }, + "Netto-Pr\u00e4mie f. R\u00fcckdeckung k\u00fcnftiger Versorgungsleistungen": { + "account_number": "6410" + }, + "Beitr\u00e4ge": { + "account_number": "6420" + }, + "Sonstige Abgaben": { + "account_number": "6430" + }, + "Steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": { + "account_number": "6436" + }, + "Steuerlich nicht abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": { + "account_number": "6437" + }, + "Ausgleichsabgabe i. S. d. Schwerbehindertengesetzes": { + "account_number": "6440" + }, + "Reparaturen und Instandhaltung von Bauten": { + "account_number": "6450" + }, + "Reparaturen und Instandhaltung von technischenAnlagen und Maschinen": { + "account_number": "6460" + }, + "Reparaturen und Instandhaltung von anderen Anlagen und Betriebs- und Gesch\u00e4ftsausstattung": { + "account_number": "6470" + }, + "Zuf\u00fchrung zu Aufwandsr\u00fcckstellungen": { + "account_number": "6475" + }, + "Reparaturen und Instandhaltung von anderen Anlagen": { + "account_number": "6485" + }, + "Sonstige Reparaturen und Instandhaltungen": { + "account_number": "6490" + }, + "Wartungskosten f. Hard- und Software": { + "account_number": "6495" + }, + "Mietleasing (bewegliche Wirtschaftsg\u00fcter)": { + "account_number": "6498" }, "Fahrzeugkosten (Gruppe)": { "is_group": 1, "Fahrzeugkosten": { "account_number": "6500" }, - "Kfz-Versicherungen (Gruppe)": { - "is_group": 1, - "Kfz-Versicherungen": { - "account_number": "6520" - } + "Kfz-Versicherungen": { + "account_number": "6520" }, - "Laufende Kfz-Betriebskosten (Gruppe)": { - "is_group": 1, - "Laufende Kfz-Betriebskosten": { - "account_number": "6530" - } + "Laufende Kfz-Betriebskosten": { + "account_number": "6530" }, - "Kfz-Reparaturen (Gruppe)": { - "is_group": 1, - "Kfz-Reparaturen": { - "account_number": "6540" - } + "Kfz-Reparaturen": { + "account_number": "6540" }, - "Garagenmiete (Gruppe)": { - "is_group": 1, - "Garagenmiete": { - "account_number": "6550" - } + "Garagenmiete": { + "account_number": "6550" }, - "Mietleasing Kfz (Gruppe)": { - "is_group": 1, - "Mietleasing Kfz": { - "account_number": "6560" - } + "Mietleasing Kfz": { + "account_number": "6560" }, - "Sonstige Kfz-Kosten (Gruppe)": { - "is_group": 1, - "Sonstige Kfz-Kosten": { - "account_number": "6570" - } + "Sonstige Kfz-Kosten": { + "account_number": "6570" }, - "Mautgeb\u00fchren (Gruppe)": { - "is_group": 1, - "Mautgeb\u00fchren": { - "account_number": "6580" - } + "Mautgeb\u00fchren": { + "account_number": "6580" }, "Kfz-Kosten f. betrieblich genutzte zum Privatverm\u00f6gen geh\u00f6rende Kraftfahrzeuge": { "account_number": "6590" @@ -3022,20 +2986,23 @@ "Nicht abzugsf\u00e4hige Betriebsausgaben aus Werbe- und Repr\u00e4sentationskosten": { "account_number": "6645" }, - "Reisekosten Arbeitnehmer": { - "account_number": "6650" - }, - "Reisekosten Arbeitnehmer \u00dcbernachtungsaufwand": { - "account_number": "6660" - }, - "Reisekosten Arbeitnehmer Fahrtkosten": { - "account_number": "6663" - }, - "Reisekosten Arbeitnehmer Verpflegungsmehraufwand": { - "account_number": "6664" - }, - "Kilometergelderstattung Arbeitnehmer": { - "account_number": "6668" + "Reisekosten Arbeitnehmer (Gruppe)": { + "is_group": 1, + "Reisekosten Arbeitnehmer": { + "account_number": "6650" + }, + "Reisekosten Arbeitnehmer \u00dcbernachtungsaufwand": { + "account_number": "6660" + }, + "Reisekosten Arbeitnehmer Fahrtkosten": { + "account_number": "6663" + }, + "Reisekosten Arbeitnehmer Verpflegungsmehraufwand": { + "account_number": "6664" + }, + "Kilometergelderstattung Arbeitnehmer": { + "account_number": "6668" + } }, "Reisekosten Unternehmer (Gruppe)": { "is_group": 1, diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index a36f4214d7..3c12f85f93 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -48,12 +48,6 @@ frappe.ui.form.on('Accounting Dimension', { frm.set_value('label', frm.doc.document_type); frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type)); - if (frm.is_new()){ - let row = frappe.model.add_child(frm.doc, "Accounting Dimension Detail", "dimension_defaults"); - row.reference_document = frm.doc.document_type; - frm.refresh_fields("dimension_defaults"); - } - frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => { if (r && r.document_type) { frm.set_df_property('document_type', 'description', "Document type is already set as dimension"); diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index cf6dc7a8fa..cf55d554fb 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -1,4 +1,5 @@ { + "actions": [], "autoname": "field:label", "creation": "2019-05-04 18:13:37.002352", "doctype": "DocType", @@ -46,7 +47,8 @@ "options": "Accounting Dimension Detail" } ], - "modified": "2019-07-17 16:49:31.134385", + "links": [], + "modified": "2020-03-22 20:34:39.805728", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Dimension", @@ -63,9 +65,20 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, + "write": 1 } ], - "quick_entry": 1, "sort_field": "modified", "sort_order": "ASC", "track_changes": 1 diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 462d967d01..14fdffc0a7 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -193,7 +193,7 @@ def get_dimension_with_children(doctype, dimension): all_dimensions = [] lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"]) - children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}) + children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft") all_dimensions += [c.name for c in children] return all_dimensions diff --git a/erpnext/accounts/doctype/bank/bank.js b/erpnext/accounts/doctype/bank/bank.js index 463d29c9f8..de9498e075 100644 --- a/erpnext/accounts/doctype/bank/bank.js +++ b/erpnext/accounts/doctype/bank/bank.js @@ -7,7 +7,20 @@ frappe.ui.form.on('Bank', { }, refresh: function(frm) { add_fields_to_mapping_table(frm); - } + + frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' }; + + frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); + + if (frm.doc.__islocal) { + frm.set_df_property('address_and_contact', 'hidden', 1); + frappe.contacts.clear_address_and_contact(frm); + } + else { + frm.set_df_property('address_and_contact', 'hidden', 0); + frappe.contacts.render_address_and_contact(frm); + } + }, }); diff --git a/erpnext/accounts/doctype/bank/bank.json b/erpnext/accounts/doctype/bank/bank.json index 4fa0e4f29b..99978e657d 100644 --- a/erpnext/accounts/doctype/bank/bank.json +++ b/erpnext/accounts/doctype/bank/bank.json @@ -1,224 +1,137 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:bank_name", - "beta": 0, - "creation": "2018-04-07 16:59:59.496668", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:bank_name", + "creation": "2018-04-07 16:59:59.496668", + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "bank_details_section", + "bank_name", + "swift_number", + "column_break_1", + "branch_code", + "website", + "address_and_contact", + "address_html", + "column_break_13", + "contact_html", + "data_import_configuration_section", + "bank_transaction_mapping", + "section_break_4", + "plaid_access_token" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank_name", - "fieldtype": "Data", - "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": "Bank Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "fieldname": "bank_name", + "fieldtype": "Data", + "label": "Bank Name", + "reqd": 1, "unique": 1 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "data_import_configuration_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Data Import Configuration", - "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 - }, + "fieldname": "bank_details_section", + "fieldtype": "Section Break", + "label": "Bank Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank_transaction_mapping", - "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": "Bank Transaction Mapping", - "length": 0, - "no_copy": 0, - "options": "Bank Transaction Mapping", - "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_in_quick_entry": 1, + "fieldname": "swift_number", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "SWIFT number", + "unique": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_4", - "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 - }, + "fieldname": "column_break_1", + "fieldtype": "Column Break", + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "plaid_access_token", - "fieldtype": "Data", - "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": "Plaid Access Token", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "allow_in_quick_entry": 1, + "fieldname": "branch_code", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Branch Code", + "unique": 1 + }, + { + "fieldname": "address_and_contact", + "fieldtype": "Section Break", + "label": "Address and Contact", + "options": "fa fa-map-marker" + }, + { + "fieldname": "address_html", + "fieldtype": "HTML", + "label": "Address HTML" + }, + { + "fieldname": "website", + "fieldtype": "Data", + "label": "Website" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "fieldname": "contact_html", + "fieldtype": "HTML", + "label": "Contact HTML" + }, + { + "collapsible": 1, + "fieldname": "data_import_configuration_section", + "fieldtype": "Section Break", + "label": "Data Import Configuration" + }, + { + "fieldname": "bank_transaction_mapping", + "fieldtype": "Table", + "label": "Bank Transaction Mapping", + "options": "Bank Transaction Mapping" + }, + { + "fieldname": "section_break_4", + "fieldtype": "Section Break" + }, + { + "fieldname": "plaid_access_token", + "fieldtype": "Data", + "hidden": 1, + "label": "Plaid Access Token", + "no_copy": 1, + "read_only": 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": 0, - "max_attachments": 0, - "modified": "2018-11-27 16:12:13.938776", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Bank", - "name_case": "", - "owner": "Administrator", + ], + "links": [], + "modified": "2020-03-25 21:22:33.496264", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Bank", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "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, - "track_views": 0 + ], + "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/bank.py b/erpnext/accounts/doctype/bank/bank.py index b205d56678..41aae14362 100644 --- a/erpnext/accounts/doctype/bank/bank.py +++ b/erpnext/accounts/doctype/bank/bank.py @@ -5,6 +5,12 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address class Bank(Document): - pass + def onload(self): + """Load address and contacts in `__onload`""" + load_address_and_contact(self) + + def on_trash(self): + delete_contact_and_address('Bank', self.name) \ No newline at end of file diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json index c8ae26d9f2..aa9c434db0 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.json +++ b/erpnext/accounts/doctype/bank_account/bank_account.json @@ -24,8 +24,6 @@ "iban", "column_break_12", "bank_account_no", - "branch_code", - "swift_number", "address_and_contact", "address_html", "website", @@ -145,17 +143,6 @@ "label": "Bank Account No", "length": 30 }, - { - "fieldname": "branch_code", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Branch Code" - }, - { - "fieldname": "swift_number", - "fieldtype": "Data", - "label": "SWIFT number" - }, { "fieldname": "address_and_contact", "fieldtype": "Section Break", @@ -213,7 +200,7 @@ } ], "links": [], - "modified": "2020-01-29 20:42:26.458316", + "modified": "2020-01-30 20:42:26.458316", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Account", diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js index 0acbe2009f..065d25e6c3 100644 --- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js +++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js @@ -4,8 +4,8 @@ cur_frm.add_fetch('bank_account','account','account'); cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no'); cur_frm.add_fetch('bank_account','iban','iban'); -cur_frm.add_fetch('bank_account','branch_code','branch_code'); -cur_frm.add_fetch('bank_account','swift_number','swift_number'); +cur_frm.add_fetch('bank','branch_code','branch_code'); +cur_frm.add_fetch('bank','swift_number','swift_number'); frappe.ui.form.on('Bank Guarantee', { setup: function(frm) { diff --git a/erpnext/accounts/doctype/cost_center/cost_center_tree.js b/erpnext/accounts/doctype/cost_center/cost_center_tree.js index 16d9734432..fde41233c4 100644 --- a/erpnext/accounts/doctype/cost_center/cost_center_tree.js +++ b/erpnext/accounts/doctype/cost_center/cost_center_tree.js @@ -1,5 +1,5 @@ frappe.treeview_settings["Cost Center"] = { - breadcrumbs: "Accounts", + breadcrumb: "Accounts", get_tree_root: false, filters: [{ fieldname: "company", diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js index 0d5456ece6..1092f4c8f1 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js @@ -30,18 +30,10 @@ frappe.ui.form.on('Exchange Rate Revaluation', { frm.doc.accounts.forEach(d=> { total_amt = total_amt + d['new_balance_in_base_currency']; }); - if(total_amt === r.sum) { - frm.add_custom_button(__("Journal Entry"), function(){ - frappe.route_options = { - 'reference_type': 'Exchange Rate Revaluation', - 'reference_name': frm.doc.name - }; - frappe.set_route("List", "Journal Entry"); - }, __("View")); - } else { - frm.add_custom_button(__('Create Journal Entry'), function() { + if(total_amt !== r.sum) { + frm.add_custom_button(__('Journal Entry'), function() { return frm.events.make_jv(frm); - }); + }, __('Create')); } }, 'Journal Entry'); } diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation_dashboard.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation_dashboard.py new file mode 100644 index 0000000000..b5cfa04ed6 --- /dev/null +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation_dashboard.py @@ -0,0 +1,11 @@ +from __future__ import unicode_literals + +def get_data(): + return { + 'fieldname': 'reference_name', + 'transactions': [ + { + 'items': ['Journal Entry'] + } + ] + } diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index e64bc9e0c7..2214811d8b 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -114,13 +114,13 @@ "fieldname": "debit_in_account_currency", "fieldtype": "Currency", "label": "Debit Amount in Account Currency", - "options": "currency" + "options": "account_currency" }, { "fieldname": "credit_in_account_currency", "fieldtype": "Currency", "label": "Credit Amount in Account Currency", - "options": "currency" + "options": "account_currency" }, { "fieldname": "against", @@ -250,7 +250,7 @@ "icon": "fa fa-list", "idx": 1, "in_create": 1, - "modified": "2020-02-10 04:54:57.777905", + "modified": "2020-03-28 16:22:33.766994", "modified_by": "Administrator", "module": "Accounts", "name": "GL Entry", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 968fb60571..b7c97a776e 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -33,7 +33,9 @@ frappe.ui.form.on('Payment Entry', { frm.set_query("party_bank_account", function() { return { filters: { - "is_company_account":0 + "is_company_account":0, + party_type: frm.doc.party_type, + party: frm.doc.party } } }); @@ -154,8 +156,11 @@ frappe.ui.form.on('Payment Entry', { frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency); - frm.toggle_display("base_received_amount", (frm.doc.paid_to_account_currency != company_currency && - frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency)); + frm.toggle_display("base_received_amount", ( + frm.doc.paid_to_account_currency != company_currency + && frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency + && frm.doc.base_paid_amount != frm.doc.base_received_amount + )); frm.toggle_display("received_amount", (frm.doc.payment_type=="Internal Transfer" || frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency)) @@ -499,6 +504,7 @@ frappe.ui.form.on('Payment Entry', { paid_amount: function(frm) { frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate)); frm.trigger("reset_received_amount"); + frm.events.hide_unhide_fields(frm); }, received_amount: function(frm) { @@ -522,6 +528,7 @@ frappe.ui.form.on('Payment Entry', { frm.events.set_unallocated_amount(frm); frm.set_paid_amount_based_on_received_amount = false; + frm.events.hide_unhide_fields(frm); }, reset_received_amount: function(frm) { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 55d275831e..a453e95b2b 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -81,7 +81,12 @@ class PaymentEntry(AccountsController): self.update_advance_paid() self.update_expense_claim() self.delink_advance_entry_references() + self.set_payment_req_status() self.set_status() + + def set_payment_req_status(self): + from erpnext.accounts.doctype.payment_request.payment_request import update_payment_req_status + update_payment_req_status(self, None) def update_outstanding_amounts(self): self.set_missing_ref_details(force=True) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index d6d494668a..d12e474c5b 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -15,11 +15,11 @@ frappe.ui.form.on('Payment Order', { if (frm.doc.docstatus == 0) { frm.add_custom_button(__('Payment Request'), function() { frm.trigger("get_from_payment_request"); - }, __("Get from")); + }, __("Get Payments from")); frm.add_custom_button(__('Payment Entry'), function() { frm.trigger("get_from_payment_entry"); - }, __("Get from")); + }, __("Get Payments from")); frm.trigger('remove_button'); } diff --git a/erpnext/accounts/doctype/payment_order/payment_order.json b/erpnext/accounts/doctype/payment_order/payment_order.json index 2e12ad3523..2ed0a4a22f 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.json +++ b/erpnext/accounts/doctype/payment_order/payment_order.json @@ -59,7 +59,6 @@ "fieldtype": "Section Break" }, { - "allow_bulk_edit": 1, "fieldname": "references", "fieldtype": "Table", "label": "Payment Order Reference", @@ -108,7 +107,7 @@ } ], "is_submittable": 1, - "modified": "2019-05-14 17:12:24.912666", + "modified": "2020-04-06 18:00:56.022642", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order", diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index bff995ec5a..97ae5ffde3 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -1,1560 +1,387 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2015-12-15 22:23:24.745065", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 0, - "engine": "InnoDB", + "autoname": "naming_series:", + "creation": "2015-12-15 22:23:24.745065", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "payment_request_type", + "transaction_date", + "column_break_2", + "naming_series", + "mode_of_payment", + "party_details", + "party_type", + "party", + "column_break_4", + "reference_doctype", + "reference_name", + "transaction_details", + "grand_total", + "is_a_subscription", + "column_break_18", + "currency", + "subscription_section", + "subscription_plans", + "bank_account_details", + "bank_account", + "bank", + "bank_account_no", + "account", + "column_break_11", + "iban", + "branch_code", + "swift_number", + "recipient_and_message", + "print_format", + "email_to", + "subject", + "column_break_9", + "payment_gateway_account", + "status", + "make_sales_invoice", + "section_break_10", + "message", + "message_examples", + "mute_email", + "payment_url", + "section_break_7", + "payment_gateway", + "payment_account", + "payment_order", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Inward", - "fieldname": "payment_request_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Request Type", - "length": 0, - "no_copy": 0, - "options": "Outward\nInward", - "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 - }, + "default": "Inward", + "fieldname": "payment_request_type", + "fieldtype": "Select", + "label": "Payment Request Type", + "options": "Outward\nInward", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "transaction_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Transaction Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "transaction_date", + "fieldtype": "Date", + "label": "Transaction Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "naming_series", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Series", - "length": 0, - "no_copy": 1, - "options": "ACC-PRQ-.YYYY.-", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "naming_series", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Series", + "no_copy": 1, + "options": "ACC-PRQ-.YYYY.-", + "print_hide": 1, + "reqd": 1, + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "mode_of_payment", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "label": "Mode of Payment", + "options": "Mode of Payment" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "party_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Party Details", - "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 - }, + "fieldname": "party_details", + "fieldtype": "Section Break", + "label": "Party Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "party_type", - "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": "Party Type", - "length": 0, - "no_copy": 0, - "options": "DocType", - "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 - }, + "fieldname": "party_type", + "fieldtype": "Link", + "label": "Party Type", + "options": "DocType" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "party", - "fieldtype": "Dynamic 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": "Party", - "length": 0, - "no_copy": 0, - "options": "party_type", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "party", + "fieldtype": "Dynamic Link", + "label": "Party", + "options": "party_type" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reference_doctype", - "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": 1, - "label": "Reference Doctype", - "length": 0, - "no_copy": 1, - "options": "DocType", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "reference_doctype", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Reference Doctype", + "no_copy": 1, + "options": "DocType", + "print_hide": 1, + "read_only": 1, + "report_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reference_name", - "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Reference Name", - "length": 0, - "no_copy": 1, - "options": "reference_doctype", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "reference_name", + "fieldtype": "Dynamic Link", + "in_global_search": 1, + "in_standard_filter": 1, + "label": "Reference Name", + "no_copy": 1, + "options": "reference_doctype", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "transaction_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Transaction Details", - "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 - }, + "fieldname": "transaction_details", + "fieldtype": "Section Break", + "label": "Transaction Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Amount in customer's currency", - "fieldname": "grand_total", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amount", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "description": "Amount in customer's currency", + "fieldname": "grand_total", + "fieldtype": "Currency", + "label": "Amount", + "options": "currency" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "is_a_subscription", - "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": "Is a Subscription", - "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 - }, + "default": "0", + "fieldname": "is_a_subscription", + "fieldtype": "Check", + "label": "Is a Subscription" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_18", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_18", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "currency", - "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": "Transaction Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "currency", + "fieldtype": "Link", + "label": "Transaction Currency", + "options": "Currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, - "depends_on": "eval:doc.is_a_subscription", - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subscription Section", - "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 - }, + "depends_on": "eval:doc.is_a_subscription", + "fieldname": "subscription_section", + "fieldtype": "Section Break", + "label": "Subscription Section" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subscription_plans", - "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": "Subscription Plans", - "length": 0, - "no_copy": 0, - "options": "Subscription Plan Detail", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "subscription_plans", + "fieldtype": "Table", + "label": "Subscription Plans", + "options": "Subscription Plan Detail" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "bank_account_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Bank Account Details", - "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 - }, + "collapsible": 1, + "fieldname": "bank_account_details", + "fieldtype": "Section Break", + "label": "Bank Account Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 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, - "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 - }, + "fieldname": "bank_account", + "fieldtype": "Link", + "label": "Bank Account", + "options": "Bank Account" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "bank_account.bank", - "fieldname": "bank", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Bank", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "bank_account.bank", + "fieldname": "bank", + "fieldtype": "Read Only", + "label": "Bank" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "bank_account.bank_account_no", - "fieldname": "bank_account_no", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Bank Account No", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "bank_account.bank_account_no", + "fieldname": "bank_account_no", + "fieldtype": "Read Only", + "label": "Bank Account No" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "bank_account.account", - "fieldname": "account", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Account", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "bank_account.account", + "fieldname": "account", + "fieldtype": "Read Only", + "label": "Account" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_11", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "bank_account.iban", - "fieldname": "iban", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "IBAN", - "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 - }, + "fetch_from": "bank_account.iban", + "fieldname": "iban", + "fieldtype": "Read Only", + "label": "IBAN" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "bank_account.branch_code", - "fieldname": "branch_code", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Branch Code", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "bank_account.branch_code", + "fieldname": "branch_code", + "fieldtype": "Read Only", + "label": "Branch Code" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "bank_account.swift_number", - "fieldname": "swift_number", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "SWIFT Number", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "bank_account.swift_number", + "fieldname": "swift_number", + "fieldtype": "Read Only", + "label": "SWIFT Number" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.payment_request_type == 'Inward'", - "fieldname": "recipient_and_message", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Recipient Message And Payment Details", - "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 - }, + "depends_on": "eval: doc.payment_request_type == 'Inward'", + "fieldname": "recipient_and_message", + "fieldtype": "Section Break", + "label": "Recipient Message And Payment Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "print_format", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Print Format", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "print_format", + "fieldtype": "Select", + "label": "Print Format" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "email_to", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "To", - "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 - }, + "fieldname": "email_to", + "fieldtype": "Data", + "in_global_search": 1, + "label": "To" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subject", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subject", - "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 - }, + "fieldname": "subject", + "fieldtype": "Data", + "in_global_search": 1, + "label": "Subject" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_9", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_9", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.payment_request_type == 'Inward'", - "fieldname": "payment_gateway_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": "Payment Gateway Account", - "length": 0, - "no_copy": 0, - "options": "Payment Gateway Account", - "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 - }, + "depends_on": "eval: doc.payment_request_type == 'Inward'", + "fieldname": "payment_gateway_account", + "fieldtype": "Link", + "label": "Payment Gateway Account", + "options": "Payment Gateway Account" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Draft", - "fieldname": "status", - "fieldtype": "Select", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "\nDraft\nInitiated\nPayment Ordered\nPaid\nFailed\nCancelled", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Draft", + "fieldname": "status", + "fieldtype": "Select", + "hidden": 1, + "in_standard_filter": 1, + "label": "Status", + "options": "\nDraft\nRequested\nInitiated\nPartially Paid\nPayment Ordered\nPaid\nFailed\nCancelled", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.reference_doctype==\"Sales Order\"", - "fieldname": "make_sales_invoice", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Make Sales Invoice", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "depends_on": "eval:doc.reference_doctype==\"Sales Order\"", + "fieldname": "make_sales_invoice", + "fieldtype": "Check", + "hidden": 1, + "label": "Make Sales Invoice", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.payment_request_type == 'Inward'", - "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 - }, + "depends_on": "eval: doc.payment_request_type == 'Inward'", + "fieldname": "section_break_10", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "message", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Message", - "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 - }, + "fieldname": "message", + "fieldtype": "Text", + "label": "Message" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "message_examples", - "fieldtype": "HTML", - "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": "Message Examples", - "length": 0, - "no_copy": 0, - "options": "
Message Example
\n\n<p>Dear {{ doc.contact_person }},</p>\n\n<p>Requesting payment for {{ doc.doctype }}, {{ doc.name }} for {{ doc.grand_total }}.</p>\n\n<a href=\"{{ payment_url }}\"> click here to pay </a>\n\n
\n", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "message_examples", + "fieldtype": "HTML", + "label": "Message Examples", + "options": "
Message Example
\n\n<p>Dear {{ doc.contact_person }},</p>\n\n<p>Requesting payment for {{ doc.doctype }}, {{ doc.name }} for {{ doc.grand_total }}.</p>\n\n<a href=\"{{ payment_url }}\"> click here to pay </a>\n\n
\n", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "mute_email", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mute Email", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "mute_email", + "fieldtype": "Check", + "hidden": 1, + "label": "Mute Email", + "no_copy": 1, + "print_hide": 1, + "read_only": 1, + "report_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_url", - "fieldtype": "Small Text", - "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": "payment_url", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_url", + "fieldtype": "Small Text", + "hidden": 1, + "label": "payment_url", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "doc.payment_gateway_account", - "columns": 0, - "depends_on": "eval: doc.payment_request_type == 'Inward'", - "fieldname": "section_break_7", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Gateway Details", - "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 - }, + "collapsible": 1, + "collapsible_depends_on": "doc.payment_gateway_account", + "depends_on": "eval: doc.payment_request_type == 'Inward'", + "fieldname": "section_break_7", + "fieldtype": "Section Break", + "label": "Payment Gateway Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "payment_gateway_account.payment_gateway", - "fieldname": "payment_gateway", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Gateway", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "payment_gateway_account.payment_gateway", + "fieldname": "payment_gateway", + "fieldtype": "Read Only", + "label": "Payment Gateway" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "payment_gateway_account.payment_account", - "fieldname": "payment_account", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Account", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "payment_gateway_account.payment_account", + "fieldname": "payment_account", + "fieldtype": "Read Only", + "label": "Payment Account", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_order", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Order", - "length": 0, - "no_copy": 0, - "options": "Payment Order", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "payment_order", + "fieldtype": "Link", + "label": "Payment Order", + "options": "Payment Order", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "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": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Payment Request", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Payment Request", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-02-18 18:52:34.203239", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Payment Request", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "modified": "2020-03-28 16:07:31.960798", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payment Request", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + ], + "sort_field": "modified", + "sort_order": "DESC" } \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 0fade8c456..53ff2225d3 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -66,6 +66,8 @@ class PaymentRequest(Document): if self.payment_request_type == 'Outward': self.db_set('status', 'Initiated') return + elif self.payment_request_type == 'Inward': + self.db_set('status', 'Requested') send_mail = self.payment_gateway_validation() ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) @@ -88,6 +90,7 @@ class PaymentRequest(Document): if (hasattr(ref_doc, "order_type") and getattr(ref_doc, "order_type") == "Shopping Cart"): from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice si = make_sales_invoice(self.reference_name, ignore_permissions=True) + si.allocate_advances_automatically = True si = si.insert(ignore_permissions=True) si.submit() @@ -317,13 +320,13 @@ def make_payment_request(**args): "payment_request_type": args.get("payment_request_type"), "currency": ref_doc.currency, "grand_total": grand_total, - "email_to": args.recipient_id or "", + "email_to": args.recipient_id or ref_doc.owner, "subject": _("Payment Request for {0}").format(args.dn), "message": gateway_account.get("message") or get_dummy_message(ref_doc), "reference_doctype": args.dt, "reference_name": args.dn, - "party_type": args.get("party_type"), - "party": args.get("party"), + "party_type": args.get("party_type") or "Customer", + "party": args.get("party") or ref_doc.customer, "bank_account": bank_account }) @@ -415,17 +418,31 @@ def make_payment_entry(docname): doc = frappe.get_doc("Payment Request", docname) return doc.create_payment_entry(submit=False).as_dict() -def make_status_as_paid(doc, method): +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, "docstatus": 1}) if payment_request_name: - doc = frappe.get_doc("Payment Request", payment_request_name) - if doc.status != "Paid": - doc.db_set('status', 'Paid') - frappe.db.commit() + 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: + status = 'Partially Paid' + elif ref_details.outstanding_amount == ref_details.total_amount: + if pay_req_doc.payment_request_type == 'Outward': + status = 'Initiated' + elif pay_req_doc.payment_request_type == 'Inward': + status = 'Requested' + + pay_req_doc.db_set('status', status) + frappe.db.commit() def get_dummy_message(doc): return frappe.render_template("""{% if doc.contact_person -%} diff --git a/erpnext/accounts/doctype/payment_request/payment_request_list.js b/erpnext/accounts/doctype/payment_request/payment_request_list.js index 0caf1c2f7f..72833d235f 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request_list.js +++ b/erpnext/accounts/doctype/payment_request/payment_request_list.js @@ -4,14 +4,20 @@ frappe.listview_settings['Payment Request'] = { if(doc.status == "Draft") { return [__("Draft"), "darkgrey", "status,=,Draft"]; } + if(doc.status == "Requested") { + return [__("Requested"), "green", "status,=,Requested"]; + } else if(doc.status == "Initiated") { return [__("Initiated"), "green", "status,=,Initiated"]; } + else if(doc.status == "Partially Paid") { + return [__("Partially Paid"), "orange", "status,=,Partially Paid"]; + } else if(doc.status == "Paid") { return [__("Paid"), "blue", "status,=,Paid"]; } else if(doc.status == "Cancelled") { - return [__("Cancelled"), "orange", "status,=,Cancelled"]; + return [__("Cancelled"), "red", "status,=,Cancelled"]; } } } diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py index 188ab0aecf..8a10e2cbd9 100644 --- a/erpnext/accounts/doctype/payment_request/test_payment_request.py +++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py @@ -101,6 +101,23 @@ class TestPaymentRequest(unittest.TestCase): self.assertEqual(expected_gle[gle.account][2], gle.credit) self.assertEqual(expected_gle[gle.account][3], gle.against_voucher) + def test_status(self): + si_usd = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC", + currency="USD", conversion_rate=50) + + pr = make_payment_request(dt="Sales Invoice", dn=si_usd.name, recipient_id="saurabh@erpnext.com", + mute_email=1, payment_gateway="_Test Gateway - USD", submit_doc=1, return_doc=1) + + pe = pr.create_payment_entry() + pr.load_from_db() + + self.assertEqual(pr.status, 'Paid') + + pe.cancel() + pr.load_from_db() + + self.assertEqual(pr.status, 'Requested') + def test_multiple_payment_entries_against_sales_order(self): # Make Sales Order, grand_total = 1000 so = make_sales_order() diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 87d40fca1b..0283d304d7 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe, erpnext -from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate +from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate, get_link_to_form from frappe import _, throw import frappe.defaults @@ -146,10 +146,14 @@ class PurchaseInvoice(BuyingController): ["account_type", "report_type", "account_currency"], as_dict=True) if account.report_type != "Balance Sheet": - frappe.throw(_("Credit To account must be a Balance Sheet account")) + frappe.throw(_("Please ensure {} account is a Balance Sheet account. \ + You can change the parent account to a Balance Sheet account or select a different account.") + .format(frappe.bold("Credit To")), title=_("Invalid Account")) if self.supplier and account.account_type != "Payable": - frappe.throw(_("Credit To account must be a Payable account")) + frappe.throw(_("Please ensure {} account is a Payable account. \ + Change the account type to Payable or select a different account.") + .format(frappe.bold("Credit To")), title=_("Invalid Account")) self.party_account_currency = account.account_currency @@ -267,16 +271,30 @@ class PurchaseInvoice(BuyingController): def po_required(self): if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes': + + if frappe.get_value('Supplier', self.supplier, 'allow_purchase_invoice_creation_without_purchase_order'): + return + for d in self.get('items'): if not d.purchase_order: - throw(_("As per the Buying Settings if Purchase Order Required == 'YES', then for creating Purchase Invoice, user need to create Purchase Order first for item {0}").format(d.item_code)) + throw(_("""Purchase Order Required for item {0} + To submit the invoice without purchase order please set + {1} as {2} in {3}""").format(frappe.bold(d.item_code), frappe.bold(_('Purchase Order Required')), + frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))) def pr_required(self): stock_items = self.get_stock_items() if frappe.db.get_value("Buying Settings", None, "pr_required") == 'Yes': + + if frappe.get_value('Supplier', self.supplier, 'allow_purchase_invoice_creation_without_purchase_receipt'): + return + for d in self.get('items'): if not d.purchase_receipt and d.item_code in stock_items: - throw(_("As per the Buying Settings if Purchase Reciept Required == 'YES', then for creating Purchase Invoice, user need to create Purchase Receipt first for item {0}").format(d.item_code)) + throw(_("""Purchase Receipt Required for item {0} + To submit the invoice without purchase receipt please set + {1} as {2} in {3}""").format(frappe.bold(d.item_code), frappe.bold(_('Purchase Receipt Required')), + frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))) def validate_write_off_account(self): if self.write_off_amount and not self.write_off_account: diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index ef90b942b5..9c974260a2 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -761,7 +761,7 @@ "depends_on": "is_fixed_asset", "fetch_from": "item_code.asset_category", "fieldname": "asset_category", - "fieldtype": "Data", + "fieldtype": "Link", "label": "Asset Category", "options": "Asset Category", "read_only": 1 @@ -777,7 +777,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2020-03-11 14:20:17.297284", + "modified": "2020-04-01 14:20:17.297284", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ba1ceffd14..82aedb6247 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -437,13 +437,17 @@ class SalesInvoice(SellingController): if (not for_validate) or (for_validate and not self.get(fieldname)): self.set(fieldname, pos.get(fieldname)) - customer_price_list = frappe.get_value("Customer", self.customer, 'default_price_list') - if pos.get("company_address"): self.company_address = pos.get("company_address") - if not customer_price_list: - self.set('selling_price_list', pos.get('selling_price_list')) + customer_price_list, customer_group = frappe.get_value("Customer", self.customer, ['default_price_list', 'customer_group']) + + customer_group_price_list = frappe.get_value("Customer Group", customer_group, 'default_price_list') + + selling_price_list = customer_price_list or customer_group_price_list or pos.get('selling_price_list') + + if selling_price_list: + self.set('selling_price_list', selling_price_list) if not for_validate: self.update_stock = cint(pos.get("update_stock")) @@ -474,13 +478,17 @@ class SalesInvoice(SellingController): ["account_type", "report_type", "account_currency"], as_dict=True) if not account: - frappe.throw(_("Debit To is required")) + frappe.throw(_("Debit To is required"), title=_("Account Missing")) if account.report_type != "Balance Sheet": - frappe.throw(_("Debit To account must be a Balance Sheet account")) + frappe.throw(_("Please ensure {} account is a Balance Sheet account. \ + You can change the parent account to a Balance Sheet account or select a different account.") + .format(frappe.bold("Debit To")), title=_("Invalid Account")) if self.customer and account.account_type != "Receivable": - frappe.throw(_("Debit To account must be a Receivable account")) + frappe.throw(_("Please ensure {} account is a Receivable account. \ + Change the account type to Receivable or select a different account.") + .format(frappe.bold("Debit To")), title=_("Invalid Account")) self.party_account_currency = account.account_currency @@ -542,12 +550,17 @@ class SalesInvoice(SellingController): """check in manage account if sales order / delivery note required or not.""" if self.is_return: return - dic = {'Sales Order':['so_required', 'is_pos'],'Delivery Note':['dn_required', 'update_stock']} - for i in dic: - if frappe.db.get_single_value('Selling Settings', dic[i][0]) == 'Yes': + + prev_doc_field_map = {'Sales Order': ['so_required', 'is_pos'],'Delivery Note': ['dn_required', 'update_stock']} + for key, value in iteritems(prev_doc_field_map): + if frappe.db.get_single_value('Selling Settings', value[0]) == 'Yes': + + if frappe.get_value('Customer', self.customer, value[0]): + continue + for d in self.get('items'): - if (d.item_code and not d.get(i.lower().replace(' ','_')) and not self.get(dic[i][1])): - msgprint(_("{0} is mandatory for Item {1}").format(i,d.item_code), raise_exception=1) + if (d.item_code and not d.get(key.lower().replace(' ', '_')) and not self.get(value[1])): + msgprint(_("{0} is mandatory for Item {1}").format(key, d.item_code), raise_exception=1) def validate_proj_cust(self): diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 3d5ce8ac40..0e54b62caa 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1926,6 +1926,16 @@ class TestSalesInvoice(unittest.TestCase): item.taxes = [] item.save() + def test_customer_provided_parts_si(self): + create_item('CUST-0987', is_customer_provided_item = 1, customer = '_Test Customer', is_purchase_item = 0) + si = create_sales_invoice(item_code='CUST-0987', rate=0) + self.assertEqual(si.get("items")[0].allow_zero_valuation_rate, 1) + self.assertEqual(si.get("items")[0].amount, 0) + + # test if Sales Invoice with rate is allowed + si2 = create_sales_invoice(item_code='CUST-0987', do_not_save=True) + self.assertRaises(frappe.ValidationError, si2.save) + def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") args = frappe._dict(args) @@ -1948,7 +1958,7 @@ def create_sales_invoice(**args): "gst_hsn_code": "999800", "warehouse": args.warehouse or "_Test Warehouse - _TC", "qty": args.qty or 1, - "rate": args.rate or 100, + "rate": args.rate if args.get("rate") is not None else 100, "income_account": args.income_account or "Sales - _TC", "expense_account": args.expense_account or "Cost of Goods Sold - _TC", "cost_center": args.cost_center or "_Test Cost Center - _TC", diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py index 1fd340c731..b2638c7827 100644 --- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py @@ -82,7 +82,7 @@ class ShippingRule(Document): if not shipping_country: frappe.throw(_('Shipping Address does not have country, which is required for this Shipping Rule')) if shipping_country not in [d.country for d in self.countries]: - frappe.throw(_('Shipping rule not applicable for country {0}').format(shipping_country)) + frappe.throw(_('Shipping rule not applicable for country {0} in Shipping Address').format(shipping_country)) def add_shipping_rule_to_tax_table(self, doc, shipping_amount): shipping_charge = { diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 422ace64f5..4cfeb251d6 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -11,7 +11,7 @@ from frappe.utils import (add_days, getdate, formatdate, date_diff, add_years, get_timestamp, nowdate, flt, cstr, add_months, get_last_day) from frappe.contacts.doctype.address.address import (get_address_display, get_default_address, get_company_address) -from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact +from frappe.contacts.doctype.contact.contact import get_contact_details from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrency from erpnext.accounts.utils import get_fiscal_year from erpnext import get_company_currency @@ -281,8 +281,8 @@ def validate_party_gle_currency(party_type, party, company, party_account_curren existing_gle_currency = get_party_gle_currency(party_type, party, company) if existing_gle_currency and party_account_currency != existing_gle_currency: - frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}") - .format(party_type, party, existing_gle_currency), InvalidAccountCurrency) + frappe.throw(_("{0} {1} has accounting entries in currency {2} for company {3}. Please select a receivable or payable account with currency {2}.") + .format(frappe.bold(party_type), frappe.bold(party), frappe.bold(existing_gle_currency), frappe.bold(company)), InvalidAccountCurrency) def validate_party_accounts(doc): companies = [] @@ -295,15 +295,13 @@ def validate_party_accounts(doc): companies.append(account.company) party_account_currency = frappe.db.get_value("Account", account.account, "account_currency", cache=True) - existing_gle_currency = get_party_gle_currency(doc.doctype, doc.name, account.company) if frappe.db.get_default("Company"): company_default_currency = frappe.get_cached_value('Company', frappe.db.get_default("Company"), "default_currency") else: company_default_currency = frappe.db.get_value('Company', account.company, "default_currency") - if existing_gle_currency and party_account_currency != existing_gle_currency: - frappe.throw(_("Accounting entries have already been made in currency {0} for company {1}. Please select a receivable or payable account with currency {0}.").format(existing_gle_currency, account.company)) + validate_party_gle_currency(doc.doctype, doc.name, account.company, party_account_currency) if doc.get("default_currency") and party_account_currency and company_default_currency: if doc.default_currency != party_account_currency and doc.default_currency != company_default_currency: @@ -615,3 +613,26 @@ def get_partywise_advanced_payment_amount(party_type, posting_date = None): if data: return frappe._dict(data) + +def get_default_contact(doctype, name): + """ + Returns default contact for the given doctype and name. + Can be ordered by `contact_type` to either is_primary_contact or is_billing_contact. + """ + out = frappe.db.sql(""" + SELECT dl.parent, c.is_primary_contact, c.is_billing_contact + FROM `tabDynamic Link` dl + INNER JOIN tabContact c ON c.name = dl.parent + WHERE + dl.link_doctype=%s AND + dl.link_name=%s AND + dl.parenttype = "Contact" + ORDER BY is_primary_contact DESC, is_billing_contact DESC + """, (doctype, name)) + if out: + try: + return out[0][0] + except: + return None + else: + return None \ No newline at end of file diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index 791f3f8008..bb0d0a132a 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -218,15 +218,15 @@ {%= __("Total") %} - {%= format_currency(data[i]["invoiced"], data[i]["currency"] ) %} + {%= format_currency(data[i]["invoiced"], data[0]["currency"] ) %} {% if(!filters.show_future_payments) { %} - {%= format_currency(data[i]["paid"], data[i]["currency"]) %} - {%= format_currency(data[i]["credit_note"], data[i]["currency"]) %} + {%= format_currency(data[i]["paid"], data[0]["currency"]) %} + {%= format_currency(data[i]["credit_note"], data[0]["currency"]) %} {% } %} - {%= format_currency(data[i]["outstanding"], data[i]["currency"]) %} + {%= format_currency(data[i]["outstanding"], data[0]["currency"]) %} {% if(filters.show_future_payments) { %} {% if(report.report_name === "Accounts Receivable") { %} @@ -234,8 +234,8 @@ {%= data[i]["po_no"] %} {% } %} {%= data[i]["future_ref"] %} - {%= format_currency(data[i]["future_amount"], data[i]["currency"]) %} - {%= format_currency(data[i]["remaining_balance"], data[i]["currency"]) %} + {%= format_currency(data[i]["future_amount"], data[0]["currency"]) %} + {%= format_currency(data[i]["remaining_balance"], data[0]["currency"]) %} {% } %} {% } %} {% } else { %} @@ -256,10 +256,10 @@ {% } else { %} {%= __("Total") %} {% } %} - {%= format_currency(data[i]["invoiced"], data[i]["currency"]) %} - {%= format_currency(data[i]["paid"], data[i]["currency"]) %} - {%= format_currency(data[i]["credit_note"], data[i]["currency"]) %} - {%= format_currency(data[i]["outstanding"], data[i]["currency"]) %} + {%= format_currency(data[i]["invoiced"], data[0]["currency"]) %} + {%= format_currency(data[i]["paid"], data[0]["currency"]) %} + {%= format_currency(data[i]["credit_note"], data[0]["currency"]) %} + {%= format_currency(data[i]["outstanding"], data[0]["currency"]) %} {% } %} {% } %} diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 97ce4f21e8..a858c1998f 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -9,6 +9,7 @@ from erpnext.accounts.report.financial_statements import (get_period_list, get_c def execute(filters=None): period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, + filters.period_start_date, filters.period_end_date, filters.filter_based_on, filters.periodicity, company=filters.company) currency = filters.presentation_currency or frappe.get_cached_value('Company', filters.company, "default_currency") @@ -58,7 +59,10 @@ def execute(filters=None): chart = get_chart_data(filters, columns, asset, liability, equity) - return columns, data, message, chart + report_summary = get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, + total_credit, currency, filters) + + return columns, data, message, chart, report_summary def get_provisional_profit_loss(asset, liability, equity, period_list, company, currency=None, consolidated=False): provisional_profit_loss = {} @@ -120,6 +124,56 @@ def check_opening_balance(asset, liability, equity): return _("Previous Financial Year is not closed"),opening_balance return None,None +def get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, total_credit, currency, + filters, consolidated=False): + + net_asset, net_liability, net_equity, net_provisional_profit_loss = 0.0, 0.0, 0.0, 0.0 + + if filters.get('accumulated_values'): + period_list = [period_list[-1]] + + for period in period_list: + key = period if consolidated else period.key + if asset: + net_asset += asset[-2].get(key) + if liability: + net_liability += liability[-2].get(key) + if equity: + net_equity += equity[-2].get(key) + if provisional_profit_loss: + net_provisional_profit_loss += provisional_profit_loss.get(key) + + return [ + { + "value": net_asset, + "label": "Total Asset", + "indicator": "Green", + "datatype": "Currency", + "currency": currency + }, + { + "value": net_liability, + "label": "Total Liability", + "datatype": "Currency", + "indicator": "Red", + "currency": currency + }, + { + "value": net_equity, + "label": "Total Equity", + "datatype": "Currency", + "indicator": "Blue", + "currency": currency + }, + { + "value": net_provisional_profit_loss, + "label": "Provisional Profit / Loss (Credit)", + "indicator": "Green" if net_provisional_profit_loss > 0 else "Red", + "datatype": "Currency", + "currency": currency + } + ] + def get_chart_data(filters, columns, asset, liability, equity): labels = [d.get("label") for d in columns[2:]] diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js index 89244c3781..e5d0c89918 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.js +++ b/erpnext/accounts/report/cash_flow/cash_flow.js @@ -9,14 +9,9 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { // filter. It won't be used in cash flow for now so we pop it. Please take // of this if you are working here. - frappe.query_reports["Cash Flow"]["filters"].splice(5, 1); + frappe.query_reports["Cash Flow"]["filters"].splice(8, 1); frappe.query_reports["Cash Flow"]["filters"].push( - { - "fieldname": "accumulated_values", - "label": __("Accumulated Values"), - "fieldtype": "Check" - }, { "fieldname": "include_default_book_entries", "label": __("Include Default Book Entries"), diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index e349a6aaaf..cf0946beab 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -8,6 +8,7 @@ from frappe.utils import cint, cstr from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data) from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss from erpnext.accounts.utils import get_fiscal_year +from six import iteritems def execute(filters=None): @@ -16,7 +17,8 @@ def execute(filters=None): return execute_custom(filters=filters) period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, - filters.periodicity, filters.accumulated_values, filters.company) + filters.period_start_date, filters.period_end_date, filters.filter_based_on, + filters.periodicity, company=filters.company) cash_flow_accounts = get_cash_flow_accounts() @@ -29,6 +31,7 @@ def execute(filters=None): net_profit_loss = get_net_profit_loss(income, expense, period_list, filters.company) data = [] + summary_data = {} company_currency = frappe.get_cached_value('Company', filters.company, "default_currency") for cash_flow_account in cash_flow_accounts: @@ -64,14 +67,16 @@ def execute(filters=None): section_data.append(account_data) add_total_row_account(data, section_data, cash_flow_account['section_footer'], - period_list, company_currency) + period_list, company_currency, summary_data) - add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency) + add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency, summary_data) columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) chart = get_chart_data(columns, data) - return columns, data, None, chart + report_summary = get_report_summary(summary_data, company_currency) + + return columns, data, None, chart, report_summary def get_cash_flow_accounts(): operation_accounts = { @@ -157,7 +162,7 @@ def get_start_date(period, accumulated_values, company): return start_date -def add_total_row_account(out, data, label, period_list, currency, consolidated = False): +def add_total_row_account(out, data, label, period_list, currency, summary_data, consolidated = False): total_row = { "account_name": "'" + _("{0}").format(label) + "'", "account": "'" + _("{0}").format(label) + "'", @@ -176,6 +181,24 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated out.append(total_row) out.append({}) + summary_data[label] = total_row["total"] + +def get_report_summary(summary_data, currency): + report_summary = [] + + for label, value in iteritems(summary_data): + report_summary.append( + { + "value": value, + "label": label, + "datatype": "Currency", + "currency": currency + } + ) + + return report_summary + + def get_chart_data(columns, data): labels = [d.get("label") for d in columns[2:]] datasets = [{'name':account.get('account').replace("'", ""), 'values': [account.get('total')]} for account in data if account.get('parent_account') == None and account.get('currency')] diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js index 48a030a99e..38fd5fa278 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js @@ -12,6 +12,39 @@ frappe.query_reports["Consolidated Financial Statement"] = { "default": frappe.defaults.get_user_default("Company"), "reqd": 1 }, + { + "fieldname":"filter_based_on", + "label": __("Filter Based On"), + "fieldtype": "Select", + "options": ["Fiscal Year", "Date Range"], + "default": ["Fiscal Year"], + "reqd": 1, + on_change: function() { + let filter_based_on = frappe.query_report.get_filter_value('filter_based_on'); + frappe.query_report.toggle_filter_display('from_fiscal_year', filter_based_on === 'Date Range'); + frappe.query_report.toggle_filter_display('to_fiscal_year', filter_based_on === 'Date Range'); + frappe.query_report.toggle_filter_display('period_start_date', filter_based_on === 'Fiscal Year'); + frappe.query_report.toggle_filter_display('period_end_date', filter_based_on === 'Fiscal Year'); + + frappe.query_report.refresh(); + } + }, + { + "fieldname":"period_start_date", + "label": __("Start Date"), + "fieldtype": "Date", + "default": frappe.datetime.nowdate(), + "hidden": 1, + "reqd": 1 + }, + { + "fieldname":"period_end_date", + "label": __("End Date"), + "fieldtype": "Date", + "default": frappe.datetime.add_months(frappe.datetime.nowdate(), 12), + "hidden": 1, + "reqd": 1 + }, { "fieldname":"from_fiscal_year", "label": __("Start Year"), @@ -61,5 +94,17 @@ frappe.query_reports["Consolidated Financial Statement"] = { "fieldtype": "Check", "default": 1 } - ] + ], + "formatter": function(value, row, column, data, default_formatter) { + value = default_formatter(value, row, column, data); + + if (!data.parent_account) { + value = $(`${value}`); + + var $value = $(value).css("font-weight", "bold"); + + value = $value.wrap("

").parent().html(); + } + return value; + } } diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index 4a79b6a340..b62238b59b 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -4,15 +4,15 @@ from __future__ import unicode_literals import frappe, erpnext from frappe import _ -from frappe.utils import flt, cint +from frappe.utils import flt, cint, getdate from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency from erpnext.accounts.report.financial_statements import get_fiscal_year_data, sort_accounts from erpnext.accounts.report.balance_sheet.balance_sheet import (get_provisional_profit_loss, - check_opening_balance, get_chart_data) + check_opening_balance, get_chart_data, get_report_summary as get_bs_summary) from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import (get_net_profit_loss, - get_chart_data as get_pl_chart_data) + get_chart_data as get_pl_chart_data, get_report_summary as get_pl_summary) from erpnext.accounts.report.cash_flow.cash_flow import (get_cash_flow_accounts, get_account_type_based_gl_data, - add_total_row_account) + add_total_row_account, get_report_summary as get_cash_flow_summary) def execute(filters=None): columns, data, message, chart = [], [], [], [] @@ -25,17 +25,17 @@ def execute(filters=None): columns = get_columns(companies_column) if filters.get('report') == "Balance Sheet": - data, message, chart = get_balance_sheet_data(fiscal_year, companies, columns, filters) + data, message, chart, report_summary = get_balance_sheet_data(fiscal_year, companies, columns, filters) elif filters.get('report') == "Profit and Loss Statement": - data, message, chart = get_profit_loss_data(fiscal_year, companies, columns, filters) + data, message, chart, report_summary = get_profit_loss_data(fiscal_year, companies, columns, filters) else: if cint(frappe.db.get_single_value('Accounts Settings', 'use_custom_cash_flow')): from erpnext.accounts.report.cash_flow.custom_cash_flow import execute as execute_custom return execute_custom(filters=filters) - data = get_cash_flow_data(fiscal_year, companies, filters) + data, report_summary = get_cash_flow_data(fiscal_year, companies, filters) - return columns, data, message, chart + return columns, data, message, chart, report_summary def get_balance_sheet_data(fiscal_year, companies, columns, filters): asset = get_data(companies, "Asset", "Debit", fiscal_year, filters=filters) @@ -75,9 +75,12 @@ def get_balance_sheet_data(fiscal_year, companies, columns, filters): if total_credit: data.append(total_credit) + report_summary = get_bs_summary(companies, asset, liability, equity, provisional_profit_loss, total_credit, + company_currency, filters, True) + chart = get_chart_data(filters, columns, asset, liability, equity) - return data, message, chart + return data, message, chart, report_summary def get_profit_loss_data(fiscal_year, companies, columns, filters): income, expense, net_profit_loss = get_income_expense_data(companies, fiscal_year, filters) @@ -90,7 +93,9 @@ def get_profit_loss_data(fiscal_year, companies, columns, filters): chart = get_pl_chart_data(filters, columns, income, expense, net_profit_loss) - return data, None, chart + report_summary = get_pl_summary(companies, '', income, expense, net_profit_loss, True) + + return data, None, chart, report_summary def get_income_expense_data(companies, fiscal_year, filters): company_currency = get_company_currency(filters) @@ -108,6 +113,7 @@ def get_cash_flow_data(fiscal_year, companies, filters): income, expense, net_profit_loss = get_income_expense_data(companies, fiscal_year, filters) data = [] + summary_data = {} company_currency = get_company_currency(filters) for cash_flow_account in cash_flow_accounts: @@ -142,11 +148,13 @@ def get_cash_flow_data(fiscal_year, companies, filters): section_data.append(account_data) add_total_row_account(data, section_data, cash_flow_account['section_footer'], - companies, company_currency, True) + companies, company_currency, summary_data, True) - add_total_row_account(data, data, _("Net Change in Cash"), companies, company_currency, True) + add_total_row_account(data, data, _("Net Change in Cash"), companies, company_currency, summary_data, True) - return data + report_summary = get_cash_flow_summary(summary_data, company_currency) + + return data, report_summary def get_account_type_based_data(account_type, companies, fiscal_year, filters): data = {} @@ -200,17 +208,24 @@ def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, i company_currency = get_company_currency(filters) + if filters.filter_based_on == 'Fiscal Year': + start_date = fiscal_year.year_start_date + end_date = fiscal_year.year_end_date + else: + start_date = filters.period_start_date + end_date = filters.period_end_date + gl_entries_by_account = {} for root in frappe.db.sql("""select lft, rgt from tabAccount where root_type=%s and ifnull(parent_account, '') = ''""", root_type, as_dict=1): - set_gl_entries_by_account(fiscal_year.year_start_date, - fiscal_year.year_end_date, root.lft, root.rgt, filters, + set_gl_entries_by_account(start_date, + end_date, root.lft, root.rgt, filters, gl_entries_by_account, accounts_by_name, ignore_closing_entries=False) - calculate_values(accounts_by_name, gl_entries_by_account, companies, fiscal_year, filters) + calculate_values(accounts_by_name, gl_entries_by_account, companies, start_date, filters) accumulate_values_into_parents(accounts, accounts_by_name, companies) - out = prepare_data(accounts, fiscal_year, balance_must_be, companies, company_currency) + out = prepare_data(accounts, start_date, end_date, balance_must_be, companies, company_currency) if out: add_total_row(out, root_type, balance_must_be, companies, company_currency) @@ -221,7 +236,7 @@ def get_company_currency(filters=None): return (filters.get('presentation_currency') or frappe.get_cached_value('Company', filters.company, "default_currency")) -def calculate_values(accounts_by_name, gl_entries_by_account, companies, fiscal_year, filters): +def calculate_values(accounts_by_name, gl_entries_by_account, companies, start_date, filters): for entries in gl_entries_by_account.values(): for entry in entries: key = entry.account_number or entry.account_name @@ -233,7 +248,7 @@ def calculate_values(accounts_by_name, gl_entries_by_account, companies, fiscal_ and entry.company in companies.get(company)): d[company] = d.get(company, 0.0) + flt(entry.debit) - flt(entry.credit) - if entry.posting_date < fiscal_year.year_start_date: + if entry.posting_date < getdate(start_date): d["opening_balance"] = d.get("opening_balance", 0.0) + flt(entry.debit) - flt(entry.credit) def accumulate_values_into_parents(accounts, accounts_by_name, companies): @@ -287,10 +302,8 @@ def get_accounts(root_type, filters): `tabAccount` where company = %s and root_type = %s """ , (filters.get('company'), root_type), as_dict=1) -def prepare_data(accounts, fiscal_year, balance_must_be, companies, company_currency): +def prepare_data(accounts, start_date, end_date, balance_must_be, companies, company_currency): data = [] - year_start_date = fiscal_year.year_start_date - year_end_date = fiscal_year.year_end_date for d in accounts: # add to output @@ -301,8 +314,8 @@ def prepare_data(accounts, fiscal_year, balance_must_be, companies, company_curr "account": _(d.account_name), "parent_account": _(d.parent_account), "indent": flt(d.indent), - "year_start_date": year_start_date, - "year_end_date": year_end_date, + "year_start_date": start_date, + "year_end_date": end_date, "currency": company_currency, "opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be == "Debit" else -1) }) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 080a7c9223..7fb598bd68 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -18,17 +18,20 @@ from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, for from six import itervalues from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children -def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False, +def get_period_list(from_fiscal_year, to_fiscal_year, period_start_date, period_end_date, filter_based_on, periodicity, accumulated_values=False, company=None, reset_period_on_fy_change=True): """Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label} Periodicity can be (Yearly, Quarterly, Monthly)""" - fiscal_year = get_fiscal_year_data(from_fiscal_year, to_fiscal_year) - validate_fiscal_year(fiscal_year, from_fiscal_year, to_fiscal_year) - - # start with first day, so as to avoid year to_dates like 2-April if ever they occur] - year_start_date = getdate(fiscal_year.year_start_date) - year_end_date = getdate(fiscal_year.year_end_date) + if filter_based_on == 'Fiscal Year': + fiscal_year = get_fiscal_year_data(from_fiscal_year, to_fiscal_year) + validate_fiscal_year(fiscal_year, from_fiscal_year, to_fiscal_year) + year_start_date = getdate(fiscal_year.year_start_date) + year_end_date = getdate(fiscal_year.year_end_date) + else: + validate_dates(period_start_date, period_end_date) + year_start_date = getdate(period_start_date) + year_end_date = getdate(period_end_date) months_to_add = { "Yearly": 12, @@ -42,6 +45,9 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_v start_date = year_start_date months = get_months(year_start_date, year_end_date) + if (months // months_to_add) != (months / months_to_add): + months += months_to_add + for i in range(months // months_to_add): period = frappe._dict({ "from_date": start_date @@ -103,9 +109,18 @@ def get_fiscal_year_data(from_fiscal_year, to_fiscal_year): def validate_fiscal_year(fiscal_year, from_fiscal_year, to_fiscal_year): - if not fiscal_year.get('year_start_date') and not fiscal_year.get('year_end_date'): + if not fiscal_year.get('year_start_date') or not fiscal_year.get('year_end_date'): + frappe.throw(_("Start Year and End Year are mandatory")) + + if getdate(fiscal_year.get('year_end_date')) < getdate(fiscal_year.get('year_start_date')): frappe.throw(_("End Year cannot be before Start Year")) +def validate_dates(from_date, to_date): + if not from_date or not to_date: + frappe.throw("From Date and To Date are mandatory") + + if to_date < from_date: + frappe.throw("To Date cannot be less than From Date") def get_months(start_date, end_date): diff = (12 * end_date.year + end_date.month) - (12 * start_date.year + start_date.month) @@ -151,7 +166,7 @@ def get_data( calculate_values( accounts_by_name, gl_entries_by_account, period_list, accumulated_values, ignore_accumulated_values_for_fy) - accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values) + accumulate_values_into_parents(accounts, accounts_by_name, period_list) out = prepare_data(accounts, balance_must_be, period_list, company_currency) out = filter_out_zero_value_rows(out, parent_children_map) @@ -191,7 +206,7 @@ def calculate_values( d["opening_balance"] = d.get("opening_balance", 0.0) + flt(entry.debit) - flt(entry.credit) -def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values): +def accumulate_values_into_parents(accounts, accounts_by_name, period_list): """accumulate children's values in parent accounts""" for d in reversed(accounts): if d.parent_account: @@ -419,7 +434,9 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters): if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'): filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type, filters.get(dimension.fieldname)) - additional_conditions.append("{0} in %({0})s".format(dimension.fieldname)) + additional_conditions.append("{0} in %({0})s".format(dimension.fieldname)) + else: + additional_conditions.append("{0} in (%({0})s)".format(dimension.fieldname)) return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else "" diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 8750c2325d..649b363c32 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -131,7 +131,7 @@ def get_gl_entries(filters): gl_entries = frappe.db.sql( """ select - posting_date, account, party_type, party, + name as gl_entry, posting_date, account, party_type, party, voucher_type, voucher_no, cost_center, project, against_voucher_type, against_voucher, account_currency, remarks, against, is_opening {select_fields} @@ -202,7 +202,9 @@ def get_conditions(filters): if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'): filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type, filters.get(dimension.fieldname)) - conditions.append("{0} in %({0})s".format(dimension.fieldname)) + conditions.append("{0} in %({0})s".format(dimension.fieldname)) + else: + conditions.append("{0} in (%({0})s)".format(dimension.fieldname)) return "and {}".format(" and ".join(conditions)) if conditions else "" @@ -362,6 +364,12 @@ def get_columns(filters): currency = get_company_currency(company) columns = [ + { + "fieldname": "gl_entry", + "fieldtype": "Link", + "options": "GL Entry", + "hidden": 1 + }, { "label": _("Posting Date"), "fieldname": "posting_date", diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js index baa0bda700..2b946c0540 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js @@ -15,11 +15,6 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { return frappe.db.get_link_options('Project', txt); } }, - { - "fieldname": "accumulated_values", - "label": __("Accumulated Values"), - "fieldtype": "Check" - }, { "fieldname": "include_default_book_entries", "label": __("Include Default Book Entries"), diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index b96fe69ba8..7caa7648b1 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -9,7 +9,8 @@ from erpnext.accounts.report.financial_statements import (get_period_list, get_c def execute(filters=None): period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, - filters.periodicity, filters.accumulated_values, filters.company) + filters.period_start_date, filters.period_end_date, filters.filter_based_on, filters.periodicity, + company=filters.company) income = get_data(filters.company, "Income", "Credit", period_list, filters = filters, accumulated_values=filters.accumulated_values, @@ -31,20 +32,22 @@ def execute(filters=None): chart = get_chart_data(filters, columns, income, expense, net_profit_loss) - report_summary = get_report_summary(columns, income, expense, net_profit_loss, filters.periodicity, period_list) + default_currency = frappe.get_cached_value('Company', filters.company, "default_currency") + report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss, default_currency) return columns, data, None, chart, report_summary -def get_report_summary(columns, income, expense, net_profit_loss, period_list, periodicity): - income_data, expense_data, net_profit = [], [], [] +def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, default_currency, consolidated=False): + net_income, net_expense, net_profit = 0.0, 0.0, 0.0 - for p in columns[2:]: + for period in period_list: + key = period if consolidated else period.key if income: - income_data.append(income[-2].get(p.get("fieldname"))) + net_income += income[-2].get(key) if expense: - expense_data.append(expense[-2].get(p.get("fieldname"))) + net_expense += expense[-2].get(key) if net_profit_loss: - net_profit.append(net_profit_loss.get(p.get("fieldname"))) + net_profit += net_profit_loss.get(key) if (len(period_list) == 1 and periodicity== 'Yearly'): profit_label = _("Profit This Year") @@ -57,23 +60,23 @@ def get_report_summary(columns, income, expense, net_profit_loss, period_list, p return [ { - "value": net_profit[-1], - "indicator": "Green" if net_profit[-1] > 0 else "Red", + "value": net_profit, + "indicator": "Green" if net_profit > 0 else "Red", "label": profit_label, "datatype": "Currency", - "currency": net_profit_loss.get("currency") + "currency": net_profit_loss.get("currency") if net_profit_loss else default_currency }, { - "value": income_data[-1], + "value": net_income, "label": income_label, "datatype": "Currency", - "currency": income[-1].get('currency') + "currency": income[-1].get('currency') if income else default_currency }, { - "value": expense_data[-1], + "value": net_expense, "label": expense_label, "datatype": "Currency", - "currency": expense[-1].get('currency') + "currency": expense[-1].get('currency') if expense else default_currency } ] diff --git a/erpnext/accounts/report/purchase_register/purchase_register.js b/erpnext/accounts/report/purchase_register/purchase_register.js index 42b35c2a99..b2b95b2b81 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.js +++ b/erpnext/accounts/report/purchase_register/purchase_register.js @@ -34,6 +34,33 @@ frappe.query_reports["Purchase Register"] = { "label": __("Mode of Payment"), "fieldtype": "Link", "options": "Mode of Payment" + }, + { + "fieldname":"cost_center", + "label": __("Cost Center"), + "fieldtype": "Link", + "options": "Cost Center" + }, + { + "fieldname":"warehouse", + "label": __("Warehouse"), + "fieldtype": "Link", + "options": "Warehouse" + }, + { + "fieldname":"item_group", + "label": __("Item Group"), + "fieldtype": "Link", + "options": "Item Group" } ] } + +erpnext.dimension_filters.forEach((dimension) => { + frappe.query_reports["Purchase Register"].filters.splice(7, 0 ,{ + "fieldname": dimension["fieldname"], + "label": __(dimension["label"]), + "fieldtype": "Link", + "options": dimension["document_type"] + }); +}); \ No newline at end of file diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 3f8abb76e2..9399e70739 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import flt from frappe import msgprint, _ +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children def execute(filters=None): return _execute(filters) @@ -66,7 +67,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum total_tax += tax_amount row.append(tax_amount) - # total tax, grand total, rounded total & outstanding amount + # total tax, grand total, rounded total & outstanding amount row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 0), inv.outstanding_amount] data.append(row) @@ -134,6 +135,38 @@ def get_conditions(filters): if filters.get("mode_of_payment"): conditions += " and ifnull(mode_of_payment, '') = %(mode_of_payment)s" + if filters.get("cost_center"): + conditions += """ and exists(select name from `tabPurchase Invoice Item` + where parent=`tabPurchase Invoice`.name + and ifnull(`tabPurchase Invoice Item`.cost_center, '') = %(cost_center)s)""" + + if filters.get("warehouse"): + conditions += """ and exists(select name from `tabPurchase Invoice Item` + where parent=`tabPurchase Invoice`.name + and ifnull(`tabPurchase Invoice Item`.warehouse, '') = %(warehouse)s)""" + + if filters.get("item_group"): + conditions += """ and exists(select name from `tabPurchase Invoice Item` + where parent=`tabPurchase Invoice`.name + and ifnull(`tabPurchase Invoice Item`.item_group, '') = %(item_group)s)""" + + accounting_dimensions = get_accounting_dimensions(as_list=False) + + if accounting_dimensions: + common_condition = """ + and exists(select name from `tabPurchase Invoice Item` + where parent=`tabPurchase Invoice`.name + """ + for dimension in accounting_dimensions: + if filters.get(dimension.fieldname): + if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'): + filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type, + filters.get(dimension.fieldname)) + + conditions += common_condition + "and ifnull(`tabPurchase Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname) + else: + conditions += common_condition + "and ifnull(`tabPurchase Invoice Item`.{0}, '') in (%({0})s))".format(dimension.fieldname) + return conditions def get_invoices(filters, additional_query_columns): diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 9864e40c1a..b6e61b1306 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -344,16 +344,19 @@ def get_conditions(filters): accounting_dimensions = get_accounting_dimensions(as_list=False) if accounting_dimensions: + common_condition = """ + and exists(select name from `tabSales Invoice Item` + where parent=`tabSales Invoice`.name + """ for dimension in accounting_dimensions: if filters.get(dimension.fieldname): if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'): filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type, filters.get(dimension.fieldname)) - conditions += """ and exists(select name from `tabSales Invoice Item` - where parent=`tabSales Invoice`.name - and ifnull(`tabSales Invoice Item`.{0}, '') in %({0})s)""".format(dimension.fieldname) - + conditions += common_condition + "and ifnull(`tabSales Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname) + else: + conditions += common_condition + "and ifnull(`tabSales Invoice Item`.{0}, '') in (%({0})s))".format(dimension.fieldname) return conditions diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 5fe6b416fd..d78324157a 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -126,7 +126,9 @@ def get_rootwise_opening_balances(filters, report_type): if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'): filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type, filters.get(dimension.fieldname)) - additional_conditions += "and {0} in %({0})s".format(dimension.fieldname) + additional_conditions += "and {0} in %({0})s".format(dimension.fieldname) + else: + additional_conditions += "and {0} in (%({0})s)".format(dimension.fieldname) query_filters.update({ dimension.fieldname: filters.get(dimension.fieldname) diff --git a/erpnext/agriculture/desk_page/agriculture/agriculture.json b/erpnext/agriculture/desk_page/agriculture/agriculture.json index 6020d628a2..e0d2c9ca25 100644 --- a/erpnext/agriculture/desk_page/agriculture/agriculture.json +++ b/erpnext/agriculture/desk_page/agriculture/agriculture.json @@ -1,16 +1,19 @@ { "cards": [ { - "links": "[\n {\n \"label\": \"Crop\",\n \"name\": \"Crop\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Crop Cycle\",\n \"name\": \"Crop Cycle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Location\",\n \"name\": \"Location\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Crops & Lands" + "hidden": 0, + "label": "Crops & Lands", + "links": "[\n {\n \"label\": \"Crop\",\n \"name\": \"Crop\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Crop Cycle\",\n \"name\": \"Crop Cycle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Location\",\n \"name\": \"Location\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Plant Analysis\",\n \"name\": \"Plant Analysis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Soil Analysis\",\n \"name\": \"Soil Analysis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Water Analysis\",\n \"name\": \"Water Analysis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Soil Texture\",\n \"name\": \"Soil Texture\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Weather\",\n \"name\": \"Weather\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Agriculture Analysis Criteria\",\n \"name\": \"Agriculture Analysis Criteria\",\n \"type\": \"doctype\"\n }\n]", - "title": "Analytics" + "hidden": 0, + "label": "Analytics", + "links": "[\n {\n \"label\": \"Plant Analysis\",\n \"name\": \"Plant Analysis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Soil Analysis\",\n \"name\": \"Soil Analysis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Water Analysis\",\n \"name\": \"Water Analysis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Soil Texture\",\n \"name\": \"Soil Texture\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Weather\",\n \"name\": \"Weather\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Agriculture Analysis Criteria\",\n \"name\": \"Agriculture Analysis Criteria\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Disease\",\n \"name\": \"Disease\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fertilizer\",\n \"name\": \"Fertilizer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Diseases & Fertilizers" + "hidden": 0, + "label": "Diseases & Fertilizers", + "links": "[\n {\n \"label\": \"Disease\",\n \"name\": \"Disease\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fertilizer\",\n \"name\": \"Fertilizer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" } ], "category": "Domains", @@ -24,7 +27,7 @@ "idx": 0, "is_standard": 1, "label": "Agriculture", - "modified": "2020-03-12 16:30:37.565413", + "modified": "2020-04-01 11:28:51.032822", "modified_by": "Administrator", "module": "Agriculture", "name": "Agriculture", diff --git a/erpnext/assets/desk_page/assets/assets.json b/erpnext/assets/desk_page/assets/assets.json index f9c65cb960..03094160e5 100644 --- a/erpnext/assets/desk_page/assets/assets.json +++ b/erpnext/assets/desk_page/assets/assets.json @@ -1,17 +1,19 @@ { "cards": [ { - "links": "[\n {\n \"label\": \"Asset\",\n \"name\": \"Asset\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Location\",\n \"name\": \"Location\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Asset Category\",\n \"name\": \"Asset Category\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Transfer an asset from one warehouse to another\",\n \"label\": \"Asset Movement\",\n \"name\": \"Asset Movement\",\n \"type\": \"doctype\"\n }\n]", - "title": "Assets" + "hidden": 0, + "label": "Assets", + "links": "[\n {\n \"label\": \"Asset\",\n \"name\": \"Asset\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Location\",\n \"name\": \"Location\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Asset Category\",\n \"name\": \"Asset Category\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Transfer an asset from one warehouse to another\",\n \"label\": \"Asset Movement\",\n \"name\": \"Asset Movement\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Asset Maintenance Team\",\n \"name\": \"Asset Maintenance Team\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset Maintenance Team\"\n ],\n \"label\": \"Asset Maintenance\",\n \"name\": \"Asset Maintenance\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset Maintenance\"\n ],\n \"label\": \"Asset Maintenance Log\",\n \"name\": \"Asset Maintenance Log\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"label\": \"Asset Value Adjustment\",\n \"name\": \"Asset Value Adjustment\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"label\": \"Asset Repair\",\n \"name\": \"Asset Repair\",\n \"type\": \"doctype\"\n }\n]", - "title": "Maintenance" + "hidden": 0, + "label": "Maintenance", + "links": "[\n {\n \"label\": \"Asset Maintenance Team\",\n \"name\": \"Asset Maintenance Team\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset Maintenance Team\"\n ],\n \"label\": \"Asset Maintenance\",\n \"name\": \"Asset Maintenance\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset Maintenance\"\n ],\n \"label\": \"Asset Maintenance Log\",\n \"name\": \"Asset Maintenance Log\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"label\": \"Asset Value Adjustment\",\n \"name\": \"Asset Value Adjustment\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"label\": \"Asset Repair\",\n \"name\": \"Asset Repair\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-table", - "links": "[\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"doctype\": \"Asset\",\n \"is_query_report\": true,\n \"label\": \"Asset Depreciation Ledger\",\n \"name\": \"Asset Depreciation Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"doctype\": \"Asset\",\n \"is_query_report\": true,\n \"label\": \"Asset Depreciations and Balances\",\n \"name\": \"Asset Depreciations and Balances\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Asset Maintenance\"\n ],\n \"doctype\": \"Asset Maintenance\",\n \"label\": \"Asset Maintenance\",\n \"name\": \"Asset Maintenance\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"doctype\": \"Asset\",\n \"is_query_report\": true,\n \"label\": \"Asset Depreciation Ledger\",\n \"name\": \"Asset Depreciation Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Asset\"\n ],\n \"doctype\": \"Asset\",\n \"is_query_report\": true,\n \"label\": \"Asset Depreciations and Balances\",\n \"name\": \"Asset Depreciations and Balances\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Asset Maintenance\"\n ],\n \"doctype\": \"Asset Maintenance\",\n \"label\": \"Asset Maintenance\",\n \"name\": \"Asset Maintenance\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", @@ -26,7 +28,7 @@ "idx": 0, "is_standard": 1, "label": "Assets", - "modified": "2020-03-12 16:30:38.651019", + "modified": "2020-04-01 11:28:51.072198", "modified_by": "Administrator", "module": "Assets", "name": "Assets", @@ -35,17 +37,17 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Asset", "link_to": "Asset", "type": "DocType" }, { - "is_query_report": 0, + "label": "Asset Movement", "link_to": "Asset Movement", "type": "DocType" }, { - "is_query_report": 0, + "label": "Fixed Asset Register", "link_to": "Fixed Asset Register", "type": "Report" } diff --git a/erpnext/buying/desk_page/buying/buying.json b/erpnext/buying/desk_page/buying/buying.json index ae8a605b85..5e764cf8bb 100644 --- a/erpnext/buying/desk_page/buying/buying.json +++ b/erpnext/buying/desk_page/buying/buying.json @@ -1,44 +1,46 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier Group master.\",\n \"label\": \"Supplier Group\",\n \"name\": \"Supplier Group\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Contacts.\",\n \"label\": \"Contact\",\n \"name\": \"Contact\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Addresses.\",\n \"label\": \"Address\",\n \"name\": \"Address\",\n \"type\": \"doctype\"\n }\n]", - "title": "Supplier" + "hidden": 0, + "label": "Supplier", + "links": "[\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier Group master.\",\n \"label\": \"Supplier Group\",\n \"name\": \"Supplier Group\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Contacts.\",\n \"label\": \"Contact\",\n \"name\": \"Contact\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Addresses.\",\n \"label\": \"Address\",\n \"name\": \"Address\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-star", - "links": "[\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"description\": \"Purchase Orders given to Suppliers.\",\n \"label\": \"Purchase Order\",\n \"name\": \"Purchase Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"label\": \"Purchase Invoice\",\n \"name\": \"Purchase Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Request for purchase.\",\n \"label\": \"Material Request\",\n \"name\": \"Material Request\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"description\": \"Request for quotation.\",\n \"label\": \"Request for Quotation\",\n \"name\": \"Request for Quotation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"description\": \"Quotations received from Suppliers.\",\n \"label\": \"Supplier Quotation\",\n \"name\": \"Supplier Quotation\",\n \"type\": \"doctype\"\n }\n]", - "title": "Purchasing" + "hidden": 0, + "label": "Purchasing", + "links": "[\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"description\": \"Purchase Orders given to Suppliers.\",\n \"label\": \"Purchase Order\",\n \"name\": \"Purchase Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"label\": \"Purchase Invoice\",\n \"name\": \"Purchase Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Request for purchase.\",\n \"label\": \"Material Request\",\n \"name\": \"Material Request\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"description\": \"Request for quotation.\",\n \"label\": \"Request for Quotation\",\n \"name\": \"Request for Quotation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"description\": \"Quotations received from Suppliers.\",\n \"label\": \"Supplier Quotation\",\n \"name\": \"Supplier Quotation\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"All Products or Services.\",\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Multiple Item prices.\",\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"onboard\": 1,\n \"route\": \"#Report/Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Price List master.\",\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bundle items at time of sale.\",\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of Item Groups.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for applying different promotional schemes.\",\n \"label\": \"Promotional Scheme\",\n \"name\": \"Promotional Scheme\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for applying pricing and discount.\",\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n }\n]", - "title": "Items and Pricing" + "hidden": 0, + "label": "Items and Pricing", + "links": "[\n {\n \"description\": \"All Products or Services.\",\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Multiple Item prices.\",\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"onboard\": 1,\n \"route\": \"#Report/Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Price List master.\",\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bundle items at time of sale.\",\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of Item Groups.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for applying different promotional schemes.\",\n \"label\": \"Promotional Scheme\",\n \"name\": \"Promotional Scheme\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for applying pricing and discount.\",\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-cog", - "links": "[\n {\n \"description\": \"Default settings for buying transactions.\",\n \"label\": \"Buying Settings\",\n \"name\": \"Buying Settings\",\n \"settings\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for buying transactions.\",\n \"label\": \"Purchase Taxes and Charges Template\",\n \"name\": \"Purchase Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Template of terms or contract.\",\n \"label\": \"Terms and Conditions Template\",\n \"name\": \"Terms and Conditions\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"description\": \"Default settings for buying transactions.\",\n \"label\": \"Buying Settings\",\n \"name\": \"Buying Settings\",\n \"settings\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for buying transactions.\",\n \"label\": \"Purchase Taxes and Charges Template\",\n \"name\": \"Purchase Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Template of terms or contract.\",\n \"label\": \"Terms and Conditions Template\",\n \"name\": \"Terms and Conditions\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"All Supplier scorecards.\",\n \"label\": \"Supplier Scorecard\",\n \"name\": \"Supplier Scorecard\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Templates of supplier scorecard variables.\",\n \"label\": \"Supplier Scorecard Variable\",\n \"name\": \"Supplier Scorecard Variable\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Templates of supplier scorecard criteria.\",\n \"label\": \"Supplier Scorecard Criteria\",\n \"name\": \"Supplier Scorecard Criteria\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Templates of supplier standings.\",\n \"label\": \"Supplier Scorecard Standing\",\n \"name\": \"Supplier Scorecard Standing\",\n \"type\": \"doctype\"\n }\n]", - "title": "Supplier Scorecard" + "hidden": 0, + "label": "Supplier Scorecard", + "links": "[\n {\n \"description\": \"All Supplier scorecards.\",\n \"label\": \"Supplier Scorecard\",\n \"name\": \"Supplier Scorecard\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Templates of supplier scorecard variables.\",\n \"label\": \"Supplier Scorecard Variable\",\n \"name\": \"Supplier Scorecard Variable\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Templates of supplier scorecard criteria.\",\n \"label\": \"Supplier Scorecard Criteria\",\n \"name\": \"Supplier Scorecard Criteria\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Templates of supplier standings.\",\n \"label\": \"Supplier Scorecard Standing\",\n \"name\": \"Supplier Scorecard Standing\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-table", - "links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Analytics\",\n \"name\": \"Purchase Analytics\",\n \"onboard\": 1,\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier-Wise Sales Analytics\",\n \"name\": \"Supplier-Wise Sales Analytics\",\n \"onboard\": 1,\n \"reference_doctype\": \"Stock Ledger Entry\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Order Trends\",\n \"name\": \"Purchase Order Trends\",\n \"onboard\": 1,\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Procurement Tracker\",\n \"name\": \"Procurement Tracker\",\n \"onboard\": 1,\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Requested Items To Be Ordered\",\n \"name\": \"Requested Items To Be Ordered\",\n \"onboard\": 1,\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n }\n]", - "title": "Key Reports" + "hidden": 0, + "label": "Key Reports", + "links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Analytics\",\n \"name\": \"Purchase Analytics\",\n \"onboard\": 1,\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier-Wise Sales Analytics\",\n \"name\": \"Supplier-Wise Sales Analytics\",\n \"onboard\": 1,\n \"reference_doctype\": \"Stock Ledger Entry\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Order Trends\",\n \"name\": \"Purchase Order Trends\",\n \"onboard\": 1,\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Procurement Tracker\",\n \"name\": \"Procurement Tracker\",\n \"onboard\": 1,\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Requested Items To Be Ordered\",\n \"name\": \"Requested Items To Be Ordered\",\n \"onboard\": 1,\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Items To Be Requested\",\n \"name\": \"Items To Be Requested\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase History\",\n \"name\": \"Item-wise Purchase History\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Material Requests for which Supplier Quotations are not created\",\n \"name\": \"Material Requests for which Supplier Quotations are not created\",\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"reference_doctype\": \"Address\",\n \"route_options\": {\n \"party_type\": \"Supplier\"\n },\n \"type\": \"report\"\n }\n]", - "title": "Other Reports" + "hidden": 0, + "label": "Other Reports", + "links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Items To Be Requested\",\n \"name\": \"Items To Be Requested\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase History\",\n \"name\": \"Item-wise Purchase History\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Material Requests for which Supplier Quotations are not created\",\n \"name\": \"Material Requests for which Supplier Quotations are not created\",\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"reference_doctype\": \"Address\",\n \"route_options\": {\n \"party_type\": \"Supplier\"\n },\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", "charts": [ { "chart_name": "Expenses", - "label": "Expenses", - "size": "Full" + "label": "Expenses" } ], "creation": "2020-01-28 11:50:26.195467", @@ -51,7 +53,7 @@ "idx": 0, "is_standard": 1, "label": "Buying", - "modified": "2020-03-12 16:30:40.779078", + "modified": "2020-04-01 11:28:51.192097", "modified_by": "Administrator", "module": "Buying", "name": "Buying", @@ -61,30 +63,30 @@ "shortcuts": [ { "format": "{} Unpaid", - "is_query_report": 0, + "label": "Purchase Invoice", "link_to": "Purchase Invoice", "stats_filter": "{\n \"company\": [\"like\", '%' + frappe.defaults.get_global_default(\"company\") + '%'],\n \"status\": \"Unpaid\"\n}", "type": "DocType" }, { "format": "{} to receive", - "is_query_report": 0, + "label": "Purchase Order", "link_to": "Purchase Order", "stats_filter": "{\n \"company\": [\"like\", '%' + frappe.defaults.get_global_default(\"company\") + '%'],\n \"status\": \"To Receive\"\n}", "type": "DocType" }, { - "is_query_report": 0, + "label": "Supplier Quotation", "link_to": "Supplier Quotation", "type": "DocType" }, { - "is_query_report": 0, + "label": "Accounts Payable", "link_to": "Accounts Payable", "type": "Report" }, { - "is_query_report": 0, + "label": "Purchase Register", "link_to": "Purchase Register", "type": "Report" } diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index a3264a4c0f..3111a3a7d5 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -499,7 +499,8 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( reference_doctype: me.frm.doctype, reference_name: me.frm.docname, content: __('Reason for hold: ')+data.reason_for_hold, - comment_email: frappe.session.user + comment_email: frappe.session.user, + comment_by: frappe.session.user_fullname }, callback: function(r) { if(!r.exc) { diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 1ab171ae37..4606395ebe 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -27,6 +27,8 @@ "supplier_type", "pan", "language", + "allow_purchase_invoice_creation_without_purchase_order", + "allow_purchase_invoice_creation_without_purchase_receipt", "disabled", "warn_rfqs", "warn_pos", @@ -364,13 +366,25 @@ "fieldname": "is_frozen", "fieldtype": "Check", "label": "Is Frozen" + }, + { + "default": "0", + "fieldname": "allow_purchase_invoice_creation_without_purchase_order", + "fieldtype": "Check", + "label": "Allow Purchase Invoice Creation Without Purchase Order" + }, + { + "default": "0", + "fieldname": "allow_purchase_invoice_creation_without_purchase_receipt", + "fieldtype": "Check", + "label": "Allow Purchase Invoice Creation Without Purchase Receipt" } ], "icon": "fa fa-user", "idx": 370, "image_field": "image", "links": [], - "modified": "2019-12-19 18:17:16.614567", + "modified": "2020-03-17 09:48:30.578242", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", diff --git a/erpnext/buying/doctype/supplier/supplier_dashboard.py b/erpnext/buying/doctype/supplier/supplier_dashboard.py index b3b294d570..d0d5b73984 100644 --- a/erpnext/buying/doctype/supplier/supplier_dashboard.py +++ b/erpnext/buying/doctype/supplier/supplier_dashboard.py @@ -34,4 +34,4 @@ def get_data(): 'items': ['Pricing Rule'] } ] - } + } \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js index 39042b8b06..16061c61ba 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js @@ -4,15 +4,17 @@ // attach required files {% include 'erpnext/public/js/controllers/buying.js' %}; -frappe.ui.form.on('Suppier Quotation', { - setup: function(frm) { - frm.custom_make_buttons = { - 'Purchase Order': 'Purchase Order' - } - } -}); - erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({ + setup: function() { + this.frm.custom_make_buttons = { + 'Purchase Order': 'Purchase Order', + 'Quotation': 'Quotation', + 'Subscription': 'Subscription' + } + + this._super(); + }, + refresh: function() { var me = this; this._super(); diff --git a/erpnext/communication/desk_page/communication/communication.json b/erpnext/communication/desk_page/communication/communication.json deleted file mode 100644 index 59318fb8cd..0000000000 --- a/erpnext/communication/desk_page/communication/communication.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "cards": [], - "charts": [], - "creation": "2020-01-28 11:49:55.003637", - "developer_mode_only": 0, - "disable_user_customization": 0, - "docstatus": 0, - "doctype": "Desk Page", - "extends_another_page": 0, - "icon": "", - "idx": 0, - "is_standard": 1, - "label": "Communication", - "modified": "2020-03-12 16:30:40.534226", - "modified_by": "Administrator", - "module": "Communication", - "name": "Communication", - "owner": "Administrator", - "pin_to_bottom": 0, - "pin_to_top": 0, - "shortcuts": [] -} \ No newline at end of file diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index d661bcbf34..d95753df90 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -19,6 +19,7 @@ from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_t from erpnext.exceptions import InvalidCurrency from six import text_type from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +from erpnext.stock.get_item_details import get_item_warehouse force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules") @@ -438,7 +439,7 @@ class AccountsController(TransactionBase): if account_currency not in valid_currency: frappe.throw(_("Account {0} is invalid. Account Currency must be {1}") - .format(account, _(" or ").join(valid_currency))) + .format(account, (' ' + _("or") + ' ').join(valid_currency))) def clear_unallocated_advances(self, childtype, parentfield): self.set(parentfield, self.get(parentfield, {"allocated_amount": ["not in", [0, None, ""]]})) @@ -833,7 +834,7 @@ class AccountsController(TransactionBase): for d in self.get("payment_schedule"): if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date): - frappe.throw(_("Row {0}: Due Date cannot be before posting date").format(d.idx)) + frappe.throw(_("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(d.idx)) elif d.due_date in dates: li.append(_("{0} in row {1}").format(d.due_date, d.idx)) dates.append(d.due_date) @@ -1126,16 +1127,16 @@ def set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, """ Returns a Sales Order Item child item containing the default values """ - p_doctype = frappe.get_doc(parent_doctype, parent_doctype_name) - child_item = frappe.new_doc('Sales Order Item', p_doctype, child_docname) + p_doc = frappe.get_doc(parent_doctype, parent_doctype_name) + child_item = frappe.new_doc('Sales Order Item', p_doc, child_docname) item = frappe.get_doc("Item", item_code) child_item.item_code = item.item_code child_item.item_name = item.item_name child_item.description = item.description - child_item.reqd_by_date = p_doctype.delivery_date + child_item.reqd_by_date = p_doc.delivery_date child_item.uom = item.stock_uom child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0 - child_item.warehouse = p_doctype.set_warehouse or p_doctype.items[0].warehouse + child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True) return child_item @@ -1143,13 +1144,13 @@ def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docna """ Returns a Purchase Order Item child item containing the default values """ - p_doctype = frappe.get_doc(parent_doctype, parent_doctype_name) - child_item = frappe.new_doc('Purchase Order Item', p_doctype, child_docname) + p_doc = frappe.get_doc(parent_doctype, parent_doctype_name) + child_item = frappe.new_doc('Purchase Order Item', p_doc, child_docname) item = frappe.get_doc("Item", item_code) child_item.item_code = item.item_code child_item.item_name = item.item_name child_item.description = item.description - child_item.schedule_date = p_doctype.schedule_date + child_item.schedule_date = p_doc.schedule_date child_item.uom = item.stock_uom child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0 child_item.base_rate = 1 # Initiallize value will update in parent validation diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 8d3db8d534..0e72ec2853 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -45,6 +45,7 @@ class BuyingController(StockController): self.validate_warehouse() self.validate_from_warehouse() self.set_supplier_address() + self.validate_asset_return() if self.doctype=="Purchase Invoice": self.validate_purchase_receipt_if_update_stock() @@ -100,6 +101,19 @@ class BuyingController(StockController): for d in tax_for_valuation: d.category = 'Total' msgprint(_('Tax Category has been changed to "Total" because all the Items are non-stock items')) + + def validate_asset_return(self): + if self.doctype not in ['Purchase Receipt', 'Purchase Invoice'] or not self.is_return: + return + + purchase_doc_field = 'purchase_receipt' if self.doctype == 'Purchase Receipt' else 'purchase_invoice' + not_cancelled_asset = [d.name for d in frappe.db.get_all("Asset", { + purchase_doc_field: self.return_against, + "docstatus": 1 + })] + if self.is_return and len(not_cancelled_asset): + frappe.throw(_("{} has submitted assets linked to it. You need to cancel the assets to create purchase return.".format(self.return_against)), + title=_("Not Allowed")) def get_asset_items(self): if self.doctype not in ['Purchase Order', 'Purchase Invoice', 'Purchase Receipt']: @@ -672,19 +686,32 @@ class BuyingController(StockController): # If asset has to be auto created # Check for asset naming series if item_data.get('asset_naming_series'): + created_assets = [] + for qty in range(cint(d.qty)): - self.make_asset(d) - is_plural = 's' if cint(d.qty) != 1 else '' - messages.append(_('{0} Asset{2} Created for {1}').format(cint(d.qty), d.item_code, is_plural)) + asset = self.make_asset(d) + created_assets.append(asset) + + if len(created_assets) > 5: + # dont show asset form links if more than 5 assets are created + messages.append(_('{} Asset{} created for {}').format(len(created_assets), is_plural, frappe.bold(d.item_code))) + else: + assets_link = list(map(lambda d: frappe.utils.get_link_to_form('Asset', d), created_assets)) + assets_link = frappe.bold(','.join(assets_link)) + + is_plural = 's' if len(created_assets) != 1 else '' + messages.append( + _('Asset{} {assets_link} created for {}').format(is_plural, frappe.bold(d.item_code), assets_link=assets_link) + ) else: - frappe.throw(_("Row {1}: Asset Naming Series is mandatory for the auto creation for item {0}") - .format(d.item_code, d.idx)) + frappe.throw(_("Row {}: Asset Naming Series is mandatory for the auto creation for item {}") + .format(d.idx, frappe.bold(d.item_code))) else: - messages.append(_("Assets not created for {0}. You will have to create asset manually.") - .format(d.item_code)) + messages.append(_("Assets not created for {0}. You will have to create asset manually.") + .format(frappe.bold(d.item_code))) for message in messages: - frappe.msgprint(message, title="Success") + frappe.msgprint(message, title="Success", indicator="green") def make_asset(self, row): if not row.asset_location: @@ -716,6 +743,8 @@ class BuyingController(StockController): asset.set_missing_values() asset.insert() + return asset.name + def update_fixed_asset(self, field, delete_asset = False): for d in self.get("items"): if d.is_fixed_asset: @@ -745,7 +774,7 @@ class BuyingController(StockController): asset.supplier = None if asset.docstatus == 1 and delete_asset: frappe.throw(_('Cannot cancel this document as it is linked with submitted asset {0}.\ - Please cancel the it to continue.').format(asset.name)) + Please cancel the it to continue.').format(frappe.utils.get_link_to_form('Asset', asset.name))) asset.flags.ignore_validate_update_after_submit = True asset.flags.ignore_mandatory = True @@ -1026,4 +1055,4 @@ def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty available_batches.append({'batch': batch, 'qty': available_qty}) required_qty -= available_qty - return available_batches \ No newline at end of file + return available_batches diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index d18f8e54d8..c14bb669a4 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe +import erpnext from frappe.desk.reportview import get_match_cond, get_filters_cond from frappe.utils import nowdate, getdate from collections import defaultdict @@ -129,23 +130,26 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters): }) def tax_account_query(doctype, txt, searchfield, start, page_len, filters): + company_currency = erpnext.get_company_currency(filters.get('company')) + tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount where tabAccount.docstatus!=2 and account_type in (%s) and is_group = 0 and company = %s + and account_currency = %s and `%s` LIKE %s order by idx desc, name limit %s, %s""" % - (", ".join(['%s']*len(filters.get("account_type"))), "%s", searchfield, "%s", "%s", "%s"), - tuple(filters.get("account_type") + [filters.get("company"), "%%%s%%" % txt, + (", ".join(['%s']*len(filters.get("account_type"))), "%s", "%s", searchfield, "%s", "%s", "%s"), + tuple(filters.get("account_type") + [filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len])) if not tax_accounts: tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount where tabAccount.docstatus!=2 and is_group = 0 - and company = %s and `%s` LIKE %s limit %s, %s""" - % ("%s", searchfield, "%s", "%s", "%s"), - (filters.get("company"), "%%%s%%" % txt, start, page_len)) + and company = %s and account_currency = %s and `%s` LIKE %s limit %s, %s""" #nosec + % ("%s", "%s", searchfield, "%s", "%s", "%s"), + (filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len)) return tax_accounts @@ -175,6 +179,12 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals # scan description only if items are less than 50000 description_cond = 'or tabItem.description LIKE %(txt)s' + extra_cond = " and tabItem.has_variants=0" + if (filters and isinstance(filters, dict) + and filters.get("doctype") == "BOM"): + extra_cond = "" + del filters["doctype"] + return frappe.db.sql("""select tabItem.name, if(length(tabItem.item_name) > 40, concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name, @@ -184,11 +194,11 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals {columns} from tabItem where tabItem.docstatus < 2 - and tabItem.has_variants=0 and tabItem.disabled=0 and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00') and ({scond} or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s) {description_cond}) + {extra_cond} {fcond} {mcond} order by if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999), @@ -199,6 +209,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals key=searchfield, columns=columns, scond=searchfields, + extra_cond=extra_cond, fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'), mcond=get_match_cond(doctype).replace('%', '%%'), description_cond = description_cond), diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 4d0520abc8..de76e45cd1 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -69,16 +69,16 @@ status_map = { ["Cancelled", "eval:self.docstatus==2"], ["Closed", "eval:self.status=='Closed'"], ], - "Purchase Invoice": [ - ["Draft", None], - ["Submitted", "eval:self.docstatus==1"], - ["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"], - ["Return", "eval:self.is_return==1 and self.docstatus==1"], - ["Debit Note Issued", - "eval:self.outstanding_amount <= 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"], - ["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], - ["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], - ["Cancelled", "eval:self.docstatus==2"], + "Purchase Invoice": [ + ["Draft", None], + ["Submitted", "eval:self.docstatus==1"], + ["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"], + ["Return", "eval:self.is_return==1 and self.docstatus==1"], + ["Debit Note Issued", + "eval:self.outstanding_amount <= 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"], + ["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], + ["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], + ["Cancelled", "eval:self.docstatus==2"], ], "Material Request": [ ["Draft", None], diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index f6908c06bd..4037f2f60f 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -21,6 +21,7 @@ class StockController(AccountsController): super(StockController, self).validate() self.validate_inspection() self.validate_serialized_batch() + self.validate_customer_provided_item() def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False): if self.docstatus == 2: @@ -377,6 +378,15 @@ class StockController(AccountsController): for blanket_order in blanket_orders: frappe.get_doc("Blanket Order", blanket_order).update_ordered_qty() + def validate_customer_provided_item(self): + for d in self.get('items'): + # Customer Provided parts will have zero valuation rate + if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'): + d.allow_zero_valuation_rate = 1 + if d.parenttype in ["Delivery Note", "Sales Invoice"] and d.rate: + frappe.throw(_("Row #{0}: {1} cannot have {2} as it is a Customer Provided Item") + .format(d.idx, frappe.bold(d.item_code), frappe.bold("Rate"))) + 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): diff --git a/erpnext/crm/desk_page/crm/crm.json b/erpnext/crm/desk_page/crm/crm.json index 9ebbe27121..4a599fe478 100644 --- a/erpnext/crm/desk_page/crm/crm.json +++ b/erpnext/crm/desk_page/crm/crm.json @@ -1,24 +1,24 @@ { "cards": [ { - "icon": "fa fa-star", - "links": "[\n {\n \"description\": \"Database of potential customers.\",\n \"label\": \"Lead\",\n \"name\": \"Lead\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Potential opportunities for selling.\",\n \"label\": \"Opportunity\",\n \"name\": \"Opportunity\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Contacts.\",\n \"label\": \"Contact\",\n \"name\": \"Contact\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Record of all communications of type email, phone, chat, visit, etc.\",\n \"label\": \"Communication\",\n \"name\": \"Communication\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Track Leads by Lead Source.\",\n \"label\": \"Lead Source\",\n \"name\": \"Lead Source\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Helps you keep tracks of Contracts based on Supplier, Customer and Employee\",\n \"label\": \"Contract\",\n \"name\": \"Contract\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Helps you manage appointments with your leads\",\n \"label\": \"Appointment\",\n \"name\": \"Appointment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Newsletter\",\n \"name\": \"Newsletter\",\n \"type\": \"doctype\"\n }\n]", - "title": "Sales Pipeline" + "hidden": 0, + "label": "Sales Pipeline", + "links": "[\n {\n \"description\": \"Database of potential customers.\",\n \"label\": \"Lead\",\n \"name\": \"Lead\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Potential opportunities for selling.\",\n \"label\": \"Opportunity\",\n \"name\": \"Opportunity\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Contacts.\",\n \"label\": \"Contact\",\n \"name\": \"Contact\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Record of all communications of type email, phone, chat, visit, etc.\",\n \"label\": \"Communication\",\n \"name\": \"Communication\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Track Leads by Lead Source.\",\n \"label\": \"Lead Source\",\n \"name\": \"Lead Source\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Helps you keep tracks of Contracts based on Supplier, Customer and Employee\",\n \"label\": \"Contract\",\n \"name\": \"Contract\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Helps you manage appointments with your leads\",\n \"label\": \"Appointment\",\n \"name\": \"Appointment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Newsletter\",\n \"name\": \"Newsletter\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Sales Funnel\",\n \"name\": \"sales-funnel\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Prospects Engaged But Not Converted\",\n \"name\": \"Prospects Engaged But Not Converted\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Opportunity\"\n ],\n \"doctype\": \"Opportunity\",\n \"is_query_report\": true,\n \"label\": \"Minutes to First Response for Opportunity\",\n \"name\": \"Minutes to First Response for Opportunity\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Inactive Customers\",\n \"name\": \"Inactive Customers\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Campaign Efficiency\",\n \"name\": \"Campaign Efficiency\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Owner Efficiency\",\n \"name\": \"Lead Owner Efficiency\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Sales Funnel\",\n \"name\": \"sales-funnel\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Prospects Engaged But Not Converted\",\n \"name\": \"Prospects Engaged But Not Converted\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Opportunity\"\n ],\n \"doctype\": \"Opportunity\",\n \"is_query_report\": true,\n \"label\": \"Minutes to First Response for Opportunity\",\n \"name\": \"Minutes to First Response for Opportunity\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Inactive Customers\",\n \"name\": \"Inactive Customers\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Campaign Efficiency\",\n \"name\": \"Campaign Efficiency\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Owner Efficiency\",\n \"name\": \"Lead Owner Efficiency\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-cog", - "links": "[\n {\n \"description\": \"Manage Customer Group Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Customer Group\",\n \"link\": \"Tree/Customer Group\",\n \"name\": \"Customer Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Territory Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Territory\",\n \"link\": \"Tree/Territory\",\n \"name\": \"Territory\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Sales Person Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Sales Person\",\n \"link\": \"Tree/Sales Person\",\n \"name\": \"Sales Person\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Sales campaigns.\",\n \"label\": \"Campaign\",\n \"name\": \"Campaign\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Sends Mails to lead or contact based on a Campaign schedule\",\n \"label\": \"Email Campaign\",\n \"name\": \"Email Campaign\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Send mass SMS to your contacts\",\n \"label\": \"SMS Center\",\n \"name\": \"SMS Center\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Logs for maintaining sms delivery status\",\n \"label\": \"SMS Log\",\n \"name\": \"SMS Log\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup SMS gateway settings\",\n \"label\": \"SMS Settings\",\n \"name\": \"SMS Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Email Group\",\n \"name\": \"Email Group\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"description\": \"Manage Customer Group Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Customer Group\",\n \"link\": \"Tree/Customer Group\",\n \"name\": \"Customer Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Territory Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Territory\",\n \"link\": \"Tree/Territory\",\n \"name\": \"Territory\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Sales Person Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Sales Person\",\n \"link\": \"Tree/Sales Person\",\n \"name\": \"Sales Person\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Sales campaigns.\",\n \"label\": \"Campaign\",\n \"name\": \"Campaign\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Sends Mails to lead or contact based on a Campaign schedule\",\n \"label\": \"Email Campaign\",\n \"name\": \"Email Campaign\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Send mass SMS to your contacts\",\n \"label\": \"SMS Center\",\n \"name\": \"SMS Center\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Logs for maintaining sms delivery status\",\n \"label\": \"SMS Log\",\n \"name\": \"SMS Log\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup SMS gateway settings\",\n \"label\": \"SMS Settings\",\n \"name\": \"SMS Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Email Group\",\n \"name\": \"Email Group\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-star", - "links": "[\n {\n \"description\": \"Plan for maintenance visits.\",\n \"label\": \"Maintenance Schedule\",\n \"name\": \"Maintenance Schedule\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Visit report for maintenance call.\",\n \"label\": \"Maintenance Visit\",\n \"name\": \"Maintenance Visit\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Warranty Claim against Serial No.\",\n \"label\": \"Warranty Claim\",\n \"name\": \"Warranty Claim\",\n \"type\": \"doctype\"\n }\n]", - "title": "Maintenance" + "hidden": 0, + "label": "Maintenance", + "links": "[\n {\n \"description\": \"Plan for maintenance visits.\",\n \"label\": \"Maintenance Schedule\",\n \"name\": \"Maintenance Schedule\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Visit report for maintenance call.\",\n \"label\": \"Maintenance Visit\",\n \"name\": \"Maintenance Visit\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Warranty Claim against Serial No.\",\n \"label\": \"Warranty Claim\",\n \"name\": \"Warranty Claim\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Modules", @@ -33,7 +33,7 @@ "idx": 0, "is_standard": 1, "label": "CRM", - "modified": "2020-03-12 16:30:41.142037", + "modified": "2020-04-01 11:28:51.219999", "modified_by": "Administrator", "module": "CRM", "name": "CRM", @@ -43,25 +43,25 @@ "shortcuts": [ { "format": "Open", - "is_query_report": 0, + "label": "Lead", "link_to": "Lead", "stats_filter": "{\"status\":\"Open\"}", "type": "DocType" }, { "format": "{} Assigned", - "is_query_report": 0, + "label": "Opportunity", "link_to": "Opportunity", "stats_filter": "{\"_assign\": [\"like\", '%' + frappe.session.user + '%']}", "type": "DocType" }, { - "is_query_report": 0, + "label": "Customer", "link_to": "Customer", "type": "DocType" }, { - "is_query_report": 0, + "label": "Sales Analytics", "link_to": "Sales Analytics", "type": "Report" } diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json index bc007b146f..20ab51d44b 100644 --- a/erpnext/crm/doctype/lead/lead.json +++ b/erpnext/crm/doctype/lead/lead.json @@ -1,5 +1,4 @@ { - "actions": [], "allow_events_in_timeline": 1, "allow_import": 1, "autoname": "naming_series:", @@ -33,6 +32,7 @@ "notes", "address_info", "address_html", + "address_type", "address_title", "address_line1", "address_line2", @@ -171,7 +171,6 @@ "options": "Customer" }, { - "depends_on": "eval: doc.source==\"Campaign\"", "fieldname": "campaign_name", "fieldtype": "Link", "label": "Campaign Name", @@ -285,8 +284,7 @@ "depends_on": "eval: doc.__islocal", "fieldname": "pincode", "fieldtype": "Data", - "label": "Postal Code", - "options": "Country" + "label": "Postal Code" }, { "fieldname": "column_break2", @@ -304,7 +302,8 @@ "fieldtype": "Data", "label": "Phone", "oldfieldname": "contact_no", - "oldfieldtype": "Data" + "oldfieldtype": "Data", + "options": "Phone" }, { "depends_on": "eval: doc.__islocal", @@ -312,7 +311,8 @@ "fieldtype": "Data", "label": "Mobile No.", "oldfieldname": "mobile_no", - "oldfieldtype": "Data" + "oldfieldtype": "Data", + "options": "Phone" }, { "depends_on": "eval: doc.__islocal", @@ -433,13 +433,21 @@ "fieldname": "contact_section", "fieldtype": "Section Break", "label": "Contact" + }, + { + "default": "Billing", + "depends_on": "eval: doc.__islocal", + "fieldname": "address_type", + "fieldtype": "Select", + "label": "Address Type", + "options": "Billing\nShipping\nOffice\nPersonal\nPlant\nPostal\nShop\nSubsidiary\nWarehouse\nCurrent\nPermanent\nOther" } ], "icon": "fa fa-user", "idx": 5, "image_field": "image", "links": [], - "modified": "2019-12-24 16:00:44.239168", + "modified": "2020-04-08 22:26:11.687110", "modified_by": "Administrator", "module": "CRM", "name": "Lead", diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index 73ef79b894..74b358219d 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -12,9 +12,6 @@ from frappe.email.inbox import link_communication_to_document from frappe.model.mapper import get_mapped_doc from frappe.utils import cint, comma_and, cstr, getdate, has_gravatar, nowdate, validate_email_address -sender_field = "email_id" - - class Lead(SellingController): def get_feed(self): return '{0}: {1}'.format(_(self.status), self.lead_name) @@ -129,16 +126,23 @@ class Lead(SellingController): self.title = self.lead_name def create_address(self): - address_fields = ["address_title", "address_line1", "address_line2", + address_fields = ["address_type", "address_title", "address_line1", "address_line2", "city", "county", "state", "country", "pincode"] info_fields = ["email_id", "phone", "fax"] # do not create an address if no fields are available, # skipping country since the system auto-sets it from system defaults - if not any([self.get(field) for field in address_fields if field != "country"]): + address = frappe.new_doc("Address") + + mandatory_fields = [ df.fieldname for df in address.meta.fields if df.reqd ] + + if not all([self.get(field) for field in mandatory_fields]): + frappe.msgprint(_('Missing mandatory fields in address. \ + {0} to create address' ).format(" Click here "), + alert=True, indicator='yellow') return - address = frappe.new_doc("Address") address.update({addr_field: self.get(addr_field) for addr_field in address_fields}) address.update({info_field: self.get(info_field) for info_field in info_fields}) address.insert() @@ -205,7 +209,7 @@ class Lead(SellingController): self.contact_doc.save() def flush_address_and_contact_fields(self): - fields = ['address_line1', 'address_line2', 'address_title', + fields = ['address_type', 'address_line1', 'address_line2', 'address_title', 'city', 'county', 'country', 'fax', 'pincode', 'state'] for field in fields: diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index 0e2068a0a5..6a54c5fc6e 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "allow_rename": 1, "autoname": "naming_series:", @@ -7,6 +8,7 @@ "doctype": "DocType", "document_type": "Document", "editable_grid": 1, + "email_append_to": 1, "engine": "InnoDB", "field_order": [ "from_section", @@ -214,7 +216,8 @@ { "fieldname": "opportunity_amount", "fieldtype": "Currency", - "label": "Opportunity Amount" + "label": "Opportunity Amount", + "options": "currency" }, { "default": "0", @@ -326,6 +329,7 @@ "fieldname": "contact_email", "fieldtype": "Data", "label": "Contact Email", + "options": "Email", "read_only": 1 }, { @@ -418,7 +422,8 @@ ], "icon": "fa fa-info-sign", "idx": 195, - "modified": "2019-09-30 12:58:37.385400", + "links": [], + "modified": "2020-04-07 09:05:39.391109", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", @@ -450,9 +455,11 @@ } ], "search_fields": "status,transaction_date,party_name,opportunity_type,territory,company", + "sender_field": "contact_email", "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", + "subject_field": "title", "timeline_field": "party_name", "title_field": "title", "track_seen": 1, diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 5911db9f6c..5e640e78c8 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -11,9 +11,6 @@ from erpnext.utilities.transaction_base import TransactionBase from erpnext.accounts.party import get_party_account_currency from frappe.email.inbox import link_communication_to_document -subject_field = "title" -sender_field = "contact_email" - class Opportunity(TransactionBase): def after_insert(self): if self.opportunity_from == "Lead": diff --git a/erpnext/demo/user/fixed_asset.py b/erpnext/demo/user/fixed_asset.py index e6d1687202..dc094e1c91 100644 --- a/erpnext/demo/user/fixed_asset.py +++ b/erpnext/demo/user/fixed_asset.py @@ -6,46 +6,28 @@ from __future__ import unicode_literals import frappe from frappe.utils.make_random import get_random -from erpnext.assets.doctype.asset.asset import make_purchase_invoice, make_sales_invoice +from erpnext.assets.doctype.asset.asset import make_sales_invoice from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset + def work(): frappe.set_user(frappe.db.get_global('demo_accounts_user')) - asset_list = make_asset_purchase_entry() - - if not asset_list: - # fixed_asset.work() already run - return - # Enable booking asset depreciation entry automatically frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) - + # post depreciation entries as on today post_depreciation_entries() - + # scrap a random asset frappe.db.set_value("Company", "Wind Power LLC", "disposal_account", "Gain/Loss on Asset Disposal - WPL") - + asset = get_random_asset() scrap_asset(asset.name) - - # Sell a random asset - sell_an_asset() -def make_asset_purchase_entry(): - asset_list = frappe.get_all("Asset", filters={"purchase_invoice": ["in", ("", None)]}, - fields=["name", "item_code", "gross_purchase_amount", "company", "purchase_date"]) - - # make purchase invoice - for asset in asset_list: - pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount, - asset.company, asset.purchase_date) - pi.supplier = get_random("Supplier") - pi.save() - pi.submit() - - return asset_list + # Sell a random asset + sell_an_asset() + def sell_an_asset(): asset = get_random_asset() @@ -55,8 +37,9 @@ def sell_an_asset(): if asset.value_after_depreciation else asset.gross_purchase_amount * 0.9 si.save() si.submit() - + + def get_random_asset(): return frappe.db.sql(""" select name, item_code, value_after_depreciation, gross_purchase_amount - from `tabAsset` + from `tabAsset` where docstatus=1 and status not in ("Scrapped", "Sold") order by rand() limit 1""", as_dict=1)[0] diff --git a/erpnext/education/desk_page/education/education.json b/erpnext/education/desk_page/education/education.json index bbd8ead43f..fc2697f0d7 100644 --- a/erpnext/education/desk_page/education/education.json +++ b/erpnext/education/desk_page/education/education.json @@ -1,56 +1,69 @@ { "cards": [ { - "links": "[\n {\n \"label\": \"Student Attendance Tool\",\n \"name\": \"Student Attendance Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result Tool\",\n \"name\": \"Assessment Result Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group Creation Tool\",\n \"name\": \"Student Group Creation Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment Tool\",\n \"name\": \"Program Enrollment Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Scheduling Tool\",\n \"name\": \"Course Scheduling Tool\",\n \"type\": \"doctype\"\n }\n]", - "title": "Tools" + "hidden": 0, + "label": "Tools", + "links": "[\n {\n \"label\": \"Student Attendance Tool\",\n \"name\": \"Student Attendance Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result Tool\",\n \"name\": \"Assessment Result Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group Creation Tool\",\n \"name\": \"Student Group Creation Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment Tool\",\n \"name\": \"Program Enrollment Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Scheduling Tool\",\n \"name\": \"Course Scheduling Tool\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Program Enrollment\"\n ],\n \"doctype\": \"Program Enrollment\",\n \"is_query_report\": true,\n \"label\": \"Student and Guardian Contact Details\",\n \"name\": \"Student and Guardian Contact Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Monthly Attendance Sheet\",\n \"name\": \"Student Monthly Attendance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Fees\"\n ],\n \"doctype\": \"Fees\",\n \"is_query_report\": true,\n \"label\": \"Student Fee Collection\",\n \"name\": \"Student Fee Collection\",\n \"type\": \"report\"\n }\n]", - "title": "Other Reports" + "hidden": 0, + "label": "Other Reports", + "links": "[\n {\n \"dependencies\": [\n \"Program Enrollment\"\n ],\n \"doctype\": \"Program Enrollment\",\n \"is_query_report\": true,\n \"label\": \"Student and Guardian Contact Details\",\n \"name\": \"Student and Guardian Contact Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Monthly Attendance Sheet\",\n \"name\": \"Student Monthly Attendance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Fees\"\n ],\n \"doctype\": \"Fees\",\n \"is_query_report\": true,\n \"label\": \"Student Fee Collection\",\n \"name\": \"Student Fee Collection\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Student Category\",\n \"name\": \"Student Category\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Batch Name\",\n \"name\": \"Student Batch Name\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Grading Scale\",\n \"name\": \"Grading Scale\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Term\",\n \"name\": \"Academic Term\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Year\",\n \"name\": \"Academic Year\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Education Settings\",\n \"name\": \"Education Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"label\": \"Student Category\",\n \"name\": \"Student Category\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Batch Name\",\n \"name\": \"Student Batch Name\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Grading Scale\",\n \"name\": \"Grading Scale\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Term\",\n \"name\": \"Academic Term\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Year\",\n \"name\": \"Academic Year\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Education Settings\",\n \"name\": \"Education Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Article\",\n \"name\": \"Article\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Video\",\n \"name\": \"Video\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quiz\",\n \"name\": \"Quiz\",\n \"type\": \"doctype\"\n }\n]", - "title": "Content Masters" + "hidden": 0, + "label": "Content Masters", + "links": "[\n {\n \"label\": \"Article\",\n \"name\": \"Article\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Video\",\n \"name\": \"Video\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quiz\",\n \"name\": \"Quiz\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Student Attendance\",\n \"name\": \"Student Attendance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Leave Application\",\n \"name\": \"Student Leave Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Absent Student Report\",\n \"name\": \"Absent Student Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Batch-Wise Attendance\",\n \"name\": \"Student Batch-Wise Attendance\",\n \"type\": \"report\"\n }\n]", - "title": "Attendance" + "hidden": 0, + "label": "Attendance", + "links": "[\n {\n \"label\": \"Student Attendance\",\n \"name\": \"Student Attendance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Leave Application\",\n \"name\": \"Student Leave Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Absent Student Report\",\n \"name\": \"Absent Student Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Batch-Wise Attendance\",\n \"name\": \"Student Batch-Wise Attendance\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Student Applicant\",\n \"name\": \"Student Applicant\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Admission\",\n \"name\": \"Student Admission\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment\",\n \"name\": \"Program Enrollment\",\n \"type\": \"doctype\"\n }\n]", - "title": "Admission" + "hidden": 0, + "label": "Admission", + "links": "[\n {\n \"label\": \"Student Applicant\",\n \"name\": \"Student Applicant\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Admission\",\n \"name\": \"Student Admission\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment\",\n \"name\": \"Program Enrollment\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Assessment Plan\",\n \"name\": \"Assessment Plan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Group\",\n \"link\": \"Tree/Assessment Group\",\n \"name\": \"Assessment Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result\",\n \"name\": \"Assessment Result\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Criteria\",\n \"name\": \"Assessment Criteria\",\n \"type\": \"doctype\"\n }\n]", - "title": "Assessment" + "hidden": 0, + "label": "Assessment", + "links": "[\n {\n \"label\": \"Assessment Plan\",\n \"name\": \"Assessment Plan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Group\",\n \"link\": \"Tree/Assessment Group\",\n \"name\": \"Assessment Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result\",\n \"name\": \"Assessment Result\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Criteria\",\n \"name\": \"Assessment Criteria\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Student\",\n \"name\": \"Student\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Guardian\",\n \"name\": \"Guardian\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Log\",\n \"name\": \"Student Log\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group\",\n \"name\": \"Student Group\",\n \"type\": \"doctype\"\n }\n]", - "title": "Student" + "hidden": 0, + "label": "Student", + "links": "[\n {\n \"label\": \"Student\",\n \"name\": \"Student\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Guardian\",\n \"name\": \"Guardian\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Log\",\n \"name\": \"Student Log\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group\",\n \"name\": \"Student Group\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Program\",\n \"name\": \"Program\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course\",\n \"name\": \"Course\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Topic\",\n \"name\": \"Topic\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Instructor\",\n \"name\": \"Instructor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Room\",\n \"name\": \"Room\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Masters" + "hidden": 0, + "label": "Masters", + "links": "[\n {\n \"label\": \"Program\",\n \"name\": \"Program\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course\",\n \"name\": \"Course\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Topic\",\n \"name\": \"Topic\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Instructor\",\n \"name\": \"Instructor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Room\",\n \"name\": \"Room\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Course Enrollment\",\n \"name\": \"Course Enrollment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Activity\",\n \"name\": \"Course Activity\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quiz Activity\",\n \"name\": \"Quiz Activity\",\n \"type\": \"doctype\"\n }\n]", - "title": "LMS Activity" + "hidden": 0, + "label": "LMS Activity", + "links": "[\n {\n \"label\": \"Course Enrollment\",\n \"name\": \"Course Enrollment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Activity\",\n \"name\": \"Course Activity\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quiz Activity\",\n \"name\": \"Quiz Activity\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Course Schedule\",\n \"name\": \"Course Schedule\",\n \"route\": \"#List/Course Schedule/Calendar\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Scheduling Tool\",\n \"name\": \"Course Scheduling Tool\",\n \"type\": \"doctype\"\n }\n]", - "title": "Schedule" + "hidden": 0, + "label": "Schedule", + "links": "[\n {\n \"label\": \"Course Schedule\",\n \"name\": \"Course Schedule\",\n \"route\": \"#List/Course Schedule/Calendar\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Scheduling Tool\",\n \"name\": \"Course Scheduling Tool\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Fees\",\n \"name\": \"Fees\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Schedule\",\n \"name\": \"Fee Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Structure\",\n \"name\": \"Fee Structure\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Category\",\n \"name\": \"Fee Category\",\n \"type\": \"doctype\"\n }\n]", - "title": "Fees" + "hidden": 0, + "label": "Fees", + "links": "[\n {\n \"label\": \"Fees\",\n \"name\": \"Fees\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Schedule\",\n \"name\": \"Fee Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Structure\",\n \"name\": \"Fee Structure\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Category\",\n \"name\": \"Fee Category\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Assessment Result\"\n ],\n \"doctype\": \"Assessment Result\",\n \"is_query_report\": true,\n \"label\": \"Course wise Assessment Report\",\n \"name\": \"Course wise Assessment Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Assessment Result\"\n ],\n \"doctype\": \"Assessment Result\",\n \"is_query_report\": true,\n \"label\": \"Final Assessment Grades\",\n \"name\": \"Final Assessment Grades\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Assessment Plan\"\n ],\n \"doctype\": \"Assessment Plan\",\n \"is_query_report\": true,\n \"label\": \"Assessment Plan Status\",\n \"name\": \"Assessment Plan Status\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Student Report Generation Tool\",\n \"name\": \"Student Report Generation Tool\",\n \"type\": \"doctype\"\n }\n]", - "title": "Assessment Reports" + "hidden": 0, + "label": "Assessment Reports", + "links": "[\n {\n \"dependencies\": [\n \"Assessment Result\"\n ],\n \"doctype\": \"Assessment Result\",\n \"is_query_report\": true,\n \"label\": \"Course wise Assessment Report\",\n \"name\": \"Course wise Assessment Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Assessment Result\"\n ],\n \"doctype\": \"Assessment Result\",\n \"is_query_report\": true,\n \"label\": \"Final Assessment Grades\",\n \"name\": \"Final Assessment Grades\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Assessment Plan\"\n ],\n \"doctype\": \"Assessment Plan\",\n \"is_query_report\": true,\n \"label\": \"Assessment Plan Status\",\n \"name\": \"Assessment Plan Status\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Student Report Generation Tool\",\n \"name\": \"Student Report Generation Tool\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Domains", @@ -64,7 +77,7 @@ "idx": 0, "is_standard": 1, "label": "Education", - "modified": "2020-03-12 16:30:37.217514", + "modified": "2020-04-01 11:28:51.011309", "modified_by": "Administrator", "module": "Education", "name": "Education", diff --git a/erpnext/education/doctype/course/course.json b/erpnext/education/doctype/course/course.json index 68426c36be..da10db1857 100644 --- a/erpnext/education/doctype/course/course.json +++ b/erpnext/education/doctype/course/course.json @@ -74,7 +74,7 @@ } ], "image_field": "hero_image", - "modified": "2019-06-12 12:34:23.748157", + "modified": "2020-03-29 12:50:27.677589", "modified_by": "Administrator", "module": "Education", "name": "Course", @@ -103,6 +103,30 @@ "role": "Instructor", "share": 1, "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Administrator", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Education Manager", + "share": 1, + "write": 1 } ], "restrict_to_domain": "Education", diff --git a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py index c2ac0d7d7b..5bebd4385c 100644 --- a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py +++ b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py @@ -14,7 +14,7 @@ def execute(filters=None): student_batch_name = filters.get("student_batch_name") columns = get_columns() - + program_enrollments = frappe.get_list("Program Enrollment", fields=["student", "student_name"], filters={"academic_year": academic_year, "program": program, "student_batch_name": student_batch_name}) @@ -46,9 +46,9 @@ def execute(filters=None): def get_columns(): columns = [ - _(" Group Roll No") + "::60", - _("Student ID") + ":Link/Student:90", - _("Student Name") + "::150", + _("Group Roll No") + "::60", + _("Student ID") + ":Link/Student:90", + _("Student Name") + "::150", _("Student Mobile No.") + "::110", _("Student Email ID") + "::125", _("Student Address") + "::175", @@ -84,10 +84,10 @@ def get_guardian_map(student_list): guardian_list = list(set([g.guardian for g in guardian_details])) or [''] - guardian_mobile_no = dict(frappe.db.sql("""select name, mobile_number from `tabGuardian` + guardian_mobile_no = dict(frappe.db.sql("""select name, mobile_number from `tabGuardian` where name in (%s)""" % ", ".join(['%s']*len(guardian_list)), tuple(guardian_list))) - guardian_email_id = dict(frappe.db.sql("""select name, email_address from `tabGuardian` + guardian_email_id = dict(frappe.db.sql("""select name, email_address from `tabGuardian` where name in (%s)""" % ", ".join(['%s']*len(guardian_list)), tuple(guardian_list))) for guardian in guardian_details: diff --git a/erpnext/erpnext_integrations/custom/contact.json b/erpnext/erpnext_integrations/custom/contact.json new file mode 100644 index 0000000000..98a4bbc795 --- /dev/null +++ b/erpnext/erpnext_integrations/custom/contact.json @@ -0,0 +1,60 @@ +{ + "custom_fields": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2019-12-02 11:00:03.432994", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Contact", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "is_billing_contact", + "fieldtype": "Check", + "hidden": 0, + "idx": 27, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "insert_after": "is_primary_contact", + "label": "Is Billing Contact", + "length": 0, + "modified": "2019-12-02 11:00:03.432994", + "modified_by": "Administrator", + "name": "Contact-is_billing_contact", + "no_copy": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "translatable": 0, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Contact", + "property_setters": [], + "sync_on_migrate": 1 +} \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py index 3bc8db5e78..cc75a0afbe 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py @@ -121,7 +121,7 @@ def call_mws_method(mws_method, *args, **kwargs): time.sleep(delay) continue - mws_settings.enable_synch = 0 + mws_settings.enable_sync = 0 mws_settings.save() frappe.throw(_("Sync has been temporarily disabled because maximum retries have been exceeded")) diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py index 9925dc4a08..f713684d37 100755 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py @@ -39,16 +39,19 @@ __all__ = [ # for a list of the end points and marketplace IDs MARKETPLACES = { - "CA" : "https://mws.amazonservices.ca", #A2EUQ1WTGCTBG2 - "US" : "https://mws.amazonservices.com", #ATVPDKIKX0DER", - "DE" : "https://mws-eu.amazonservices.com", #A1PA6795UKMFR9 - "ES" : "https://mws-eu.amazonservices.com", #A1RKKUPIHCS9HS - "FR" : "https://mws-eu.amazonservices.com", #A13V1IB3VIYZZH - "IN" : "https://mws.amazonservices.in", #A21TJRUUN4KGV - "IT" : "https://mws-eu.amazonservices.com", #APJ6JRA9NG5V4 - "UK" : "https://mws-eu.amazonservices.com", #A1F83G8C2ARO7P - "JP" : "https://mws.amazonservices.jp", #A1VC38T7YXB528 - "CN" : "https://mws.amazonservices.com.cn", #AAHKV2X7AFYLW + "CA": "https://mws.amazonservices.ca", #A2EUQ1WTGCTBG2 + "US": "https://mws.amazonservices.com", #ATVPDKIKX0DER", + "DE": "https://mws-eu.amazonservices.com", #A1PA6795UKMFR9 + "ES": "https://mws-eu.amazonservices.com", #A1RKKUPIHCS9HS + "FR": "https://mws-eu.amazonservices.com", #A13V1IB3VIYZZH + "IN": "https://mws.amazonservices.in", #A21TJRUUN4KGV + "IT": "https://mws-eu.amazonservices.com", #APJ6JRA9NG5V4 + "UK": "https://mws-eu.amazonservices.com", #A1F83G8C2ARO7P + "JP": "https://mws.amazonservices.jp", #A1VC38T7YXB528 + "CN": "https://mws.amazonservices.com.cn", #AAHKV2X7AFYLW + "AE": " https://mws.amazonservices.ae", #A2VIGQ35RCS4UG + "MX": "https://mws.amazonservices.com.mx", #A1AM78C64UM0Y8 + "BR": "https://mws.amazonservices.com", #A2Q3Y263D00KWC } diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.json b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.json index 607ca4fe1d..5a678e77d1 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.json +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.json @@ -1,974 +1,237 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "", - "beta": 0, - "creation": "2018-07-31 05:51:41.357047", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "creation": "2018-07-31 05:51:41.357047", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "enable_amazon", + "mws_credentials", + "seller_id", + "aws_access_key_id", + "mws_auth_token", + "secret_key", + "column_break_4", + "market_place_id", + "region", + "domain", + "section_break_13", + "company", + "warehouse", + "item_group", + "price_list", + "column_break_17", + "customer_group", + "territory", + "customer_type", + "market_place_account_group", + "section_break_12", + "after_date", + "taxes_charges", + "sync_products", + "sync_orders", + "column_break_10", + "enable_sync", + "max_retry_limit" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "enable_amazon", - "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": "Enable Amazon", - "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 - }, + "default": "0", + "fieldname": "enable_amazon", + "fieldtype": "Check", + "label": "Enable Amazon" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, - "fieldname": "mws_credentials", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "MWS Credentials", - "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 - }, + "fieldname": "mws_credentials", + "fieldtype": "Section Break", + "label": "MWS Credentials" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "seller_id", - "fieldtype": "Data", - "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": "Seller ID", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "seller_id", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Seller ID", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "aws_access_key_id", - "fieldtype": "Data", - "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": "AWS Access Key ID", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "aws_access_key_id", + "fieldtype": "Data", + "in_list_view": 1, + "label": "AWS Access Key ID", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "mws_auth_token", - "fieldtype": "Data", - "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": "MWS Auth Token", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "mws_auth_token", + "fieldtype": "Data", + "in_list_view": 1, + "label": "MWS Auth Token", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "secret_key", - "fieldtype": "Data", - "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": "Secret Key", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "secret_key", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Secret Key", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "market_place_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Market Place ID", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "market_place_id", + "fieldtype": "Data", + "label": "Market Place ID", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "region", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Region", - "length": 0, - "no_copy": 0, - "options": "\nIN\nCN\nJP\nBR\nAU\nES\nUK\nFR\nDE\nIT\nCA\nUS\nMX", - "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": "region", + "fieldtype": "Select", + "label": "Region", + "options": "\nAE\nAU\nBR\nCA\nCN\nDE\nES\nFR\nIN\nJP\nIT\nMX\nUK\nUS", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "domain", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Domain", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "domain", + "fieldtype": "Data", + "label": "Domain", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_13", - "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 - }, + "fieldname": "section_break_13", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "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", + "label": "Company", + "options": "Company", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "warehouse", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Warehouse", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "warehouse", + "fieldtype": "Link", + "label": "Warehouse", + "options": "Warehouse", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "item_group", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Item Group", - "length": 0, - "no_copy": 0, - "options": "Item Group", - "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": "item_group", + "fieldtype": "Link", + "label": "Item Group", + "options": "Item Group", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "options": "Price List", - "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": "price_list", + "fieldtype": "Link", + "label": "Price List", + "options": "Price List", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_17", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_17", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer_group", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer Group", - "length": 0, - "no_copy": 0, - "options": "Customer Group", - "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": "customer_group", + "fieldtype": "Link", + "label": "Customer Group", + "options": "Customer Group", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "territory", - "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": "Territory", - "length": 0, - "no_copy": 0, - "options": "Territory", - "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": "territory", + "fieldtype": "Link", + "label": "Territory", + "options": "Territory", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer Type", - "length": 0, - "no_copy": 0, - "options": "Individual\nCompany", - "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": "customer_type", + "fieldtype": "Select", + "label": "Customer Type", + "options": "Individual\nCompany", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "market_place_account_group", - "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": "Market Place Account Group", - "length": 0, - "no_copy": 0, - "options": "Account", - "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": "market_place_account_group", + "fieldtype": "Link", + "label": "Market Place Account Group", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_12", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_12", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Amazon will synch data updated after this date", - "fieldname": "after_date", - "fieldtype": "Datetime", - "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": "After Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "description": "Amazon will synch data updated after this date", + "fieldname": "after_date", + "fieldtype": "Datetime", + "label": "After Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Get financial breakup of Taxes and charges data by Amazon ", - "fieldname": "taxes_charges", - "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": "Synch Taxes and Charges", - "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 - }, + "default": "0", + "description": "Get financial breakup of Taxes and charges data by Amazon ", + "fieldname": "taxes_charges", + "fieldtype": "Check", + "label": "Sync Taxes and Charges" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Always synch your products from Amazon MWS before synching the Orders details", - "fieldname": "synch_products", - "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": "Synch Products", - "length": 0, - "no_copy": 0, - "options": "get_products_details", - "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 - }, + "fieldname": "column_break_10", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Click this button to pull your Sales Order data from Amazon MWS.", - "fieldname": "synch_orders", - "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": "Synch Orders", - "length": 0, - "no_copy": 0, - "options": "get_order_details", - "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 - }, + "default": "3", + "fieldname": "max_retry_limit", + "fieldtype": "Int", + "label": "Max Retry Limit" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_10", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "description": "Always sync your products from Amazon MWS before synching the Orders details", + "fieldname": "sync_products", + "fieldtype": "Button", + "label": "Sync Products", + "options": "get_products_details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "description": "Check this to enable a scheduled Daily synchronization routine via scheduler", - "fieldname": "enable_synch", - "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": "Enable Scheduled Synch", - "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 - }, + "description": "Click this button to pull your Sales Order data from Amazon MWS.", + "fieldname": "sync_orders", + "fieldtype": "Button", + "label": "Sync Orders", + "options": "get_order_details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "3", - "fieldname": "max_retry_limit", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Max Retry Limit", - "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 + "default": "0", + "description": "Check this to enable a scheduled Daily synchronization routine via scheduler", + "fieldname": "enable_sync", + "fieldtype": "Check", + "label": "Enable Scheduled Sync" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2018-09-07 16:45:44.439834", - "modified_by": "Administrator", - "module": "ERPNext Integrations", - "name": "Amazon MWS Settings", - "name_case": "", - "owner": "Administrator", + ], + "issingle": 1, + "links": [], + "modified": "2020-04-07 14:26:20.174848", + "modified_by": "Administrator", + "module": "ERPNext Integrations", + "name": "Amazon MWS Settings", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, "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, - "track_views": 0 + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py index c222afbb6c..899b7ffe13 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py @@ -7,14 +7,15 @@ import frappe from frappe.model.document import Document import dateutil from frappe.custom.doctype.custom_field.custom_field import create_custom_fields +from erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods import get_orders class AmazonMWSSettings(Document): def validate(self): if self.enable_amazon == 1: - self.enable_synch = 1 + self.enable_sync = 1 setup_custom_fields() else: - self.enable_synch = 0 + self.enable_sync = 0 def get_products_details(self): if self.enable_amazon == 1: @@ -27,7 +28,7 @@ class AmazonMWSSettings(Document): def schedule_get_order_details(): mws_settings = frappe.get_doc("Amazon MWS Settings") - if mws_settings.enable_synch and mws_settings.enable_amazon: + if mws_settings.enable_sync and mws_settings.enable_amazon: after_date = dateutil.parser.parse(mws_settings.after_date).strftime("%Y-%m-%d") get_orders(after_date = after_date) diff --git a/erpnext/healthcare/desk_page/healthcare/healthcare.json b/erpnext/healthcare/desk_page/healthcare/healthcare.json index 258a72c308..849f4c3919 100644 --- a/erpnext/healthcare/desk_page/healthcare/healthcare.json +++ b/erpnext/healthcare/desk_page/healthcare/healthcare.json @@ -1,24 +1,24 @@ { "cards": [ { - "icon": "icon-cog", - "links": "[\n {\n \"label\": \"Healthcare Settings\",\n \"name\": \"Healthcare Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Department\",\n \"name\": \"Medical Department\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Appointment Type\",\n \"name\": \"Appointment Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Prescription Dosage\",\n \"name\": \"Prescription Dosage\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Prescription Duration\",\n \"name\": \"Prescription Duration\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Complaint\",\n \"name\": \"Complaint\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Diagnosis\",\n \"name\": \"Diagnosis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test Sample\",\n \"name\": \"Lab Test Sample\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test UOM\",\n \"name\": \"Lab Test UOM\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Antibiotic\",\n \"name\": \"Antibiotic\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Sensitivity\",\n \"name\": \"Sensitivity\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test Template\",\n \"name\": \"Lab Test Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Clinical Procedure Template\",\n \"name\": \"Clinical Procedure Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Service Unit Type\",\n \"name\": \"Healthcare Service Unit Type\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"label\": \"Healthcare Settings\",\n \"name\": \"Healthcare Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Department\",\n \"name\": \"Medical Department\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Appointment Type\",\n \"name\": \"Appointment Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Prescription Dosage\",\n \"name\": \"Prescription Dosage\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Prescription Duration\",\n \"name\": \"Prescription Duration\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Complaint\",\n \"name\": \"Complaint\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Diagnosis\",\n \"name\": \"Diagnosis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test Sample\",\n \"name\": \"Lab Test Sample\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test UOM\",\n \"name\": \"Lab Test UOM\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Antibiotic\",\n \"name\": \"Antibiotic\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Sensitivity\",\n \"name\": \"Sensitivity\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test Template\",\n \"name\": \"Lab Test Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Clinical Procedure Template\",\n \"name\": \"Clinical Procedure Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Service Unit Type\",\n \"name\": \"Healthcare Service Unit Type\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "icon-list", - "links": "[\n {\n \"label\": \"Lab Test\",\n \"name\": \"Lab Test\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Sample Collection\",\n \"name\": \"Sample Collection\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Lab Test Report\",\n \"name\": \"Lab Test Report\",\n \"type\": \"report\"\n }\n]", - "title": "Laboratory" + "hidden": 0, + "label": "Laboratory", + "links": "[\n {\n \"label\": \"Lab Test\",\n \"name\": \"Lab Test\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Sample Collection\",\n \"name\": \"Sample Collection\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Lab Test Report\",\n \"name\": \"Lab Test Report\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "icon-list", - "links": "[\n {\n \"label\": \"Patient\",\n \"name\": \"Patient\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Practitioner\",\n \"name\": \"Healthcare Practitioner\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Practitioner Schedule\",\n \"name\": \"Practitioner Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Code Standard\",\n \"name\": \"Medical Code Standard\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Code\",\n \"name\": \"Medical Code\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Service Unit\",\n \"name\": \"Healthcare Service Unit\",\n \"type\": \"doctype\"\n }\n]", - "title": "Masters" + "hidden": 0, + "label": "Masters", + "links": "[\n {\n \"label\": \"Patient\",\n \"name\": \"Patient\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Practitioner\",\n \"name\": \"Healthcare Practitioner\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Practitioner Schedule\",\n \"name\": \"Practitioner Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Code Standard\",\n \"name\": \"Medical Code Standard\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Code\",\n \"name\": \"Medical Code\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Service Unit\",\n \"name\": \"Healthcare Service Unit\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "icon-star", - "links": "[\n {\n \"label\": \"Patient Appointment\",\n \"name\": \"Patient Appointment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Patient Encounter\",\n \"name\": \"Patient Encounter\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Record Patient Vitals\",\n \"label\": \"Vital Signs\",\n \"name\": \"Vital Signs\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Patient History\",\n \"name\": \"patient_history\",\n \"type\": \"page\"\n },\n {\n \"label\": \"Appointment Analytics\",\n \"name\": \"appointment-analytic\",\n \"type\": \"page\"\n },\n {\n \"label\": \"Clinical Procedure\",\n \"name\": \"Clinical Procedure\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Inpatient Record\",\n \"name\": \"Inpatient Record\",\n \"type\": \"doctype\"\n }\n]", - "title": "Consultation" + "hidden": 0, + "label": "Consultation", + "links": "[\n {\n \"label\": \"Patient Appointment\",\n \"name\": \"Patient Appointment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Patient Encounter\",\n \"name\": \"Patient Encounter\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Record Patient Vitals\",\n \"label\": \"Vital Signs\",\n \"name\": \"Vital Signs\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Patient History\",\n \"name\": \"patient_history\",\n \"type\": \"page\"\n },\n {\n \"label\": \"Appointment Analytics\",\n \"name\": \"appointment-analytic\",\n \"type\": \"page\"\n },\n {\n \"label\": \"Clinical Procedure\",\n \"name\": \"Clinical Procedure\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Inpatient Record\",\n \"name\": \"Inpatient Record\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Domains", @@ -32,7 +32,7 @@ "idx": 0, "is_standard": 1, "label": "Healthcare", - "modified": "2020-03-12 16:30:36.952979", + "modified": "2020-04-01 11:28:50.996366", "modified_by": "Administrator", "module": "Healthcare", "name": "Healthcare", diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 54f1a1e452..6199cb2264 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -55,12 +55,8 @@ treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Grou update_website_context = ["erpnext.shopping_cart.utils.update_website_context", "erpnext.education.doctype.education_settings.education_settings.update_website_context"] my_account_context = "erpnext.shopping_cart.utils.update_my_account_context" -email_append_to = ["Job Applicant", "Lead", "Opportunity", "Issue"] - calendars = ["Task", "Work Order", "Leave Application", "Sales Order", "Holiday List", "Course Schedule"] - - domains = { 'Agriculture': 'erpnext.domains.agriculture', 'Distribution': 'erpnext.domains.distribution', @@ -243,7 +239,7 @@ doc_events = { "on_trash": "erpnext.regional.check_deletion_permission" }, "Payment Entry": { - "on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.make_status_as_paid"], + "on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status"], "on_trash": "erpnext.regional.check_deletion_permission" }, 'Address': { diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json index ec38ef078d..743aa23239 100644 --- a/erpnext/hr/desk_page/hr/hr.json +++ b/erpnext/hr/desk_page/hr/hr.json @@ -1,66 +1,79 @@ { "cards": [ { - "links": "[\n {\n \"label\": \"Employee\",\n \"name\": \"Employee\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Employment Type\",\n \"name\": \"Employment Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Branch\",\n \"name\": \"Branch\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Department\",\n \"name\": \"Department\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Designation\",\n \"name\": \"Designation\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Employee Grade\",\n \"name\": \"Employee Grade\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Group\",\n \"name\": \"Employee Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Employee Health Insurance\",\n \"name\": \"Employee Health Insurance\",\n \"type\": \"doctype\"\n }\n]", - "title": "Employee" + "hidden": 0, + "label": "Employee", + "links": "[\n {\n \"label\": \"Employee\",\n \"name\": \"Employee\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Employment Type\",\n \"name\": \"Employment Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Branch\",\n \"name\": \"Branch\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Department\",\n \"name\": \"Department\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Designation\",\n \"name\": \"Designation\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Employee Grade\",\n \"name\": \"Employee Grade\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Group\",\n \"name\": \"Employee Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Employee Health Insurance\",\n \"name\": \"Employee Health Insurance\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Job Applicant\"\n ],\n \"label\": \"Employee Onboarding\",\n \"name\": \"Employee Onboarding\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Skill Map\",\n \"name\": \"Employee Skill Map\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Promotion\",\n \"name\": \"Employee Promotion\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Transfer\",\n \"name\": \"Employee Transfer\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Separation\",\n \"name\": \"Employee Separation\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Onboarding Template\",\n \"name\": \"Employee Onboarding Template\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Separation Template\",\n \"name\": \"Employee Separation Template\",\n \"type\": \"doctype\"\n }\n]", - "title": "Employee Lifecycle" + "hidden": 0, + "label": "Employee Lifecycle", + "links": "[\n {\n \"dependencies\": [\n \"Job Applicant\"\n ],\n \"label\": \"Employee Onboarding\",\n \"name\": \"Employee Onboarding\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Skill Map\",\n \"name\": \"Employee Skill Map\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Promotion\",\n \"name\": \"Employee Promotion\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Transfer\",\n \"name\": \"Employee Transfer\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Separation\",\n \"name\": \"Employee Separation\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Onboarding Template\",\n \"name\": \"Employee Onboarding Template\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Separation Template\",\n \"name\": \"Employee Separation Template\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Shift Type\",\n \"name\": \"Shift Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shift Request\",\n \"name\": \"Shift Request\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shift Assignment\",\n \"name\": \"Shift Assignment\",\n \"type\": \"doctype\"\n }\n]", - "title": "Shift Management" + "hidden": 0, + "label": "Shift Management", + "links": "[\n {\n \"label\": \"Shift Type\",\n \"name\": \"Shift Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shift Request\",\n \"name\": \"Shift Request\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shift Assignment\",\n \"name\": \"Shift Assignment\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Application\",\n \"name\": \"Leave Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Allocation\",\n \"name\": \"Leave Allocation\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Leave Type\"\n ],\n \"label\": \"Leave Policy\",\n \"name\": \"Leave Policy\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Period\",\n \"name\": \"Leave Period\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Leave Type\",\n \"name\": \"Leave Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Holiday List\",\n \"name\": \"Holiday List\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Compensatory Leave Request\",\n \"name\": \"Compensatory Leave Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Encashment\",\n \"name\": \"Leave Encashment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Leave Block List\",\n \"name\": \"Leave Block List\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Leave Application\"\n ],\n \"doctype\": \"Leave Application\",\n \"is_query_report\": true,\n \"label\": \"Employee Leave Balance\",\n \"name\": \"Employee Leave Balance\",\n \"type\": \"report\"\n }\n]", - "title": "Leaves" + "hidden": 0, + "label": "Leaves", + "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Application\",\n \"name\": \"Leave Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Allocation\",\n \"name\": \"Leave Allocation\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Leave Type\"\n ],\n \"label\": \"Leave Policy\",\n \"name\": \"Leave Policy\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Period\",\n \"name\": \"Leave Period\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Leave Type\",\n \"name\": \"Leave Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Holiday List\",\n \"name\": \"Holiday List\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Compensatory Leave Request\",\n \"name\": \"Compensatory Leave Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Leave Encashment\",\n \"name\": \"Leave Encashment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Leave Block List\",\n \"name\": \"Leave Block List\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Leave Application\"\n ],\n \"doctype\": \"Leave Application\",\n \"is_query_report\": true,\n \"label\": \"Employee Leave Balance\",\n \"name\": \"Employee Leave Balance\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Salary Structure\",\n \"name\": \"Salary Structure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Structure\",\n \"Employee\"\n ],\n \"label\": \"Salary Structure Assignment\",\n \"name\": \"Salary Structure Assignment\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Entry\",\n \"name\": \"Payroll Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Slip\",\n \"name\": \"Salary Slip\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Component\",\n \"name\": \"Salary Component\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Additional Salary\",\n \"name\": \"Additional Salary\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Retention Bonus\",\n \"name\": \"Retention Bonus\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Incentive\",\n \"name\": \"Employee Incentive\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Slip\"\n ],\n \"doctype\": \"Salary Slip\",\n \"is_query_report\": true,\n \"label\": \"Salary Register\",\n \"name\": \"Salary Register\",\n \"type\": \"report\"\n }\n]", - "title": "Payroll" + "hidden": 0, + "label": "Payroll", + "links": "[\n {\n \"label\": \"Salary Structure\",\n \"name\": \"Salary Structure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Structure\",\n \"Employee\"\n ],\n \"label\": \"Salary Structure Assignment\",\n \"name\": \"Salary Structure Assignment\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Entry\",\n \"name\": \"Payroll Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Slip\",\n \"name\": \"Salary Slip\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Component\",\n \"name\": \"Salary Component\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Additional Salary\",\n \"name\": \"Additional Salary\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Retention Bonus\",\n \"name\": \"Retention Bonus\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Incentive\",\n \"name\": \"Employee Incentive\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Salary Slip\"\n ],\n \"doctype\": \"Salary Slip\",\n \"is_query_report\": true,\n \"label\": \"Salary Register\",\n \"name\": \"Salary Register\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Employee Attendance Tool\",\n \"name\": \"Employee Attendance Tool\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Attendance\",\n \"name\": \"Attendance\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Attendance Request\",\n \"name\": \"Attendance Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Upload Attendance\",\n \"name\": \"Upload Attendance\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Employee Checkin\",\n \"name\": \"Employee Checkin\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Attendance\"\n ],\n \"doctype\": \"Attendance\",\n \"is_query_report\": true,\n \"label\": \"Monthly Attendance Sheet\",\n \"name\": \"Monthly Attendance Sheet\",\n \"type\": \"report\"\n }\n]", - "title": "Attendance" + "hidden": 0, + "label": "Attendance", + "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Employee Attendance Tool\",\n \"name\": \"Employee Attendance Tool\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Attendance\",\n \"name\": \"Attendance\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Attendance Request\",\n \"name\": \"Attendance Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Upload Attendance\",\n \"name\": \"Upload Attendance\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Employee Checkin\",\n \"name\": \"Employee Checkin\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Attendance\"\n ],\n \"doctype\": \"Attendance\",\n \"is_query_report\": true,\n \"label\": \"Monthly Attendance Sheet\",\n \"name\": \"Monthly Attendance Sheet\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Expense Claim\",\n \"name\": \"Expense Claim\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Advance\",\n \"name\": \"Employee Advance\",\n \"type\": \"doctype\"\n }\n]", - "title": "Expense Claims" + "hidden": 0, + "label": "Expense Claims", + "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Expense Claim\",\n \"name\": \"Expense Claim\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Advance\",\n \"name\": \"Employee Advance\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-cog", - "links": "[\n {\n \"label\": \"HR Settings\",\n \"name\": \"HR Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Daily Work Summary Group\",\n \"name\": \"Daily Work Summary Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Team Updates\",\n \"name\": \"team-updates\",\n \"type\": \"page\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"label\": \"HR Settings\",\n \"name\": \"HR Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Daily Work Summary Group\",\n \"name\": \"Daily Work Summary Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Team Updates\",\n \"name\": \"team-updates\",\n \"type\": \"page\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Vehicle\",\n \"name\": \"Vehicle\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Vehicle Log\",\n \"name\": \"Vehicle Log\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Vehicle\"\n ],\n \"doctype\": \"Vehicle\",\n \"is_query_report\": true,\n \"label\": \"Vehicle Expenses\",\n \"name\": \"Vehicle Expenses\",\n \"type\": \"report\"\n }\n]", - "title": "Fleet Management" + "hidden": 0, + "label": "Fleet Management", + "links": "[\n {\n \"label\": \"Vehicle\",\n \"name\": \"Vehicle\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Vehicle Log\",\n \"name\": \"Vehicle Log\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Vehicle\"\n ],\n \"doctype\": \"Vehicle\",\n \"is_query_report\": true,\n \"label\": \"Vehicle Expenses\",\n \"name\": \"Vehicle Expenses\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Job Opening\",\n \"name\": \"Job Opening\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Job Applicant\",\n \"name\": \"Job Applicant\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Job Offer\",\n \"name\": \"Job Offer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Staffing Plan\",\n \"name\": \"Staffing Plan\",\n \"type\": \"doctype\"\n }\n]", - "title": "Recruitment" + "hidden": 0, + "label": "Recruitment", + "links": "[\n {\n \"label\": \"Job Opening\",\n \"name\": \"Job Opening\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Job Applicant\",\n \"name\": \"Job Applicant\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Job Offer\",\n \"name\": \"Job Offer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Staffing Plan\",\n \"name\": \"Staffing Plan\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n }\n]", - "title": "Loans" + "hidden": 0, + "label": "Loans", + "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Training Program\",\n \"name\": \"Training Program\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Training Event\",\n \"name\": \"Training Event\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Training Result\",\n \"name\": \"Training Result\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Training Feedback\",\n \"name\": \"Training Feedback\",\n \"type\": \"doctype\"\n }\n]", - "title": "Training" + "hidden": 0, + "label": "Training", + "links": "[\n {\n \"label\": \"Training Program\",\n \"name\": \"Training Program\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Training Event\",\n \"name\": \"Training Event\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Training Result\",\n \"name\": \"Training Result\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Training Feedback\",\n \"name\": \"Training Feedback\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"doctype\": \"Employee\",\n \"is_query_report\": true,\n \"label\": \"Employee Birthday\",\n \"name\": \"Employee Birthday\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"doctype\": \"Employee\",\n \"is_query_report\": true,\n \"label\": \"Employees working on a holiday\",\n \"name\": \"Employees working on a holiday\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"doctype\": \"Employee\",\n \"is_query_report\": true,\n \"label\": \"Department Analytics\",\n \"name\": \"Department Analytics\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"doctype\": \"Employee\",\n \"is_query_report\": true,\n \"label\": \"Employee Birthday\",\n \"name\": \"Employee Birthday\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"doctype\": \"Employee\",\n \"is_query_report\": true,\n \"label\": \"Employees working on a holiday\",\n \"name\": \"Employees working on a holiday\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"doctype\": \"Employee\",\n \"is_query_report\": true,\n \"label\": \"Department Analytics\",\n \"name\": \"Department Analytics\",\n \"type\": \"report\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Appraisal\",\n \"name\": \"Appraisal\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Appraisal Template\",\n \"name\": \"Appraisal Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Energy Point Rule\",\n \"name\": \"Energy Point Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Energy Point Log\",\n \"name\": \"Energy Point Log\",\n \"type\": \"doctype\"\n }\n]", - "title": "Performance" + "hidden": 0, + "label": "Performance", + "links": "[\n {\n \"label\": \"Appraisal\",\n \"name\": \"Appraisal\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Appraisal Template\",\n \"name\": \"Appraisal Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Energy Point Rule\",\n \"name\": \"Energy Point Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Energy Point Log\",\n \"name\": \"Energy Point Log\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Application\",\n \"name\": \"Employee Benefit Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Claim\",\n \"name\": \"Employee Benefit Claim\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n }\n]", - "title": "Employee Tax and Benefits" + "hidden": 0, + "label": "Employee Tax and Benefits", + "links": "[\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Application\",\n \"name\": \"Employee Benefit Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Benefit Claim\",\n \"name\": \"Employee Benefit Claim\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Modules", @@ -75,7 +88,7 @@ "idx": 0, "is_standard": 1, "label": "HR", - "modified": "2020-03-12 16:30:35.211246", + "modified": "2020-04-01 11:28:50.860012", "modified_by": "Administrator", "module": "HR", "name": "HR", @@ -85,37 +98,37 @@ "shortcuts": [ { "format": "{} Active", - "is_query_report": 0, + "label": "Employee", "link_to": "Employee", "stats_filter": "{\"status\":\"Active\"}", "type": "DocType" }, { "format": "{} Unpaid", - "is_query_report": 0, + "label": "Expense Claim", "link_to": "Expense Claim", "stats_filter": "{\"approval_status\":\"Draft\"}", "type": "DocType" }, { "format": "{} Open", - "is_query_report": 0, + "label": "Job Applicant", "link_to": "Job Applicant", "stats_filter": "{\n \"status\": \"Open\"\n}", "type": "DocType" }, { - "is_query_report": 0, + "label": "Salary Structure", "link_to": "Salary Structure", "type": "DocType" }, { - "is_query_report": 0, + "label": "Leave Application", "link_to": "Leave Application", "type": "DocType" }, { - "is_query_report": 0, + "label": "Salary Register", "link_to": "Salary Register", "type": "Report" } diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json index 3f0b9c49ac..13c202c775 100644 --- a/erpnext/hr/doctype/employee/employee.json +++ b/erpnext/hr/doctype/employee/employee.json @@ -259,7 +259,8 @@ "bold": 1, "fieldname": "emergency_phone_number", "fieldtype": "Data", - "label": "Emergency Phone" + "label": "Emergency Phone", + "options": "Phone" }, { "bold": 1, @@ -480,7 +481,8 @@ { "fieldname": "cell_number", "fieldtype": "Data", - "label": "Mobile" + "label": "Mobile", + "options": "Phone" }, { "fieldname": "prefered_contact_email", @@ -787,7 +789,7 @@ "idx": 24, "image_field": "image", "links": [], - "modified": "2020-01-09 04:23:55.611366", + "modified": "2020-04-08 12:25:34.306695", "modified_by": "Administrator", "module": "HR", "name": "Employee", @@ -834,6 +836,5 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", - "title_field": "employee_name", - "track_changes": 1 -} + "title_field": "employee_name" +} \ No newline at end of file diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.json b/erpnext/hr/doctype/job_applicant/job_applicant.json index b0cddc257e..c13548ab82 100644 --- a/erpnext/hr/doctype/job_applicant/job_applicant.json +++ b/erpnext/hr/doctype/job_applicant/job_applicant.json @@ -1,385 +1,123 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 1, - "autoname": "HR-APP-.YYYY.-.#####", - "beta": 0, - "creation": "2013-01-29 19:25:37", - "custom": 0, - "description": "Applicant for a Job", - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 0, - "engine": "InnoDB", + "actions": [], + "allow_rename": 1, + "autoname": "HR-APP-.YYYY.-.#####", + "creation": "2013-01-29 19:25:37", + "description": "Applicant for a Job", + "doctype": "DocType", + "document_type": "Document", + "email_append_to": 1, + "engine": "InnoDB", + "field_order": [ + "applicant_name", + "email_id", + "status", + "column_break_3", + "job_title", + "source", + "source_name", + "section_break_6", + "notes", + "cover_letter", + "resume_attachment" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "applicant_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Applicant Name", - "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 - }, + "bold": 1, + "fieldname": "applicant_name", + "fieldtype": "Data", + "in_global_search": 1, + "label": "Applicant Name", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "email_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Email Address", - "length": 0, - "no_copy": 0, - "options": "Email", - "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 - }, + "bold": 1, + "fieldname": "email_id", + "fieldtype": "Data", + "label": "Email Address", + "options": "Email", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Open\nReplied\nRejected\nHold\nAccepted", - "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 - }, + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Status", + "options": "Open\nReplied\nRejected\nHold\nAccepted", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, + "fieldname": "column_break_3", + "fieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "job_title", - "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": "Job Opening", - "length": 0, - "no_copy": 0, - "options": "Job Opening", - "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 - }, + "fieldname": "job_title", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Job Opening", + "options": "Job Opening" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "source", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Source", - "length": 0, - "no_copy": 0, - "options": "Job Applicant Source", - "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 - }, + "fieldname": "source", + "fieldtype": "Link", + "label": "Source", + "options": "Job Applicant Source" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.source==\"Employee Referral\" ", - "fieldname": "source_name", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Source Name", - "length": 0, - "no_copy": 0, - "options": "Employee", - "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 - }, + "depends_on": "eval: doc.source==\"Employee Referral\" ", + "fieldname": "source_name", + "fieldtype": "Link", + "label": "Source Name", + "options": "Employee" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_6", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_6", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cover_letter", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Cover Letter", - "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 - }, + "fieldname": "cover_letter", + "fieldtype": "Text", + "label": "Cover Letter" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "resume_attachment", - "fieldtype": "Attach", - "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": "Resume Attachment", - "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 + "fieldname": "resume_attachment", + "fieldtype": "Attach", + "label": "Resume Attachment" + }, + { + "fieldname": "notes", + "fieldtype": "Data", + "label": "Notes", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-user", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-07-21 16:15:43.552049", - "modified_by": "Administrator", - "module": "HR", - "name": "Job Applicant", - "owner": "Administrator", + ], + "icon": "fa fa-user", + "idx": 1, + "links": [], + "modified": "2020-01-13 16:19:39.113330", + "modified_by": "Administrator", + "module": "HR", + "name": "Job Applicant", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR User", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "applicant_name", - "show_name_in_global_search": 0, - "sort_order": "ASC", - "title_field": "applicant_name", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + ], + "search_fields": "applicant_name", + "sender_field": "email_id", + "sort_field": "modified", + "sort_order": "ASC", + "subject_field": "notes", + "title_field": "applicant_name" } \ No newline at end of file diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.py b/erpnext/hr/doctype/job_applicant/job_applicant.py index 4fc7719f38..a6aef04919 100644 --- a/erpnext/hr/doctype/job_applicant/job_applicant.py +++ b/erpnext/hr/doctype/job_applicant/job_applicant.py @@ -9,8 +9,6 @@ import frappe from frappe import _ from frappe.utils import comma_and, validate_email_address -sender_field = "email_id" - class DuplicationError(frappe.ValidationError): pass class JobApplicant(Document): diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 96e4cb5bb3..afd52de397 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -130,7 +130,7 @@ class LeaveApplication(Document): if self.status == "Approved": for dt in daterange(getdate(self.from_date), getdate(self.to_date)): date = dt.strftime("%Y-%m-%d") - status = "Half Day" if date == self.half_day_date else "On Leave" + status = "Half Day" if getdate(date) == getdate(self.half_day_date) else "On Leave" attendance_name = frappe.db.exists('Attendance', dict(employee = self.employee, attendance_date = date, docstatus = ('!=', 2))) @@ -687,8 +687,7 @@ def add_leaves(events, start, end, filter_conditions=None): "to_date": d.to_date, "docstatus": d.docstatus, "color": d.color, - "title": cstr(d.employee_name) + \ - (d.half_day and _(" (Half Day)") or ""), + "title": cstr(d.employee_name) + (' ' + _('(Half Day)') if d.half_day else ''), } if e not in events: events.append(e) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index d03a3dd9a3..c637215e96 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -356,13 +356,13 @@ class SalarySlip(TransactionBase): def eval_condition_and_formula(self, d, data): try: - condition = d.condition.strip() if d.condition else None + condition = d.condition.strip().replace("\n", " ") if d.condition else None if condition: if not frappe.safe_eval(condition, self.whitelisted_globals, data): return None amount = d.amount if d.amount_based_on_formula: - formula = d.formula.strip() if d.formula else None + formula = d.formula.strip().replace("\n", " ") if d.formula else None if formula: amount = flt(frappe.safe_eval(formula, self.whitelisted_globals, data), d.precision("amount")) if amount: diff --git a/erpnext/loan_management/desk_page/loan_management/loan_management.json b/erpnext/loan_management/desk_page/loan_management/loan_management.json index 1d60ca4913..691d2c1e0c 100644 --- a/erpnext/loan_management/desk_page/loan_management/loan_management.json +++ b/erpnext/loan_management/desk_page/loan_management/loan_management.json @@ -1,24 +1,29 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"Loan Type for interest and penalty rates\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Applications from customers and employees.\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loans provided to customers and employees.\",\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]", - "title": "Loan" + "hidden": 0, + "label": "Loan", + "links": "[\n {\n \"description\": \"Loan Type for interest and penalty rates\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Applications from customers and employees.\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loans provided to customers and employees.\",\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Process Loan Security Shortfall\",\n \"name\": \"Process Loan Security Shortfall\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Process Loan Interest Accrual\",\n \"name\": \"Process Loan Interest Accrual\",\n \"type\": \"doctype\"\n }\n]", - "title": "Loan Processes" + "hidden": 0, + "label": "Loan Processes", + "links": "[\n {\n \"label\": \"Process Loan Security Shortfall\",\n \"name\": \"Process Loan Security Shortfall\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Process Loan Interest Accrual\",\n \"name\": \"Process Loan Interest Accrual\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Loan Disbursement\",\n \"name\": \"Loan Disbursement\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Repayment\",\n \"name\": \"Loan Repayment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Interest Accrual\",\n \"name\": \"Loan Interest Accrual\",\n \"type\": \"doctype\"\n }\n]", - "title": "Disbursement and Repayment" + "hidden": 0, + "label": "Disbursement and Repayment", + "links": "[\n {\n \"label\": \"Loan Disbursement\",\n \"name\": \"Loan Disbursement\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Repayment\",\n \"name\": \"Loan Repayment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Interest Accrual\",\n \"name\": \"Loan Interest Accrual\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Loan Security Type\",\n \"name\": \"Loan Security Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Price\",\n \"name\": \"Loan Security Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security\",\n \"name\": \"Loan Security\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Pledge\",\n \"name\": \"Loan Security Pledge\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Unpledge\",\n \"name\": \"Loan Security Unpledge\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Shortfall\",\n \"name\": \"Loan Security Shortfall\",\n \"type\": \"doctype\"\n }\n]", - "title": "Loan Security" + "hidden": 0, + "label": "Loan Security", + "links": "[\n {\n \"label\": \"Loan Security Type\",\n \"name\": \"Loan Security Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Price\",\n \"name\": \"Loan Security Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security\",\n \"name\": \"Loan Security\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Pledge\",\n \"name\": \"Loan Security Pledge\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Unpledge\",\n \"name\": \"Loan Security Unpledge\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan Security Shortfall\",\n \"name\": \"Loan Security Shortfall\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Loan Repayment\"\n ],\n \"doctype\": \"Loan Repayment\",\n \"incomplete_dependencies\": [\n \"Loan Repayment\"\n ],\n \"is_query_report\": true,\n \"label\": \"Loan Repayment and Closure\",\n \"name\": \"Loan Repayment and Closure\",\n \"route\": \"#query-report/Loan Repayment and Closure\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Loan Security Pledge\"\n ],\n \"doctype\": \"Loan Security Pledge\",\n \"incomplete_dependencies\": [\n \"Loan Security Pledge\"\n ],\n \"is_query_report\": true,\n \"label\": \"Loan Security Status\",\n \"name\": \"Loan Security Status\",\n \"route\": \"#query-report/Loan Security Status\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"Loan Repayment\"\n ],\n \"doctype\": \"Loan Repayment\",\n \"incomplete_dependencies\": [\n \"Loan Repayment\"\n ],\n \"is_query_report\": true,\n \"label\": \"Loan Repayment and Closure\",\n \"name\": \"Loan Repayment and Closure\",\n \"route\": \"#query-report/Loan Repayment and Closure\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Loan Security Pledge\"\n ],\n \"doctype\": \"Loan Security Pledge\",\n \"incomplete_dependencies\": [\n \"Loan Security Pledge\"\n ],\n \"is_query_report\": true,\n \"label\": \"Loan Security Status\",\n \"name\": \"Loan Security Status\",\n \"route\": \"#query-report/Loan Security Status\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", @@ -32,7 +37,7 @@ "idx": 0, "is_standard": 1, "label": "Loan Management", - "modified": "2020-03-12 16:38:00.347959", + "modified": "2020-04-01 11:28:51.380509", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Management", @@ -41,12 +46,12 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Loan Application", "link_to": "Loan Application", "type": "DocType" }, { - "is_query_report": 0, + "label": "Loan", "link_to": "Loan", "type": "DocType" } diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index c2e5685ea7..759b0d8e09 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -273,11 +273,11 @@ class TestLoan(unittest.TestCase): penalty_amount = (accrued_interest_amount * 4 * 25) / (100 * days_in_year(get_datetime(first_date).year)) - lia = frappe.get_all("Loan Interest Accrual", fields=["is_paid"], - filters={"loan": loan.name}, order_by="posting_date") + lia1 = frappe.get_value("Loan Interest Accrual", {"loan": loan.name, "is_paid": 1}, 'name') + lia2 = frappe.get_value("Loan Interest Accrual", {"loan": loan.name, "is_paid": 0}, 'name') - self.assertTrue(lia[0].get('is_paid')) - self.assertFalse(lia[1].get('is_paid')) + self.assertTrue(lia1) + self.assertTrue(lia2) def test_security_shortfall(self): pledges = [] diff --git a/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json b/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json index 6127ef6896..18604e283a 100644 --- a/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json +++ b/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json @@ -1,32 +1,34 @@ { "cards": [ { - "icon": "fa fa-star", - "links": "[\n {\n \"dependencies\": [\n \"Item\",\n \"BOM\"\n ],\n \"description\": \"Orders released for production.\",\n \"label\": \"Work Order\",\n \"name\": \"Work Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"BOM\"\n ],\n \"description\": \"Generate Material Requests (MRP) and Work Orders.\",\n \"label\": \"Production Plan\",\n \"name\": \"Production Plan\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Entry\",\n \"name\": \"Stock Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Activity Type\"\n ],\n \"description\": \"Time Sheet for manufacturing.\",\n \"label\": \"Timesheet\",\n \"name\": \"Timesheet\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Job Card\",\n \"name\": \"Job Card\",\n \"type\": \"doctype\"\n }\n]", - "title": "Production" + "hidden": 0, + "label": "Production", + "links": "[\n {\n \"dependencies\": [\n \"Item\",\n \"BOM\"\n ],\n \"description\": \"Orders released for production.\",\n \"label\": \"Work Order\",\n \"name\": \"Work Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"BOM\"\n ],\n \"description\": \"Generate Material Requests (MRP) and Work Orders.\",\n \"label\": \"Production Plan\",\n \"name\": \"Production Plan\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Entry\",\n \"name\": \"Stock Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Activity Type\"\n ],\n \"description\": \"Time Sheet for manufacturing.\",\n \"label\": \"Timesheet\",\n \"name\": \"Timesheet\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Job Card\",\n \"name\": \"Job Card\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"All Products or Services.\",\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Bill of Materials (BOM)\",\n \"label\": \"Bill of Materials\",\n \"name\": \"BOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Where manufacturing operations are carried.\",\n \"label\": \"Workstation\",\n \"name\": \"Workstation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Details of the operations carried out.\",\n \"label\": \"Operation\",\n \"name\": \"Operation\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Routing\",\n \"name\": \"Routing\",\n \"type\": \"doctype\"\n }\n]", - "title": "Bill of Materials" + "hidden": 0, + "label": "Bill of Materials", + "links": "[\n {\n \"description\": \"All Products or Services.\",\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Bill of Materials (BOM)\",\n \"label\": \"Bill of Materials\",\n \"name\": \"BOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Where manufacturing operations are carried.\",\n \"label\": \"Workstation\",\n \"name\": \"Workstation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Details of the operations carried out.\",\n \"label\": \"Operation\",\n \"name\": \"Operation\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Routing\",\n \"name\": \"Routing\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Open Work Orders\",\n \"name\": \"Open Work Orders\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Work Orders in Progress\",\n \"name\": \"Work Orders in Progress\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Issued Items Against Work Order\",\n \"name\": \"Issued Items Against Work Order\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Completed Work Orders\",\n \"name\": \"Completed Work Orders\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Production Analytics\",\n \"name\": \"Production Analytics\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"BOM\"\n ],\n \"doctype\": \"BOM\",\n \"is_query_report\": true,\n \"label\": \"BOM Search\",\n \"name\": \"BOM Search\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"BOM\"\n ],\n \"doctype\": \"BOM\",\n \"is_query_report\": true,\n \"label\": \"BOM Stock Report\",\n \"name\": \"BOM Stock Report\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Open Work Orders\",\n \"name\": \"Open Work Orders\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Work Orders in Progress\",\n \"name\": \"Work Orders in Progress\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Issued Items Against Work Order\",\n \"name\": \"Issued Items Against Work Order\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Completed Work Orders\",\n \"name\": \"Completed Work Orders\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Work Order\"\n ],\n \"doctype\": \"Work Order\",\n \"is_query_report\": true,\n \"label\": \"Production Analytics\",\n \"name\": \"Production Analytics\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"BOM\"\n ],\n \"doctype\": \"BOM\",\n \"is_query_report\": true,\n \"label\": \"BOM Search\",\n \"name\": \"BOM Search\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"BOM\"\n ],\n \"doctype\": \"BOM\",\n \"is_query_report\": true,\n \"label\": \"BOM Stock Report\",\n \"name\": \"BOM Stock Report\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-wrench", - "links": "[\n {\n \"description\": \"Replace BOM and update latest price in all BOMs\",\n \"label\": \"BOM Update Tool\",\n \"name\": \"BOM Update Tool\",\n \"type\": \"doctype\"\n },\n {\n \"data_doctype\": \"BOM\",\n \"description\": \"Compare BOMs for changes in Raw Materials and Operations\",\n \"label\": \"BOM Comparison Tool\",\n \"name\": \"bom-comparison-tool\",\n \"type\": \"page\"\n }\n]", - "title": "Tools" + "hidden": 0, + "label": "Tools", + "links": "[\n {\n \"description\": \"Replace BOM and update latest price in all BOMs\",\n \"label\": \"BOM Update Tool\",\n \"name\": \"BOM Update Tool\",\n \"type\": \"doctype\"\n },\n {\n \"data_doctype\": \"BOM\",\n \"description\": \"Compare BOMs for changes in Raw Materials and Operations\",\n \"label\": \"BOM Comparison Tool\",\n \"name\": \"bom-comparison-tool\",\n \"type\": \"page\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Global settings for all manufacturing processes.\",\n \"label\": \"Manufacturing Settings\",\n \"name\": \"Manufacturing Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"description\": \"Global settings for all manufacturing processes.\",\n \"label\": \"Manufacturing Settings\",\n \"name\": \"Manufacturing Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-facetime-video", - "links": "[\n {\n \"label\": \"Work Order\",\n \"name\": \"Work Order\",\n \"type\": \"help\",\n \"youtube_id\": \"ZotgLyp2YFY\"\n }\n]", - "title": "Help" + "hidden": 0, + "label": "Help", + "links": "[\n {\n \"label\": \"Work Order\",\n \"name\": \"Work Order\",\n \"type\": \"help\",\n \"youtube_id\": \"ZotgLyp2YFY\"\n }\n]" } ], "category": "Domains", @@ -40,7 +42,7 @@ "idx": 0, "is_standard": 1, "label": "Manufacturing", - "modified": "2020-03-12 16:30:36.389877", + "modified": "2020-04-01 11:28:50.979358", "modified_by": "Administrator", "module": "Manufacturing", "name": "Manufacturing", diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.js b/erpnext/manufacturing/doctype/blanket_order/blanket_order.js index 1cd9446c8b..4c31bd0b7d 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.js +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.js @@ -14,27 +14,37 @@ frappe.ui.form.on('Blanket Order', { refresh: function(frm) { erpnext.hide_company(); if (frm.doc.customer && frm.doc.docstatus === 1) { - frm.add_custom_button(__('View Orders'), function() { - frappe.set_route('List', 'Sales Order', {blanket_order: frm.doc.name}); - }); - frm.add_custom_button(__("Create Sales Order"), function(){ + frm.add_custom_button(__("Sales Order"), function() { frappe.model.open_mapped_doc({ - method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_sales_order", - frm: frm + method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order", + frm: frm, + args: { + doctype: 'Sales Order' + } }); - }).addClass("btn-primary"); + }, __('Create')); + + frm.add_custom_button(__("Quotation"), function() { + frappe.model.open_mapped_doc({ + method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order", + frm: frm, + args: { + doctype: 'Quotation' + } + }); + }, __('Create')); } if (frm.doc.supplier && frm.doc.docstatus === 1) { - frm.add_custom_button(__('View Orders'), function() { - frappe.set_route('List', 'Purchase Order', {blanket_order: frm.doc.name}); - }); - frm.add_custom_button(__("Create Purchase Order"), function(){ + frm.add_custom_button(__("Purchase Order"), function(){ frappe.model.open_mapped_doc({ - method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_purchase_order", - frm: frm + method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order", + frm: frm, + args: { + doctype: 'Purchase Order' + } }); - }).addClass("btn-primary"); + }, __('Create')); } }, diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py index 38118bd78d..d7556add80 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py @@ -14,10 +14,18 @@ from erpnext.stock.doctype.item.item import get_item_defaults class BlanketOrder(Document): def validate(self): self.validate_dates() + self.validate_duplicate_items() def validate_dates(self): if getdate(self.from_date) > getdate(self.to_date): - frappe.throw(_("From date cannot be greater than To date")) + frappe.throw(_("From date cannot be greater than To date")) + + def validate_duplicate_items(self): + item_list = [] + for item in self.items: + if item.item_code in item_list: + frappe.throw(_("Note: Item {0} added multiple times").format(frappe.bold(item.item_code))) + item_list.append(item.item_code) def update_ordered_qty(self): ref_doctype = "Sales Order" if self.blanket_order_type == "Selling" else "Purchase Order" @@ -35,7 +43,14 @@ class BlanketOrder(Document): d.db_set("ordered_qty", item_ordered_qty.get(d.item_code, 0)) @frappe.whitelist() -def make_sales_order(source_name): +def make_order(source_name): + doctype = frappe.flags.args.doctype + + def update_doc(source_doc, target_doc, source_parent): + if doctype == 'Quotation': + target_doc.quotation_to = 'Customer' + target_doc.party_name = source_doc.customer + def update_item(source, target, source_parent): target_qty = source.get("qty") - source.get("ordered_qty") target.qty = target_qty if not flt(target_qty) < 0 else 0 @@ -49,39 +64,11 @@ def make_sales_order(source_name): target_doc = get_mapped_doc("Blanket Order", source_name, { "Blanket Order": { - "doctype": "Sales Order" + "doctype": doctype, + "postprocess": update_doc }, "Blanket Order Item": { - "doctype": "Sales Order Item", - "field_map": { - "rate": "blanket_order_rate", - "parent": "blanket_order" - }, - "postprocess": update_item - } - }) - return target_doc - -@frappe.whitelist() -def make_purchase_order(source_name): - def update_item(source, target, source_parent): - target_qty = source.get("qty") - source.get("ordered_qty") - target.qty = target_qty if not flt(target_qty) < 0 else 0 - item = get_item_defaults(target.item_code, source_parent.company) - if item: - target.item_name = item.get("item_name") - target.description = item.get("description") - target.uom = item.get("stock_uom") - target.warehouse = item.get("default_warehouse") - target.against_blanket_order = 1 - target.blanket_order = source_name - - target_doc = get_mapped_doc("Blanket Order", source_name, { - "Blanket Order": { - "doctype": "Purchase Order" - }, - "Blanket Order Item": { - "doctype": "Purchase Order Item", + "doctype": doctype + " Item", "field_map": { "rate": "blanket_order_rate", "parent": "blanket_order" diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py index ed319a0cef..d9aa0ca49d 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order_dashboard.py @@ -6,7 +6,7 @@ def get_data(): 'fieldname': 'blanket_order', 'transactions': [ { - 'items': ['Purchase Order', 'Sales Order'] + 'items': ['Purchase Order', 'Sales Order', 'Quotation'] } ] } diff --git a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py index 455ea06137..3171defdae 100644 --- a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py @@ -7,13 +7,17 @@ import frappe import unittest from frappe.utils import add_months, today from erpnext import get_company_currency -from .blanket_order import make_sales_order, make_purchase_order +from .blanket_order import make_order class TestBlanketOrder(unittest.TestCase): + def setUp(self): + frappe.flags.args = frappe._dict() + def test_sales_order_creation(self): bo = make_blanket_order(blanket_order_type="Selling") - so = make_sales_order(bo.name) + frappe.flags.args.doctype = 'Sales Order' + so = make_order(bo.name) so.currency = get_company_currency(so.company) so.delivery_date = today() so.items[0].qty = 10 @@ -29,7 +33,8 @@ class TestBlanketOrder(unittest.TestCase): self.assertEqual(so.items[0].qty, bo.items[0].ordered_qty) # test the quantity - so1 = make_sales_order(bo.name) + frappe.flags.args.doctype = 'Sales Order' + so1 = make_order(bo.name) so1.currency = get_company_currency(so1.company) self.assertEqual(so1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty)) @@ -37,7 +42,8 @@ class TestBlanketOrder(unittest.TestCase): def test_purchase_order_creation(self): bo = make_blanket_order(blanket_order_type="Purchasing") - po = make_purchase_order(bo.name) + frappe.flags.args.doctype = 'Purchase Order' + po = make_order(bo.name) po.currency = get_company_currency(po.company) po.schedule_date = today() po.items[0].qty = 10 @@ -53,7 +59,8 @@ class TestBlanketOrder(unittest.TestCase): self.assertEqual(po.items[0].qty, bo.items[0].ordered_qty) # test the quantity - po1 = make_sales_order(bo.name) + frappe.flags.args.doctype = 'Purchase Order' + po1 = make_order(bo.name) po1.currency = get_company_currency(po1.company) self.assertEqual(po1.items[0].qty, (bo.items[0].qty-bo.items[0].ordered_qty)) @@ -78,7 +85,7 @@ def make_blanket_order(**args): "qty": args.quantity or 1000, "rate": args.rate or 100 }) - + bo.insert() bo.submit() return bo \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 3acaee4ffb..ebfb762640 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -29,7 +29,10 @@ frappe.ui.form.on("BOM", { frm.set_query("item", function() { return { - query: "erpnext.controllers.queries.item_query" + query: "erpnext.controllers.queries.item_query", + filters: { + "doctype": "BOM" + } }; }); @@ -43,8 +46,7 @@ frappe.ui.form.on("BOM", { frm.set_query("item_code", "items", function() { return { - query: "erpnext.controllers.queries.item_query", - filters: [["Item", "name", "!=", cur_frm.doc.item]] + query: "erpnext.controllers.queries.item_query" }; }); @@ -120,22 +122,58 @@ frappe.ui.form.on("BOM", { }); } } + + + if (frm.doc.__onload && frm.doc.__onload["has_variants"]) { + frm.set_intro(__('This is a Template BOM and will be used to make the work order for {0} of the item {1}', + [ + `variants`, + `${frm.doc.item}`, + ]), true); + + frm.$wrapper.find(".variants-intro").on("click", () => { + frappe.set_route("List", "Item", {"variant_of": frm.doc.item}); + }); + } }, make_work_order: function(frm) { - const fields = [{ + const fields = []; + + if (frm.doc.__onload && frm.doc.__onload["has_variants"]) { + fields.push({ + fieldtype: 'Link', + label: __('Variant Item'), + fieldname: 'item', + options: "Item", + reqd: 1, + get_query: function() { + return { + query: "erpnext.controllers.queries.item_query", + filters: { + "variant_of": frm.doc.item + } + }; + } + }); + } + + fields.push({ fieldtype: 'Float', label: __('Qty To Manufacture'), fieldname: 'qty', reqd: 1, default: 1 - }]; + }); frappe.prompt(fields, data => { + let item = data.item || frm.doc.item; + frappe.call({ method: "erpnext.manufacturing.doctype.work_order.work_order.make_work_order", args: { - item: frm.doc.item, + bom_no: frm.doc.name, + item: item, qty: data.qty || 0.0, project: frm.doc.project }, diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index f6cdb2e57c..6ccd12aed3 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -59,6 +59,10 @@ class BOM(WebsiteGenerator): self.name = name + def onload(self): + super(BOM, self).onload() + if self.get("item") and cint(frappe.db.get_value("Item", self.item, "has_variants")): + self.set_onload("has_variants", True) def validate(self): self.route = frappe.scrub(self.name).replace('_', '-') @@ -114,10 +118,6 @@ class BOM(WebsiteGenerator): child = self.append('operations', d) child.hour_rate = flt(d.hour_rate / self.conversion_rate, 2) - def validate_rm_item(self, item): - if (item[0]['name'] in [it.item_code for it in self.items]) and item[0]['name'] == self.item: - frappe.throw(_("BOM #{0}: Raw material cannot be same as main Item").format(self.name)) - def set_bom_material_details(self): for item in self.get("items"): self.validate_bom_currecny(item) @@ -147,7 +147,6 @@ class BOM(WebsiteGenerator): args = json.loads(args) item = self.get_item_det(args['item_code']) - self.validate_rm_item(item) args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or '' args['transfer_for_manufacture'] = (cstr(args.get('include_item_in_manufacturing', '')) or diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index bc8c22998a..8c7876d48d 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -20,7 +20,7 @@ frappe.ui.form.on('Job Card', { } } - if (frm.doc.docstatus == 0 && frm.doc.for_quantity > frm.doc.total_completed_qty + if (frm.doc.docstatus == 0 && (frm.doc.for_quantity > frm.doc.total_completed_qty || !frm.doc.for_quantity) && (!frm.doc.items.length || frm.doc.for_quantity == frm.doc.transferred_qty)) { frm.trigger("prepare_timer_buttons"); } @@ -59,10 +59,14 @@ frappe.ui.form.on('Job Card', { let completed_time = frappe.datetime.now_datetime(); frm.trigger("hide_timer"); - frappe.prompt({fieldtype: 'Float', label: __('Completed Quantity'), - fieldname: 'qty', reqd: 1, default: frm.doc.for_quantity}, data => { - frm.events.complete_job(frm, completed_time, data.qty); - }, __("Enter Value"), __("Complete")); + if (frm.doc.for_quantity) { + frappe.prompt({fieldtype: 'Float', label: __('Completed Quantity'), + fieldname: 'qty', reqd: 1, default: frm.doc.for_quantity}, data => { + frm.events.complete_job(frm, completed_time, data.qty); + }, __("Enter Value"), __("Complete")); + } else { + frm.events.complete_job(frm, completed_time, 0); + } }).addClass("btn-primary"); } }, diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json index 156accee74..7661fffa86 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.json +++ b/erpnext/manufacturing/doctype/job_card/job_card.json @@ -99,8 +99,7 @@ "fieldname": "for_quantity", "fieldtype": "Float", "in_list_view": 1, - "label": "Qty To Manufacture", - "reqd": 1 + "label": "Qty To Manufacture" }, { "fieldname": "wip_warehouse", @@ -122,6 +121,7 @@ "options": "Employee" }, { + "allow_bulk_edit": 1, "fieldname": "time_logs", "fieldtype": "Table", "label": "Time Logs", @@ -290,7 +290,7 @@ } ], "is_submittable": 1, - "modified": "2019-12-03 13:08:57.926201", + "modified": "2020-03-27 13:36:35.417502", "modified_by": "Administrator", "module": "Manufacturing", "name": "Job Card", diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 029db1cb4e..f8c60f2a11 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -191,12 +191,9 @@ class JobCard(Document): if not self.time_logs: frappe.throw(_("Time logs are required for job card {0}").format(self.name)) - if self.total_completed_qty <= 0.0: - frappe.throw(_("Total completed qty must be greater than zero")) - - if self.total_completed_qty != self.for_quantity: - frappe.throw(_("The total completed qty({0}) must be equal to qty to manufacture({1})") - .format(frappe.bold(self.total_completed_qty),frappe.bold(self.for_quantity))) + if self.for_quantity and self.total_completed_qty != self.for_quantity: + frappe.throw(_("The total completed qty({0}) must be equal to qty to manufacture({1})" + .format(frappe.bold(self.total_completed_qty),frappe.bold(self.for_quantity)))) def update_work_order(self): if not self.work_order: @@ -205,27 +202,34 @@ class JobCard(Document): for_quantity, time_in_mins = 0, 0 from_time_list, to_time_list = [], [] - for d in frappe.get_all('Job Card', - filters = {'docstatus': 1, 'operation_id': self.operation_id}): - doc = frappe.get_doc('Job Card', d.name) - for_quantity += doc.total_completed_qty - time_in_mins += doc.total_time_in_mins - for time_log in doc.time_logs: - if time_log.from_time: - from_time_list.append(time_log.from_time) - if time_log.to_time: - to_time_list.append(time_log.to_time) + data = frappe.get_all('Job Card', + fields = ["sum(total_time_in_mins) as time_in_mins", "sum(total_completed_qty) as completed_qty"], + filters = {"docstatus": 1, "work_order": self.work_order, + "workstation": self.workstation, "operation": self.operation}) + + if data and len(data) > 0: + for_quantity = data[0].completed_qty + time_in_mins = data[0].time_in_mins if for_quantity: + time_data = frappe.db.sql(""" + SELECT + min(from_time) as start_time, max(to_time) as end_time + FROM `tabJob Card` jc, `tabJob Card Time Log` jctl + WHERE + jctl.parent = jc.name and jc.work_order = %s + and jc.workstation = %s and jc.operation = %s and jc.docstatus = 1 + """, (self.work_order, self.workstation, self.operation), as_dict=1) + wo = frappe.get_doc('Work Order', self.work_order) for data in wo.operations: - if data.name == self.operation_id: + if data.workstation == self.workstation and data.operation == self.operation: data.completed_qty = for_quantity data.actual_operation_time = time_in_mins - data.actual_start_time = min(from_time_list) if from_time_list else None - data.actual_end_time = max(to_time_list) if to_time_list else None + data.actual_start_time = time_data[0].start_time if time_data else None + data.actual_end_time = time_data[0].end_time if time_data else None wo.flags.ignore_validate_update_after_submit = True wo.update_operation_status() diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index a79ea0e14b..358a5429d9 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -144,7 +144,7 @@ class ProductionPlan(Document): item_condition = " and mr_item.item_code ={0}".format(frappe.db.escape(self.item_code)) items = frappe.db.sql("""select distinct parent, name, item_code, warehouse, description, - (qty - ordered_qty) as pending_qty + (qty - ordered_qty) * conversion_factor as pending_qty from `tabMaterial Request Item` mr_item where parent in (%s) and docstatus = 1 and qty > ordered_qty and exists (select name from `tabBOM` bom where bom.item=mr_item.item_code diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 98149aedef..84bfab2f1d 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -314,7 +314,7 @@ class WorkOrder(Document): stock_entry = frappe.db.sql("""select name from `tabStock Entry` where work_order = %s and docstatus = 1""", self.name) if stock_entry: - frappe.throw(_("Cannot cancel because submitted Stock Entry {0} exists").format(stock_entry[0][0])) + frappe.throw(_("Cannot cancel because submitted Stock Entry {0} exists").format(frappe.utils.get_link_to_form('Stock Entry', stock_entry[0][0]))) def update_planned_qty(self): update_bin_qty(self.production_item, self.fg_warehouse, { @@ -552,24 +552,33 @@ class WorkOrder(Document): d.db_set('transferred_qty', flt(transferred_qty), update_modified = False) def update_consumed_qty_for_required_items(self): - '''update consumed qty from submitted stock entries for that item against - the work order''' + ''' + Update consumed qty from submitted stock entries + against a work order for each stock item + ''' - for d in self.required_items: - consumed_qty = frappe.db.sql('''select sum(qty) - from `tabStock Entry` entry, `tabStock Entry Detail` detail - where + for item in self.required_items: + consumed_qty = frappe.db.sql(''' + SELECT + SUM(qty) + FROM + `tabStock Entry` entry, + `tabStock Entry Detail` detail + WHERE entry.work_order = %(name)s - and (entry.purpose = "Material Consumption for Manufacture" - or entry.purpose = "Manufacture") - and entry.docstatus = 1 - and detail.parent = entry.name - and (detail.item_code = %(item)s or detail.original_item = %(item)s)''', { - 'name': self.name, - 'item': d.item_code - })[0][0] + AND (entry.purpose = "Material Consumption for Manufacture" + OR entry.purpose = "Manufacture") + AND entry.docstatus = 1 + AND detail.parent = entry.name + AND detail.s_warehouse IS NOT null + AND (detail.item_code = %(item)s + OR detail.original_item = %(item)s) + ''', { + 'name': self.name, + 'item': item.item_code + })[0][0] - d.db_set('consumed_qty', flt(consumed_qty), update_modified = False) + item.db_set('consumed_qty', flt(consumed_qty), update_modified=False) def make_bom(self): data = frappe.db.sql(""" select sed.item_code, sed.qty, sed.s_warehouse @@ -648,7 +657,7 @@ def get_item_details(item, project = None): return res @frappe.whitelist() -def make_work_order(item, qty=0, project=None): +def make_work_order(bom_no, item, qty=0, project=None): if not frappe.has_permission("Work Order", "write"): frappe.throw(_("Not permitted"), frappe.PermissionError) @@ -657,6 +666,7 @@ def make_work_order(item, qty=0, project=None): wo_doc = frappe.new_doc("Work Order") wo_doc.production_item = item wo_doc.update(item_details) + wo_doc.bom_no = bom_no if flt(qty) > 0: wo_doc.qty = flt(qty) diff --git a/erpnext/non_profit/desk_page/non_profit/non_profit.json b/erpnext/non_profit/desk_page/non_profit/non_profit.json index 5d759ba113..a476857f09 100644 --- a/erpnext/non_profit/desk_page/non_profit/non_profit.json +++ b/erpnext/non_profit/desk_page/non_profit/non_profit.json @@ -1,30 +1,34 @@ { "cards": [ { - "icon": "icon-list", - "links": "[\n {\n \"description\": \"Define various loan types\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Application\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]", - "title": "Loan Management" + "hidden": 0, + "label": "Loan Management", + "links": "[\n {\n \"description\": \"Define various loan types\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Application\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Grant information.\",\n \"label\": \"Grant Application\",\n \"name\": \"Grant Application\",\n \"type\": \"doctype\"\n }\n]", - "title": "Grant Application" + "hidden": 0, + "label": "Grant Application", + "links": "[\n {\n \"description\": \"Grant information.\",\n \"label\": \"Grant Application\",\n \"name\": \"Grant Application\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Member information.\",\n \"label\": \"Member\",\n \"name\": \"Member\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Memebership Details\",\n \"label\": \"Membership\",\n \"name\": \"Membership\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Memebership Type Details\",\n \"label\": \"Membership Type\",\n \"name\": \"Membership Type\",\n \"type\": \"doctype\"\n }\n]", - "title": "Membership" + "hidden": 0, + "label": "Membership", + "links": "[\n {\n \"description\": \"Member information.\",\n \"label\": \"Member\",\n \"name\": \"Member\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Membership Details\",\n \"label\": \"Membership\",\n \"name\": \"Membership\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Membership Type Details\",\n \"label\": \"Membership Type\",\n \"name\": \"Membership Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Billing and Gateway Settings\",\n \"label\": \"Membership Settings\",\n \"name\": \"Membership Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Volunteer information.\",\n \"label\": \"Volunteer\",\n \"name\": \"Volunteer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Volunteer Type information.\",\n \"label\": \"Volunteer Type\",\n \"name\": \"Volunteer Type\",\n \"type\": \"doctype\"\n }\n]", - "title": "Volunteer" + "hidden": 0, + "label": "Volunteer", + "links": "[\n {\n \"description\": \"Volunteer information.\",\n \"label\": \"Volunteer\",\n \"name\": \"Volunteer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Volunteer Type information.\",\n \"label\": \"Volunteer Type\",\n \"name\": \"Volunteer Type\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-star", - "links": "[\n {\n \"description\": \"Chapter information.\",\n \"label\": \"Chapter\",\n \"name\": \"Chapter\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Chapter" + "hidden": 0, + "label": "Chapter", + "links": "[\n {\n \"description\": \"Chapter information.\",\n \"label\": \"Chapter\",\n \"name\": \"Chapter\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Donor information.\",\n \"label\": \"Donor\",\n \"name\": \"Donor\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Donor Type information.\",\n \"label\": \"Donor Type\",\n \"name\": \"Donor Type\",\n \"type\": \"doctype\"\n }\n]", - "title": "Donor" + "hidden": 0, + "label": "Donor", + "links": "[\n {\n \"description\": \"Donor information.\",\n \"label\": \"Donor\",\n \"name\": \"Donor\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Donor Type information.\",\n \"label\": \"Donor Type\",\n \"name\": \"Donor Type\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Domains", @@ -38,7 +42,7 @@ "idx": 0, "is_standard": 1, "label": "Non Profit", - "modified": "2020-03-12 16:30:36.683012", + "modified": "2020-04-01 11:28:51.430882", "modified_by": "Administrator", "module": "Non Profit", "name": "Non Profit", diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b0fc7ea59c..9b5e5d02fb 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -581,7 +581,7 @@ erpnext.patches.v11_0.rename_bom_wo_fields erpnext.patches.v12_0.set_default_homepage_type erpnext.patches.v11_0.rename_additional_salary_component_additional_salary erpnext.patches.v11_0.renamed_from_to_fields_in_project -erpnext.patches.v11_0.add_permissions_in_gst_settings +erpnext.patches.v11_0.add_permissions_in_gst_settings #2020-04-04 erpnext.patches.v11_1.setup_guardian_role execute:frappe.delete_doc('DocType', 'Notification Control') erpnext.patches.v12_0.set_gst_category @@ -626,10 +626,11 @@ erpnext.patches.v12_0.update_ewaybill_field_position erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes erpnext.patches.v11_1.set_status_for_material_request_type_manufacture erpnext.patches.v12_0.move_plaid_settings_to_doctype -execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_link') -execute:frappe.reload_doc('desk', 'doctype','dashboard') -execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_source') -execute:frappe.reload_doc('desk', 'doctype','dashboard_chart') +execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_link') +execute:frappe.reload_doc('desk', 'doctype', 'dashboard') +execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_source') +execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart') +execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_field') erpnext.patches.v12_0.add_default_dashboards erpnext.patches.v12_0.remove_bank_remittance_custom_fields erpnext.patches.v12_0.generate_leave_ledger_entries @@ -658,4 +659,10 @@ erpnext.patches.v12_0.set_permission_einvoicing erpnext.patches.v12_0.set_published_in_hub_tracked_item erpnext.patches.v12_0.set_job_offer_applicant_email erpnext.patches.v12_0.create_irs_1099_field_united_states +erpnext.patches.v12_0.move_bank_account_swift_number_to_bank erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22 +erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom +erpnext.patches.v12_0.recalculate_requested_qty_in_bin +erpnext.patches.v12_0.set_total_batch_quantity +erpnext.patches.v12_0.rename_mws_settings_fields +erpnext.patches.v12_0.set_updated_purpose_in_pick_list diff --git a/erpnext/patches/v10_0/update_address_template_for_india.py b/erpnext/patches/v10_0/update_address_template_for_india.py index 145ed452e9..1ddca93760 100644 --- a/erpnext/patches/v10_0/update_address_template_for_india.py +++ b/erpnext/patches/v10_0/update_address_template_for_india.py @@ -3,10 +3,10 @@ from __future__ import unicode_literals import frappe -from erpnext.regional.india.setup import update_address_template +from erpnext.regional.address_template.setup import set_up_address_templates def execute(): if frappe.db.get_value('Company', {'country': 'India'}, 'name'): address_template = frappe.db.get_value('Address Template', 'India', 'template') if not address_template or "gstin" not in address_template: - update_address_template() + set_up_address_templates(default_country='India') diff --git a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py index e8fcf33bed..121a20288c 100644 --- a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py +++ b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py @@ -1,12 +1,9 @@ import frappe -from frappe.permissions import add_permission, update_permission_property +from erpnext.regional.india.setup import add_permissions def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) if not company: return - for doctype in ('GST HSN Code', 'GST Settings'): - add_permission(doctype, 'Accounts Manager', 0) - update_permission_property(doctype, 'Accounts Manager', 0, 'write', 1) - update_permission_property(doctype, 'Accounts Manager', 0, 'create', 1) \ No newline at end of file + add_permissions() \ No newline at end of file diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py new file mode 100644 index 0000000000..3c9758eb84 --- /dev/null +++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py @@ -0,0 +1,15 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('accounts', 'doctype', 'bank', force=1) + + if frappe.db.table_exists('Bank') and frappe.db.table_exists('Bank Account'): + frappe.db.sql(""" + UPDATE `tabBank` b, `tabBank Account` ba + SET b.swift_number = ba.swift_number, b.branch_code = ba.branch_code + WHERE b.name = ba.bank + """) + + frappe.reload_doc('accounts', 'doctype', 'bank_account') + frappe.reload_doc('accounts', 'doctype', 'payment_request') \ No newline at end of file diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py index 31d500ea2f..8889056e2d 100644 --- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py +++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py @@ -118,7 +118,9 @@ def get_item_tax_template(item_tax_templates, item_tax_map, item_code, parenttyp account.insert() tax_type = account.name - if tax_type: + account_type = frappe.get_cached_value("Account", tax_type, "account_type") + + if tax_type and account_type in ('Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation'): item_tax_template.append("taxes", {"tax_type": tax_type, "tax_rate": tax_rate}) item_tax_templates.setdefault(item_tax_template.title, {}) item_tax_templates[item_tax_template.title][tax_type] = tax_rate diff --git a/erpnext/patches/v12_0/recalculate_requested_qty_in_bin.py b/erpnext/patches/v12_0/recalculate_requested_qty_in_bin.py new file mode 100644 index 0000000000..8267df95e1 --- /dev/null +++ b/erpnext/patches/v12_0/recalculate_requested_qty_in_bin.py @@ -0,0 +1,13 @@ +from __future__ import unicode_literals +import frappe +from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty + +def execute(): + bin_details = frappe.db.sql(""" + SELECT item_code, warehouse + FROM `tabBin`""",as_dict=1) + + for entry in bin_details: + update_bin_qty(entry.get("item_code"), entry.get("warehouse"), { + "indented_qty": get_indented_qty(entry.get("item_code"), entry.get("warehouse")) + }) \ No newline at end of file diff --git a/erpnext/patches/v12_0/rename_mws_settings_fields.py b/erpnext/patches/v12_0/rename_mws_settings_fields.py new file mode 100644 index 0000000000..e08e376915 --- /dev/null +++ b/erpnext/patches/v12_0/rename_mws_settings_fields.py @@ -0,0 +1,11 @@ +# Copyright (c) 2020, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +import frappe + +def execute(): + count = frappe.db.sql("SELECT COUNT(*) FROM `tabSingles` WHERE doctype='Amazon MWS Settings' AND field='enable_sync';")[0][0] + if count == 0: + frappe.db.sql("UPDATE `tabSingles` SET field='enable_sync' WHERE doctype='Amazon MWS Settings' AND field='enable_synch';") + + frappe.reload_doc("ERPNext Integrations", "doctype", "Amazon MWS Settings") diff --git a/erpnext/patches/v12_0/set_received_qty_in_material_request_as_per_stock_uom.py b/erpnext/patches/v12_0/set_received_qty_in_material_request_as_per_stock_uom.py new file mode 100644 index 0000000000..88c3e2e302 --- /dev/null +++ b/erpnext/patches/v12_0/set_received_qty_in_material_request_as_per_stock_uom.py @@ -0,0 +1,30 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + purchase_receipts = frappe.db.sql(""" + SELECT + parent from `tabPurchase Receipt Item` + WHERE + material_request is not null + AND docstatus=1 + """,as_dict=1) + + purchase_receipts = set([d.parent for d in purchase_receipts]) + + for pr in purchase_receipts: + doc = frappe.get_doc("Purchase Receipt", pr) + doc.status_updater = [ + { + 'source_dt': 'Purchase Receipt Item', + 'target_dt': 'Material Request Item', + 'join_field': 'material_request_item', + 'target_field': 'received_qty', + 'target_parent_dt': 'Material Request', + 'target_parent_field': 'per_received', + 'target_ref_field': 'stock_qty', + 'source_field': 'stock_qty', + 'percent_join_field': 'material_request' + } + ] + doc.update_qty() diff --git a/erpnext/patches/v12_0/set_task_status.py b/erpnext/patches/v12_0/set_task_status.py index 70f65097dc..dbd7e5a818 100644 --- a/erpnext/patches/v12_0/set_task_status.py +++ b/erpnext/patches/v12_0/set_task_status.py @@ -1,16 +1,15 @@ import frappe def execute(): - frappe.reload_doctype('Task') + frappe.reload_doctype('Task') - # add "Completed" if customized - for doctype in ('Task'): - property_setter_name = frappe.db.exists('Property Setter', dict(doc_type = doctype, field_name = 'status', property = 'options')) - if property_setter_name: - property_setter = frappe.get_doc('Property Setter', property_setter_name) - if not "Completed" in property_setter.value: - property_setter.value = property_setter.value + '\nCompleted' - property_setter.save() + # add "Completed" if customized + property_setter_name = frappe.db.exists('Property Setter', dict(doc_type='Task', field_name = 'status', property = 'options')) + if property_setter_name: + property_setter = frappe.get_doc('Property Setter', property_setter_name) + if not "Completed" in property_setter.value: + property_setter.value = property_setter.value + '\nCompleted' + property_setter.save() - # renamed default status to Completed as status "Closed" is ambiguous - frappe.db.sql('update tabTask set status = "Completed" where status = "Closed"') \ No newline at end of file + # renamed default status to Completed as status "Closed" is ambiguous + frappe.db.sql('update tabTask set status = "Completed" where status = "Closed"') diff --git a/erpnext/patches/v12_0/set_total_batch_quantity.py b/erpnext/patches/v12_0/set_total_batch_quantity.py new file mode 100644 index 0000000000..d373275c25 --- /dev/null +++ b/erpnext/patches/v12_0/set_total_batch_quantity.py @@ -0,0 +1,11 @@ +import frappe + + +def execute(): + frappe.reload_doc("stock", "doctype", "batch") + + for batch in frappe.get_all("Batch", fields=["name", "batch_id"]): + batch_qty = frappe.db.get_value("Stock Ledger Entry", + {"docstatus": 1, "batch_no": batch.batch_id, "is_cancelled": "No"}, + "sum(actual_qty)") or 0.0 + frappe.db.set_value("Batch", batch.name, "batch_qty", batch_qty, update_modified=False) diff --git a/erpnext/patches/v12_0/set_updated_purpose_in_pick_list.py b/erpnext/patches/v12_0/set_updated_purpose_in_pick_list.py new file mode 100644 index 0000000000..63ca540a8e --- /dev/null +++ b/erpnext/patches/v12_0/set_updated_purpose_in_pick_list.py @@ -0,0 +1,11 @@ +# Copyright (c) 2019, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals + +import frappe + +def execute(): + frappe.reload_doc("stock", "doctype", "pick_list") + frappe.db.sql("""UPDATE `tabPick List` set purpose = 'Delivery' + WHERE docstatus = 1 and purpose = 'Delivery against Sales Order' """) \ No newline at end of file diff --git a/erpnext/patches/v8_1/gst_fixes.py b/erpnext/patches/v8_1/gst_fixes.py index 22fa53ba37..34255eb0a4 100644 --- a/erpnext/patches/v8_1/gst_fixes.py +++ b/erpnext/patches/v8_1/gst_fixes.py @@ -1,7 +1,8 @@ from __future__ import unicode_literals import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_field -from erpnext.regional.india.setup import update_address_template +from erpnext.regional.address_template.setup import set_up_address_templates + def execute(): company = frappe.get_all('Company', filters = {'country': 'India'}) @@ -10,9 +11,10 @@ def execute(): update_existing_custom_fields() add_custom_fields() - update_address_template() + set_up_address_templates(default_country='India') frappe.reload_doc("regional", "print_format", "gst_tax_invoice") + def update_existing_custom_fields(): frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC' where fieldname='gst_hsn_code' and label='GST HSN Code' @@ -34,6 +36,7 @@ def update_existing_custom_fields(): where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item') """) + def add_custom_fields(): hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC', fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description') diff --git a/erpnext/projects/desk_page/projects/projects.json b/erpnext/projects/desk_page/projects/projects.json index 13fd1b848f..a07cdffcbe 100644 --- a/erpnext/projects/desk_page/projects/projects.json +++ b/erpnext/projects/desk_page/projects/projects.json @@ -1,18 +1,19 @@ { "cards": [ { - "icon": "fa fa-star", - "links": "[\n {\n \"description\": \"Project master.\",\n \"label\": \"Project\",\n \"name\": \"Project\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Project activity / task.\",\n \"label\": \"Task\",\n \"name\": \"Task\",\n \"onboard\": 1,\n \"route\": \"#List/Task\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Make project from a template.\",\n \"label\": \"Project Template\",\n \"name\": \"Project Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define Project type.\",\n \"label\": \"Project Type\",\n \"name\": \"Project Type\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Project\"\n ],\n \"description\": \"Project Update.\",\n \"label\": \"Project Update\",\n \"name\": \"Project Update\",\n \"type\": \"doctype\"\n }\n]", - "title": "Projects" + "hidden": 0, + "label": "Projects", + "links": "[\n {\n \"description\": \"Project master.\",\n \"label\": \"Project\",\n \"name\": \"Project\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Project activity / task.\",\n \"label\": \"Task\",\n \"name\": \"Task\",\n \"onboard\": 1,\n \"route\": \"#List/Task\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Make project from a template.\",\n \"label\": \"Project Template\",\n \"name\": \"Project Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define Project type.\",\n \"label\": \"Project Type\",\n \"name\": \"Project Type\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Project\"\n ],\n \"description\": \"Project Update.\",\n \"label\": \"Project Update\",\n \"name\": \"Project Update\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Timesheet for tasks.\",\n \"label\": \"Timesheet\",\n \"name\": \"Timesheet\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Types of activities for Time Logs\",\n \"label\": \"Activity Type\",\n \"name\": \"Activity Type\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Activity Type\"\n ],\n \"description\": \"Cost of various activities\",\n \"label\": \"Activity Cost\",\n \"name\": \"Activity Cost\",\n \"type\": \"doctype\"\n }\n]", - "title": "Time Tracking" + "hidden": 0, + "label": "Time Tracking", + "links": "[\n {\n \"description\": \"Timesheet for tasks.\",\n \"label\": \"Timesheet\",\n \"name\": \"Timesheet\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Types of activities for Time Logs\",\n \"label\": \"Activity Type\",\n \"name\": \"Activity Type\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Activity Type\"\n ],\n \"description\": \"Cost of various activities\",\n \"label\": \"Activity Cost\",\n \"name\": \"Activity Cost\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"dependencies\": [\n \"Timesheet\"\n ],\n \"doctype\": \"Timesheet\",\n \"is_query_report\": true,\n \"label\": \"Daily Timesheet Summary\",\n \"name\": \"Daily Timesheet Summary\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Project\"\n ],\n \"doctype\": \"Project\",\n \"is_query_report\": true,\n \"label\": \"Project wise Stock Tracking\",\n \"name\": \"Project wise Stock Tracking\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Project\"\n ],\n \"doctype\": \"Project\",\n \"is_query_report\": true,\n \"label\": \"Project Billing Summary\",\n \"name\": \"Project Billing Summary\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"Timesheet\"\n ],\n \"doctype\": \"Timesheet\",\n \"is_query_report\": true,\n \"label\": \"Daily Timesheet Summary\",\n \"name\": \"Daily Timesheet Summary\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Project\"\n ],\n \"doctype\": \"Project\",\n \"is_query_report\": true,\n \"label\": \"Project wise Stock Tracking\",\n \"name\": \"Project wise Stock Tracking\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Project\"\n ],\n \"doctype\": \"Project\",\n \"is_query_report\": true,\n \"label\": \"Project Billing Summary\",\n \"name\": \"Project Billing Summary\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", @@ -27,7 +28,7 @@ "idx": 0, "is_standard": 1, "label": "Projects", - "modified": "2020-03-12 16:30:41.538685", + "modified": "2020-04-01 11:28:51.245756", "modified_by": "Administrator", "module": "Projects", "name": "Projects", @@ -37,23 +38,23 @@ "shortcuts": [ { "format": "{} Assigned", - "is_query_report": 0, + "label": "Task", "link_to": "Task", "stats_filter": "{\n \"_assign\": [\"like\", '%' + frappe.session.user + '%'],\n \"status\": \"Open\"\n}", "type": "DocType" }, { - "is_query_report": 0, + "label": "Project", "link_to": "Project", "type": "DocType" }, { - "is_query_report": 0, + "label": "Timesheet", "link_to": "Timesheet", "type": "DocType" }, { - "is_query_report": 0, + "label": "Project Billing Summary", "link_to": "Project Billing Summary", "type": "Report" } diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js index 3570a0f2be..5862963496 100644 --- a/erpnext/projects/doctype/project/project.js +++ b/erpnext/projects/doctype/project/project.js @@ -18,7 +18,7 @@ frappe.ui.form.on("Project", { }; }, onload: function (frm) { - var so = frappe.meta.get_docfield("Project", "sales_order"); + var so = frm.get_docfield("Project", "sales_order"); so.get_route_options_for_new_doc = function (field) { if (frm.is_new()) return; return { @@ -135,4 +135,4 @@ function open_form(frm, doctype, child_doctype, parentfield) { frappe.ui.form.make_quick_entry(doctype, null, null, new_doc); }); -} \ No newline at end of file +} diff --git a/erpnext/projects/report/billing_summary.py b/erpnext/projects/report/billing_summary.py index 76379f1de2..b808268d1b 100644 --- a/erpnext/projects/report/billing_summary.py +++ b/erpnext/projects/report/billing_summary.py @@ -53,7 +53,7 @@ def get_columns(): def get_data(filters): data = [] if(filters.from_date > filters.to_date): - frappe.msgprint(_(" From Date can not be greater than To Date")) + frappe.msgprint(_("From Date can not be greater than To Date")) return data timesheets = get_timesheets(filters) diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index 615f6a43f9..9870f81910 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -43,7 +43,6 @@ $.extend(frappe.breadcrumbs.preferred, { $.extend(frappe.breadcrumbs.module_map, { 'ERPNext Integrations': 'Integrations', 'Geo': 'Settings', - 'Accounts': 'Accounting', 'Portal': 'Website', 'Utilities': 'Settings', 'Shopping Cart': 'Website', diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index 3d4c4a6459..27a9de95e0 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -85,12 +85,6 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ filters:{ 'is_sub_contracted_item': 1 } } } - else if (me.frm.doc.material_request_type == "Customer Provided") { - return{ - query: "erpnext.controllers.queries.item_query", - filters:{ 'customer': me.frm.doc.customer } - } - } else { return{ query: "erpnext.controllers.queries.item_query", diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 9a5b750e8c..dbe48ec654 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -6,7 +6,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ apply_pricing_rule_on_item: function(item){ let effective_item_rate = item.price_list_rate; - if (item.parenttype === "Sales Order" && item.blanket_order_rate) { + if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) { effective_item_rate = item.blanket_order_rate; } if(item.margin_type == "Percentage"){ diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index fea2d5e700..0c63c33f7a 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -4,7 +4,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ setup: function() { this._super(); - frappe.flags.hide_serial_batch_dialog = false; + frappe.flags.hide_serial_batch_dialog = true; frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) { var item = frappe.get_doc(cdt, cdn); var has_margin_field = frappe.meta.has_field(cdt, 'margin_type'); @@ -165,6 +165,16 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ return (doc.rule_applied) ? "green" : "red"; }); } + + let batch_no_field = this.frm.get_docfield("items", "batch_no"); + if (batch_no_field) { + batch_no_field.get_route_options_for_new_doc = function(row) { + return { + "item": row.doc.item_code + } + }; + } + }, onload: function() { var me = this; @@ -352,12 +362,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ ['serial_no', 'batch_no', 'barcode'].forEach(field => { if (data[field] && frappe.meta.has_field(row_to_modify.doctype, field)) { + + let value = (row_to_modify[field] && field === "serial_no") + ? row_to_modify[field] + '\n' + data[field] : data[field]; + frappe.model.set_value(row_to_modify.doctype, - row_to_modify.name, field, data[field]); + row_to_modify.name, field, value); } }); scan_barcode_field.set_value(''); + refresh_field("items"); }); } return false; @@ -458,6 +473,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ item_code: item.item_code, barcode: item.barcode, serial_no: item.serial_no, + batch_no: item.batch_no, set_warehouse: me.frm.doc.set_warehouse, warehouse: item.warehouse, customer: me.frm.doc.customer || me.frm.doc.party_name, @@ -519,6 +535,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, () => me.toggle_conversion_factor(item), + () => { + if (show_batch_dialog) + return frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"]) + .then((r) => { + if(r.message.has_batch_no || r.message.has_serial_no) { + frappe.flags.hide_serial_batch_dialog = false; + } + }); + }, () => { if(show_batch_dialog && !frappe.flags.hide_serial_batch_dialog) { var d = locals[cdt][cdn]; @@ -528,7 +553,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ erpnext.show_serial_batch_selector(me.frm, d, (item) => { me.frm.script_manager.trigger('qty', item.doctype, item.name); - }); + if (!me.frm.doc.set_warehouse) + me.frm.script_manager.trigger('warehouse', item.doctype, item.name); + }, undefined, !frappe.flags.hide_serial_batch_dialog); } }, () => me.conversion_factor(doc, cdt, cdn, true), @@ -611,6 +638,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ // Add the new list to the serial no. field in grid with each in new line item.serial_no = valid_serial_nos.join('\n'); + item.conversion_factor = item.conversion_factor || 1; refresh_field("serial_no", item.name, item.parentfield); if(!doc.is_return && cint(user_defaults.set_qty_in_transactions_based_on_serial_no_input)) { @@ -866,7 +894,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ shipping_rule: function() { var me = this; - if(this.frm.doc.shipping_rule) { + if(this.frm.doc.shipping_rule && this.frm.doc.shipping_address) { return this.frm.call({ doc: this.frm.doc, method: "apply_shipping_rule", diff --git a/erpnext/public/js/education/lms/quiz.js b/erpnext/public/js/education/lms/quiz.js index 52481291e0..91cbbf4d66 100644 --- a/erpnext/public/js/education/lms/quiz.js +++ b/erpnext/public/js/education/lms/quiz.js @@ -29,7 +29,7 @@ class Quiz { this.questions.push(question) this.wrapper.appendChild(question_wrapper); }) - if (data.activity.is_complete) { + if (data.activity && data.activity.is_complete) { this.disable() let indicator = 'red' let message = 'Your are not allowed to attempt the quiz again.' diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index dead309a5d..296c6280d8 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -78,6 +78,39 @@ function get_filters(){ "fieldtype": "Link", "options": "Finance Book" }, + { + "fieldname":"filter_based_on", + "label": __("Filter Based On"), + "fieldtype": "Select", + "options": ["Fiscal Year", "Date Range"], + "default": ["Fiscal Year"], + "reqd": 1, + on_change: function() { + let filter_based_on = frappe.query_report.get_filter_value('filter_based_on'); + frappe.query_report.toggle_filter_display('from_fiscal_year', filter_based_on === 'Date Range'); + frappe.query_report.toggle_filter_display('to_fiscal_year', filter_based_on === 'Date Range'); + frappe.query_report.toggle_filter_display('period_start_date', filter_based_on === 'Fiscal Year'); + frappe.query_report.toggle_filter_display('period_end_date', filter_based_on === 'Fiscal Year'); + + frappe.query_report.refresh(); + } + }, + { + "fieldname":"period_start_date", + "label": __("Start Date"), + "fieldtype": "Date", + "default": frappe.datetime.nowdate(), + "hidden": 1, + "reqd": 1 + }, + { + "fieldname":"period_end_date", + "label": __("End Date"), + "fieldtype": "Date", + "default": frappe.datetime.add_months(frappe.datetime.nowdate(), 12), + "hidden": 1, + "reqd": 1 + }, { "fieldname":"from_fiscal_year", "label": __("Start Year"), diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 4eb3175186..4d44eae086 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -453,7 +453,8 @@ erpnext.utils.update_child_items = function(opts) { fields: [{ fieldtype:'Data', fieldname:"docname", - hidden: 0, + read_only: 1, + hidden: 1, }, { fieldtype:'Link', fieldname:"item_code", diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index 8b6de0f517..75c5a820b4 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -1,23 +1,25 @@ frappe.provide('frappe.ui.form'); -erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset", +let default_dimensions = {}; + +let doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset", "Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Shipping Rule", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Subscription", "Purchase Order", "Journal Entry", "Material Request", "Purchase Receipt", "Landed Cost Item", "Asset"]; -erpnext.child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account", +let child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Landed Cost Item", "Asset Value Adjustment", "Opening Invoice Creation Tool Item", "Subscription Plan"]; frappe.call({ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters", - callback: function(r){ + callback: function(r) { erpnext.dimension_filters = r.message[0]; - erpnext.default_dimensions = r.message[1]; + default_dimensions = r.message[1]; } }); -erpnext.doctypes_with_dimensions.forEach((doctype) => { +doctypes_with_dimensions.forEach((doctype) => { frappe.ui.form.on(doctype, { onload: function(frm) { erpnext.dimension_filters.forEach((dimension) => { @@ -27,41 +29,40 @@ erpnext.doctypes_with_dimensions.forEach((doctype) => { "is_group": 0 }); } - - if (Object.keys(erpnext.default_dimensions).length > 0) { - if (frappe.meta.has_field(doctype, dimension['fieldname'])) { - if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) { - frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]); - } - } - - if (frm.doc.items && frm.doc.items.length && frm.doc.docstatus === 0 - && (!frm.doc.items[0][dimension['fieldname']])) { - frm.doc.items[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']]; - } - - if (frm.doc.accounts && frm.doc.accounts.length && frm.doc.docstatus === 0 - && (!frm.doc.items[0][dimension['fieldname']])) { - frm.doc.accounts[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']]; - } - } }); }); }, company: function(frm) { - if(frm.doc.company && (Object.keys(erpnext.default_dimensions).length > 0)) { - erpnext.dimension_filters.forEach((dimension) => { - if (frappe.meta.has_field(doctype, dimension['fieldname'])) { - frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]); - } - }); + if(frm.doc.company && (Object.keys(default_dimensions || {}).length > 0) + && default_dimensions[frm.doc.company]) { + frm.trigger('update_dimension'); } }, + + update_dimension: function(frm) { + erpnext.dimension_filters.forEach((dimension) => { + if (frm.is_new()) { + if (frm.doc.company && Object.keys(default_dimensions || {}).length > 0 + && default_dimensions[frm.doc.company]) { + + if (frappe.meta.has_field(doctype, dimension['fieldname'])) { + frm.set_value(dimension['fieldname'], + default_dimensions[frm.doc.company][dimension['document_type']]); + } + + $.each(frm.doc.items || frm.doc.accounts || [], function(i, row) { + frappe.model.set_value(row.doctype, row.name, dimension['fieldname'], + default_dimensions[frm.doc.company][dimension['document_type']]) + }); + } + } + }); + } }); }); -erpnext.child_docs.forEach((doctype) => { +child_docs.forEach((doctype) => { frappe.ui.form.on(doctype, { items_add: function(frm, cdt, cdn) { erpnext.dimension_filters.forEach((dimension) => { @@ -77,14 +78,6 @@ erpnext.child_docs.forEach((doctype) => { }); }, - company: function(frm) { - if(frm.doc.company) { - erpnext.dimension_filters.forEach((dimension) => { - frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]); - }); - } - }, - items_add: function(frm, cdt, cdn) { erpnext.dimension_filters.forEach((dimension) => { var row = frappe.get_doc(cdt, cdn); diff --git a/erpnext/public/js/utils/item_quick_entry.js b/erpnext/public/js/utils/item_quick_entry.js index 2947d5b98e..27ef107ace 100644 --- a/erpnext/public/js/utils/item_quick_entry.js +++ b/erpnext/public/js/utils/item_quick_entry.js @@ -8,12 +8,19 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({ render_dialog: function() { this.mandatory = this.get_variant_fields().concat(this.mandatory); this.mandatory = this.mandatory.concat(this.get_attributes_fields()); + this.check_naming_series_based_on(); this._super(); this.init_post_render_dialog_operations(); this.preset_fields_for_template(); this.dialog.$wrapper.find('.edit-full').text(__('Edit in full page for more options like assets, serial nos, batches etc.')) }, + check_naming_series_based_on: function() { + if (frappe.defaults.get_default("item_naming_by") === "Naming Series") { + this.mandatory = this.mandatory.filter(d => d.fieldname !== "item_code"); + } + }, + init_post_render_dialog_operations: function() { this.dialog.fields_dict.attribute_html.$wrapper.append(frappe.render_template("item_quick_entry")); this.init_for_create_variant_trigger(); diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index a240e49b6a..d75633e5a9 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -5,14 +5,13 @@ erpnext.SerialNoBatchSelector = Class.extend({ this.show_dialog = show_dialog; // frm, item, warehouse_details, has_batch, oldest let d = this.item; - if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) { - this.has_batch = 1; - this.setup(); + this.has_batch = 0; this.has_serial_no = 0; + + if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) this.has_batch = 1; // !(this.show_dialog == false) ensures that show_dialog is implictly true, even when undefined - } else if(d && d.has_serial_no && !(this.show_dialog == false)) { - this.has_batch = 0; - this.setup(); - } + if(d && d.has_serial_no && !(this.show_dialog == false)) this.has_serial_no = 1; + + this.setup(); }, setup: function() { @@ -36,16 +35,16 @@ erpnext.SerialNoBatchSelector = Class.extend({ label: __('Item Code'), default: me.item_code }, - {fieldtype:'Column Break'}, { fieldname: 'warehouse', fieldtype:'Link', options: 'Warehouse', + reqd: me.has_batch && !me.has_serial_no ? 0 : 1, label: __(me.warehouse_details.type), - default: me.warehouse_details.name, + default: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '', onchange: function(e) { - if(me.has_batch) { + if(me.has_batch && !me.has_serial_no) { fields = fields.concat(me.get_batch_fields()); } else { fields = fields.concat(me.get_serial_no_fields()); @@ -74,15 +73,16 @@ erpnext.SerialNoBatchSelector = Class.extend({ { fieldname: 'qty', fieldtype:'Float', - read_only: me.has_batch, - label: __(me.has_batch ? 'Total Qty' : 'Qty'), + read_only: me.has_batch && !me.has_serial_no, + label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'), default: 0 }, { fieldname: 'auto_fetch_button', fieldtype:'Button', - hidden: me.has_batch, - label: __('Fetch based on FIFO'), + hidden: me.has_batch && !me.has_serial_no, + label: __('Auto Fetch'), + description: __('Fetch Serial Numbers based on FIFO'), click: () => { let qty = this.dialog.fields_dict.qty.get_value(); let numbers = frappe.call({ @@ -90,7 +90,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ args: { qty: qty, item_code: me.item_code, - warehouse: me.warehouse_details.name, + warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '', batch_no: me.item.batch_no || null } }); @@ -109,10 +109,12 @@ erpnext.SerialNoBatchSelector = Class.extend({ } ]; - if (this.has_batch) { + if (this.has_batch && !this.has_serial_no) { title = __("Select Batch Numbers"); fields = fields.concat(this.get_batch_fields()); } else { + // if only serial no OR + // if both batch_no & serial_no then only select serial_no and auto set batches nos title = __("Select Serial Numbers"); fields = fields.concat(this.get_serial_no_fields()); } @@ -122,25 +124,31 @@ erpnext.SerialNoBatchSelector = Class.extend({ fields: fields }); - if (this.item.serial_no) { - this.dialog.fields_dict.serial_no.set_value(this.item.serial_no); - } - this.dialog.set_primary_action(__('Insert'), function() { me.values = me.dialog.get_values(); if(me.validate()) { - me.set_items(); - me.dialog.hide(); + frappe.run_serially([ + () => me.update_batch_items(), + () => me.update_serial_no_item(), + () => me.update_batch_serial_no_items(), + () => { + refresh_field("items"); + if (me.callback) { + return me.callback(me.item); + } + }, + () => me.dialog.hide() + ]) } }); if(this.show_dialog) { let d = this.item; - if (d.has_serial_no && d.serial_no) { - this.dialog.set_value('serial_no', d.serial_no); + if (this.item.serial_no) { + this.dialog.fields_dict.serial_no.set_value(this.item.serial_no); } - - if (d.has_batch_no && d.batch_no) { + + if (this.has_batch && !this.has_serial_no && d.batch_no) { this.frm.doc.items.forEach(data => { if(data.item_code == d.item_code) { this.dialog.fields_dict.batches.df.data.push({ @@ -155,7 +163,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ } } - if (this.has_batch) { + if (this.has_batch && !this.has_serial_no) { this.update_total_qty(); } @@ -174,7 +182,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ frappe.throw(__("Please select a warehouse")); return false; } - if(this.has_batch) { + if(this.has_batch && !this.has_serial_no) { if(values.batches.length === 0 || !values.batches) { frappe.throw(__("Please select batches for batched item " + values.item_code)); @@ -193,34 +201,23 @@ erpnext.SerialNoBatchSelector = Class.extend({ } else { let serial_nos = values.serial_no || ''; if (!serial_nos || !serial_nos.replace(/\s/g, '').length) { - if (!this.show_dialog) { - frappe.throw(__("Please enter serial numbers for serialized item " - + values.item_code)); - return false; - } + frappe.throw(__("Please enter serial numbers for serialized item " + + values.item_code)); + return false; } return true; } }, - set_items: function() { - var me = this; - if(this.has_batch) { + update_batch_items() { + // clones an items if muliple batches are selected. + if(this.has_batch && !this.has_serial_no) { this.values.batches.map((batch, i) => { let batch_no = batch.batch_no; let row = ''; if (i !== 0 && !this.batch_exists(batch_no)) { - row = this.frm.add_child("items", { - 'item_code': this.item.item_code, - 'item_name': this.item.item_name, - 'price_list_rate': this.item.price_list_rate, - 'rate': this.item.rate, - 'qty': batch.selected_qty, - 'batch_no': batch_no, - 'actual_qty': this.item.actual_qty, - 'discount_percentage': this.item.discount_percentage - }); + row = this.frm.add_child("items", { ...this.item }); } else { row = this.frm.doc.items.find(i => i.batch_no === batch_no); } @@ -228,16 +225,59 @@ erpnext.SerialNoBatchSelector = Class.extend({ if (!row) { row = this.item; } - + // this ensures that qty & batch no is set this.map_row_values(row, batch, 'batch_no', 'selected_qty', this.values.warehouse); }); - } else { + } + }, + + update_serial_no_item() { + // just updates serial no for the item + if(this.has_serial_no && !this.has_batch) { this.map_row_values(this.item, this.values, 'serial_no', 'qty'); } + }, - refresh_field("items"); - this.callback && this.callback(this.item); + update_batch_serial_no_items() { + // if serial no selected is from different batches, adds new rows for each batch. + if(this.has_batch && this.has_serial_no) { + const selected_serial_nos = this.values.serial_no.split(/\n/g).filter(s => s); + + return frappe.db.get_list("Serial No", { + filters: { 'name': ["in", selected_serial_nos]}, + fields: ["batch_no", "name"] + }).then((data) => { + // data = [{batch_no: 'batch-1', name: "SR-001"}, + // {batch_no: 'batch-2', name: "SR-003"}, {batch_no: 'batch-2', name: "SR-004"}] + const batch_serial_map = data.reduce((acc, d) => { + if (!acc[d['batch_no']]) acc[d['batch_no']] = []; + acc[d['batch_no']].push(d['name']) + return acc + }, {}) + // batch_serial_map = { "batch-1": ['SR-001'], "batch-2": ["SR-003", "SR-004"]} + Object.keys(batch_serial_map).map((batch_no, i) => { + let row = ''; + const serial_no = batch_serial_map[batch_no]; + if (i == 0) { + row = this.item; + this.map_row_values(row, {qty: serial_no.length, batch_no: batch_no}, 'batch_no', + 'qty', this.values.warehouse); + } else if (!this.batch_exists(batch_no)) { + row = this.frm.add_child("items", { ...this.item }); + row.batch_no = batch_no; + } else { + row = this.frm.doc.items.find(i => i.batch_no === batch_no); + } + const values = { + 'qty': serial_no.length, + 'serial_no': serial_no.join('\n') + } + this.map_row_values(row, values, 'serial_no', + 'qty', this.values.warehouse); + }); + }) + } }, batch_exists: function(batch) { @@ -287,7 +327,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ return { filters: { item_code: me.item_code, - warehouse: me.warehouse || me.warehouse_details.name + warehouse: me.warehouse || typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '' }, query: 'erpnext.controllers.queries.get_batch_no' }; @@ -313,11 +353,15 @@ erpnext.SerialNoBatchSelector = Class.extend({ frappe.throw(__(`Batch ${val} already selected.`)); return; } + + let batch_number = me.item.batch_no || + this.grid_row.on_grid_fields_dict.batch_no.get_value(); + if (me.warehouse_details.name) { frappe.call({ method: 'erpnext.stock.doctype.batch.batch.get_batch_qty', args: { - batch_no: me.item.batch_no, + batch_no: batch_number, warehouse: me.warehouse_details.name, item_code: me.item_code }, @@ -444,7 +488,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ { fieldname: 'serial_no', fieldtype: 'Small Text', - label: __(me.has_batch ? 'Selected Batch Numbers' : 'Selected Serial Numbers'), + label: __(me.has_batch && !me.has_serial_no ? 'Selected Batch Numbers' : 'Selected Serial Numbers'), onchange: function() { me.serial_list = this.get_value() .replace(/\n/g, ' ').match(/\S+/g) || []; diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss index 7b9a70d232..735b417da1 100644 --- a/erpnext/public/scss/website.scss +++ b/erpnext/public/scss/website.scss @@ -78,3 +78,7 @@ z-index: 0; } } + +.place-order-container { + text-align: right; +} \ No newline at end of file diff --git a/erpnext/quality_management/desk_page/quality/quality.json b/erpnext/quality_management/desk_page/quality/quality.json index 5193e0cfde..5ee70008dd 100644 --- a/erpnext/quality_management/desk_page/quality/quality.json +++ b/erpnext/quality_management/desk_page/quality/quality.json @@ -1,20 +1,24 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"Quality Goal.\",\n \"label\": \"Quality Goal\",\n \"name\": \"Quality Goal\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Quality Procedure.\",\n \"label\": \"Quality Procedure\",\n \"name\": \"Quality Procedure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of Quality Procedures.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Tree of Procedures\",\n \"name\": \"Quality Procedure\",\n \"route\": \"#Tree/Quality Procedure\",\n \"type\": \"doctype\"\n }\n]", - "title": "Goal and Procedure" + "hidden": 0, + "label": "Goal and Procedure", + "links": "[\n {\n \"description\": \"Quality Goal.\",\n \"label\": \"Quality Goal\",\n \"name\": \"Quality Goal\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Quality Procedure.\",\n \"label\": \"Quality Procedure\",\n \"name\": \"Quality Procedure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of Quality Procedures.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Tree of Procedures\",\n \"name\": \"Quality Procedure\",\n \"route\": \"#Tree/Quality Procedure\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Quality Feedback\",\n \"label\": \"Quality Feedback\",\n \"name\": \"Quality Feedback\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Quality Feedback Template\",\n \"label\": \"Quality Feedback Template\",\n \"name\": \"Quality Feedback Template\",\n \"type\": \"doctype\"\n }\n]", - "title": "Feedback" + "hidden": 0, + "label": "Feedback", + "links": "[\n {\n \"description\": \"Quality Feedback\",\n \"label\": \"Quality Feedback\",\n \"name\": \"Quality Feedback\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Quality Feedback Template\",\n \"label\": \"Quality Feedback Template\",\n \"name\": \"Quality Feedback Template\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Quality Meeting\",\n \"label\": \"Quality Meeting\",\n \"name\": \"Quality Meeting\",\n \"type\": \"doctype\"\n }\n]", - "title": "Meeting" + "hidden": 0, + "label": "Meeting", + "links": "[\n {\n \"description\": \"Quality Meeting\",\n \"label\": \"Quality Meeting\",\n \"name\": \"Quality Meeting\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Quality Review\",\n \"label\": \"Quality Review\",\n \"name\": \"Quality Review\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Quality Action\",\n \"label\": \"Quality Action\",\n \"name\": \"Quality Action\",\n \"type\": \"doctype\"\n }\n]", - "title": "Review and Action" + "hidden": 0, + "label": "Review and Action", + "links": "[\n {\n \"description\": \"Quality Review\",\n \"label\": \"Quality Review\",\n \"name\": \"Quality Review\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Quality Action\",\n \"label\": \"Quality Action\",\n \"name\": \"Quality Action\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Modules", @@ -29,7 +33,7 @@ "idx": 0, "is_standard": 1, "label": "Quality", - "modified": "2020-03-12 16:30:39.093081", + "modified": "2020-04-01 11:28:51.095012", "modified_by": "Administrator", "module": "Quality Management", "name": "Quality", @@ -38,17 +42,17 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Quality Goal", "link_to": "Quality Goal", "type": "DocType" }, { - "is_query_report": 0, + "label": "Quality Procedure", "link_to": "Quality Procedure", "type": "DocType" }, { - "is_query_report": 0, + "label": "Quality Inspection", "link_to": "Quality Inspection", "type": "DocType" } diff --git a/erpnext/regional/address_template/README.md b/erpnext/regional/address_template/README.md new file mode 100644 index 0000000000..991573448e --- /dev/null +++ b/erpnext/regional/address_template/README.md @@ -0,0 +1,18 @@ +To add an **Address Template** for your country, place a new file in this directory: + + * File name: `your_country.html` (lower case with underscores) + * File content: a [Jinja Template](http://jinja.pocoo.org/docs/templates/). + +All the fields of **Address** (including Custom Fields, if any) will be available to the template. Example: + +```jinja +{{ address_line1 }}
+{% if address_line2 %}{{ address_line2 }}
{% endif -%} +{{ city }}
+{% if state %}{{ state }}
{% endif -%} +{% if pincode %} PIN: {{ pincode }}
{% endif -%} +{{ country }}
+{% if phone %}Phone: {{ phone }}
{% endif -%} +{% if fax %}Fax: {{ fax }}
{% endif -%} +{% if email_id %}Email: {{ email_id }}
{% endif -%} +``` diff --git a/erpnext/regional/address_template/__init__.py b/erpnext/regional/address_template/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/regional/address_template/setup.py b/erpnext/regional/address_template/setup.py new file mode 100644 index 0000000000..9f318de345 --- /dev/null +++ b/erpnext/regional/address_template/setup.py @@ -0,0 +1,53 @@ +"""Import Address Templates from ./templates directory.""" +import os +import frappe + +def set_up_address_templates(default_country=None): + for country, html in get_address_templates(): + is_default = 1 if country == default_country else 0 + update_address_template(country, html, is_default) + +def get_address_templates(): + """ + Return country and path for all HTML files in this directory. + + Returns a list of dicts. + """ + def country(file_name): + """Convert 'united_states.html' to 'United States'.""" + suffix_pos = file_name.find(".html") + country_snake_case = file_name[:suffix_pos] + country_title_case = " ".join(country_snake_case.split("_")).title() + return country_title_case + + def get_file_content(file_name): + """Convert 'united_states.html' to '/path/to/united_states.html'.""" + full_path = os.path.join(template_dir, file_name) + with open(full_path, "r") as f: + content = f.read() + return content + + dir_name = os.path.dirname(__file__) + template_dir = os.path.join(dir_name, "templates") + file_names = os.listdir(template_dir) + html_files = [file for file in file_names if file.endswith(".html")] + + return [(country(file_name), get_file_content(file_name)) for file_name in html_files] + + +def update_address_template(country, html, is_default=0): + """Update existing Address Template or create a new one.""" + if not frappe.db.exists("Country", country): + frappe.log_error("Country {} for regional Address Template does not exist.".format(country)) + return + + if frappe.db.exists("Address Template", country): + frappe.db.set_value("Address Template", country, "template", html) + frappe.db.set_value("Address Template", country, "is_default", is_default) + else: + frappe.get_doc(dict( + doctype="Address Template", + country=country, + is_default=is_default, + template=html + )).insert() diff --git a/erpnext/regional/germany/address_template.html b/erpnext/regional/address_template/templates/germany.html similarity index 100% rename from erpnext/regional/germany/address_template.html rename to erpnext/regional/address_template/templates/germany.html diff --git a/erpnext/regional/india/address_template.html b/erpnext/regional/address_template/templates/india.html similarity index 89% rename from erpnext/regional/india/address_template.html rename to erpnext/regional/address_template/templates/india.html index 55cc9af0d1..ffb9d0547e 100644 --- a/erpnext/regional/india/address_template.html +++ b/erpnext/regional/address_template/templates/india.html @@ -6,4 +6,4 @@ {% if phone %}Phone: {{ phone }}
{% endif -%} {% if fax %}Fax: {{ fax }}
{% endif -%} {% if email_id %}Email: {{ email_id }}
{% endif -%} -{% if gstin %}GSTIN: {{ gstin }}
{% endif -%} \ No newline at end of file +{% if gstin %}GSTIN: {{ gstin }}
{% endif -%} diff --git a/erpnext/regional/united_states/address_template.html b/erpnext/regional/address_template/templates/united_states.html similarity index 100% rename from erpnext/regional/united_states/address_template.html rename to erpnext/regional/address_template/templates/united_states.html diff --git a/erpnext/regional/address_template/test_regional_address_template.py b/erpnext/regional/address_template/test_regional_address_template.py new file mode 100644 index 0000000000..8a05ea26f4 --- /dev/null +++ b/erpnext/regional/address_template/test_regional_address_template.py @@ -0,0 +1,45 @@ +from __future__ import unicode_literals +from unittest import TestCase + +import frappe +from erpnext.regional.address_template.setup import get_address_templates +from erpnext.regional.address_template.setup import update_address_template + +def ensure_country(country): + if frappe.db.exists("Country", country): + return frappe.get_doc("Country", country) + else: + c = frappe.get_doc({ + "doctype": "Country", + "country_name": country + }) + c.insert() + return c + +class TestRegionalAddressTemplate(TestCase): + def test_get_address_templates(self): + """Get the countries and paths from the templates directory.""" + templates = get_address_templates() + self.assertIsInstance(templates, list) + self.assertIsInstance(templates[0], tuple) + + def test_create_address_template(self): + """Create a new Address Template.""" + country = ensure_country("Germany") + update_address_template(country.name, "TEST") + doc = frappe.get_doc("Address Template", country.name) + self.assertEqual(doc.template, "TEST") + + def test_update_address_template(self): + """Update an existing Address Template.""" + country = ensure_country("Germany") + if not frappe.db.exists("Address Template", country.name): + template = frappe.get_doc({ + "doctype": "Address Template", + "country": country.name, + "template": "EXISTING" + }).insert() + + update_address_template(country.name, "NEW") + doc = frappe.get_doc("Address Template", country.name) + self.assertEqual(doc.template, "NEW") diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html index 2da79a6364..35f9cf674c 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html @@ -29,7 +29,7 @@ - (a) {{__("Outward taxable supplies(other than zero rated, nil rated and exempted")}} + (a) {{__("Outward taxable supplies(other than zero rated, nil rated and exempted)")}} {{ flt(data.sup_details.osup_det.txval, 2) }} {{ flt(data.sup_details.osup_det.iamt, 2) }} {{ flt(data.sup_details.osup_det.camt, 2) }} diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json index 548d40b974..1f208df1f2 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json @@ -1,4 +1,5 @@ { + "actions": [], "autoname": "format:GSTR3B-{month}-{year}-{company_address}", "creation": "2019-02-04 11:35:55.964639", "doctype": "DocType", @@ -48,25 +49,13 @@ "read_only": 1 } ], - "modified": "2019-08-10 22:30:26.727038", + "links": [], + "modified": "2020-04-04 19:32:30.772908", "modified_by": "Administrator", "module": "Regional", "name": "GSTR 3B Report", "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], + "permissions": [], "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index a2b32fec78..9e7a023926 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -277,7 +277,7 @@ class GSTR3BReport(Document): def get_itc_details(self, reverse_charge='N'): itc_amount = frappe.db.sql(""" - select s.gst_category, sum(t.tax_amount) as tax_amount, t.account_head, s.eligibility_for_itc, s.reverse_charge + select s.gst_category, sum(t.tax_amount_after_discount_amount) as tax_amount, t.account_head, s.eligibility_for_itc, s.reverse_charge from `tabPurchase Invoice` s , `tabPurchase Taxes and Charges` t where s.docstatus = 1 and t.parent = s.name and s.reverse_charge = %s and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s @@ -312,7 +312,7 @@ class GSTR3BReport(Document): and s.company = %s and s.company_gstin = %s and s.gst_category in ('Unregistered', 'Registered Composition', 'UIN Holders') group by s.gst_category, s.place_of_supply""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) - inter_state_supply_tax = frappe.db.sql(""" select sum(t.tax_amount) as tax_amount, s.place_of_supply, s.gst_category + inter_state_supply_tax = frappe.db.sql(""" select sum(t.tax_amount_after_discount_amount) as tax_amount, s.place_of_supply, s.gst_category from `tabSales Invoice` s, `tabSales Taxes and Charges` t where t.parent = s.name and s.docstatus = 1 and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s and s.company_gstin = %s and s.gst_category in ('Unregistered', 'Registered Composition', 'UIN Holders') @@ -385,7 +385,7 @@ class GSTR3BReport(Document): tax_template = 'Purchase Taxes and Charges' tax_amounts = frappe.db.sql(""" - select s.gst_category, sum(t.tax_amount) as tax_amount, t.account_head + select s.gst_category, sum(t.tax_amount_after_discount_amount) as tax_amount, t.account_head from `tab{doctype}` s , `tab{template}` t where s.docstatus = 1 and t.parent = s.name and s.reverse_charge = %s and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s diff --git a/erpnext/regional/germany/setup.py b/erpnext/regional/germany/setup.py index a5471366ca..d6047e863c 100644 --- a/erpnext/regional/germany/setup.py +++ b/erpnext/regional/germany/setup.py @@ -3,29 +3,4 @@ import frappe def setup(company=None, patch=True): - if not patch: - update_address_template() - - -def update_address_template(): - """ - Read address template from file. Update existing Address Template or create a - new one. - """ - dir_name = os.path.dirname(__file__) - template_path = os.path.join(dir_name, 'address_template.html') - - with open(template_path, 'r') as template_file: - template_html = template_file.read() - - address_template = frappe.db.get_value('Address Template', 'Germany') - - if address_template: - frappe.db.set_value('Address Template', 'Germany', 'template', template_html) - else: - # make new html template for Germany - frappe.get_doc(dict( - doctype='Address Template', - country='Germany', - template=template_html - )).insert() + pass diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 970a831e0e..28b1f8ffb8 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -13,7 +13,6 @@ from frappe.utils import today def setup(company=None, patch=True): setup_company_independent_fixtures() if not patch: - update_address_template() make_fixtures(company) # TODO: for all countries @@ -24,21 +23,6 @@ def setup_company_independent_fixtures(): frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test) add_print_formats() -def update_address_template(): - with open(os.path.join(os.path.dirname(__file__), 'address_template.html'), 'r') as f: - html = f.read() - - address_template = frappe.db.get_value('Address Template', 'India') - if address_template: - frappe.db.set_value('Address Template', 'India', 'template', html) - else: - # make new html template for India - frappe.get_doc(dict( - doctype='Address Template', - country='India', - template=html - )).insert() - def add_hsn_sac_codes(): # HSN codes with open(os.path.join(os.path.dirname(__file__), 'hsn_code_data.json'), 'r') as f: @@ -77,13 +61,19 @@ def add_custom_roles_for_reports(): )).insert() def add_permissions(): - for doctype in ('GST HSN Code', 'GST Settings'): + for doctype in ('GST HSN Code', 'GST Settings', 'GSTR 3B Report'): add_permission(doctype, 'All', 0) - for role in ('Accounts Manager', 'System Manager', 'Item Manager', 'Stock Manager'): + for role in ('Accounts Manager', 'Accounts User', 'System Manager'): add_permission(doctype, role, 0) update_permission_property(doctype, role, 0, 'write', 1) update_permission_property(doctype, role, 0, 'create', 1) + if doctype == 'GST HSN Code': + for role in ('Item Manager', 'Stock Manager'): + add_permission(doctype, role, 0) + update_permission_property(doctype, role, 0, 'write', 1) + update_permission_property(doctype, role, 0, 'create', 1) + def add_print_formats(): frappe.reload_doc("regional", "print_format", "gst_tax_invoice") frappe.reload_doc("accounts", "print_format", "gst_pos_invoice") diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js index 1e000b673e..d8638ab05d 100644 --- a/erpnext/regional/report/datev/datev.js +++ b/erpnext/regional/report/datev/datev.js @@ -21,6 +21,12 @@ frappe.query_reports["DATEV"] = { "default": frappe.datetime.now_date(), "fieldtype": "Date", "reqd": 1 + }, + { + "fieldname": "voucher_type", + "label": __("Voucher Type"), + "fieldtype": "Select", + "options": "\nSales Invoice\nPurchase Invoice\nPayment Entry\nExpense Claim\nPayroll Entry\nBank Reconciliation\nAsset\nStock Entry" } ], onload: function(query_report) { diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 7ceaf50134..a8e40cc493 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -13,6 +13,7 @@ import json import zlib import zipfile import six +from csv import QUOTE_NONNUMERIC from six import BytesIO from six import string_types import frappe @@ -62,6 +63,7 @@ def get_transactions(filters, as_dict=1): filters -- dict of filters to be passed to the sql query as_dict -- return as list of dicts [0,1] """ + filter_by_voucher = 'AND gl.voucher_type = %(voucher_type)s' if filters.get('voucher_type') else '' gl_entries = frappe.db.sql(""" SELECT @@ -79,9 +81,11 @@ def get_transactions(filters, as_dict=1): gl.posting_date as 'Belegdatum', gl.voucher_no as 'Belegfeld 1', - gl.remarks as 'Buchungstext', - gl.against_voucher_type as 'Beleginfo - Art 1', - gl.against_voucher as 'Beleginfo - Inhalt 1' + LEFT(gl.remarks, 60) as 'Buchungstext', + gl.voucher_type as 'Beleginfo - Art 1', + gl.voucher_no as 'Beleginfo - Inhalt 1', + gl.against_voucher_type as 'Beleginfo - Art 2', + gl.against_voucher as 'Beleginfo - Inhalt 2' FROM `tabGL Entry` gl @@ -109,7 +113,8 @@ def get_transactions(filters, as_dict=1): WHERE gl.company = %(company)s AND DATE(gl.posting_date) >= %(from_date)s AND DATE(gl.posting_date) <= %(to_date)s - ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1) + {} + ORDER BY 'Belegdatum', gl.voucher_no""".format(filter_by_voucher), filters, as_dict=as_dict) return gl_entries @@ -160,7 +165,7 @@ def get_customers(filters): and ccl.company = par.company WHERE par.company = %(company)s - AND par.parenttype = 'Customer'""", filters, as_dict=1, as_utf8=1) + AND par.parenttype = 'Customer'""", filters, as_dict=1) def get_suppliers(filters): @@ -217,7 +222,7 @@ def get_suppliers(filters): and con.is_primary_contact = '1' WHERE par.company = %(company)s - AND par.parenttype = 'Supplier'""", filters, as_dict=1, as_utf8=1) + AND par.parenttype = 'Supplier'""", filters, as_dict=1) def get_account_names(filters): @@ -264,7 +269,9 @@ def get_datev_csv(data, filters, csv_class): # Do not number rows index=False, # Use all columns defined above - columns=csv_class.COLUMNS + columns=csv_class.COLUMNS, + # Quote most fields, even currency values with "," separator + quoting=QUOTE_NONNUMERIC ) if not six.PY2: @@ -281,24 +288,25 @@ def get_datev_csv(data, filters, csv_class): def get_header(filters, csv_class): coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts") - coa_used = "SKR04" if "SKR04" in coa else ("SKR03" if "SKR03" in coa else "") + description = filters.get("voucher_type", csv_class.FORMAT_NAME) + coa_used = "04" if "SKR04" in coa else ("03" if "SKR03" in coa else "") header = [ # DATEV format - # "DTVF" = created by DATEV software, - # "EXTF" = created by other software + # "DTVF" = created by DATEV software, + # "EXTF" = created by other software '"EXTF"', # version of the DATEV format - # 141 = 1.41, - # 510 = 5.10, - # 720 = 7.20 + # 141 = 1.41, + # 510 = 5.10, + # 720 = 7.20 '700', csv_class.DATA_CATEGORY, '"%s"' % csv_class.FORMAT_NAME, # Format version (regarding format name) csv_class.FORMAT_VERSION, # Generated on - datetime.datetime.now().strftime("%Y%m%d%H%M%S"), + datetime.datetime.now().strftime("%Y%m%d%H%M%S") + '000', # Imported on -- stays empty '', # Origin. Any two symbols, will be replaced by "SV" on import. @@ -319,22 +327,26 @@ def get_header(filters, csv_class): frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd"), # P = Transaction batch end date (YYYYMMDD) frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"), - # Q = Description (for example, "January - February 2019 Transactions") - '"{} - {} {}"'.format( - frappe.utils.formatdate(filters.get('from_date'), "MMMM yyyy"), - frappe.utils.formatdate(filters.get('to_date'), "MMMM yyyy"), - csv_class.FORMAT_NAME - ), + # Q = Description (for example, "Sales Invoice") Max. 30 chars + '"{}"'.format(_(description)), # R = Diktatkürzel '', # S = Buchungstyp - # 1 = Transaction batch (Finanzbuchführung), - # 2 = Annual financial statement (Jahresabschluss) + # 1 = Transaction batch (Finanzbuchführung), + # 2 = Annual financial statement (Jahresabschluss) '1' if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '', # T = Rechnungslegungszweck - '', + # 0 oder leer = vom Rechnungslegungszweck unabhängig + # 50 = Handelsrecht + # 30 = Steuerrecht + # 64 = IFRS + # 40 = Kalkulatorik + # 11 = Reserviert + # 12 = Reserviert + '0', # U = Festschreibung - '', + # TODO: Filter by Accounting Period. In export for closed Accounting Period, this will be "1" + '0', # V = Default currency, for example, "EUR" '"%s"' % frappe.get_value("Company", filters.get("company"), "default_currency"), # reserviert diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py index a4cd5fc10e..a059ed365a 100644 --- a/erpnext/regional/report/datev/datev_constants.py +++ b/erpnext/regional/report/datev/datev_constants.py @@ -498,13 +498,27 @@ QUERY_REPORT_COLUMNS = [ }, { "label": "Beleginfo - Art 1", - "fieldname": "Beleginfo - Art 2", - "fieldtype": "Data", + "fieldname": "Beleginfo - Art 1", + "fieldtype": "Link", + "options": "DocType" }, { "label": "Beleginfo - Inhalt 1", + "fieldname": "Beleginfo - Inhalt 1", + "fieldtype": "Dynamic Link", + "options": "Beleginfo - Art 1" + }, + { + "label": "Beleginfo - Art 2", + "fieldname": "Beleginfo - Art 2", + "fieldtype": "Link", + "options": "DocType" + }, + { + "label": "Beleginfo - Inhalt 2", "fieldname": "Beleginfo - Inhalt 2", - "fieldtype": "Data", + "fieldtype": "Dynamic Link", + "options": "Beleginfo - Art 2" } ] diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 2c5ab7cb91..fd1cc58c20 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -54,8 +54,8 @@ class Gstr1Report(object): return self.columns, self.data def get_data(self): - if self.filters.get("type_of_business") == "B2C Small": - self.get_b2cs_data() + if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"): + self.get_b2c_data() else: for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): invoice_details = self.invoices.get(inv) @@ -69,7 +69,7 @@ class Gstr1Report(object): if taxable_value: self.data.append(row) - def get_b2cs_data(self): + def get_b2c_data(self): b2cs_output = {} for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): @@ -84,7 +84,10 @@ class Gstr1Report(object): "rate": "", "taxable_value": 0, "cess_amount": 0, - "type": "" + "type": "", + "invoice_number": invoice_details.get("invoice_number"), + "posting_date": invoice_details.get("posting_date"), + "invoice_value": invoice_details.get("base_grand_total"), }) row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin)) @@ -164,7 +167,7 @@ class Gstr1Report(object): frappe.throw(_("Please set B2C Limit in GST Settings.")) if self.filters.get("type_of_business") == "B2C Large": - conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2) + conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) elif self.filters.get("type_of_business") == "B2C Small": @@ -581,6 +584,11 @@ def get_b2b_json(res, gstin): if not gst_in: continue for number, invoice in iteritems(res[gst_in]): + if not invoice[0]["place_of_supply"]: + frappe.throw(_("""{0} not entered in Invoice {1}. + Please update and try again""").format(frappe.bold("Place Of Supply"), + frappe.bold(invoice[0]['invoice_number']))) + inv_item = get_basic_invoice_detail(invoice[0]) inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0]) inv_item["rchrg"] = invoice[0]["reverse_charge"] @@ -606,6 +614,9 @@ def get_b2cs_json(data, gstin): out = [] for d in data: + if not d.get("place_of_supply"): + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) pos = d.get('place_of_supply').split('-')[0] tax_details = {} @@ -642,6 +653,10 @@ def get_b2cs_json(data, gstin): def get_b2cl_json(res, gstin): out = [] for pos in res: + if not pos: + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) + b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, [] for row in res[pos]: diff --git a/erpnext/regional/united_states/setup.py b/erpnext/regional/united_states/setup.py index cb82b639ba..6d344025d2 100644 --- a/erpnext/regional/united_states/setup.py +++ b/erpnext/regional/united_states/setup.py @@ -5,12 +5,9 @@ from __future__ import unicode_literals import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields - def setup(company=None, patch=True): make_custom_fields() add_print_formats() - update_address_template() - def make_custom_fields(): custom_fields = { @@ -21,22 +18,7 @@ def make_custom_fields(): } create_custom_fields(custom_fields) - def add_print_formats(): frappe.reload_doc("regional", "print_format", "irs_1099_form") frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where name in('IRS 1099 Form') """) - - -def update_address_template(): - html = """{{ address_line1 }}
- {% if address_line2 %}{{ address_line2 }}
{% endif -%} - {{ city }}, {% if state %}{{ state }}{% endif -%}{% if pincode %} {{ pincode }}
{% endif -%} - {% if country != "United States" %}{{ country|upper }}{% endif -%} - """ - - address_template = frappe.db.get_value('Address Template', 'United States') - if address_template: - frappe.db.set_value('Address Template', 'United States', 'template', html) - else: - frappe.get_doc(dict(doctype='Address Template', country='United States', template=html)).insert() diff --git a/erpnext/selling/desk_page/retail/retail.json b/erpnext/selling/desk_page/retail/retail.json index 9838462f68..9f3912db4c 100644 --- a/erpnext/selling/desk_page/retail/retail.json +++ b/erpnext/selling/desk_page/retail/retail.json @@ -1,8 +1,9 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"Setup default values for POS Invoices\",\n \"label\": \"Point-of-Sale Profile\",\n \"name\": \"POS Profile\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"POS Profile\"\n ],\n \"description\": \"Point of Sale\",\n \"label\": \"POS\",\n \"name\": \"pos\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"description\": \"Cashier Closing\",\n \"label\": \"Cashier Closing\",\n \"name\": \"Cashier Closing\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup mode of POS (Online / Offline)\",\n \"label\": \"POS Settings\",\n \"name\": \"POS Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To make Customer based incentive schemes.\",\n \"label\": \"Loyalty Program\",\n \"name\": \"Loyalty Program\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To view logs of Loyalty Points assigned to a Customer.\",\n \"label\": \"Loyalty Point Entry\",\n \"name\": \"Loyalty Point Entry\",\n \"type\": \"doctype\"\n }\n]", - "title": "Retail Operations" + "hidden": 0, + "label": "Retail Operations", + "links": "[\n {\n \"description\": \"Setup default values for POS Invoices\",\n \"label\": \"Point-of-Sale Profile\",\n \"name\": \"POS Profile\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"POS Profile\"\n ],\n \"description\": \"Point of Sale\",\n \"label\": \"POS\",\n \"name\": \"pos\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"description\": \"Cashier Closing\",\n \"label\": \"Cashier Closing\",\n \"name\": \"Cashier Closing\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup mode of POS (Online / Offline)\",\n \"label\": \"POS Settings\",\n \"name\": \"POS Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To make Customer based incentive schemes.\",\n \"label\": \"Loyalty Program\",\n \"name\": \"Loyalty Program\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To view logs of Loyalty Points assigned to a Customer.\",\n \"label\": \"Loyalty Point Entry\",\n \"name\": \"Loyalty Point Entry\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Domains", @@ -16,7 +17,7 @@ "idx": 0, "is_standard": 1, "label": "Retail", - "modified": "2020-03-12 16:30:36.154297", + "modified": "2020-04-01 11:28:50.966145", "modified_by": "Administrator", "module": "Selling", "name": "Retail", diff --git a/erpnext/selling/desk_page/selling/selling.json b/erpnext/selling/desk_page/selling/selling.json index 7a0111c8f9..a20806b264 100644 --- a/erpnext/selling/desk_page/selling/selling.json +++ b/erpnext/selling/desk_page/selling/selling.json @@ -1,36 +1,36 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"All Products or Services.\",\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Price List\"\n ],\n \"description\": \"Multiple Item prices.\",\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"onboard\": 1,\n \"route\": \"#Report/Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Price List master.\",\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of Item Groups.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Bundle items at time of sale.\",\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for applying different promotional schemes.\",\n \"label\": \"Promotional Scheme\",\n \"name\": \"Promotional Scheme\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Rules for applying pricing and discount.\",\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for adding shipping costs.\",\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define coupon codes.\",\n \"label\": \"Coupon Code\",\n \"name\": \"Coupon Code\",\n \"type\": \"doctype\"\n }\n]", - "title": "Items and Pricing" + "hidden": 0, + "label": "Items and Pricing", + "links": "[\n {\n \"description\": \"All Products or Services.\",\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Price List\"\n ],\n \"description\": \"Multiple Item prices.\",\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"onboard\": 1,\n \"route\": \"#Report/Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Price List master.\",\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of Item Groups.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Bundle items at time of sale.\",\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for applying different promotional schemes.\",\n \"label\": \"Promotional Scheme\",\n \"name\": \"Promotional Scheme\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Rules for applying pricing and discount.\",\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for adding shipping costs.\",\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define coupon codes.\",\n \"label\": \"Coupon Code\",\n \"name\": \"Coupon Code\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-cog", - "links": "[\n {\n \"description\": \"Default settings for selling transactions.\",\n \"label\": \"Selling Settings\",\n \"name\": \"Selling Settings\",\n \"settings\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Template of terms or contract.\",\n \"label\": \"Terms and Conditions Template\",\n \"name\": \"Terms and Conditions\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for selling transactions.\",\n \"label\": \"Sales Taxes and Charges Template\",\n \"name\": \"Sales Taxes and Charges Template\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Track Leads by Lead Source.\",\n \"label\": \"Lead Source\",\n \"name\": \"Lead Source\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Customer Group Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Customer Group\",\n \"link\": \"Tree/Customer Group\",\n \"name\": \"Customer Group\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Contacts.\",\n \"label\": \"Contact\",\n \"name\": \"Contact\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Addresses.\",\n \"label\": \"Address\",\n \"name\": \"Address\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Territory Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Territory\",\n \"link\": \"Tree/Territory\",\n \"name\": \"Territory\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Sales campaigns.\",\n \"label\": \"Campaign\",\n \"name\": \"Campaign\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"description\": \"Default settings for selling transactions.\",\n \"label\": \"Selling Settings\",\n \"name\": \"Selling Settings\",\n \"settings\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Template of terms or contract.\",\n \"label\": \"Terms and Conditions Template\",\n \"name\": \"Terms and Conditions\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for selling transactions.\",\n \"label\": \"Sales Taxes and Charges Template\",\n \"name\": \"Sales Taxes and Charges Template\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Track Leads by Lead Source.\",\n \"label\": \"Lead Source\",\n \"name\": \"Lead Source\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Customer Group Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Customer Group\",\n \"link\": \"Tree/Customer Group\",\n \"name\": \"Customer Group\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Contacts.\",\n \"label\": \"Contact\",\n \"name\": \"Contact\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"All Addresses.\",\n \"label\": \"Address\",\n \"name\": \"Address\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Territory Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Territory\",\n \"link\": \"Tree/Territory\",\n \"name\": \"Territory\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Sales campaigns.\",\n \"label\": \"Campaign\",\n \"name\": \"Campaign\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"BOM\"\n ],\n \"doctype\": \"BOM\",\n \"is_query_report\": true,\n \"label\": \"BOM Search\",\n \"name\": \"BOM Search\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n }\n]", - "title": "Other Reports" + "hidden": 0, + "label": "Other Reports", + "links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"BOM\"\n ],\n \"doctype\": \"BOM\",\n \"is_query_report\": true,\n \"label\": \"BOM Search\",\n \"name\": \"BOM Search\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-star", - "links": "[\n {\n \"description\": \"Customer Database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Quotes to Leads or Customers.\",\n \"label\": \"Quotation\",\n \"name\": \"Quotation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Confirmed orders from Customers.\",\n \"label\": \"Sales Order\",\n \"name\": \"Sales Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Invoices for Costumers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Blanket Orders from Costumers.\",\n \"label\": \"Blanket Order\",\n \"name\": \"Blanket Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Manage Sales Partners.\",\n \"label\": \"Sales Partner\",\n \"name\": \"Sales Partner\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Manage Sales Person Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Sales Person\",\n \"link\": \"Tree/Sales Person\",\n \"name\": \"Sales Person\",\n \"type\": \"doctype\"\n }\n]", - "title": "Sales" + "hidden": 0, + "label": "Sales", + "links": "[\n {\n \"description\": \"Customer Database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Quotes to Leads or Customers.\",\n \"label\": \"Quotation\",\n \"name\": \"Quotation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Confirmed orders from Customers.\",\n \"label\": \"Sales Order\",\n \"name\": \"Sales Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Invoices for Costumers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Blanket Orders from Costumers.\",\n \"label\": \"Blanket Order\",\n \"name\": \"Blanket Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Manage Sales Partners.\",\n \"label\": \"Sales Partner\",\n \"name\": \"Sales Partner\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Manage Sales Person Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Sales Person\",\n \"link\": \"Tree/Sales Person\",\n \"name\": \"Sales Person\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-table", - "links": "[\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Analytics\",\n \"name\": \"Sales Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Sales Funnel\",\n \"name\": \"sales-funnel\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"icon\": \"fa fa-bar-chart\",\n \"is_query_report\": true,\n \"label\": \"Customer Acquisition and Loyalty\",\n \"name\": \"Customer Acquisition and Loyalty\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Inactive Customers\",\n \"name\": \"Inactive Customers\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Delivered\",\n \"name\": \"Ordered Items To Be Delivered\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Person-wise Transaction Summary\",\n \"name\": \"Sales Person-wise Transaction Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales History\",\n \"name\": \"Item-wise Sales History\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Quotation\"\n ],\n \"doctype\": \"Quotation\",\n \"is_query_report\": true,\n \"label\": \"Quotation Trends\",\n \"name\": \"Quotation Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Trends\",\n \"name\": \"Sales Order Trends\",\n \"type\": \"report\"\n }\n]", - "title": "Key Reports" + "hidden": 0, + "label": "Key Reports", + "links": "[\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Analytics\",\n \"name\": \"Sales Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Sales Funnel\",\n \"name\": \"sales-funnel\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"icon\": \"fa fa-bar-chart\",\n \"is_query_report\": true,\n \"label\": \"Customer Acquisition and Loyalty\",\n \"name\": \"Customer Acquisition and Loyalty\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Inactive Customers\",\n \"name\": \"Inactive Customers\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Delivered\",\n \"name\": \"Ordered Items To Be Delivered\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Person-wise Transaction Summary\",\n \"name\": \"Sales Person-wise Transaction Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales History\",\n \"name\": \"Item-wise Sales History\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Quotation\"\n ],\n \"doctype\": \"Quotation\",\n \"is_query_report\": true,\n \"label\": \"Quotation Trends\",\n \"name\": \"Quotation Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Trends\",\n \"name\": \"Sales Order Trends\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", "charts": [ { "chart_name": "Income", - "label": "Income", - "size": "Full" + "label": "Income" } ], "creation": "2020-01-28 11:49:12.092882", @@ -43,7 +43,7 @@ "idx": 0, "is_standard": 1, "label": "Selling", - "modified": "2020-03-12 16:30:38.207013", + "modified": "2020-04-01 11:28:51.047373", "modified_by": "Administrator", "module": "Selling", "name": "Selling", @@ -52,32 +52,32 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Sales Invoice", "link_to": "Sales Invoice", "type": "DocType" }, { - "is_query_report": 0, + "label": "Sales Order", "link_to": "Sales Order", "type": "DocType" }, { - "is_query_report": 0, + "label": "Quotation", "link_to": "Quotation", "type": "DocType" }, { - "is_query_report": 0, + "label": "Delivery Note", "link_to": "Delivery Note", "type": "DocType" }, { - "is_query_report": 0, + "label": "Accounts Receivable", "link_to": "Accounts Receivable", "type": "Report" }, { - "is_query_report": 0, + "label": "Sales Register", "link_to": "Sales Register", "type": "Report" } diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index df563ee8ff..557c7151d9 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -25,6 +25,8 @@ "territory", "tax_id", "tax_category", + "so_required", + "dn_required", "disabled", "is_internal_customer", "represents_company", @@ -465,13 +467,25 @@ "fieldtype": "Table", "label": "Credit Limit", "options": "Customer Credit Limit" + }, + { + "default": "0", + "fieldname": "so_required", + "fieldtype": "Check", + "label": "Allow Sales Invoice Creation Without Sales Order" + }, + { + "default": "0", + "fieldname": "dn_required", + "fieldtype": "Check", + "label": "Allow Sales Invoice Creation Without Delivery Note" } ], "icon": "fa fa-user", "idx": 363, "image_field": "image", "links": [], - "modified": "2020-01-29 20:36:37.879581", + "modified": "2020-03-17 11:03:42.706907", "modified_by": "Administrator", "module": "Selling", "name": "Customer", diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 6571ecb404..02667e8c23 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -268,9 +268,11 @@ def make_quotation(source_name, target_doc=None): target_doc.run_method("set_other_charges") target_doc.run_method("calculate_taxes_and_totals") - price_list = frappe.get_value("Customer", source_name, 'default_price_list') + price_list, currency = frappe.db.get_value("Customer", {'name': source_name}, ['default_price_list', 'default_currency']) if price_list: target_doc.selling_price_list = price_list + if currency: + target_doc.currency = currency return target_doc diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index b79c91cef1..7c47b8ac51 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -155,6 +155,11 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): def update_item(obj, target, source_parent): target.stock_qty = flt(obj.qty) * flt(obj.conversion_factor) + if obj.against_blanket_order: + target.against_blanket_order = obj.against_blanket_order + target.blanket_order = obj.blanket_order + target.blanket_order_rate = obj.blanket_order_rate + doclist = get_mapped_doc("Quotation", source_name, { "Quotation": { "doctype": "Sales Order", diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index 3ff5555e82..d50397cfad 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -55,6 +55,9 @@ "weight_uom", "reference", "warehouse", + "against_blanket_order", + "blanket_order", + "blanket_order_rate", "column_break_30", "prevdoc_doctype", "prevdoc_docname", @@ -573,12 +576,38 @@ "fieldname": "image_section", "fieldtype": "Section Break", "label": "Image" + }, + { + "depends_on": "eval:doc.against_blanket_order", + "fieldname": "blanket_order", + "fieldtype": "Link", + "label": "Blanket Order", + "no_copy": 1, + "options": "Blanket Order", + "print_hide": 1 + }, + { + "depends_on": "eval:doc.against_blanket_order", + "fieldname": "blanket_order_rate", + "fieldtype": "Currency", + "label": "Blanket Order Rate", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 + }, + { + "default": "0", + "fieldname": "against_blanket_order", + "fieldtype": "Check", + "label": "Against Blanket Order", + "no_copy": 1, + "print_hide": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2020-03-05 14:18:58.783751", + "modified": "2020-03-30 18:40:28.782720", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item", diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index fa765dfaad..61aa608dd3 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -664,7 +664,8 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( reference_doctype: me.frm.doctype, reference_name: me.frm.docname, content: __('Reason for hold: ')+data.reason_for_hold, - comment_email: frappe.session.user + comment_email: frappe.session.user, + comment_by: frappe.session.user_fullname }, callback: function(r) { if(!r.exc) { diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 13d2b1519f..05e4aa892b 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -496,7 +496,7 @@ def close_or_unclose_sales_orders(names, status): def get_requested_item_qty(sales_order): return frappe._dict(frappe.db.sql(""" - select sales_order_item, sum(stock_qty) + select sales_order_item, sum(qty) from `tabMaterial Request Item` where docstatus = 1 and sales_order = %s @@ -507,16 +507,12 @@ def get_requested_item_qty(sales_order): def make_material_request(source_name, target_doc=None): requested_item_qty = get_requested_item_qty(source_name) - def postprocess(source, doc): - doc.material_request_type = "Purchase" - def update_item(source, target, source_parent): # qty is for packed items, because packed items don't have stock_qty field - qty = source.get("stock_qty") or source.get("qty") + qty = source.get("qty") target.project = source_parent.project target.qty = qty - requested_item_qty.get(source.name, 0) - target.conversion_factor = 1 - target.stock_qty = qty - requested_item_qty.get(source.name, 0) + target.stock_qty = flt(target.qty) * flt(target.conversion_factor) doc = get_mapped_doc("Sales Order", source_name, { "Sales Order": { @@ -537,14 +533,12 @@ def make_material_request(source_name, target_doc=None): "doctype": "Material Request Item", "field_map": { "name": "sales_order_item", - "parent": "sales_order", - "stock_uom": "uom", - "stock_qty": "qty" + "parent": "sales_order" }, "condition": lambda doc: not frappe.db.exists('Product Bundle', doc.item_code) and doc.stock_qty > requested_item_qty.get(doc.name, 0), "postprocess": update_item } - }, target_doc, postprocess) + }, target_doc) return doc @@ -1042,7 +1036,7 @@ def create_pick_list(source_name, target_doc=None): }, }, target_doc) - doc.purpose = 'Delivery against Sales Order' + doc.purpose = 'Delivery' doc.set_item_locations() diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 3425f8f2a5..17136e0472 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -64,30 +64,40 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p for d in item_prices_data: item_prices[d.item_code] = d - + # prepare filter for bin query + bin_filters = {'item_code': ['in', items]} + if warehouse: + bin_filters['warehouse'] = warehouse if display_items_in_stock: - filters = {'actual_qty': [">", 0], 'item_code': ['in', items]} + bin_filters['actual_qty'] = [">", 0] - if warehouse: - filters['warehouse'] = warehouse + # query item bin + bin_data = frappe.get_all( + 'Bin', fields=['item_code', 'sum(actual_qty) as actual_qty'], + filters=bin_filters, group_by='item_code' + ) - bin_data = frappe._dict( - frappe.get_all("Bin", fields = ["item_code", "sum(actual_qty) as actual_qty"], - filters = filters, group_by = "item_code") - ) + # convert list of dict into dict as {item_code: actual_qty} + bin_dict = {} + for b in bin_data: + bin_dict[b.get('item_code')] = b.get('actual_qty') for item in items_data: - row = {} + item_code = item.item_code + item_price = item_prices.get(item_code) or {} + item_stock_qty = bin_dict.get(item_code) - row.update(item) - item_price = item_prices.get(item.item_code) or {} - row.update({ - 'price_list_rate': item_price.get('price_list_rate'), - 'currency': item_price.get('currency'), - 'actual_qty': bin_data.get('actual_qty') - }) - - result.append(row) + if display_items_in_stock and not item_stock_qty: + pass + else: + row = {} + row.update(item) + row.update({ + 'price_list_rate': item_price.get('price_list_rate'), + 'currency': item_price.get('currency'), + 'actual_qty': item_stock_qty, + }) + result.append(row) res = { 'items': result diff --git a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py index 4509904249..28dd056407 100644 --- a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py +++ b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import getdate, cint +from frappe.utils import getdate, cint, cstr import calendar def execute(filters=None): @@ -48,7 +48,7 @@ def execute(filters=None): new = new_customers_in.get(key, [0,0.0]) repeat = repeat_customers_in.get(key, [0,0.0]) - out.append([year, calendar.month_name[month], + out.append([cstr(year), calendar.month_name[month], new[0], repeat[0], new[0] + repeat[0], new[1], repeat[1], new[1] + repeat[1]]) diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py index 1fc3663bed..405004ece5 100644 --- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py +++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py @@ -121,8 +121,8 @@ def get_columns(filters): }, { "label": _("Billed Amount"), - "fieldname": "rate", - "options": "billed_amount", + "fieldtype": "currency", + "fieldname": "billed_amount", "width": 120 }, { diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 8278745a80..af100692c6 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -413,15 +413,20 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ */ set_batch_number: function(cdt, cdn) { const doc = frappe.get_doc(cdt, cdn); - if (doc && doc.has_batch_no) { + if (doc && doc.has_batch_no && doc.warehouse) { this._set_batch_number(doc); } }, _set_batch_number: function(doc) { + let args = {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)}; + if (doc.has_serial_no && doc.serial_no) { + args['serial_no'] = doc.serial_no + } + return frappe.call({ method: 'erpnext.stock.doctype.batch.batch.get_batch_no', - args: {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)}, + args: args, callback: function(r) { if(r.message) { frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message); diff --git a/erpnext/setup/desk_page/erpnext_settings/erpnext_settings.json b/erpnext/setup/desk_page/erpnext_settings/erpnext_settings.json index ac0a4b21fb..253d711b32 100644 --- a/erpnext/setup/desk_page/erpnext_settings/erpnext_settings.json +++ b/erpnext/setup/desk_page/erpnext_settings/erpnext_settings.json @@ -12,7 +12,7 @@ "idx": 0, "is_standard": 1, "label": "ERPNext Settings", - "modified": "2020-03-12 18:03:17.126782", + "modified": "2020-04-01 11:28:51.400851", "modified_by": "Administrator", "module": "Setup", "name": "ERPNext Settings", @@ -22,89 +22,89 @@ "shortcuts": [ { "icon": "octicon octicon-rocket", - "is_query_report": 0, + "label": "Projects Settings", "link_to": "Projects Settings", "type": "DocType" }, { "icon": "octicon octicon-repo", - "is_query_report": 0, + "label": "Accounts Settings", "link_to": "Accounts Settings", "type": "DocType" }, { "icon": "octicon octicon-package", - "is_query_report": 0, + "label": "Stock Settings", "link_to": "Stock Settings", "type": "DocType" }, { "icon": "octicon octicon-organization", - "is_query_report": 0, + "label": "HR Settings", "link_to": "HR Settings", "type": "DocType" }, { "icon": "octicon octicon-tag", - "is_query_report": 0, + "label": "Selling Settings", "link_to": "Selling Settings", "type": "DocType" }, { "icon": "octicon octicon-briefcase", - "is_query_report": 0, + "label": "Buying Settings", "link_to": "Buying Settings", "type": "DocType" }, { "icon": "fa fa-life-ring", - "is_query_report": 0, + "label": "Support Settings", "link_to": "Support Settings", "type": "DocType" }, { "icon": "fa fa-shopping-cart", - "is_query_report": 0, + "label": "Shopping Cart Settings", "link_to": "Shopping Cart Settings", "type": "DocType" }, { "icon": "fa fa-globe", - "is_query_report": 0, + "label": "Portal Settings", "link_to": "Portal Settings", "type": "DocType" }, { "icon": "octicon octicon-tools", - "is_query_report": 0, + "label": "Manufacturing Settings", "link_to": "Manufacturing Settings", "restrict_to_domain": "Manufacturing", "type": "DocType" }, { "icon": "octicon octicon-mortar-board", - "is_query_report": 0, + "label": "Education Settings", "link_to": "Education Settings", "restrict_to_domain": "Education", "type": "DocType" }, { "icon": "fa fa-bed", - "is_query_report": 0, + "label": "Hotel Settings", "link_to": "Hotel Settings", "restrict_to_domain": "Hospitality", "type": "DocType" }, { "icon": "fa fa-heartbeat", - "is_query_report": 0, + "label": "Healthcare Settings", "link_to": "Healthcare Settings", "restrict_to_domain": "Healthcare", "type": "DocType" }, { "icon": "fa fa-cog", - "is_query_report": 0, + "label": "Domain Settings", "link_to": "Domain Settings", "type": "DocType" } diff --git a/erpnext/setup/desk_page/getting_started/getting_started.json b/erpnext/setup/desk_page/getting_started/getting_started.json index 00236ba5fe..63d8984c40 100644 --- a/erpnext/setup/desk_page/getting_started/getting_started.json +++ b/erpnext/setup/desk_page/getting_started/getting_started.json @@ -1,48 +1,56 @@ { "cards": [ { - "links": "[\n {\n \"label\": \"Patient\",\n \"name\": \"Patient\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Diagnosis\",\n \"name\": \"Diagnosis\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Healthcare" + "hidden": 0, + "label": "Healthcare", + "links": "[\n {\n \"label\": \"Patient\",\n \"name\": \"Patient\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Diagnosis\",\n \"name\": \"Diagnosis\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Crop\",\n \"name\": \"Crop\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Crop Cycle\",\n \"name\": \"Crop Cycle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Location\",\n \"name\": \"Location\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fertilizer\",\n \"name\": \"Fertilizer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Agriculture" + "hidden": 0, + "label": "Agriculture", + "links": "[\n {\n \"label\": \"Crop\",\n \"name\": \"Crop\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Crop Cycle\",\n \"name\": \"Crop Cycle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Location\",\n \"name\": \"Location\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fertilizer\",\n \"name\": \"Fertilizer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Stock Reconciliation\",\n \"name\": \"Stock Reconciliation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Stock" + "hidden": 0, + "label": "Education", + "links": "[\n {\n \"label\": \"Student\",\n \"name\": \"Student\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course\",\n \"name\": \"Course\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Instructor\",\n \"name\": \"Instructor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Room\",\n \"name\": \"Room\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Employee\",\n \"name\": \"Employee\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Employee Attendance Tool\",\n \"name\": \"Employee Attendance Tool\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Structure\",\n \"name\": \"Salary Structure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Human Resources" + "hidden": 0, + "label": "Non Profit", + "links": "[\n {\n \"description\": \"Member information.\",\n \"label\": \"Member\",\n \"name\": \"Member\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Volunteer information.\",\n \"label\": \"Volunteer\",\n \"name\": \"Volunteer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Chapter information.\",\n \"label\": \"Chapter\",\n \"name\": \"Chapter\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Donor information.\",\n \"label\": \"Donor\",\n \"name\": \"Donor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Database of potential customers.\",\n \"label\": \"Lead\",\n \"name\": \"Lead\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Customer Group Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Customer Group\",\n \"link\": \"Tree/Customer Group\",\n \"name\": \"Customer Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Territory Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Territory\",\n \"link\": \"Tree/Territory\",\n \"name\": \"Territory\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "CRM" + "hidden": 0, + "label": "Stock", + "links": "[\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Stock Reconciliation\",\n \"name\": \"Stock Reconciliation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Company (not Customer or Supplier) master.\",\n \"label\": \"Company\",\n \"name\": \"Company\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of financial accounts.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Accounts\",\n \"name\": \"Account\",\n \"onboard\": 1,\n \"route\": \"#Tree/Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Create Opening Sales and Purchase Invoices\",\n \"label\": \"Opening Invoice Creation Tool\",\n \"name\": \"Opening Invoice Creation Tool\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Accounting" + "hidden": 0, + "label": "Human Resources", + "links": "[\n {\n \"label\": \"Employee\",\n \"name\": \"Employee\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Employee\"\n ],\n \"hide_count\": true,\n \"label\": \"Employee Attendance Tool\",\n \"name\": \"Employee Attendance Tool\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Salary Structure\",\n \"name\": \"Salary Structure\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Student\",\n \"name\": \"Student\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course\",\n \"name\": \"Course\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Instructor\",\n \"name\": \"Instructor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Room\",\n \"name\": \"Room\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Education" + "hidden": 0, + "label": "CRM", + "links": "[\n {\n \"description\": \"Database of potential customers.\",\n \"label\": \"Lead\",\n \"name\": \"Lead\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Customer Group Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Customer Group\",\n \"link\": \"Tree/Customer Group\",\n \"name\": \"Customer Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Manage Territory Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Territory\",\n \"link\": \"Tree/Territory\",\n \"name\": \"Territory\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Import Data from CSV / Excel files.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Import Data\",\n \"name\": \"Data Import\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Import Chart Of Accounts from CSV / Excel files\",\n \"labe\": \"Chart Of Accounts Importer\",\n \"label\": \"Chart of Accounts Importer\",\n \"name\": \"Chart of Accounts Importer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Letter Heads for print templates.\",\n \"label\": \"Letter Head\",\n \"name\": \"Letter Head\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add / Manage Email Accounts.\",\n \"label\": \"Email Account\",\n \"name\": \"Email Account\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Data Import and Settings" + "hidden": 0, + "label": "Accounting", + "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Company (not Customer or Supplier) master.\",\n \"label\": \"Company\",\n \"name\": \"Company\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of financial accounts.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Accounts\",\n \"name\": \"Account\",\n \"onboard\": 1,\n \"route\": \"#Tree/Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Create Opening Sales and Purchase Invoices\",\n \"label\": \"Opening Invoice Creation Tool\",\n \"name\": \"Opening Invoice Creation Tool\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Member information.\",\n \"label\": \"Member\",\n \"name\": \"Member\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Volunteer information.\",\n \"label\": \"Volunteer\",\n \"name\": \"Volunteer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Chapter information.\",\n \"label\": \"Chapter\",\n \"name\": \"Chapter\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Donor information.\",\n \"label\": \"Donor\",\n \"name\": \"Donor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Non Profit" + "hidden": 0, + "label": "Data Import and Settings", + "links": "[\n {\n \"description\": \"Import Data from CSV / Excel files.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Import Data\",\n \"name\": \"Data Import\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Import Chart Of Accounts from CSV / Excel files\",\n \"labe\": \"Chart Of Accounts Importer\",\n \"label\": \"Chart of Accounts Importer\",\n \"name\": \"Chart of Accounts Importer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Letter Heads for print templates.\",\n \"label\": \"Letter Head\",\n \"name\": \"Letter Head\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add / Manage Email Accounts.\",\n \"label\": \"Email Account\",\n \"name\": \"Email Account\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" } ], "category": "Modules", "charts": [ { "chart_name": "Bank Balance", - "label": "All Your Money", - "size": "Full" + "label": "Bank Balance" } ], "creation": "2020-01-23 13:46:38.833076", @@ -55,7 +63,7 @@ "idx": 0, "is_standard": 1, "label": "Getting Started", - "modified": "2020-03-12 16:30:37.821762", + "modified": "2020-04-01 11:30:19.763099", "modified_by": "Administrator", "module": "Setup", "name": "Getting Started", @@ -64,24 +72,34 @@ "pin_to_top": 1, "shortcuts": [ { - "is_query_report": 0, + "label": "Item", "link_to": "Item", "type": "DocType" }, { - "is_query_report": 0, + "label": "Customer", "link_to": "Customer", "type": "DocType" }, { - "is_query_report": 0, + "label": "Supplier", "link_to": "Supplier", "type": "DocType" }, { - "is_query_report": 0, + "label": "Sales Invoice", "link_to": "Sales Invoice", "type": "DocType" + }, + { + "label": "Dashboard", + "link_to": "dashboard", + "type": "Page" + }, + { + "label": "Leaderboard", + "link_to": "leaderboard", + "type": "Page" } ] } \ No newline at end of file diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 84810b6824..020a93ff6a 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -157,6 +157,7 @@ { "fieldname": "parent_company", "fieldtype": "Link", + "ignore_user_permissions": 1, "in_list_view": 1, "label": "Parent Company", "options": "Company" @@ -277,6 +278,7 @@ "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"", "fieldname": "existing_company", "fieldtype": "Link", + "ignore_user_permissions": 1, "label": "Existing Company ", "no_copy": 1, "options": "Company" @@ -728,7 +730,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2020-03-18 18:09:53.534211", + "modified": "2020-03-21 18:09:53.534211", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 956deef928..8bcaa28707 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -16,6 +16,7 @@ from frappe.utils.nestedset import NestedSet from past.builtins import cmp import functools +from erpnext.accounts.doctype.account.account import get_account_currency class Company(NestedSet): nsm_parent_field = 'parent_company' @@ -73,18 +74,22 @@ class Company(NestedSet): def validate_default_accounts(self): accounts = [ - "default_bank_account", "default_cash_account", - "default_receivable_account", "default_payable_account", - "default_expense_account", "default_income_account", - "stock_received_but_not_billed", "stock_adjustment_account", - "expenses_included_in_valuation", "default_payroll_payable_account" + ["Default Bank Account", "default_bank_account"], ["Default Cash Account", "default_cash_account"], + ["Default Receivable Account", "default_receivable_account"], ["Default Payable Account", "default_payable_account"], + ["Default Expense Account", "default_expense_account"], ["Default Income Account", "default_income_account"], + ["Stock Received But Not Billed Account", "stock_received_but_not_billed"], ["Stock Adjustment Account", "stock_adjustment_account"], + ["Expense Included In Valuation Account", "expenses_included_in_valuation"], ["Default Payroll Payable Account", "default_payroll_payable_account"] ] - for field in accounts: - if self.get(field): - for_company = frappe.db.get_value("Account", self.get(field), "company") + for account in accounts: + if self.get(account[1]): + for_company = frappe.db.get_value("Account", self.get(account[1]), "company") if for_company != self.name: - frappe.throw(_("Account {0} does not belong to company: {1}").format(self.get(field), self.name)) + frappe.throw(_("Account {0} does not belong to company: {1}").format(self.get(account[1]), self.name)) + + if get_account_currency(self.get(account[1])) != self.default_currency: + frappe.throw(_("""{0} currency must be same as company's default currency. + Please select another account""").format(frappe.bold(account[0]))) def validate_currency(self): if self.is_new(): diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index ebd7b50939..e4986e36b7 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -8,9 +8,11 @@ import frappe, os, json from frappe import _ from frappe.desk.page.setup_wizard.setup_wizard import make_records from frappe.utils import cstr, getdate -from erpnext.accounts.doctype.account.account import RootNotEditable from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes +from erpnext.accounts.doctype.account.account import RootNotEditable +from erpnext.regional.address_template.setup import set_up_address_templates + default_lead_sources = ["Existing Customer", "Reference", "Advertisement", "Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing", "Customer's Vendor", "Campaign", "Walk In"] @@ -30,7 +32,7 @@ def install(country=None): { 'doctype': 'Domain', 'domain': 'Agriculture'}, { 'doctype': 'Domain', 'domain': 'Non Profit'}, - # address template + # ensure at least an empty Address Template exists for this Country {'doctype':"Address Template", "country": country}, # item group @@ -269,12 +271,11 @@ def install(country=None): # Records for the Supplier Scorecard from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records + make_default_records() - make_records(records) - + set_up_address_templates(default_country=country) set_more_defaults() - update_global_search_doctypes() # path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country)) diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index 1dac9bd162..e11e1bb5dc 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -38,14 +38,14 @@ def get_cart_quotation(doc=None): addresses = get_address_docs(party=party) if not doc.customer_address and addresses: - update_cart_address("customer_address", addresses[0].name) + update_cart_address("billing", addresses[0].name) return { "doc": decorate_quotation_doc(doc), "shipping_addresses": [{"name": address.name, "display": address.display} - for address in addresses], + for address in addresses if address.address_type == "Shipping"], "billing_addresses": [{"name": address.name, "display": address.display} - for address in addresses], + for address in addresses if address.address_type == "Billing"], "shipping_rules": get_applicable_shipping_rules(party), "cart_settings": frappe.get_cached_doc("Shopping Cart Settings") } @@ -64,6 +64,9 @@ def place_order(): # company used to create customer accounts frappe.defaults.set_user_default("company", quotation.company) + if not (quotation.shipping_address_name or quotation.customer_address): + frappe.throw(_("Set Shipping Address or Billing Address")) + from erpnext.selling.doctype.quotation.quotation import _make_sales_order sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True)) sales_order.payment_schedule = [] @@ -194,21 +197,18 @@ def get_terms_and_conditions(terms_name): return frappe.db.get_value('Terms and Conditions', terms_name, 'terms') @frappe.whitelist() -def update_cart_address(address_fieldname, address_name): +def update_cart_address(address_type, address_name): quotation = _get_cart_quotation() address_display = get_address_display(frappe.get_doc("Address", address_name).as_dict()) - if address_fieldname == "shipping_address_name": - quotation.shipping_address_name = address_name - quotation.shipping_address = address_display - - if not quotation.customer_address: - address_fieldname == "customer_address" - - if address_fieldname == "customer_address": + if address_type.lower() == "billing": quotation.customer_address = address_name quotation.address_display = address_display - + quotation.shipping_address_name == quotation.shipping_address_name or address_name + elif address_type.lower() == "shipping": + quotation.shipping_address_name = address_name + quotation.shipping_address = address_display + quotation.customer_address == quotation.customer_address or address_name apply_cart_settings(quotation=quotation) diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py index a4d4cbd8ef..8d64efe41d 100644 --- a/erpnext/stock/__init__.py +++ b/erpnext/stock/__init__.py @@ -13,12 +13,16 @@ install_docs = [ ] def get_warehouse_account_map(company=None): - if not frappe.flags.warehouse_account_map or frappe.flags.in_test: + company_warehouse_account_map = company and frappe.flags.setdefault('warehouse_account_map', {}).get(company) + warehouse_account_map = frappe.flags.warehouse_account_map + + if not warehouse_account_map or not company_warehouse_account_map or frappe.flags.in_test: warehouse_account = frappe._dict() filters = {} if company: filters['company'] = company + frappe.flags.setdefault('warehouse_account_map', {}).setdefault(company, {}) for d in frappe.get_all('Warehouse', fields = ["name", "account", "parent_warehouse", "company", "is_group"], @@ -30,10 +34,12 @@ def get_warehouse_account_map(company=None): if d.account: d.account_currency = frappe.db.get_value('Account', d.account, 'account_currency', cache=True) warehouse_account.setdefault(d.name, d) - - frappe.flags.warehouse_account_map = warehouse_account - - return frappe.flags.warehouse_account_map + if company: + frappe.flags.warehouse_account_map[company] = warehouse_account + else: + frappe.flags.warehouse_account_map = warehouse_account + + return frappe.flags.warehouse_account_map.get(company) or frappe.flags.warehouse_account_map def get_warehouse_account(warehouse, warehouse_account=None): account = warehouse.account diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index 1bfa2cf56c..9bd03d45cb 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -108,8 +108,8 @@ erpnext.stock.ItemDashboard = Class.extend({ if (context.data.length > 0) { $(frappe.render_template('item_dashboard_list', context)).appendTo(this.result); } else { - var message = __(" Currently no stock available in any warehouse") - $(""+message+"").appendTo(this.result); + var message = __("Currently no stock available in any warehouse"); + $(` ${message} `).appendTo(this.result); } }, get_item_dashboard_data: function(data, max_count, show_item) { diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json index 779e61f81a..38475a6f26 100644 --- a/erpnext/stock/desk_page/stock/stock.json +++ b/erpnext/stock/desk_page/stock/stock.json @@ -1,40 +1,44 @@ { "cards": [ { - "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Entry\",\n \"name\": \"Stock Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"label\": \"Delivery Note\",\n \"name\": \"Delivery Note\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"label\": \"Purchase Receipt\",\n \"name\": \"Purchase Receipt\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Material Request\",\n \"name\": \"Material Request\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Pick List\",\n \"name\": \"Pick List\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Delivery Trip\",\n \"name\": \"Delivery Trip\",\n \"type\": \"doctype\"\n }\n]", - "title": "Stock Transactions" + "hidden": 0, + "label": "Stock Transactions", + "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Entry\",\n \"name\": \"Stock Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"label\": \"Delivery Note\",\n \"name\": \"Delivery Note\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"label\": \"Purchase Receipt\",\n \"name\": \"Purchase Receipt\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Material Request\",\n \"name\": \"Material Request\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Pick List\",\n \"name\": \"Pick List\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Delivery Trip\",\n \"name\": \"Delivery Trip\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Ledger\",\n \"name\": \"Stock Ledger\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Balance\",\n \"name\": \"Stock Balance\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Stock Projected Qty\",\n \"name\": \"Stock Projected Qty\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Summary\",\n \"name\": \"stock-balance\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Stock Ageing\",\n \"name\": \"Stock Ageing\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item Price Stock\",\n \"name\": \"Item Price Stock\",\n \"type\": \"report\"\n }\n]", - "title": "Stock Reports" + "hidden": 0, + "label": "Stock Reports", + "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Ledger\",\n \"name\": \"Stock Ledger\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Balance\",\n \"name\": \"Stock Balance\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Stock Projected Qty\",\n \"name\": \"Stock Projected Qty\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Summary\",\n \"name\": \"stock-balance\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Stock Ageing\",\n \"name\": \"Stock Ageing\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item Price Stock\",\n \"name\": \"Item Price Stock\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-cog", - "links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Items and Pricing" + "hidden": 0, + "label": "Items and Pricing", + "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Serial No\",\n \"name\": \"Serial No\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Batch\",\n \"name\": \"Batch\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Installation Note\",\n \"name\": \"Installation Note\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Serial No\"\n ],\n \"doctype\": \"Serial No\",\n \"label\": \"Serial No Service Contract Expiry\",\n \"name\": \"Serial No Service Contract Expiry\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Serial No\"\n ],\n \"doctype\": \"Serial No\",\n \"label\": \"Serial No Status\",\n \"name\": \"Serial No Status\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Serial No\"\n ],\n \"doctype\": \"Serial No\",\n \"label\": \"Serial No Warranty Expiry\",\n \"name\": \"Serial No Warranty Expiry\",\n \"type\": \"report\"\n }\n]", - "title": "Serial No and Batch" + "hidden": 0, + "label": "Serial No and Batch", + "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Serial No\",\n \"name\": \"Serial No\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Batch\",\n \"name\": \"Batch\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Installation Note\",\n \"name\": \"Installation Note\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Serial No\"\n ],\n \"doctype\": \"Serial No\",\n \"label\": \"Serial No Service Contract Expiry\",\n \"name\": \"Serial No Service Contract Expiry\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Serial No\"\n ],\n \"doctype\": \"Serial No\",\n \"label\": \"Serial No Status\",\n \"name\": \"Serial No Status\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Serial No\"\n ],\n \"doctype\": \"Serial No\",\n \"label\": \"Serial No Warranty Expiry\",\n \"name\": \"Serial No Warranty Expiry\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-wrench", - "links": "[\n {\n \"label\": \"Stock Reconciliation\",\n \"name\": \"Stock Reconciliation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Landed Cost Voucher\",\n \"name\": \"Landed Cost Voucher\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Packing Slip\",\n \"name\": \"Packing Slip\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quality Inspection\",\n \"name\": \"Quality Inspection\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quality Inspection Template\",\n \"name\": \"Quality Inspection Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quick Stock Balance\",\n \"name\": \"Quick Stock Balance\",\n \"type\": \"doctype\"\n }\n]", - "title": "Tools" + "hidden": 0, + "label": "Tools", + "links": "[\n {\n \"label\": \"Stock Reconciliation\",\n \"name\": \"Stock Reconciliation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Landed Cost Voucher\",\n \"name\": \"Landed Cost Voucher\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Packing Slip\",\n \"name\": \"Packing Slip\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quality Inspection\",\n \"name\": \"Quality Inspection\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quality Inspection Template\",\n \"name\": \"Quality Inspection Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quick Stock Balance\",\n \"name\": \"Quick Stock Balance\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-table", - "links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Delivered\",\n \"name\": \"Ordered Items To Be Delivered\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Items To Be Received\",\n \"name\": \"Purchase Order Items To Be Received\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]", - "title": "Key Reports" + "hidden": 0, + "label": "Key Reports", + "links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Delivered\",\n \"name\": \"Ordered Items To Be Delivered\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Items To Be Received\",\n \"name\": \"Purchase Order Items To Be Received\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"dependencies\": [\n \"Material Request\"\n ],\n \"doctype\": \"Material Request\",\n \"is_query_report\": true,\n \"label\": \"Requested Items To Be Transferred\",\n \"name\": \"Requested Items To Be Transferred\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Ledger Entry\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Batch Item Expiry Status\",\n \"name\": \"Batch Item Expiry Status\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Price List\"\n ],\n \"doctype\": \"Price List\",\n \"is_query_report\": true,\n \"label\": \"Item Prices\",\n \"name\": \"Item Prices\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Itemwise Recommended Reorder Level\",\n \"name\": \"Itemwise Recommended Reorder Level\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item Variant Details\",\n \"name\": \"Item Variant Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Subcontracted Item To Be Received\",\n \"name\": \"Subcontracted Item To Be Received\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Ledger Entry\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock and Account Value Comparison\",\n \"name\": \"Stock and Account Value Comparison\",\n \"type\": \"report\"\n }\n]", - "title": "Other Reports" + "hidden": 0, + "label": "Other Reports", + "links": "[\n {\n \"dependencies\": [\n \"Material Request\"\n ],\n \"doctype\": \"Material Request\",\n \"is_query_report\": true,\n \"label\": \"Requested Items To Be Transferred\",\n \"name\": \"Requested Items To Be Transferred\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Ledger Entry\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Batch Item Expiry Status\",\n \"name\": \"Batch Item Expiry Status\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Price List\"\n ],\n \"doctype\": \"Price List\",\n \"is_query_report\": true,\n \"label\": \"Item Prices\",\n \"name\": \"Item Prices\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Itemwise Recommended Reorder Level\",\n \"name\": \"Itemwise Recommended Reorder Level\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item Variant Details\",\n \"name\": \"Item Variant Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Subcontracted Item To Be Received\",\n \"name\": \"Subcontracted Item To Be Received\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Ledger Entry\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock and Account Value Comparison\",\n \"name\": \"Stock and Account Value Comparison\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", @@ -49,7 +53,7 @@ "idx": 0, "is_standard": 1, "label": "Stock", - "modified": "2020-03-12 16:30:39.881667", + "modified": "2020-04-01 11:28:51.148421", "modified_by": "Administrator", "module": "Stock", "name": "Stock", @@ -58,27 +62,27 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Item", "link_to": "Item", "type": "DocType" }, { - "is_query_report": 0, + "label": "Pricing Rule", "link_to": "Pricing Rule", "type": "DocType" }, { - "is_query_report": 0, + "label": "Stock Entry", "link_to": "Stock Entry", "type": "DocType" }, { - "is_query_report": 0, + "label": "Stock Ledger", "link_to": "Stock Ledger", "type": "Report" }, { - "is_query_report": 0, + "label": "Stock Balance", "link_to": "Stock Balance", "type": "Report" } diff --git a/erpnext/stock/doctype/batch/batch.json b/erpnext/stock/doctype/batch/batch.json index e6d4e9d8b1..1eb457734e 100644 --- a/erpnext/stock/doctype/batch/batch.json +++ b/erpnext/stock/doctype/batch/batch.json @@ -1,554 +1,194 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, "allow_import": 1, - "allow_rename": 0, "autoname": "field:batch_id", - "beta": 0, "creation": "2013-03-05 14:50:38", - "custom": 0, - "docstatus": 0, "doctype": "DocType", "document_type": "Setup", - "editable_grid": 0, "engine": "InnoDB", + "field_order": [ + "sb_disabled", + "disabled", + "sb_batch", + "batch_id", + "item", + "item_name", + "image", + "parent_batch", + "manufacturing_date", + "column_break_3", + "batch_qty", + "stock_uom", + "expiry_date", + "source", + "supplier", + "column_break_9", + "reference_doctype", + "reference_name", + "section_break_7", + "description" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, + "default": "0", + "fieldname": "disabled", + "fieldtype": "Check", + "label": "Disabled" + }, + { "depends_on": "eval:doc.__islocal", "fieldname": "batch_id", "fieldtype": "Data", - "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": "Batch ID", - "length": 0, "no_copy": 1, "oldfieldname": "batch_id", "oldfieldtype": "Data", - "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": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "item", "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": 1, "label": "Item", - "length": 0, - "no_copy": 0, "oldfieldname": "item", "oldfieldtype": "Link", "options": "Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "image", "fieldtype": "Attach Image", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "image", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 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 + "label": "image" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.parent_batch", "fieldname": "parent_batch", "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": "Parent Batch", - "length": 0, - "no_copy": 0, "options": "Batch", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "disabled", - "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": "Disabled", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "Today", "fieldname": "manufacturing_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Manufacturing Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Manufacturing Date" + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "expiry_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Expiry Date", - "length": 0, - "no_copy": 0, "oldfieldname": "expiry_date", - "oldfieldtype": "Date", - "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 + "oldfieldtype": "Date" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "source", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Source", - "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 + "label": "Source" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "supplier", "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": "Supplier", - "length": 0, - "no_copy": 0, "options": "Supplier", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break_9", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "reference_doctype", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Source Document Type", - "length": 0, - "no_copy": 0, "options": "DocType", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "reference_name", "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Source Document Name", - "length": 0, - "no_copy": 0, "options": "reference_doctype", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "section_break_7", - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "description", "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Batch Description", - "length": 0, - "no_copy": 0, "oldfieldname": "description", "oldfieldtype": "Small Text", - "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, "width": "300px" + }, + { + "fieldname": "sb_disabled", + "fieldtype": "Section Break" + }, + { + "fieldname": "sb_batch", + "fieldtype": "Section Break", + "label": "Batch Details" + }, + { + "fetch_from": "item.item_name", + "fieldname": "item_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Item Name", + "read_only": 1 + }, + { + "fieldname": "batch_qty", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Batch Quantity", + "read_only": 1 + }, + { + "fetch_from": "item.stock_uom", + "fieldname": "stock_uom", + "fieldtype": "Link", + "label": "Batch UOM", + "options": "UOM", + "read_only": 1 } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, "icon": "fa fa-archive", "idx": 1, "image_field": "image", - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, "max_attachments": 5, - "modified": "2018-08-29 06:28:57.985997", + "modified": "2019-10-03 22:38:45.104056", "modified_by": "Administrator", "module": "Stock", "name": "Batch", "owner": "harshada@webnotestech.com", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, "import": 1, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Item Manager", "set_user_permissions": 1, "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", - "title_field": "item", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + "title_field": "batch_id" } \ No newline at end of file diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 8ae978eaf0..9b7249e66b 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -122,8 +122,11 @@ class Batch(Document): self.expiry_date = add_days(self.manufacturing_date, shelf_life_in_days) if has_expiry_date and not self.expiry_date: - frappe.msgprint(_('Expiry date is mandatory for selected item.')) - frappe.throw(_("Set item's shelf life in days, to set expiry based on manufacturing date plus shelf-life.")) + frappe.throw(msg=_("Please set {0} for Batched Item {1}, which is used to set {2} on Submit.") \ + .format(frappe.bold("Shelf Life in Days"), + frappe.utils.get_link_to_form("Item", self.item), + frappe.bold("Batch Expiry Date")), + title=_("Expiry Date Mandatory")) def get_name_from_naming_series(self): """ diff --git a/erpnext/stock/doctype/batch/batch_dashboard.py b/erpnext/stock/doctype/batch/batch_dashboard.py new file mode 100644 index 0000000000..eb6a97ecfd --- /dev/null +++ b/erpnext/stock/doctype/batch/batch_dashboard.py @@ -0,0 +1,27 @@ +from __future__ import unicode_literals + +from frappe import _ + + +def get_data(): + return { + 'fieldname': 'batch_no', + 'transactions': [ + { + 'label': _('Buy'), + 'items': ['Purchase Invoice', 'Purchase Receipt'] + }, + { + 'label': _('Sell'), + 'items': ['Sales Invoice', 'Delivery Note'] + }, + { + 'label': _('Move'), + 'items': ['Stock Entry'] + }, + { + 'label': _('Quality'), + 'items': ['Quality Inspection'] + } + ] + } diff --git a/erpnext/stock/doctype/batch/batch_list.js b/erpnext/stock/doctype/batch/batch_list.js index 7ee81aa7e9..d4f74c3a21 100644 --- a/erpnext/stock/doctype/batch/batch_list.js +++ b/erpnext/stock/doctype/batch/batch_list.js @@ -1,12 +1,14 @@ frappe.listview_settings['Batch'] = { - add_fields: ["item", "expiry_date"], - get_indicator: function(doc) { - if(doc.expiry_date && frappe.datetime.get_diff(doc.expiry_date, frappe.datetime.nowdate()) <= 0) { - return [__("Expired"), "red", "expiry_date,>=,Today"] - } else if(doc.expiry_date) { - return [__("Not Expired"), "green", "expiry_date,<,Today"] + add_fields: ["item", "expiry_date", "batch_qty", "disabled"], + get_indicator: (doc) => { + if (doc.disabled) { + return [__("Disabled"), "darkgrey", "disabled,=,1"]; + } else if (!doc.batch_qty) { + return [__("Empty"), "darkgrey", "batch_qty,=,0|disabled,=,0"]; + } else if (doc.expiry_date && frappe.datetime.get_diff(doc.expiry_date, frappe.datetime.nowdate()) <= 0) { + return [__("Expired"), "red", "expiry_date,not in,|expiry_date,<=,Today|batch_qty,>,0|disabled,=,0"] } else { - return ["Not Set", "darkgrey", ""]; - } + return [__("Active"), "green", "batch_qty,>,0|disabled,=,0"]; + }; } }; diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index 32445a618d..1fce5046f9 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -7,7 +7,7 @@ from frappe.exceptions import ValidationError import unittest from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError, get_batch_no -from frappe.utils import cint +from frappe.utils import cint, flt from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory class TestBatch(unittest.TestCase): @@ -35,12 +35,13 @@ class TestBatch(unittest.TestCase): receipt = frappe.get_doc(dict( doctype='Purchase Receipt', supplier='_Test Supplier', + company='_Test Company', items=[ dict( item_code='ITEM-BATCH-1', qty=batch_qty, rate=10, - warehouse= 'Stores - WP' + warehouse= 'Stores - _TC' ) ] )).insert() @@ -175,6 +176,18 @@ class TestBatch(unittest.TestCase): self.assertEqual(get_batch_qty('batch a', '_Test Warehouse - _TC'), 90) + def test_total_batch_qty(self): + self.make_batch_item('ITEM-BATCH-3') + existing_batch_qty = flt(frappe.db.get_value("Batch", "B100", "batch_qty")) + stock_entry = self.make_new_batch_and_entry('ITEM-BATCH-3', 'B100', '_Test Warehouse - _TC') + + current_batch_qty = flt(frappe.db.get_value("Batch", "B100", "batch_qty")) + self.assertEqual(current_batch_qty, existing_batch_qty + 90) + + stock_entry.cancel() + current_batch_qty = flt(frappe.db.get_value("Batch", "B100", "batch_qty")) + self.assertEqual(current_batch_qty, existing_batch_qty) + @classmethod def make_new_batch_and_entry(cls, item_name, batch_name, warehouse): '''Make a new stock entry for given target warehouse and batch name of item''' @@ -208,6 +221,8 @@ class TestBatch(unittest.TestCase): stock_entry.insert() stock_entry.submit() + return stock_entry + def test_batch_name_with_naming_series(self): stock_settings = frappe.get_single('Stock Settings') use_naming_series = cint(stock_settings.use_naming_series) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 30d82ca415..dc96e7bd49 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -112,7 +112,6 @@ class DeliveryNote(SellingController): self.so_required() self.validate_proj_cust() self.check_sales_order_on_hold_or_close("against_sales_order") - self.validate_for_items() self.validate_warehouse() self.validate_uom_is_integer("stock_uom", "stock_qty") self.validate_uom_is_integer("uom", "qty") @@ -166,12 +165,6 @@ class DeliveryNote(SellingController): if not res: frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project)) - def validate_for_items(self): - for d in self.get('items'): - #Customer Provided parts will have zero valuation rate - if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'): - d.allow_zero_valuation_rate = 1 - def validate_warehouse(self): super(DeliveryNote, self).validate_warehouse() diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index dc92c5c9ff..47a72b21a6 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -21,6 +21,7 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation \ from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order, create_dn_against_so from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse +from erpnext.stock.doctype.item.test_item import create_item class TestDeliveryNote(unittest.TestCase): def setUp(self): @@ -433,6 +434,15 @@ class TestDeliveryNote(unittest.TestCase): update_delivery_note_status(dn.name, "Closed") self.assertEqual(frappe.db.get_value("Delivery Note", dn.name, "Status"), "Closed") + def test_customer_provided_parts_dn(self): + create_item('CUST-0987', is_customer_provided_item = 1, customer = '_Test Customer', is_purchase_item = 0) + dn = create_delivery_note(item_code='CUST-0987', rate=0) + self.assertEqual(dn.get("items")[0].allow_zero_valuation_rate, 1) + + # test if Delivery Note with rate is allowed against Customer Provided Item + dn2 = create_delivery_note(item_code='CUST-0987', do_not_save=True) + self.assertRaises(frappe.ValidationError, dn2.save) + def test_dn_billing_status_case1(self): # SO -> DN -> SI so = make_sales_order() @@ -671,7 +681,7 @@ def create_delivery_note(**args): "item_code": args.item or args.item_code or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", "qty": args.qty or 1, - "rate": args.rate or 100, + "rate": args.rate if args.get("rate") is not None else 100, "conversion_factor": 1.0, "allow_zero_valuation_rate": args.allow_zero_valuation_rate or 1, "expense_account": args.expense_account or "Cost of Goods Sold - _TC", diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py index a34db45114..28e9533186 100644 --- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -238,7 +238,7 @@ class DeliveryTrip(Document): try: directions = maps_client.directions(**directions_data) except Exception as e: - frappe.throw(_(e)) + frappe.throw(_(str(e))) return directions[0] if directions else False diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 3503e7cc1c..aa6b2fedd7 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -343,7 +343,8 @@ { "fieldname": "shelf_life_in_days", "fieldtype": "Int", - "label": "Shelf Life In Days" + "label": "Shelf Life In Days", + "mandatory_depends_on": "eval:doc.has_batch_no && doc.has_expiry_date" }, { "default": "2099-12-31", @@ -1045,7 +1046,7 @@ "image_field": "image", "links": [], "max_attachments": 1, - "modified": "2020-01-02 19:13:59.295963", + "modified": "2020-03-24 16:14:36.950677", "modified_by": "Administrator", "module": "Stock", "name": "Item", diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index f805a674ca..c62b3ab583 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -101,6 +101,7 @@ class Item(WebsiteGenerator): self.add_default_uom_in_conversion_factor_table() self.validate_conversion_factor() self.validate_item_type() + self.validate_naming_series() self.check_for_active_boms() self.fill_customer_code() self.check_item_tax() @@ -186,7 +187,7 @@ class Item(WebsiteGenerator): or frappe.db.get_single_value('Stock Settings', 'default_warehouse')) if default_warehouse: warehouse_company = frappe.db.get_value("Warehouse", default_warehouse, "company") - + if not default_warehouse or warehouse_company != default.company: default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores'), 'company': default.company}) @@ -307,7 +308,7 @@ class Item(WebsiteGenerator): if self.retain_sample and not frappe.db.get_single_value('Stock Settings', 'sample_retention_warehouse'): frappe.throw(_("Please select Sample Retention Warehouse in Stock Settings first")) if self.retain_sample and not self.has_batch_no: - frappe.throw(_(" {0} Retain Sample is based on batch, please check Has Batch No to retain sample of item").format( + frappe.throw(_("{0} Retain Sample is based on batch, please check Has Batch No to retain sample of item").format( self.item_code)) def get_context(self, context): @@ -522,6 +523,13 @@ class Item(WebsiteGenerator): if self.has_serial_no == 0 and self.serial_no_series: self.serial_no_series = None + def validate_naming_series(self): + for field in ["serial_no_series", "batch_number_series"]: + series = self.get(field) + if series and "#" in series and "." not in series: + frappe.throw(_("Invalid naming series (. missing) for {0}") + .format(frappe.bold(self.meta.get_field(field).label))) + def check_for_active_boms(self): if self.default_bom: bom_item = frappe.db.get_value("BOM", self.default_bom, "item") @@ -741,14 +749,12 @@ class Item(WebsiteGenerator): defaults = frappe.defaults.get_defaults() or {} # To check default warehouse is belong to the default company - if defaults.get("default_warehouse") and frappe.db.exists("Warehouse", + if defaults.get("default_warehouse") and defaults.company and frappe.db.exists("Warehouse", {'name': defaults.default_warehouse, 'company': defaults.company}): - warehouse = defaults.default_warehouse - - self.append("item_defaults", { - "company": defaults.get("company"), - "default_warehouse": warehouse - }) + self.append("item_defaults", { + "company": defaults.get("company"), + "default_warehouse": defaults.default_warehouse + }) def update_variants(self): if self.flags.dont_update_variants or \ @@ -1009,8 +1015,6 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): order by pr.posting_date desc, pr.posting_time desc, pr.name desc limit 1""", (item_code, cstr(doc_name)), as_dict=1) - - purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date or "1900-01-01") purchase_receipt_date = getdate(last_purchase_receipt and @@ -1018,7 +1022,7 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): if last_purchase_order and (purchase_order_date >= purchase_receipt_date or not last_purchase_receipt): # use purchase order - + last_purchase = last_purchase_order[0] purchase_date = purchase_order_date @@ -1038,7 +1042,7 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): "discount_percentage": flt(last_purchase.discount_percentage), "purchase_date": purchase_date }) - + conversion_rate = flt(conversion_rate) or 1.0 out.update({ diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index d97b699a0f..5ad0e13db9 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -8,6 +8,7 @@ from frappe.utils import flt from frappe.model.meta import get_field_precision from frappe.model.document import Document from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.accounts.doctype.account.account import get_account_currency class LandedCostVoucher(Document): def get_items_from_purchase_receipts(self): @@ -43,6 +44,7 @@ class LandedCostVoucher(Document): else: self.validate_applicable_charges_for_item() self.validate_purchase_receipts() + self.validate_expense_accounts() self.set_total_taxes_and_charges() def check_mandatory(self): @@ -71,6 +73,14 @@ class LandedCostVoucher(Document): frappe.throw(_("Row {0}: Cost center is required for an item {1}") .format(item.idx, item.item_code)) + def validate_expense_accounts(self): + company_currency = erpnext.get_company_currency(self.company) + for account in self.taxes: + if get_account_currency(account.expense_account) != company_currency: + frappe.throw(msg=_(""" Row {0}: Expense account currency should be same as company's default currency. + Please select expense account with account currency as {1}""") + .format(account.idx, frappe.bold(company_currency)), title=_("Invalid Account Currency")) + def set_total_taxes_and_charges(self): self.total_taxes_and_charges = sum([flt(d.amount) for d in self.get("taxes")]) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 6b26d38377..6110ea822c 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -19,11 +19,6 @@ frappe.ui.form.on('Material Request', { frm.set_indicator_formatter('item_code', function(doc) { return (doc.qty<=doc.ordered_qty) ? "green" : "orange"; }); - frm.set_query("item_code", "items", function() { - return { - query: "erpnext.controllers.queries.item_query" - }; - }); }, onload: function(frm) { @@ -145,7 +140,8 @@ frappe.ui.form.on('Material Request', { }, get_item_data: function(frm, item) { - if (!item.item_code) return; + if (item && !item.item_code) { return; } + frm.call({ method: "erpnext.stock.get_item_details.get_item_details", child: item, @@ -360,6 +356,22 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten set_schedule_date(this.frm); }, + onload: function(doc, cdt, cdn) { + this.frm.set_query("item_code", "items", function() { + if (doc.material_request_type == "Customer Provided") { + return{ + query: "erpnext.controllers.queries.item_query", + filters:{ 'customer': me.frm.doc.customer } + } + } else if (doc.material_request_type != "Manufacture") { + return{ + query: "erpnext.controllers.queries.item_query", + filters: {'is_purchase_item': 1} + } + } + }); + }, + items_add: function(doc, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); if(doc.schedule_date) { diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 4542847016..5b242a51bc 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -454,6 +454,9 @@ def make_stock_entry(source_name, target_doc=None): else: target.s_warehouse = obj.warehouse + if source_parent.material_request_type == "Customer Provided": + target.allow_zero_valuation_rate = 1 + def set_missing_values(source, target): target.purpose = source.material_request_type if source.job_card: @@ -471,7 +474,7 @@ def make_stock_entry(source_name, target_doc=None): "doctype": "Stock Entry", "validation": { "docstatus": ["=", 1], - "material_request_type": ["in", ["Material Transfer", "Material Issue"]] + "material_request_type": ["in", ["Material Transfer", "Material Issue", "Customer Provided"]] } }, "Material Request Item": { @@ -501,7 +504,7 @@ def raise_work_orders(material_request): wo_order = frappe.new_doc("Work Order") wo_order.update({ "production_item": d.item_code, - "qty": d.qty - d.ordered_qty, + "qty": d.stock_qty - d.ordered_qty, "fg_warehouse": d.warehouse, "wip_warehouse": default_wip_warehouse, "description": d.description, diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index 79cdc1ad18..b925aedd1a 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -276,8 +276,8 @@ class TestMaterialRequest(unittest.TestCase): current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC") current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC") - self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 + 54.0) - self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 + 3.0) + self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 - 54.0) + self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 - 3.0) from erpnext.stock.doctype.material_request.material_request import make_stock_entry @@ -331,8 +331,8 @@ class TestMaterialRequest(unittest.TestCase): current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC") current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC") - self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 + 27.0) - self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 + 1.5) + self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 - 27.0) + self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 - 1.5) # check if per complete is as expected for Stock Entry cancelled se.cancel() @@ -344,8 +344,8 @@ class TestMaterialRequest(unittest.TestCase): current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC") current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC") - self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 + 54.0) - self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 + 3.0) + self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 - 54.0) + self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 - 3.0) def test_completed_qty_for_over_transfer(self): existing_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC") @@ -425,8 +425,8 @@ class TestMaterialRequest(unittest.TestCase): current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC") current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC") - self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 + 54.0) - self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 + 3.0) + self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 - 54.0) + self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 - 3.0) def test_incorrect_mapping_of_stock_entry(self): # submit material request of type Transfer @@ -512,7 +512,7 @@ class TestMaterialRequest(unittest.TestCase): mr.submit() #testing bin value after material request is submitted - self.assertEqual(_get_requested_qty(), existing_requested_qty + 54.0) + self.assertEqual(_get_requested_qty(), existing_requested_qty - 54.0) # receive items to allow issue self._insert_stock_entry(60, 6, "_Test Warehouse - _TC") @@ -609,6 +609,8 @@ class TestMaterialRequest(unittest.TestCase): def test_customer_provided_parts_mr(self): from erpnext.stock.doctype.material_request.material_request import make_stock_entry create_item('CUST-0987', is_customer_provided_item = 1, customer = '_Test Customer', is_purchase_item = 0) + existing_requested_qty = self._get_requested_qty("_Test Customer", "_Test Warehouse - _TC") + mr = make_material_request(item_code='CUST-0987', material_request_type='Customer Provided') se = make_stock_entry(mr.name) se.insert() @@ -617,7 +619,10 @@ class TestMaterialRequest(unittest.TestCase): self.assertEqual(se.get("items")[0].material_request, mr.name) mr = frappe.get_doc("Material Request", mr.name) mr.submit() + current_requested_qty = self._get_requested_qty("_Test Customer", "_Test Warehouse - _TC") + self.assertEqual(mr.per_ordered, 100) + self.assertEqual(existing_requested_qty, current_requested_qty) def make_material_request(**args): args = frappe._dict(args) diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js index 278971125f..d46b98b461 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.js +++ b/erpnext/stock/doctype/pick_list/pick_list.js @@ -38,13 +38,17 @@ frappe.ui.form.on('Pick List', { }; }); }, - get_item_locations: (frm) => { - if (!frm.doc.locations || !frm.doc.locations.length) { - frappe.msgprint(__('First add items in the Item Locations table')); + set_item_locations:(frm, save) => { + if (!(frm.doc.locations && frm.doc.locations.length)) { + frappe.msgprint(__('Add items in the Item Locations table')); } else { - frm.call('set_item_locations'); + frm.call('set_item_locations', {save: save}); } }, + get_item_locations: (frm) => { + // Button on the form + frm.events.set_item_locations(frm, false); + }, refresh: (frm) => { frm.trigger('add_get_items_button'); if (frm.doc.docstatus === 1) { @@ -52,8 +56,13 @@ frappe.ui.form.on('Pick List', { 'pick_list_name': frm.doc.name, 'purpose': frm.doc.purpose }).then(target_document_exists => { + frm.set_df_property("locations", "allow_on_submit", target_document_exists ? 0 : 1); + if (target_document_exists) return; - if (frm.doc.purpose === 'Delivery against Sales Order') { + + frm.add_custom_button(__('Update Current Stock'), () => frm.trigger('update_pick_list_stock')); + + if (frm.doc.purpose === 'Delivery') { frm.add_custom_button(__('Delivery Note'), () => frm.trigger('create_delivery_note'), __('Create')); } else { frm.add_custom_button(__('Stock Entry'), () => frm.trigger('create_stock_entry'), __('Create')); @@ -105,6 +114,7 @@ frappe.ui.form.on('Pick List', { method: 'erpnext.stock.doctype.pick_list.pick_list.create_delivery_note', frm: frm }); + }, create_stock_entry: (frm) => { frappe.xcall('erpnext.stock.doctype.pick_list.pick_list.create_stock_entry', { @@ -114,9 +124,12 @@ frappe.ui.form.on('Pick List', { frappe.set_route("Form", 'Stock Entry', stock_entry.name); }); }, + update_pick_list_stock: (frm) => { + frm.events.set_item_locations(frm, true); + }, add_get_items_button: (frm) => { let purpose = frm.doc.purpose; - if (purpose != 'Delivery against Sales Order' || frm.doc.docstatus !== 0) return; + if (purpose != 'Delivery' || frm.doc.docstatus !== 0) return; let get_query_filters = { docstatus: 1, per_delivered: ['<', 100], diff --git a/erpnext/stock/doctype/pick_list/pick_list.json b/erpnext/stock/doctype/pick_list/pick_list.json index 8d5ef3d12a..c01388dcd2 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.json +++ b/erpnext/stock/doctype/pick_list/pick_list.json @@ -1,4 +1,5 @@ { + "actions": [], "autoname": "naming_series:", "creation": "2019-07-11 16:03:13.681045", "doctype": "DocType", @@ -44,7 +45,7 @@ "options": "Warehouse" }, { - "depends_on": "eval:doc.purpose==='Delivery against Sales Order'", + "depends_on": "eval:doc.purpose==='Delivery'", "fieldname": "customer", "fieldtype": "Link", "in_list_view": 1, @@ -59,6 +60,7 @@ "options": "Work Order" }, { + "allow_on_submit": 1, "fieldname": "locations", "fieldtype": "Table", "label": "Item Locations", @@ -86,7 +88,7 @@ "fieldname": "purpose", "fieldtype": "Select", "label": "Purpose", - "options": "Material Transfer for Manufacture\nMaterial Transfer\nDelivery against Sales Order" + "options": "Material Transfer for Manufacture\nMaterial Transfer\nDelivery" }, { "depends_on": "eval:['Material Transfer', 'Material Issue'].includes(doc.purpose)", @@ -111,7 +113,8 @@ } ], "is_submittable": 1, - "modified": "2019-08-29 21:10:11.572387", + "links": [], + "modified": "2020-03-17 11:38:41.932875", "modified_by": "Administrator", "module": "Stock", "name": "Pick List", diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index c4d8c41ebb..616de5e00a 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -29,7 +29,7 @@ class PickList(Document): frappe.throw(_('For item {0} at row {1}, count of serial numbers does not match with the picked quantity') .format(frappe.bold(item.item_code), frappe.bold(item.idx))) - def set_item_locations(self): + def set_item_locations(self, save=False): items = self.aggregate_item_qty() self.item_location_map = frappe._dict() @@ -43,7 +43,7 @@ class PickList(Document): item_code = item_doc.item_code self.item_location_map.setdefault(item_code, - get_available_item_locations(item_code, from_warehouses, self.item_count_map.get(item_code))) + get_available_item_locations(item_code, from_warehouses, self.item_count_map.get(item_code), self.company)) locations = get_items_with_location_and_quantity(item_doc, self.item_location_map) @@ -59,12 +59,17 @@ class PickList(Document): location.update(row) self.append('locations', location) + if save: + self.save() + def aggregate_item_qty(self): locations = self.get('locations') self.item_count_map = {} # aggregate qty for same item item_map = OrderedDict() for item in locations: + if not item.item_code: + frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx)) item_code = item.item_code reference = item.sales_order_item or item.material_request_item key = (item_code, item.uom, reference) @@ -85,6 +90,10 @@ class PickList(Document): return item_map.values() +def validate_item_locations(pick_list): + if not pick_list.locations: + frappe.throw(_("Add items in the Item Locations table")) + def get_items_with_location_and_quantity(item_doc, item_location_map): available_locations = item_location_map.get(item_doc.item_code) locations = [] @@ -130,14 +139,14 @@ def get_items_with_location_and_quantity(item_doc, item_location_map): item_location_map[item_doc.item_code] = available_locations return locations -def get_available_item_locations(item_code, from_warehouses, required_qty): +def get_available_item_locations(item_code, from_warehouses, required_qty, company): locations = [] if frappe.get_cached_value('Item', item_code, 'has_serial_no'): - locations = get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty) + locations = get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty, company) elif frappe.get_cached_value('Item', item_code, 'has_batch_no'): - locations = get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty) + locations = get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty, company) else: - locations = get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty) + locations = get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty, company) total_qty_available = sum(location.get('qty') for location in locations) @@ -150,9 +159,10 @@ def get_available_item_locations(item_code, from_warehouses, required_qty): return locations -def get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty): +def get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty, company): filters = frappe._dict({ 'item_code': item_code, + 'company': company, 'warehouse': ['!=', ''] }) @@ -180,7 +190,7 @@ def get_available_item_locations_for_serialized_item(item_code, from_warehouses, return locations -def get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty): +def get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty, company): warehouse_condition = 'and warehouse in %(warehouses)s' if from_warehouses else '' batch_locations = frappe.db.sql(""" SELECT @@ -192,6 +202,7 @@ def get_available_item_locations_for_batched_item(item_code, from_warehouses, re WHERE sle.batch_no = batch.name and sle.`item_code`=%(item_code)s + and sle.`company` = %(company)s and IFNULL(batch.`expiry_date`, '2200-01-01') > %(today)s {warehouse_condition} GROUP BY @@ -202,16 +213,20 @@ def get_available_item_locations_for_batched_item(item_code, from_warehouses, re ORDER BY IFNULL(batch.`expiry_date`, '2200-01-01'), batch.`creation` """.format(warehouse_condition=warehouse_condition), { #nosec 'item_code': item_code, + 'company': company, 'today': today(), 'warehouses': from_warehouses }, as_dict=1) return batch_locations -def get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty): +def get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty, company): # gets all items available in different warehouses + warehouses = [x.get('name') for x in frappe.get_list("Warehouse", {'company': company}, "name")] + filters = frappe._dict({ 'item_code': item_code, + 'warehouse': ['in', warehouses], 'actual_qty': ['>', 0] }) @@ -230,7 +245,9 @@ def get_available_item_locations_for_other_item(item_code, from_warehouses, requ @frappe.whitelist() def create_delivery_note(source_name, target_doc=None): pick_list = frappe.get_doc('Pick List', source_name) - sales_orders = [d.sales_order for d in pick_list.locations] + validate_item_locations(pick_list) + + sales_orders = [d.sales_order for d in pick_list.locations if d.sales_order] sales_orders = set(sales_orders) delivery_note = None @@ -238,6 +255,10 @@ def create_delivery_note(source_name, target_doc=None): delivery_note = create_delivery_note_from_sales_order(sales_order, delivery_note, skip_item_mapping=True) + # map rows without sales orders as well + if not delivery_note: + delivery_note = frappe.new_doc("Delivery Note") + item_table_mapper = { 'doctype': 'Delivery Note Item', 'field_map': { @@ -248,9 +269,25 @@ def create_delivery_note(source_name, target_doc=None): 'condition': lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1 } + item_table_mapper_without_so = { + 'doctype': 'Delivery Note Item', + 'field_map': { + 'rate': 'rate', + 'name': 'name', + 'parent': '', + } + } + for location in pick_list.locations: - sales_order_item = frappe.get_cached_doc('Sales Order Item', location.sales_order_item) - dn_item = map_child_doc(sales_order_item, delivery_note, item_table_mapper) + if location.sales_order_item: + sales_order_item = frappe.get_cached_doc('Sales Order Item', {'name':location.sales_order_item}) + else: + sales_order_item = None + + source_doc, table_mapper = [sales_order_item, item_table_mapper] if sales_order_item \ + else [location, item_table_mapper_without_so] + + dn_item = map_child_doc(source_doc, delivery_note, table_mapper) if dn_item: dn_item.warehouse = location.warehouse @@ -258,7 +295,7 @@ def create_delivery_note(source_name, target_doc=None): dn_item.batch_no = location.batch_no dn_item.serial_no = location.serial_no - update_delivery_note_item(sales_order_item, dn_item, delivery_note) + update_delivery_note_item(source_doc, dn_item, delivery_note) set_delivery_note_missing_values(delivery_note) @@ -269,6 +306,7 @@ def create_delivery_note(source_name, target_doc=None): @frappe.whitelist() def create_stock_entry(pick_list): pick_list = frappe.get_doc(json.loads(pick_list)) + validate_item_locations(pick_list) if stock_entry_exists(pick_list.get('name')): return frappe.msgprint(_('Stock Entry has been already created against this Pick List')) @@ -318,7 +356,7 @@ def get_pending_work_orders(doctype, txt, searchfield, start, page_length, filte @frappe.whitelist() def target_document_exists(pick_list_name, purpose): - if purpose == 'Delivery against Sales Order': + if purpose == 'Delivery': return frappe.db.exists('Delivery Note', { 'pick_list': pick_list_name }) diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.json b/erpnext/stock/doctype/pick_list_item/pick_list_item.json index c7a35df51f..71fbf9a866 100644 --- a/erpnext/stock/doctype/pick_list_item/pick_list_item.json +++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2019-07-11 16:01:22.832885", "doctype": "DocType", "editable_grid": 1, @@ -8,6 +9,7 @@ "item_name", "column_break_2", "description", + "item_group", "section_break_5", "warehouse", "quantity_section", @@ -120,7 +122,8 @@ "fieldtype": "Link", "in_list_view": 1, "label": "Item", - "options": "Item" + "options": "Item", + "reqd": 1 }, { "fieldname": "quantity_section", @@ -166,10 +169,18 @@ "fieldtype": "Data", "label": "Material Request Item", "read_only": 1 + }, + { + "fetch_from": "item_code.item_group", + "fieldname": "item_group", + "fieldtype": "Data", + "label": "Item Group", + "read_only": 1 } ], "istable": 1, - "modified": "2019-08-29 21:28:39.539007", + "links": [], + "modified": "2020-03-13 19:08:21.995986", "modified_by": "Administrator", "module": "Stock", "name": "Pick List Item", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index 35446ecb1f..e38bb38b19 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -47,6 +47,7 @@ "is_subcontracted", "supplier_warehouse", "items_section", + "scan_barcode", "items", "pricing_rule_details", "pricing_rules", @@ -1070,13 +1071,18 @@ "label": "Inter Company Reference", "options": "Delivery Note", "read_only": 1 + }, + { + "fieldname": "scan_barcode", + "fieldtype": "Data", + "label": "Scan Barcode" } ], "icon": "fa fa-truck", "idx": 261, "is_submittable": 1, "links": [], - "modified": "2019-12-30 19:12:49.709711", + "modified": "2020-04-06 16:31:37.444891", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 3b43690658..c2b38927f7 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -50,8 +50,8 @@ class PurchaseReceipt(BuyingController): 'target_field': 'received_qty', 'target_parent_dt': 'Material Request', 'target_parent_field': 'per_received', - 'target_ref_field': 'qty', - 'source_field': 'qty', + 'target_ref_field': 'stock_qty', + 'source_field': 'stock_qty', 'percent_join_field': 'material_request' }] if cint(self.is_return): @@ -357,7 +357,7 @@ class PurchaseReceipt(BuyingController): if warehouse_with_no_account: frappe.msgprint(_("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) - + return process_gl_map(gl_entries) def get_asset_gl_entry(self, gl_entries): @@ -628,7 +628,7 @@ def get_item_account_wise_additional_cost(purchase_document): if not landed_cost_vouchers: return - + item_account_wise_cost = {} for lcv in landed_cost_vouchers: diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index cd190da689..40d7cc2537 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -375,6 +375,33 @@ class TestPurchaseReceipt(unittest.TestCase): location = frappe.db.get_value('Asset', assets[0].name, 'location') self.assertEquals(location, "Test Location") + + def test_purchase_return_with_submitted_asset(self): + from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_return + + pr = make_purchase_receipt(item_code="Test Asset Item", qty=1) + + asset = frappe.get_doc("Asset", { + 'purchase_receipt': pr.name + }) + asset.available_for_use_date = frappe.utils.nowdate() + asset.gross_purchase_amount = 50.0 + asset.append("finance_books", { + "expected_value_after_useful_life": 10, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 1, + "depreciation_start_date": frappe.utils.nowdate() + }) + asset.submit() + + pr_return = make_purchase_return(pr.name) + self.assertRaises(frappe.exceptions.ValidationError, pr_return.submit) + + asset.load_from_db() + asset.cancel() + + pr_return.submit() def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self): from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json index fb28b5c079..731a730279 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.json +++ b/erpnext/stock/doctype/serial_no/serial_no.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "allow_rename": 1, "autoname": "field:serial_no", @@ -41,7 +42,6 @@ "delivery_document_no", "delivery_date", "delivery_time", - "is_cancelled", "column_break5", "customer", "customer_name", @@ -56,7 +56,8 @@ "warranty_period", "more_info", "serial_no_details", - "company" + "company", + "status" ], "fields": [ { @@ -306,16 +307,6 @@ "no_copy": 1, "read_only": 1 }, - { - "fieldname": "is_cancelled", - "fieldtype": "Select", - "hidden": 1, - "label": "Is Cancelled", - "oldfieldname": "is_cancelled", - "oldfieldtype": "Select", - "options": "\nYes\nNo", - "report_hide": 1 - }, { "fieldname": "column_break5", "fieldtype": "Column Break", @@ -423,11 +414,20 @@ "remember_last_selected_value": 1, "reqd": 1, "search_index": 1 + }, + { + "fieldname": "status", + "fieldtype": "Select", + "in_standard_filter": 1, + "label": "Status", + "options": "\nActive\nDelivered\nExpired", + "read_only": 1 } ], "icon": "fa fa-barcode", "idx": 1, - "modified": "2020-02-28 19:31:09.357323", + "links": [], + "modified": "2020-04-08 13:29:58.517772", "modified_by": "Administrator", "module": "Stock", "name": "Serial No", diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 64d4c6c082..b32c709be3 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -35,6 +35,15 @@ class SerialNo(StockController): self.set_maintenance_status() self.validate_warehouse() self.validate_item() + self.set_status() + + def set_status(self): + if self.delivery_document_type: + self.status = "Delivered" + elif self.warranty_expiry_date and getdate(self.warranty_expiry_date) <= getdate(nowdate()): + self.status = "Expired" + else: + self.status = "Active" def set_maintenance_status(self): if not self.warranty_expiry_date and not self.amc_expiry_date: @@ -197,6 +206,7 @@ class SerialNo(StockController): self.set_purchase_details(last_sle.get("purchase_sle")) self.set_sales_details(last_sle.get("delivery_sle")) self.set_maintenance_status() + self.set_status() def process_serial_no(sle): item_det = get_item_details(sle.item_code) @@ -523,12 +533,15 @@ def get_delivery_note_serial_no(item_code, qty, delivery_note): return serial_nos @frappe.whitelist() -def auto_fetch_serial_number(qty, item_code, warehouse, batch_no=None): - serial_numbers = frappe.get_list("Serial No", filters={ +def auto_fetch_serial_number(qty, item_code, warehouse, batch_nos=None): + import json + filters = { "item_code": item_code, "warehouse": warehouse, - "batch_no": batch_no, "delivery_document_no": "", "sales_invoice": "" - }, limit=qty, order_by="creation") + } + if batch_nos: filters["batch_no"] = ["in", json.loads(batch_nos)] + + serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation") return [item['name'] for item in serial_numbers] diff --git a/erpnext/stock/doctype/serial_no/serial_no_list.js b/erpnext/stock/doctype/serial_no/serial_no_list.js index 5b1e312f68..651f790583 100644 --- a/erpnext/stock/doctype/serial_no/serial_no_list.js +++ b/erpnext/stock/doctype/serial_no/serial_no_list.js @@ -1,14 +1,12 @@ frappe.listview_settings['Serial No'] = { - add_fields: ["is_cancelled", "item_code", "warehouse", "warranty_expiry_date", "delivery_document_type"], + add_fields: ["item_code", "warehouse", "warranty_expiry_date", "delivery_document_type"], get_indicator: (doc) => { - if (doc.is_cancelled) { - return [__("Cancelled"), "red", "is_cancelled,=,Yes"]; - } else if (doc.delivery_document_type) { - return [__("Delivered"), "green", "delivery_document_type,is,set|is_cancelled,=,No"]; + if (doc.delivery_document_type) { + return [__("Delivered"), "green", "delivery_document_type,is,set"]; } else if (doc.warranty_expiry_date && frappe.datetime.get_diff(doc.warranty_expiry_date, frappe.datetime.nowdate()) <= 0) { - return [__("Expired"), "red", "warranty_expiry_date,not in,|warranty_expiry_date,<=,Today|delivery_document_type,is,not set|is_cancelled,=,No"]; + return [__("Expired"), "red", "warranty_expiry_date,not in,|warranty_expiry_date,<=,Today|delivery_document_type,is,not set"]; } else { - return [__("Active"), "green", "delivery_document_type,is,not set|is_cancelled,=,No"]; + return [__("Active"), "green", "delivery_document_type,is,not set"]; } } }; diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 2840a70dd0..3bb941573b 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -60,7 +60,8 @@ frappe.ui.form.on('Stock Entry', { } } - if(item.s_warehouse) filters["warehouse"] = item.s_warehouse; + filters["warehouse"] = item.s_warehouse || item.t_warehouse; + return { query : "erpnext.controllers.queries.get_batch_no", filters: filters @@ -309,12 +310,12 @@ frappe.ui.form.on('Stock Entry', { method: "erpnext.stock.get_item_details.get_serial_no", args: {"args": args}, callback: function(r) { - if (!r.exe){ + if (!r.exe && r.message){ frappe.model.set_value(cdt, cdn, "serial_no", r.message); - } - if (callback) { - callback(); + if (callback) { + callback(); + } } } }); @@ -622,10 +623,15 @@ frappe.ui.form.on('Stock Entry Detail', { if(r.message) { var d = locals[cdt][cdn]; $.each(r.message, function(k, v) { - frappe.model.set_value(cdt, cdn, k, v); // qty and it's subsequent fields weren't triggered + if (v) { + frappe.model.set_value(cdt, cdn, k, v); // qty and it's subsequent fields weren't triggered + } }); refresh_field("items"); - erpnext.stock.select_batch_and_serial_no(frm, d); + + if (!d.serial_no) { + erpnext.stock.select_batch_and_serial_no(frm, d); + } } } }); @@ -964,7 +970,7 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => { } } - if(item && !item.has_serial_no && item.has_batch_no) return; + if(item && !item.has_serial_no && !item.has_batch_no) return; if (frm.doc.purpose === 'Material Receipt') return; frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 8b072c66ee..7cf822bf49 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -50,6 +50,7 @@ class StockEntry(StockController): self.validate_posting_time() self.validate_purpose() self.validate_item() + self.validate_customer_provided_item() self.validate_qty() self.set_transfer_qty() self.validate_uom_is_integer("uom", "qty") @@ -177,6 +178,10 @@ class StockEntry(StockController): stock_items = self.get_stock_items() serialized_items = self.get_serialized_items() for item in self.get("items"): + if item.qty and item.qty < 0: + frappe.throw(_("Row {0}: The item {1}, quantity must be positive number") + .format(item.idx, frappe.bold(item.item_code))) + if item.item_code not in stock_items: frappe.throw(_("{0} is not a stock Item").format(item.item_code)) @@ -199,10 +204,6 @@ class StockEntry(StockController): frappe.throw(_("Row #{0}: Please specify Serial No for Item {1}").format(item.idx, item.item_code), frappe.MandatoryError) - #Customer Provided parts will have zero valuation rate - if frappe.db.get_value('Item', item.item_code, 'is_customer_provided_item'): - item.allow_zero_valuation_rate = 1 - def validate_qty(self): manufacture_purpose = ["Manufacture", "Material Consumption for Manufacture"] @@ -234,7 +235,7 @@ class StockEntry(StockController): if self.purpose == "Manufacture" and self.work_order: production_item = frappe.get_value('Work Order', self.work_order, 'production_item') for item in self.items: - if item.item_code == production_item and item.qty != self.fg_completed_qty: + if item.item_code == production_item and item.t_warehouse and item.qty != self.fg_completed_qty: frappe.throw(_("Finished product quantity {0} and For Quantity {1} cannot be different") .format(item.qty, self.fg_completed_qty)) @@ -294,13 +295,8 @@ class StockEntry(StockController): if validate_for_manufacture: if d.bom_no: d.s_warehouse = None - if not d.t_warehouse: frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) - - elif self.pro_doc and (cstr(d.t_warehouse) != self.pro_doc.fg_warehouse and cstr(d.t_warehouse) != self.pro_doc.scrap_warehouse): - frappe.throw(_("Target warehouse in row {0} must be same as Work Order").format(d.idx)) - else: d.t_warehouse = None if not d.s_warehouse: diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index ee5f237098..2afabe1480 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -744,7 +744,7 @@ class TestStockEntry(unittest.TestCase): def test_customer_provided_parts_se(self): create_item('CUST-0987', is_customer_provided_item = 1, customer = '_Test Customer', is_purchase_item = 0) - se = make_stock_entry(item_code='CUST-0987', purporse = 'Material Receipt', qty=4, to_warehouse = "_Test Warehouse - _TC") + se = make_stock_entry(item_code='CUST-0987', purpose = 'Material Receipt', qty=4, to_warehouse = "_Test Warehouse - _TC") self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1) self.assertEqual(se.get("items")[0].amount, 0) diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index d86e68b722..a848c80cf2 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -1,4 +1,5 @@ { + "actions": [], "autoname": "hash", "creation": "2013-03-29 18:22:12", "doctype": "DocType", @@ -479,8 +480,7 @@ "fieldname": "project", "fieldtype": "Link", "label": "Project", - "options": "Project", - "read_only": 1 + "options": "Project" }, { "fieldname": "po_detail", @@ -494,7 +494,8 @@ ], "idx": 1, "istable": 1, - "modified": "2019-08-20 14:01:02.319754", + "links": [], + "modified": "2020-03-19 12:34:09.836295", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail", diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 5fe89d6e22..0d3e33164a 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -37,11 +37,19 @@ class StockLedgerEntry(Document): def on_submit(self): self.check_stock_frozen_date() self.actual_amt_check() + self.calculate_batch_qty() if not self.get("via_landed_cost_voucher"): from erpnext.stock.doctype.serial_no.serial_no import process_serial_no process_serial_no(self) + def calculate_batch_qty(self): + if self.batch_no: + batch_qty = frappe.db.get_value("Stock Ledger Entry", + {"docstatus": 1, "batch_no": self.batch_no, "is_cancelled": "No"}, + "sum(actual_qty)") or 0 + frappe.db.set_value("Batch", self.batch_no, "batch_qty", batch_qty) + #check for item quantity available in stock def actual_amt_check(self): if self.batch_no and not self.get("allow_negative_stock"): @@ -139,4 +147,3 @@ def on_doctype_update(): frappe.db.add_index("Stock Ledger Entry", ["voucher_no", "voucher_type"]) frappe.db.add_index("Stock Ledger Entry", ["batch_no", "item_code", "warehouse"]) - diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index afa239466b..0a49c26b62 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -488,12 +488,14 @@ def get_stock_balance_for(item_code, warehouse, ["has_serial_no", "has_batch_no"], as_dict=1) serial_nos = "" - if item_dict.get("has_serial_no"): - qty, rate, serial_nos = get_qty_rate_for_serial_nos(item_code, - warehouse, posting_date, posting_time, item_dict) + with_serial_no = True if item_dict.get("has_serial_no") else False + data = get_stock_balance(item_code, warehouse, posting_date, posting_time, + with_valuation_rate=with_valuation_rate, with_serial_no=with_serial_no) + + if with_serial_no: + qty, rate, serial_nos = data else: - qty, rate = get_stock_balance(item_code, warehouse, - posting_date, posting_time, with_valuation_rate=with_valuation_rate) + qty, rate = data if item_dict.get("has_batch_no"): qty = get_batch_qty(batch_no, warehouse) or 0 @@ -504,28 +506,6 @@ def get_stock_balance_for(item_code, warehouse, 'serial_nos': serial_nos } -def get_qty_rate_for_serial_nos(item_code, warehouse, posting_date, posting_time, item_dict): - args = { - "item_code": item_code, - "warehouse": warehouse, - "posting_date": posting_date, - "posting_time": posting_time, - } - - serial_nos_list = [serial_no.get("name") - for serial_no in get_available_serial_nos(args)] - - qty = len(serial_nos_list) - serial_nos = '\n'.join(serial_nos_list) - args.update({ - 'qty': qty, - "serial_nos": serial_nos - }) - - rate = get_incoming_rate(args, raise_error_if_no_rate=False) or 0 - - return qty, rate, serial_nos - @frappe.whitelist() def get_difference_account(purpose, company): if purpose == 'Stock Reconciliation': diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json index f43390f19d..c9a3527e91 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.json +++ b/erpnext/stock/doctype/stock_settings/stock_settings.json @@ -1,955 +1,238 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "", - "beta": 0, + "actions": [], "creation": "2013-06-24 16:37:54", - "custom": 0, "description": "Settings", - "docstatus": 0, "doctype": "DocType", - "editable_grid": 0, + "engine": "InnoDB", + "field_order": [ + "item_naming_by", + "item_group", + "stock_uom", + "default_warehouse", + "sample_retention_warehouse", + "column_break_4", + "valuation_method", + "over_delivery_receipt_allowance", + "action_if_quality_inspection_is_not_submitted", + "show_barcode_field", + "clean_description_html", + "section_break_7", + "auto_insert_price_list_rate_if_missing", + "allow_negative_stock", + "column_break_10", + "automatically_set_serial_nos_based_on_fifo", + "set_qty_in_transactions_based_on_serial_no_input", + "auto_material_request", + "auto_indent", + "reorder_email_notify", + "inter_warehouse_transfer_settings_section", + "allow_from_dn", + "allow_from_pr", + "freeze_stock_entries", + "stock_frozen_upto", + "stock_frozen_upto_days", + "stock_auth_role", + "batch_id_sb", + "use_naming_series", + "naming_series_prefix" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "Item Code", - "fetch_if_empty": 0, "fieldname": "item_naming_by", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Item Naming By", - "length": 0, - "no_copy": 0, - "options": "Item Code\nNaming Series", - "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 + "options": "Item Code\nNaming Series" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fetch_if_empty": 0, "fieldname": "item_group", "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": "Default Item Group", - "length": 0, - "no_copy": 0, - "options": "Item Group", - "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 + "options": "Item Group" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "stock_uom", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Default Stock UOM", - "length": 0, - "no_copy": 0, - "options": "UOM", - "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 + "options": "UOM" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "default_warehouse", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Warehouse", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Warehouse" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "sample_retention_warehouse", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Sample Retention Warehouse", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Warehouse" }, { - "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_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "valuation_method", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Valuation Method", - "length": 0, - "no_copy": 0, - "options": "FIFO\nMoving Average", - "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 + "options": "FIFO\nMoving Average" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "description": "Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.", - "fetch_if_empty": 0, "fieldname": "over_delivery_receipt_allowance", "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Over Delivery/Receipt Allowance (%)", - "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 + "label": "Over Delivery/Receipt Allowance (%)" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "Stop", - "fetch_if_empty": 0, "fieldname": "action_if_quality_inspection_is_not_submitted", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Action if Quality inspection is not submitted", - "length": 0, - "no_copy": 0, - "options": "Stop\nWarn", - "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 + "options": "Stop\nWarn" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "1", - "fetch_if_empty": 0, "fieldname": "show_barcode_field", "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": "Show Barcode Field", - "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 + "label": "Show Barcode Field" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "1", - "fetch_if_empty": 0, "fieldname": "clean_description_html", "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": "Convert Item Description to Clean HTML", - "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 + "label": "Convert Item Description to Clean HTML" }, { - "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_7", - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, + "default": "0", "fieldname": "auto_insert_price_list_rate_if_missing", "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": "Auto insert Price List rate if missing", - "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 + "label": "Auto insert Price List rate if missing" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, + "default": "0", "fieldname": "allow_negative_stock", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Negative Stock", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Allow Negative Stock" }, { - "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_10", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "1", - "fetch_if_empty": 0, "fieldname": "automatically_set_serial_nos_based_on_fifo", "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": "Automatically Set Serial Nos based on FIFO", - "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 + "label": "Automatically Set Serial Nos based on FIFO" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "1", - "fetch_if_empty": 0, "fieldname": "set_qty_in_transactions_based_on_serial_no_input", "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": "Set Qty in Transactions based on Serial No Input", - "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 + "label": "Set Qty in Transactions based on Serial No Input" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "auto_material_request", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Auto Material Request", - "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 + "label": "Auto Material Request" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, + "default": "0", "fieldname": "auto_indent", "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": "Raise Material Request when stock reaches re-order level", - "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 + "label": "Raise Material Request when stock reaches re-order level" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, + "default": "0", "fieldname": "reorder_email_notify", "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": "Notify by Email on creation of automatic Material Request", - "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 + "label": "Notify by Email on creation of automatic Material Request" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "freeze_stock_entries", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Freeze Stock 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 + "label": "Freeze Stock Entries" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "stock_frozen_upto", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Stock Frozen Upto", - "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 + "label": "Stock Frozen Upto" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "stock_frozen_upto_days", "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Freeze Stocks Older Than [Days]", - "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 + "label": "Freeze Stocks Older Than [Days]" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "stock_auth_role", "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": "Role Allowed to edit frozen stock", - "length": 0, - "no_copy": 0, - "options": "Role", - "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 + "options": "Role" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "batch_id_sb", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Batch Identification", - "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 + "label": "Batch Identification" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0", - "fetch_if_empty": 0, "fieldname": "use_naming_series", "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": "Use Naming Series", - "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 + "label": "Use Naming Series" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "BATCH-", "depends_on": "eval:doc.use_naming_series==1", - "fetch_if_empty": 0, "fieldname": "naming_series_prefix", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Naming Series Prefix", - "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 + "label": "Naming Series Prefix" + }, + { + "fieldname": "inter_warehouse_transfer_settings_section", + "fieldtype": "Section Break", + "label": "Inter Warehouse Transfer Settings" + }, + { + "default": "0", + "fieldname": "allow_from_dn", + "fieldtype": "Check", + "label": "Allow Material Transfer From Delivery Note and Sales Invoice" + }, + { + "default": "0", + "fieldname": "allow_from_pr", + "fieldtype": "Check", + "label": "Allow Material Transfer From Purchase Receipt and Purchase Invoice" } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, "icon": "icon-cog", "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2019-07-04 01:19:07.738045", + "links": [], + "modified": "2020-04-01 18:11:25.417678", "modified_by": "Administrator", "module": "Stock", "name": "Stock Settings", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, - "delete": 0, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, - "report": 0, "role": "Stock 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_order": "ASC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + "sort_field": "modified", + "sort_order": "ASC" } \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py index 93b5eee75c..4c7828b873 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/stock_settings.py @@ -8,6 +8,8 @@ import frappe from frappe import _ from frappe.model.document import Document from frappe.utils.html_utils import clean_html +from frappe.utils import cint +from frappe.custom.doctype.property_setter.property_setter import make_property_setter class StockSettings(Document): def validate(self): @@ -61,6 +63,15 @@ class StockSettings(Document): # changed to text frappe.enqueue('erpnext.stock.doctype.stock_settings.stock_settings.clean_all_descriptions', now=frappe.flags.in_test) + def on_update(self): + self.toggle_warehouse_field_for_inter_warehouse_transfer() + + def toggle_warehouse_field_for_inter_warehouse_transfer(self): + make_property_setter("Sales Invoice Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check") + make_property_setter("Delivery Note Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check") + make_property_setter("Purchase Invoice Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check") + make_property_setter("Purchase Receipt Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check") + def clean_all_descriptions(): for item in frappe.get_all('Item', ['name', 'description']): diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 53964f24c4..b1bfc90588 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -240,26 +240,13 @@ def get_basic_details(args, item, overwrite_warehouse=True): item_group_defaults = get_item_group_defaults(item.name, args.company) brand_defaults = get_brand_defaults(item.name, args.company) - if overwrite_warehouse or not args.warehouse: - warehouse = ( - args.get("set_warehouse") or - item_defaults.get("default_warehouse") or - item_group_defaults.get("default_warehouse") or - brand_defaults.get("default_warehouse") or - args.warehouse - ) + defaults = frappe._dict({ + 'item_defaults': item_defaults, + 'item_group_defaults': item_group_defaults, + 'brand_defaults': brand_defaults + }) - if not warehouse: - defaults = frappe.defaults.get_defaults() or {} - warehouse_exists = frappe.db.exists("Warehouse", { - 'name': defaults.default_warehouse, - 'company': args.company - }) - if defaults.get("default_warehouse") and warehouse_exists: - warehouse = defaults.default_warehouse - - else: - warehouse = args.warehouse + warehouse = get_item_warehouse(item, args, overwrite_warehouse, defaults) if args.get('doctype') == "Material Request" and not args.get('material_request_type'): args['material_request_type'] = frappe.db.get_value('Material Request', @@ -272,7 +259,7 @@ def get_basic_details(args, item, overwrite_warehouse=True): expense_account = get_asset_category_account(fieldname = "fixed_asset_account", item = args.item_code, company= args.company) #Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master - if not args.uom: + if not args.get('uom'): if args.get('doctype') in sales_doctypes: args.uom = item.sales_uom if item.sales_uom else item.stock_uom elif (args.get('doctype') in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']) or \ @@ -292,7 +279,7 @@ def get_basic_details(args, item, overwrite_warehouse=True): "cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults), 'has_serial_no': item.has_serial_no, 'has_batch_no': item.has_batch_no, - "batch_no": None, + "batch_no": args.get("batch_no"), "uom": args.uom, "min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "", "qty": flt(args.qty) or 1.0, @@ -362,6 +349,37 @@ def get_basic_details(args, item, overwrite_warehouse=True): return out +def get_item_warehouse(item, args, overwrite_warehouse, defaults={}): + if not defaults: + defaults = frappe._dict({ + 'item_defaults' : get_item_defaults(item.name, args.company), + 'item_group_defaults' : get_item_group_defaults(item.name, args.company), + 'brand_defaults' : get_brand_defaults(item.name, args.company) + }) + + if overwrite_warehouse or not args.warehouse: + warehouse = ( + args.get("set_warehouse") or + defaults.item_defaults.get("default_warehouse") or + defaults.item_group_defaults.get("default_warehouse") or + defaults.brand_defaults.get("default_warehouse") or + args.get('warehouse') + ) + + if not warehouse: + defaults = frappe.defaults.get_defaults() or {} + warehouse_exists = frappe.db.exists("Warehouse", { + 'name': defaults.default_warehouse, + 'company': args.company + }) + if defaults.get("default_warehouse") and warehouse_exists: + warehouse = defaults.default_warehouse + + else: + warehouse = args.get('warehouse') + + return warehouse + def update_barcode_value(out): from erpnext.accounts.doctype.sales_invoice.pos import get_barcode_data barcode_data = get_barcode_data([out]) diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py index 94ec314e8c..1af68dd7f2 100644 --- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -35,7 +35,7 @@ def get_data(report_filters): gl_data = voucher_wise_gl_data.get(key) or {} d.account_value = gl_data.get("account_value", 0) d.difference_value = (d.stock_value - d.account_value) - if abs(d.difference_value) > 1.0/10 ** currency_precision: + if abs(d.difference_value) > 0.1: data.append(d) return data diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js index 3d5cfdc274..9adfbf7cd0 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.js +++ b/erpnext/stock/report/stock_ledger/stock_ledger.js @@ -29,7 +29,13 @@ frappe.query_reports["Stock Ledger"] = { "fieldname":"warehouse", "label": __("Warehouse"), "fieldtype": "Link", - "options": "Warehouse" + "options": "Warehouse", + "get_query": function() { + const company = frappe.query_report.get_filter_value('company'); + return { + filters: { 'company': company } + } + } }, { "fieldname":"item_code", diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index e5dc6b12df..2bdb04ed2c 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -113,13 +113,24 @@ def get_reserved_qty(item_code, warehouse): return flt(reserved_qty[0][0]) if reserved_qty else 0 def get_indented_qty(item_code, warehouse): - indented_qty = frappe.db.sql("""select sum((mr_item.qty - mr_item.ordered_qty) * mr_item.conversion_factor) + inward_qty = frappe.db.sql("""select sum((mr_item.qty - mr_item.ordered_qty) * mr_item.conversion_factor) + from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr + where mr_item.item_code=%s and mr_item.warehouse=%s + and mr.material_request_type in ('Purchase', 'Manufacture') + and mr_item.qty > mr_item.ordered_qty and mr_item.parent=mr.name + and mr.status!='Stopped' and mr.docstatus=1""", (item_code, warehouse)) + + outward_qty = frappe.db.sql("""select sum((mr_item.qty - mr_item.ordered_qty) * mr_item.conversion_factor) from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr where mr_item.item_code=%s and mr_item.warehouse=%s + and mr.material_request_type in ('Material Issue', 'Material Transfer') and mr_item.qty > mr_item.ordered_qty and mr_item.parent=mr.name and mr.status!='Stopped' and mr.docstatus=1""", (item_code, warehouse)) - return flt(indented_qty[0][0]) if indented_qty else 0 + inward_qty, outward_qty = flt(inward_qty[0][0]) if inward_qty else 0, flt(outward_qty[0][0]) if outward_qty else 0 + indented_qty = inward_qty - outward_qty + + return indented_qty def get_ordered_qty(item_code, warehouse): ordered_qty = frappe.db.sql(""" @@ -145,9 +156,9 @@ def update_bin_qty(item_code, warehouse, qty_dict=None): from erpnext.stock.utils import get_bin bin = get_bin(item_code, warehouse) mismatch = False - for fld, val in qty_dict.items(): - if flt(bin.get(fld)) != flt(val): - bin.set(fld, flt(val)) + for field, value in qty_dict.items(): + if flt(bin.get(field)) != flt(value): + bin.set(field, flt(value)) mismatch = True if mismatch: diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index b100f45327..7567a1ae75 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -428,7 +428,7 @@ class update_entries_after(object): frappe.get_desk_link(self.exceptions[0]["voucher_type"], self.exceptions[0]["voucher_no"])) if self.verbose: - frappe.throw(msg, NegativeStockError, title='Insufficent Stock') + frappe.throw(msg, NegativeStockError, title='Insufficient Stock') else: raise NegativeStockError(msg) diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index f3381c7609..7f32b8d8bb 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -74,7 +74,8 @@ def get_stock_value_on(warehouse=None, posting_date=None, item_code=None): return sum(sle_map.values()) @frappe.whitelist() -def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None, with_valuation_rate=False): +def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None, + with_valuation_rate=False, with_serial_no=False): """Returns stock balance quantity at given warehouse on given posting date or current date. If `with_valuation_rate` is True, will return tuple (qty, rate)""" @@ -84,17 +85,51 @@ def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None if not posting_date: posting_date = nowdate() if not posting_time: posting_time = nowtime() - last_entry = get_previous_sle({ + args = { "item_code": item_code, "warehouse":warehouse, "posting_date": posting_date, - "posting_time": posting_time }) + "posting_time": posting_time + } + + last_entry = get_previous_sle(args) if with_valuation_rate: - return (last_entry.qty_after_transaction, last_entry.valuation_rate) if last_entry else (0.0, 0.0) + if with_serial_no: + serial_nos = last_entry.get("serial_no") + + if (serial_nos and + len(get_serial_nos_data(serial_nos)) < last_entry.qty_after_transaction): + serial_nos = get_serial_nos_data_after_transactions(args) + + return ((last_entry.qty_after_transaction, last_entry.valuation_rate, serial_nos) + if last_entry else (0.0, 0.0, 0.0)) + else: + return (last_entry.qty_after_transaction, last_entry.valuation_rate) if last_entry else (0.0, 0.0) else: return last_entry.qty_after_transaction if last_entry else 0.0 +def get_serial_nos_data_after_transactions(args): + serial_nos = [] + data = frappe.db.sql(""" SELECT serial_no, actual_qty + FROM `tabStock Ledger Entry` + WHERE + item_code = %(item_code)s and warehouse = %(warehouse)s + and timestamp(posting_date, posting_time) < timestamp(%(posting_date)s, %(posting_time)s) + order by posting_date, posting_time asc """, args, as_dict=1) + + for d in data: + if d.actual_qty > 0: + serial_nos.extend(get_serial_nos_data(d.serial_no)) + else: + serial_nos = list(set(serial_nos) - set(get_serial_nos_data(d.serial_no))) + + return '\n'.join(serial_nos) + +def get_serial_nos_data(serial_nos): + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + return get_serial_nos(serial_nos) + @frappe.whitelist() def get_latest_stock_qty(item_code, warehouse=None): values, condition = [item_code], "" diff --git a/erpnext/support/desk_page/support/support.json b/erpnext/support/desk_page/support/support.json index 4a7885e46f..596987f46a 100644 --- a/erpnext/support/desk_page/support/support.json +++ b/erpnext/support/desk_page/support/support.json @@ -1,30 +1,34 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"Service Level.\",\n \"label\": \"Service Level\",\n \"name\": \"Service Level\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Service Level Agreement.\",\n \"label\": \"Service Level Agreement\",\n \"name\": \"Service Level Agreement\",\n \"type\": \"doctype\"\n }\n]", - "title": "Service Level Agreement" + "hidden": 0, + "label": "Service Level Agreement", + "links": "[\n {\n \"description\": \"Service Level.\",\n \"label\": \"Service Level\",\n \"name\": \"Service Level\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Service Level Agreement.\",\n \"label\": \"Service Level Agreement\",\n \"name\": \"Service Level Agreement\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Maintenance Schedule\",\n \"name\": \"Maintenance Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Maintenance Visit\",\n \"name\": \"Maintenance Visit\",\n \"type\": \"doctype\"\n }\n]", - "title": "Maintenance" + "hidden": 0, + "label": "Maintenance", + "links": "[\n {\n \"label\": \"Maintenance Schedule\",\n \"name\": \"Maintenance Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Maintenance Visit\",\n \"name\": \"Maintenance Visit\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Support queries from customers.\",\n \"label\": \"Issue\",\n \"name\": \"Issue\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Issue Type.\",\n \"label\": \"Issue Type\",\n \"name\": \"Issue Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Issue Priority.\",\n \"label\": \"Issue Priority\",\n \"name\": \"Issue Priority\",\n \"type\": \"doctype\"\n }\n]", - "title": "Issues" + "hidden": 0, + "label": "Issues", + "links": "[\n {\n \"description\": \"Support queries from customers.\",\n \"label\": \"Issue\",\n \"name\": \"Issue\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Issue Type.\",\n \"label\": \"Issue Type\",\n \"name\": \"Issue Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Issue Priority.\",\n \"label\": \"Issue Priority\",\n \"name\": \"Issue Priority\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Warranty Claim against Serial No.\",\n \"label\": \"Warranty Claim\",\n \"name\": \"Warranty Claim\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Single unit of an Item.\",\n \"label\": \"Serial No\",\n \"name\": \"Serial No\",\n \"type\": \"doctype\"\n }\n]", - "title": "Warranty" + "hidden": 0, + "label": "Warranty", + "links": "[\n {\n \"description\": \"Warranty Claim against Serial No.\",\n \"label\": \"Warranty Claim\",\n \"name\": \"Warranty Claim\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Single unit of an Item.\",\n \"label\": \"Serial No\",\n \"name\": \"Serial No\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"label\": \"Support Settings\",\n \"name\": \"Support Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Settings" + "hidden": 0, + "label": "Settings", + "links": "[\n {\n \"label\": \"Support Settings\",\n \"name\": \"Support Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-list", - "links": "[\n {\n \"dependencies\": [\n \"Issue\"\n ],\n \"doctype\": \"Issue\",\n \"is_query_report\": true,\n \"label\": \"Minutes to First Response for Issues\",\n \"name\": \"Minutes to First Response for Issues\",\n \"type\": \"report\"\n }\n]", - "title": "Reports" + "hidden": 0, + "label": "Reports", + "links": "[\n {\n \"dependencies\": [\n \"Issue\"\n ],\n \"doctype\": \"Issue\",\n \"is_query_report\": true,\n \"label\": \"Minutes to First Response for Issues\",\n \"name\": \"Minutes to First Response for Issues\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", @@ -39,7 +43,7 @@ "idx": 0, "is_standard": 1, "label": "Support", - "modified": "2020-03-12 16:30:39.482621", + "modified": "2020-04-01 11:28:51.120583", "modified_by": "Administrator", "module": "Support", "name": "Support", @@ -48,17 +52,17 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Issue", "link_to": "Issue", "type": "DocType" }, { - "is_query_report": 0, + "label": "Service Level", "link_to": "Service Level", "type": "DocType" }, { - "is_query_report": 0, + "label": "Maintenance Visit", "link_to": "Maintenance Visit", "type": "DocType" } diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json index 6641f56d18..c12cef4a5f 100644 --- a/erpnext/support/doctype/issue/issue.json +++ b/erpnext/support/doctype/issue/issue.json @@ -6,6 +6,7 @@ "creation": "2013-02-01 10:36:25", "doctype": "DocType", "document_type": "Setup", + "email_append_to": 1, "engine": "InnoDB", "field_order": [ "subject_section", @@ -366,7 +367,7 @@ "icon": "fa fa-ticket", "idx": 7, "links": [], - "modified": "2020-02-26 02:19:49.477928", + "modified": "2020-03-13 02:19:49.477928", "modified_by": "Administrator", "module": "Support", "name": "Issue", @@ -386,8 +387,10 @@ ], "quick_entry": 1, "search_fields": "status,customer,subject,raised_by", + "sender_field": "raised_by", "sort_field": "modified", "sort_order": "DESC", + "subject_field": "subject", "timeline_field": "customer", "title_field": "subject", "track_changes": 1, diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 1ca6de48cb..fd72807418 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -14,9 +14,6 @@ from frappe.utils.user import is_website_user from erpnext.support.doctype.service_level_agreement.service_level_agreement import get_active_service_level_agreement_for from frappe.email.inbox import link_communication_to_document -sender_field = "raised_by" - - class Issue(Document): def get_feed(self): return "{0}: {1}".format(_(self.status), self.subject) diff --git a/erpnext/support/web_form/issues/issues.json b/erpnext/support/web_form/issues/issues.json index 9b904ad796..0f15e4737f 100644 --- a/erpnext/support/web_form/issues/issues.json +++ b/erpnext/support/web_form/issues/issues.json @@ -18,7 +18,7 @@ "is_standard": 1, "login_required": 1, "max_attachment_size": 0, - "modified": "2019-12-10 13:48:19.894186", + "modified": "2020-03-06 05:24:05.749664", "modified_by": "Administrator", "module": "Support", "name": "issues", @@ -58,7 +58,7 @@ "options": "Open\nReplied\nHold\nClosed", "read_only": 1, "reqd": 0, - "show_in_filter": 0 + "show_in_filter": 1 }, { "allow_read_on_all_link_options": 0, diff --git a/erpnext/templates/includes/cart.js b/erpnext/templates/includes/cart.js index 456bc7e413..c6dfd35e29 100644 --- a/erpnext/templates/includes/cart.js +++ b/erpnext/templates/includes/cart.js @@ -26,15 +26,14 @@ $.extend(shopping_cart, { bind_address_select: function() { $(".cart-addresses").on('click', '.address-card', function(e) { const $card = $(e.currentTarget); - const address_fieldname = $card.closest('[data-fieldname]').attr('data-fieldname'); + const address_type = $card.closest('[data-address-type]').attr('data-address-type'); const address_name = $card.closest('[data-address-name]').attr('data-address-name'); - return frappe.call({ type: "POST", method: "erpnext.shopping_cart.cart.update_cart_address", freeze: true, args: { - address_fieldname, + address_type, address_name }, callback: function(r) { diff --git a/erpnext/templates/includes/cart/cart_address.html b/erpnext/templates/includes/cart/cart_address.html index f7f3548320..60de3af17b 100644 --- a/erpnext/templates/includes/cart/cart_address.html +++ b/erpnext/templates/includes/cart/cart_address.html @@ -18,7 +18,7 @@
{{ _("Shipping Address") }}
{% for address in shipping_addresses %} -
+
{% include "templates/includes/cart/address_card.html" %}
{% endfor %} @@ -28,7 +28,7 @@
{{ _("Billing Address") }}
{% for address in billing_addresses %} -
+
{% include "templates/includes/cart/address_card.html" %}
{% endfor %} @@ -123,9 +123,19 @@ frappe.ready(() => { primary_action: (values) => { frappe.call('erpnext.shopping_cart.cart.add_new_address', { doc: values }) .then(r => { - d.hide(); - window.location.reload(); + frappe.call({ + method: "erpnext.shopping_cart.cart.update_cart_address", + args: { + address_type: r.message.address_type, + address_name: r.message.name + }, + callback: function (r) { + d.hide(); + window.location.reload(); + } + }); }); + } }) diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html index 4a32aa4744..ebec838d03 100644 --- a/erpnext/templates/includes/order/order_taxes.html +++ b/erpnext/templates/includes/order/order_taxes.html @@ -10,16 +10,16 @@ {% endif %} {% for d in doc.taxes %} -{% if d.base_tax_amount > 0 %} - - - {{ d.description }} - - - {{ d.get_formatted("base_tax_amount") }} - - -{% endif %} + {% if d.base_tax_amount %} + + + {{ d.description }} + + + {{ d.get_formatted("base_tax_amount") }} + + + {% endif %} {% endfor %} {% if doc.doctype == 'Quotation' %} diff --git a/erpnext/templates/pages/cart.html b/erpnext/templates/pages/cart.html index 912702e386..3033d1587d 100644 --- a/erpnext/templates/pages/cart.html +++ b/erpnext/templates/pages/cart.html @@ -12,16 +12,6 @@ {% block header_actions %} -{% if doc.items and cart_settings.enable_checkout %} - -{% endif %} -{% if doc.items and not cart_settings.enable_checkout %} - -{% endif %} {% endblock %} {% block page_content %} @@ -55,6 +45,20 @@

{{ _('Your cart is Empty') }}

{% endif %} + {% if doc.items %} +
+ {% if cart_settings.enable_checkout %} + + {% else %} + + {% endif %} +
+ {% endif %} + {% if doc.items %} {% if doc.tc_name %}
-

{{ content.name }} ({{ position + 1 }}/{{length}})

+

{{ content.name }} ({{ position + 1 }}/{{length}})

{% endmacro %} diff --git a/yarn.lock b/yarn.lock index 9b315180fe..c5509d6e1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1133,9 +1133,9 @@ minimatch@^3.0.4: brace-expansion "^1.1.7" minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== ms@2.0.0: version "2.0.0"