Merge branch 'develop' into rename-bank-reco
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000..5e1113d
--- /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/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index d0b747d..8a9a7c5 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]"
},
{
+ "hidden": 0,
"links": "[\n {\n \"description\": \"Match non-linked Invoices and Payments.\",\n \"label\": \"Match Payments with Invoices\",\n \"name\": \"Payment Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update bank payment dates with journals.\",\n \"label\": \"Update Bank Clearance Dates\",\n \"name\": \"Bank Clearance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Invoice Discounting\",\n \"name\": \"Invoice Discounting\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Reconciliation Statement\",\n \"name\": \"Bank Reconciliation Statement\",\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Bank Reconciliation\",\n \"name\": \"bank-reconciliation\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Clearance Summary\",\n \"name\": \"Bank Clearance Summary\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Bank Guarantee\",\n \"name\": \"Bank Guarantee\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup cheque dimensions for printing\",\n \"label\": \"Cheque Print Template\",\n \"name\": \"Cheque Print Template\",\n \"type\": \"doctype\"\n }\n]",
"title": "Banking and Payments"
},
{
- "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 0a72d4f..c6de641 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -89,7 +89,7 @@
throw(_("Root cannot be edited."), RootNotEditable)
if not self.parent_account and not self.is_group:
- frappe.throw(_("Root Account must be a group"))
+ frappe.throw(_("The root account {0} must be a group").format(frappe.bold(self.name)))
def validate_root_company_and_sync_account_to_children(self):
# ignore validation while creating new compnay or while syncing to child companies
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index efac1af..f62d076 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/test_account.py b/erpnext/accounts/doctype/account/test_account.py
index dc23b2b..89bb018 100644
--- a/erpnext/accounts/doctype/account/test_account.py
+++ b/erpnext/accounts/doctype/account/test_account.py
@@ -69,6 +69,7 @@
acc.account_name = "Accumulated Depreciation"
acc.parent_account = "Fixed Assets - _TC"
acc.company = "_Test Company"
+ acc.account_type = "Accumulated Depreciation"
acc.insert()
doc = frappe.get_doc("Account", "Securities and Deposits - _TC")
@@ -149,7 +150,7 @@
# fixed asset depreciation
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
- ["_Test Accumulated Depreciations", "Current Assets", 0, None, None],
+ ["_Test Accumulated Depreciations", "Current Assets", 0, "Accumulated Depreciation", None],
["_Test Depreciations", "Expenses", 0, None, None],
["_Test Gain/Loss on Asset Disposal", "Expenses", 0, None, None],
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 462d967..14fdffc 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -193,7 +193,7 @@
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/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index b6f5396..e1b331b 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -152,10 +152,9 @@
return [parent_account]
elif account_name == child:
parent_account_list = return_parent(data, parent_account)
- if not parent_account_list:
+ if not parent_account_list and parent_account:
frappe.throw(_("The parent account {0} does not exists in the uploaded template").format(
frappe.bold(parent_account)))
-
return [child] + parent_account_list
charts_map, paths = {}, []
@@ -164,7 +163,7 @@
error_messages = []
for i in data:
- account_name, _, account_number, is_group, account_type, root_type = i
+ account_name, dummy, account_number, is_group, account_type, root_type = i
if not account_name:
error_messages.append("Row {0}: Please enter Account Name".format(line_no))
diff --git a/erpnext/accounts/doctype/cost_center/cost_center_tree.js b/erpnext/accounts/doctype/cost_center/cost_center_tree.js
index 16d9734..fde4123 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/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index d208087..b7c97a7 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -156,8 +156,11 @@
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))
@@ -501,6 +504,7 @@
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) {
@@ -524,6 +528,7 @@
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 55d2758..a453e95 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -81,7 +81,12 @@
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 d6d4946..d12e474 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.js
+++ b/erpnext/accounts/doctype/payment_order/payment_order.js
@@ -15,11 +15,11 @@
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 2e12ad3..2ed0a4a 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 c1559a7..97ae5ff 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.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.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": "<pre><h5>Message Example</h5>\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</pre>\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": "<pre><h5>Message Example</h5>\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</pre>\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 7e9211a..53ff222 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -66,6 +66,8 @@
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 @@
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()
@@ -415,17 +418,31 @@
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 0caf1c2..72833d2 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 @@
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 188ab0a..8a10e2c 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 @@
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/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index 2ffa27f..100bb1d 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -178,7 +178,8 @@
if pricing_rules[0].mixed_conditions and doc:
stock_qty, amount, items = get_qty_and_rate_for_mixed_conditions(doc, pr_doc, args)
- pricing_rules[0].apply_rule_on_other_items = items
+ for pricing_rule_args in pricing_rules:
+ pricing_rule_args.apply_rule_on_other_items = items
elif pricing_rules[0].is_cumulative:
items = [args.get(frappe.scrub(pr_doc.get('apply_on')))]
@@ -329,9 +330,9 @@
if pr_doc.mixed_conditions:
amt = args.get('qty') * args.get("price_list_rate")
if args.get("item_code") != row.get("item_code"):
- amt = row.get('qty') * row.get("price_list_rate")
+ amt = row.get('qty') * (row.get("price_list_rate") or args.get("rate"))
- sum_qty += row.get("stock_qty") or args.get("stock_qty")
+ sum_qty += row.get("stock_qty") or args.get("stock_qty") or args.get("qty")
sum_amt += amt
if pr_doc.is_cumulative:
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index c5c5483..9292b63 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -174,7 +174,8 @@
read_only: 0,
fieldtype:'Date',
label: __('Release Date'),
- default: me.frm.doc.release_date
+ default: me.frm.doc.release_date,
+ reqd: 1
},
{
fieldname: 'hold_comment',
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 3cd988c..3af236c 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -73,9 +73,9 @@
"base_total",
"base_net_total",
"column_break_28",
+ "total_net_weight",
"total",
"net_total",
- "total_net_weight",
"taxes_section",
"tax_category",
"column_break_49",
@@ -1298,7 +1298,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2019-12-30 19:13:49.610538",
+ "modified": "2020-04-17 13:05:25.199832",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
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 9c97426..db3f72a 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -754,8 +754,7 @@
{
"fieldname": "manufacturer_part_no",
"fieldtype": "Data",
- "label": "Manufacturer Part Number",
- "read_only": 1
+ "label": "Manufacturer Part Number"
},
{
"depends_on": "is_fixed_asset",
@@ -777,7 +776,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-04-01 14:20:17.297284",
+ "modified": "2020-04-07 18:34:35.104178",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index db6ac55..6f78db2 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -794,7 +794,7 @@
},
refresh: function(frm) {
- if (frappe.boot.active_domains.includes("Healthcare")){
+ if (frappe.boot.active_domains.includes("Healthcare")) {
frm.set_df_property("patient", "hidden", 0);
frm.set_df_property("patient_name", "hidden", 0);
frm.set_df_property("ref_practitioner", "hidden", 0);
@@ -807,7 +807,7 @@
},"Get items from");
}
}
- else{
+ else {
frm.set_df_property("patient", "hidden", 1);
frm.set_df_property("patient_name", "hidden", 1);
frm.set_df_property("ref_practitioner", "hidden", 1);
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index e239f91..918fa14 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-24 19:29:05",
@@ -74,9 +75,9 @@
"base_total",
"base_net_total",
"column_break_32",
+ "total_net_weight",
"total",
"net_total",
- "total_net_weight",
"taxes_section",
"taxes_and_charges",
"column_break_38",
@@ -1577,7 +1578,8 @@
"icon": "fa fa-file-text",
"idx": 181,
"is_submittable": 1,
- "modified": "2020-02-10 04:57:11.221180",
+ "links": [],
+ "modified": "2020-04-17 12:38:41.435728",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 82aedb6..3c40112 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -440,11 +440,12 @@
if pos.get("company_address"):
self.company_address = pos.get("company_address")
- 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 self.customer:
+ 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')
+ else:
+ selling_price_list = pos.get('selling_price_list')
if selling_price_list:
self.set('selling_price_list', selling_price_list)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 3d5ce8a..a2819af 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -1948,7 +1948,7 @@
"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 1fd340c..b2638c7 100644
--- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
+++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
@@ -82,7 +82,7 @@
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 4cfeb25..47dfa09 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -162,8 +162,9 @@
def set_price_list(party_details, party, party_type, given_price_list, pos=None):
# price list
price_list = get_permitted_documents('Price List')
-
- if price_list:
+
+ # if there is only one permitted document based on user permissions, set it
+ if price_list and len(price_list) == 1:
price_list = price_list[0]
elif pos and party_type == 'Customer':
customer_price_list = frappe.get_value('Customer', party.name, 'default_price_list')
@@ -635,4 +636,4 @@
except:
return None
else:
- return None
\ No newline at end of file
+ return None
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py
index cb1fdc1..a858c19 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.py
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py
@@ -9,6 +9,7 @@
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")
diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js
index 904874f..e5d0c89 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.js
+++ b/erpnext/accounts/report/cash_flow/cash_flow.js
@@ -9,7 +9,7 @@
// 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(
{
diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py
index be6e93c..cf0946b 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.py
+++ b/erpnext/accounts/report/cash_flow/cash_flow.py
@@ -17,7 +17,8 @@
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()
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 92c5ee9..38fd5fa 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
@@ -13,6 +13,39 @@
"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"),
"fieldtype": "Link",
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 461291b..b62238b 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -4,7 +4,7 @@
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,
@@ -208,17 +208,24 @@
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)
@@ -229,7 +236,7 @@
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
@@ -241,7 +248,7 @@
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):
@@ -295,10 +302,8 @@
`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
@@ -309,8 +314,8 @@
"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 e760b79..7fb598b 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -18,17 +18,20 @@
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 @@
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 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)
@@ -419,7 +434,9 @@
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.html b/erpnext/accounts/report/general_ledger/general_ledger.html
index 9a2205a..378fa37 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.html
+++ b/erpnext/accounts/report/general_ledger/general_ledger.html
@@ -2,7 +2,7 @@
<h4 class="text-center">
{% if (filters.party_name) { %}
{%= filters.party_name %}
- {% } else if (filters.party) { %}
+ {% } else if (filters.party && filters.party.length) { %}
{%= filters.party %}
{% } else if (filters.account) { %}
{%= filters.account %}
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 898ac13..f776d93 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -202,7 +202,9 @@
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 ""
@@ -363,6 +365,7 @@
columns = [
{
+ "label": _("GL Entry"),
"fieldname": "gl_entry",
"fieldtype": "Link",
"options": "GL Entry",
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 81fb1e0..7caa764 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 @@
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,
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.js b/erpnext/accounts/report/purchase_register/purchase_register.js
index 42b35c2..b2b95b2 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.js
+++ b/erpnext/accounts/report/purchase_register/purchase_register.js
@@ -34,6 +34,33 @@
"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 3f8abb7..9399e70 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -5,6 +5,7 @@
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 @@
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 @@
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 9864e40..b6e61b1 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -344,16 +344,19 @@
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 5fe6b41..d783241 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.py
+++ b/erpnext/accounts/report/trial_balance/trial_balance.py
@@ -126,7 +126,9 @@
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 6020d62..e0d2c9c 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 f9c65cb..0309416 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/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index fc08841..9bf4df4 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -11,12 +11,34 @@
class AssetCategory(Document):
def validate(self):
self.validate_finance_books()
+ self.validate_accounts()
def validate_finance_books(self):
for d in self.finance_books:
for field in ("Total Number of Depreciations", "Frequency of Depreciation"):
if cint(d.get(frappe.scrub(field)))<1:
frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError)
+
+ def validate_accounts(self):
+ account_type_map = {
+ 'fixed_asset_account': { 'account_type': 'Fixed Asset' },
+ 'accumulated_depreciation_account': { 'account_type': 'Accumulated Depreciation' },
+ 'depreciation_expense_account': { 'root_type': 'Expense' },
+ 'capital_work_in_progress_account': { 'account_type': 'Capital Work in Progress' }
+ }
+ for d in self.accounts:
+ for fieldname in account_type_map.keys():
+ if d.get(fieldname):
+ selected_account = d.get(fieldname)
+ key_to_match = next(iter(account_type_map.get(fieldname))) # acount_type or root_type
+ selected_key_type = frappe.db.get_value('Account', selected_account, key_to_match)
+ expected_key_type = account_type_map[fieldname][key_to_match]
+
+ if selected_key_type != expected_key_type:
+ frappe.throw(_("Row #{}: {} of {} should be {}. Please modify the account or select a different account.")
+ .format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)),
+ title=_("Invalid Account"))
+
@frappe.whitelist()
def get_asset_category_account(fieldname, item=None, asset=None, account=None, asset_category = None, company = None):
diff --git a/erpnext/buying/desk_page/buying/buying.json b/erpnext/buying/desk_page/buying/buying.json
index ae8a605..5e764cf 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.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 4d83690..578858c 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-21 16:16:39",
@@ -63,9 +64,9 @@
"base_total",
"base_net_total",
"column_break_26",
+ "total_net_weight",
"total",
"net_total",
- "total_net_weight",
"taxes_section",
"tax_category",
"column_break_50",
@@ -170,8 +171,8 @@
"search_index": 1
},
{
- "description": "Fetch items based on Default Supplier.",
"depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))",
+ "description": "Fetch items based on Default Supplier.",
"fieldname": "get_items_from_open_material_requests",
"fieldtype": "Button",
"label": "Get Items from Open Material Requests"
@@ -1054,7 +1055,8 @@
"icon": "fa fa-file-text",
"idx": 105,
"is_submittable": 1,
- "modified": "2020-01-14 18:54:39.694448",
+ "links": [],
+ "modified": "2020-04-17 13:04:28.185197",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 6768dfa..e37e1dd 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -702,8 +702,7 @@
{
"fieldname": "manufacturer_part_no",
"fieldtype": "Data",
- "label": "Manufacturer Part Number",
- "read_only": 1
+ "label": "Manufacturer Part Number"
},
{
"default": "0",
@@ -723,7 +722,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2019-12-06 13:17:12.142799",
+ "modified": "2020-04-07 18:35:17.558928",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",
diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
index 7d7d6f4..b50e834 100644
--- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
+++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "hash",
"creation": "2013-05-22 12:43:10",
"doctype": "DocType",
@@ -522,8 +523,7 @@
{
"fieldname": "manufacturer_part_no",
"fieldtype": "Data",
- "label": "Manufacturer Part Number",
- "read_only": 1
+ "label": "Manufacturer Part Number"
},
{
"fieldname": "column_break_15",
@@ -532,7 +532,8 @@
],
"idx": 1,
"istable": 1,
- "modified": "2019-06-02 05:32:46.019237",
+ "links": [],
+ "modified": "2020-04-07 18:35:51.175947",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",
diff --git a/erpnext/config/healthcare.py b/erpnext/config/healthcare.py
index 756d22e..2b46127 100644
--- a/erpnext/config/healthcare.py
+++ b/erpnext/config/healthcare.py
@@ -2,120 +2,27 @@
from frappe import _
def get_data():
-
return [
{
- "label": _("Consultation"),
- "icon": "icon-star",
- "items": [
- {
- "type": "doctype",
- "name": "Patient Appointment",
- "label": _("Patient Appointment"),
- },
- {
- "type": "doctype",
- "name": "Patient Encounter",
- "label": _("Patient Encounter"),
- },
- {
- "type": "doctype",
- "name": "Vital Signs",
- "label": _("Vital Signs"),
- "description": _("Record Patient Vitals"),
- },
- {
- "type": "page",
- "name": "patient_history",
- "label": _("Patient History"),
- },
- {
- "type": "page",
- "name": "appointment-analytic",
- "label": _("Appointment Analytics"),
- },
- {
- "type": "doctype",
- "name": "Clinical Procedure",
- "label": _("Clinical Procedure"),
- },
- {
- "type": "doctype",
- "name": "Inpatient Record",
- "label": _("Inpatient Record"),
- }
- ]
- },
- {
- "label": _("Laboratory"),
- "icon": "icon-list",
- "items": [
- {
- "type": "doctype",
- "name": "Lab Test",
- "label": _("Lab Test"),
- },
- {
- "type": "doctype",
- "name": "Sample Collection",
- "label": _("Sample Collection"),
- },
- {
- "type": "report",
- "name": "Lab Test Report",
- "is_query_report": True,
- "label": _("Lab Test Report"),
- }
- ]
- },
- {
"label": _("Masters"),
- "icon": "icon-list",
"items": [
{
"type": "doctype",
"name": "Patient",
"label": _("Patient"),
- "onboard": 1,
+ "onboard": 1
},
{
"type": "doctype",
"name": "Healthcare Practitioner",
"label": _("Healthcare Practitioner"),
- "onboard": 1,
+ "onboard": 1
},
{
"type": "doctype",
"name": "Practitioner Schedule",
"label": _("Practitioner Schedule"),
- },
- {
- "type": "doctype",
- "name": "Medical Code Standard",
- "label": _("Medical Code Standard"),
- },
- {
- "type": "doctype",
- "name": "Medical Code",
- "label": _("Medical Code"),
- "onboard": 1,
- },
- {
- "type": "doctype",
- "name": "Healthcare Service Unit",
- "label": _("Healthcare Service Unit")
- }
- ]
- },
- {
- "label": _("Settings"),
- "icon": "icon-cog",
- "items": [
- {
- "type": "doctype",
- "name": "Healthcare Settings",
- "label": _("Healthcare Settings"),
- "onboard": 1,
+ "onboard": 1
},
{
"type": "doctype",
@@ -124,11 +31,41 @@
},
{
"type": "doctype",
+ "name": "Healthcare Service Unit Type",
+ "label": _("Healthcare Service Unit Type")
+ },
+ {
+ "type": "doctype",
+ "name": "Healthcare Service Unit",
+ "label": _("Healthcare Service Unit")
+ },
+ {
+ "type": "doctype",
+ "name": "Medical Code Standard",
+ "label": _("Medical Code Standard")
+ },
+ {
+ "type": "doctype",
+ "name": "Medical Code",
+ "label": _("Medical Code")
+ }
+ ]
+ },
+ {
+ "label": _("Consultation Setup"),
+ "items": [
+ {
+ "type": "doctype",
"name": "Appointment Type",
"label": _("Appointment Type"),
},
{
"type": "doctype",
+ "name": "Clinical Procedure Template",
+ "label": _("Clinical Procedure Template")
+ },
+ {
+ "type": "doctype",
"name": "Prescription Dosage",
"label": _("Prescription Dosage")
},
@@ -139,6 +76,36 @@
},
{
"type": "doctype",
+ "name": "Antibiotic",
+ "label": _("Antibiotic")
+ }
+ ]
+ },
+ {
+ "label": _("Consultation"),
+ "items": [
+ {
+ "type": "doctype",
+ "name": "Patient Appointment",
+ "label": _("Patient Appointment")
+ },
+ {
+ "type": "doctype",
+ "name": "Clinical Procedure",
+ "label": _("Clinical Procedure")
+ },
+ {
+ "type": "doctype",
+ "name": "Patient Encounter",
+ "label": _("Patient Encounter")
+ },
+ {
+ "type": "doctype",
+ "name": "Vital Signs",
+ "label": _("Vital Signs")
+ },
+ {
+ "type": "doctype",
"name": "Complaint",
"label": _("Complaint")
},
@@ -149,8 +116,34 @@
},
{
"type": "doctype",
+ "name": "Fee Validity",
+ "label": _("Fee Validity")
+ }
+ ]
+ },
+ {
+ "label": _("Settings"),
+ "items": [
+ {
+ "type": "doctype",
+ "name": "Healthcare Settings",
+ "label": _("Healthcare Settings"),
+ "onboard": 1
+ }
+ ]
+ },
+ {
+ "label": _("Laboratory Setup"),
+ "items": [
+ {
+ "type": "doctype",
+ "name": "Lab Test Template",
+ "label": _("Lab Test Template")
+ },
+ {
+ "type": "doctype",
"name": "Lab Test Sample",
- "label": _("Lab Test Sample"),
+ "label": _("Lab Test Sample")
},
{
"type": "doctype",
@@ -159,28 +152,66 @@
},
{
"type": "doctype",
- "name": "Antibiotic",
- "label": _("Antibiotic")
- },
- {
- "type": "doctype",
"name": "Sensitivity",
"label": _("Sensitivity")
+ }
+ ]
+ },
+ {
+ "label": _("Laboratory"),
+ "items": [
+ {
+ "type": "doctype",
+ "name": "Lab Test",
+ "label": _("Lab Test")
},
{
"type": "doctype",
- "name": "Lab Test Template",
- "label": _("Lab Test Template")
+ "name": "Sample Collection",
+ "label": _("Sample Collection")
},
{
"type": "doctype",
- "name": "Clinical Procedure Template",
- "label": _("Clinical Procedure Template"),
+ "name": "Dosage Form",
+ "label": _("Dosage Form")
+ }
+ ]
+ },
+ {
+ "label": _("Records and History"),
+ "items": [
+ {
+ "type": "page",
+ "name": "patient_history",
+ "label": _("Patient History"),
},
{
"type": "doctype",
- "name": "Healthcare Service Unit Type",
- "label": _("Healthcare Service Unit Type")
+ "name": "Patient Medical Record",
+ "label": _("Patient Medical Record")
+ },
+ {
+ "type": "doctype",
+ "name": "Inpatient Record",
+ "label": _("Inpatient Record")
+ }
+ ]
+ },
+ {
+ "label": _("Reports"),
+ "items": [
+ {
+ "type": "report",
+ "is_query_report": True,
+ "name": "Patient Appointment Analytics",
+ "doctype": "Patient Appointment"
+ },
+ {
+ "type": "report",
+ "is_query_report": True,
+ "name": "Lab Test Report",
+ "doctype": "Lab Test",
+ "label": _("Lab Test Report")
}
]
}
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 76eb56f..4045250 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -439,7 +439,7 @@
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, ""]]}))
@@ -834,7 +834,7 @@
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)
@@ -1123,36 +1123,39 @@
}
return info
-def set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_code):
+def set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, trans_item):
"""
Returns a Sales Order Item child item containing the default values
"""
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)
+ item = frappe.get_doc("Item", trans_item.get('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_doc.delivery_date
+ child_item.delivery_date = trans_item.get('delivery_date') or 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.conversion_factor = get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True)
+ if not child_item.warehouse:
+ frappe.throw(_("Cannot find {} for item {}. Please set the same in Item Master or Stock Settings.")
+ .format(frappe.bold("default warehouse"), frappe.bold(item.item_code)))
return child_item
-def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_code):
+def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, trans_item):
"""
Returns a Purchase Order Item child item containing the default values
"""
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)
+ item = frappe.get_doc("Item", trans_item.get('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_doc.schedule_date
+ child_item.schedule_date = trans_item.get('schedule_date') or 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.conversion_factor = get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.base_rate = 1 # Initiallize value will update in parent validation
child_item.base_amount = 1 # Initiallize value will update in parent validation
return child_item
@@ -1196,9 +1199,9 @@
if not d.get("docname"):
new_child_flag = True
if parent_doctype == "Sales Order":
- child_item = set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, d.get("item_code"))
+ child_item = set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, d)
if parent_doctype == "Purchase Order":
- child_item = set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, d.get("item_code"))
+ child_item = set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, d)
else:
child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
if flt(child_item.get("rate")) == flt(d.get("rate")) and flt(child_item.get("qty")) == flt(d.get("qty")):
@@ -1243,6 +1246,7 @@
child_item.flags.ignore_validate_update_after_submit = True
if new_child_flag:
+ parent.load_from_db()
child_item.idx = len(parent.items) + 1
child_item.insert()
else:
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index fcc9098..0e72ec2 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -45,6 +45,7 @@
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 @@
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']:
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 4d0520a..de76e45 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -69,16 +69,16 @@
["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 f6908c0..55a2c43 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -21,6 +21,7 @@
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,12 @@
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
+
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/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 95e661a..4e568e2 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -667,8 +667,7 @@
itemised_tax=itemised_tax,
itemised_taxable_amount=itemised_taxable_amount,
tax_accounts=tax_accounts,
- conversion_rate=doc.conversion_rate,
- currency=doc.currency
+ doc=doc
)
)
diff --git a/erpnext/crm/desk_page/crm/crm.json b/erpnext/crm/desk_page/crm/crm.json
index 9ebbe27..4a599fe 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 b3197ae..20ab51d 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -1,12 +1,10 @@
{
- "actions": [],
"allow_events_in_timeline": 1,
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-04-10 11:45:37",
"doctype": "DocType",
"document_type": "Document",
- "email_append_to": 1,
"engine": "InnoDB",
"field_order": [
"organization_lead",
@@ -34,6 +32,7 @@
"notes",
"address_info",
"address_html",
+ "address_type",
"address_title",
"address_line1",
"address_line2",
@@ -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": "2020-01-13 16:16:48.885228",
+ "modified": "2020-04-08 22:26:11.687110",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead",
@@ -508,9 +516,8 @@
}
],
"search_fields": "lead_name,lead_owner,status",
- "sender_field": "email_id",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "title"
-}
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index 985abfb..74b3582 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -126,7 +126,7 @@
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"]
@@ -209,7 +209,7 @@
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 98a350a..6a54c5f 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -423,7 +423,7 @@
"icon": "fa fa-info-sign",
"idx": 195,
"links": [],
- "modified": "2020-03-20 12:28:45.228994",
+ "modified": "2020-04-07 09:05:39.391109",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index 5e640e7..1b071ea 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -336,3 +336,27 @@
link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links)
return opportunity.name
+@frappe.whitelist()
+def get_events(start, end, filters=None):
+ """Returns events for Gantt / Calendar view rendering.
+ :param start: Start date-time.
+ :param end: End date-time.
+ :param filters: Filters (JSON).
+ """
+ from frappe.desk.calendar import get_event_conditions
+ conditions = get_event_conditions("Opportunity", filters)
+
+ data = frappe.db.sql("""
+ select
+ distinct `tabOpportunity`.name, `tabOpportunity`.customer_name, `tabOpportunity`.opportunity_amount,
+ `tabOpportunity`.title, `tabOpportunity`.contact_date
+ from
+ `tabOpportunity`
+ where
+ (`tabOpportunity`.contact_date between %(start)s and %(end)s)
+ {conditions}
+ """.format(conditions=conditions), {
+ "start": start,
+ "end": end
+ }, as_dict=True, update={"allDay": 0})
+ return data
\ No newline at end of file
diff --git a/erpnext/crm/doctype/opportunity/opportunity_calendar.js b/erpnext/crm/doctype/opportunity/opportunity_calendar.js
new file mode 100644
index 0000000..58fa2b8
--- /dev/null
+++ b/erpnext/crm/doctype/opportunity/opportunity_calendar.js
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+frappe.views.calendar["Opportunity"] = {
+ field_map: {
+ "start": "contact_date",
+ "end": "contact_date",
+ "id": "name",
+ "title": "customer_name",
+ "allDay": "allDay"
+ },
+ options: {
+ header: {
+ left: 'prev,next today',
+ center: 'title',
+ right: 'month'
+ }
+ },
+ get_events_method: 'erpnext.crm.doctype.opportunity.opportunity.get_events'
+}
diff --git a/erpnext/education/desk_page/education/education.json b/erpnext/education/desk_page/education/education.json
index bbd8ead..fc2697f 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/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 c2ac0d7..5bebd43 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 @@
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 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 @@
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/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
index 3bc8db5..cc75a0a 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 @@
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 9925dc4..f713684 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 @@
# 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 607ca4f..5a678e7 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 c222afb..899b7ff 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 @@
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 @@
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/erpnext_integrations/doctype/tally_migration/tally_migration.js b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.js
index 104ac57..d84c823 100644
--- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.js
+++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.js
@@ -2,15 +2,40 @@
// For license information, please see license.txt
frappe.ui.form.on('Tally Migration', {
- onload: function(frm) {
+ onload: function (frm) {
+ let reload_status = true;
frappe.realtime.on("tally_migration_progress_update", function (data) {
+ if (reload_status) {
+ frappe.model.with_doc(frm.doc.doctype, frm.doc.name, () => {
+ frm.refresh_header();
+ });
+ reload_status = false;
+ }
frm.dashboard.show_progress(data.title, (data.count / data.total) * 100, data.message);
- if (data.count == data.total) {
- window.setTimeout(title => frm.dashboard.hide_progress(title), 1500, data.title);
+ let error_occurred = data.count === -1;
+ if (data.count == data.total || error_occurred) {
+ window.setTimeout((title) => {
+ frm.dashboard.hide_progress(title);
+ frm.reload_doc();
+ if (error_occurred) {
+ frappe.msgprint({
+ message: __("An error has occurred during {0}. Check {1} for more details",
+ [
+ repl("<a href='#Form/Tally Migration/%(tally_document)s' class='variant-click'>%(tally_document)s</a>", {
+ tally_document: frm.docname
+ }),
+ "<a href='#List/Error Log' class='variant-click'>Error Log</a>"
+ ]
+ ),
+ title: __("Tally Migration Error"),
+ indicator: "red"
+ });
+ }
+ }, 2000, data.title);
}
});
},
- refresh: function(frm) {
+ refresh: function (frm) {
if (frm.doc.master_data && !frm.doc.is_master_data_imported) {
if (frm.doc.is_master_data_processed) {
if (frm.doc.status != "Importing Master Data") {
@@ -34,17 +59,17 @@
}
}
},
- add_button: function(frm, label, method) {
+ add_button: function (frm, label, method) {
frm.add_custom_button(
label,
- () => frm.call({
- doc: frm.doc,
- method: method,
- freeze: true,
- callback: () => {
- frm.remove_custom_button(label);
- }
- })
+ () => {
+ frm.call({
+ doc: frm.doc,
+ method: method,
+ freeze: true
+ });
+ frm.reload_doc();
+ }
);
}
});
diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.json b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.json
index 26415ca..dc6f093 100644
--- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.json
+++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"beta": 1,
"creation": "2019-02-01 14:27:09.485238",
"doctype": "DocType",
@@ -14,6 +15,7 @@
"tally_debtors_account",
"company_section",
"tally_company",
+ "default_uom",
"column_break_8",
"erpnext_company",
"processed_files_section",
@@ -43,6 +45,7 @@
"label": "Status"
},
{
+ "description": "Data exported from Tally that consists of the Chart of Accounts, Customers, Suppliers, Addresses, Items and UOMs",
"fieldname": "master_data",
"fieldtype": "Attach",
"in_list_view": 1,
@@ -50,6 +53,7 @@
},
{
"default": "Sundry Creditors",
+ "description": "Creditors Account set in Tally",
"fieldname": "tally_creditors_account",
"fieldtype": "Data",
"label": "Tally Creditors Account",
@@ -61,6 +65,7 @@
},
{
"default": "Sundry Debtors",
+ "description": "Debtors Account set in Tally",
"fieldname": "tally_debtors_account",
"fieldtype": "Data",
"label": "Tally Debtors Account",
@@ -72,6 +77,7 @@
"fieldtype": "Section Break"
},
{
+ "description": "Company Name as per Imported Tally Data",
"fieldname": "tally_company",
"fieldtype": "Data",
"label": "Tally Company",
@@ -82,9 +88,11 @@
"fieldtype": "Column Break"
},
{
+ "description": "Your Company set in ERPNext",
"fieldname": "erpnext_company",
"fieldtype": "Data",
- "label": "ERPNext Company"
+ "label": "ERPNext Company",
+ "read_only_depends_on": "eval:doc.is_master_data_processed == 1"
},
{
"fieldname": "processed_files_section",
@@ -155,24 +163,28 @@
"options": "Cost Center"
},
{
+ "default": "0",
"fieldname": "is_master_data_processed",
"fieldtype": "Check",
"label": "Is Master Data Processed",
"read_only": 1
},
{
+ "default": "0",
"fieldname": "is_day_book_data_processed",
"fieldtype": "Check",
"label": "Is Day Book Data Processed",
"read_only": 1
},
{
+ "default": "0",
"fieldname": "is_day_book_data_imported",
"fieldtype": "Check",
"label": "Is Day Book Data Imported",
"read_only": 1
},
{
+ "default": "0",
"fieldname": "is_master_data_imported",
"fieldtype": "Check",
"label": "Is Master Data Imported",
@@ -188,13 +200,23 @@
"fieldtype": "Column Break"
},
{
+ "description": "Day Book Data exported from Tally that consists of all historic transactions",
"fieldname": "day_book_data",
"fieldtype": "Attach",
"in_list_view": 1,
"label": "Day Book Data"
+ },
+ {
+ "default": "Unit",
+ "description": "UOM in case unspecified in imported data",
+ "fieldname": "default_uom",
+ "fieldtype": "Link",
+ "label": "Default UOM",
+ "options": "UOM"
}
],
- "modified": "2019-04-29 05:46:54.394967",
+ "links": [],
+ "modified": "2020-04-16 13:03:28.894919",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "Tally Migration",
diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
index 01eee5b..13474e1 100644
--- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
+++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
@@ -4,20 +4,23 @@
from __future__ import unicode_literals
-from decimal import Decimal
import json
import re
import traceback
import zipfile
+from decimal import Decimal
+
+from bs4 import BeautifulSoup as bs
+
import frappe
+from erpnext import encode_company_abbr
+from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
from frappe import _
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from frappe.model.document import Document
from frappe.model.naming import getseries, revert_series_if_last
from frappe.utils.data import format_datetime
-from bs4 import BeautifulSoup as bs
-from erpnext import encode_company_abbr
-from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
+
PRIMARY_ACCOUNT = "Primary"
VOUCHER_CHUNK_SIZE = 500
@@ -39,13 +42,15 @@
return string
master_file = frappe.get_doc("File", {"file_url": data_file})
+ master_file_path = master_file.get_full_path()
- with zipfile.ZipFile(master_file.get_full_path()) as zf:
- encoded_content = zf.read(zf.namelist()[0])
- try:
- content = encoded_content.decode("utf-8-sig")
- except UnicodeDecodeError:
- content = encoded_content.decode("utf-16")
+ if zipfile.is_zipfile(master_file_path):
+ with zipfile.ZipFile(master_file_path) as zf:
+ encoded_content = zf.read(zf.namelist()[0])
+ try:
+ content = encoded_content.decode("utf-8-sig")
+ except UnicodeDecodeError:
+ content = encoded_content.decode("utf-16")
master = bs(sanitize(emptify(content)), "xml")
collection = master.BODY.IMPORTDATA.REQUESTDATA
@@ -58,13 +63,14 @@
"file_name": key + ".json",
"attached_to_doctype": self.doctype,
"attached_to_name": self.name,
- "content": json.dumps(value)
+ "content": json.dumps(value),
+ "is_private": True
}).insert()
setattr(self, key, f.file_url)
def _process_master_data(self):
def get_company_name(collection):
- return collection.find_all("REMOTECMPINFO.LIST")[0].REMOTECMPNAME.string
+ return collection.find_all("REMOTECMPINFO.LIST")[0].REMOTECMPNAME.string.strip()
def get_coa_customers_suppliers(collection):
root_type_map = {
@@ -97,17 +103,17 @@
# If Ledger doesn't have PARENT field then don't create Account
# For example "Profit & Loss A/c"
if account.PARENT:
- yield account.PARENT.string, account["NAME"], 0
+ yield account.PARENT.string.strip(), account["NAME"], 0
def get_parent(account):
if account.PARENT:
- return account.PARENT.string
+ return account.PARENT.string.strip()
return {
("Yes", "No"): "Application of Funds (Assets)",
("Yes", "Yes"): "Expenses",
("No", "Yes"): "Income",
("No", "No"): "Source of Funds (Liabilities)",
- }[(account.ISDEEMEDPOSITIVE.string, account.ISREVENUE.string)]
+ }[(account.ISDEEMEDPOSITIVE.string.strip(), account.ISREVENUE.string.strip())]
def get_children_and_parent_dict(accounts):
children, parents = {}, {}
@@ -145,38 +151,38 @@
parties, addresses = [], []
for account in collection.find_all("LEDGER"):
party_type = None
- if account.NAME.string in customers:
+ if account.NAME.string.strip() in customers:
party_type = "Customer"
parties.append({
"doctype": party_type,
- "customer_name": account.NAME.string,
- "tax_id": account.INCOMETAXNUMBER.string if account.INCOMETAXNUMBER else None,
+ "customer_name": account.NAME.string.strip(),
+ "tax_id": account.INCOMETAXNUMBER.string.strip() if account.INCOMETAXNUMBER else None,
"customer_group": "All Customer Groups",
"territory": "All Territories",
"customer_type": "Individual",
})
- elif account.NAME.string in suppliers:
+ elif account.NAME.string.strip() in suppliers:
party_type = "Supplier"
parties.append({
"doctype": party_type,
- "supplier_name": account.NAME.string,
- "pan": account.INCOMETAXNUMBER.string if account.INCOMETAXNUMBER else None,
+ "supplier_name": account.NAME.string.strip(),
+ "pan": account.INCOMETAXNUMBER.string.strip() if account.INCOMETAXNUMBER else None,
"supplier_group": "All Supplier Groups",
"supplier_type": "Individual",
})
if party_type:
- address = "\n".join([a.string for a in account.find_all("ADDRESS")])
+ address = "\n".join([a.string.strip() for a in account.find_all("ADDRESS")])
addresses.append({
"doctype": "Address",
"address_line1": address[:140].strip(),
"address_line2": address[140:].strip(),
- "country": account.COUNTRYNAME.string if account.COUNTRYNAME else None,
- "state": account.LEDSTATENAME.string if account.LEDSTATENAME else None,
- "gst_state": account.LEDSTATENAME.string if account.LEDSTATENAME else None,
- "pin_code": account.PINCODE.string if account.PINCODE else None,
- "mobile": account.LEDGERPHONE.string if account.LEDGERPHONE else None,
- "phone": account.LEDGERPHONE.string if account.LEDGERPHONE else None,
- "gstin": account.PARTYGSTIN.string if account.PARTYGSTIN else None,
+ "country": account.COUNTRYNAME.string.strip() if account.COUNTRYNAME else None,
+ "state": account.LEDSTATENAME.string.strip() if account.LEDSTATENAME else None,
+ "gst_state": account.LEDSTATENAME.string.strip() if account.LEDSTATENAME else None,
+ "pin_code": account.PINCODE.string.strip() if account.PINCODE else None,
+ "mobile": account.LEDGERPHONE.string.strip() if account.LEDGERPHONE else None,
+ "phone": account.LEDGERPHONE.string.strip() if account.LEDGERPHONE else None,
+ "gstin": account.PARTYGSTIN.string.strip() if account.PARTYGSTIN else None,
"links": [{"link_doctype": party_type, "link_name": account["NAME"]}],
})
return parties, addresses
@@ -184,41 +190,50 @@
def get_stock_items_uoms(collection):
uoms = []
for uom in collection.find_all("UNIT"):
- uoms.append({"doctype": "UOM", "uom_name": uom.NAME.string})
+ uoms.append({"doctype": "UOM", "uom_name": uom.NAME.string.strip()})
items = []
for item in collection.find_all("STOCKITEM"):
+ stock_uom = item.BASEUNITS.string.strip() if item.BASEUNITS else self.default_uom
items.append({
"doctype": "Item",
- "item_code" : item.NAME.string,
- "stock_uom": item.BASEUNITS.string,
+ "item_code" : item.NAME.string.strip(),
+ "stock_uom": stock_uom.strip(),
"is_stock_item": 0,
"item_group": "All Item Groups",
"item_defaults": [{"company": self.erpnext_company}]
})
+
return items, uoms
+ try:
+ self.publish("Process Master Data", _("Reading Uploaded File"), 1, 5)
+ collection = self.get_collection(self.master_data)
+ company = get_company_name(collection)
+ self.tally_company = company
+ self.erpnext_company = company
- self.publish("Process Master Data", _("Reading Uploaded File"), 1, 5)
- collection = self.get_collection(self.master_data)
+ self.publish("Process Master Data", _("Processing Chart of Accounts and Parties"), 2, 5)
+ chart_of_accounts, customers, suppliers = get_coa_customers_suppliers(collection)
- company = get_company_name(collection)
- self.tally_company = company
- self.erpnext_company = company
+ self.publish("Process Master Data", _("Processing Party Addresses"), 3, 5)
+ parties, addresses = get_parties_addresses(collection, customers, suppliers)
- self.publish("Process Master Data", _("Processing Chart of Accounts and Parties"), 2, 5)
- chart_of_accounts, customers, suppliers = get_coa_customers_suppliers(collection)
- self.publish("Process Master Data", _("Processing Party Addresses"), 3, 5)
- parties, addresses = get_parties_addresses(collection, customers, suppliers)
- self.publish("Process Master Data", _("Processing Items and UOMs"), 4, 5)
- items, uoms = get_stock_items_uoms(collection)
- data = {"chart_of_accounts": chart_of_accounts, "parties": parties, "addresses": addresses, "items": items, "uoms": uoms}
- self.publish("Process Master Data", _("Done"), 5, 5)
+ self.publish("Process Master Data", _("Processing Items and UOMs"), 4, 5)
+ items, uoms = get_stock_items_uoms(collection)
+ data = {"chart_of_accounts": chart_of_accounts, "parties": parties, "addresses": addresses, "items": items, "uoms": uoms}
- self.dump_processed_data(data)
- self.is_master_data_processed = 1
- self.status = ""
- self.save()
+ self.publish("Process Master Data", _("Done"), 5, 5)
+ self.dump_processed_data(data)
+
+ self.is_master_data_processed = 1
+
+ except:
+ self.publish("Process Master Data", _("Process Failed"), -1, 5)
+ self.log()
+
+ finally:
+ self.set_status()
def publish(self, title, message, count, total):
frappe.publish_realtime("tally_migration_progress_update", {"title": title, "message": message, "count": count, "total": total})
@@ -256,7 +271,6 @@
except:
self.log(address)
-
def create_items_uoms(items_file_url, uoms_file_url):
uoms_file = frappe.get_doc("File", {"file_url": uoms_file_url})
for uom in json.loads(uoms_file.get_content()):
@@ -273,25 +287,35 @@
except:
self.log(item)
- self.publish("Import Master Data", _("Creating Company and Importing Chart of Accounts"), 1, 4)
- create_company_and_coa(self.chart_of_accounts)
- self.publish("Import Master Data", _("Importing Parties and Addresses"), 2, 4)
- create_parties_and_addresses(self.parties, self.addresses)
- self.publish("Import Master Data", _("Importing Items and UOMs"), 3, 4)
- create_items_uoms(self.items, self.uoms)
- self.publish("Import Master Data", _("Done"), 4, 4)
- self.status = ""
- self.is_master_data_imported = 1
- self.save()
+ try:
+ self.publish("Import Master Data", _("Creating Company and Importing Chart of Accounts"), 1, 4)
+ create_company_and_coa(self.chart_of_accounts)
+
+ self.publish("Import Master Data", _("Importing Parties and Addresses"), 2, 4)
+ create_parties_and_addresses(self.parties, self.addresses)
+
+ self.publish("Import Master Data", _("Importing Items and UOMs"), 3, 4)
+ create_items_uoms(self.items, self.uoms)
+
+ self.publish("Import Master Data", _("Done"), 4, 4)
+
+ self.is_master_data_imported = 1
+
+ except:
+ self.publish("Import Master Data", _("Process Failed"), -1, 5)
+ self.log()
+
+ finally:
+ self.set_status()
def _process_day_book_data(self):
def get_vouchers(collection):
vouchers = []
for voucher in collection.find_all("VOUCHER"):
- if voucher.ISCANCELLED.string == "Yes":
+ if voucher.ISCANCELLED.string.strip() == "Yes":
continue
inventory_entries = voucher.find_all("INVENTORYENTRIES.LIST") + voucher.find_all("ALLINVENTORYENTRIES.LIST") + voucher.find_all("INVENTORYENTRIESIN.LIST") + voucher.find_all("INVENTORYENTRIESOUT.LIST")
- if voucher.VOUCHERTYPENAME.string not in ["Journal", "Receipt", "Payment", "Contra"] and inventory_entries:
+ if voucher.VOUCHERTYPENAME.string.strip() not in ["Journal", "Receipt", "Payment", "Contra"] and inventory_entries:
function = voucher_to_invoice
else:
function = voucher_to_journal_entry
@@ -307,15 +331,15 @@
accounts = []
ledger_entries = voucher.find_all("ALLLEDGERENTRIES.LIST") + voucher.find_all("LEDGERENTRIES.LIST")
for entry in ledger_entries:
- account = {"account": encode_company_abbr(entry.LEDGERNAME.string, self.erpnext_company), "cost_center": self.default_cost_center}
- if entry.ISPARTYLEDGER.string == "Yes":
- party_details = get_party(entry.LEDGERNAME.string)
+ account = {"account": encode_company_abbr(entry.LEDGERNAME.string.strip(), self.erpnext_company), "cost_center": self.default_cost_center}
+ if entry.ISPARTYLEDGER.string.strip() == "Yes":
+ party_details = get_party(entry.LEDGERNAME.string.strip())
if party_details:
party_type, party_account = party_details
account["party_type"] = party_type
account["account"] = party_account
- account["party"] = entry.LEDGERNAME.string
- amount = Decimal(entry.AMOUNT.string)
+ account["party"] = entry.LEDGERNAME.string.strip()
+ amount = Decimal(entry.AMOUNT.string.strip())
if amount > 0:
account["credit_in_account_currency"] = str(abs(amount))
else:
@@ -324,21 +348,21 @@
journal_entry = {
"doctype": "Journal Entry",
- "tally_guid": voucher.GUID.string,
- "posting_date": voucher.DATE.string,
+ "tally_guid": voucher.GUID.string.strip(),
+ "posting_date": voucher.DATE.string.strip(),
"company": self.erpnext_company,
"accounts": accounts,
}
return journal_entry
def voucher_to_invoice(voucher):
- if voucher.VOUCHERTYPENAME.string in ["Sales", "Credit Note"]:
+ if voucher.VOUCHERTYPENAME.string.strip() in ["Sales", "Credit Note"]:
doctype = "Sales Invoice"
party_field = "customer"
account_field = "debit_to"
account_name = encode_company_abbr(self.tally_debtors_account, self.erpnext_company)
price_list_field = "selling_price_list"
- elif voucher.VOUCHERTYPENAME.string in ["Purchase", "Debit Note"]:
+ elif voucher.VOUCHERTYPENAME.string.strip() in ["Purchase", "Debit Note"]:
doctype = "Purchase Invoice"
party_field = "supplier"
account_field = "credit_to"
@@ -351,10 +375,10 @@
invoice = {
"doctype": doctype,
- party_field: voucher.PARTYNAME.string,
- "tally_guid": voucher.GUID.string,
- "posting_date": voucher.DATE.string,
- "due_date": voucher.DATE.string,
+ party_field: voucher.PARTYNAME.string.strip(),
+ "tally_guid": voucher.GUID.string.strip(),
+ "posting_date": voucher.DATE.string.strip(),
+ "due_date": voucher.DATE.string.strip(),
"items": get_voucher_items(voucher, doctype),
"taxes": get_voucher_taxes(voucher),
account_field: account_name,
@@ -375,15 +399,15 @@
for entry in inventory_entries:
qty, uom = entry.ACTUALQTY.string.strip().split()
items.append({
- "item_code": entry.STOCKITEMNAME.string,
- "description": entry.STOCKITEMNAME.string,
+ "item_code": entry.STOCKITEMNAME.string.strip(),
+ "description": entry.STOCKITEMNAME.string.strip(),
"qty": qty.strip(),
"uom": uom.strip(),
"conversion_factor": 1,
- "price_list_rate": entry.RATE.string.split("/")[0],
+ "price_list_rate": entry.RATE.string.strip().split("/")[0],
"cost_center": self.default_cost_center,
"warehouse": self.default_warehouse,
- account_field: encode_company_abbr(entry.find_all("ACCOUNTINGALLOCATIONS.LIST")[0].LEDGERNAME.string, self.erpnext_company),
+ account_field: encode_company_abbr(entry.find_all("ACCOUNTINGALLOCATIONS.LIST")[0].LEDGERNAME.string.strip(), self.erpnext_company),
})
return items
@@ -391,13 +415,13 @@
ledger_entries = voucher.find_all("ALLLEDGERENTRIES.LIST") + voucher.find_all("LEDGERENTRIES.LIST")
taxes = []
for entry in ledger_entries:
- if entry.ISPARTYLEDGER.string == "No":
- tax_account = encode_company_abbr(entry.LEDGERNAME.string, self.erpnext_company)
+ if entry.ISPARTYLEDGER.string.strip() == "No":
+ tax_account = encode_company_abbr(entry.LEDGERNAME.string.strip(), self.erpnext_company)
taxes.append({
"charge_type": "Actual",
"account_head": tax_account,
"description": tax_account,
- "tax_amount": entry.AMOUNT.string,
+ "tax_amount": entry.AMOUNT.string.strip(),
"cost_center": self.default_cost_center,
})
return taxes
@@ -408,15 +432,24 @@
elif frappe.db.exists({"doctype": "Customer", "customer_name": party}):
return "Customer", encode_company_abbr(self.tally_debtors_account, self.erpnext_company)
- self.publish("Process Day Book Data", _("Reading Uploaded File"), 1, 3)
- collection = self.get_collection(self.day_book_data)
- self.publish("Process Day Book Data", _("Processing Vouchers"), 2, 3)
- vouchers = get_vouchers(collection)
- self.publish("Process Day Book Data", _("Done"), 3, 3)
- self.dump_processed_data({"vouchers": vouchers})
- self.status = ""
- self.is_day_book_data_processed = 1
- self.save()
+ try:
+ self.publish("Process Day Book Data", _("Reading Uploaded File"), 1, 3)
+ collection = self.get_collection(self.day_book_data)
+
+ self.publish("Process Day Book Data", _("Processing Vouchers"), 2, 3)
+ vouchers = get_vouchers(collection)
+
+ self.publish("Process Day Book Data", _("Done"), 3, 3)
+ self.dump_processed_data({"vouchers": vouchers})
+
+ self.is_day_book_data_processed = 1
+
+ except:
+ self.publish("Process Day Book Data", _("Process Failed"), -1, 5)
+ self.log()
+
+ finally:
+ self.set_status()
def _import_day_book_data(self):
def create_fiscal_years(vouchers):
@@ -454,23 +487,31 @@
"currency": "INR"
}).insert()
- frappe.db.set_value("Account", encode_company_abbr(self.tally_creditors_account, self.erpnext_company), "account_type", "Payable")
- frappe.db.set_value("Account", encode_company_abbr(self.tally_debtors_account, self.erpnext_company), "account_type", "Receivable")
- frappe.db.set_value("Company", self.erpnext_company, "round_off_account", self.round_off_account)
+ try:
+ frappe.db.set_value("Account", encode_company_abbr(self.tally_creditors_account, self.erpnext_company), "account_type", "Payable")
+ frappe.db.set_value("Account", encode_company_abbr(self.tally_debtors_account, self.erpnext_company), "account_type", "Receivable")
+ frappe.db.set_value("Company", self.erpnext_company, "round_off_account", self.round_off_account)
- vouchers_file = frappe.get_doc("File", {"file_url": self.vouchers})
- vouchers = json.loads(vouchers_file.get_content())
+ vouchers_file = frappe.get_doc("File", {"file_url": self.vouchers})
+ vouchers = json.loads(vouchers_file.get_content())
- create_fiscal_years(vouchers)
- create_price_list()
- create_custom_fields(["Journal Entry", "Purchase Invoice", "Sales Invoice"])
+ create_fiscal_years(vouchers)
+ create_price_list()
+ create_custom_fields(["Journal Entry", "Purchase Invoice", "Sales Invoice"])
- total = len(vouchers)
- is_last = False
- for index in range(0, total, VOUCHER_CHUNK_SIZE):
- if index + VOUCHER_CHUNK_SIZE >= total:
- is_last = True
- frappe.enqueue_doc(self.doctype, self.name, "_import_vouchers", queue="long", timeout=3600, start=index+1, total=total, is_last=is_last)
+ total = len(vouchers)
+ is_last = False
+
+ for index in range(0, total, VOUCHER_CHUNK_SIZE):
+ if index + VOUCHER_CHUNK_SIZE >= total:
+ is_last = True
+ frappe.enqueue_doc(self.doctype, self.name, "_import_vouchers", queue="long", timeout=3600, start=index+1, total=total, is_last=is_last)
+
+ except:
+ self.log()
+
+ finally:
+ self.set_status()
def _import_vouchers(self, start, total, is_last=False):
frappe.flags.in_migrate = True
@@ -494,25 +535,26 @@
frappe.flags.in_migrate = False
def process_master_data(self):
- self.status = "Processing Master Data"
- self.save()
+ self.set_status("Processing Master Data")
frappe.enqueue_doc(self.doctype, self.name, "_process_master_data", queue="long", timeout=3600)
def import_master_data(self):
- self.status = "Importing Master Data"
- self.save()
+ self.set_status("Importing Master Data")
frappe.enqueue_doc(self.doctype, self.name, "_import_master_data", queue="long", timeout=3600)
def process_day_book_data(self):
- self.status = "Processing Day Book Data"
- self.save()
+ self.set_status("Processing Day Book Data")
frappe.enqueue_doc(self.doctype, self.name, "_process_day_book_data", queue="long", timeout=3600)
def import_day_book_data(self):
- self.status = "Importing Day Book Data"
- self.save()
+ self.set_status("Importing Day Book Data")
frappe.enqueue_doc(self.doctype, self.name, "_import_day_book_data", queue="long", timeout=3600)
def log(self, data=None):
- message = "\n".join(["Data", json.dumps(data, default=str, indent=4), "Exception", traceback.format_exc()])
+ data = data or self.status
+ message = "\n".join(["Data:", json.dumps(data, default=str, indent=4), "--" * 50, "\nException:", traceback.format_exc()])
return frappe.log_error(title="Tally Migration Error", message=message)
+
+ def set_status(self, status=""):
+ self.status = status
+ self.save()
diff --git a/erpnext/healthcare/desk_page/healthcare/healthcare.json b/erpnext/healthcare/desk_page/healthcare/healthcare.json
index 258a72c..54798ba 100644
--- a/erpnext/healthcare/desk_page/healthcare/healthcare.json
+++ b/erpnext/healthcare/desk_page/healthcare/healthcare.json
@@ -1,28 +1,49 @@
{
"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"
- },
- {
- "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"
- },
- {
- "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]",
+ "icon": "",
+ "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient\",\n\t\t\"label\": \"Patient\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Practitioner\",\n\t\t\"label\":\"Healthcare Practitioner\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Practitioner Schedule\",\n\t\t\"label\": \"Practitioner Schedule\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Department\",\n\t\t\"label\": \"Medical Department\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Service Unit Type\",\n\t\t\"label\": \"Healthcare Service Unit Type\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Service Unit\",\n\t\t\"label\": \"Healthcare Service Unit\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Code Standard\",\n\t\t\"label\": \"Medical Code Standard\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Code\",\n\t\t\"label\": \"Medical Code\"\n\t}\n]",
"title": "Masters"
},
{
+ "icon": "",
+ "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Appointment Type\",\n\t\t\"label\": \"Appointment Type\"\n },\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Clinical Procedure Template\",\n\t\t\"label\": \"Clinical Procedure Template\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Prescription Dosage\",\n\t\t\"label\": \"Prescription Dosage\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Prescription Duration\",\n\t\t\"label\": \"Prescription Duration\"\n\t},\n\t{\n\t \"type\": \"doctype\",\n\t\t\"name\": \"Antibiotic\",\n\t\t\"label\": \"Antibiotic\"\n\t}\n]",
+ "title": "Consultation Setup"
+ },
+ {
"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]",
+ "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Appointment\",\n\t\t\"label\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Clinical Procedure\",\n\t\t\"label\": \"Clinical Procedure\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Encounter\",\n\t\t\"label\": \"Patient Encounter\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Vital Signs\",\n\t\t\"label\": \"Vital Signs\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Complaint\",\n\t\t\"label\": \"Complaint\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Diagnosis\",\n\t\t\"label\": \"Diagnosis\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Fee Validity\",\n\t\t\"label\": \"Fee Validity\"\n\t}\n]",
"title": "Consultation"
+ },
+ {
+ "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Settings\",\n\t\t\"label\": \"Healthcare Settings\",\n\t\t\"onboard\": 1\n\t}\n]",
+ "title": "Settings"
+ },
+ {
+ "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test Template\",\n\t\t\"label\": \"Lab Test Template\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test Sample\",\n\t\t\"label\": \"Lab Test Sample\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test UOM\",\n\t\t\"label\": \"Lab Test UOM\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Sensitivity\",\n\t\t\"label\": \"Sensitivity\"\n\t}\n]",
+ "title": "Laboratory Setup"
+ },
+ {
+ "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test\",\n\t\t\"label\": \"Lab Test\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Sample Collection\",\n\t\t\"label\": \"Sample Collection\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Dosage Form\",\n\t\t\"label\": \"Dosage Form\"\n\t}\n]",
+ "title": "Laboratory"
+ },
+ {
+ "links": "[\n\t{\n\t\t\"type\": \"page\",\n\t\t\"name\": \"patient_history\",\n\t\t\"label\": \"Patient History\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Medical Record\",\n\t\t\"label\": \"Patient Medical Record\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Inpatient Record\",\n\t\t\"label\": \"Inpatient Record\"\n\t}\n]",
+ "title": "Records and History"
+ },
+ {
+ "links": "[\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Patient Appointment Analytics\",\n\t\t\"doctype\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Lab Test Report\",\n\t\t\"doctype\": \"Lab Test\",\n\t\t\"label\": \"Lab Test Report\"\n\t}\n]",
+ "title": "Reports"
}
],
"category": "Domains",
- "charts": [],
+ "charts": [
+ {
+ "chart_name": "Patient Appointments",
+ "label": "Patient Appointments"
+ }
+ ],
+ "charts_label": "",
"creation": "2020-03-02 17:23:17.919682",
"developer_mode_only": 0,
"disable_user_customization": 0,
@@ -32,7 +53,7 @@
"idx": 0,
"is_standard": 1,
"label": "Healthcare",
- "modified": "2020-03-12 16:30:36.952979",
+ "modified": "2020-03-26 16:10:44.629795",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare",
@@ -40,5 +61,37 @@
"pin_to_bottom": 0,
"pin_to_top": 0,
"restrict_to_domain": "Healthcare",
- "shortcuts": []
+ "shortcuts": [
+ {
+ "format": "{} Open",
+ "is_query_report": 0,
+ "link_to": "Patient Appointment",
+ "stats_filter": "{\n \"status\": \"Open\"\n}",
+ "type": "DocType"
+ },
+ {
+ "format": "{} Active",
+ "is_query_report": 0,
+ "link_to": "Patient",
+ "stats_filter": "{\n \"status\": \"Active\"\n}",
+ "type": "DocType"
+ },
+ {
+ "format": "{} Vacant",
+ "is_query_report": 0,
+ "link_to": "Healthcare Service Unit",
+ "stats_filter": "{\n \"occupancy_status\": \"Vacant\",\n \"is_group\": 0\n}",
+ "type": "DocType"
+ },
+ {
+ "is_query_report": 0,
+ "link_to": "Healthcare Practitioner",
+ "type": "DocType"
+ },
+ {
+ "is_query_report": 0,
+ "link_to": "patient_history",
+ "type": "Page"
+ }
+ ]
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/appointment_type/appointment_type.json b/erpnext/healthcare/doctype/appointment_type/appointment_type.json
index ceabce2..58753bb 100644
--- a/erpnext/healthcare/doctype/appointment_type/appointment_type.json
+++ b/erpnext/healthcare/doctype/appointment_type/appointment_type.json
@@ -1,213 +1,94 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:appointment_type",
- "beta": 1,
- "creation": "2016-07-22 11:52:34.953019",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:appointment_type",
+ "beta": 1,
+ "creation": "2016-07-22 11:52:34.953019",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "appointment_type",
+ "ip",
+ "default_duration",
+ "color"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 1,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "appointment_type",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Type",
- "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": 1,
+ "allow_in_quick_entry": 1,
+ "fieldname": "appointment_type",
+ "fieldtype": "Data",
+ "ignore_xss_filter": 1,
+ "in_list_view": 1,
+ "label": "Type",
+ "reqd": 1,
+ "translatable": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "ip",
- "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 Inpatient",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "bold": 1,
+ "default": "0",
+ "fieldname": "ip",
+ "fieldtype": "Check",
+ "label": "Is Inpatient",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 1,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "description": "In Minutes",
- "fieldname": "default_duration",
- "fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Default Duration",
- "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_in_quick_entry": 1,
+ "bold": 1,
+ "fieldname": "default_duration",
+ "fieldtype": "Int",
+ "in_filter": 1,
+ "in_list_view": 1,
+ "label": "Default Duration (In Minutes)"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 1,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "color",
- "fieldtype": "Color",
- "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": "Color",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "allow_in_quick_entry": 1,
+ "fieldname": "color",
+ "fieldtype": "Color",
+ "in_list_view": 1,
+ "label": "Color",
+ "no_copy": 1,
+ "report_hide": 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-08-08 12:57:54.544216",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Appointment Type",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "links": [],
+ "modified": "2020-02-03 21:06:05.833050",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Appointment Type",
+ "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": "Healthcare Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
"write": 1
- },
+ },
{
- "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": "Physician",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "appointment_type",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "appointment_type",
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/appointment_type/appointment_type_dashboard.py b/erpnext/healthcare/doctype/appointment_type/appointment_type_dashboard.py
new file mode 100644
index 0000000..845e446
--- /dev/null
+++ b/erpnext/healthcare/doctype/appointment_type/appointment_type_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'appointment_type',
+ 'transactions': [
+ {
+ 'label': _('Patient Appointments'),
+ 'items': ['Patient Appointment']
+ },
+ ]
+ }
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
index fa91884..5f36bdd 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
@@ -4,244 +4,285 @@
frappe.ui.form.on('Clinical Procedure', {
setup: function(frm) {
frm.set_query('batch_no', 'items', function(doc, cdt, cdn) {
- var item = locals[cdt][cdn];
- if(!item.item_code) {
- frappe.throw(__("Please enter Item Code to get Batch Number"));
+ let item = locals[cdt][cdn];
+ if (!item.item_code) {
+ frappe.throw(__('Please enter Item Code to get Batch Number'));
} else {
+ let filters = {'item_code': item.item_code};
+
if (frm.doc.status == 'In Progress') {
- var filters = {
- 'item_code': item.item_code,
- 'posting_date': frm.doc.start_date || frappe.datetime.nowdate()
- };
- if(frm.doc.warehouse) filters["warehouse"] = frm.doc.warehouse;
- } else {
- filters = {
- 'item_code': item.item_code
- };
+ filters['posting_date'] = frm.doc.start_date || frappe.datetime.nowdate();
+ if (frm.doc.warehouse) filters['warehouse'] = frm.doc.warehouse;
}
+
return {
- query : "erpnext.controllers.queries.get_batch_no",
+ query : 'erpnext.controllers.queries.get_batch_no',
filters: filters
};
}
});
},
+
refresh: function(frm) {
- frm.set_query("patient", function () {
+ frm.set_query('patient', function () {
return {
- filters: {"disabled": 0}
+ filters: {'status': ['!=', 'Disabled']}
};
});
- frm.set_query("appointment", function () {
+
+ frm.set_query('appointment', function () {
return {
filters: {
- "procedure_template": ["not in", null],
- "status": ['in', 'Open, Scheduled']
+ 'procedure_template': ['not in', null],
+ 'status': ['in', 'Open, Scheduled']
}
};
});
- frm.set_query("service_unit", function(){
+
+ frm.set_query('service_unit', function() {
return {
filters: {
- "is_group": false,
- "allow_appointments": true
+ 'is_group': false,
+ 'allow_appointments': true
}
};
});
- frm.set_query("practitioner", function() {
+
+ frm.set_query('practitioner', function() {
return {
filters: {
'department': frm.doc.medical_department
}
};
});
- if(frm.doc.consume_stock){
+
+ if (frm.doc.consume_stock) {
frm.set_indicator_formatter('item_code',
- function(doc) { return (doc.qty<=doc.actual_qty) ? "green" : "orange" ; });
+ function(doc) { return (doc.qty<=doc.actual_qty) ? 'green' : 'orange' ; });
}
- if (!frm.doc.__islocal && frm.doc.status == 'In Progress'){
+ if (frm.doc.docstatus == 1) {
+ if (frm.doc.status == 'In Progress') {
+ let btn_label = '';
+ let msg = '';
+ if (frm.doc.consume_stock) {
+ btn_label = __('Complete and Consume');
+ msg = __('Complete {0} and Consume Stock?', [frm.doc.name]);
+ } else {
+ btn_label = 'Complete';
+ msg = __('Complete {0}?', [frm.doc.name]);
+ }
- if(frm.doc.consume_stock){
- var btn_label = 'Complete and Consume';
- var msg = 'Complete '+frm.doc.name+' and Consume Stock?';
- }else{
- btn_label = 'Complete';
- msg = 'Complete '+frm.doc.name+'?';
- }
+ frm.add_custom_button(__(btn_label), function () {
+ frappe.confirm(
+ msg,
+ function() {
+ frappe.call({
+ method: 'complete_procedure',
+ doc: frm.doc,
+ callback: function(r) {
+ if (r.message) {
+ frappe.show_alert({
+ message: __('Stock Entry {0} created',
+ ['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
+ indicator: 'green'
+ });
+ frm.reload_doc();
+ }
+ }
+ });
+ }
+ );
+ }).addClass("btn-primary");
- frm.add_custom_button(__(btn_label), function () {
- frappe.confirm(
- __(msg),
- function(){
- frappe.call({
- doc: frm.doc,
- method: "complete",
- callback: function(r) {
- if(!r.exc){
+ } else if (frm.doc.status == 'Pending') {
+ frm.add_custom_button(__('Start'), function() {
+ frappe.call({
+ doc: frm.doc,
+ method: 'start_procedure',
+ callback: function(r) {
+ if (!r.exc) {
+ if (r.message == 'insufficient stock') {
+ let msg = __('Stock quantity to start the Procedure is not available in the Warehouse {0}. Do you want to record a Stock Entry?',
+ [frm.doc.warehouse.bold()]);
+ frappe.confirm(
+ msg,
+ function() {
+ frappe.call({
+ doc: frm.doc,
+ method: 'make_material_receipt',
+ callback: function(r) {
+ if (!r.exc) {
+ cur_frm.reload_doc();
+ let doclist = frappe.model.sync(r.message);
+ frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
+ }
+ }
+ });
+ }
+ );
+ } else {
cur_frm.reload_doc();
}
}
- });
- }
- );
- });
- }else if (frm.doc.status == 'Draft') {
- frm.add_custom_button(__("Start"), function () {
- frappe.call({
- doc: frm.doc,
- method: "start",
- callback: function(r) {
- if(!r.exc){
- if(frm.doc.status == 'Draft'){
- frappe.confirm(
- __("Stock quantity to start procedure is not available in the warehouse. Do you want to record a Stock Transfer"),
- function(){
- frappe.call({
- doc: frm.doc,
- method: "make_material_transfer",
- callback: function(r) {
- if(!r.exc){
- cur_frm.reload_doc();
- var doclist = frappe.model.sync(r.message);
- frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
- }
- }
- });
- }
- );
- }else{
- cur_frm.reload_doc();
- }
}
- }
- });
- });
- }
- if (frm.doc.__islocal){
- frm.set_df_property("consumables", "hidden", 1);
- }else{
- frm.set_df_property("consumables", "hidden", 0);
+ });
+ }).addClass("btn-primary");
+ }
}
},
- onload: function(frm){
- if(frm.doc.status == 'Completed'){
- frm.set_df_property("items", "read_only", 1);
- }
- if(frm.is_new()) {
- frm.add_fetch("procedure_template", "medical_department", "medical_department");
- frm.set_value("start_time", null);
+
+ onload: function(frm) {
+ if (frm.is_new()) {
+ frm.add_fetch('procedure_template', 'medical_department', 'medical_department');
+ frm.set_value('start_time', null);
}
},
+
patient: function(frm) {
- if(frm.doc.patient){
+ if (frm.doc.patient) {
frappe.call({
- "method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
+ 'method': 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
args: {
patient: frm.doc.patient
},
callback: function (data) {
- let age = "";
- if(data.message.dob){
+ let age = '';
+ if (data.message.dob) {
age = calculate_age(data.message.dob);
- }else if (data.message.age){
+ } else if (data.message.age) {
age = data.message.age;
- if(data.message.age_as_on){
- age = age+" as on "+data.message.age_as_on;
+ if (data.message.age_as_on) {
+ age = __('{0} as on {1}', [age, data.message.age_as_on]);
}
}
- frm.set_value("patient_age", age);
- frm.set_value("patient_sex", data.message.sex);
+ frm.set_value('patient_age', age);
+ frm.set_value('patient_sex', data.message.sex);
}
});
- }else{
- frm.set_value("patient_age", "");
- frm.set_value("patient_sex", "");
+ } else {
+ frm.set_value('patient_age', '');
+ frm.set_value('patient_sex', '');
}
},
+
appointment: function(frm) {
- if(frm.doc.appointment){
+ if (frm.doc.appointment) {
frappe.call({
- "method": "frappe.client.get",
+ 'method': 'frappe.client.get',
args: {
- doctype: "Patient Appointment",
+ doctype: 'Patient Appointment',
name: frm.doc.appointment
},
- callback: function (data) {
- frm.set_value("patient", data.message.patient);
- frm.set_value("procedure_template", data.message.procedure_template);
- frm.set_value("medical_department", data.message.department);
- frm.set_value("start_date", data.message.appointment_date);
- frm.set_value("start_time", data.message.appointment_time);
- frm.set_value("notes", data.message.notes);
- frm.set_value("service_unit", data.message.service_unit);
+ callback: function(data) {
+ frm.set_value('patient', data.message.patient);
+ frm.set_value('procedure_template', data.message.procedure_template);
+ frm.set_value('medical_department', data.message.department);
+ frm.set_value('start_date', data.message.appointment_date);
+ frm.set_value('start_time', data.message.appointment_time);
+ frm.set_value('notes', data.message.notes);
+ frm.set_value('service_unit', data.message.service_unit);
}
});
}
},
+
procedure_template: function(frm) {
- if(frm.doc.procedure_template){
+ if (frm.doc.procedure_template) {
frappe.call({
- "method": "frappe.client.get",
+ 'method': 'frappe.client.get',
args: {
- doctype: "Clinical Procedure Template",
+ doctype: 'Clinical Procedure Template',
name: frm.doc.procedure_template
},
callback: function (data) {
- frm.set_value("medical_department", data.message.medical_department);
- frm.set_value("consume_stock", data.message.consume_stock);
- if(!frm.doc.warehouse){
- frappe.call({
- method: "frappe.client.get_value",
- args: {
- doctype: "Stock Settings",
- fieldname: "default_warehouse"
- },
- callback: function (data) {
- frm.set_value("warehouse", data.message.default_warehouse);
- }
- });
- }
+ frm.set_value('medical_department', data.message.medical_department);
+ frm.set_value('consume_stock', data.message.consume_stock);
+ frm.events.set_warehouse(frm);
+ frm.events.set_procedure_consumables(frm);
}
});
- }else{
- frm.set_value("consume_stock", 0);
}
},
+
service_unit: function(frm) {
- if(frm.doc.service_unit){
+ if (frm.doc.service_unit) {
frappe.call({
- method: "frappe.client.get_value",
+ method: 'frappe.client.get_value',
args:{
- fieldname: "warehouse",
- doctype: "Healthcare Service Unit",
+ fieldname: 'warehouse',
+ doctype: 'Healthcare Service Unit',
filters:{name: frm.doc.service_unit},
},
callback: function(data) {
- if(data.message){
- frm.set_value("warehouse", data.message.warehouse);
+ if (data.message) {
+ frm.set_value('warehouse', data.message.warehouse);
}
}
});
}
},
+
practitioner: function(frm) {
- if(frm.doc.practitioner){
+ if (frm.doc.practitioner) {
frappe.call({
- "method": "frappe.client.get",
+ 'method': 'frappe.client.get',
args: {
- doctype: "Healthcare Practitioner",
+ doctype: 'Healthcare Practitioner',
name: frm.doc.practitioner
},
callback: function (data) {
- frappe.model.set_value(frm.doctype,frm.docname, "medical_department",data.message.department);
+ frappe.model.set_value(frm.doctype,frm.docname, 'medical_department',data.message.department);
}
});
}
+ },
+
+ set_warehouse: function(frm) {
+ if (!frm.doc.warehouse) {
+ frappe.call({
+ method: 'frappe.client.get_value',
+ args: {
+ doctype: 'Stock Settings',
+ fieldname: 'default_warehouse'
+ },
+ callback: function (data) {
+ frm.set_value('warehouse', data.message.default_warehouse);
+ }
+ });
+ }
+ },
+
+ set_procedure_consumables: function(frm) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.clinical_procedure.clinical_procedure.get_procedure_consumables',
+ args: {
+ procedure_template: frm.doc.procedure_template
+ },
+ callback: function(data) {
+ if (data.message) {
+ frm.doc.items = [];
+ $.each(data.message, function(i, v) {
+ let item = frm.add_child('items');
+ item.item_code = v.item_code;
+ item.item_name = v.item_name;
+ item.uom = v.uom;
+ item.stock_uom = v.stock_uom;
+ item.qty = flt(v.qty);
+ item.transfer_qty = v.transfer_qty;
+ item.conversion_factor = v.conversion_factor;
+ item.invoice_separately_as_consumables = v.invoice_separately_as_consumables;
+ item.batch_no = v.batch_no;
+ });
+ refresh_field('items');
+ }
+ }
+ });
}
+
});
-cur_frm.set_query("procedure_template", function(doc) {
+cur_frm.set_query('procedure_template', function(doc) {
return {
filters: {
'medical_department': doc.medical_department
@@ -249,57 +290,51 @@
};
});
-cur_frm.set_query("appointment", function() {
- return {
- filters: {
- status:['in',["Open"]]
- }
- };
-});
-
frappe.ui.form.on('Clinical Procedure Item', {
- qty: function(frm, cdt, cdn){
- var d = locals[cdt][cdn];
- frappe.model.set_value(cdt, cdn, "transfer_qty", d.qty*d.conversion_factor);
+ qty: function(frm, cdt, cdn) {
+ let d = locals[cdt][cdn];
+ frappe.model.set_value(cdt, cdn, 'transfer_qty', d.qty*d.conversion_factor);
},
- uom: function(doc, cdt, cdn){
- var d = locals[cdt][cdn];
- if(d.uom && d.item_code){
+
+ uom: function(doc, cdt, cdn) {
+ let d = locals[cdt][cdn];
+ if (d.uom && d.item_code) {
return frappe.call({
- method: "erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details",
+ method: 'erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details',
args: {
item_code: d.item_code,
uom: d.uom,
qty: d.qty
},
callback: function(r) {
- if(r.message) {
+ if (r.message) {
frappe.model.set_value(cdt, cdn, r.message);
}
}
});
}
},
+
item_code: function(frm, cdt, cdn) {
- var d = locals[cdt][cdn];
+ let d = locals[cdt][cdn];
let args = null;
- if(d.item_code) {
+ if (d.item_code) {
args = {
- 'doctype' : "Clinical Procedure",
+ 'doctype' : 'Clinical Procedure',
'item_code' : d.item_code,
'company' : frm.doc.company,
'warehouse': frm.doc.warehouse
};
return frappe.call({
- method: "erpnext.stock.get_item_details.get_item_details",
+ method: 'erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.get_item_details',
args: {args: args},
callback: function(r) {
- if(r.message) {
- frappe.model.set_value(cdt, cdn, "item_name", r.message.item_name);
- frappe.model.set_value(cdt, cdn, "stock_uom", r.message.stock_uom);
- frappe.model.set_value(cdt, cdn, "conversion_factor", r.message.conversion_factor);
- frappe.model.set_value(cdt, cdn, "actual_qty", r.message.actual_qty);
- refresh_field("items");
+ if (r.message) {
+ let d = locals[cdt][cdn];
+ $.each(r.message, function(k, v) {
+ d[k] = v;
+ });
+ refresh_field('items');
}
}
});
@@ -307,16 +342,16 @@
}
});
-var calculate_age = function(birth) {
- var ageMS = Date.parse(Date()) - Date.parse(birth);
- var age = new Date();
+let calculate_age = function(birth) {
+ let ageMS = Date.parse(Date()) - Date.parse(birth);
+ let age = new Date();
age.setTime(ageMS);
- var years = age.getFullYear() - 1970;
- return years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)";
+ let years = age.getFullYear() - 1970;
+ return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
};
// List Stock items
-cur_frm.set_query("item_code", "items", function() {
+cur_frm.set_query('item_code', 'items', function() {
return {
filters: {
is_stock_item:1
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json
index 3097ba3..3c936bb 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json
@@ -1,955 +1,267 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2017-04-07 12:52:43.542429",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2017-04-07 12:52:43.542429",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "inpatient_record",
+ "naming_series",
+ "procedure_template",
+ "appointment",
+ "patient",
+ "patient_sex",
+ "patient_age",
+ "prescription",
+ "medical_department",
+ "practitioner",
+ "column_break_7",
+ "status",
+ "service_unit",
+ "warehouse",
+ "start_date",
+ "start_time",
+ "sample",
+ "invoiced",
+ "notes",
+ "company",
+ "consumables_section",
+ "consume_stock",
+ "items",
+ "section_break_24",
+ "invoice_separately_as_consumables",
+ "consumption_invoiced",
+ "consumable_total_amount",
+ "column_break_27",
+ "consumption_details",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.inpatient_record",
- "fieldname": "inpatient_record",
- "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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
- "options": "Inpatient Record",
- "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": "patient.inpatient_record",
+ "fieldname": "inpatient_record",
+ "fieldtype": "Link",
+ "label": "Inpatient Record",
+ "options": "Inpatient Record",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "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": 0,
- "in_standard_filter": 0,
- "label": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "HLC-CPR-.YYYY.-",
- "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": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-CPR-.YYYY.-"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "appointment",
- "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": "Appointment",
- "length": 0,
- "no_copy": 0,
- "options": "Patient Appointment",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "appointment",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Appointment",
+ "options": "Patient Appointment"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "inpatient_record.patient",
- "fieldname": "patient",
- "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": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "inpatient_record.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient_age",
- "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": "Age",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient_age",
+ "fieldtype": "Data",
+ "label": "Age",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient_sex",
- "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": "Gender",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient_sex",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender",
+ "read_only": 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": "prescription",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Procedure Prescription",
- "length": 0,
- "no_copy": 0,
- "options": "Procedure Prescription",
- "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": "prescription",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Procedure Prescription",
+ "options": "Procedure Prescription"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "medical_department",
- "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": "Medical Department",
- "length": 0,
- "no_copy": 0,
- "options": "Medical Department",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "medical_department",
+ "fieldtype": "Link",
+ "label": "Medical Department",
+ "options": "Medical Department"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "practitioner",
- "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": "Healthcare Practitioner",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "practitioner",
+ "fieldtype": "Link",
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_7",
- "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_7",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure_template",
- "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": "Procedure Template",
- "length": 0,
- "no_copy": 0,
- "options": "Clinical Procedure Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "procedure_template",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Procedure Template",
+ "options": "Clinical Procedure Template",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "service_unit",
- "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": "Service Unit",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Service Unit",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "service_unit",
+ "fieldtype": "Link",
+ "label": "Service Unit",
+ "options": "Healthcare Service Unit",
+ "set_only_once": 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": 0,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "label": "Warehouse",
+ "mandatory_depends_on": "eval: doc.consume_stock == 1",
+ "options": "Warehouse"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fieldname": "start_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": "Start 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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "default": "Today",
+ "fieldname": "start_date",
+ "fieldtype": "Date",
+ "label": "Start Date"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "start_time",
- "fieldtype": "Time",
- "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": "Time",
- "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": "start_time",
+ "fieldtype": "Time",
+ "label": "Start Time"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Sample Collection",
- "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": "sample",
+ "fieldtype": "Link",
+ "label": "Sample",
+ "options": "Sample Collection"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "invoiced",
- "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": "Invoiced",
- "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
- },
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "no_copy": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "notes",
- "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": "Notes",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "notes",
+ "fieldtype": "Small Text",
+ "label": "Notes",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "consume_stock",
- "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": "Consume Stock",
- "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
- },
+ "default": "0",
+ "fieldname": "consume_stock",
+ "fieldtype": "Check",
+ "label": "Consume Stock"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.consume_stock == 1",
- "fieldname": "consumables",
- "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": "Consumables",
- "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": "items",
+ "fieldtype": "Table",
+ "label": "Consumables",
+ "options": "Clinical Procedure Item"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "items",
- "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": "Consumables",
- "length": 0,
- "no_copy": 0,
- "options": "Clinical Procedure Item",
- "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": "invoice_separately_as_consumables",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Invoice Consumables Separately",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "invoice_separately_as_consumables",
- "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": "Consumables Invoice Separately",
- "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
- },
+ "depends_on": "invoice_separately_as_consumables",
+ "fieldname": "consumable_total_amount",
+ "fieldtype": "Currency",
+ "label": "Consumable Total Amount",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "invoice_separately_as_consumables",
- "fieldname": "consumable_total_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Consumable Total Amount",
- "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
- },
+ "depends_on": "invoice_separately_as_consumables",
+ "fieldname": "consumption_details",
+ "fieldtype": "Small Text",
+ "label": "Consumption Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "invoice_separately_as_consumables",
- "fieldname": "consumption_details",
- "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": "Consumption 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
- },
+ "default": "0",
+ "depends_on": "invoice_separately_as_consumables",
+ "fieldname": "consumption_invoiced",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Consumption Invoiced",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "depends_on": "invoice_separately_as_consumables",
- "fieldname": "consumption_invoiced",
- "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": "Consumption Invoiced",
- "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": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Status",
+ "options": "Draft\nSubmitted\nCancelled\nIn Progress\nCompleted\nPending",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "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": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Draft\nIn Progress\nCompleted\nPending\nCancelled",
- "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": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Clinical Procedure",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "consumables_section",
+ "fieldtype": "Section Break",
+ "label": "Consumables"
+ },
+ {
+ "fieldname": "column_break_27",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_24",
+ "fieldtype": "Section Break"
}
- ],
- "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-08-21 14:44:49.438611",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Clinical Procedure",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-03-02 11:44:27.970651",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Clinical Procedure",
+ "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": "Nursing User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Nursing User",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
+ ],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
index 7c6f4d5..db3afc8 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
@@ -6,88 +6,101 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from frappe.utils import cint, flt, nowdate, nowtime, cstr
+from frappe.utils import flt, nowdate, nowtime, cstr
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account
from erpnext.healthcare.doctype.lab_test.lab_test import create_sample_doc
from erpnext.stock.stock_ledger import get_previous_sle
from erpnext.stock.get_item_details import get_item_details
+from frappe.model.mapper import get_mapped_doc
class ClinicalProcedure(Document):
def validate(self):
- if self.consume_stock and not self.status == 'Draft':
- if not self.warehouse:
- frappe.throw(_("Set warehouse for Procedure {0} ").format(self.name))
+ self.set_status()
+ if self.consume_stock:
self.set_actual_qty()
if self.items:
self.invoice_separately_as_consumables = False
for item in self.items:
- if item.invoice_separately_as_consumables == 1:
+ if item.invoice_separately_as_consumables:
self.invoice_separately_as_consumables = True
def before_insert(self):
if self.consume_stock:
- set_stock_items(self, self.procedure_template, "Clinical Procedure Template")
- self.set_actual_qty();
+ self.set_actual_qty()
def after_insert(self):
if self.prescription:
- frappe.db.set_value("Procedure Prescription", self.prescription, "procedure_created", 1)
+ frappe.db.set_value('Procedure Prescription', self.prescription, 'procedure_created', 1)
if self.appointment:
- frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
- template = frappe.get_doc("Clinical Procedure Template", self.procedure_template)
+ frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
+ template = frappe.get_doc('Clinical Procedure Template', self.procedure_template)
if template.sample:
- patient = frappe.get_doc("Patient", self.patient)
+ patient = frappe.get_doc('Patient', self.patient)
sample_collection = create_sample_doc(template, patient, None)
- frappe.db.set_value("Clinical Procedure", self.name, "sample", sample_collection.name)
+ frappe.db.set_value('Clinical Procedure', self.name, 'sample', sample_collection.name)
self.reload()
- def complete(self):
+ def set_status(self):
+ if self.docstatus == 0:
+ self.status = 'Draft'
+ elif self.docstatus == 1:
+ if self.status not in ['In Progress', 'Completed']:
+ self.status = 'Pending'
+ elif self.docstatus == 2:
+ self.status = 'Cancelled'
+
+ def complete_procedure(self):
if self.consume_stock and self.items:
- create_stock_entry(self)
- frappe.db.set_value("Clinical Procedure", self.name, "status", 'Completed')
+ stock_entry = make_stock_entry(self)
if self.items:
consumable_total_amount = 0
consumption_details = False
- for item in self.items:
- if item.invoice_separately_as_consumables:
- price_list, price_list_currency = frappe.db.get_values("Price List", {"selling": 1}, ['name', 'currency'])[0]
- args = {
- 'doctype': "Sales Invoice",
- 'item_code': item.item_code,
- 'company': self.company,
- 'warehouse': self.warehouse,
- 'customer': frappe.db.get_value("Patient", self.patient, "customer"),
- 'selling_price_list': price_list,
- 'price_list_currency': price_list_currency,
- 'plc_conversion_rate': 1.0,
- 'conversion_rate': 1.0
- }
- item_details = get_item_details(args)
- item_price = item_details.price_list_rate * item.transfer_qty
- item_consumption_details = item_details.item_name+"\t"+str(item.qty)+" "+item.uom+"\t"+str(item_price)
- consumable_total_amount += item_price
- if not consumption_details:
- consumption_details = "Clinical Procedure ("+self.name+"):\n\t"+item_consumption_details
- else:
- consumption_details += "\n\t"+item_consumption_details
- if consumable_total_amount > 0:
- frappe.db.set_value("Clinical Procedure", self.name, "consumable_total_amount", consumable_total_amount)
- frappe.db.set_value("Clinical Procedure", self.name, "consumption_details", consumption_details)
+ customer = frappe.db.get_value('Patient', self.patient, 'customer')
+ if customer:
+ for item in self.items:
+ if item.invoice_separately_as_consumables:
+ price_list, price_list_currency = frappe.db.get_values('Price List', {'selling': 1}, ['name', 'currency'])[0]
+ args = {
+ 'doctype': 'Sales Invoice',
+ 'item_code': item.item_code,
+ 'company': self.company,
+ 'warehouse': self.warehouse,
+ 'customer': customer,
+ 'selling_price_list': price_list,
+ 'price_list_currency': price_list_currency,
+ 'plc_conversion_rate': 1.0,
+ 'conversion_rate': 1.0
+ }
+ item_details = get_item_details(args)
+ item_price = item_details.price_list_rate * item.qty
+ item_consumption_details = item_details.item_name + ' ' + str(item.qty) + ' ' + item.uom + ' ' + str(item_price)
+ consumable_total_amount += item_price
+ if not consumption_details:
+ consumption_details = _('Clinical Procedure ({0}):').format(self.name)
+ consumption_details += '\n\t' + item_consumption_details
+ if consumable_total_amount > 0:
+ frappe.db.set_value('Clinical Procedure', self.name, 'consumable_total_amount', consumable_total_amount)
+ frappe.db.set_value('Clinical Procedure', self.name, 'consumption_details', consumption_details)
+ else:
+ frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
- def start(self):
+ frappe.db.set_value('Clinical Procedure', self.name, 'status', 'Completed')
+ if self.consume_stock and self.items:
+ return stock_entry
+
+ def start_procedure(self):
allow_start = self.set_actual_qty()
if allow_start:
- self.status = 'In Progress'
+ self.db_set('status', 'In Progress')
insert_clinical_procedure_to_medical_record(self)
- else:
- self.status = 'Draft'
- self.save()
+ return 'success'
+ return 'insufficient stock'
def set_actual_qty(self):
- allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
+ allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
allow_start = True
for d in self.get('items'):
@@ -95,15 +108,16 @@
# validate qty
if not allow_negative_stock and d.actual_qty < d.qty:
allow_start = False
+ break
return allow_start
- def make_material_transfer(self):
- stock_entry = frappe.new_doc("Stock Entry")
+ def make_material_receipt(self, submit=False):
+ stock_entry = frappe.new_doc('Stock Entry')
- stock_entry.purpose = "Material Transfer"
+ stock_entry.stock_entry_type = 'Material Receipt'
stock_entry.to_warehouse = self.warehouse
- expense_account = get_account(None, "expense_account", "Healthcare Settings", self.company)
+ expense_account = get_account(None, 'expense_account', 'Healthcare Settings', self.company)
for item in self.items:
if item.qty > item.actual_qty:
se_child = stock_entry.append('items')
@@ -111,7 +125,7 @@
se_child.item_name = item.item_name
se_child.uom = item.uom
se_child.stock_uom = item.stock_uom
- se_child.qty = flt(item.qty-item.actual_qty)
+ se_child.qty = flt(item.qty - item.actual_qty)
se_child.t_warehouse = self.warehouse
# in stock uom
se_child.transfer_qty = flt(item.transfer_qty)
@@ -119,104 +133,130 @@
cost_center = frappe.get_cached_value('Company', self.company, 'cost_center')
se_child.cost_center = cost_center
se_child.expense_account = expense_account
+ if submit:
+ stock_entry.submit()
+ return stock_entry
return stock_entry.as_dict()
-@frappe.whitelist()
+
def get_stock_qty(item_code, warehouse):
return get_previous_sle({
- "item_code": item_code,
- "warehouse": warehouse,
- "posting_date": nowdate(),
- "posting_time": nowtime()
- }).get("qty_after_transaction") or 0
+ 'item_code': item_code,
+ 'warehouse': warehouse,
+ 'posting_date': nowdate(),
+ 'posting_time': nowtime()
+ }).get('qty_after_transaction') or 0
+
+
+@frappe.whitelist()
+def get_procedure_consumables(procedure_template):
+ return get_items('Clinical Procedure Item', procedure_template, 'Clinical Procedure Template')
+
@frappe.whitelist()
def set_stock_items(doc, stock_detail_parent, parenttype):
- item_dict = get_item_dict("Clinical Procedure Item", stock_detail_parent, parenttype)
+ items = get_items('Clinical Procedure Item', stock_detail_parent, parenttype)
- for d in item_dict:
+ for item in items:
se_child = doc.append('items')
- se_child.item_code = d["item_code"]
- se_child.item_name = d["item_name"]
- se_child.uom = d["uom"]
- se_child.stock_uom = d["stock_uom"]
- se_child.qty = flt(d["qty"])
+ se_child.item_code = item.item_code
+ se_child.item_name = item.item_name
+ se_child.uom = item.uom
+ se_child.stock_uom = item.stock_uom
+ se_child.qty = flt(item.qty)
# in stock uom
- se_child.transfer_qty = flt(d["transfer_qty"])
- se_child.conversion_factor = flt(d["conversion_factor"])
- if d["batch_no"]:
- se_child.batch_no = d["batch_no"]
- if parenttype == "Clinical Procedure Template":
- se_child.invoice_separately_as_consumables = d["invoice_separately_as_consumables"]
+ se_child.transfer_qty = flt(item.transfer_qty)
+ se_child.conversion_factor = flt(item.conversion_factor)
+ if item.batch_no:
+ se_child.batch_no = item.batch_no
+ if parenttype == 'Clinical Procedure Template':
+ se_child.invoice_separately_as_consumables = item.invoice_separately_as_consumables
+
return doc
-def get_item_dict(table, parent, parenttype):
- query = """select * from `tab{table}` where parent = '{parent}' and parenttype = '{parenttype}' """
- return frappe.db.sql(query.format(table=table, parent=parent, parenttype=parenttype), as_dict=True)
+def get_items(table, parent, parenttype):
+ items = frappe.db.get_all(table, filters={
+ 'parent': parent,
+ 'parenttype': parenttype
+ }, fields=['*'])
-def create_stock_entry(doc):
- stock_entry = frappe.new_doc("Stock Entry")
- stock_entry = set_stock_items(stock_entry, doc.name, "Clinical Procedure")
- stock_entry.purpose = "Material Issue"
+ return items
+
+
+@frappe.whitelist()
+def make_stock_entry(doc):
+ stock_entry = frappe.new_doc('Stock Entry')
+ stock_entry = set_stock_items(stock_entry, doc.name, 'Clinical Procedure')
+ stock_entry.stock_entry_type = 'Material Issue'
stock_entry.from_warehouse = doc.warehouse
stock_entry.company = doc.company
- expense_account = get_account(None, "expense_account", "Healthcare Settings", doc.company)
+ expense_account = get_account(None, 'expense_account', 'Healthcare Settings', doc.company)
for item_line in stock_entry.items:
cost_center = frappe.get_cached_value('Company', doc.company, 'cost_center')
- #item_line.s_warehouse = warehouse #deaful source warehouse set, stock entry to copy to lines
item_line.cost_center = cost_center
- #if not expense_account:
- # expense_account = frappe.db.get_value("Item", item_line.item_code, "expense_account")
item_line.expense_account = expense_account
- stock_entry.insert(ignore_permissions = True)
+ stock_entry.save(ignore_permissions=True)
stock_entry.submit()
+ return stock_entry.name
+
@frappe.whitelist()
-def create_procedure(appointment):
- appointment = frappe.get_doc("Patient Appointment",appointment)
- procedure = frappe.new_doc("Clinical Procedure")
- procedure.appointment = appointment.name
- procedure.patient = appointment.patient
- procedure.patient_age = appointment.patient_age
- procedure.patient_sex = appointment.patient_sex
- procedure.procedure_template = appointment.procedure_template
- procedure.prescription = appointment.procedure_prescription
- procedure.practitioner = appointment.practitioner
- procedure.invoiced = appointment.invoiced
- procedure.medical_department = appointment.department
- procedure.start_date = appointment.appointment_date
- procedure.start_time = appointment.appointment_time
- procedure.notes = appointment.notes
- procedure.service_unit = appointment.service_unit
- procedure.company = appointment.company
- consume_stock = frappe.db.get_value("Clinical Procedure Template", appointment.procedure_template, "consume_stock")
- if consume_stock == 1:
- procedure.consume_stock = True
- warehouse = False
- if appointment.service_unit:
- warehouse = frappe.db.get_value("Healthcare Service Unit", appointment.service_unit, "warehouse")
- if not warehouse:
- warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse")
- if warehouse:
- procedure.warehouse = warehouse
- return procedure.as_dict()
+def make_procedure(source_name, target_doc=None):
+ def set_missing_values(source, target):
+ consume_stock = frappe.db.get_value('Clinical Procedure Template', source.procedure_template, 'consume_stock')
+ if consume_stock:
+ target.consume_stock = 1
+ warehouse = None
+ if source.service_unit:
+ warehouse = frappe.db.get_value('Healthcare Service Unit', source.service_unit, 'warehouse')
+ if not warehouse:
+ warehouse = frappe.db.get_value('Stock Settings', None, 'default_warehouse')
+ if warehouse:
+ target.warehouse = warehouse
+
+ set_stock_items(target, source.procedure_template, 'Clinical Procedure Template')
+
+ doc = get_mapped_doc('Patient Appointment', source_name, {
+ 'Patient Appointment': {
+ 'doctype': 'Clinical Procedure',
+ 'field_map': [
+ ['appointment', 'name'],
+ ['patient', 'patient'],
+ ['patient_age', 'patient_age'],
+ ['patient_sex', 'patient_sex'],
+ ['procedure_template', 'procedure_template'],
+ ['prescription', 'procedure_prescription'],
+ ['practitioner', 'practitioner'],
+ ['medical_department', 'department'],
+ ['start_date', 'appointment_date'],
+ ['start_time', 'appointment_time'],
+ ['notes', 'notes'],
+ ['service_unit', 'service_unit'],
+ ['company', 'company'],
+ ['invoiced', 'invoiced']
+ ]
+ }
+ }, target_doc, set_missing_values)
+
+ return doc
+
def insert_clinical_procedure_to_medical_record(doc):
subject = cstr(doc.procedure_template)
if doc.practitioner:
- subject += " "+doc.practitioner
+ subject += ' ' + doc.practitioner
if subject and doc.notes:
- subject += "<br/>"+doc.notes
+ subject += '<br/>' + doc.notes
- medical_record = frappe.new_doc("Patient Medical Record")
+ medical_record = frappe.new_doc('Patient Medical Record')
medical_record.patient = doc.patient
medical_record.subject = subject
- medical_record.status = "Open"
+ medical_record.status = 'Open'
medical_record.communication_date = doc.start_date
- medical_record.reference_doctype = "Clinical Procedure"
+ medical_record.reference_doctype = 'Clinical Procedure'
medical_record.reference_name = doc.name
medical_record.reference_owner = doc.owner
medical_record.save(ignore_permissions=True)
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure_list.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure_list.js
new file mode 100644
index 0000000..c8601f9
--- /dev/null
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure_list.js
@@ -0,0 +1,11 @@
+frappe.listview_settings['Clinical Procedure'] = {
+ get_indicator: function(doc) {
+ var colors = {
+ 'Completed': 'green',
+ 'In Progress': 'orange',
+ 'Pending': 'orange',
+ 'Cancelled': 'grey'
+ };
+ return [__(doc.status), colors[doc.status], 'status,=,' + doc.status];
+ }
+};
diff --git a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
index 09059e1..207351f 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
@@ -4,6 +4,60 @@
from __future__ import unicode_literals
import unittest
+import frappe
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_clinical_procedure_template
class TestClinicalProcedure(unittest.TestCase):
- pass
+ def test_procedure_template_item(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ procedure_template = create_clinical_procedure_template()
+ self.assertTrue(frappe.db.exists('Item', procedure_template.item))
+
+ procedure_template.disabled = 1
+ procedure_template.save()
+ self.assertEquals(frappe.db.get_value('Item', procedure_template.item, 'disabled'), 1)
+
+ def test_consumables(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ procedure_template = create_clinical_procedure_template()
+ procedure_template.allow_stock_consumption = 1
+ consumable = create_consumable()
+ procedure_template.append('items', {
+ 'item_code': consumable.item_code,
+ 'qty': 1,
+ 'uom': consumable.stock_uom,
+ 'stock_uom': consumable.stock_uom
+ })
+ procedure_template.save()
+ procedure = create_procedure(procedure_template, patient, practitioner)
+ result = procedure.start_procedure()
+ if result == 'insufficient stock':
+ procedure.make_material_receipt(submit=True)
+ result = procedure.start_procedure()
+ self.assertEqual(procedure.status, 'In Progress')
+ result = procedure.complete_procedure()
+ # check consumption
+ self.assertTrue(frappe.db.exists('Stock Entry', result))
+
+
+def create_consumable():
+ if frappe.db.exists('Item', 'Syringe'):
+ return frappe.get_doc('Item', 'Syringe')
+ consumable = frappe.new_doc('Item')
+ consumable.item_code = 'Syringe'
+ consumable.item_group = '_Test Item Group'
+ consumable.stock_uom = 'Nos'
+ consumable.valuation_rate = 5.00
+ consumable.save()
+ return consumable
+
+def create_procedure(procedure_template, patient, practitioner):
+ procedure = frappe.new_doc('Clinical Procedure')
+ procedure.procedure_template = procedure_template.name
+ procedure.patient = patient
+ procedure.practitioner = practitioner
+ procedure.consume_stock = procedure_template.allow_stock_consumption
+ procedure.items = procedure_template.items
+ procedure.warehouse = frappe.db.get_single_value('Stock Settings', 'default_warehouse')
+ procedure.submit()
+ return procedure
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.json b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.json
index 75151b1..a7dde0b 100644
--- a/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.json
+++ b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.json
@@ -1,431 +1,123 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-10-05 16:15:10.876952",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "beta": 1,
+ "creation": "2017-10-05 16:15:10.876952",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "item_code",
+ "item_name",
+ "qty",
+ "barcode",
+ "uom",
+ "invoice_separately_as_consumables",
+ "column_break_5",
+ "batch_no",
+ "conversion_factor",
+ "stock_uom",
+ "transfer_qty",
+ "actual_qty"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 3,
- "fieldname": "item_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "Item",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "bold": 1,
+ "columns": 3,
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "Item",
+ "options": "Item",
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "barcode",
- "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": "Barcode",
- "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": "barcode",
+ "fieldtype": "Data",
+ "label": "Barcode"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item_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": "Item Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Item Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "qty",
- "fieldtype": "Float",
- "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": "Quantity",
- "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": "qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Quantity",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "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": "UOM",
- "length": 0,
- "no_copy": 0,
- "options": "UOM",
- "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": "uom",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "UOM",
+ "options": "UOM",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "invoice_separately_as_consumables",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Invoice Separately as Consumables",
- "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": "invoice_separately_as_consumables",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Invoice Separately as Consumables"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_5",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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_5",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "batch_no",
- "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": "Batch",
- "length": 0,
- "no_copy": 0,
- "options": "Batch",
- "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": "batch_no",
+ "fieldtype": "Link",
+ "label": "Batch",
+ "options": "Batch"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "conversion_factor",
- "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": "Conversion Factor",
- "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": "conversion_factor",
+ "fieldtype": "Float",
+ "label": "Conversion Factor",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "in_standard_filter": 0,
- "label": "Stock UOM",
- "length": 0,
- "no_copy": 0,
- "options": "UOM",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "label": "Stock UOM",
+ "options": "UOM",
+ "read_only": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "transfer_qty",
- "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": "Transfer Qty",
- "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": "transfer_qty",
+ "fieldtype": "Float",
+ "label": "Transfer Qty",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "actual_qty",
- "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": "Actual Qty (at source/target)",
- "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": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "actual_qty",
+ "fieldtype": "Float",
+ "label": "Actual Qty (at source/target)",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1,
+ "search_index": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-04 03:33:16.833884",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Clinical Procedure Item",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-01 15:34:54.226722",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Clinical Procedure Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js
index 583728d..57f4cdf 100644
--- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js
+++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js
@@ -3,170 +3,141 @@
frappe.ui.form.on('Clinical Procedure Template', {
template: function(frm) {
- if(!frm.doc.item_code)
- frm.set_value("item_code", frm.doc.template);
- if(!frm.doc.description)
- frm.set_value("description", frm.doc.template);
+ if (!frm.doc.item_code)
+ frm.set_value('item_code', frm.doc.template);
+ if (!frm.doc.description)
+ frm.set_value('description', frm.doc.template);
mark_change_in_item(frm);
},
+
rate: function(frm) {
mark_change_in_item(frm);
},
+
is_billable: function (frm) {
mark_change_in_item(frm);
},
+
item_group: function(frm) {
mark_change_in_item(frm);
},
+
description: function(frm) {
mark_change_in_item(frm);
},
+
medical_department: function(frm) {
mark_change_in_item(frm);
},
+
refresh: function(frm) {
- frm.fields_dict["items"].grid.set_column_disp("barcode", false);
- frm.fields_dict["items"].grid.set_column_disp("batch_no", false);
- cur_frm.set_df_property("item_code", "read_only", frm.doc.__islocal ? 0 : 1);
- if(!frm.doc.__islocal) {
+ frm.fields_dict['items'].grid.set_column_disp('barcode', false);
+ frm.fields_dict['items'].grid.set_column_disp('batch_no', false);
+
+ if (!frm.doc.__islocal) {
cur_frm.add_custom_button(__('Change Item Code'), function() {
change_template_code(frm.doc);
- } );
- if(frm.doc.disabled == 1){
- cur_frm.add_custom_button(__('Enable Template'), function() {
- enable_template(frm.doc);
- } );
- }
- else{
- cur_frm.add_custom_button(__('Disable Template'), function() {
- disable_template(frm.doc);
- } );
- }
+ });
}
}
});
-var mark_change_in_item = function(frm) {
- if(!frm.doc.__islocal){
+let mark_change_in_item = function(frm) {
+ if (!frm.doc.__islocal) {
frm.doc.change_in_item = 1;
}
};
-var disable_template = function(doc){
- frappe.call({
- method: "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.disable_enable_template",
- args: {status: 1, name: doc.name, item_code: doc.item_code, is_billable: doc.is_billable},
- callback: function(){
- cur_frm.reload_doc();
- }
- });
-};
-
-var enable_template = function(doc){
- frappe.call({
- method: "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.disable_enable_template",
- args: {status: 0, name: doc.name, item_code: doc.item_code, is_billable: doc.is_billable},
- callback: function(){
- cur_frm.reload_doc();
- }
- });
-};
-
-
-var change_template_code = function(doc){
- var d = new frappe.ui.Dialog({
- title:__("Change Template Code"),
+let change_template_code = function(doc) {
+ let d = new frappe.ui.Dialog({
+ title:__('Change Item Code'),
fields:[
{
- "fieldtype": "Data",
- "label": "Template Code",
- "fieldname": "Item Code",
- reqd:1
- },
- {
- "fieldtype": "Button",
- "label": __("Change Code"),
- click: function() {
- var values = d.get_values();
- if(!values)
- return;
- change_item_code_from_template(values["Item Code"], doc);
- d.hide();
- }
+ 'fieldtype': 'Data',
+ 'label': 'Item Code',
+ 'fieldname': 'item_code',
+ reqd: 1
}
- ]
+ ],
+ primary_action: function() {
+ let values = d.get_values();
+
+ if (values) {
+ frappe.call({
+ 'method': 'erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.change_item_code_from_template',
+ 'args': {item_code: values.item_code, doc: doc},
+ callback: function () {
+ cur_frm.reload_doc();
+ frappe.show_alert({
+ message: 'Item Code renamed successfully',
+ indicator: 'green'
+ });
+ }
+ });
+ }
+ d.hide();
+ },
+ primary_action_label: __('Change Item Code')
});
d.show();
- d.set_values({
- 'Item Code': doc.item_code
- });
-};
-var change_item_code_from_template = function(item_code, doc){
- frappe.call({
- "method": "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.change_item_code_from_template",
- "args": {item_code: item_code, doc: doc},
- callback: function () {
- cur_frm.reload_doc();
- frappe.show_alert({
- message: "Item Code renamed successfully",
- indicator: "green"
- });
- }
+ d.set_values({
+ 'item_code': doc.item_code
});
};
frappe.ui.form.on('Clinical Procedure Item', {
- qty: function(frm, cdt, cdn){
- var d = locals[cdt][cdn];
- frappe.model.set_value(cdt, cdn, "transfer_qty", d.qty*d.conversion_factor);
+ qty: function(frm, cdt, cdn) {
+ let d = locals[cdt][cdn];
+ frappe.model.set_value(cdt, cdn, 'transfer_qty', d.qty * d.conversion_factor);
},
+
uom: function(doc, cdt, cdn){
- var d = locals[cdt][cdn];
- if(d.uom && d.item_code){
+ let d = locals[cdt][cdn];
+ if (d.uom && d.item_code) {
return frappe.call({
- method: "erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details",
+ method: 'erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details',
args: {
item_code: d.item_code,
uom: d.uom,
qty: d.qty
},
callback: function(r) {
- if(r.message) {
+ if (r.message) {
frappe.model.set_value(cdt, cdn, r.message);
}
}
});
}
},
+
item_code: function(frm, cdt, cdn) {
- var d = locals[cdt][cdn];
- if(d.item_code) {
+ let d = locals[cdt][cdn];
+ if (d.item_code) {
let args = {
'item_code' : d.item_code,
'transfer_qty' : d.transfer_qty,
- 'company' : frm.doc.company,
- 'quantity' : d.qty
+ 'quantity' : d.qty
};
return frappe.call({
- doc: frm.doc,
- method: "get_item_details",
- args: args,
+ method: 'erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.get_item_details',
+ args: {args: args},
callback: function(r) {
- if(r.message) {
- var d = locals[cdt][cdn];
- $.each(r.message, function(k, v){
+ if (r.message) {
+ let d = locals[cdt][cdn];
+ $.each(r.message, function(k, v) {
d[k] = v;
});
- refresh_field("items");
+ refresh_field('items');
}
}
});
}
}
});
+
// List Stock items
-cur_frm.set_query("item_code", "items", function() {
+cur_frm.set_query('item_code', 'items', function() {
return {
filters: {
is_stock_item:1
diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json
index 26564a3..9cfd682 100644
--- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json
+++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json
@@ -1,807 +1,236 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:template",
- "beta": 1,
- "creation": "2017-10-05 14:59:55.438359",
- "custom": 0,
- "description": "Procedure Template",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:template",
+ "beta": 1,
+ "creation": "2017-10-05 14:59:55.438359",
+ "description": "Procedure Template",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "template",
+ "item",
+ "item_code",
+ "item_group",
+ "description",
+ "column_break_5",
+ "disabled",
+ "is_billable",
+ "rate",
+ "medical_department",
+ "consumables",
+ "consume_stock",
+ "items",
+ "sample_collection",
+ "sample",
+ "sample_uom",
+ "sample_qty",
+ "column_break_21",
+ "sample_details",
+ "change_in_item"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "template",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Template Name",
- "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,
+ "fieldname": "template",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "Template Name",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item_code",
+ "fieldname": "item_code",
+ "fieldtype": "Data",
+ "label": "Item Code",
+ "options": "Item",
+ "read_only_depends_on": "eval: !doc.__islocal ",
+ "reqd": 1
+ },
+ {
+ "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 Code",
- "length": 0,
- "no_copy": 1,
- "options": "Item",
- "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
- },
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "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": "item_group",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "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": "medical_department",
+ "fieldtype": "Link",
+ "label": "Medical Department",
+ "options": "Medical Department"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "medical_department",
- "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": "Medical Department",
- "length": 0,
- "no_copy": 0,
- "options": "Medical Department",
- "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_5",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_5",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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_billable",
+ "fieldtype": "Check",
+ "label": "Is Billable"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "is_billable",
- "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 Billable",
- "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": "is_billable",
+ "fieldname": "rate",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Rate",
+ "mandatory_depends_on": "is_billable"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "is_billable",
- "fieldname": "rate",
- "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": "Rate",
- "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": "description",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Description",
+ "no_copy": 1,
+ "reqd": 1
+ },
{
- "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": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 1,
- "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": "0",
+ "fieldname": "consume_stock",
+ "fieldtype": "Check",
+ "label": "Allow Stock Consumption",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "section_break_9",
- "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": "consumables",
+ "fieldtype": "Section Break",
+ "label": "Consumables"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "consume_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 Stock Consumption",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "depends_on": "eval:doc.consume_stock == 1",
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "ignore_user_permissions": 1,
+ "label": "Items",
+ "options": "Clinical Procedure Item"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.consume_stock == 1",
- "fieldname": "consumables",
- "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": "Consumables",
- "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": "sample_collection",
+ "fieldtype": "Section Break",
+ "label": "Sample Collection"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "items",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Items",
- "length": 0,
- "no_copy": 0,
- "options": "Clinical Procedure Item",
- "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": "sample",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Sample",
+ "options": "Lab Test Sample"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "depends_on": "",
- "fieldname": "sample_collection",
- "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": "Sample Collection",
- "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": "sample.sample_uom",
+ "fieldname": "sample_uom",
+ "fieldtype": "Data",
+ "label": "Sample UOM",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Sample",
- "length": 0,
- "no_copy": 0,
- "options": "Lab Test Sample",
- "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": "sample_qty",
+ "fieldtype": "Float",
+ "label": "Quantity"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "sample.sample_uom",
- "fieldname": "sample_uom",
- "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": "UOM",
- "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": "column_break_21",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample_qty",
- "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": "Quantity",
- "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": "sample_details",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Collection Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_21",
- "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
- },
+ "default": "0",
+ "fieldname": "change_in_item",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Change In Item",
+ "no_copy": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample_details",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Collection 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
- },
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "label": "Disabled"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "change_in_item",
- "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": "Change In Item",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "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": 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": "Disabled",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "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": "item",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 1,
- "options": "Item",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Item",
+ "no_copy": 1,
+ "options": "Item",
+ "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": "2019-02-12 11:37:18.713344",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Clinical Procedure Template",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "links": [],
+ "modified": "2020-02-28 14:16:13.184981",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Clinical Procedure Template",
+ "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
- },
+ },
{
- "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": "Healthcare Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Nursing User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
- },
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Nursing User",
+ "share": 1
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Physician",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "template",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "template",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "template",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "template",
+ "track_changes": 1,
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py
index 5a71ca5..3f295af 100644
--- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py
+++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py
@@ -7,126 +7,114 @@
from frappe import _
from frappe.model.document import Document
from frappe.model.rename_doc import rename_doc
-from frappe.utils import nowdate
class ClinicalProcedureTemplate(Document):
- def on_update(self):
- #Item and Price List update --> if (change_in_item)
- if(self.change_in_item and self.is_billable == 1 and self.item):
- updating_item(self)
- if(self.rate != 0.0):
- updating_rate(self)
- elif(self.is_billable == 0 and self.item):
- frappe.db.set_value("Item",self.item,"disabled",1)
-
- frappe.db.set_value(self.doctype,self.name,"change_in_item",0)
- self.reload()
+ def validate(self):
+ self.enable_disable_item()
def after_insert(self):
create_item_from_template(self)
- #Call before delete the template
- def on_trash(self):
- if(self.item):
- try:
- frappe.delete_doc("Item",self.item)
- except Exception:
- frappe.throw(_("""Not permitted. Please disable the Procedure Template"""))
+ def on_update(self):
+ if self.change_in_item:
+ self.update_item_and_item_price()
- def get_item_details(self, args=None):
- item = frappe.db.sql("""select stock_uom, item_name
- from `tabItem`
- where name = %s
- and disabled=0
- and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""",
- (args.get('item_code'), nowdate()), as_dict = 1)
- if not item:
- frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get('item_code')))
+ def enable_disable_item(self):
+ if self.is_billable:
+ if self.disabled:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
+ else:
+ frappe.db.set_value('Item', self.item, 'disabled', 0)
- item = item[0]
+ def update_item_and_item_price(self):
+ if self.is_billable and self.item:
+ item_doc = frappe.get_doc('Item', {'item_code': self.item})
+ item_doc.item_name = self.template
+ item_doc.item_group = self.item_group
+ item_doc.description = self.description
+ item_doc.disabled = 0
+ item_doc.save(ignore_permissions=True)
- ret = {
- 'uom' : item.stock_uom,
- 'stock_uom' : item.stock_uom,
- 'item_name' : item.item_name,
- 'quantity' : 0,
- 'transfer_qty' : 0,
- 'conversion_factor' : 1
- }
- return ret
+ if self.rate:
+ item_price = frappe.get_doc('Item Price', {'item_code': self.item})
+ item_price.item_name = self.template
+ item_price.price_list_rate = self.rate
+ item_price.save()
-def updating_item(self):
- frappe.db.sql("""update `tabItem` set item_name=%s, item_group=%s, disabled=0,
- description=%s, modified=NOW() where item_code=%s""",
- (self.template, self.item_group , self.description, self.item))
-def updating_rate(self):
- frappe.db.sql("""update `tabItem Price` set item_name=%s, price_list_rate=%s, modified=NOW() where
- item_code=%s""",(self.template, self.rate, self.item))
+ elif not self.is_billable and self.item:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
+
+ self.db_set('change_in_item', 0)
+
+
+@frappe.whitelist()
+def get_item_details(args=None):
+ if not isinstance(args, dict):
+ args = json.loads(args)
+
+ item = frappe.db.get_all('Item',
+ filters={
+ 'disabled': 0,
+ 'name': args.get('item_code')
+ },
+ fields=['stock_uom', 'item_name']
+ )
+
+ if not item:
+ frappe.throw(_('Item {0} is not active').format(args.get('item_code')))
+
+ item = item[0]
+ ret = {
+ 'uom': item.stock_uom,
+ 'stock_uom': item.stock_uom,
+ 'item_name': item.item_name,
+ 'qty': 1,
+ 'transfer_qty': 0,
+ 'conversion_factor': 1
+ }
+ return ret
def create_item_from_template(doc):
- disabled = 1
-
- if(doc.is_billable == 1):
+ disabled = doc.disabled
+ if doc.is_billable and not doc.disabled:
disabled = 0
- #insert item
- item = frappe.get_doc({
- "doctype": "Item",
- "item_code": doc.template,
- "item_name":doc.template,
- "item_group": doc.item_group,
- "description":doc.description,
- "is_sales_item": 1,
- "is_service_item": 1,
- "is_purchase_item": 0,
- "is_stock_item": 0,
- "show_in_website": 0,
- "is_pro_applicable": 0,
- "disabled": disabled,
- "stock_uom": "Unit"
- }).insert(ignore_permissions=True)
+ item = frappe.get_doc({
+ 'doctype': 'Item',
+ 'item_code': doc.template,
+ 'item_name':doc.template,
+ 'item_group': doc.item_group,
+ 'description':doc.description,
+ 'is_sales_item': 1,
+ 'is_service_item': 1,
+ 'is_purchase_item': 0,
+ 'is_stock_item': 0,
+ 'show_in_website': 0,
+ 'is_pro_applicable': 0,
+ 'disabled': disabled,
+ 'stock_uom': 'Unit'
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
- #insert item price
- #get item price list to insert item price
- if(doc.rate != 0.0):
- price_list_name = frappe.db.get_value("Price List", {"selling": 1})
- if(doc.rate):
- make_item_price(item.name, price_list_name, doc.rate)
- else:
- make_item_price(item.name, price_list_name, 0.0)
- #Set item to the template
- frappe.db.set_value("Clinical Procedure Template", doc.name, "item", item.name)
+ make_item_price(item.name, doc.rate)
+ doc.db_set('item', item.name)
- doc.reload() #refresh the doc after insert.
-
-def make_item_price(item, price_list_name, item_price):
+def make_item_price(item, item_price):
+ price_list_name = frappe.db.get_value('Price List', {'selling': 1})
frappe.get_doc({
- "doctype": "Item Price",
- "price_list": price_list_name,
- "item_code": item,
- "price_list_rate": item_price
- }).insert(ignore_permissions=True)
+ 'doctype': 'Item Price',
+ 'price_list': price_list_name,
+ 'item_code': item,
+ 'price_list_rate': item_price
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
@frappe.whitelist()
def change_item_code_from_template(item_code, doc):
- args = json.loads(doc)
- doc = frappe._dict(args)
+ doc = frappe._dict(json.loads(doc))
- if(frappe.db.exists({
- "doctype": "Item",
- "item_code": item_code})):
- frappe.throw(_("Code {0} already exist").format(item_code))
+ if frappe.db.exists('Item', {'item_code': item_code}):
+ frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
else:
- rename_doc("Item", doc.item_code, item_code, ignore_permissions=True)
- frappe.db.set_value("Clinical Procedure Template", doc.name, "item_code", item_code)
+ rename_doc('Item', doc.item_code, item_code, ignore_permissions=True)
+ frappe.db.set_value('Clinical Procedure Template', doc.name, 'item_code', item_code)
return
-@frappe.whitelist()
-def disable_enable_template(status, name, item_code):
- frappe.db.set_value("Clinical Procedure Template", name, "disabled", status)
- if (frappe.db.exists({ #set Item's disabled field to status
- "doctype": "Item",
- "item_code": item_code})):
- frappe.db.set_value("Item", item_code, "disabled", status)
-
- return
diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template_dashboard.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template_dashboard.py
new file mode 100644
index 0000000..9aab521
--- /dev/null
+++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'procedure_template',
+ 'transactions': [
+ {
+ 'label': _('Consultations'),
+ 'items': ['Clinical Procedure']
+ }
+ ]
+ }
diff --git a/erpnext/healthcare/doctype/codification_table/codification_table.json b/erpnext/healthcare/doctype/codification_table/codification_table.json
index e65ae77..9a917b4 100644
--- a/erpnext/healthcare/doctype/codification_table/codification_table.json
+++ b/erpnext/healthcare/doctype/codification_table/codification_table.json
@@ -1,140 +1,56 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-06-22 13:09:23.159579",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2017-06-22 13:09:23.159579",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "medical_code",
+ "code",
+ "description"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "medical_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Medical Code",
- "length": 0,
- "no_copy": 0,
- "options": "Medical Code",
- "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": "medical_code",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Medical Code",
+ "options": "Medical Code",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "medical_code.code",
- "fieldname": "code",
- "fieldtype": "Read Only",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "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
- },
+ "fieldname": "code",
+ "fieldtype": "Data",
+ "ignore_xss_filter": 1,
+ "in_list_view": 1,
+ "label": "Code",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "medical_code.description",
- "fieldname": "description",
- "fieldtype": "Read Only",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "in_list_view": 1,
+ "label": "Description",
+ "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": 1,
- "max_attachments": 0,
- "modified": "2018-05-16 22:43:27.047479",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Codification Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 13:17:49.016293",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Codification Table",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json
index 5647d3c..5e4d59c 100644
--- a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json
+++ b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json
@@ -1,381 +1,116 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2016-09-16 16:41:45.533374",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2016-09-16 16:41:45.533374",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "drug_code",
+ "drug_name",
+ "dosage",
+ "period",
+ "dosage_form",
+ "column_break_7",
+ "comment",
+ "usage_interval",
+ "interval",
+ "interval_uom",
+ "update_schedule"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "drug_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Drug Code",
- "length": 0,
- "no_copy": 0,
- "options": "Item",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "drug_code",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Drug",
+ "options": "Item",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "drug_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": "Description/Strength",
- "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,
- "unique": 0
- },
+ "fetch_from": "drug_code.item_name",
+ "fieldname": "drug_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Drug Name / Description"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "dosage",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Dosage",
- "length": 0,
- "no_copy": 0,
- "options": "Prescription Dosage",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "dosage",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Dosage",
+ "options": "Prescription Dosage"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "period",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Period",
- "length": 0,
- "no_copy": 0,
- "options": "Prescription Duration",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "period",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Period",
+ "options": "Prescription Duration"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "dosage_form",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Dosage Form",
- "length": 0,
- "no_copy": 0,
- "options": "Dosage Form",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "dosage_form",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Dosage Form",
+ "options": "Dosage Form"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_7",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "column_break_7",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "comment",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Comment",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "comment",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "in_list_view": 1,
+ "label": "Comment"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "use_interval",
- "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": "Dosage by time interval",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "depends_on": "use_interval",
+ "fieldname": "interval",
+ "fieldtype": "Int",
+ "in_list_view": 1,
+ "label": "Interval"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "use_interval",
- "fieldname": "interval",
- "fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Interval",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "default": "1",
+ "fieldname": "update_schedule",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Update Schedule",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "use_interval",
- "fieldname": "in_every",
- "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": "Interval UOM",
- "length": 0,
- "no_copy": 0,
- "options": "\nHour\nDay",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "depends_on": "use_interval",
+ "fieldname": "interval_uom",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Interval UOM",
+ "options": "\nHour\nDay"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fieldname": "update_schedule",
- "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": "Update Schedule",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
+ "default": "0",
+ "fieldname": "usage_interval",
+ "fieldtype": "Check",
+ "label": "Dosage by Time Interval"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2017-10-04 17:09:54.998517",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Drug Prescription",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 17:02:42.741338",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Drug Prescription",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py
index 0d99198..68a2dc5 100755
--- a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py
+++ b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.py
@@ -12,21 +12,21 @@
dosage = None
period = None
- if(self.dosage):
- dosage = frappe.get_doc("Prescription Dosage",self.dosage)
+ if self.dosage:
+ dosage = frappe.get_doc('Prescription Dosage', self.dosage)
for item in dosage.dosage_strength:
quantity += item.strength
- if(self.period and self.interval):
- period = frappe.get_doc("Prescription Duration",self.period)
- if(self.interval < period.get_days()):
- quantity = quantity*(period.get_days()/self.interval)
+ if self.period and self.interval:
+ period = frappe.get_doc('Prescription Duration', self.period)
+ if self.interval < period.get_days():
+ quantity = quantity * (period.get_days()/self.interval)
- elif(self.interval and self.in_every and self.period):
- period = frappe.get_doc("Prescription Duration",self.period)
- interval_in = self.in_every
- if(interval_in == 'Day' and (self.interval < period.get_days())):
+ elif self.interval and self.interval_uom and self.period:
+ period = frappe.get_doc('Prescription Duration', self.period)
+ interval_in = self.interval_uom
+ if interval_in == 'Day' and self.interval < period.get_days():
quantity = period.get_days()/self.interval
- elif(interval_in == 'Hour' and (self.interval < period.get_hours())):
+ elif interval_in == 'Hour' and self.interval < period.get_hours():
quantity = period.get_hours()/self.interval
if quantity > 0:
return quantity
diff --git a/erpnext/healthcare/doctype/fee_validity/fee_validity.json b/erpnext/healthcare/doctype/fee_validity/fee_validity.json
index 802f04a..b001bf0 100644
--- a/erpnext/healthcare/doctype/fee_validity/fee_validity.json
+++ b/erpnext/healthcare/doctype/fee_validity/fee_validity.json
@@ -1,259 +1,134 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-01-05 10:56:29.564806",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "beta": 1,
+ "creation": "2017-01-05 10:56:29.564806",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "practitioner",
+ "patient",
+ "column_break_3",
+ "status",
+ "section_break_5",
+ "section_break_3",
+ "max_visits",
+ "visited",
+ "ref_appointments",
+ "column_break_6",
+ "start_date",
+ "valid_till"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "practitioner",
- "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": "Healthcare Practitioner",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "practitioner",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner",
+ "read_only": 1,
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient",
- "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": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "read_only": 1,
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "max_visit",
- "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 number of visit",
- "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": "visited",
+ "fieldtype": "Int",
+ "label": "Visited yet",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "visited",
- "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": "Visited yet",
- "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": "valid_till",
+ "fieldtype": "Date",
+ "label": "Valid till",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "valid_till",
- "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": "Valid till",
- "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_3",
+ "fieldtype": "Section Break",
+ "label": "Validity",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "ref_invoice",
- "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": "Reference Inv",
- "length": 0,
- "no_copy": 0,
- "options": "Sales Invoice",
- "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_6",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "max_visits",
+ "fieldtype": "Int",
+ "label": "Max number of visit",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Status",
+ "options": "Completed\nPending",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "ref_appointment.appointment_date",
+ "fieldname": "start_date",
+ "fieldtype": "Date",
+ "label": "Start Date",
+ "read_only": 1
+ },
+ {
+ "fieldname": "ref_appointments",
+ "fieldtype": "Table MultiSelect",
+ "label": "Reference Appointments",
+ "options": "Fee Validity Reference",
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break"
}
- ],
- "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-07-16 12:43:45.635230",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Fee Validity",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "in_create": 1,
+ "links": [],
+ "modified": "2020-03-17 20:25:06.487418",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Fee Validity",
+ "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": "Healthcare Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "practitioner, patient",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "practitioner",
- "track_changes": 0,
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "practitioner, patient",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "practitioner"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/fee_validity/fee_validity.py b/erpnext/healthcare/doctype/fee_validity/fee_validity.py
index 9028545..058bc97 100644
--- a/erpnext/healthcare/doctype/fee_validity/fee_validity.py
+++ b/erpnext/healthcare/doctype/fee_validity/fee_validity.py
@@ -9,28 +9,55 @@
import datetime
class FeeValidity(Document):
- pass
+ def validate(self):
+ self.update_status()
+ self.set_start_date()
-def update_fee_validity(fee_validity, date, ref_invoice=None):
- max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
- valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
- if not valid_days:
- valid_days = 1
- if not max_visit:
- max_visit = 1
- date = getdate(date)
- valid_till = date + datetime.timedelta(days=int(valid_days))
- fee_validity.max_visit = max_visit
+ def update_status(self):
+ if self.visited >= self.max_visits:
+ self.status = 'Completed'
+ else:
+ self.status = 'Pending'
+
+ def set_start_date(self):
+ self.start_date = getdate()
+ for appointment in self.ref_appointments:
+ appointment_date = frappe.db.get_value('Patient Appointment', appointment.appointment, 'appointment_date')
+ if getdate(appointment_date) < self.start_date:
+ self.start_date = getdate(appointment_date)
+
+
+def create_fee_validity(appointment):
+ if not check_is_new_patient(appointment):
+ return
+
+ fee_validity = frappe.new_doc('Fee Validity')
+ fee_validity.practitioner = appointment.practitioner
+ fee_validity.patient = appointment.patient
+ fee_validity.max_visits = frappe.db.get_single_value('Healthcare Settings', 'max_visits') or 1
+ valid_days = frappe.db.get_single_value('Healthcare Settings', 'valid_days') or 1
fee_validity.visited = 1
- fee_validity.valid_till = valid_till
- fee_validity.ref_invoice = ref_invoice
+ fee_validity.valid_till = getdate(appointment.appointment_date) + datetime.timedelta(days=int(valid_days))
+ fee_validity.append('ref_appointments', {
+ 'appointment': appointment.name
+ })
fee_validity.save(ignore_permissions=True)
return fee_validity
+def check_is_new_patient(appointment):
+ validity_exists = frappe.db.exists('Fee Validity', {
+ 'practitioner': appointment.practitioner,
+ 'patient': appointment.patient
+ })
+ if validity_exists:
+ return False
-def create_fee_validity(practitioner, patient, date, ref_invoice=None):
- fee_validity = frappe.new_doc("Fee Validity")
- fee_validity.practitioner = practitioner
- fee_validity.patient = patient
- fee_validity = update_fee_validity(fee_validity, date, ref_invoice)
- return fee_validity
+ appointment_exists = frappe.db.get_all('Patient Appointment', {
+ 'name': ('!=', appointment.name),
+ 'status': ('!=', 'Cancelled'),
+ 'patient': appointment.patient,
+ 'practitioner': appointment.practitioner
+ })
+ if len(appointment_exists) and appointment_exists[0]:
+ return False
+ return True
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
index 26b1450..cdf692e 100644
--- a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
+++ b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
@@ -5,100 +5,44 @@
import frappe
import unittest
-from frappe.utils.make_random import get_random
-from frappe.utils import nowdate, add_days, getdate
+from frappe.utils import nowdate, add_days
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_appointment, create_healthcare_service_items
test_dependencies = ["Company"]
class TestFeeValidity(unittest.TestCase):
- def test_fee_validity(self):
+ def setUp(self):
frappe.db.sql("""delete from `tabPatient Appointment`""")
frappe.db.sql("""delete from `tabFee Validity`""")
- patient = get_random("Patient")
- practitioner = get_random("Healthcare Practitioner")
- department = get_random("Medical Department")
+ frappe.db.sql("""delete from `tabPatient`""")
- if not patient:
- patient = frappe.new_doc("Patient")
- patient.patient_name = "_Test Patient"
- patient.sex = "Male"
- patient.save(ignore_permissions=True)
- patient = patient.name
+ def test_fee_validity(self):
+ item = create_healthcare_service_items()
+ healthcare_settings = frappe.get_single("Healthcare Settings")
+ healthcare_settings.enable_free_follow_ups = 1
+ healthcare_settings.max_visits = 2
+ healthcare_settings.valid_days = 7
+ healthcare_settings.automate_appointment_invoicing = 1
+ healthcare_settings.op_consulting_charge_item = item
+ healthcare_settings.save(ignore_permissions=True)
+ patient, medical_department, practitioner = create_healthcare_docs()
- if not department:
- medical_department = frappe.new_doc("Medical Department")
- medical_department.department = "_Test Medical Department"
- medical_department.save(ignore_permissions=True)
- department = medical_department.name
-
- if not practitioner:
- practitioner = frappe.new_doc("Healthcare Practitioner")
- practitioner.first_name = "_Test Healthcare Practitioner"
- practitioner.department = department
- practitioner.save(ignore_permissions=True)
- practitioner = practitioner.name
-
-
-
- frappe.db.set_value("Healthcare Settings", None, "max_visit", 2)
- frappe.db.set_value("Healthcare Settings", None, "valid_days", 7)
-
- appointment = create_appointment(patient, practitioner, nowdate(), department)
+ # appointment should not be invoiced. Check Fee Validity created for new patient
+ appointment = create_appointment(patient, practitioner, nowdate())
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
self.assertEqual(invoiced, 0)
- invoice_appointment(appointment)
-
- appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4), department)
- invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
- self.assertTrue(invoiced)
-
- appointment = create_appointment(patient, practitioner, add_days(nowdate(), 5), department)
+ # appointment should not be invoiced as it is within fee validity
+ appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4))
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
self.assertEqual(invoiced, 0)
- appointment = create_appointment(patient, practitioner, add_days(nowdate(), 10), department)
+ # appointment should be invoiced as it is within fee validity but the max_visits are exceeded
+ appointment = create_appointment(patient, practitioner, add_days(nowdate(), 5), invoice=1)
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
- self.assertEqual(invoiced, 0)
+ self.assertEqual(invoiced, 1)
-def create_appointment(patient, practitioner, appointment_date, department):
- appointment = frappe.new_doc("Patient Appointment")
- appointment.patient = patient
- appointment.practitioner = practitioner
- appointment.department = department
- appointment.appointment_date = appointment_date
- appointment.company = "_Test Company"
- appointment.duration = 15
- appointment.save(ignore_permissions=True)
- return appointment
-
-def invoice_appointment(appointment_doc):
- if not appointment_doc.name:
- return False
- sales_invoice = frappe.new_doc("Sales Invoice")
- sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
- sales_invoice.due_date = getdate()
- sales_invoice.is_pos = 0
- sales_invoice.company = appointment_doc.company
- sales_invoice.debit_to = "_Test Receivable - _TC"
-
- create_invoice_items(appointment_doc, sales_invoice)
-
- sales_invoice.save(ignore_permissions=True)
- sales_invoice.submit()
-
-def create_invoice_items(appointment, invoice):
- item_line = invoice.append("items")
- item_line.item_name = "Consulting Charges"
- item_line.description = "Consulting Charges: " + appointment.practitioner
- item_line.uom = "Nos"
- item_line.conversion_factor = 1
- item_line.income_account = "_Test Account Cost for Goods Sold - _TC"
- item_line.cost_center = "_Test Cost Center - _TC"
- item_line.rate = 250
- item_line.amount = 250
- item_line.qty = 1
- item_line.reference_dt = "Patient Appointment"
- item_line.reference_dn = appointment.name
-
- return invoice
+ # appointment should be invoiced as it is not within fee validity and the max_visits are exceeded
+ appointment = create_appointment(patient, practitioner, add_days(nowdate(), 10), invoice=1)
+ invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
+ self.assertEqual(invoiced, 1)
\ No newline at end of file
diff --git a/erpnext/healthcare/page/appointment_analytic/__init__.py b/erpnext/healthcare/doctype/fee_validity_reference/__init__.py
similarity index 100%
rename from erpnext/healthcare/page/appointment_analytic/__init__.py
rename to erpnext/healthcare/doctype/fee_validity_reference/__init__.py
diff --git a/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.json b/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.json
new file mode 100644
index 0000000..40f128e
--- /dev/null
+++ b/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.json
@@ -0,0 +1,32 @@
+{
+ "actions": [],
+ "creation": "2020-03-13 16:08:42.859996",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "appointment"
+ ],
+ "fields": [
+ {
+ "fieldname": "appointment",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient Appointment",
+ "options": "Patient Appointment",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-15 00:27:02.076470",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Fee Validity Reference",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.py b/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.py
new file mode 100644
index 0000000..c819280
--- /dev/null
+++ b/erpnext/healthcare/doctype/fee_validity_reference/fee_validity_reference.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class FeeValidityReference(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.js b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.js
index efca484..4ab3b6e 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.js
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.js
@@ -4,7 +4,7 @@
frappe.ui.form.on('Healthcare Practitioner', {
setup: function(frm) {
frm.set_query('account', 'accounts', function(doc, cdt, cdn) {
- var d = locals[cdt][cdn];
+ let d = locals[cdt][cdn];
return {
filters: {
'root_type': 'Income',
@@ -16,23 +16,28 @@
},
refresh: function(frm) {
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Healthcare Practitioner'};
- if(!frm.is_new()) {
+
+ if (!frm.is_new()) {
frappe.contacts.render_address_and_contact(frm);
+ } else {
+ frappe.contacts.clear_address_and_contact(frm);
}
- frm.set_query("service_unit", "practitioner_schedules", function(){
+
+ frm.set_query('service_unit', 'practitioner_schedules', function(){
return {
filters: {
- "is_group": false,
- "allow_appointments": true
+ 'is_group': false,
+ 'allow_appointments': true
}
};
});
+
set_query_service_item(frm, 'inpatient_visit_charge_item');
set_query_service_item(frm, 'op_consulting_charge_item');
}
});
-var set_query_service_item = function(frm, service_item_field) {
+let set_query_service_item = function(frm, service_item_field) {
frm.set_query(service_item_field, function() {
return {
filters: {
@@ -43,62 +48,62 @@
});
};
-frappe.ui.form.on("Healthcare Practitioner", "user_id",function(frm) {
- if(frm.doc.user_id){
+frappe.ui.form.on('Healthcare Practitioner', 'user_id',function(frm) {
+ if (frm.doc.user_id) {
frappe.call({
- "method": "frappe.client.get",
+ 'method': 'frappe.client.get',
args: {
- doctype: "User",
+ doctype: 'User',
name: frm.doc.user_id
},
callback: function (data) {
frappe.model.get_value('Employee', {'user_id': frm.doc.user_id}, 'name',
function(data) {
- if(data){
- if(!frm.doc.employee || frm.doc.employee != data.name)
- frappe.model.set_value(frm.doctype,frm.docname, "employee", data.name);
- }else{
- frappe.model.set_value(frm.doctype,frm.docname, "employee", "");
+ if (data) {
+ if (!frm.doc.employee || frm.doc.employee != data.name)
+ frappe.model.set_value(frm.doctype, frm.docname, 'employee', data.name);
+ } else {
+ frappe.model.set_value(frm.doctype, frm.docname, 'employee', '');
}
}
);
- if(!frm.doc.first_name || frm.doc.first_name != data.message.first_name)
- frappe.model.set_value(frm.doctype,frm.docname, "first_name", data.message.first_name);
- if(!frm.doc.middle_name || frm.doc.middle_name != data.message.middle_name)
- frappe.model.set_value(frm.doctype,frm.docname, "middle_name", data.message.middle_name);
- if(!frm.doc.last_name || frm.doc.last_name != data.message.last_name)
- frappe.model.set_value(frm.doctype,frm.docname, "last_name", data.message.last_name);
- if(!frm.doc.mobile_phone || frm.doc.mobile_phone != data.message.mobile_no)
- frappe.model.set_value(frm.doctype,frm.docname, "mobile_phone", data.message.mobile_no);
+ if (!frm.doc.first_name || frm.doc.first_name != data.message.first_name)
+ frappe.model.set_value(frm.doctype,frm.docname, 'first_name', data.message.first_name);
+ if (!frm.doc.middle_name || frm.doc.middle_name != data.message.middle_name)
+ frappe.model.set_value(frm.doctype,frm.docname, 'middle_name', data.message.middle_name);
+ if (!frm.doc.last_name || frm.doc.last_name != data.message.last_name)
+ frappe.model.set_value(frm.doctype,frm.docname, 'last_name', data.message.last_name);
+ if (!frm.doc.mobile_phone || frm.doc.mobile_phone != data.message.mobile_no)
+ frappe.model.set_value(frm.doctype,frm.docname, 'mobile_phone', data.message.mobile_no);
}
});
}
});
-frappe.ui.form.on("Healthcare Practitioner", "employee", function(frm) {
- if(frm.doc.employee){
+frappe.ui.form.on('Healthcare Practitioner', 'employee', function(frm) {
+ if (frm.doc.employee){
frappe.call({
- "method": "frappe.client.get",
+ 'method': 'frappe.client.get',
args: {
- doctype: "Employee",
+ doctype: 'Employee',
name: frm.doc.employee
},
callback: function (data) {
- if(!frm.doc.user_id || frm.doc.user_id != data.message.user_id)
- frm.set_value("user_id", data.message.user_id);
- if(!frm.doc.designation || frm.doc.designation != data.message.designation)
- frappe.model.set_value(frm.doctype,frm.docname, "designation", data.message.designation);
- if(!frm.doc.first_name || !frm.doc.user_id){
- frappe.model.set_value(frm.doctype,frm.docname, "first_name", data.message.employee_name);
- frappe.model.set_value(frm.doctype,frm.docname, "middle_name", "");
- frappe.model.set_value(frm.doctype,frm.docname, "last_name", "");
+ if (!frm.doc.user_id || frm.doc.user_id != data.message.user_id)
+ frm.set_value('user_id', data.message.user_id);
+ if (!frm.doc.designation || frm.doc.designation != data.message.designation)
+ frappe.model.set_value(frm.doctype,frm.docname, 'designation', data.message.designation);
+ if (!frm.doc.first_name || !frm.doc.user_id){
+ frappe.model.set_value(frm.doctype,frm.docname, 'first_name', data.message.first_name);
+ frappe.model.set_value(frm.doctype,frm.docname, 'middle_name', '');
+ frappe.model.set_value(frm.doctype,frm.docname, 'last_name', data.message.last_name);
}
- if(!frm.doc.mobile_phone || !frm.doc.user_id)
- frappe.model.set_value(frm.doctype,frm.docname, "mobile_phone", data.message.cell_number);
- if(!frm.doc.address || frm.doc.address != data.message.current_address)
- frappe.model.set_value(frm.doctype,frm.docname, "address", data.message.current_address);
+ if (!frm.doc.mobile_phone || !frm.doc.user_id)
+ frappe.model.set_value(frm.doctype,frm.docname, 'mobile_phone', data.message.cell_number);
+ if (!frm.doc.address || frm.doc.address != data.message.current_address)
+ frappe.model.set_value(frm.doctype,frm.docname, 'address', data.message.current_address);
}
});
}
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json
index 4a848a0..fd5b6e1 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json
@@ -1,1041 +1,327 @@
{
+ "actions": [],
"allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
- "autoname": "",
+ "autoname": "naming_series:",
"beta": 1,
"creation": "2016-02-23 11:20:53.565119",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
- "editable_grid": 0,
+ "engine": "InnoDB",
+ "field_order": [
+ "basic_details_section",
+ "naming_series",
+ "first_name",
+ "middle_name",
+ "last_name",
+ "practitioner_name",
+ "gender",
+ "image",
+ "column_break_7",
+ "status",
+ "mobile_phone",
+ "residence_phone",
+ "office_phone",
+ "employee_and_user_details_section",
+ "employee",
+ "department",
+ "designation",
+ "column_break_17",
+ "user_id",
+ "hospital",
+ "appointments",
+ "practitioner_schedules",
+ "charges",
+ "op_consulting_charge_item",
+ "op_consulting_charge",
+ "column_break_18",
+ "inpatient_visit_charge_item",
+ "inpatient_visit_charge",
+ "account_details",
+ "default_currency",
+ "accounts",
+ "address_and_contacts_section",
+ "address_html",
+ "column_break_19",
+ "contact_html"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "first_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": 1,
"label": "First Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "middle_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Middle Name (Optional)",
- "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": "Middle Name (Optional)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "last_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": "Last Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Last Name"
},
{
- "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": 1,
- "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
+ "print_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "employee",
"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": "Employee",
- "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
+ "options": "Employee"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "user_id",
"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": "User",
- "length": 0,
- "no_copy": 0,
"options": "User",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "fetch_from": "employee",
"fieldname": "designation",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Designation",
- "length": 0,
- "no_copy": 0,
"options": "Designation",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "department",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
"in_standard_filter": 1,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Medical Department",
- "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": "Medical Department",
+ "options": "Medical Department"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_7",
- "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": "hospital",
"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": "Hospital",
- "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": "Hospital"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "mobile_phone",
"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": "Mobile",
- "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": "Mobile"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "residence_phone",
"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": "Phone (R)",
- "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": "Phone (R)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "office_phone",
"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": "Phone (Office)",
- "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": "Phone (Office)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fieldname": "active",
- "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": "Active",
- "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,
+ "collapsible": 1,
"fieldname": "appointments",
"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": "Appointments",
- "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": "Appointments"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "practitioner_schedules",
"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": "Practitioner Schedules",
- "length": 0,
- "no_copy": 0,
- "options": "Practitioner Service Unit Schedule",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Practitioner Service Unit Schedule"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "collapsible": 1,
"fieldname": "charges",
"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": "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
+ "label": "Charges"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "op_consulting_charge_item",
"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": "Out Patient Consulting Charge Item",
- "length": 0,
- "no_copy": 0,
- "options": "Item",
- "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": "Item"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "op_consulting_charge",
"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": "OP Consulting Charge",
- "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
+ "label": "Out Patient Consulting Charge",
+ "options": "Currency"
},
{
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "inpatient_visit_charge_item",
"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": "Inpatient Visit Charge Item",
- "length": 0,
- "no_copy": 0,
- "options": "Item",
- "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": "Item"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "inpatient_visit_charge",
"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": "Inpatient Visit Charge",
- "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": "Inpatient Visit Charge"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "contacts_and_address",
- "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": "Contacts and Address",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "depends_on": "eval: !doc.__islocal",
"fieldname": "address_html",
"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": "Address HTML",
- "length": 0,
"no_copy": 1,
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_19",
- "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,
+ "depends_on": "eval: !doc.__islocal",
"fieldname": "contact_html",
"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": "Contact HTML",
- "length": 0,
"no_copy": 1,
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "collapsible": 1,
"fieldname": "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": "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
+ "label": "Account Details"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "accounts",
"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": "Income Account",
- "length": 0,
- "no_copy": 0,
- "options": "Party 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
+ "options": "Party Account"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "default_currency",
"fieldtype": "Link",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Default Currency",
- "length": 0,
"no_copy": 1,
"options": "Currency",
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
+ "report_hide": 1
+ },
+ {
+ "bold": 1,
+ "fieldname": "practitioner_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Full Name",
+ "read_only": 1,
+ "search_index": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-PRAC-.YYYY.-",
"report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
+ },
+ {
+ "fieldname": "gender",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender"
+ },
+ {
+ "fieldname": "employee_and_user_details_section",
+ "fieldtype": "Section Break",
+ "label": "Employee and User Details"
+ },
+ {
+ "fieldname": "column_break_17",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "Active",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Status",
+ "options": "\nActive\nDisabled",
+ "reqd": 1
+ },
+ {
+ "fieldname": "basic_details_section",
+ "fieldtype": "Section Break",
+ "label": "Basic Details"
+ },
+ {
+ "collapsible": 1,
+ "depends_on": "eval: !doc.__islocal",
+ "fieldname": "address_and_contacts_section",
+ "fieldtype": "Section Break",
+ "label": "Address and Contacts"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
"image_field": "image",
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-23 08:54:51.442105",
+ "links": [],
+ "modified": "2020-04-06 13:44:24.759623",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Practitioner",
- "name_case": "",
"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": 1,
"role": "Laboratory User",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "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": "Physician",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "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": "Nursing User",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Healthcare",
- "search_fields": "first_name,mobile_phone,office_phone",
+ "search_fields": "practitioner_name, mobile_phone, office_phone",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
- "title_field": "first_name",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "title_field": "practitioner_name",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
index ad32e94..0c13b6a 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
@@ -5,10 +5,10 @@
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
-from frappe import throw, _
-from frappe.utils import cstr
+from frappe import _
from erpnext.accounts.party import validate_party_accounts
from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address
+from frappe.model.naming import append_number_if_name_exists
from frappe.desk.reportview import build_match_conditions, get_filters_cond
class HealthcarePractitioner(Document):
@@ -16,63 +16,66 @@
load_address_and_contact(self)
def autoname(self):
- # practitioner first_name and last_name
- self.name = " ".join(filter(None,
- [cstr(self.get(f)).strip() for f in ["first_name","middle_name","last_name"]]))
+ # concat first and last name
+ self.name = self.practitioner_name
+
+ if frappe.db.exists('Healthcare Practitioner', self.name):
+ self.name = append_number_if_name_exists('Contact', self.name)
def validate(self):
+ self.set_full_name()
validate_party_accounts(self)
if self.inpatient_visit_charge_item:
- validate_service_item(self.inpatient_visit_charge_item, "Configure a service Item for Inpatient Visit Charge Item")
+ validate_service_item(self.inpatient_visit_charge_item, 'Configure a service Item for Inpatient Consulting Charge Item')
if self.op_consulting_charge_item:
- validate_service_item(self.op_consulting_charge_item, "Configure a service Item for Out Patient Consulting Charge Item")
+ validate_service_item(self.op_consulting_charge_item, 'Configure a service Item for Out Patient Consulting Charge Item')
if self.user_id:
- self.validate_for_enabled_user_id()
- self.validate_duplicate_user_id()
- existing_user_id = frappe.db.get_value("Healthcare Practitioner", self.name, "user_id")
- if self.user_id != existing_user_id:
- frappe.permissions.remove_user_permission(
- "Healthcare Practitioner", self.name, existing_user_id)
-
+ self.validate_user_id()
else:
- existing_user_id = frappe.db.get_value("Healthcare Practitioner", self.name, "user_id")
+ existing_user_id = frappe.db.get_value('Healthcare Practitioner', self.name, 'user_id')
if existing_user_id:
frappe.permissions.remove_user_permission(
- "Healthcare Practitioner", self.name, existing_user_id)
+ 'Healthcare Practitioner', self.name, existing_user_id)
def on_update(self):
if self.user_id:
- frappe.permissions.add_user_permission("Healthcare Practitioner", self.name, self.user_id)
+ frappe.permissions.add_user_permission('Healthcare Practitioner', self.name, self.user_id)
+ def set_full_name(self):
+ if self.last_name:
+ self.practitioner_name = ' '.join(filter(None, [self.first_name, self.last_name]))
+ else:
+ self.practitioner_name = self.first_name
- def validate_for_enabled_user_id(self):
- enabled = frappe.db.get_value("User", self.user_id, "enabled")
- if enabled is None:
- frappe.throw(_("User {0} does not exist").format(self.user_id))
- if enabled == 0:
- frappe.throw(_("User {0} is disabled").format(self.user_id))
+ def validate_user_id(self):
+ if not frappe.db.exists('User', self.user_id):
+ frappe.throw(_('User {0} does not exist').format(self.user_id))
+ elif not frappe.db.exists('User', self.user_id, 'enabled'):
+ frappe.throw(_('User {0} is disabled').format(self.user_id))
- def validate_duplicate_user_id(self):
- practitioner = frappe.db.sql_list("""select name from `tabHealthcare Practitioner` where
- user_id=%s and name!=%s""", (self.user_id, self.name))
+ # check duplicate
+ practitioner = frappe.db.exists('Healthcare Practitioner', {
+ 'user_id': self.user_id,
+ 'name': ('!=', self.name)
+ })
if practitioner:
- throw(_("User {0} is already assigned to Healthcare Practitioner {1}").format(
- self.user_id, practitioner[0]), frappe.DuplicateEntryError)
+ frappe.throw(_('User {0} is already assigned to Healthcare Practitioner {1}').format(
+ self.user_id, practitioner))
def on_trash(self):
delete_contact_and_address('Healthcare Practitioner', self.name)
def validate_service_item(item, msg):
- if frappe.db.get_value("Item", item, "is_stock_item") == 1:
+ if frappe.db.get_value('Item', item, 'is_stock_item'):
frappe.throw(_(msg))
def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
- fields = ["name", "first_name", "mobile_phone"]
+ fields = ['name', 'practitioner_name', 'mobile_phone']
filters = {
- 'name': ("like", "%%%s%%" % txt)
+ 'name': ('like', '%%%s%%' % txt)
}
- return frappe.get_all("Healthcare Practitioner", fields = fields,
- filters = filters, start=start, page_length=page_len, order_by="name, first_name", as_list=1)
+ return frappe.get_all('Healthcare Practitioner', fields = fields,
+ filters = filters, start=start, page_length=page_len, order_by='name, practitioner_name', as_list=1)
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py
index 70c0b3c..bcee444 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner_dashboard.py
@@ -9,7 +9,11 @@
'transactions': [
{
'label': _('Appointments and Patient Encounters'),
- 'items': ['Patient Appointment', 'Patient Encounter']
+ 'items': ['Patient Appointment', 'Patient Encounter', 'Fee Validity']
+ },
+ {
+ 'label': _('Consultation'),
+ 'items': ['Clinical Procedure', 'Lab Test']
}
]
}
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.js b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.js
index 8480a52..2cdd550 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.js
+++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.js
@@ -3,7 +3,7 @@
frappe.ui.form.on('Healthcare Service Unit', {
onload: function(frm) {
- frm.list_route = "Tree/Healthcare Service Unit";
+ frm.list_route = 'Tree/Healthcare Service Unit';
// get query select healthcare service unit
frm.fields_dict['parent_healthcare_service_unit'].get_query = function(doc) {
@@ -16,32 +16,32 @@
};
},
refresh: function(frm) {
- frm.trigger("set_root_readonly");
- frm.set_df_property("service_unit_type", "reqd", 1);
- frm.add_custom_button(__("Healthcare Service Unit Tree"), function() {
- frappe.set_route("Tree", "Healthcare Service Unit");
+ frm.trigger('set_root_readonly');
+ frm.set_df_property('service_unit_type', 'reqd', 1);
+ frm.add_custom_button(__('Healthcare Service Unit Tree'), function() {
+ frappe.set_route('Tree', 'Healthcare Service Unit');
});
},
set_root_readonly: function(frm) {
// read-only for root healthcare service unit
- frm.set_intro("");
- if(!frm.doc.parent_healthcare_service_unit) {
+ frm.set_intro('');
+ if (!frm.doc.parent_healthcare_service_unit) {
frm.set_read_only();
- frm.set_intro(__("This is a root healthcare service unit and cannot be edited."), true);
+ frm.set_intro(__('This is a root healthcare service unit and cannot be edited.'), true);
}
},
allow_appointments: function(frm) {
- if(!frm.doc.allow_appointments){
- frm.set_value("overlap_appointments", false);
+ if (!frm.doc.allow_appointments) {
+ frm.set_value('overlap_appointments', false);
}
},
is_group: function(frm) {
- if(frm.doc.is_group == 1){
- frm.set_value("allow_appointments", false);
- frm.set_df_property("service_unit_type", "reqd", 0);
+ if (frm.doc.is_group == 1) {
+ frm.set_value('allow_appointments', false);
+ frm.set_df_property('service_unit_type', 'reqd', 0);
}
- else{
- frm.set_df_property("service_unit_type", "reqd", 1);
+ else {
+ frm.set_df_property('service_unit_type', 'reqd', 1);
}
}
});
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
index 8601f69..ea4ae84 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
+++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
@@ -9,6 +9,7 @@
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
+ "engine": "InnoDB",
"field_order": [
"healthcare_service_unit_name",
"parent_healthcare_service_unit",
@@ -18,6 +19,7 @@
"overlap_appointments",
"inpatient_occupancy",
"occupancy_status",
+ "column_break_9",
"warehouse",
"company",
"lft",
@@ -99,10 +101,14 @@
"fieldtype": "Select",
"label": "Occupancy Status",
"no_copy": 1,
- "options": "Vacant\nOccupied",
+ "options": "\nVacant\nOccupied",
"read_only": 1
},
{
+ "fieldname": "column_break_9",
+ "fieldtype": "Column Break"
+ },
+ {
"bold": 1,
"depends_on": "eval:doc.is_group != 1",
"fieldname": "warehouse",
@@ -153,13 +159,11 @@
"report_hide": 1
}
],
- "is_tree": 1,
"links": [],
- "modified": "2020-03-18 18:02:23.713439",
+ "modified": "2020-03-26 16:13:08.675952",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Service Unit",
- "nsm_parent_field": "parent_healthcare_service_unit",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py
index b408693..13cc43d 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py
+++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py
@@ -23,9 +23,9 @@
self.validate_one_root()
def validate(self):
- if self.is_group == 1:
+ if self.is_group:
self.allow_appointments = 0
self.overlap_appointments = 0
self.inpatient_occupancy = 0
- elif self.allow_appointments != 1:
+ elif not self.allow_appointments:
self.overlap_appointments = 0
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js
index 288ebc4..eb33ab6 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js
@@ -2,118 +2,85 @@
// For license information, please see license.txt
frappe.ui.form.on('Healthcare Service Unit Type', {
+ refresh: function(frm) {
+ frm.set_df_property('item_code', 'read_only', frm.doc.__islocal ? 0 : 1);
+ if (!frm.doc.__islocal && frm.doc.is_billable) {
+ frm.add_custom_button(__('Change Item Code'), function() {
+ change_item_code(cur_frm, frm.doc);
+ });
+ }
+ },
+
service_unit_type: function(frm) {
set_item_details(frm);
- if(!frm.doc.__islocal){
+
+ if (!frm.doc.__islocal) {
frm.doc.change_in_item = 1;
}
},
+
is_billable: function(frm) {
set_item_details(frm);
},
- refresh: function(frm) {
- frm.set_df_property("item_code", "read_only", frm.doc.__islocal ? 0 : 1);
- if(!frm.doc.__islocal) {
- frm.add_custom_button(__('Change Item Code'), function() {
- change_item_code(cur_frm,frm.doc);
- } );
- if(frm.doc.disabled == 1){
- frm.add_custom_button(__('Enable'), function() {
- enable(cur_frm);
- } );
- }
- else{
- frm.add_custom_button(__('Disable'), function() {
- disable(cur_frm);
- } );
- }
- }
- },
+
rate: function(frm) {
- if(!frm.doc.__islocal){
+ if (!frm.doc.__islocal) {
frm.doc.change_in_item = 1;
}
},
item_group: function(frm) {
- if(!frm.doc.__islocal){
+ if (!frm.doc.__islocal) {
frm.doc.change_in_item = 1;
}
},
description: function(frm) {
- if(!frm.doc.__islocal){
+ if (!frm.doc.__islocal) {
frm.doc.change_in_item = 1;
}
}
});
-var disable = function(frm){
- var doc = frm.doc;
- frappe.call({
- method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
- args: {status: 1, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
- callback: function(){
- cur_frm.reload_doc();
- }
- });
+let set_item_details = function(frm) {
+ if (frm.doc.service_unit_type && frm.doc.is_billable) {
+ if (!frm.doc.item_code)
+ frm.set_value('item_code', frm.doc.service_unit_type);
+ if (!frm.doc.description)
+ frm.set_value('description', frm.doc.service_unit_type);
+ if (!frm.doc.item_group)
+ frm.set_value('item_group', 'Services');
+ }
};
-var enable = function(frm){
- var doc = frm.doc;
- frappe.call({
- method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
- args: {status: 0, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
- callback: function(){
- cur_frm.reload_doc();
- }
- });
-};
-
-var change_item_code = function(frm, doc){
- var d = new frappe.ui.Dialog({
- title:__("Change Item Code"),
- fields:[
+let change_item_code = function(frm, doc) {
+ let d = new frappe.ui.Dialog({
+ title: __('Change Item Code'),
+ fields: [
{
- "fieldtype": "Data",
- "label": "Item Code",
- "fieldname": "Item Code",
- reqd:1
- },
- {
- "fieldtype": "Button",
- "label": __("Change Code"),
- click: function() {
- var values = d.get_values();
- if(!values)
- return;
- change_item_code_from_unit_type(values["Item Code"], doc);
- d.hide();
- }
+ 'fieldtype': 'Data',
+ 'label': 'Item Code',
+ 'fieldname': 'item_code',
+ 'default': doc.item_code,
+ reqd: 1,
}
- ]
+ ],
+ primary_action: function() {
+ let values = d.get_values();
+ if (values) {
+ frappe.call({
+ "method": "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.change_item_code",
+ "args": {item: doc.item, item_code: values['item_code'], doc_name: doc.name},
+ callback: function () {
+ frm.reload_doc();
+ }
+ });
+ }
+ d.hide();
+ },
+ primary_action_label: __("Change Template Code")
});
+
d.show();
d.set_values({
'Item Code': frm.doc.item_code
});
-
- var change_item_code_from_unit_type = function(item_code, doc){
- frappe.call({
- "method": "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.change_item_code",
- "args": {item: doc.item, item_code: item_code, doc_name: doc.name},
- callback: function () {
- frm.reload_doc();
- }
- });
- };
-};
-
-var set_item_details = function(frm) {
- if(frm.doc.service_unit_type && frm.doc.is_billable == 1){
- if(!frm.doc.item_code)
- frm.set_value("item_code", frm.doc.service_unit_type);
- if(!frm.doc.description)
- frm.set_value("description", frm.doc.service_unit_type);
- if(!frm.doc.item_group)
- frm.set_value("item_group", 'Services');
- }
};
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json
index 40681e9..5fa47d9 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json
@@ -1,588 +1,164 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:service_unit_type",
- "beta": 0,
- "creation": "2018-07-11 16:47:51.414675",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:service_unit_type",
+ "creation": "2018-07-11 16:47:51.414675",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "disabled",
+ "service_unit_type",
+ "allow_appointments",
+ "overlap_appointments",
+ "inpatient_occupancy",
+ "is_billable",
+ "item_details",
+ "item",
+ "item_code",
+ "item_group",
+ "uom",
+ "no_of_hours",
+ "column_break_11",
+ "rate",
+ "description",
+ "change_in_item"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "service_unit_type",
- "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": "Service Unit Type",
- "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": "service_unit_type",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Service Unit Type",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "depends_on": "eval:doc.inpatient_occupancy != 1",
- "fieldname": "allow_appointments",
- "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 Appointments",
- "length": 0,
- "no_copy": 1,
- "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
- },
+ "bold": 1,
+ "default": "0",
+ "depends_on": "eval:doc.inpatient_occupancy != 1",
+ "fieldname": "allow_appointments",
+ "fieldtype": "Check",
+ "label": "Allow Appointments",
+ "no_copy": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "depends_on": "eval:doc.allow_appointments == 1 && doc.inpatient_occupany != 1",
- "fieldname": "overlap_appointments",
- "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 Overlap",
- "length": 0,
- "no_copy": 1,
- "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
- },
+ "bold": 1,
+ "default": "0",
+ "depends_on": "eval:doc.allow_appointments == 1 && doc.inpatient_occupany != 1",
+ "fieldname": "overlap_appointments",
+ "fieldtype": "Check",
+ "label": "Allow Overlap",
+ "no_copy": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "depends_on": "eval:doc.allow_appointments != 1",
- "fieldname": "inpatient_occupancy",
- "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": "Inpatient Occupancy",
- "length": 0,
- "no_copy": 1,
- "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
- },
+ "bold": 1,
+ "default": "0",
+ "depends_on": "eval:doc.allow_appointments != 1",
+ "fieldname": "inpatient_occupancy",
+ "fieldtype": "Check",
+ "label": "Inpatient Occupancy",
+ "no_copy": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.inpatient_occupancy == 1 && doc.allow_appointments != 1",
- "fieldname": "is_billable",
- "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 Billable",
- "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
- },
+ "bold": 1,
+ "default": "0",
+ "depends_on": "eval:doc.inpatient_occupancy == 1 && doc.allow_appointments != 1",
+ "fieldname": "is_billable",
+ "fieldtype": "Check",
+ "label": "Is Billable"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "is_billable",
- "fieldname": "item_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": "Item 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": "is_billable",
+ "fieldname": "item_details",
+ "fieldtype": "Section Break",
+ "label": "Item Details"
+ },
{
- "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": 0,
- "in_standard_filter": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "Item",
- "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": "item",
+ "fieldtype": "Link",
+ "label": "Item",
+ "options": "Item",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item_code",
- "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": "Item Code",
- "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": "item_code",
+ "fieldtype": "Data",
+ "label": "Item Code",
+ "mandatory_depends_on": "eval: doc.is_billable == 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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "label": "Item Group",
+ "mandatory_depends_on": "eval: doc.is_billable == 1",
+ "options": "Item Group"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "uom",
- "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": "UOM",
- "length": 0,
- "no_copy": 0,
- "options": "UOM",
- "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": "uom",
+ "fieldtype": "Link",
+ "label": "UOM",
+ "mandatory_depends_on": "eval: doc.is_billable == 1",
+ "options": "UOM"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "no_of_hours",
- "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": "UOM Conversion in Hours",
- "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": "no_of_hours",
+ "fieldtype": "Int",
+ "label": "UOM Conversion in Hours",
+ "mandatory_depends_on": "eval: doc.is_billable == 1"
+ },
{
- "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,
- "fieldname": "rate",
- "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": "Rate / UOM",
- "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": "rate",
+ "fieldtype": "Currency",
+ "label": "Rate / UOM"
+ },
{
- "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",
- "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": 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
- },
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "label": "Disabled",
+ "no_copy": 1
+ },
{
- "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": "Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "change_in_item",
- "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": "Change in Item",
- "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": "change_in_item",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Change in Item"
}
- ],
- "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-08-08 13:00:23.751635",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Healthcare Service Unit Type",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "links": [],
+ "modified": "2020-01-30 16:06:00.624496",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Healthcare Service Unit Type",
+ "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": "Healthcare Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "service_unit_type",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "service_unit_type"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
index 43f01c8..286ecc0 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
@@ -10,109 +10,107 @@
class HealthcareServiceUnitType(Document):
def validate(self):
- if self.is_billable == 1:
- if not self.uom or not self.item_group or not self.description or not self.no_of_hours > 0:
- frappe.throw(_("Configure Item Fields like UOM, Item Group, Description and No of Hours."))
+ if self.is_billable:
+ if self.disabled:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
+ else:
+ frappe.db.set_value('Item', self.item, 'disabled', 0)
def after_insert(self):
if self.inpatient_occupancy and self.is_billable:
create_item(self)
def on_trash(self):
- if(self.item):
+ if self.item:
try:
- frappe.delete_doc("Item",self.item)
+ frappe.delete_doc('Item', self.item)
except Exception:
- frappe.throw(_("""Not permitted. Please disable the Service Unit Type"""))
+ frappe.throw(_('Not permitted. Please disable the Service Unit Type'))
def on_update(self):
- if(self.change_in_item and self.is_billable == 1 and self.item):
- updating_item(self)
- item_price = item_price_exist(self)
- if not item_price:
- if(self.rate != 0.0):
- price_list_name = frappe.db.get_value("Price List", {"selling": 1})
- if(self.rate):
- make_item_price(self.item_code, price_list_name, self.rate)
- else:
- make_item_price(self.item_code, price_list_name, 0.0)
- else:
- frappe.db.set_value("Item Price", item_price, "price_list_rate", self.rate)
+ if self.change_in_item and self.is_billable and self.item:
+ update_item(self)
- frappe.db.set_value(self.doctype,self.name,"change_in_item",0)
- elif(self.is_billable == 0 and self.item):
- frappe.db.set_value("Item",self.item,"disabled",1)
+ item_price = item_price_exists(self)
+
+ if not item_price:
+ price_list_name = frappe.db.get_value('Price List', {'selling': 1})
+ if self.rate:
+ make_item_price(self.item_code, price_list_name, self.rate)
+ else:
+ make_item_price(self.item_code, price_list_name, 0.0)
+ else:
+ frappe.db.set_value('Item Price', item_price, 'price_list_rate', self.rate)
+
+ frappe.db.set_value(self.doctype, self.name, 'change_in_item',0)
+ elif not self.is_billable and self.item:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
self.reload()
-def item_price_exist(doc):
- item_price = frappe.db.exists({
- "doctype": "Item Price",
- "item_code": doc.item_code})
- if(item_price):
- return item_price[0][0]
- else:
- return False
-def updating_item(doc):
- frappe.db.sql("""update `tabItem` set item_name=%s, item_group=%s, disabled=0, standard_rate=%s,
- description=%s, modified=NOW() where item_code=%s""",
- (doc.service_unit_type, doc.item_group , doc.rate, doc.description, doc.item))
+def item_price_exists(doc):
+ item_price = frappe.db.exists({'doctype': 'Item Price', 'item_code': doc.item_code})
+ if len(item_price):
+ return item_price[0][0]
+ return False
def create_item(doc):
- #insert item
+ # insert item
item = frappe.get_doc({
- "doctype": "Item",
- "item_code": doc.item_code,
- "item_name":doc.service_unit_type,
- "item_group": doc.item_group,
- "description":doc.description,
- "is_sales_item": 1,
- "is_service_item": 1,
- "is_purchase_item": 0,
- "is_stock_item": 0,
- "show_in_website": 0,
- "is_pro_applicable": 0,
- "disabled": 0,
- "stock_uom": doc.uom
- }).insert(ignore_permissions=True)
+ 'doctype': 'Item',
+ 'item_code': doc.item_code,
+ 'item_name': doc.service_unit_type,
+ 'item_group': doc.item_group,
+ 'description': doc.description or doc.item_code,
+ 'is_sales_item': 1,
+ 'is_service_item': 1,
+ 'is_purchase_item': 0,
+ 'is_stock_item': 0,
+ 'show_in_website': 0,
+ 'is_pro_applicable': 0,
+ 'disabled': 0,
+ 'stock_uom': doc.uom
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
- #insert item price
- #get item price list to insert item price
- if(doc.rate != 0.0):
- price_list_name = frappe.db.get_value("Price List", {"selling": 1})
- if(doc.rate):
- make_item_price(item.name, price_list_name, doc.rate)
- item.standard_rate = doc.rate
- else:
- make_item_price(item.name, price_list_name, 0.0)
- item.standard_rate = 0.0
- item.save(ignore_permissions = True)
- #Set item to the Doc
- frappe.db.set_value("Healthcare Service Unit Type", doc.name, "item", item.name)
+ # insert item price
+ # get item price list to insert item price
+ price_list_name = frappe.db.get_value('Price List', {'selling': 1})
+ if doc.rate:
+ make_item_price(item.name, price_list_name, doc.rate)
+ item.standard_rate = doc.rate
+ else:
+ make_item_price(item.name, price_list_name, 0.0)
+ item.standard_rate = 0.0
- doc.reload() #refresh the doc after insert.
+ item.save(ignore_permissions=True)
+
+ # Set item in the doc
+ doc.db_set('item', item.name)
def make_item_price(item, price_list_name, item_price):
frappe.get_doc({
- "doctype": "Item Price",
- "price_list": price_list_name,
- "item_code": item,
- "price_list_rate": item_price
- }).insert(ignore_permissions=True)
+ 'doctype': 'Item Price',
+ 'price_list': price_list_name,
+ 'item_code': item,
+ 'price_list_rate': item_price
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
+
+def update_item(doc):
+ item = frappe.get_doc("Item", doc.item)
+ if item:
+ item.update({
+ "item_name": doc.service_unit_type,
+ "item_group": doc.item_group,
+ "disabled": 0,
+ "standard_rate": doc.rate,
+ "description": doc.description
+ })
+ item.db_update()
@frappe.whitelist()
def change_item_code(item, item_code, doc_name):
- item_exist = frappe.db.exists({
- "doctype": "Item",
- "item_code": item_code})
- if(item_exist):
- frappe.throw(_("Code {0} already exist").format(item_code))
+ if frappe.db.exists({'doctype': 'Item', 'item_code': item_code}):
+ frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
else:
- rename_doc("Item", item, item_code, ignore_permissions=True)
- frappe.db.set_value("Healthcare Service Unit Type", doc_name, "item_code", item_code)
-
-@frappe.whitelist()
-def disable_enable(status, doc_name, item=None, is_billable=None):
- frappe.db.set_value("Healthcare Service Unit Type", doc_name, "disabled", status)
- if(is_billable == 1):
- frappe.db.set_value("Item", item, "disabled", status)
+ rename_doc('Item', item, item_code, ignore_permissions=True)
+ frappe.db.set_value('Healthcare Service Unit Type', doc_name, 'item_code', item_code)
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type_dashboard.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type_dashboard.py
new file mode 100644
index 0000000..0ac548b
--- /dev/null
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'service_unit_type',
+ 'transactions': [
+ {
+ 'label': _('Healthcare Service Units'),
+ 'items': ['Healthcare Service Unit']
+ },
+ ]
+ }
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py
index 3c5b64f..01cf4b0 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.py
@@ -3,6 +3,31 @@
# See license.txt
from __future__ import unicode_literals
import unittest
+import frappe
class TestHealthcareServiceUnitType(unittest.TestCase):
- pass
+ def test_item_creation(self):
+ unit_type = get_unit_type()
+ self.assertTrue(frappe.db.exists('Item', unit_type.item))
+
+ # check item disabled
+ unit_type.disabled = 1
+ unit_type.save()
+ self.assertEqual(frappe.db.get_value('Item', unit_type.item, 'disabled'), 1)
+
+
+def get_unit_type():
+ if frappe.db.exists('Healthcare Service Unit Type', 'Inpatient Rooms'):
+ return frappe.get_doc('Healthcare Service Unit Type', 'Inpatient Rooms')
+
+ unit_type = frappe.new_doc('Healthcare Service Unit Type')
+ unit_type.service_unit_type = 'Inpatient Rooms'
+ unit_type.inpatient_occupancy = 1
+ unit_type.is_billable = 1
+ unit_type.item_code = 'Inpatient Rooms'
+ unit_type.item_group = 'Services'
+ unit_type.uom = 'Hour'
+ unit_type.no_of_hours = 1
+ unit_type.rate = 4000
+ unit_type.save()
+ return unit_type
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json
index 95d9e44..de08620 100644
--- a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json
+++ b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json
@@ -7,40 +7,40 @@
"engine": "InnoDB",
"field_order": [
"sb_op_settings",
- "patient_master_name",
- "manage_customer",
+ "patient_name_by",
+ "link_customer_to_patient",
"default_medical_code_standard",
"column_break_9",
"collect_registration_fee",
"registration_fee",
- "manage_appointment_invoice_automatically",
- "max_visit",
+ "automate_appointment_invoicing",
+ "enable_free_follow_ups",
+ "max_visits",
"valid_days",
"healthcare_service_items",
"inpatient_visit_charge_item",
"op_consulting_charge_item",
"column_break_13",
"clinical_procedure_consumable_item",
- "out_patient_sms_alerts",
- "reg_sms",
- "reg_msg",
- "app_con",
- "app_con_msg",
- "no_con",
- "column_break_16",
- "app_rem",
- "app_rem_msg",
- "rem_before",
"sb_in_ac",
"income_account",
- "sb_r_ac",
"receivable_account",
+ "out_patient_sms_alerts",
+ "send_registration_msg",
+ "registration_msg",
+ "send_appointment_confirmation",
+ "appointment_confirmation_msg",
+ "avoid_confirmation",
+ "column_break_16",
+ "send_appointment_reminder",
+ "appointment_reminder_msg",
+ "remind_before",
"sb_lab_settings",
- "create_test_on_si_submit",
- "require_sample_collection",
- "require_test_result_approval",
+ "create_lab_test_on_si_submit",
+ "create_sample_collection_for_lab_test",
"column_break_34",
"employee_name_and_designation_in_print",
+ "lab_test_approval_required",
"custom_signature_in_print",
"laboratory_sms_alerts",
"sms_printed",
@@ -54,19 +54,6 @@
"label": "Out Patient Settings"
},
{
- "fieldname": "patient_master_name",
- "fieldtype": "Select",
- "label": "Patient Name By",
- "options": "Patient Name\nNaming Series"
- },
- {
- "default": "1",
- "description": "If checked, a customer will be created, mapped to Patient.\nPatient Invoices will be created against this Customer. You can also select existing Customer while creating Patient.",
- "fieldname": "manage_customer",
- "fieldtype": "Check",
- "label": "Manage Customer"
- },
- {
"fieldname": "default_medical_code_standard",
"fieldtype": "Link",
"label": "Default Medical Code Standard",
@@ -78,6 +65,7 @@
},
{
"default": "0",
+ "description": "Checking this will create new Patients with a Disabled status by default and will only be enabled after invoicing the Registration Fee.",
"fieldname": "collect_registration_fee",
"fieldtype": "Check",
"label": "Collect Fee for Patient Registration"
@@ -91,27 +79,19 @@
"options": "Currency"
},
{
- "default": "0",
- "description": "Manage Appointment Invoice submit and cancel automatically for Patient Encounter",
- "fieldname": "manage_appointment_invoice_automatically",
- "fieldtype": "Check",
- "label": "Invoice Appointments Automatically"
- },
- {
- "fieldname": "max_visit",
- "fieldtype": "Int",
- "label": "Patient Encounters in valid days"
- },
- {
+ "depends_on": "eval:doc.enable_free_follow_ups == 1",
+ "description": "Time period (Valid number of days) for free consultations",
"fieldname": "valid_days",
"fieldtype": "Int",
- "label": "Valid number of days"
+ "label": "Valid Number of Days",
+ "mandatory_depends_on": "eval:doc.enable_free_follow_ups == 1"
},
{
"collapsible": 1,
+ "description": "You can configure default Items for billing consultation charges, procedure consumption items and inpatient visits",
"fieldname": "healthcare_service_items",
"fieldtype": "Section Break",
- "label": "Healthcare Service Items"
+ "label": "Default Healthcare Service Items"
},
{
"fieldname": "inpatient_visit_charge_item",
@@ -142,86 +122,24 @@
"label": "Out Patient SMS Alerts"
},
{
- "default": "0",
- "fieldname": "reg_sms",
- "fieldtype": "Check",
- "label": "Patient Registration"
- },
- {
- "default": "Hello {{doc.patient}}, Thank you for registering with {{doc.company}}. Your ID is {{doc.id}} . Please note this ID for future reference. \nThank You, Get well soon!",
- "depends_on": "reg_sms",
- "fieldname": "reg_msg",
- "fieldtype": "Small Text",
- "ignore_xss_filter": 1,
- "label": "Registration Message"
- },
- {
- "default": "0",
- "fieldname": "app_con",
- "fieldtype": "Check",
- "label": "Appointment Confirmation"
- },
- {
- "default": "Hello {{doc.patient}}, You have scheduled an appointment with {{doc.practitioner}} by {{doc.start_dt}} at {{doc.company}}.\nThank you, Good day!",
- "depends_on": "app_con",
- "fieldname": "app_con_msg",
- "fieldtype": "Small Text",
- "ignore_xss_filter": 1,
- "label": "Confirmation Message"
- },
- {
- "default": "0",
- "depends_on": "app_con",
- "description": "Do not confirm if appointment is created for the same day",
- "fieldname": "no_con",
- "fieldtype": "Check",
- "label": "Avoid Confirmation"
- },
- {
"fieldname": "column_break_16",
"fieldtype": "Column Break"
},
{
- "default": "0",
- "fieldname": "app_rem",
- "fieldtype": "Check",
- "label": "Appointment Reminder"
- },
- {
- "default": "Hello {{doc.patient}}, You have an appointment with {{doc.practitioner}} by {{doc.appointment_time}} at {{doc.company}}.\nThank you, Good day!\n",
- "depends_on": "app_rem",
- "fieldname": "app_rem_msg",
- "fieldtype": "Small Text",
- "ignore_xss_filter": 1,
- "label": "Reminder Message"
- },
- {
- "depends_on": "app_rem",
- "fieldname": "rem_before",
- "fieldtype": "Time",
- "label": "Remind Before"
- },
- {
"collapsible": 1,
- "description": "Default income accounts to be used if not set in Healthcare Practitioner to book Appointment charges.",
"fieldname": "sb_in_ac",
"fieldtype": "Section Break",
- "label": "Income Account"
+ "label": "Default Accounts"
},
{
+ "description": "Default income accounts to be used if not set in Healthcare Practitioner to book Appointment charges.",
"fieldname": "income_account",
"fieldtype": "Table",
"label": "Income Account",
"options": "Party Account"
},
{
- "collapsible": 1,
- "description": "Default receivable accounts to be used if not set in Patient to book Appointment charges.",
- "fieldname": "sb_r_ac",
- "fieldtype": "Section Break",
- "label": "Receivable Account"
- },
- {
+ "description": "Default receivable accounts to be used to book Appointment charges.",
"fieldname": "receivable_account",
"fieldtype": "Table",
"label": "Receivable Account",
@@ -234,30 +152,12 @@
"label": "Laboratory Settings"
},
{
- "default": "0",
- "fieldname": "create_test_on_si_submit",
- "fieldtype": "Check",
- "label": "Create Lab Test(s) on Sales Invoice Submit"
- },
- {
- "default": "0",
- "description": "Create documents for sample collection",
- "fieldname": "require_sample_collection",
- "fieldtype": "Check",
- "label": "Manage Sample Collection"
- },
- {
- "default": "0",
- "fieldname": "require_test_result_approval",
- "fieldtype": "Check",
- "label": "Require Lab Test Approval"
- },
- {
"fieldname": "column_break_34",
"fieldtype": "Column Break"
},
{
"default": "1",
+ "description": "Check this if you want the Name and Designation of the Employee associated with the User who submits the document to be printed in the Lab Test Report.",
"fieldname": "employee_name_and_designation_in_print",
"fieldtype": "Check",
"label": "Employee name and designation in print"
@@ -279,7 +179,7 @@
"fieldname": "sms_printed",
"fieldtype": "Small Text",
"ignore_xss_filter": 1,
- "label": "Result Printed"
+ "label": "Result Printed Message"
},
{
"fieldname": "column_break_28",
@@ -290,12 +190,123 @@
"fieldname": "sms_emailed",
"fieldtype": "Small Text",
"ignore_xss_filter": 1,
- "label": "Result Emailed"
+ "label": "Result Emailed Message"
+ },
+ {
+ "default": "0",
+ "description": "Checking this will restrict printing and emailing of Lab Test documents unless they have the status as Approved.",
+ "fieldname": "lab_test_approval_required",
+ "fieldtype": "Check",
+ "label": "Do not print or email Lab Tests without Approval"
+ },
+ {
+ "default": "1",
+ "description": "If checked, a customer will be created, mapped to Patient.\nPatient Invoices will be created against this Customer. You can also select existing Customer while creating Patient.",
+ "fieldname": "link_customer_to_patient",
+ "fieldtype": "Check",
+ "label": "Link Customer to Patient"
+ },
+ {
+ "default": "0",
+ "description": "Checking this will create Lab Test(s) specified in the Sales Invoice on submission.",
+ "fieldname": "create_lab_test_on_si_submit",
+ "fieldtype": "Check",
+ "label": "Create Lab Test(s) on Sales Invoice Submission"
+ },
+ {
+ "default": "0",
+ "description": "Checking this will create a Sample Collection document every time you create a Lab Test",
+ "fieldname": "create_sample_collection_for_lab_test",
+ "fieldtype": "Check",
+ "label": "Create Sample Collection document for Lab Test"
+ },
+ {
+ "fieldname": "patient_name_by",
+ "fieldtype": "Select",
+ "label": "Patient Name By",
+ "options": "Patient Name\nNaming Series"
+ },
+ {
+ "default": "0",
+ "description": "Manage Appointment Invoice submit and cancel automatically for Patient Encounter",
+ "fieldname": "automate_appointment_invoicing",
+ "fieldtype": "Check",
+ "label": "Automate Appointment Invoicing"
+ },
+ {
+ "default": "0",
+ "fieldname": "send_registration_msg",
+ "fieldtype": "Check",
+ "label": "Patient Registration"
+ },
+ {
+ "default": "Hello {{doc.patient}}, Thank you for registering with {{doc.company}}. Your ID is {{doc.id}} . Please note this ID for future reference. \nThank You, Get well soon!",
+ "depends_on": "send_registration_msg",
+ "fieldname": "registration_msg",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Registration Message"
+ },
+ {
+ "default": "0",
+ "fieldname": "send_appointment_confirmation",
+ "fieldtype": "Check",
+ "label": "Appointment Confirmation"
+ },
+ {
+ "default": "Hello {{doc.patient}}, You have scheduled an appointment with {{doc.practitioner}} by {{doc.start_dt}} at {{doc.company}}.\nThank you, Good day!",
+ "depends_on": "send_appointment_confirmation",
+ "fieldname": "appointment_confirmation_msg",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Confirmation Message"
+ },
+ {
+ "default": "0",
+ "depends_on": "send_appointment_confirmation",
+ "description": "Do not confirm if appointment is created for the same day",
+ "fieldname": "avoid_confirmation",
+ "fieldtype": "Check",
+ "label": "Avoid Confirmation"
+ },
+ {
+ "default": "0",
+ "fieldname": "send_appointment_reminder",
+ "fieldtype": "Check",
+ "label": "Appointment Reminder"
+ },
+ {
+ "default": "Hello {{doc.patient}}, You have an appointment with {{doc.practitioner}} by {{doc.appointment_time}} at {{doc.company}}.\nThank you, Good day!\n",
+ "depends_on": "send_appointment_reminder",
+ "fieldname": "appointment_reminder_msg",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Reminder Message"
+ },
+ {
+ "depends_on": "send_appointment_reminder",
+ "fieldname": "remind_before",
+ "fieldtype": "Time",
+ "label": "Remind Before"
+ },
+ {
+ "depends_on": "eval:doc.enable_free_follow_ups == 1",
+ "description": "The number of free follow ups (Patient Encounters in valid days) allowed",
+ "fieldname": "max_visits",
+ "fieldtype": "Int",
+ "label": "Number of Patient Encounters in Valid Days",
+ "mandatory_depends_on": "eval:doc.enable_free_follow_ups == 1"
+ },
+ {
+ "default": "0",
+ "fieldname": "enable_free_follow_ups",
+ "fieldtype": "Check",
+ "label": "Enable Free Follow-ups"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-01-23 13:31:43.699711",
+ "modified": "2020-03-26 11:25:21.842092",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Settings",
diff --git a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py
index 8555e80..a16fceb 100644
--- a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py
+++ b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py
@@ -11,69 +11,80 @@
class HealthcareSettings(Document):
def validate(self):
- for key in ["collect_registration_fee","manage_customer","patient_master_name",
- "require_test_result_approval","require_sample_collection", "default_medical_code_standard"]:
+ for key in ['collect_registration_fee', 'link_customer_to_patient', 'patient_name_by',
+ 'lab_test_approval_required', 'create_sample_collection_for_lab_test', 'default_medical_code_standard']:
frappe.db.set_default(key, self.get(key, ""))
- if(self.collect_registration_fee):
- if self.registration_fee <= 0 :
- frappe.throw(_("Registration fee can not be Zero"))
+
+ if self.collect_registration_fee:
+ if self.registration_fee <= 0:
+ frappe.throw(_('Registration Fee cannot be negative or zero'))
+
if self.inpatient_visit_charge_item:
- validate_service_item(self.inpatient_visit_charge_item, "Configure a service Item for Inpatient Visit Charge Item")
+ validate_service_item(self.inpatient_visit_charge_item)
if self.op_consulting_charge_item:
- validate_service_item(self.op_consulting_charge_item, "Configure a service Item for Out Patient Consulting Charge Item")
+ validate_service_item(self.op_consulting_charge_item)
if self.clinical_procedure_consumable_item:
- validate_service_item(self.clinical_procedure_consumable_item, "Configure a service Item for Clinical Procedure Consumable Item")
+ validate_service_item(self.clinical_procedure_consumable_item)
+
+
+def validate_service_item(item):
+ if frappe.db.get_value('Item', item, 'is_stock_item'):
+ frappe.throw(_('Configure a service Item for {0}').format(item))
@frappe.whitelist()
def get_sms_text(doc):
- sms_text = {}
- doc = frappe.get_doc("Lab Test",doc)
- #doc = json.loads(doc)
- context = {"doc": doc, "alert": doc, "comments": None}
- emailed = frappe.db.get_value("Healthcare Settings", None, "sms_emailed")
- sms_text['emailed'] = frappe.render_template(emailed, context)
- printed = frappe.db.get_value("Healthcare Settings", None, "sms_printed")
- sms_text['printed'] = frappe.render_template(printed, context)
- return sms_text
+ sms_text = {}
+ doc = frappe.get_doc('Lab Test', doc)
+ context = {'doc': doc, 'alert': doc, 'comments': None}
+
+ emailed = frappe.db.get_value('Healthcare Settings', None, 'sms_emailed')
+ sms_text['emailed'] = frappe.render_template(emailed, context)
+
+ printed = frappe.db.get_value('Healthcare Settings', None, 'sms_printed')
+ sms_text['printed'] = frappe.render_template(printed, context)
+
+ return sms_text
def send_registration_sms(doc):
- if (frappe.db.get_value("Healthcare Settings", None, "reg_sms")=='1'):
- if doc.mobile:
- context = {"doc": doc, "alert": doc, "comments": None}
- if doc.get("_comments"):
- context["comments"] = json.loads(doc.get("_comments"))
- messages = frappe.db.get_value("Healthcare Settings", None, "reg_msg")
- messages = frappe.render_template(messages, context)
- number = [doc.mobile]
- send_sms(number,messages)
- else:
- frappe.msgprint(doc.name + " Has no mobile number to send registration SMS", alert=True)
-
+ if frappe.db.get_single_value('Healthcare Settings', 'send_registration_msg'):
+ if doc.mobile:
+ context = {'doc': doc, 'alert': doc, 'comments': None}
+ if doc.get('_comments'):
+ context['comments'] = json.loads(doc.get('_comments'))
+ messages = frappe.db.get_single_value('Healthcare Settings', 'registration_msg')
+ messages = frappe.render_template(messages, context)
+ number = [doc.mobile]
+ send_sms(number,messages)
+ else:
+ frappe.msgprint(doc.name + ' has no mobile number to send registration SMS', alert=True)
def get_receivable_account(company):
- receivable_account = get_account(None, "receivable_account", "Healthcare Settings", company)
- if receivable_account:
- return receivable_account
- return frappe.get_cached_value('Company', company, "default_receivable_account")
+ receivable_account = get_account(None, 'receivable_account', 'Healthcare Settings', company)
+ if receivable_account:
+ return receivable_account
+
+ return frappe.get_cached_value('Company', company, 'default_receivable_account')
def get_income_account(practitioner, company):
- if(practitioner):
- income_account = get_account("Healthcare Practitioner", None, practitioner, company)
- if income_account:
- return income_account
- income_account = get_account(None, "income_account", "Healthcare Settings", company)
- if income_account:
- return income_account
- return frappe.get_cached_value('Company', company, "default_income_account")
+ # check income account in Healthcare Practitioner
+ if practitioner:
+ income_account = get_account('Healthcare Practitioner', None, practitioner, company)
+ if income_account:
+ return income_account
+
+ # else check income account in Healthcare Settings
+ income_account = get_account(None, 'income_account', 'Healthcare Settings', company)
+ if income_account:
+ return income_account
+
+ # else return default income account of company
+ return frappe.get_cached_value('Company', company, 'default_income_account')
def get_account(parent_type, parent_field, parent, company):
- if(parent_type):
- return frappe.db.get_value("Party Account",
- {"parenttype": parent_type, "parent": parent, "company": company}, "account")
- if(parent_field):
- return frappe.db.get_value("Party Account",
- {"parentfield": parent_field, "parent": parent, "company": company}, "account")
+ if parent_type:
+ return frappe.db.get_value('Party Account',
+ {'parenttype': parent_type, 'parent': parent, 'company': company}, 'account')
-def validate_service_item(item, msg):
- if frappe.db.get_value("Item", item, "is_stock_item") == 1:
- frappe.throw(_(msg))
+ if parent_field:
+ return frappe.db.get_value('Party Account',
+ {'parentfield': parent_field, 'parent': parent, 'company': company}, 'account')
diff --git a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py
index f10725e..e15324c 100644
--- a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py
+++ b/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py
@@ -8,11 +8,12 @@
from frappe.utils import now_datetime, today
from frappe.utils.make_random import get_random
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient
class TestInpatientRecord(unittest.TestCase):
def test_admit_and_discharge(self):
frappe.db.sql("""delete from `tabInpatient Record`""")
- patient = get_patient()
+ patient = create_patient()
# Schedule Admission
ip_record = create_inpatient(patient)
ip_record.save(ignore_permissions = True)
@@ -41,7 +42,7 @@
def test_validate_overlap_admission(self):
frappe.db.sql("""delete from `tabInpatient Record`""")
- patient = get_patient()
+ patient = create_patient()
ip_record = create_inpatient(patient)
ip_record.save(ignore_permissions = True)
@@ -75,17 +76,6 @@
inpatient_record.scheduled_date = today()
return inpatient_record
-def get_patient():
- patient = get_random("Patient")
- if not patient:
- patient = frappe.new_doc("Patient")
- patient.patient_name = "Test Patient"
- patient.sex = "Male"
- patient.save(ignore_permissions=True)
- return patient.name
- return patient
-
-
def get_healthcare_service_unit():
service_unit = get_random("Healthcare Service Unit", filters={"inpatient_occupancy": 1})
if not service_unit:
diff --git a/erpnext/healthcare/doctype/lab_prescription/lab_prescription.json b/erpnext/healthcare/doctype/lab_prescription/lab_prescription.json
index d6691d4..0720bb4 100644
--- a/erpnext/healthcare/doctype/lab_prescription/lab_prescription.json
+++ b/erpnext/healthcare/doctype/lab_prescription/lab_prescription.json
@@ -1,238 +1,78 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2016-09-16 16:53:06.882970",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2016-09-16 16:53:06.882970",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "lab_test_code",
+ "lab_test_name",
+ "invoiced",
+ "column_break_4",
+ "lab_test_comment",
+ "lab_test_created"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lab_test_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Test Code",
- "length": 0,
- "no_copy": 0,
- "options": "Lab Test Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "lab_test_code",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Lab Test",
+ "options": "Lab Test Template",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "lab_test_code.lab_test_name",
- "fieldname": "lab_test_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": "Test",
- "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": "lab_test_code.lab_test_name",
+ "fieldname": "lab_test_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Lab Test Name"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "invoiced",
- "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": "Invoiced",
- "length": 0,
- "no_copy": 1,
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "no_copy": 1,
+ "read_only": 1,
+ "search_index": 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": "lab_test_comment",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Comments",
- "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": "lab_test_comment",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "in_list_view": 1,
+ "label": "Comments"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lab_test_created",
- "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": "Test Created",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "default": "0",
+ "fieldname": "lab_test_created",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Test Created",
+ "no_copy": 1,
+ "print_hide": 1,
+ "report_hide": 1,
+ "search_index": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-09-04 09:02:18.592637",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Lab Prescription",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 17:03:00.255560",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Lab Prescription",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.js b/erpnext/healthcare/doctype/lab_test/lab_test.js
index b60e70f..5b3f4c7 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.js
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.js
@@ -29,7 +29,7 @@
get_lab_test_prescribed(frm);
});
}
- if(frm.doc.docstatus==1 && frm.doc.status!='Approved' && frm.doc.status!='Rejected' && frappe.defaults.get_default("require_test_result_approval") && frappe.user.has_role("LabTest Approver")){
+ if(frm.doc.docstatus==1 && frm.doc.status!='Approved' && frm.doc.status!='Rejected' && frappe.defaults.get_default("lab_test_approval_required") && frappe.user.has_role("LabTest Approver")){
frm.add_custom_button(__('Approve'), function() {
status_update(1,frm);
});
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.json b/erpnext/healthcare/doctype/lab_test/lab_test.json
index 00e613a..ccbc24b 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.json
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.json
@@ -1,1597 +1,478 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2016-03-29 17:34:47.509094",
- "custom": 0,
- "default_print_format": "",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 0,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2016-03-29 17:34:47.509094",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+ "inpatient_record",
+ "naming_series",
+ "invoiced",
+ "patient",
+ "patient_name",
+ "patient_age",
+ "patient_sex",
+ "practitioner",
+ "email",
+ "mobile",
+ "company",
+ "c_b",
+ "department",
+ "status",
+ "submitted_date",
+ "approved_date",
+ "sample",
+ "result_date",
+ "employee",
+ "employee_name",
+ "employee_designation",
+ "user",
+ "report_preference",
+ "sb_first",
+ "lab_test_name",
+ "column_break_26",
+ "template",
+ "lab_test_group",
+ "sb_normal",
+ "normal_test_items",
+ "sb_special",
+ "special_test_items",
+ "sb_sensitivity",
+ "sensitivity_test_items",
+ "sb_comments",
+ "lab_test_comment",
+ "sb_customresult",
+ "custom_result",
+ "email_sent",
+ "sms_sent",
+ "printed",
+ "normal_toggle",
+ "special_toggle",
+ "sensitivity_toggle",
+ "amended_from",
+ "prescription"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.inpatient_record",
- "fieldname": "inpatient_record",
- "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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
- "options": "Inpatient Record",
- "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": "patient.inpatient_record",
+ "fieldname": "inpatient_record",
+ "fieldtype": "Link",
+ "label": "Inpatient Record",
+ "options": "Inpatient Record",
+ "read_only": 1
+ },
{
- "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": 0,
- "in_standard_filter": 0,
- "label": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "LP-",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "LP-",
+ "print_hide": 1,
+ "report_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "invoiced",
- "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": "Invoiced",
- "length": 0,
- "no_copy": 1,
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "no_copy": 1,
+ "read_only": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "inpatient_record.patient",
- "fieldname": "patient",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 1,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "inpatient_record.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1,
+ "search_index": 1,
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.patient_name",
- "fieldname": "patient_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Patient Name",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fetch_from": "patient.patient_name",
+ "fieldname": "patient_name",
+ "fieldtype": "Data",
+ "label": "Patient Name",
+ "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": "patient_age",
- "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": "Age",
- "length": 0,
- "no_copy": 0,
- "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": "patient_age",
+ "fieldtype": "Data",
+ "label": "Age",
+ "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": "patient_sex",
- "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": "Gender",
- "length": 0,
- "no_copy": 0,
- "options": "\nMale\nFemale\nOther",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient_sex",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender",
+ "print_hide": 1,
+ "report_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": "practitioner",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Healthcare Practitioner",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "practitioner",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "email",
- "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": "Email",
- "length": 0,
- "no_copy": 0,
- "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": "email",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Email",
+ "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": "mobile",
- "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": "Mobile",
- "length": 0,
- "no_copy": 0,
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "mobile",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Mobile",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Company",
+ "options": "Company",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "c_b",
- "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": 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": "c_b",
+ "fieldtype": "Column Break",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "department",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Medical Department",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Department",
+ "options": "Medical Department",
+ "search_index": 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": 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": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Draft\nCompleted\nApproved\nRejected\nCancelled",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "hidden": 1,
+ "label": "Status",
+ "options": "Draft\nCompleted\nApproved\nRejected\nCancelled",
+ "print_hide": 1,
+ "report_hide": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "submitted_date",
- "fieldtype": "Datetime",
- "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": "Submitted Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "submitted_date",
+ "fieldtype": "Datetime",
+ "hidden": 1,
+ "label": "Submitted Date",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "approved_date",
- "fieldtype": "Datetime",
- "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": "Approved Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "approved_date",
+ "fieldtype": "Datetime",
+ "hidden": 1,
+ "label": "Approved Date",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Sample ID",
- "length": 0,
- "no_copy": 0,
- "options": "Sample Collection",
- "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": "sample",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_filter": 1,
+ "label": "Sample ID",
+ "options": "Sample Collection",
+ "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,
- "default": "",
- "fieldname": "result_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": "Result 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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "result_date",
+ "fieldtype": "Date",
+ "label": "Result Date",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "employee",
- "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": "Lab Technician",
- "length": 0,
- "no_copy": 1,
- "options": "Employee",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "label": "Lab Technician",
+ "no_copy": 1,
+ "options": "Employee",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.employee_name",
- "fieldname": "employee_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Technician Name",
- "length": 0,
- "no_copy": 1,
- "options": "",
- "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
- },
+ "fetch_from": "employee.employee_name",
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
+ "label": "Technician Name",
+ "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,
- "fetch_from": "employee.designation",
- "fieldname": "employee_designation",
- "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": "Designation",
- "length": 0,
- "no_copy": 1,
- "options": "",
- "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
- },
+ "fetch_from": "employee.designation",
+ "fieldname": "employee_designation",
+ "fieldtype": "Data",
+ "label": "Designation",
+ "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": "user",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "User",
- "length": 0,
- "no_copy": 1,
- "options": "User",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "user",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "User",
+ "no_copy": 1,
+ "options": "User",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "report_preference",
- "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": "Report Preference",
- "length": 0,
- "no_copy": 0,
- "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": "report_preference",
+ "fieldtype": "Data",
+ "label": "Report Preference",
+ "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": "sb_first",
- "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": "sb_first",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lab_test_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": 1,
- "label": "Test Name",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "lab_test_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Test Name",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_26",
- "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_26",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "template",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Test Template",
- "length": 0,
- "no_copy": 0,
- "options": "Lab Test Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "template",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Test Template",
+ "options": "Lab Test Template",
+ "print_hide": 1,
+ "report_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": "lab_test_group",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Test Group",
- "length": 0,
- "no_copy": 0,
- "options": "Item Group",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "lab_test_group",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Test Group",
+ "options": "Item Group",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_normal",
- "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": "sb_normal",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "normal_test_items",
- "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,
- "length": 0,
- "no_copy": 0,
- "options": "Normal Test Items",
- "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": "normal_test_items",
+ "fieldtype": "Table",
+ "options": "Normal Test Items"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_special",
- "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": "sb_special",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "special_test_items",
- "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,
- "length": 0,
- "no_copy": 0,
- "options": "Special Test Items",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "special_test_items",
+ "fieldtype": "Table",
+ "options": "Special Test Items",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_sensitivity",
- "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": "sb_sensitivity",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sensitivity_test_items",
- "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,
- "length": 0,
- "no_copy": 0,
- "options": "Sensitivity Test Items",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "sensitivity_test_items",
+ "fieldtype": "Table",
+ "options": "Sensitivity Test Items",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_comments",
- "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": "sb_comments",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lab_test_comment",
- "fieldtype": "Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Comments",
- "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": "lab_test_comment",
+ "fieldtype": "Text",
+ "ignore_xss_filter": 1,
+ "label": "Comments"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "sb_customresult",
- "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": "Custom Result",
- "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": "sb_customresult",
+ "fieldtype": "Section Break",
+ "label": "Custom Result"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "custom_result",
- "fieldtype": "Text Editor",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Custom Result",
- "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": "custom_result",
+ "fieldtype": "Text Editor",
+ "ignore_xss_filter": 1,
+ "label": "Custom Result"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "email_sent",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "email_sent",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "sms_sent",
- "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": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "sms_sent",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "printed",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "printed",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "normal_toggle",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "normal_toggle",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "special_toggle",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "special_toggle",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "sensitivity_toggle",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "sensitivity_toggle",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "print_hide": 1,
+ "report_hide": 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": "Lab Test",
- "permlevel": 0,
- "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": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Lab Test",
+ "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": "prescription",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Prescription",
- "length": 0,
- "no_copy": 1,
- "options": "Lab Prescription",
- "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": "prescription",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Prescription",
+ "no_copy": 1,
+ "options": "Lab Prescription",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "",
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-09-04 10:19:33.422304",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Lab Test",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-03-23 19:37:06.617764",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Lab Test",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Laboratory User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Laboratory User",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "LabTest Approver",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "LabTest Approver",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Physician",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "patient,practitioner,lab_test_name,sample",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "patient",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "patient,practitioner,lab_test_name,sample",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1,
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py
index 8609489..4e4015d 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.py
@@ -191,20 +191,24 @@
special.template = template.name
def create_sample_doc(template, patient, invoice):
- if(template.sample):
- sample_exist = frappe.db.exists({
+ if template.sample:
+ sample_exists = frappe.db.exists({
"doctype": "Sample Collection",
"patient": patient.name,
"docstatus": 0,
- "sample": template.sample})
- if sample_exist :
- #Update Sample Collection by adding quantity
- sample_collection = frappe.get_doc("Sample Collection",sample_exist[0][0])
- quantity = int(sample_collection.sample_quantity)+int(template.sample_quantity)
- if(template.sample_collection_details):
- sample_collection_details = sample_collection.sample_collection_details+"\n==============\n"+"Test :"+template.lab_test_name+"\n"+"Collection Detials:\n\t"+template.sample_collection_details
- frappe.db.set_value("Sample Collection", sample_collection.name, "sample_collection_details",sample_collection_details)
- frappe.db.set_value("Sample Collection", sample_collection.name, "sample_quantity",quantity)
+ "sample": template.sample
+ })
+ if sample_exists:
+ # update Sample Collection by adding quantity
+ sample_collection = frappe.get_doc("Sample Collection", sample_exists[0][0])
+ quantity = int(sample_collection.sample_qty) + int(template.sample_qty)
+ if template.sample_details:
+ sample_details = sample_collection.sample_details + "\n==============\n" + _("Test: ")
+ sample_details += (template.get("lab_test_name") or template.get("template")) + "\n"
+ sample_details += _("Collection Details: ") + "\n\t" + template.sample_details
+
+ frappe.db.set_value("Sample Collection", sample_collection.name, "sample_details", sample_details)
+ frappe.db.set_value("Sample Collection", sample_collection.name, "sample_qty", quantity)
else:
#create Sample Collection for template, copy vals from Invoice
@@ -216,15 +220,15 @@
sample_collection.patient_sex = patient.sex
sample_collection.sample = template.sample
sample_collection.sample_uom = template.sample_uom
- sample_collection.sample_quantity = template.sample_quantity
- if(template.sample_collection_details):
- sample_collection.sample_collection_details = "Test :"+template.lab_test_name+"\n"+"Collection Detials:\n\t"+template.sample_collection_details
+ sample_collection.sample_qty = template.sample_qty
+ if(template.sample_details):
+ sample_collection.sample_details = "Test :" + (template.get("lab_test_name") or template.get("template")) +"\n"+"Collection Detials:\n\t"+template.sample_details
sample_collection.save(ignore_permissions=True)
return sample_collection
def create_sample_collection(lab_test, template, patient, invoice):
- if(frappe.db.get_value("Healthcare Settings", None, "require_sample_collection") == "1"):
+ if(frappe.db.get_value("Healthcare Settings", None, "create_sample_collection_for_lab_test") == "1"):
sample_collection = create_sample_doc(template, patient, invoice)
if(sample_collection):
lab_test.sample = sample_collection.name
@@ -290,10 +294,14 @@
comment = ""
if item.lab_test_comment:
comment = str(item.lab_test_comment)
- event = ""
+ table_row = item.lab_test_name
+
if item.lab_test_event:
- event = item.lab_test_event
- table_row = item.lab_test_name +" "+ event +" "+ item.result_value
+ table_row += " " + item.lab_test_event
+
+ if item.result_value:
+ table_row += " " + item.result_value
+
if item.normal_range:
table_row += " normal_range("+item.normal_range+")"
table_row += " "+comment
diff --git a/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.json b/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.json
index 46c04c6..2830038 100644
--- a/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.json
+++ b/erpnext/healthcare/doctype/lab_test_sample/lab_test_sample.json
@@ -1,145 +1,68 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:sample",
- "beta": 1,
- "creation": "2016-04-04 17:35:44.823951",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:sample",
+ "beta": 1,
+ "creation": "2016-04-04 17:35:44.823951",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "sample",
+ "sample_uom"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample",
- "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": "Sample",
- "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,
- "unique": 0
- },
+ "fieldname": "sample",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Sample",
+ "reqd": 1,
+ "unique": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample_uom",
- "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": "UOM",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
+ "bold": 1,
+ "fieldname": "sample_uom",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "UOM",
+ "options": "Lab Test UOM"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-08-31 13:46:22.508908",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Lab Test Sample",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "links": [],
+ "modified": "2020-01-29 23:02:02.249839",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Lab Test Sample",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Healthcare Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Laboratory User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Laboratory User",
+ "share": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "sample",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "sample",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json
index fcfecba..a606bc4 100644
--- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json
+++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json
@@ -35,8 +35,8 @@
"sb_sample_collection",
"sample",
"sample_uom",
- "sample_quantity",
- "sample_collection_details",
+ "sample_qty",
+ "sample_details",
"change_in_item"
],
"fields": [
@@ -105,7 +105,7 @@
"description": "If unchecked, the item wont be appear in Sales Invoice, but can be used in group test creation. ",
"fieldname": "is_billable",
"fieldtype": "Check",
- "label": "Is billable",
+ "label": "Is Billable",
"search_index": 1
},
{
@@ -114,7 +114,8 @@
"fieldname": "lab_test_rate",
"fieldtype": "Currency",
"in_list_view": 1,
- "label": "Standard Selling Rate"
+ "label": "Rate",
+ "mandatory_depends_on": "eval:doc.is_billable == 1"
},
{
"depends_on": "eval:doc.lab_test_template_type == 'Single'",
@@ -211,18 +212,6 @@
},
{
"default": "0",
- "fieldname": "sample_quantity",
- "fieldtype": "Float",
- "label": "Quantity"
- },
- {
- "fieldname": "sample_collection_details",
- "fieldtype": "Text",
- "ignore_xss_filter": 1,
- "label": "Collection Details"
- },
- {
- "default": "0",
"fieldname": "change_in_item",
"fieldtype": "Check",
"hidden": 1,
@@ -236,11 +225,23 @@
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
+ },
+ {
+ "default": "0",
+ "fieldname": "sample_qty",
+ "fieldtype": "Float",
+ "label": "Quantity"
+ },
+ {
+ "fieldname": "sample_details",
+ "fieldtype": "Text",
+ "ignore_xss_filter": 1,
+ "label": "Collection Details"
}
],
"links": [],
- "modified": "2020-01-21 21:02:16.108347",
- "modified_by": "ruchamahabal2@gmail.com",
+ "modified": "2020-03-25 16:53:01.740103",
+ "modified_by": "Administrator",
"module": "Healthcare",
"name": "Lab Test Template",
"owner": "Administrator",
diff --git a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py
index fd7ae80..6bbb4f1 100644
--- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py
+++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py
@@ -99,13 +99,10 @@
# get item price list to insert item price
if doc.lab_test_rate != 0.0:
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
- if(doc.lab_test_rate):
+ if doc.lab_test_rate:
make_item_price(item.name, price_list_name, doc.lab_test_rate)
- item.standard_rate = doc.lab_test_rate
else:
make_item_price(item.name, price_list_name, 0.0)
- item.standard_rate = 0.0
- item.save(ignore_permissions = True)
# Set item in the template
frappe.db.set_value("Lab Test Template", doc.name, "item", item.name)
diff --git a/erpnext/healthcare/doctype/patient/patient.js b/erpnext/healthcare/doctype/patient/patient.js
index 1a34fe8..d5df956 100644
--- a/erpnext/healthcare/doctype/patient/patient.js
+++ b/erpnext/healthcare/doctype/patient/patient.js
@@ -3,128 +3,77 @@
frappe.ui.form.on('Patient', {
refresh: function (frm) {
- frm.set_query("patient", "patient_relation", function () {
+ frm.set_query('patient', 'patient_relation', function () {
return {
filters: [
- ["Patient", "name", "!=", frm.doc.name]
+ ['Patient', 'name', '!=', frm.doc.name]
]
};
});
- if (frappe.defaults.get_default("patient_master_name") != "Naming Series") {
- frm.toggle_display("naming_series", false);
+
+ if (frappe.defaults.get_default('patient_name_by') != 'Naming Series') {
+ frm.toggle_display('naming_series', false);
} else {
erpnext.toggle_naming_series();
}
- if (frappe.defaults.get_default("collect_registration_fee") && frm.doc.disabled == 1) {
+
+ if (frappe.defaults.get_default('collect_registration_fee') && frm.doc.status == 'Disabled') {
frm.add_custom_button(__('Invoice Patient Registration'), function () {
- btn_invoice_registration(frm);
+ invoice_registration(frm);
});
}
- if (frm.doc.patient_name && frappe.user.has_role("Physician")) {
- frm.add_custom_button(__('Patient History'), function () {
- frappe.route_options = { "patient": frm.doc.name };
- frappe.set_route("patient_history");
- },"View");
+
+ if (frm.doc.patient_name && frappe.user.has_role('Physician')) {
+ frm.add_custom_button(__('Patient History'), function() {
+ frappe.route_options = {'patient': frm.doc.name};
+ frappe.set_route('patient_history');
+ },'View');
}
- if (!frm.doc.__islocal && (frappe.user.has_role("Nursing User") || frappe.user.has_role("Physician"))) {
+
+ if (!frm.doc.__islocal && (frappe.user.has_role('Nursing User') || frappe.user.has_role('Physician'))) {
frm.add_custom_button(__('Vital Signs'), function () {
- btn_create_vital_signs(frm);
- }, "Create");
+ create_vital_signs(frm);
+ }, 'Create');
frm.add_custom_button(__('Medical Record'), function () {
create_medical_record(frm);
- }, "Create");
+ }, 'Create');
frm.add_custom_button(__('Patient Encounter'), function () {
- btn_create_encounter(frm);
- }, "Create");
+ create_encounter(frm);
+ }, 'Create');
}
},
onload: function (frm) {
if(!frm.doc.dob){
- $(frm.fields_dict['age_html'].wrapper).html("");
+ $(frm.fields_dict['age_html'].wrapper).html('');
}
if(frm.doc.dob){
- $(frm.fields_dict['age_html'].wrapper).html("AGE : " + get_age(frm.doc.dob));
+ $(frm.fields_dict['age_html'].wrapper).html('AGE : ' + get_age(frm.doc.dob));
}
}
});
-frappe.ui.form.on("Patient", "dob", function(frm) {
- if(frm.doc.dob) {
- var today = new Date();
- var birthDate = new Date(frm.doc.dob);
- if(today < birthDate){
- frappe.msgprint(__("Please select a valid Date"));
- frappe.model.set_value(frm.doctype,frm.docname, "dob", "");
+frappe.ui.form.on('Patient', 'dob', function(frm) {
+ if (frm.doc.dob) {
+ let today = new Date();
+ let birthDate = new Date(frm.doc.dob);
+ if (today < birthDate){
+ frappe.msgprint(__('Please select a valid Date'));
+ frappe.model.set_value(frm.doctype,frm.docname, 'dob', '');
}
- else{
- var age_str = get_age(frm.doc.dob);
- $(frm.fields_dict['age_html'].wrapper).html("AGE : " + age_str);
+ else {
+ let age_str = get_age(frm.doc.dob);
+ $(frm.fields_dict['age_html'].wrapper).html('AGE : ' + age_str);
}
}
else {
- $(frm.fields_dict['age_html'].wrapper).html("");
+ $(frm.fields_dict['age_html'].wrapper).html('');
}
});
-var create_medical_record = function (frm) {
- frappe.route_options = {
- "patient": frm.doc.name,
- "status": "Open",
- "reference_doctype": "Patient Medical Record",
- "reference_owner": frm.doc.owner
- };
- frappe.new_doc("Patient Medical Record");
-};
-
-var get_age = function (birth) {
- var ageMS = Date.parse(Date()) - Date.parse(birth);
- var age = new Date();
- age.setTime(ageMS);
- var years = age.getFullYear() - 1970;
- return years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)";
-};
-
-var btn_create_vital_signs = function (frm) {
- if (!frm.doc.name) {
- frappe.throw(__("Please save the patient first"));
- }
- frappe.route_options = {
- "patient": frm.doc.name,
- };
- frappe.new_doc("Vital Signs");
-};
-
-var btn_create_encounter = function (frm) {
- if (!frm.doc.name) {
- frappe.throw(__("Please save the patient first"));
- }
- frappe.route_options = {
- "patient": frm.doc.name,
- };
- frappe.new_doc("Patient Encounter");
-};
-
-var btn_invoice_registration = function (frm) {
- frappe.call({
- doc: frm.doc,
- method: "invoice_patient_registration",
- callback: function(data){
- if(!data.exc){
- if(data.message.invoice){
- /* frappe.show_alert(__('Sales Invoice {0} created',
- ['<a href="#Form/Sales Invoice/'+data.message.invoice+'">' + data.message.invoice+ '</a>'])); */
- frappe.set_route("Form", "Sales Invoice", data.message.invoice);
- }
- cur_frm.reload_doc();
- }
- }
- });
-};
-
frappe.ui.form.on('Patient Relation', {
patient_relation_add: function(frm){
frm.fields_dict['patient_relation'].grid.get_field('patient').get_query = function(doc){
- var patient_list = [];
+ let patient_list = [];
if(!doc.__islocal) patient_list.push(doc.name);
$.each(doc.patient_relation, function(idx, val){
if (val.patient) patient_list.push(val.patient);
@@ -133,3 +82,56 @@
};
}
});
+
+let create_medical_record = function (frm) {
+ frappe.route_options = {
+ 'patient': frm.doc.name,
+ 'status': 'Open',
+ 'reference_doctype': 'Patient Medical Record',
+ 'reference_owner': frm.doc.owner
+ };
+ frappe.new_doc('Patient Medical Record');
+};
+
+let get_age = function (birth) {
+ let ageMS = Date.parse(Date()) - Date.parse(birth);
+ let age = new Date();
+ age.setTime(ageMS);
+ let years = age.getFullYear() - 1970;
+ return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
+};
+
+let create_vital_signs = function (frm) {
+ if (!frm.doc.name) {
+ frappe.throw(__('Please save the patient first'));
+ }
+ frappe.route_options = {
+ 'patient': frm.doc.name,
+ };
+ frappe.new_doc('Vital Signs');
+};
+
+let create_encounter = function (frm) {
+ if (!frm.doc.name) {
+ frappe.throw(__('Please save the patient first'));
+ }
+ frappe.route_options = {
+ 'patient': frm.doc.name,
+ };
+ frappe.new_doc('Patient Encounter');
+};
+
+let invoice_registration = function (frm) {
+ frappe.call({
+ doc: frm.doc,
+ method: 'invoice_patient_registration',
+ callback: function(data) {
+ if (!data.exc) {
+ if (data.message.invoice) {
+ frappe.set_route('Form', 'Sales Invoice', data.message.invoice);
+ }
+ cur_frm.reload_doc();
+ }
+ }
+ });
+};
diff --git a/erpnext/healthcare/doctype/patient/patient.json b/erpnext/healthcare/doctype/patient/patient.json
index 0136f72..4258e40 100644
--- a/erpnext/healthcare/doctype/patient/patient.json
+++ b/erpnext/healthcare/doctype/patient/patient.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_copy": 1,
"allow_import": 1,
"allow_rename": 1,
@@ -11,23 +12,29 @@
"engine": "InnoDB",
"field_order": [
"basic_info",
- "inpatient_status",
- "inpatient_record",
"naming_series",
+ "first_name",
+ "middle_name",
+ "last_name",
"patient_name",
"sex",
"blood_group",
"dob",
"age_html",
- "status",
"image",
"column_break_14",
+ "status",
+ "inpatient_status",
+ "inpatient_record",
"customer",
- "report_preference",
"mobile",
"email",
"phone",
- "disabled",
+ "report_preference",
+ "personal_and_social_history",
+ "occupation",
+ "column_break_25",
+ "marital_status",
"sb_relation",
"patient_relation",
"allergy_medical_and_surgical_history",
@@ -36,10 +43,6 @@
"column_break_20",
"medical_history",
"surgical_history",
- "personal_and_social_history",
- "occupation",
- "column_break_25",
- "marital_status",
"risk_factors",
"tobacco_past_use",
"tobacco_current_use",
@@ -78,28 +81,28 @@
{
"fieldname": "naming_series",
"fieldtype": "Select",
- "label": "Patient ID",
+ "label": "Series",
"options": "HLC-PAT-.YYYY.-",
"print_hide": 1,
- "report_hide": 1
+ "report_hide": 1,
+ "set_only_once": 1
},
{
"bold": 1,
"fieldname": "patient_name",
"fieldtype": "Data",
- "in_filter": 1,
+ "in_global_search": 1,
+ "in_list_view": 1,
"in_standard_filter": 1,
"label": "Full Name",
- "no_copy": 1,
- "oldfieldtype": "Data",
- "reqd": 1,
+ "read_only": 1,
"search_index": 1
},
{
"fieldname": "sex",
- "fieldtype": "Select",
+ "fieldtype": "Link",
"label": "Gender",
- "options": "\nMale\nFemale\nOther",
+ "options": "Gender",
"reqd": 1
},
{
@@ -125,15 +128,15 @@
"report_hide": 1
},
{
- "default": "Active",
"fieldname": "status",
"fieldtype": "Select",
- "hidden": 1,
+ "in_filter": 1,
+ "in_list_view": 1,
"label": "Status",
"no_copy": 1,
- "options": "Active\nDormant\nOpen",
+ "options": "Active\nDisabled",
"print_hide": 1,
- "report_hide": 1
+ "read_only": 1
},
{
"fieldname": "image",
@@ -149,12 +152,12 @@
"fieldtype": "Column Break"
},
{
+ "description": "If \"Link Customer to Patient\" is checked in Healthcare Settings and an existing Customer is not selected then, a Customer will be created for this Patient for recording transactions in Accounts module.",
"fieldname": "customer",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Customer",
- "options": "Customer",
- "set_only_once": 1
+ "options": "Customer"
},
{
"fieldname": "report_preference",
@@ -183,20 +186,9 @@
"fieldname": "phone",
"fieldtype": "Data",
"in_filter": 1,
- "in_list_view": 1,
"label": "Phone"
},
{
- "default": "0",
- "fieldname": "disabled",
- "fieldtype": "Check",
- "hidden": 1,
- "label": "Disabled",
- "no_copy": 1,
- "print_hide": 1,
- "report_hide": 1
- },
- {
"collapsible": 1,
"fieldname": "sb_relation",
"fieldtype": "Section Break",
@@ -276,25 +268,25 @@
"fieldname": "tobacco_past_use",
"fieldtype": "Data",
"ignore_xss_filter": 1,
- "label": "Tobacco Past Use"
+ "label": "Tobacco Consumption Habbits (Past)"
},
{
"fieldname": "tobacco_current_use",
"fieldtype": "Data",
"ignore_xss_filter": 1,
- "label": "Tobacco Current Use"
+ "label": "Tobacco Consumption Habbits (Present)"
},
{
"fieldname": "alcohol_past_use",
"fieldtype": "Data",
"ignore_xss_filter": 1,
- "label": "Alcohol Past Use"
+ "label": "Alcohol Consumption Habbits (Past)"
},
{
"fieldname": "alcohol_current_use",
"fieldtype": "Data",
"ignore_user_permissions": 1,
- "label": "Alcohol Current Use"
+ "label": "Alcohol Consumption Habbits (Present)"
},
{
"fieldname": "column_break_32",
@@ -342,12 +334,30 @@
"label": "Default Currency",
"options": "Currency",
"print_hide": 1
+ },
+ {
+ "fieldname": "last_name",
+ "fieldtype": "Data",
+ "label": "Last Name"
+ },
+ {
+ "fieldname": "first_name",
+ "fieldtype": "Data",
+ "label": "First Name",
+ "oldfieldtype": "Data",
+ "reqd": 1
+ },
+ {
+ "fieldname": "middle_name",
+ "fieldtype": "Data",
+ "label": "Middle Name (optional)"
}
],
"icon": "fa fa-user",
"image_field": "image",
+ "links": [],
"max_attachments": 50,
- "modified": "2019-09-25 23:30:49.905893",
+ "modified": "2020-04-06 12:55:30.807744",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Patient",
diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py
index e3eea96..e304a0b 100644
--- a/erpnext/healthcare/doctype/patient/patient.py
+++ b/erpnext/healthcare/doctype/patient/patient.py
@@ -6,46 +6,57 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from frappe.utils import cint, cstr, getdate, flt
+from frappe.utils import cint, cstr, getdate
import dateutil
from frappe.model.naming import set_name_by_naming_series
-from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account,get_income_account,send_registration_sms
+from frappe.utils.nestedset import get_root_of
+from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account, send_registration_sms
class Patient(Document):
- def after_insert(self):
- if(frappe.db.get_value("Healthcare Settings", None, "manage_customer") == '1' and not self.customer):
- create_customer(self)
- if(frappe.db.get_value("Healthcare Settings", None, "collect_registration_fee") == '1'):
- frappe.db.set_value("Patient", self.name, "disabled", 1)
- else:
- send_registration_sms(self)
- self.reload()
-
- def on_update(self):
+ def validate(self):
+ self.set_full_name()
self.add_as_website_user()
+ def after_insert(self):
+ self.add_as_website_user()
+ self.reload()
+ if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient') and not self.customer:
+ create_customer(self)
+ if frappe.db.get_single_value('Healthcare Settings', 'collect_registration_fee'):
+ frappe.db.set_value('Patient', self.name, 'status', 'Disabled')
+ else:
+ send_registration_sms(self)
+
+ def set_full_name(self):
+ if self.last_name:
+ self.patient_name = ' '.join(filter(None, [self.first_name, self.last_name]))
+ else:
+ self.patient_name = self.first_name
+
def add_as_website_user(self):
- if(self.email):
- if not frappe.db.exists ("User", self.email):
+ if self.email:
+ if not frappe.db.exists ('User', self.email):
user = frappe.get_doc({
- "doctype": "User",
- "first_name": self.patient_name,
- "email": self.email,
- "user_type": "Website User"
+ 'doctype': 'User',
+ 'first_name': self.first_name,
+ 'last_name': self.last_name,
+ 'email': self.email,
+ 'user_type': 'Website User'
})
user.flags.ignore_permissions = True
- user.add_roles("Patient")
+ user.add_roles('Patient')
def autoname(self):
- patient_master_name = frappe.defaults.get_global_default('patient_master_name')
- if patient_master_name == 'Patient Name':
+ patient_name_by = frappe.db.get_single_value('Healthcare Settings', 'patient_name_by')
+ if patient_name_by == 'Patient Name':
self.name = self.get_patient_name()
else:
set_name_by_naming_series(self)
def get_patient_name(self):
+ self.set_full_name()
name = self.patient_name
- if frappe.db.get_value("Patient", name):
+ if frappe.db.get_value('Patient', name):
count = frappe.db.sql("""select ifnull(MAX(CAST(SUBSTRING_INDEX(name, ' ', -1) AS UNSIGNED)), 0) from tabPatient
where name like %s""", "%{0} - %".format(name), as_list=1)[0][0]
count = cint(count) + 1
@@ -54,56 +65,62 @@
return name
def get_age(self):
- age_str = ""
+ age_str = ''
if self.dob:
- born = getdate(self.dob)
- age = dateutil.relativedelta.relativedelta(getdate(), born)
- age_str = str(age.years) + " year(s) " + str(age.months) + " month(s) " + str(age.days) + " day(s)"
+ dob = getdate(self.dob)
+ age = dateutil.relativedelta.relativedelta(getdate(), dob)
+ age_str = str(age.years) + ' year(s) ' + str(age.months) + ' month(s) ' + str(age.days) + ' day(s)'
return age_str
def invoice_patient_registration(self):
- frappe.db.set_value("Patient", self.name, "disabled", 0)
- send_registration_sms(self)
- if(flt(frappe.get_value("Healthcare Settings", None, "registration_fee"))>0):
+ if frappe.db.get_single_value('Healthcare Settings', 'registration_fee'):
company = frappe.defaults.get_user_default('company')
if not company:
- company = frappe.db.get_value("Global Defaults", None, "default_company")
+ company = frappe.db.get_single_value('Global Defaults', 'default_company')
+
sales_invoice = make_invoice(self.name, company)
sales_invoice.save(ignore_permissions=True)
+ frappe.db.set_value('Patient', self.name, 'status', 'Active')
+ send_registration_sms(self)
+
return {'invoice': sales_invoice.name}
def create_customer(doc):
- customer_group = frappe.get_value("Selling Settings", None, "customer_group")
- territory = frappe.get_value("Selling Settings", None, "territory")
+ customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
+ territory = frappe.db.get_single_value('Selling Settings', 'territory')
if not (customer_group and territory):
- customer_group = "Commercial"
- territory = "Rest Of The World"
- frappe.msgprint(_("Please set default customer group and territory in Selling Settings"), alert=True)
- customer = frappe.get_doc({"doctype": "Customer",
- "customer_name": doc.patient_name,
- "customer_group": customer_group,
- "territory" : territory,
- "customer_type": "Individual"
- }).insert(ignore_permissions=True)
- frappe.db.set_value("Patient", doc.name, "customer", customer.name)
- frappe.msgprint(_("Customer {0} is created.").format(customer.name), alert=True)
+ customer_group = get_root_of('Customer Group')
+ territory = get_root_of('Territory')
+ frappe.msgprint(_('Please set default customer group and territory in Selling Settings'), alert=True)
+
+ customer = frappe.get_doc({
+ 'doctype': 'Customer',
+ 'customer_name': doc.patient_name,
+ 'customer_group': customer_group,
+ 'territory' : territory,
+ 'customer_type': 'Individual'
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
+
+ frappe.db.set_value('Patient', doc.name, 'customer', customer.name)
+ frappe.msgprint(_('Customer {0} is created.').format(customer.name), alert=True)
def make_invoice(patient, company):
- sales_invoice = frappe.new_doc("Sales Invoice")
- sales_invoice.customer = frappe.get_value("Patient", patient, "customer")
+ uom = frappe.db.exists('UOM', 'Nos') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
+ sales_invoice = frappe.new_doc('Sales Invoice')
+ sales_invoice.customer = frappe.db.get_value('Patient', patient, 'customer')
sales_invoice.due_date = getdate()
sales_invoice.company = company
- sales_invoice.is_pos = '0'
+ sales_invoice.is_pos = 0
sales_invoice.debit_to = get_receivable_account(company)
- item_line = sales_invoice.append("items")
- item_line.item_name = "Registeration Fee"
- item_line.description = "Registeration Fee"
+ item_line = sales_invoice.append('items')
+ item_line.item_name = 'Registeration Fee'
+ item_line.description = 'Registeration Fee'
item_line.qty = 1
- item_line.uom = "Nos"
+ item_line.uom = uom
item_line.conversion_factor = 1
item_line.income_account = get_income_account(None, company)
- item_line.rate = frappe.get_value("Healthcare Settings", None, "registration_fee")
+ item_line.rate = frappe.db.get_single_value('Healthcare Settings', 'registration_fee')
item_line.amount = item_line.rate
sales_invoice.set_missing_values()
return sales_invoice
@@ -112,7 +129,7 @@
def get_patient_detail(patient):
patient_dict = frappe.db.sql("""select * from tabPatient where name=%s""", (patient), as_dict=1)
if not patient_dict:
- frappe.throw(_("Patient not found"))
+ frappe.throw(_('Patient not found'))
vital_sign = frappe.db.sql("""select * from `tabVital Signs` where patient=%s
order by signs_date desc limit 1""", (patient), as_dict=1)
diff --git a/erpnext/healthcare/doctype/patient/test_patient.py b/erpnext/healthcare/doctype/patient/test_patient.py
index aebaa6b..9274b6f 100644
--- a/erpnext/healthcare/doctype/patient/test_patient.py
+++ b/erpnext/healthcare/doctype/patient/test_patient.py
@@ -4,8 +4,31 @@
from __future__ import unicode_literals
import unittest
-
-# test_records = frappe.get_test_records('Patient')
+import frappe
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient
class TestPatient(unittest.TestCase):
- pass
+ def test_customer_created(self):
+ frappe.db.sql("""delete from `tabPatient`""")
+ frappe.db.set_value('Healthcare Settings', None, 'link_customer_to_patient', 1)
+ patient = create_patient()
+ self.assertTrue(frappe.db.get_value('Patient', patient, 'customer'))
+
+ def test_patient_registration(self):
+ frappe.db.sql("""delete from `tabPatient`""")
+ settings = frappe.get_single('Healthcare Settings')
+ settings.collect_registration_fee = 1
+ settings.registration_fee = 500
+ settings.save()
+
+ patient = create_patient()
+ patient = frappe.get_doc('Patient', patient)
+ self.assertEqual(patient.status, 'Disabled')
+
+ # check sales invoice and patient status
+ result = patient.invoice_patient_registration()
+ self.assertTrue(frappe.db.exists('Sales Invoice', result.get('invoice')))
+ self.assertTrue(patient.status, 'Active')
+
+ settings.collect_registration_fee = 0
+ settings.save()
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
index 858145e..efa6b24 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, ESS LLP and contributors
// For license information, please see license.txt
-frappe.provide("erpnext.queries");
+frappe.provide('erpnext.queries');
frappe.ui.form.on('Patient Appointment', {
setup: function(frm) {
frm.custom_make_buttons = {
@@ -8,151 +8,188 @@
'Patient Encounter': 'Patient Encounter'
};
},
+
+ onload: function(frm) {
+ if (frm.is_new()) {
+ frm.set_value('appointment_time', null);
+ frm.disable_save();
+ }
+ },
+
refresh: function(frm) {
- frm.set_query("patient", function () {
+ frm.set_query('patient', function () {
return {
- filters: {"disabled": 0}
+ filters: {'status': 'Active'}
};
});
- frm.set_query("practitioner", function() {
+ frm.set_query('practitioner', function() {
return {
filters: {
'department': frm.doc.department
}
};
});
- frm.set_query("service_unit", function(){
+ frm.set_query('service_unit', function(){
return {
filters: {
- "is_group": false,
- "allow_appointments": true
+ 'is_group': 0,
+ 'allow_appointments': 1
}
};
});
- if(frm.doc.patient){
+
+ if (frm.is_new()) {
+ frm.page.set_primary_action(__('Check Availability'), function() {
+ if (!frm.doc.patient) {
+ frappe.msgprint({
+ title: __('Not Allowed'),
+ message: __('Please select Patient first'),
+ indicator: 'red'
+ });
+ } else {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.check_payment_fields_reqd',
+ args: {'patient': frm.doc.patient},
+ callback: function(data) {
+ if (data.message == true) {
+ if (frm.doc.mode_of_payment && frm.doc.paid_amount) {
+ check_and_set_availability(frm);
+ }
+ if (!frm.doc.mode_of_payment) {
+ frappe.msgprint({
+ title: __('Not Allowed'),
+ message: __('Please select a Mode of Payment first'),
+ indicator: 'red'
+ });
+ }
+ if (!frm.doc.paid_amount) {
+ frappe.msgprint({
+ title: __('Not Allowed'),
+ message: __('Please set the Paid Amount first'),
+ indicator: 'red'
+ });
+ }
+ } else {
+ check_and_set_availability(frm);
+ }
+ }
+ });
+ }
+ });
+ } else {
+ frm.page.set_primary_action(__('Save'), () => frm.save());
+ }
+
+ if (frm.doc.patient) {
frm.add_custom_button(__('Patient History'), function() {
- frappe.route_options = {"patient": frm.doc.patient};
- frappe.set_route("patient_history");
- },__("View"));
+ frappe.route_options = {'patient': frm.doc.patient};
+ frappe.set_route('patient_history');
+ }, __('View'));
}
- if(frm.doc.status == "Open"){
+
+ if (frm.doc.status == 'Open' || (frm.doc.status == 'Scheduled' && !frm.doc.__islocal)) {
frm.add_custom_button(__('Cancel'), function() {
- btn_update_status(frm, "Cancelled");
+ update_status(frm, 'Cancelled');
});
frm.add_custom_button(__('Reschedule'), function() {
check_and_set_availability(frm);
});
- if(frm.doc.procedure_template){
- frm.add_custom_button(__("Procedure"),function(){
- btn_create_procedure(frm);
- },"Create");
- }
- else{
- frm.add_custom_button(__("Patient Encounter"),function(){
- btn_create_encounter(frm);
- },"Create");
+
+ if (frm.doc.procedure_template) {
+ frm.add_custom_button(__('Clinical Procedure'), function(){
+ frappe.model.open_mapped_doc({
+ method: 'erpnext.healthcare.doctype.clinical_procedure.clinical_procedure.make_procedure',
+ frm: frm,
+ });
+ }, __('Create'));
+ } else {
+ frm.add_custom_button(__('Patient Encounter'), function() {
+ frappe.model.open_mapped_doc({
+ method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.make_encounter',
+ frm: frm,
+ });
+ }, __('Create'));
}
frm.add_custom_button(__('Vital Signs'), function() {
- btn_create_vital_signs(frm);
- },"Create");
+ create_vital_signs(frm);
+ }, __('Create'));
}
- if(frm.doc.status == "Scheduled" && !frm.doc.__islocal){
- frm.add_custom_button(__('Cancel'), function() {
- btn_update_status(frm, "Cancelled");
- });
- frm.add_custom_button(__('Reschedule'), function() {
- check_and_set_availability(frm);
- });
- if(frm.doc.procedure_template){
- frm.add_custom_button(__("Procedure"),function(){
- btn_create_procedure(frm);
- },"Create");
- }
- else{
- frm.add_custom_button(__("Patient Encounter"),function(){
- btn_create_encounter(frm);
- },"Create");
- }
+ },
- frm.add_custom_button(__('Vital Signs'), function() {
- btn_create_vital_signs(frm);
- },"Create");
+ patient: function(frm) {
+ if (frm.doc.patient) {
+ frm.trigger('toggle_payment_fields');
}
- if(frm.doc.status == "Pending"){
- frm.add_custom_button(__('Set Open'), function() {
- btn_update_status(frm, "Open");
- });
- frm.add_custom_button(__('Cancel'), function() {
- btn_update_status(frm, "Cancelled");
- });
- }
- frm.set_df_property("get_procedure_from_encounter", "read_only", frm.doc.__islocal ? 0 : 1);
- frappe.db.get_value('Healthcare Settings', {name: 'Healthcare Settings'}, 'manage_appointment_invoice_automatically', (r) => {
- if(r.manage_appointment_invoice_automatically == 1){
- frm.set_df_property("mode_of_payment", "hidden", 0);
- frm.set_df_property("paid_amount", "hidden", 0);
- frm.set_df_property("mode_of_payment", "reqd", 1);
- frm.set_df_property("paid_amount", "reqd", 1);
- }
- else{
- frm.set_df_property("mode_of_payment", "hidden", 1);
- frm.set_df_property("paid_amount", "hidden", 1);
- frm.set_df_property("mode_of_payment", "reqd", 0);
- frm.set_df_property("paid_amount", "reqd", 0);
+ },
+
+ get_procedure_from_encounter: function(frm) {
+ get_prescribed_procedure(frm);
+ },
+
+ toggle_payment_fields: function(frm) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.check_payment_fields_reqd',
+ args: {'patient': frm.doc.patient},
+ callback: function(data) {
+ if (data.message.fee_validity) {
+ // if fee validity exists and automated appointment invoicing is enabled,
+ // show payment fields as non-mandatory
+ frm.toggle_display('mode_of_payment', 0);
+ frm.toggle_display('paid_amount', 0);
+ frm.toggle_reqd('mode_of_payment', 0);
+ frm.toggle_reqd('paid_amount', 0);
+ } else {
+ // if automated appointment invoicing is disabled, hide fields
+ frm.toggle_display('mode_of_payment', data.message ? 1 : 0);
+ frm.toggle_display('paid_amount', data.message ? 1 : 0);
+ frm.toggle_reqd('mode_of_payment', data.message ? 1 : 0);
+ frm.toggle_reqd('paid_amount', data.message ? 1 :0);
+ }
}
});
- },
- check_availability: function(frm) {
- check_and_set_availability(frm);
- },
- onload:function(frm){
- if(frm.is_new()) {
- frm.set_value("appointment_time", null);
- frm.disable_save();
- }
- },
- get_procedure_from_encounter: function(frm) {
- get_procedure_prescribed(frm);
}
});
-var check_and_set_availability = function(frm) {
- var selected_slot = null;
- var service_unit = null;
- var duration = null;
+let check_and_set_availability = function(frm) {
+ let selected_slot = null;
+ let service_unit = null;
+ let duration = null;
show_availability();
function show_empty_state(practitioner, appointment_date) {
frappe.msgprint({
title: __('Not Available'),
- message: __("Healthcare Practitioner {0} not available on {1}", [practitioner.bold(), appointment_date.bold()]),
+ message: __('Healthcare Practitioner {0} not available on {1}', [practitioner.bold(), appointment_date.bold()]),
indicator: 'red'
});
}
function show_availability() {
let selected_practitioner = '';
- var d = new frappe.ui.Dialog({
- title: __("Available slots"),
+ let d = new frappe.ui.Dialog({
+ title: __('Available slots'),
fields: [
- { fieldtype: 'Link', options: 'Medical Department', reqd:1, fieldname: 'department', label: 'Medical Department'},
+ { fieldtype: 'Link', options: 'Medical Department', reqd: 1, fieldname: 'department', label: 'Medical Department'},
{ fieldtype: 'Column Break'},
- { fieldtype: 'Link', options: 'Healthcare Practitioner', reqd:1, fieldname: 'practitioner', label: 'Healthcare Practitioner'},
+ { fieldtype: 'Link', options: 'Healthcare Practitioner', reqd: 1, fieldname: 'practitioner', label: 'Healthcare Practitioner'},
{ fieldtype: 'Column Break'},
- { fieldtype: 'Date', reqd:1, fieldname: 'appointment_date', label: 'Date'},
+ { fieldtype: 'Date', reqd: 1, fieldname: 'appointment_date', label: 'Date'},
{ fieldtype: 'Section Break'},
{ fieldtype: 'HTML', fieldname: 'available_slots'}
+
],
- primary_action_label: __("Book"),
+ primary_action_label: __('Book'),
primary_action: function() {
frm.set_value('appointment_time', selected_slot);
- frm.set_value('service_unit', service_unit || '');
frm.set_value('duration', duration);
frm.set_value('practitioner', d.get_value('practitioner'));
frm.set_value('department', d.get_value('department'));
frm.set_value('appointment_date', d.get_value('appointment_date'));
+ if (service_unit) {
+ frm.set_value('service_unit', service_unit);
+ }
d.hide();
frm.enable_save();
frm.save();
@@ -167,16 +204,16 @@
'appointment_date': frm.doc.appointment_date
});
- d.fields_dict["department"].df.onchange = () => {
+ d.fields_dict['department'].df.onchange = () => {
d.set_values({
'practitioner': ''
});
- var department = d.get_value('department');
- if(department){
+ let department = d.get_value('department');
+ if (department) {
d.fields_dict.practitioner.get_query = function() {
return {
filters: {
- "department": department
+ 'department': department
}
};
};
@@ -188,13 +225,13 @@
// Field Change Handler
- var fd = d.fields_dict;
+ let fd = d.fields_dict;
- d.fields_dict["appointment_date"].df.onchange = () => {
+ d.fields_dict['appointment_date'].df.onchange = () => {
show_slots(d, fd);
};
- d.fields_dict["practitioner"].df.onchange = () => {
- if(d.get_value('practitioner') && d.get_value('practitioner') != selected_practitioner){
+ d.fields_dict['practitioner'].df.onchange = () => {
+ if (d.get_value('practitioner') && d.get_value('practitioner') != selected_practitioner) {
selected_practitioner = d.get_value('practitioner');
show_slots(d, fd);
}
@@ -203,8 +240,8 @@
}
function show_slots(d, fd) {
- if (d.get_value('appointment_date') && d.get_value('practitioner')){
- fd.available_slots.html("");
+ if (d.get_value('appointment_date') && d.get_value('practitioner')) {
+ fd.available_slots.html('');
frappe.call({
method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_availability_data',
args: {
@@ -212,13 +249,13 @@
date: d.get_value('appointment_date')
},
callback: (r) => {
- var data = r.message;
- if(data.slot_details.length > 0) {
- var $wrapper = d.fields_dict.available_slots.$wrapper;
+ let data = r.message;
+ if (data.slot_details.length > 0) {
+ let $wrapper = d.fields_dict.available_slots.$wrapper;
// make buttons for each slot
- var slot_details = data.slot_details;
- var slot_html = "";
+ let slot_details = data.slot_details;
+ let slot_html = '';
for (let i = 0; i < slot_details.length; i++) {
slot_html = slot_html + `<label>${slot_details[i].slot_name}</label>`;
slot_html = slot_html + `<br/>` + slot_details[i].avail_slot.map(slot => {
@@ -232,14 +269,14 @@
let booked_moment = moment(booked.appointment_time, 'HH:mm:ss');
let end_time = booked_moment.clone().add(booked.duration, 'minutes');
// Deal with 0 duration appointments
- if(booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)){
+ if (booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)) {
if(booked.duration == 0){
disabled = 'disabled="disabled"';
return false;
}
}
// Check for overlaps considering appointment duration
- if(slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)){
+ if (slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)) {
// There is an overlap
disabled = 'disabled="disabled"';
return false;
@@ -263,7 +300,7 @@
// blue button when clicked
$wrapper.on('click', 'button', function() {
- var $btn = $(this);
+ let $btn = $(this);
$wrapper.find('button').removeClass('btn-primary');
$btn.addClass('btn-primary');
selected_slot = $btn.attr('data-name');
@@ -273,48 +310,57 @@
d.get_primary_btn().attr('disabled', null);
});
- }else {
- // fd.available_slots.html("Please select a valid date.".bold())
+ } else {
+ // fd.available_slots.html('Please select a valid date.'.bold())
show_empty_state(d.get_value('practitioner'), d.get_value('appointment_date'));
}
},
freeze: true,
- freeze_message: __("Fetching records......")
+ freeze_message: __('Fetching records......')
});
- }else{
- fd.available_slots.html("Appointment date and Healthcare Practitioner are Mandatory".bold());
+ } else {
+ fd.available_slots.html(__('Appointment date and Healthcare Practitioner are Mandatory').bold());
}
}
};
-var get_procedure_prescribed = function(frm){
- if(frm.doc.patient){
+let get_prescribed_procedure = function(frm) {
+ if (frm.doc.patient) {
frappe.call({
- method:"erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_procedure_prescribed",
+ method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_procedure_prescribed',
args: {patient: frm.doc.patient},
- callback: function(r){
- show_procedure_templates(frm, r.message);
+ callback: function(r) {
+ if (r.message && r.message.length) {
+ show_procedure_templates(frm, r.message);
+ } else {
+ frappe.msgprint({
+ title: __('Not Found'),
+ message: __('No Prescribed Procedures found for the selected Patient')
+ });
+ }
}
});
- }
- else{
- frappe.msgprint(__("Please select Patient to get prescribed procedure"));
+ } else {
+ frappe.msgprint({
+ title: __('Not Allowed'),
+ message: __('Please select a Patient first')
+ });
}
};
-var show_procedure_templates = function(frm, result){
- var d = new frappe.ui.Dialog({
- title: __("Prescribed Procedures"),
+let show_procedure_templates = function(frm, result){
+ let d = new frappe.ui.Dialog({
+ title: __('Prescribed Procedures'),
fields: [
{
- fieldtype: "HTML", fieldname: "procedure_template"
+ fieldtype: 'HTML', fieldname: 'procedure_template'
}
]
});
- var html_field = d.fields_dict.procedure_template.$wrapper;
+ let html_field = d.fields_dict.procedure_template.$wrapper;
html_field.empty();
- $.each(result, function(x, y){
- var row = $(repl('<div class="col-xs-12" style="padding-top:12px; text-align:center;" >\
+ $.each(result, function(x, y) {
+ let row = $(repl('<div class="col-xs-12" style="padding-top:12px; text-align:center;" >\
<div class="col-xs-5"> %(encounter)s <br> %(consulting_practitioner)s <br> %(encounter_date)s </div>\
<div class="col-xs-5"> %(procedure_template)s <br>%(practitioner)s <br> %(date)s</div>\
<div class="col-xs-2">\
@@ -326,76 +372,47 @@
encounter:y[2], consulting_practitioner:y[3], encounter_date:y[4],
practitioner:y[5]? y[5]:'', date: y[6]? y[6]:'', department: y[7]? y[7]:''})).appendTo(html_field);
row.find("a").click(function() {
- frm.doc.procedure_template = $(this).attr("data-procedure-template");
- frm.doc.procedure_prescription = $(this).attr("data-name");
- frm.doc.practitioner = $(this).attr("data-practitioner");
- frm.doc.appointment_date = $(this).attr("data-date");
- frm.doc.department = $(this).attr("data-department");
- refresh_field("procedure_template");
- refresh_field("procedure_prescription");
- refresh_field("appointment_date");
- refresh_field("practitioner");
- refresh_field("department");
+ frm.doc.procedure_template = $(this).attr('data-procedure-template');
+ frm.doc.procedure_prescription = $(this).attr('data-name');
+ frm.doc.practitioner = $(this).attr('data-practitioner');
+ frm.doc.appointment_date = $(this).attr('data-date');
+ frm.doc.department = $(this).attr('data-department');
+ refresh_field('procedure_template');
+ refresh_field('procedure_prescription');
+ refresh_field('appointment_date');
+ refresh_field('practitioner');
+ refresh_field('department');
d.hide();
return false;
});
});
- if(!result){
- var msg = "There are no procedure prescribed for "+frm.doc.patient;
+ if (!result) {
+ let msg = __('There are no procedure prescribed for ') + frm.doc.patient;
$(repl('<div class="col-xs-12" style="padding-top:20px;" >%(msg)s</div></div>', {msg: msg})).appendTo(html_field);
}
d.show();
};
-var btn_create_procedure = function(frm){
- var doc = frm.doc;
- frappe.call({
- method:"erpnext.healthcare.doctype.clinical_procedure.clinical_procedure.create_procedure",
- args: {appointment: doc.name},
- callback: function(data){
- if(!data.exc){
- var doclist = frappe.model.sync(data.message);
- frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
- }
- }
- });
-};
-
-var btn_create_encounter = function(frm){
- var doc = frm.doc;
- frappe.call({
- method:"erpnext.healthcare.doctype.patient_appointment.patient_appointment.create_encounter",
- args: {appointment: doc.name},
- callback: function(data){
- if(!data.exc){
- var doclist = frappe.model.sync(data.message);
- frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
- }
- }
- });
-};
-
-var btn_create_vital_signs = function (frm) {
- if(!frm.doc.patient){
- frappe.throw(__("Please select patient"));
+let create_vital_signs = function(frm) {
+ if (!frm.doc.patient) {
+ frappe.throw(__('Please select patient'));
}
frappe.route_options = {
- "patient": frm.doc.patient,
- "appointment": frm.doc.name,
+ 'patient': frm.doc.patient,
+ 'appointment': frm.doc.name,
};
- frappe.new_doc("Vital Signs");
+ frappe.new_doc('Vital Signs');
};
-var btn_update_status = function(frm, status){
- var doc = frm.doc;
+let update_status = function(frm, status){
+ let doc = frm.doc;
frappe.confirm(__('Are you sure you want to cancel this appointment?'),
function() {
frappe.call({
- method:
- "erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status",
+ method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status',
args: {appointment_id: doc.name, status:status},
- callback: function(data){
- if(!data.exc){
+ callback: function(data) {
+ if (!data.exc) {
frm.reload_doc();
}
}
@@ -404,60 +421,60 @@
);
};
-frappe.ui.form.on("Patient Appointment", "practitioner", function(frm) {
- if(frm.doc.practitioner){
+frappe.ui.form.on('Patient Appointment', 'practitioner', function(frm) {
+ if (frm.doc.practitioner) {
frappe.call({
- "method": "frappe.client.get",
+ method: 'frappe.client.get',
args: {
- doctype: "Healthcare Practitioner",
+ doctype: 'Healthcare Practitioner',
name: frm.doc.practitioner
},
callback: function (data) {
- frappe.model.set_value(frm.doctype,frm.docname, "department",data.message.department);
- frappe.model.set_value(frm.doctype,frm.docname, "paid_amount",data.message.op_consulting_charge);
+ frappe.model.set_value(frm.doctype, frm.docname, 'department', data.message.department);
+ frappe.model.set_value(frm.doctype, frm.docname, 'paid_amount', data.message.op_consulting_charge);
}
});
}
});
-frappe.ui.form.on("Patient Appointment", "patient", function(frm) {
- if(frm.doc.patient){
+frappe.ui.form.on('Patient Appointment', 'patient', function(frm) {
+ if (frm.doc.patient) {
frappe.call({
- "method": "frappe.client.get",
+ method: 'frappe.client.get',
args: {
- doctype: "Patient",
+ doctype: 'Patient',
name: frm.doc.patient
},
callback: function (data) {
- var age = null;
- if(data.message.dob){
+ let age = null;
+ if (data.message.dob) {
age = calculate_age(data.message.dob);
}
- frappe.model.set_value(frm.doctype,frm.docname, "patient_age", age);
+ frappe.model.set_value(frm.doctype,frm.docname, 'patient_age', age);
}
});
}
});
-frappe.ui.form.on("Patient Appointment", "appointment_type", function(frm) {
- if(frm.doc.appointment_type) {
+frappe.ui.form.on('Patient Appointment', 'appointment_type', function(frm) {
+ if (frm.doc.appointment_type) {
frappe.call({
- "method": "frappe.client.get",
+ method: 'frappe.client.get',
args: {
- doctype: "Appointment Type",
+ doctype: 'Appointment Type',
name: frm.doc.appointment_type
},
- callback: function (data) {
- frappe.model.set_value(frm.doctype,frm.docname, "duration",data.message.default_duration);
+ callback: function(data) {
+ frappe.model.set_value(frm.doctype,frm.docname, 'duration',data.message.default_duration);
}
});
}
});
-var calculate_age = function(birth) {
- var ageMS = Date.parse(Date()) - Date.parse(birth);
- var age = new Date();
+let calculate_age = function(birth) {
+ let ageMS = Date.parse(Date()) - Date.parse(birth);
+ let age = new Date();
age.setTime(ageMS);
- var years = age.getFullYear() - 1970;
- return years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)";
+ let years = age.getFullYear() - 1970;
+ return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
};
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
index ee9f013..7f9a671 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
@@ -1,1177 +1,333 @@
{
+ "actions": [],
"allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
- "allow_rename": 0,
- "autoname": "OP-.######",
+ "autoname": "naming_series:",
"beta": 1,
"creation": "2017-05-04 11:52:40.941507",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
- "editable_grid": 0,
"engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "patient",
+ "patient_name",
+ "patient_sex",
+ "patient_age",
+ "inpatient_record",
+ "column_break_1",
+ "status",
+ "procedure_template",
+ "get_procedure_from_encounter",
+ "procedure_prescription",
+ "service_unit",
+ "section_break_12",
+ "practitioner",
+ "department",
+ "appointment_type",
+ "column_break_17",
+ "appointment_date",
+ "appointment_time",
+ "appointment_datetime",
+ "duration",
+ "section_break_16",
+ "mode_of_payment",
+ "paid_amount",
+ "company",
+ "column_break_2",
+ "invoiced",
+ "ref_sales_invoice",
+ "section_break_3",
+ "notes",
+ "referring_practitioner",
+ "reminded"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.inpatient_record",
"fieldname": "inpatient_record",
"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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
"options": "Inpatient Record",
- "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,
"fetch_from": "inpatient_record.patient",
"fieldname": "patient",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Patient",
- "length": 0,
- "no_copy": 0,
"options": "Patient",
- "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": 1,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment_type",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Appointment Type",
- "length": 0,
- "no_copy": 0,
"options": "Appointment 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": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "In Minutes",
"fieldname": "duration",
"fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Duration",
- "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": "Duration (In Minutes)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_1",
"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,
- "label": "",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Scheduled",
"depends_on": "eval:!doc.__islocal",
"fieldname": "status",
"fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
+ "in_list_view": 1,
"label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "\nScheduled\nOpen\nClosed\nPending\nCancelled",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
+ "options": "\nScheduled\nOpen\nClosed\nCancelled",
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "procedure_template",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
+ "label": "Clinical Procedure Template",
"options": "Clinical Procedure Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "depends_on": "eval:doc.__islocal && doc.patient",
"fieldname": "get_procedure_from_encounter",
"fieldtype": "Button",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Get prescribed procedures",
- "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": "Get Prescribed Clinical Procedures"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "procedure_prescription",
"fieldtype": "Link",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Procedure Prescription",
- "length": 0,
"no_copy": 1,
"options": "Procedure Prescription",
- "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
+ "print_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "service_unit",
"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": "Service Unit",
- "length": 0,
- "no_copy": 0,
"options": "Healthcare Service Unit",
- "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": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.__islocal",
- "fieldname": "check_availability",
- "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": "Check availability",
- "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": "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
+ "fieldtype": "Section Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "practitioner",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
"in_standard_filter": 1,
"label": "Healthcare Practitioner",
- "length": 0,
- "no_copy": 0,
"options": "Healthcare Practitioner",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
"search_index": 1,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "department",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Department",
- "length": 0,
- "no_copy": 0,
"options": "Medical Department",
- "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": 1,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment_date",
"fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Date",
- "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": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment_time",
"fieldtype": "Time",
- "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": "Time",
- "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
+ "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_16",
- "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,
- "depends_on": "",
"fetch_from": "patient.patient_name",
"fieldname": "patient_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Patient Name",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.sex",
"fieldname": "patient_sex",
- "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,
+ "fieldtype": "Link",
"label": "Gender",
- "length": 0,
"no_copy": 1,
- "options": "",
- "permlevel": 0,
- "precision": "",
+ "options": "Gender",
"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
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_21",
- "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": "patient_age",
"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": "Patient Age",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "section_break_1",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment_datetime",
"fieldtype": "Datetime",
- "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": "Date TIme",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
+ "label": "Appointment Datetime",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
+ "read_only": 1,
"report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 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
+ "options": "Mode of Payment"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "paid_amount",
"fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Paid Amount",
- "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": "Paid Amount"
},
{
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0",
"fieldname": "invoiced",
"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": "Invoiced",
- "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": 1,
- "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": "company",
"fieldtype": "Link",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Company",
- "length": 0,
"no_copy": 1,
"options": "Company",
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
"fieldname": "section_break_3",
"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": "More Info",
- "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": "More Info"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "notes",
"fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Notes",
- "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": "Notes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "referring_practitioner",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Referring Practitioner",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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": 1,
- "translatable": 0,
- "unique": 0
+ "options": "Healthcare Practitioner"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0",
"fieldname": "reminded",
"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": "Reminded",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
+ },
+ {
+ "fieldname": "ref_sales_invoice",
+ "fieldtype": "Link",
+ "label": "Reference Sales Invoice",
+ "options": "Sales Invoice",
+ "read_only": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-APP-.YYYY.-",
+ "set_only_once": 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-14 13:24:01.529536",
+ "links": [],
+ "modified": "2020-03-27 11:27:33.773195",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Patient Appointment",
- "name_case": "",
"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": "Healthcare Administrator",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "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": "Physician",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "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": "Nursing User",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Healthcare",
"search_fields": "patient, practitioner, department, appointment_date, appointment_time",
"show_name_in_global_search": 1,
@@ -1179,6 +335,5 @@
"sort_order": "DESC",
"title_field": "patient",
"track_changes": 1,
- "track_seen": 1,
- "track_views": 0
-}
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 5f48c9f..a2d9d02 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -6,26 +6,42 @@
import frappe
from frappe.model.document import Document
import json
-from frappe.utils import getdate, add_days, get_time
+from frappe.utils import getdate, get_time
+from frappe.model.mapper import get_mapped_doc
from frappe import _
import datetime
from frappe.core.doctype.sms_settings.sms_settings import send_sms
from erpnext.hr.doctype.employee.employee import is_holiday
-from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account,get_income_account
-from erpnext.healthcare.utils import validity_exists, service_item_and_practitioner_charge
+from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
+from erpnext.healthcare.utils import check_fee_validity, get_service_item_and_practitioner_charge, manage_fee_validity
class PatientAppointment(Document):
- def on_update(self):
- today = datetime.date.today()
+ def validate(self):
+ self.validate_overlaps()
+ self.set_appointment_datetime()
+ self.validate_customer_created()
+ self.set_status()
+
+ def after_insert(self):
+ self.update_prescription_details()
+ invoice_appointment(self)
+ self.update_fee_validity()
+ send_confirmation_msg(self)
+
+ def set_status(self):
+ today = getdate()
appointment_date = getdate(self.appointment_date)
- # If appointment created for today set as open
- if today == appointment_date:
- frappe.db.set_value("Patient Appointment", self.name, "status", "Open")
- self.reload()
+ # If appointment is created for today set status as Open else Scheduled
+ if appointment_date == today:
+ self.status = 'Open'
+ elif appointment_date > today:
+ self.status = 'Scheduled'
- def validate(self):
- end_time = datetime.datetime.combine(getdate(self.appointment_date), get_time(self.appointment_time)) + datetime.timedelta(minutes=float(self.duration))
+ def validate_overlaps(self):
+ end_time = datetime.datetime.combine(getdate(self.appointment_date), get_time(self.appointment_time)) \
+ + datetime.timedelta(minutes=float(self.duration))
+
overlaps = frappe.db.sql("""
select
name, practitioner, patient, appointment_time, duration
@@ -41,135 +57,153 @@
self.appointment_time, end_time.time(), self.appointment_time, end_time.time(), self.appointment_time))
if overlaps:
- frappe.throw(_("""Appointment overlaps with {0}.<br> {1} has appointment scheduled
- with {2} at {3} having {4} minute(s) duration.""").format(overlaps[0][0], overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4]))
+ overlapping_details = _('Appointment overlaps with ')
+ overlapping_details += "<b><a href='#Form/Patient Appointment/{0}'>{0}</a></b><br>".format(overlaps[0][0])
+ overlapping_details += _('{0} has appointment scheduled with {1} at {2} having {3} minute(s) duration.').format(
+ overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4])
+ frappe.throw(overlapping_details, title=_('Appointments Overlapping'))
- def after_insert(self):
+ def set_appointment_datetime(self):
+ self.appointment_datetime = "%s %s" % (self.appointment_date, self.appointment_time or "00:00:00")
+
+ def validate_customer_created(self):
+ if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
+ if not frappe.db.get_value('Patient', self.patient, 'customer'):
+ msg = _("Please set a Customer linked to the Patient")
+ msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(self.patient)
+ frappe.throw(msg, title=_('Customer Not Found'))
+
+ def update_prescription_details(self):
if self.procedure_prescription:
- frappe.db.set_value("Procedure Prescription", self.procedure_prescription, "appointment_booked", True)
+ frappe.db.set_value('Procedure Prescription', self.procedure_prescription, 'appointment_booked', 1)
if self.procedure_template:
- comments = frappe.db.get_value("Procedure Prescription", self.procedure_prescription, "comments")
+ comments = frappe.db.get_value('Procedure Prescription', self.procedure_prescription, 'comments')
if comments:
- frappe.db.set_value("Patient Appointment", self.name, "notes", comments)
- # Check fee validity exists
- appointment = self
- validity_exist = validity_exists(appointment.practitioner, appointment.patient)
- if validity_exist:
- fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
+ frappe.db.set_value('Patient Appointment', self.name, 'notes', comments)
- # Check if the validity is valid
- appointment_date = getdate(appointment.appointment_date)
- if (fee_validity.valid_till >= appointment_date) and (fee_validity.visited < fee_validity.max_visit):
- visited = fee_validity.visited + 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- if fee_validity.ref_invoice:
- frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", True)
- frappe.msgprint(_("{0} has fee validity till {1}").format(appointment.patient, fee_validity.valid_till))
- confirm_sms(self)
+ def update_fee_validity(self):
+ fee_validity = manage_fee_validity(self)
+ if fee_validity:
+ frappe.msgprint(_('{0} has fee validity till {1}').format(self.patient, fee_validity.valid_till))
- if frappe.db.get_value("Healthcare Settings", None, "manage_appointment_invoice_automatically") == '1' and \
- frappe.db.get_value("Patient Appointment", self.name, "invoiced") != 1:
- invoice_appointment(self)
@frappe.whitelist()
-def invoice_appointment(appointment_doc):
- if not appointment_doc.name:
- return False
- sales_invoice = frappe.new_doc("Sales Invoice")
- sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
- sales_invoice.appointment = appointment_doc.name
- sales_invoice.due_date = getdate()
- sales_invoice.is_pos = True
- sales_invoice.company = appointment_doc.company
- sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
-
- item_line = sales_invoice.append("items")
- service_item, practitioner_charge = service_item_and_practitioner_charge(appointment_doc)
- item_line.item_code = service_item
- item_line.description = "Consulting Charges: " + appointment_doc.practitioner
- item_line.income_account = get_income_account(appointment_doc.practitioner, appointment_doc.company)
- item_line.rate = practitioner_charge
- item_line.amount = practitioner_charge
- item_line.qty = 1
- item_line.reference_dt = "Patient Appointment"
- item_line.reference_dn = appointment_doc.name
-
- payments_line = sales_invoice.append("payments")
- payments_line.mode_of_payment = appointment_doc.mode_of_payment
- payments_line.amount = appointment_doc.paid_amount
-
- sales_invoice.set_missing_values(for_validate = True)
-
- sales_invoice.save(ignore_permissions=True)
- sales_invoice.submit()
- frappe.msgprint(_("Sales Invoice {0} created as paid").format(sales_invoice.name), alert=True)
-
-def appointment_cancel(appointment_id):
- appointment = frappe.get_doc("Patient Appointment", appointment_id)
- # If invoiced --> fee_validity update with -1 visit
- if appointment.invoiced:
- sales_invoice = exists_sales_invoice(appointment)
- if sales_invoice and cancel_sales_invoice(sales_invoice):
- frappe.msgprint(
- _("Appointment {0} and Sales Invoice {1} cancelled").format(appointment.name, sales_invoice.name)
- )
- else:
- validity = validity_exists(appointment.practitioner, appointment.patient)
- if validity:
- fee_validity = frappe.get_doc("Fee Validity", validity[0][0])
- if appointment_valid_in_fee_validity(appointment, fee_validity.valid_till, True, fee_validity.ref_invoice):
- visited = fee_validity.visited - 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- frappe.msgprint(
- _("Appointment cancelled, Please review and cancel the invoice {0}").format(fee_validity.ref_invoice)
- )
- else:
- frappe.msgprint(_("Appointment cancelled"))
- else:
- frappe.msgprint(_("Appointment cancelled"))
- else:
- frappe.msgprint(_("Appointment cancelled"))
-
-def appointment_valid_in_fee_validity(appointment, valid_end_date, invoiced, ref_invoice):
- valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
- max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
- valid_start_date = add_days(getdate(valid_end_date), -int(valid_days))
-
- # Appointments which has same fee validity range with the appointment
- appointments = frappe.get_list("Patient Appointment",{'patient': appointment.patient, 'invoiced': invoiced,
- 'appointment_date':("<=", getdate(valid_end_date)), 'appointment_date':(">=", getdate(valid_start_date)),
- 'practitioner': appointment.practitioner}, order_by="appointment_date desc", limit=int(max_visit))
-
- if appointments and len(appointments) > 0:
- appointment_obj = appointments[len(appointments)-1]
- sales_invoice = exists_sales_invoice(appointment_obj)
- if sales_invoice.name == ref_invoice:
- return True
+def check_payment_fields_reqd(patient):
+ automate_invoicing = frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing')
+ free_follow_ups = frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups')
+ if automate_invoicing:
+ if free_follow_ups:
+ fee_validity = frappe.db.exists('Fee Validity', {'patient': patient, 'status': 'Pending'})
+ if fee_validity:
+ return {'fee_validity': fee_validity}
+ if check_is_new_patient(patient):
+ return False
+ return True
return False
+def invoice_appointment(appointment_doc):
+ automate_invoicing = frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing')
+ appointment_invoiced = frappe.db.get_value('Patient Appointment', appointment_doc.name, 'invoiced')
+ enable_free_follow_ups = frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups')
+ if enable_free_follow_ups:
+ fee_validity = check_fee_validity(appointment_doc)
+ if fee_validity and fee_validity.status == 'Completed':
+ fee_validity = None
+ elif not fee_validity:
+ if frappe.db.exists('Fee Validity Reference', {'appointment': appointment_doc.name}):
+ return
+ if check_is_new_patient(appointment_doc.patient, appointment_doc.name):
+ return
+ else:
+ fee_validity = None
+
+ if automate_invoicing and not appointment_invoiced and not fee_validity:
+ sales_invoice = frappe.new_doc('Sales Invoice')
+ sales_invoice.customer = frappe.get_value('Patient', appointment_doc.patient, 'customer')
+ sales_invoice.appointment = appointment_doc.name
+ sales_invoice.due_date = getdate()
+ sales_invoice.is_pos = 1
+ sales_invoice.company = appointment_doc.company
+ sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
+
+ item = sales_invoice.append('items', {})
+ item = get_appointment_item(appointment_doc, item)
+
+ payment = sales_invoice.append('payments', {})
+ payment.mode_of_payment = appointment_doc.mode_of_payment
+ payment.amount = appointment_doc.paid_amount
+
+ sales_invoice.set_missing_values(for_validate=True)
+ sales_invoice.flags.ignore_mandatory = True
+ sales_invoice.save(ignore_permissions=True)
+ sales_invoice.submit()
+ frappe.msgprint(_('Sales Invoice {0} created as paid'.format(sales_invoice.name)), alert=True)
+ frappe.db.set_value('Patient Appointment', appointment_doc.name, 'invoiced', 1)
+ frappe.db.set_value('Patient Appointment', appointment_doc.name, 'ref_sales_invoice', sales_invoice.name)
+
+
+def check_is_new_patient(patient, name=None):
+ filters = {'patient': patient, 'status': ('!=','Cancelled')}
+ if name:
+ filters['name'] = ('!=', name)
+
+ has_previous_appointment = frappe.db.exists('Patient Appointment', filters)
+ if has_previous_appointment:
+ return False
+ return True
+
+
+def get_appointment_item(appointment_doc, item):
+ service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment_doc)
+ item.item_code = service_item
+ item.description = _('Consulting Charges: {0}').format(appointment_doc.practitioner)
+ item.income_account = get_income_account(appointment_doc.practitioner, appointment_doc.company)
+ item.cost_center = frappe.get_cached_value('Company', appointment_doc.company, 'cost_center')
+ item.rate = practitioner_charge
+ item.amount = practitioner_charge
+ item.qty = 1
+ item.reference_dt = 'Patient Appointment'
+ item.reference_dn = appointment_doc.name
+ return item
+
+
+def cancel_appointment(appointment_id):
+ appointment = frappe.get_doc('Patient Appointment', appointment_id)
+ if appointment.invoiced:
+ sales_invoice = check_sales_invoice_exists(appointment)
+ if sales_invoice and cancel_sales_invoice(sales_invoice):
+ msg = _('Appointment {0} and Sales Invoice {1} cancelled').format(appointment.name, sales_invoice.name)
+ else:
+ msg = _('Appointment Cancelled. Please review and cancel the invoice {0}').format(sales_invoice.name)
+ else:
+ fee_validity = manage_fee_validity(appointment)
+ msg = _('Appointment Cancelled.')
+ if fee_validity:
+ msg += _('Fee Validity {0} updated.').format(fee_validity.name)
+
+ frappe.msgprint(msg)
+
+
def cancel_sales_invoice(sales_invoice):
- if frappe.db.get_value("Healthcare Settings", None, "manage_appointment_invoice_automatically") == '1':
+ if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
if len(sales_invoice.items) == 1:
sales_invoice.cancel()
return True
return False
-def exists_sales_invoice_item(appointment):
- return frappe.db.exists(
- "Sales Invoice Item",
- {
- "reference_dt": "Patient Appointment",
- "reference_dn": appointment.name
- }
- )
-def exists_sales_invoice(appointment):
- sales_item_exist = exists_sales_invoice_item(appointment)
- if sales_item_exist:
- sales_invoice = frappe.get_doc("Sales Invoice", frappe.db.get_value("Sales Invoice Item", sales_item_exist, "parent"))
+def check_sales_invoice_exists(appointment):
+ sales_invoice = frappe.db.get_value('Sales Invoice Item', {
+ 'reference_dt': 'Patient Appointment',
+ 'reference_dn': appointment.name
+ }, 'parent')
+
+ if sales_invoice:
+ sales_invoice = frappe.get_doc('Sales Invoice', sales_invoice)
return sales_invoice
return False
+
@frappe.whitelist()
def get_availability_data(date, practitioner):
"""
@@ -180,169 +214,163 @@
"""
date = getdate(date)
- weekday = date.strftime("%A")
+ weekday = date.strftime('%A')
- available_slots = []
- slot_details = []
- practitioner_schedule = None
+ practitioner_doc = frappe.get_doc('Healthcare Practitioner', practitioner)
+ check_employee_wise_availability(date, practitioner_doc)
+
+ if practitioner_doc.practitioner_schedules:
+ slot_details = get_available_slots(practitioner_doc, date)
+ else:
+ frappe.throw(_('{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master').format(
+ practitioner), title=_('Practitioner Schedule Not Found'))
+
+
+ if not slot_details:
+ # TODO: return available slots in nearby dates
+ frappe.throw(_('Healthcare Practitioner not available on {0}').format(weekday), title=_('Not Available'))
+
+ return {'slot_details': slot_details}
+
+
+def check_employee_wise_availability(date, practitioner_doc):
employee = None
-
- practitioner_obj = frappe.get_doc("Healthcare Practitioner", practitioner)
-
- # Get practitioner employee relation
- if practitioner_obj.employee:
- employee = practitioner_obj.employee
- elif practitioner_obj.user_id:
- if frappe.db.exists({
- "doctype": "Employee",
- "user_id": practitioner_obj.user_id
- }):
- employee = frappe.get_doc("Employee", {"user_id": practitioner_obj.user_id}).name
+ if practitioner_doc.employee:
+ employee = practitioner_doc.employee
+ elif practitioner_doc.user_id:
+ employee = frappe.db.get_value('Employee', {'user_id': practitioner_doc.user_id}, 'name')
if employee:
- # Check if it is Holiday
+ # check holiday
if is_holiday(employee, date):
- frappe.throw(_("{0} is a company holiday").format(date))
+ frappe.throw(_('{0} is a holiday'.format(date)), title=_('Not Available'))
- # Check if He/She on Leave
+ # check leave status
leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
where employee = %s and %s between from_date and to_date
and docstatus = 1""", (employee, date), as_dict=True)
if leave_record:
if leave_record[0].half_day:
- frappe.throw(_("{0} on Half day Leave on {1}").format(practitioner, date))
+ frappe.throw(_('{0} is on a Half day Leave on {1}').format(practitioner_doc.name, date), title=_('Not Available'))
else:
- frappe.throw(_("{0} on Leave on {1}").format(practitioner, date))
+ frappe.throw(_('{0} is on Leave on {1}').format(practitioner_doc.name, date), title=_('Not Available'))
- # get practitioners schedule
- if practitioner_obj.practitioner_schedules:
- for schedule in practitioner_obj.practitioner_schedules:
- if schedule.schedule:
- practitioner_schedule = frappe.get_doc("Practitioner Schedule", schedule.schedule)
- else:
- frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master").format(practitioner))
- if practitioner_schedule:
- available_slots = []
- for t in practitioner_schedule.time_slots:
- if weekday == t.day:
- available_slots.append(t)
+def get_available_slots(practitioner_doc, date):
+ available_slots = []
+ slot_details = []
+ weekday = date.strftime('%A')
+ practitioner = practitioner_doc.name
- if available_slots:
- appointments = []
+ for schedule_entry in practitioner_doc.practitioner_schedules:
+ if schedule_entry.schedule:
+ practitioner_schedule = frappe.get_doc('Practitioner Schedule', schedule_entry.schedule)
+ else:
+ frappe.throw(_('{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner').format(
+ frappe.bold(practitioner)), title=_('Practitioner Schedule Not Found'))
- if schedule.service_unit:
- slot_name = schedule.schedule+" - "+schedule.service_unit
- allow_overlap = frappe.get_value('Healthcare Service Unit', schedule.service_unit, 'overlap_appointments')
- if allow_overlap:
- # fetch all appointments to practitioner by service unit
- appointments = frappe.get_all(
- "Patient Appointment",
- filters={"practitioner": practitioner, "service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
- fields=["name", "appointment_time", "duration", "status"])
- else:
- # fetch all appointments to service unit
- appointments = frappe.get_all(
- "Patient Appointment",
- filters={"service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
- fields=["name", "appointment_time", "duration", "status"])
- else:
- slot_name = schedule.schedule
- # fetch all appointments to practitioner without service unit
- appointments = frappe.get_all(
- "Patient Appointment",
- filters={"practitioner": practitioner, "service_unit": '', "appointment_date": date, "status": ["not in",["Cancelled"]]},
- fields=["name", "appointment_time", "duration", "status"])
+ if practitioner_schedule:
+ available_slots = []
+ for time_slot in practitioner_schedule.time_slots:
+ if weekday == time_slot.day:
+ available_slots.append(time_slot)
- slot_details.append({"slot_name":slot_name, "service_unit":schedule.service_unit,
- "avail_slot":available_slots, 'appointments': appointments})
+ if available_slots:
+ appointments = []
+ # fetch all appointments to practitioner by service unit
+ filters = {
+ 'practitioner': practitioner,
+ 'service_unit': schedule_entry.service_unit,
+ 'appointment_date': date,
+ 'status': ['not in',['Cancelled']]
+ }
- else:
- frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master").format(practitioner))
+ if schedule_entry.service_unit:
+ slot_name = schedule_entry.schedule + ' - ' + schedule_entry.service_unit
+ allow_overlap = frappe.get_value('Healthcare Service Unit', schedule_entry.service_unit, 'overlap_appointments')
+ if not allow_overlap:
+ # fetch all appointments to service unit
+ filters.pop('practitioner')
+ else:
+ slot_name = schedule_entry.schedule
+ # fetch all appointments to practitioner without service unit
+ filters['practitioner'] = practitioner
+ filters.pop('service_unit')
- if not available_slots and not slot_details:
- # TODO: return available slots in nearby dates
- frappe.throw(_("Healthcare Practitioner not available on {0}").format(weekday))
+ appointments = frappe.get_all(
+ 'Patient Appointment',
+ filters=filters,
+ fields=['name', 'appointment_time', 'duration', 'status'])
- return {
- "slot_details": slot_details
- }
+ slot_details.append({'slot_name':slot_name, 'service_unit':schedule_entry.service_unit,
+ 'avail_slot':available_slots, 'appointments': appointments})
+
+ return slot_details
@frappe.whitelist()
def update_status(appointment_id, status):
- frappe.db.set_value("Patient Appointment", appointment_id, "status", status)
+ frappe.db.set_value('Patient Appointment', appointment_id, 'status', status)
appointment_booked = True
- if status == "Cancelled":
+ if status == 'Cancelled':
appointment_booked = False
- appointment_cancel(appointment_id)
+ cancel_appointment(appointment_id)
- procedure_prescription = frappe.db.get_value("Patient Appointment", appointment_id, "procedure_prescription")
+ procedure_prescription = frappe.db.get_value('Patient Appointment', appointment_id, 'procedure_prescription')
if procedure_prescription:
- frappe.db.set_value("Procedure Prescription", procedure_prescription, "appointment_booked", appointment_booked)
+ frappe.db.set_value('Procedure Prescription', procedure_prescription, 'appointment_booked', appointment_booked)
-@frappe.whitelist()
-def set_open_appointments():
- today = getdate()
- frappe.db.sql(
- "update `tabPatient Appointment` set status='Open' where status = 'Scheduled'"
- " and appointment_date = %s", today)
-
-
-@frappe.whitelist()
-def set_pending_appointments():
- today = getdate()
- frappe.db.sql(
- "update `tabPatient Appointment` set status='Pending' where status in "
- "('Scheduled','Open') and appointment_date < %s", today)
-
-
-def confirm_sms(doc):
- if frappe.db.get_value("Healthcare Settings", None, "app_con") == '1':
- message = frappe.db.get_value("Healthcare Settings", None, "app_con_msg")
+def send_confirmation_msg(doc):
+ if frappe.db.get_single_value('Healthcare Settings', 'send_appointment_confirmation'):
+ message = frappe.db.get_single_value('Healthcare Settings', 'appointment_confirmation_msg')
send_message(doc, message)
+
@frappe.whitelist()
-def create_encounter(appointment):
- appointment = frappe.get_doc("Patient Appointment", appointment)
- encounter = frappe.new_doc("Patient Encounter")
- encounter.appointment = appointment.name
- encounter.patient = appointment.patient
- encounter.practitioner = appointment.practitioner
- encounter.visit_department = appointment.department
- encounter.patient_sex = appointment.patient_sex
- encounter.encounter_date = appointment.appointment_date
- if appointment.invoiced:
- encounter.invoiced = True
- return encounter.as_dict()
+def make_encounter(source_name, target_doc=None):
+ doc = get_mapped_doc('Patient Appointment', source_name, {
+ 'Patient Appointment': {
+ 'doctype': 'Patient Encounter',
+ 'field_map': [
+ ['appointment', 'name'],
+ ['patient', 'patient'],
+ ['practitioner', 'practitioner'],
+ ['medical_department', 'department'],
+ ['patient_sex', 'patient_sex'],
+ ['encounter_date', 'appointment_date'],
+ ['invoiced', 'invoiced']
+ ]
+ }
+ }, target_doc)
+ return doc
-def remind_appointment():
- if frappe.db.get_value("Healthcare Settings", None, "app_rem") == '1':
- rem_before = datetime.datetime.strptime(frappe.get_value("Healthcare Settings", None, "rem_before"), "%H:%M:%S")
- rem_dt = datetime.datetime.now() + datetime.timedelta(
- hours=rem_before.hour, minutes=rem_before.minute, seconds=rem_before.second)
+def send_appointment_reminder():
+ if frappe.db.get_single_value('Healthcare Settings', 'send_appointment_reminder'):
+ remind_before = datetime.datetime.strptime(frappe.db.get_single_value('Healthcare Settings', 'remind_before'), '%H:%M:%S')
+ reminder_dt = datetime.datetime.now() + datetime.timedelta(
+ hours=remind_before.hour, minutes=remind_before.minute, seconds=remind_before.second)
- appointment_list = frappe.db.sql(
- "select name from `tabPatient Appointment` where start_dt between %s and %s and reminded = 0 ",
- (datetime.datetime.now(), rem_dt)
- )
+ appointment_list = frappe.db.get_all('Patient Appointment', {
+ 'appointment_datetime': ['between', (datetime.datetime.now(), reminder_dt)],
+ 'reminded': 0,
+ 'status': ['!=', 'Cancelled']
+ })
- for i in range(0, len(appointment_list)):
- doc = frappe.get_doc("Patient Appointment", appointment_list[i][0])
- message = frappe.db.get_value("Healthcare Settings", None, "app_rem_msg")
+ for appointment in appointment_list:
+ doc = frappe.get_doc('Patient Appointment', appointment.name)
+ message = frappe.db.get_single_value('Healthcare Settings', 'appointment_reminder_msg')
send_message(doc, message)
- frappe.db.set_value("Patient Appointment", doc.name, "reminded",1)
-
+ frappe.db.set_value('Patient Appointment', doc.name, 'reminded', 1)
def send_message(doc, message):
- patient = frappe.get_doc("Patient", doc.patient)
+ patient = frappe.get_doc('Patient', doc.patient)
if patient.mobile:
- context = {"doc": doc, "alert": doc, "comments": None}
- if doc.get("_comments"):
- context["comments"] = json.loads(doc.get("_comments"))
+ context = {'doc': doc, 'alert': doc, 'comments': None}
+ if doc.get('_comments'):
+ context['comments'] = json.loads(doc.get('_comments'))
# jinja to string convertion happens here
message = frappe.render_template(message, context)
@@ -359,7 +387,7 @@
:param filters: Filters (JSON).
"""
from frappe.desk.calendar import get_event_conditions
- conditions = get_event_conditions("Patient Appointment", filters)
+ conditions = get_event_conditions('Patient Appointment', filters)
data = frappe.db.sql("""
select
@@ -381,10 +409,21 @@
return data
+
@frappe.whitelist()
def get_procedure_prescribed(patient):
return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
ct.encounter_date, pp.practitioner, pp.date, pp.department
from `tabPatient Encounter` ct, `tabProcedure Prescription` pp
where ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
- order by ct.creation desc""", {"patient": patient})
+ order by ct.creation desc""", {'patient': patient})
+
+
+def update_appointment_status():
+ # update the status of appointments daily
+ appointments = frappe.get_all('Patient Appointment', {
+ 'status': ('not in', ['Closed', 'Cancelled'])
+ }, as_dict=1)
+
+ for appointment in appointments:
+ frappe.get_doc('Patient Appointment', appointment.name).set_status()
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js
index 701cb69..721887b 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js
@@ -3,4 +3,14 @@
*/
frappe.listview_settings['Patient Appointment'] = {
filters: [["status", "=", "Open"]],
+ get_indicator: function(doc) {
+ var colors = {
+ "Open": "orange",
+ "Scheduled": "yellow",
+ "Closed": "green",
+ "Cancelled": "red",
+ "Expired": "grey"
+ };
+ return [__(doc.status), colors[doc.status], "status,=," + doc.status];
+ }
};
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 3536a5f..7075af5 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -3,8 +3,144 @@
# See license.txt
from __future__ import unicode_literals
import unittest
-
-# test_records = frappe.get_test_records('Patient Appointment')
+import frappe
+from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status
+from frappe.utils import nowdate, add_days
+from frappe.utils.make_random import get_random
class TestPatientAppointment(unittest.TestCase):
- pass
+ def setUp(self):
+ frappe.db.sql("""delete from `tabPatient Appointment`""")
+ frappe.db.sql("""delete from `tabFee Validity""")
+
+ def test_status(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 0)
+ appointment = create_appointment(patient, practitioner, nowdate())
+ self.assertEquals(appointment.status, 'Open')
+ appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2))
+ self.assertEquals(appointment.status, 'Scheduled')
+ create_encounter(appointment)
+ self.assertEquals(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
+
+ def test_invoicing(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 0)
+ appointment = create_appointment(patient, practitioner, nowdate())
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'invoiced'), 0)
+
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+ appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2), invoice=1)
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'invoiced'), 1)
+ self.assertTrue(frappe.db.get_value('Patient Appointment', appointment.name, 'ref_sales_invoice'))
+
+ def test_appointment_cancel(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 1)
+ appointment = create_appointment(patient, practitioner, nowdate())
+ fee_validity = frappe.db.get_value('Fee Validity Reference', {'appointment': appointment.name}, 'parent')
+ # fee validity created
+ self.assertTrue(fee_validity)
+
+ visited = frappe.db.get_value('Fee Validity', fee_validity, 'visited')
+ update_status(appointment.name, 'Cancelled')
+ # check fee validity updated
+ self.assertEqual(frappe.db.get_value('Fee Validity', fee_validity, 'visited'), visited - 1)
+
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+ appointment = create_appointment(patient, practitioner, nowdate(), invoice=1)
+ update_status(appointment.name, 'Cancelled')
+ # check invoice cancelled
+ sales_invoice = frappe.db.get_value('Patient Appointment', appointment.name, 'ref_sales_invoice')
+ self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice, 'status'), 'Cancelled')
+
+
+def create_healthcare_docs():
+ patient = create_patient()
+ practitioner = frappe.db.exists('Healthcare Practitioner', '_Test Healthcare Practitioner')
+ medical_department = frappe.db.exists('Medical Department', '_Test Medical Department')
+
+ if not medical_department:
+ medical_department = frappe.new_doc('Medical Department')
+ medical_department.department = '_Test Medical Department'
+ medical_department.save(ignore_permissions=True)
+ medical_department = medical_department.name
+
+ if not practitioner:
+ practitioner = frappe.new_doc('Healthcare Practitioner')
+ practitioner.first_name = '_Test Healthcare Practitioner'
+ practitioner.gender = 'Female'
+ practitioner.department = medical_department
+ practitioner.op_consulting_charge = 500
+ practitioner.inpatient_visit_charge = 500
+ practitioner.save(ignore_permissions=True)
+ practitioner = practitioner.name
+
+ return patient, medical_department, practitioner
+
+def create_patient():
+ patient = frappe.db.exists('Patient', '_Test Patient')
+ if not patient:
+ patient = frappe.new_doc('Patient')
+ patient.first_name = '_Test Patient'
+ patient.sex = 'Female'
+ patient.save(ignore_permissions=True)
+ patient = patient.name
+ return patient
+
+def create_encounter(appointment=None):
+ encounter = frappe.new_doc('Patient Encounter')
+ if appointment:
+ encounter.appointment = appointment.name
+ encounter.patient = appointment.patient
+ encounter.practitioner = appointment.practitioner
+ encounter.encounter_date = appointment.appointment_date
+ encounter.encounter_time = appointment.appointment_time
+ encounter.save()
+ encounter.submit()
+ return encounter
+
+def create_appointment(patient, practitioner, appointment_date, invoice=0, procedure_template=0):
+ item = create_healthcare_service_items()
+ frappe.db.set_value('Healthcare Settings', None, 'inpatient_visit_charge_item', item)
+ frappe.db.set_value('Healthcare Settings', None, 'op_consulting_charge_item', item)
+ appointment = frappe.new_doc('Patient Appointment')
+ appointment.patient = patient
+ appointment.practitioner = practitioner
+ appointment.department = '_Test Medical Department'
+ appointment.appointment_date = appointment_date
+ appointment.company = '_Test Company'
+ appointment.duration = 15
+ if invoice:
+ appointment.mode_of_payment = 'Cash'
+ appointment.paid_amount = 500
+ if procedure_template:
+ appointment.procedure_template = create_clinical_procedure_template().get('name')
+ appointment.save(ignore_permissions=True)
+ return appointment
+
+def create_healthcare_service_items():
+ if frappe.db.exists('Item', 'HLC-SI-001'):
+ return 'HLC-SI-001'
+ item = frappe.new_doc('Item')
+ item.item_code = 'HLC-SI-001'
+ item.item_name = 'Consulting Charges'
+ item.item_group = 'Services'
+ item.is_stock_item = 0
+ item.save()
+ return item.name
+
+def create_clinical_procedure_template():
+ if frappe.db.exists('Clinical Procedure Template', 'Knee Surgery and Rehab'):
+ return frappe.get_doc('Clinical Procedure Template', 'Knee Surgery and Rehab')
+ template = frappe.new_doc('Clinical Procedure Template')
+ template.template = 'Knee Surgery and Rehab'
+ template.item_code = 'Knee Surgery and Rehab'
+ template.item_group = 'Services'
+ template.is_billable = 1
+ template.description = 'Knee Surgery and Rehab'
+ template.rate = 50000
+ template.save()
+ return template
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
index 088bc81..83c5d2b 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
@@ -19,297 +19,237 @@
refresh: function(frm) {
refresh_field('drug_prescription');
refresh_field('lab_test_prescription');
- if (!frm.doc.__islocal){
- frappe.call({
- method: 'frappe.client.get_value',
- args: {
- doctype: 'Patient',
- fieldname: 'inpatient_status',
- filters: {name: frm.doc.patient}
- },
- callback: function(data) {
- if(data.message && data.message.inpatient_status == "Admission Scheduled" || data.message.inpatient_status == "Admitted"){
- frm.add_custom_button(__('Schedule Discharge'), function() {
- schedule_discharge(frm);
- });
- }
- else if(data.message.inpatient_status != "Discharge Scheduled"){
- frm.add_custom_button(__('Schedule Admission'), function() {
- schedule_inpatient(frm);
- });
- }
- }
- });
- }
- frm.add_custom_button(__('Patient History'), function() {
- if (frm.doc.patient) {
- frappe.route_options = {"patient": frm.doc.patient};
- frappe.set_route("patient_history");
- } else {
- frappe.msgprint(__("Please select Patient"));
+
+ if (!frm.doc.__islocal) {
+
+ if (frm.doc.inpatient_status == 'Admission Scheduled' || frm.doc.inpatient_status == 'Admitted') {
+ frm.add_custom_button(__('Schedule Discharge'), function() {
+ schedule_discharge(frm);
+ });
+ } else if (frm.doc.inpatient_status != 'Discharge Scheduled') {
+ frm.add_custom_button(__('Schedule Admission'), function() {
+ schedule_inpatient(frm);
+ });
}
- },"View");
- frm.add_custom_button(__('Vital Signs'), function() {
- btn_create_vital_signs(frm);
- },"Create");
- frm.add_custom_button(__('Medical Record'), function() {
- create_medical_record(frm);
- },"Create");
- frm.add_custom_button(__("Procedure"),function(){
- btn_create_procedure(frm);
- },"Create");
+ frm.add_custom_button(__('Patient History'), function() {
+ if (frm.doc.patient) {
+ frappe.route_options = {'patient': frm.doc.patient};
+ frappe.set_route('patient_history');
+ } else {
+ frappe.msgprint(__('Please select Patient'));
+ }
+ },'View');
- frm.set_query("patient", function () {
+ frm.add_custom_button(__('Vital Signs'), function() {
+ create_vital_signs(frm);
+ },'Create');
+
+ frm.add_custom_button(__('Medical Record'), function() {
+ create_medical_record(frm);
+ },'Create');
+
+ frm.add_custom_button(__('Clinical Procedure'), function() {
+ create_procedure(frm);
+ },'Create');
+
+ }
+
+ frm.set_query('patient', function() {
return {
- filters: {"disabled": 0}
+ filters: {'status': 'Active'}
};
});
- frm.set_query("drug_code", "drug_prescription", function() {
+
+ frm.set_query('drug_code', 'drug_prescription', function() {
return {
filters: {
- is_stock_item:'1'
+ is_stock_item: 1
}
};
});
- frm.set_query("lab_test_code", "lab_test_prescription", function() {
+
+ frm.set_query('lab_test_code', 'lab_test_prescription', function() {
return {
filters: {
- is_billable:'1'
+ is_billable: 1
}
};
});
- frm.set_query("medical_code", "codification_table", function() {
- return {
- filters: {
- medical_code_standard: frappe.defaults.get_default("default_medical_code_standard")
- }
- };
- });
- frm.set_query("appointment", function() {
+
+ frm.set_query('appointment', function() {
return {
filters: {
// Scheduled filter for demo ...
- status:['in',["Open","Scheduled"]]
+ status:['in',['Open','Scheduled']]
}
};
});
- frm.set_df_property("appointment", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("patient", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("patient_age", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("patient_sex", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("type", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("practitioner", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("visit_department", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("encounter_date", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("encounter_time", "read_only", frm.doc.__islocal ? 0:1);
- }
-});
-var schedule_inpatient = function(frm) {
- frappe.call({
- method: "erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_inpatient",
- args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
- callback: function(data) {
- if(!data.exc){
- frm.reload_doc();
- }
- },
- freeze: true,
- freeze_message: "Process Inpatient Scheduling"
- });
-};
+ frm.set_df_property('patient', 'read_only', frm.doc.appointment ? 1 : 0);
+ },
-var schedule_discharge = function(frm) {
- frappe.call({
- method: "erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_discharge",
- args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
- callback: function(data) {
- if(!data.exc){
- frm.reload_doc();
- }
- },
- freeze: true,
- freeze_message: "Process Discharge"
- });
-};
+ appointment: function(frm) {
+ frm.events.set_appointment_fields(frm);
+ },
-var create_medical_record = function (frm) {
- if(!frm.doc.patient){
- frappe.throw(__("Please select patient"));
- }
- frappe.route_options = {
- "patient": frm.doc.patient,
- "status": "Open",
- "reference_doctype": "Patient Medical Record",
- "reference_owner": frm.doc.owner
- };
- frappe.new_doc("Patient Medical Record");
-};
+ patient: function(frm) {
+ frm.events.set_patient_info(frm);
+ },
-var btn_create_vital_signs = function (frm) {
- if(!frm.doc.patient){
- frappe.throw(__("Please select patient"));
- }
- frappe.route_options = {
- "patient": frm.doc.patient,
- "appointment": frm.doc.appointment
- };
- frappe.new_doc("Vital Signs");
-};
-
-var btn_create_procedure = function (frm) {
- if(!frm.doc.patient){
- frappe.throw(__("Please select patient"));
- }
- frappe.route_options = {
- "patient": frm.doc.patient,
- "medical_department": frm.doc.visit_department
- };
- frappe.new_doc("Clinical Procedure");
-};
-
-frappe.ui.form.on("Patient Encounter", "appointment", function(frm){
- if(frm.doc.appointment){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Patient Appointment",
- name: frm.doc.appointment
- },
- callback: function (data) {
- frappe.model.set_value(frm.doctype,frm.docname, "patient", data.message.patient);
- frappe.model.set_value(frm.doctype,frm.docname, "type", data.message.appointment_type);
- frappe.model.set_value(frm.doctype,frm.docname, "practitioner", data.message.practitioner);
- frappe.model.set_value(frm.doctype,frm.docname, "invoiced", data.message.invoiced);
- }
- });
- }
- else{
- frappe.model.set_value(frm.doctype,frm.docname, "patient", "");
- frappe.model.set_value(frm.doctype,frm.docname, "type", "");
- frappe.model.set_value(frm.doctype,frm.docname, "practitioner", "");
- frappe.model.set_value(frm.doctype,frm.docname, "invoiced", 0);
- }
-});
-
-frappe.ui.form.on("Patient Encounter", "practitioner", function(frm) {
- if(frm.doc.practitioner){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Healthcare Practitioner",
- name: frm.doc.practitioner
- },
- callback: function (data) {
- frappe.model.set_value(frm.doctype,frm.docname, "visit_department",data.message.department);
- }
- });
- }
-});
-
-frappe.ui.form.on("Patient Encounter", "symptoms_select", function(frm) {
- if(frm.doc.symptoms_select){
- var symptoms = null;
- if(frm.doc.symptoms)
- symptoms = frm.doc.symptoms + "\n" +frm.doc.symptoms_select;
- else
- symptoms = frm.doc.symptoms_select;
- frappe.model.set_value(frm.doctype,frm.docname, "symptoms", symptoms);
- frappe.model.set_value(frm.doctype,frm.docname, "symptoms_select", null);
- }
-});
-frappe.ui.form.on("Patient Encounter", "diagnosis_select", function(frm) {
- if(frm.doc.diagnosis_select){
- var diagnosis = null;
- if(frm.doc.diagnosis)
- diagnosis = frm.doc.diagnosis + "\n" +frm.doc.diagnosis_select;
- else
- diagnosis = frm.doc.diagnosis_select;
- frappe.model.set_value(frm.doctype,frm.docname, "diagnosis", diagnosis);
- frappe.model.set_value(frm.doctype,frm.docname, "diagnosis_select", null);
- }
-});
-
-frappe.ui.form.on("Patient Encounter", "patient", function(frm) {
- if(frm.doc.patient){
- frappe.call({
- "method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
- args: {
- patient: frm.doc.patient
- },
- callback: function (data) {
- var age = "";
- if(data.message.dob){
- age = calculate_age(data.message.dob);
- }
- frappe.model.set_value(frm.doctype,frm.docname, "patient_age", age);
- frappe.model.set_value(frm.doctype,frm.docname, "patient_sex", data.message.sex);
- }
- });
- }
-});
-
-frappe.ui.form.on("Drug Prescription", {
- drug_code: function(frm, cdt, cdn) {
- var child = locals[cdt][cdn];
- if(child.drug_code){
+ set_appointment_fields: function(frm) {
+ if (frm.doc.appointment) {
frappe.call({
- "method": "frappe.client.get",
+ method: 'frappe.client.get',
args: {
- doctype: "Item",
- name: child.drug_code,
+ doctype: 'Patient Appointment',
+ name: frm.doc.appointment
},
- callback: function (data) {
- frappe.model.set_value(cdt, cdn, 'drug_name',data.message.item_name);
+ callback: function(data) {
+ let values = {
+ 'patient':data.message.patient,
+ 'type': data.message.appointment_type,
+ 'practitioner': data.message.practitioner,
+ 'invoiced': data.message.invoiced
+ };
+ frm.set_value(values);
}
});
}
+ else {
+ let values = {
+ 'patient': '',
+ 'patient_name': '',
+ 'type': '',
+ 'practitioner': '',
+ 'invoiced': 0,
+ 'patient_sex': '',
+ 'patient_age': '',
+ 'inpatient_record': '',
+ 'inpatient_status': ''
+ };
+ frm.set_value(values);
+ }
},
+
+ set_patient_info: function(frm) {
+ if (frm.doc.patient) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
+ args: {
+ patient: frm.doc.patient
+ },
+ callback: function(data) {
+ let age = '';
+ if (data.message.dob) {
+ age = calculate_age(data.message.dob);
+ }
+ frappe.model.set_value(frm.doctype, frm.docname, 'patient_age', age);
+ frappe.model.set_value(frm.doctype, frm.docname, 'patient_sex', data.message.sex);
+ if (data.message.inpatient_record) {
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_record', data.message.inpatient_record);
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_status', data.message.inpatient_status);
+ }
+ }
+ });
+ } else {
+ frappe.model.set_value(frm.doctype, frm.docname, 'patient_sex', '');
+ frappe.model.set_value(frm.doctype, frm.docname, 'patient_age', '');
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_record', '');
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_status', '');
+ }
+ }
+});
+
+let schedule_inpatient = function(frm) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_inpatient',
+ args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
+ callback: function(data) {
+ if (!data.exc) {
+ frm.reload_doc();
+ }
+ },
+ freeze: true,
+ freeze_message: __('Process Inpatient Scheduling')
+ });
+};
+
+let schedule_discharge = function(frm) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_discharge',
+ args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
+ callback: function(data) {
+ if (!data.exc) {
+ frm.reload_doc();
+ }
+ },
+ freeze: true,
+ freeze_message: 'Process Discharge'
+ });
+};
+
+let create_medical_record = function (frm) {
+ if (!frm.doc.patient) {
+ frappe.throw(__('Please select patient'));
+ }
+ frappe.route_options = {
+ 'patient': frm.doc.patient,
+ 'status': 'Open',
+ 'reference_doctype': 'Patient Medical Record',
+ 'reference_owner': frm.doc.owner
+ };
+ frappe.new_doc('Patient Medical Record');
+};
+
+let create_vital_signs = function (frm) {
+ if (!frm.doc.patient) {
+ frappe.throw(__('Please select patient'));
+ }
+ frappe.route_options = {
+ 'patient': frm.doc.patient,
+ 'appointment': frm.doc.appointment,
+ 'encounter': frm.doc.name
+ };
+ frappe.new_doc('Vital Signs');
+};
+
+let create_procedure = function (frm) {
+ if (!frm.doc.patient) {
+ frappe.throw(__('Please select patient'));
+ }
+ frappe.route_options = {
+ 'patient': frm.doc.patient,
+ 'medical_department': frm.doc.medical_department
+ };
+ frappe.new_doc('Clinical Procedure');
+};
+
+frappe.ui.form.on('Drug Prescription', {
dosage: function(frm, cdt, cdn){
frappe.model.set_value(cdt, cdn, 'update_schedule', 1);
- var child = locals[cdt][cdn];
- if(child.dosage){
- frappe.model.set_value(cdt, cdn, 'in_every', 'Day');
+ let child = locals[cdt][cdn];
+ if (child.dosage) {
+ frappe.model.set_value(cdt, cdn, 'interval_uom', 'Day');
frappe.model.set_value(cdt, cdn, 'interval', 1);
}
},
- period: function(frm, cdt, cdn){
+ period: function(frm, cdt, cdn) {
frappe.model.set_value(cdt, cdn, 'update_schedule', 1);
},
- in_every: function(frm, cdt, cdn){
+ interval_uom: function(frm, cdt, cdn) {
frappe.model.set_value(cdt, cdn, 'update_schedule', 1);
- var child = locals[cdt][cdn];
- if(child.in_every == "Hour"){
+ let child = locals[cdt][cdn];
+ if (child.interval_uom == 'Hour') {
frappe.model.set_value(cdt, cdn, 'dosage', null);
}
}
});
-frappe.ui.form.on("Procedure Prescription", {
- procedure: function(frm, cdt, cdn) {
- var child = locals[cdt][cdn];
- if(child.procedure){
- frappe.call({
- "method": "frappe.client.get_value",
- args: {
- doctype: "Clinical Procedure Template",
- fieldname: "medical_department",
- filters: {name: child.procedure}
- },
- callback: function (data) {
- frappe.model.set_value(cdt, cdn, 'department',data.message.medical_department);
- }
- });
- }
- }
-});
-
-
-var calculate_age = function(birth) {
- var ageMS = Date.parse(Date()) - Date.parse(birth);
- var age = new Date();
+let calculate_age = function(birth) {
+ let ageMS = Date.parse(Date()) - Date.parse(birth);
+ let age = new Date();
age.setTime(ageMS);
- var years = age.getFullYear() - 1970;
- return years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)";
+ let years = age.getFullYear() - 1970;
+ return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
};
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
index 91c9d7b..d00e7bc 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
@@ -1,1183 +1,324 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2016-04-21 10:53:44.637684",
- "custom": 0,
- "default_print_format": "",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2016-04-21 10:53:44.637684",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "appointment",
+ "appointment_type",
+ "patient",
+ "patient_name",
+ "patient_sex",
+ "patient_age",
+ "company",
+ "column_break_6",
+ "practitioner",
+ "medical_department",
+ "encounter_date",
+ "encounter_time",
+ "invoiced",
+ "section_break_1",
+ "inpatient_record",
+ "column_break_17",
+ "inpatient_status",
+ "sb_symptoms",
+ "symptoms",
+ "symptoms_in_print",
+ "physical_examination",
+ "diagnosis",
+ "diagnosis_in_print",
+ "codification",
+ "codification_table",
+ "sb_drug_prescription",
+ "drug_prescription",
+ "sb_test_prescription",
+ "lab_test_prescription",
+ "sb_procedures",
+ "procedure_prescription",
+ "encounter_comment",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.inpatient_record",
- "fieldname": "inpatient_record",
- "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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
- "options": "Inpatient Record",
- "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": "inpatient_record",
+ "fieldtype": "Link",
+ "label": "Inpatient Record",
+ "options": "Inpatient Record",
+ "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_1",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "section_break_1",
+ "fieldtype": "Section Break",
+ "label": "Inpatient Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "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": 0,
- "label": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "HLC-ENC-.YYYY.-",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "HLC-ENC-.YYYY.-",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "appointment",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Appointment",
- "length": 0,
- "no_copy": 0,
- "options": "Patient Appointment",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "appointment",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Appointment",
+ "options": "Patient Appointment",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "type",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Type",
- "length": 0,
- "no_copy": 1,
- "options": "Appointment Type",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "inpatient_record.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "inpatient_record.patient",
- "fieldname": "patient",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "patient.patient_name",
+ "fieldname": "patient_name",
+ "fieldtype": "Data",
+ "label": "Patient Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_from": "patient.patient_name",
- "fieldname": "patient_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Patient Name",
- "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": "patient_age",
+ "fieldtype": "Data",
+ "label": "Age",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient_age",
- "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": "Age",
- "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": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient_sex",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient_sex",
- "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": "Gender",
- "length": 0,
- "no_copy": 0,
- "options": "\nMale\nFemale\nOther",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "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": "company",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Company",
+ "options": "Company"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_6",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_6",
- "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": "practitioner",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "practitioner",
- "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": "Healthcare Practitioner",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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": "Today",
+ "fieldname": "encounter_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Encounter Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "visit_department",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Medical Department",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "encounter_time",
+ "fieldtype": "Time",
+ "label": "Encounter Time",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fieldname": "encounter_date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Encounter 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
- },
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "no_copy": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "encounter_time",
- "fieldtype": "Time",
- "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": "Encounter Time",
- "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": "sb_symptoms",
+ "fieldtype": "Section Break",
+ "label": "Encounter Impression"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "invoiced",
- "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": "Invoiced",
- "length": 0,
- "no_copy": 1,
- "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
- },
+ "fieldname": "symptoms",
+ "fieldtype": "Table MultiSelect",
+ "ignore_xss_filter": 1,
+ "label": "Symptoms",
+ "no_copy": 1,
+ "options": "Patient Encounter Symptom"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "sb_symptoms",
- "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": "Encounter Impression",
- "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",
+ "depends_on": "eval: doc.symptoms != ''",
+ "fieldname": "symptoms_in_print",
+ "fieldtype": "Check",
+ "label": "In print",
+ "no_copy": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "symptoms_select",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Complaints",
- "length": 0,
- "no_copy": 1,
- "options": "Complaint",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "physical_examination",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "symptoms",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "",
- "length": 0,
- "no_copy": 1,
- "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": "diagnosis",
+ "fieldtype": "Table MultiSelect",
+ "ignore_xss_filter": 1,
+ "label": "Diagnosis",
+ "no_copy": 1,
+ "options": "Patient Encounter Diagnosis"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "symptoms_in_print",
- "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": "In print",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "1",
+ "depends_on": "eval: doc.diagnosis != ''",
+ "fieldname": "diagnosis_in_print",
+ "fieldtype": "Check",
+ "label": "In print",
+ "no_copy": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "physical_examination",
- "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,
- "label": "",
- "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": "codification",
+ "fieldtype": "Section Break",
+ "label": "Medical Coding"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "diagnosis_select",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Diagnosis",
- "length": 0,
- "no_copy": 1,
- "options": "Diagnosis",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "codification_table",
+ "fieldtype": "Table",
+ "label": "Medical Coding",
+ "options": "Codification Table"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "diagnosis",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "",
- "length": 0,
- "no_copy": 1,
- "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": "sb_drug_prescription",
+ "fieldtype": "Section Break",
+ "label": "Medication"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "depends_on": "",
- "fieldname": "diagnosis_in_print",
- "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": "In print",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "drug_prescription",
+ "fieldtype": "Table",
+ "label": "Drug Prescription",
+ "options": "Drug Prescription"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "codification",
- "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": "Medical Coding",
- "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": "sb_test_prescription",
+ "fieldtype": "Section Break",
+ "label": "Investigation"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "codification_table",
- "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": "Medical Coding",
- "length": 0,
- "no_copy": 0,
- "options": "Codification Table",
- "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": "lab_test_prescription",
+ "fieldtype": "Table",
+ "label": "Lab Prescription",
+ "options": "Lab Prescription"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_drug_prescription",
- "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": "Medication",
- "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": "sb_procedures",
+ "fieldtype": "Section Break",
+ "label": "Procedures"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "drug_prescription",
- "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": "Medication",
- "length": 0,
- "no_copy": 0,
- "options": "Drug Prescription",
- "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": "procedure_prescription",
+ "fieldtype": "Table",
+ "label": "Procedure Prescription",
+ "no_copy": 1,
+ "options": "Procedure Prescription"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_test_prescription",
- "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": "Investigations",
- "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": "encounter_comment",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Review Details",
+ "no_copy": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lab_test_prescription",
- "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": "Investigations",
- "length": 0,
- "no_copy": 0,
- "options": "Lab Prescription",
- "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": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Patient Encounter",
+ "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": "sb_procedures",
- "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": "Procedures",
- "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": "appointment_type",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Appointment Type",
+ "no_copy": 1,
+ "options": "Appointment Type",
+ "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": "procedure_prescription",
- "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": "Procedures",
- "length": 0,
- "no_copy": 1,
- "options": "Procedure Prescription",
- "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": "practitioner.department",
+ "fieldname": "medical_department",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Department",
+ "options": "Medical Department",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "encounter_comment",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Review Details",
- "length": 0,
- "no_copy": 1,
- "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": "inpatient_status",
+ "fieldtype": "Data",
+ "label": "Inpatient Status",
+ "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": "Patient Encounter",
- "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": "column_break_17",
+ "fieldtype": "Column Break"
}
- ],
- "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": "2018-09-04 11:50:52.217175",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Patient Encounter",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-02-27 12:42:21.751964",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Encounter",
+ "owner": "Administrator",
"permissions": [
{
- "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": "Physician",
- "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": "Physician",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "patient, practitioner, visit_department, encounter_date, encounter_time",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "patient",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "patient, practitioner, medical_department, encounter_date, encounter_time",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1,
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
index fe7ac8e..ade4748 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
@@ -6,59 +6,63 @@
import frappe
from frappe.model.document import Document
from frappe.utils import cstr
+from frappe import _
class PatientEncounter(Document):
def on_update(self):
- if(self.appointment):
- frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
- update_encounter_to_medical_record(self)
+ if self.appointment:
+ frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
+ update_encounter_medical_record(self)
def after_insert(self):
insert_encounter_to_medical_record(self)
def on_cancel(self):
- if(self.appointment):
- frappe.db.set_value("Patient Appointment", self.appointment, "status", "Open")
+ if self.appointment:
+ frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
delete_medical_record(self)
def insert_encounter_to_medical_record(doc):
subject = set_subject_field(doc)
- medical_record = frappe.new_doc("Patient Medical Record")
+ medical_record = frappe.new_doc('Patient Medical Record')
medical_record.patient = doc.patient
medical_record.subject = subject
- medical_record.status = "Open"
+ medical_record.status = 'Open'
medical_record.communication_date = doc.encounter_date
- medical_record.reference_doctype = "Patient Encounter"
+ medical_record.reference_doctype = 'Patient Encounter'
medical_record.reference_name = doc.name
medical_record.reference_owner = doc.owner
medical_record.save(ignore_permissions=True)
-def update_encounter_to_medical_record(encounter):
- medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s", (encounter.name))
+def update_encounter_medical_record(encounter):
+ medical_record_id = frappe.db.exists('Patient Medical Record', {'reference_name': encounter.name})
+
if medical_record_id and medical_record_id[0][0]:
subject = set_subject_field(encounter)
- frappe.db.set_value("Patient Medical Record", medical_record_id[0][0], "subject", subject)
+ frappe.db.set_value('Patient Medical Record', medical_record_id[0][0], 'subject', subject)
else:
insert_encounter_to_medical_record(encounter)
def delete_medical_record(encounter):
- frappe.db.sql("""delete from `tabPatient Medical Record` where reference_name = %s""", (encounter.name))
+ frappe.db.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
def set_subject_field(encounter):
- subject = encounter.practitioner+"<br/>"
- if(encounter.symptoms):
- subject += "Symptoms: "+ cstr(encounter.symptoms)+".<br/>"
+ subject = encounter.practitioner + '\n'
+ if encounter.symptoms:
+ subject += _('Symptoms: ') + cstr(encounter.symptoms) + '\n'
else:
- subject += "No Symptoms <br/>"
- if(encounter.diagnosis):
- subject += "Diagnosis: "+ cstr(encounter.diagnosis)+".<br/>"
+ subject += _('No Symptoms') + '\n'
+
+ if encounter.diagnosis:
+ subject += _('Diagnosis: ') + cstr(encounter.diagnosis) + '\n'
else:
- subject += "No Diagnosis <br/>"
- if(encounter.drug_prescription):
- subject +="\nDrug(s) Prescribed. "
- if(encounter.lab_test_prescription):
- subject += "\nTest(s) Prescribed."
- if(encounter.procedure_prescription):
- subject += "\nProcedure(s) Prescribed."
+ subject += _('No Diagnosis') + '\n'
+
+ if encounter.drug_prescription:
+ subject += '\n' + _('Drug(s) Prescribed.')
+ if encounter.lab_test_prescription:
+ subject += '\n' + _('Test(s) Prescribed.')
+ if encounter.procedure_prescription:
+ subject += '\n' + _('Procedure(s) Prescribed.')
return subject
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js
index 93c02f6..d8f63bd 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js
@@ -2,5 +2,5 @@
(c) ESS 2015-16
*/
frappe.listview_settings['Patient Encounter'] = {
- filters:[["docstatus","!=","1"]]
+ filters:[["docstatus","!=","2"]]
};
diff --git a/erpnext/healthcare/page/appointment_analytic/__init__.py b/erpnext/healthcare/doctype/patient_encounter_diagnosis/__init__.py
similarity index 100%
copy from erpnext/healthcare/page/appointment_analytic/__init__.py
copy to erpnext/healthcare/doctype/patient_encounter_diagnosis/__init__.py
diff --git a/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.json b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.json
new file mode 100644
index 0000000..00ca309
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.json
@@ -0,0 +1,33 @@
+{
+ "actions": [],
+ "beta": 1,
+ "creation": "2020-02-26 16:48:16.835105",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "diagnosis"
+ ],
+ "fields": [
+ {
+ "fieldname": "diagnosis",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Diagnosis",
+ "options": "Diagnosis",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 16:58:16.480583",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Encounter Diagnosis",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py
new file mode 100644
index 0000000..34b0cf8
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientEncounterDiagnosis(Document):
+ pass
diff --git a/erpnext/healthcare/page/appointment_analytic/__init__.py b/erpnext/healthcare/doctype/patient_encounter_symptom/__init__.py
similarity index 100%
copy from erpnext/healthcare/page/appointment_analytic/__init__.py
copy to erpnext/healthcare/doctype/patient_encounter_symptom/__init__.py
diff --git a/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.json b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.json
new file mode 100644
index 0000000..bc92145
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.json
@@ -0,0 +1,33 @@
+{
+ "actions": [],
+ "beta": 1,
+ "creation": "2020-02-26 16:47:00.525657",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "complaint"
+ ],
+ "fields": [
+ {
+ "fieldname": "complaint",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Complaint",
+ "options": "Complaint",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 16:57:37.997481",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Encounter Symptom",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py
new file mode 100644
index 0000000..bdb7bb2
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientEncounterSymptom(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
index c6a6b44..3655e24 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
+++ b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
@@ -1,457 +1,155 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2016-06-09 11:30:44.972056",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2016-06-09 11:30:44.972056",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "patient",
+ "status",
+ "column_break_2",
+ "attach",
+ "section_break_4",
+ "subject",
+ "section_break_8",
+ "communication_date",
+ "reference_doctype",
+ "reference_name",
+ "column_break_9",
+ "reference_owner",
+ "user"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "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": 0,
- "in_standard_filter": 0,
- "label": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "HLC-PMR-.YYYY.-",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-PMR-.YYYY.-",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "search_index": 1
+ },
{
- "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": "attach",
- "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,
- "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": "attach",
+ "fieldtype": "Attach",
+ "label": "Attach Medical Record"
+ },
{
- "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": "section_break_4",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "subject",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "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": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Subject"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "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": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Open\nClose",
- "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": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "options": "Open\nClose",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fieldname": "communication_date",
- "fieldtype": "Date",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Datetime",
- "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": "Today",
+ "fieldname": "communication_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Datetime",
+ "read_only": 1
+ },
{
- "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": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Reference DocType",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "reference_doctype",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Reference DocType",
+ "options": "DocType",
+ "read_only": 1,
+ "search_index": 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": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Reference Name",
- "length": 0,
- "no_copy": 0,
- "options": "reference_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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "reference_name",
+ "fieldtype": "Dynamic Link",
+ "in_list_view": 1,
+ "label": "Reference Name",
+ "options": "reference_doctype",
+ "read_only": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "reference_name.owner",
- "fieldname": "reference_owner",
- "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": "Reference Owner",
- "length": 0,
- "no_copy": 1,
- "options": "",
- "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
- },
+ "fetch_from": "reference_name.owner",
+ "fieldname": "reference_owner",
+ "fieldtype": "Data",
+ "label": "Reference Owner",
+ "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,
- "default": "__user",
- "fieldname": "user",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "User",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "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": "__user",
+ "fieldname": "user",
+ "fieldtype": "Link",
+ "label": "User",
+ "options": "User",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
+ {
+ "fieldname": "column_break_9",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_8",
+ "fieldtype": "Section Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 1,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-21 14:44:37.927284",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Patient Medical Record",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "in_create": 1,
+ "links": [],
+ "modified": "2020-03-23 19:26:59.308383",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Medical Record",
+ "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": "Physician",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "patient, subject, communication_date, reference_doctype, reference_name",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "patient",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
-}
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "patient, subject, communication_date, reference_doctype, reference_name",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
index 460774a..e5a5e4c 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
+++ b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
@@ -3,8 +3,86 @@
# See license.txt
from __future__ import unicode_literals
import unittest
-
-# test_records = frappe.get_test_records('Patient Medical Record')
+import frappe
+from frappe.utils import nowdate
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_encounter, create_healthcare_docs, create_appointment
class TestPatientMedicalRecord(unittest.TestCase):
- pass
+ def setUp(self):
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+
+ def test_medical_record(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ appointment = create_appointment(patient, practitioner, nowdate(), invoice=1)
+ encounter = create_encounter(appointment)
+ # check for encounter
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': encounter.name})
+ self.assertTrue(medical_rec)
+
+ vital_signs = create_vital_signs(appointment)
+ # check for vital signs
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': vital_signs.name})
+ self.assertTrue(medical_rec)
+
+ appointment = create_appointment(patient, practitioner, nowdate(), invoice=1, procedure_template=1)
+ procedure = create_procedure(appointment)
+ procedure.start_procedure()
+ procedure.complete_procedure()
+ # check for clinical procedure
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': procedure.name})
+ self.assertTrue(medical_rec)
+
+ template = create_lab_test_template(medical_department)
+ lab_test = create_lab_test(template, patient)
+ # check for lab test
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': lab_test.name})
+ self.assertTrue(medical_rec)
+
+
+def create_procedure(appointment):
+ if appointment:
+ procedure = frappe.new_doc('Clinical Procedure')
+ procedure.procedure_template = appointment.procedure_template
+ procedure.appointment = appointment.name
+ procedure.patient = appointment.patient
+ procedure.practitioner = appointment.practitioner
+ procedure.medical_department = appointment.department
+ procedure.start_dt = appointment.appointment_date
+ procedure.start_time = appointment.appointment_time
+ procedure.save()
+ procedure.submit()
+ return procedure
+
+def create_vital_signs(appointment):
+ vital_signs = frappe.new_doc('Vital Signs')
+ vital_signs.patient = appointment.patient
+ vital_signs.signs_date = appointment.appointment_date
+ vital_signs.signs_time = appointment.appointment_time
+ vital_signs.temperature = 38.5
+ vital_signs.save()
+ vital_signs.submit()
+ return vital_signs
+
+def create_lab_test_template(medical_department):
+ if frappe.db.exists('Lab Test Template', 'Blood Test'):
+ return 'Blood Test'
+
+ template = frappe.new_doc('Lab Test Template')
+ template.lab_test_name = 'Blood Test'
+ template.lab_test_code = 'Blood Test'
+ template.lab_test_group = 'Services'
+ template.department = medical_department
+ template.is_billable = 1
+ template.lab_test_rate = 2000
+ template.save()
+ return template.name
+
+def create_lab_test(template, patient):
+ lab_test = frappe.new_doc('Lab Test')
+ lab_test.patient = patient
+ lab_test.patient_sex = frappe.db.get_value('Patient', patient, 'sex')
+ lab_test.template = template
+ lab_test.save()
+ lab_test.submit()
+ return lab_test
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_relation/patient_relation.json b/erpnext/healthcare/doctype/patient_relation/patient_relation.json
index 209a374..376f7f7 100644
--- a/erpnext/healthcare/doctype/patient_relation/patient_relation.json
+++ b/erpnext/healthcare/doctype/patient_relation/patient_relation.json
@@ -1,134 +1,52 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-04-26 15:40:11.561855",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2017-04-26 15:40:11.561855",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "patient",
+ "relation",
+ "description"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "relation",
- "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": "Relation",
- "length": 0,
- "no_copy": 0,
- "options": "\nFather\nMother\nSpouse\nSiblings\nFamily",
- "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": 1,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "relation",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Relation",
+ "options": "\nFather\nMother\nSpouse\nSiblings\nFamily\nOther",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Description"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2017-10-04 16:12:45.485333",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Patient Relation",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-01-29 12:45:40.081899",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Relation",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js
index f247856..7cb7c4b 100644
--- a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js
+++ b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js
@@ -5,9 +5,9 @@
refresh: function(frm) {
cur_frm.fields_dict["time_slots"].grid.wrapper.find('.grid-add-row').hide();
cur_frm.fields_dict["time_slots"].grid.add_custom_button(__('Add Time Slots'), () => {
- var d = new frappe.ui.Dialog({
+ let d = new frappe.ui.Dialog({
fields: [
- {fieldname: 'days', label: __('Select Days'), fieldtype:'MultiSelect',
+ {fieldname: 'days', label: __('Select Days'), fieldtype: 'MultiSelect',
options:[
{value:'Sunday', label:__('Sunday')},
{value:'Monday', label:__('Monday')},
@@ -17,40 +17,41 @@
{value:'Friday', label:__('Friday')},
{value:'Saturday', label:__('Saturday')},
], reqd: 1},
- {fieldname: 'from_time', label:__('From'), fieldtype:'Time',
+ {fieldname: 'from_time', label: __('From'), fieldtype: 'Time',
'default': '09:00:00', reqd: 1},
- {fieldname: 'to_time', label:__('To'), fieldtype:'Time',
+ {fieldname: 'to_time', label: __('To'), fieldtype: 'Time',
'default': '12:00:00', reqd: 1},
- {fieldname: 'duration', label:__('Appointment Duration (mins)'),
+ {fieldname: 'duration', label: __('Appointment Duration (mins)'),
fieldtype:'Int', 'default': 15, reqd: 1},
],
primary_action_label: __('Add Timeslots'),
primary_action: () => {
- var values = d.get_values();
- if(values) {
+ let values = d.get_values();
+ if (values) {
let slot_added = false;
values.days.split(',').forEach(function(day){
day = $.trim(day);
- if(['Sunday', 'Monday', 'Tuesday', 'Wednesday',
+ if (['Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday'].includes(day)){
add_slots(day);
}
});
+
function check_overlap_or_add_slot(week_day, cur_time, end_time, add_slots_to_child){
let overlap = false;
- while(cur_time < end_time) {
+ while (cur_time < end_time) {
let add_to_child = true;
let to_time = cur_time.clone().add(values.duration, 'minutes');
- if(to_time <= end_time) {
- if(frm.doc.time_slots){
+ if (to_time <= end_time) {
+ if (frm.doc.time_slots){
frm.doc.time_slots.forEach(function(slot) {
- if(slot.day == week_day){
+ if (slot.day == week_day){
let slot_from_moment = moment(slot.from_time, 'HH:mm:ss');
let slot_to_moment = moment(slot.to_time, 'HH:mm:ss');
- if(cur_time.isSame(slot_from_moment) || cur_time.isBetween(slot_from_moment, slot_to_moment) ||
- to_time.isSame(slot_to_moment) || to_time.isBetween(slot_from_moment, slot_to_moment)){
+ if (cur_time.isSame(slot_from_moment) || cur_time.isBetween(slot_from_moment, slot_to_moment) ||
+ to_time.isSame(slot_to_moment) || to_time.isBetween(slot_from_moment, slot_to_moment)) {
overlap = true;
- if(add_slots_to_child){
+ if (add_slots_to_child) {
frappe.show_alert({
message:__('Time slot skiped, the slot {0} to {1} overlap exisiting slot {2} to {3}',
[cur_time.format('HH:mm:ss'), to_time.format('HH:mm:ss'), slot.from_time, slot.to_time]),
@@ -63,7 +64,7 @@
});
}
// add a new timeslot
- if(add_to_child && add_slots_to_child){
+ if (add_to_child && add_slots_to_child) {
frm.add_child('time_slots', {
from_time: cur_time.format('HH:mm:ss'),
to_time: to_time.format('HH:mm:ss'),
@@ -76,10 +77,11 @@
}
return overlap;
}
- function add_slots(week_day){
+
+ function add_slots(week_day) {
let cur_time = moment(values.from_time, 'HH:mm:ss');
let end_time = moment(values.to_time, 'HH:mm:ss');
- if(check_overlap_or_add_slot(week_day, cur_time, end_time, false)){
+ if (check_overlap_or_add_slot(week_day, cur_time, end_time, false)) {
frappe.confirm(__('Schedules for {0} overlaps, do you want to proceed after skiping overlaped slots ?', [week_day]),
function() {
// if Yes
@@ -88,21 +90,22 @@
function() {
// if No
frappe.show_alert({
- message:__('Slots for {0} are not added to the schedule', [week_day]),
- indicator:'red'
+ message: __('Slots for {0} are not added to the schedule', [week_day]),
+ indicator: 'red'
});
}
);
- }
- else{
+ } else {
check_overlap_or_add_slot(week_day, cur_time, end_time, true);
}
}
+
frm.refresh_field('time_slots');
- if(slot_added){
+
+ if (slot_added) {
frappe.show_alert({
- message:__('Time slots added'),
- indicator:'green'
+ message: __('Time slots added'),
+ indicator: 'green'
});
}
}
diff --git a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json
index 08a1b86..cff100c 100644
--- a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json
+++ b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json
@@ -1,160 +1,71 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:schedule_name",
- "beta": 1,
- "creation": "2017-05-03 17:28:03.926787",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:schedule_name",
+ "beta": 1,
+ "creation": "2017-05-03 17:28:03.926787",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "disabled",
+ "schedule_details_section",
+ "schedule_name",
+ "time_slots"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "schedule_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Schedule Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "schedule_name",
+ "fieldtype": "Data",
+ "ignore_xss_filter": 1,
+ "in_list_view": 1,
+ "label": "Schedule Name",
+ "reqd": 1,
+ "unique": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "time_slots",
- "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": "Time Slots",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Schedule Time Slot",
- "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": "time_slots",
+ "fieldtype": "Table",
+ "label": "Time Slots",
+ "options": "Healthcare Schedule Time Slot"
+ },
{
- "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": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "label": "Disabled",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "schedule_details_section",
+ "fieldtype": "Section Break",
+ "label": "Schedule Details"
}
- ],
- "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-06-29 14:55:34.795995",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Practitioner Schedule",
- "name_case": "",
- "owner": "rmehta@gmail.com",
+ ],
+ "links": [],
+ "modified": "2020-01-31 12:21:45.975488",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Practitioner Schedule",
+ "owner": "rmehta@gmail.com",
"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": "Healthcare Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "restrict_to_domain": "Healthcare",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json b/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json
index 236c2b8..e4c01d7 100644
--- a/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json
+++ b/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json
@@ -1,338 +1,99 @@
{
- "allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-11-17 15:52:48.324157",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2017-11-17 15:52:48.324157",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "procedure",
+ "procedure_name",
+ "department",
+ "practitioner",
+ "date",
+ "comments",
+ "appointment_booked",
+ "procedure_created",
+ "invoiced"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure",
- "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": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Clinical Procedure Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "procedure",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Clinical Procedure",
+ "options": "Clinical Procedure Template",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "procedure.template",
- "fieldname": "procedure_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": "Procedure Name",
- "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": "procedure.template",
+ "fieldname": "procedure_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Procedure Name"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "department",
- "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": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Medical Department",
- "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": "procedure.medical_department",
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Department",
+ "options": "Medical Department"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "practitioner",
- "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": "Referral",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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": "practitioner",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Referring Practitioner",
+ "options": "Healthcare Practitioner"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "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": "date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Date"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "comments",
- "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": "Comments",
- "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": "comments",
+ "fieldtype": "Data",
+ "label": "Comments"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "appointment_booked",
- "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": "Appointment Booked",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "appointment_booked",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Appointment Booked",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure_created",
- "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": "Procedure Created",
- "length": 0,
- "no_copy": 1,
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "procedure_created",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Procedure Created",
+ "no_copy": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "invoiced",
- "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": "Invoiced",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "read_only": 1,
+ "search_index": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-04 03:33:35.939816",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Procedure Prescription",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 15:42:33.988081",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Procedure Prescription",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.js b/erpnext/healthcare/doctype/sample_collection/sample_collection.js
index 9934ce4..2f5278b 100644
--- a/erpnext/healthcare/doctype/sample_collection/sample_collection.js
+++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.js
@@ -3,7 +3,7 @@
frappe.ui.form.on('Sample Collection', {
refresh: function(frm) {
- if(frappe.defaults.get_default("require_sample_collection")){
+ if(frappe.defaults.get_default("create_sample_collection_for_lab_test")){
frm.add_custom_button(__("View Lab Tests"), function() {
frappe.route_options = {"sample": frm.doc.name};
frappe.set_route("List", "Lab Test");
diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.json b/erpnext/healthcare/doctype/sample_collection/sample_collection.json
index 783fc3d..39cead8 100644
--- a/erpnext/healthcare/doctype/sample_collection/sample_collection.json
+++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.json
@@ -1,687 +1,199 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2016-04-05 15:58:18.076977",
- "custom": 0,
- "default_print_format": "",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 0,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2016-04-05 15:58:18.076977",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+ "inpatient_record",
+ "naming_series",
+ "invoiced",
+ "patient",
+ "column_break_4",
+ "patient_age",
+ "patient_sex",
+ "company",
+ "section_break_6",
+ "sample",
+ "sample_uom",
+ "sample_qty",
+ "column_break_10",
+ "collected_by",
+ "collected_time",
+ "num_print",
+ "amended_from",
+ "section_break_15",
+ "sample_details"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.inpatient_record",
- "fieldname": "inpatient_record",
- "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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
- "options": "Inpatient Record",
- "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": "patient.inpatient_record",
+ "fieldname": "inpatient_record",
+ "fieldtype": "Link",
+ "label": "Inpatient Record",
+ "options": "Inpatient Record",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "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": 0,
- "in_standard_filter": 0,
- "label": "Series",
- "length": 0,
- "no_copy": 1,
- "options": "HLC-SC-.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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "bold": 1,
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "HLC-SC-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "invoiced",
- "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": "Invoiced",
- "length": 0,
- "no_copy": 1,
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "no_copy": 1,
+ "read_only": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "inpatient_record.patient",
- "fieldname": "patient",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "inpatient_record.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_standard_filter": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "search_index": 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": "patient_age",
- "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": "Age",
- "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": "patient_age",
+ "fieldtype": "Data",
+ "label": "Age"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.sex",
- "fieldname": "patient_sex",
- "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": "Gender",
- "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": "patient.sex",
+ "fieldname": "patient_sex",
+ "fieldtype": "Data",
+ "label": "Gender"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Company",
+ "options": "Company",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "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": "sample",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Sample",
- "length": 0,
- "no_copy": 0,
- "options": "Lab Test Sample",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "sample",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Sample",
+ "options": "Lab Test Sample",
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "sample.sample_uom",
- "fieldname": "sample_uom",
- "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": "UOM",
- "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": "sample.sample_uom",
+ "fieldname": "sample_uom",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "UOM"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "sample_quantity",
- "fieldtype": "Float",
- "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": "Quantity",
- "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_10",
+ "fieldtype": "Column Break"
+ },
{
- "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
- },
+ "fieldname": "collected_by",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Collected By",
+ "options": "User"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "collected_by",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Collected By",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "collected_time",
+ "fieldtype": "Datetime",
+ "label": "Collected Time"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "collected_time",
- "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": "Collected Time",
- "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_on_submit": 1,
+ "default": "1",
+ "fieldname": "num_print",
+ "fieldtype": "Int",
+ "label": "No. of print",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fieldname": "num_print",
- "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": "No. of print",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "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": "Sample Collection",
+ "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": "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": "Sample Collection",
- "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": "section_break_15",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_15",
- "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
- },
+ "default": "0",
+ "fieldname": "sample_qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Quantity"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample_collection_details",
- "fieldtype": "Long Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Collection 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": "sample_details",
+ "fieldtype": "Long Text",
+ "ignore_xss_filter": 1,
+ "label": "Collection Details"
}
- ],
- "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": "2018-08-21 14:44:39.128989",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Sample Collection",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-03-25 16:55:52.376834",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Sample Collection",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Laboratory User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Laboratory User",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "patient, sample",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "patient",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
-}
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "patient, sample",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.js b/erpnext/healthcare/doctype/vital_signs/vital_signs.js
index a5f9d61..78509e0 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.js
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.js
@@ -1,49 +1,52 @@
// Copyright (c) 2016, ESS LLP and contributors
// For license information, please see license.txt
-frappe.ui.form.on("Vital Signs", "height", function(frm) {
- if(frm.doc.height && frm.doc.weight){
- calculate_bmi(frm);
+frappe.ui.form.on('Vital Signs', {
+ height: function(frm) {
+ if (frm.doc.height && frm.doc.weight) {
+ calculate_bmi(frm);
+ }
+ },
+
+ weight: function(frm) {
+ if (frm.doc.height && frm.doc.weight) {
+ calculate_bmi(frm);
+ }
+ },
+
+ bp_systolic: function(frm) {
+ if (frm.doc.bp_systolic && frm.doc.bp_diastolic) {
+ set_bp(frm);
+ }
+ },
+
+ bp_diastolic: function(frm) {
+ if (frm.doc.bp_systolic && frm.doc.bp_diastolic) {
+ set_bp(frm);
+ }
}
});
-frappe.ui.form.on("Vital Signs", "weight", function(frm) {
- if(frm.doc.height && frm.doc.weight){
- calculate_bmi(frm);
- }
-});
-
-var calculate_bmi = function(frm){
+let calculate_bmi = function(frm){
// Reference https://en.wikipedia.org/wiki/Body_mass_index
// bmi = weight (in Kg) / height * height (in Meter)
- var bmi = (frm.doc.weight/(frm.doc.height*frm.doc.height)).toFixed(2);
- var bmi_note = null;
- if(bmi<18.5){
- bmi_note = "Underweight";
- }else if(bmi>=18.5 && bmi<25){
- bmi_note = "Normal";
- }else if(bmi>=25 && bmi<30){
- bmi_note = "Overweight";
- }else if(bmi>=30){
- bmi_note = "Obese";
+ let bmi = (frm.doc.weight / (frm.doc.height * frm.doc.height)).toFixed(2);
+ let bmi_note = null;
+
+ if (bmi<18.5) {
+ bmi_note = 'Underweight';
+ } else if (bmi>=18.5 && bmi<25) {
+ bmi_note = 'Normal';
+ } else if (bmi>=25 && bmi<30) {
+ bmi_note = 'Overweight';
+ } else if (bmi>=30) {
+ bmi_note = 'Obese';
}
- frappe.model.set_value(frm.doctype,frm.docname, "bmi", bmi);
- frappe.model.set_value(frm.doctype,frm.docname, "nutrition_note", bmi_note);
+ frappe.model.set_value(frm.doctype,frm.docname, 'bmi', bmi);
+ frappe.model.set_value(frm.doctype,frm.docname, 'nutrition_note', bmi_note);
};
-frappe.ui.form.on("Vital Signs", "bp_systolic", function(frm) {
- if(frm.doc.bp_systolic && frm.doc.bp_diastolic){
- set_bp(frm);
- }
-});
-
-frappe.ui.form.on("Vital Signs", "bp_diastolic", function(frm) {
- if(frm.doc.bp_systolic && frm.doc.bp_diastolic){
- set_bp(frm);
- }
-});
-
-var set_bp = function(frm){
- var bp = frm.doc.bp_systolic+"/"+frm.doc.bp_diastolic+" mmHg";
- frappe.model.set_value(frm.doctype,frm.docname, "bp", bp);
+let set_bp = function(frm){
+ let bp = frm.doc.bp_systolic+ '/' + frm.doc.bp_diastolic + ' mmHg';
+ frappe.model.set_value(frm.doctype,frm.docname, 'bp', bp);
};
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.json b/erpnext/healthcare/doctype/vital_signs/vital_signs.json
index 1503f83..75726db 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.json
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.json
@@ -1,991 +1,273 @@
{
+ "actions": [],
"allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
- "allow_rename": 0,
"beta": 1,
"creation": "2017-02-02 11:00:24.853005",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
+ "field_order": [
+ "inpatient_record",
+ "patient",
+ "patient_name",
+ "appointment",
+ "encounter",
+ "column_break_2",
+ "signs_date",
+ "signs_time",
+ "sb_vs",
+ "temperature",
+ "pulse",
+ "respiratory_rate",
+ "tongue",
+ "abdomen",
+ "column_break_8",
+ "reflexes",
+ "bp_systolic",
+ "bp_diastolic",
+ "bp",
+ "vital_signs_note",
+ "sb_nutrition_values",
+ "height",
+ "weight",
+ "bmi",
+ "column_break_14",
+ "nutrition_note",
+ "company",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.inpatient_record",
"fieldname": "inpatient_record",
"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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
"options": "Inpatient Record",
- "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,
"fetch_from": "inpatient_record.patient",
"fieldname": "patient",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Patient",
- "length": 0,
- "no_copy": 0,
"options": "Patient",
- "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.patient_name",
"fieldname": "patient_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Patient Name",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Appointment",
- "length": 0,
- "no_copy": 1,
"options": "Patient Appointment",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "encounter",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Patient Encounter",
- "length": 0,
"no_copy": 1,
"options": "Patient Encounter",
- "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
+ "report_hide": 1
},
{
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "Today",
"fieldname": "signs_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": "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
"fieldname": "signs_time",
"fieldtype": "Time",
- "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": "Time",
- "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "sb_vs",
"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": "Vital Signs",
- "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": "Vital Signs"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Presence of a fever (temp > 38.5 \u00b0C/101.3 \u00b0F or sustained temp > 38 \u00b0C/100.4 \u00b0F)",
"fieldname": "temperature",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Body Temperature",
- "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": "Body Temperature"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Adults' pulse rate is anywhere between 50 and 80 beats per minute.",
"fieldname": "pulse",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Heart Rate / Pulse",
- "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": "Heart Rate / Pulse"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Normal reference range for an adult is 16\u201320 breaths/minute (RCP 2012)",
"fieldname": "respiratory_rate",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Respiratory rate",
- "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": "Respiratory rate"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "tongue",
"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": "Tongue",
- "length": 0,
- "no_copy": 0,
- "options": "\nCoated\nVery Coated\nNormal\nFurry\nCuts",
- "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": "\nCoated\nVery Coated\nNormal\nFurry\nCuts"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "abdomen",
"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": "Abdomen",
- "length": 0,
- "no_copy": 0,
- "options": "\nNormal\nBloated\nFull\nFluid\nConstipated",
- "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": "\nNormal\nBloated\nFull\nFluid\nConstipated"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_8",
- "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": "reflexes",
"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": "Reflexes",
- "length": 0,
- "no_copy": 0,
- "options": "\nNormal\nHyper\nVery Hyper\nOne Sided",
- "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": "\nNormal\nHyper\nVery Hyper\nOne Sided"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "bp_systolic",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Blood Pressure (systolic)",
- "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": "Blood Pressure (systolic)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
"fieldname": "bp_diastolic",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Blood Pressure (diastolic)",
- "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": "Blood Pressure (diastolic)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Normal resting blood pressure in an adult is approximately 120 mmHg systolic, and 80 mmHg diastolic, abbreviated \"120/80 mmHg\"",
"fieldname": "bp",
"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": "Blood Pressure",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "vital_signs_note",
"fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Notes",
- "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": "Notes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "sb_nutrition_values",
"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": "Nutrition Values",
- "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": "Nutrition Values"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "height",
"fieldtype": "Float",
- "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": "Height (In Meter)",
- "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": "Height (In Meter)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "weight",
"fieldtype": "Float",
- "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": "Weight (In Kilogram)",
- "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": "Weight (In Kilogram)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0.00",
"fieldname": "bmi",
"fieldtype": "Float",
- "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": "BMI",
- "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
+ "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_14",
- "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": "nutrition_note",
"fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Notes",
- "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": "Notes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Company"
},
{
- "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": "Vital Signs",
- "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
+ "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": "2018-11-23 14:14:05.933292",
+ "links": [],
+ "modified": "2020-03-04 17:19:29.549889",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Vital Signs",
- "name_case": "",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Physician",
- "set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
- "amend": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Nursing User",
- "set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Healthcare",
"search_fields": "patient, signs_date",
"show_name_in_global_search": 1,
@@ -993,6 +275,5 @@
"sort_order": "DESC",
"title_field": "patient",
"track_changes": 1,
- "track_seen": 1,
- "track_views": 0
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.py b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
index bf4dace..959e850 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.py
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
@@ -6,6 +6,7 @@
import frappe
from frappe.model.document import Document
from frappe.utils import cstr
+from frappe import _
class VitalSigns(Document):
def on_submit(self):
@@ -16,34 +17,35 @@
def insert_vital_signs_to_medical_record(doc):
subject = set_subject_field(doc)
- medical_record = frappe.new_doc("Patient Medical Record")
+ medical_record = frappe.new_doc('Patient Medical Record')
medical_record.patient = doc.patient
medical_record.subject = subject
- medical_record.status = "Open"
+ medical_record.status = 'Open'
medical_record.communication_date = doc.signs_date
- medical_record.reference_doctype = "Vital Signs"
+ medical_record.reference_doctype = 'Vital Signs'
medical_record.reference_name = doc.name
medical_record.reference_owner = doc.owner
+ medical_record.flags.ignore_mandatory = True
medical_record.save(ignore_permissions=True)
def delete_vital_signs_from_medical_record(doc):
- medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s",(doc.name))
- if medical_record_id and medical_record_id[0][0]:
- frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
+ medical_record = frappe.db.get_value('Patient Medical Record', {'reference_name': doc.name})
+ if medical_record:
+ frappe.delete_doc('Patient Medical Record', medical_record)
def set_subject_field(doc):
- subject = ""
+ subject = ''
if(doc.temperature):
- subject += "Temperature: \n"+ cstr(doc.temperature)+". "
+ subject += _('Temperature: ') + '\n'+ cstr(doc.temperature) + '. '
if(doc.pulse):
- subject += "Pulse: \n"+ cstr(doc.pulse)+". "
+ subject += _('Pulse: ') + '\n' + cstr(doc.pulse) + '. '
if(doc.respiratory_rate):
- subject += "Respiratory Rate: \n"+ cstr(doc.respiratory_rate)+". "
+ subject += _('Respiratory Rate: ') + '\n' + cstr(doc.respiratory_rate) + '. '
if(doc.bp):
- subject += "BP: \n"+ cstr(doc.bp)+". "
+ subject += _('BP: ') + '\n' + cstr(doc.bp) + '. '
if(doc.bmi):
- subject += "BMI: \n"+ cstr(doc.bmi)+". "
+ subject += _('BMI: ') + '\n' + cstr(doc.bmi) + '. '
if(doc.nutrition_note):
- subject += "Note: \n"+ cstr(doc.nutrition_note)+". "
+ subject += _('Note: ') + '\n' + cstr(doc.nutrition_note) + '. '
return subject
diff --git a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.js b/erpnext/healthcare/page/appointment_analytic/appointment_analytic.js
deleted file mode 100644
index 9f2e552..0000000
--- a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.js
+++ /dev/null
@@ -1,205 +0,0 @@
-frappe.pages['appointment-analytic'].on_page_load = function(wrapper) {
- frappe.ui.make_app_page({
- parent: wrapper,
- title: 'Appointment Analytics',
- single_column: true
- });
- new erpnext.AppointmentAnalytics(wrapper);
- frappe.breadcrumbs.add("Medical");
-};
-
-erpnext.AppointmentAnalytics = frappe.views.TreeGridReport.extend({
- init: function(wrapper) {
- this._super({
- title: __("Appointment Analytics"),
- parent: $(wrapper).find('.layout-main'),
- page: wrapper.page,
- doctypes: ["Patient Appointment", "Healthcare Practitioner", "Medical Department", "Appointment Type", "Patient"],
- tree_grid: { show: true }
- });
-
- this.tree_grids = {
- "Medical Department": {
- label: __("Department"),
- show: true,
- item_key: "practitioner",
- parent_field: "department",
- formatter: function(item) {
- return item.name;
- }
- },
- "Healthcare Practitioner": {
- label: __("Healthcare Practitioner"),
- show: true,
- item_key: "practitioner",
- formatter: function(item) {
- return item.name;
- }
- },
- };
- },
- setup_columns: function() {
- this.tree_grid = this.tree_grids[this.tree_type];
-
- var std_columns = [
- {id: "name", name: this.tree_grid.label, field: "name", width: 300},
- {id: "total", name: "Total", field: "total", plot: false,
- formatter: this.currency_formatter}
- ];
-
- this.make_date_range_columns();
- this.columns = std_columns.concat(this.columns);
- },
- filters: [
- {fieldtype:"Select", label: __("Tree Type"), fieldname: "tree_type",
- options:["Healthcare Practitioner", "Medical Department"], filter: function(val, item, opts, me) {
- return me.apply_zero_filter(val, item, opts, me);}},
- {fieldtype:"Select", label: __("Status"), fieldname: "status",
- options:[
- {label: __("Select Status"), value: "Select Status..."},
- {label: __("Open"), value: "Open"},
- {label: __("Closed"), value: "Closed"},
- {label: __("Pending"), value: "Pending"},
- {label: __("Scheduled"), value: "Scheduled"},
- {label: __("Cancelled"), value: "Cancelled"}]},
- {fieldtype:"Select", label: __("Type"), link:"Appointment Type", fieldname: "type",
- default_value: __("Select Type...")},
- {fieldtype:"Select", label: __("Healthcare Practitioner"), link:"Healthcare Practitioner", fieldname: "practitioner",
- default_value: __("Select Healthcare Practitioner..."), filter: function(val, item, opts) {
- return val == opts.default_value || item.name == val || item._show;
- }, link_formatter: {filter_input: "practitioner"}},
- {fieldtype:"Select", label: __("Department"), link:"Medical Department", fieldname: "department",
- default_value: __("Select Department..."), filter: function(val, item, opts) {
- return val == opts.default_value || item.department == val || item._show;
- }, link_formatter: {filter_input: "department"}},
- {fieldtype:"Date", label: __("From Date"), fieldname: "from_date"},
- {fieldtype:"Date", label: __("To Date"), fieldname: "to_date"},
- {fieldtype:"Select", label: __("Range"), fieldname: "range",
- options:[{label: __("Daily"), value: "Daily"}, {label: __("Weekly"), value: "Weekly"},
- {label: __("Monthly"), value: "Monthly"}, {label: __("Quarterly"), value: "Quarterly"},
- {label: __("Yearly"), value: "Yearly"}]}
- ],
- setup_filters: function() {
- this._super();
- this.trigger_refresh_on_change(["tree_type", "practitioner", "department", "status", "type"]);
-
- // this.show_zero_check()
- },
- init_filter_values: function() {
- this._super();
- this.filter_inputs.range.val('Quarterly');
- },
- prepare_data: function() {
- var me = this;
- if (!this.tl) {
- this.tl = frappe.report_dump.data["Patient Appointment"];
- }
- if(!this.data || me.item_type != me.tree_type) {
- var items = null;
- if(me.tree_type=='Healthcare Practitioner') {
- items = frappe.report_dump.data["Healthcare Practitioner"];
- } if(me.tree_type=='Medical Department') {
- items = this.prepare_tree("Healthcare Practitioner", "Medical Department");
- }
- me.item_type = me.tree_type;
- me.parent_map = {};
- me.item_by_name = {};
- me.data = [];
-
- $.each(items, function(i, v) {
- var d = copy_dict(v);
-
- me.data.push(d);
- me.item_by_name[d.name] = d;
- if(d[me.tree_grid.parent_field]) {
- me.parent_map[d.name] = d[me.tree_grid.parent_field];
- }
- me.reset_item_values(d);
- });
-
- this.set_indent();
-
-
- } else {
- // otherwise, only reset values
- $.each(this.data, function(i, d) {
- me.reset_item_values(d);
- });
- }
- this.prepare_balances();
- if(me.tree_grid.show) {
- this.set_totals(false);
- this.update_groups();
- } else {
- this.set_totals(true);
- }
-
-
- },
- prepare_balances: function() {
- var me = this;
- var from_date = frappe.datetime.str_to_obj(this.from_date);
- var status = this.status;
- var type = this.type;
- var to_date = frappe.datetime.str_to_obj(this.to_date);
- $.each(this.tl, function(i, tl) {
- if (me.is_default('company') ? true : tl.company === me.company) {
-
- var date = frappe.datetime.str_to_obj(tl.appointment_date);
- if (date >= from_date && date <= to_date) {
- var item = me.item_by_name[tl[me.tree_grid.item_key]] ||
- me.item_by_name['Not Set'];
-
- var d = tl.appointment_date.split(" ")[0];
- if(status == "Select Status..." && type=="Select Type...")
- {
- item[me.column_map[d].field] += 1;
-
- }else if (status !== "Select Status..." && type == "Select Type..."){
- if(status === tl.status){item[me.column_map[d].field] += 1;}
- }else if (status == "Select Status..." && type !== "Select Type..."){
- if(type === tl.appointment_type){item[me.column_map[d].field] += 1;}
- }else {
- if(type === tl.appointment_type && status === tl.status){item[me.column_map[d].field] += 1;}
- }
- }
- }
- });
- },
- update_groups: function() {
- var me = this;
-
- $.each(this.data, function(i, item) {
- var parent = me.parent_map[item.name];
- while(parent) {
- var parent_group = me.item_by_name[parent];
-
- $.each(me.columns, function(c, col) {
- if (col.formatter == me.currency_formatter) {
- parent_group[col.field] =
- flt(parent_group[col.field])
- + flt(item[col.field]);
- }
- });
- parent = me.parent_map[parent];
- }
- });
- },
- set_totals: function(sort) {
- var me = this;
- $.each(this.data, function(i, d) {
- d.total = 0.0;
- $.each(me.columns, function(i, col) {
- if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total")
- d.total += d[col.field];
- });
- });
-
- if(sort)this.data = this.data.sort(function(a, b) { return b.total - a.total; });
-
- if(!this.checked) {
- this.data[0].checked = true;
- }
- }
-
-});
diff --git a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.json b/erpnext/healthcare/page/appointment_analytic/appointment_analytic.json
deleted file mode 100644
index ac5ca1a..0000000
--- a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "content": null,
- "creation": "2016-08-18 12:29:52.497819",
- "docstatus": 0,
- "doctype": "Page",
- "idx": 0,
- "modified": "2018-08-06 11:40:53.082863",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "appointment-analytic",
- "owner": "Administrator",
- "page_name": "Appointment Analytics",
- "restrict_to_domain": "Healthcare",
- "roles": [
- {
- "role": "Physician"
- }
- ],
- "script": null,
- "standard": "Yes",
- "style": null,
- "system_page": 0,
- "title": "Appointment Analytics"
-}
\ No newline at end of file
diff --git a/erpnext/healthcare/print_format/encounter_print/encounter_print.json b/erpnext/healthcare/print_format/encounter_print/encounter_print.json
index 20e44b7..ec1e0f2 100644
--- a/erpnext/healthcare/print_format/encounter_print/encounter_print.json
+++ b/erpnext/healthcare/print_format/encounter_print/encounter_print.json
@@ -1,22 +1,22 @@
{
- "align_labels_right": 0,
- "creation": "2017-04-10 14:05:53.355863",
- "custom_format": 1,
- "disabled": 0,
- "doc_type": "Patient Encounter",
- "docstatus": 0,
- "doctype": "Print Format",
- "font": "Default",
- "html": "<div >\n {% if letter_head and not no_letterhead -%}\n <div class=\"letter-head\">{{ letter_head }}</div>\n <hr>\n {% else %}\n <div align=\"right\">\n <h1>{{doc.name}}</h1>\n </div>\n {%- endif %}\n <div class=\"row section-break\">\n <div class=\"col-xs-6 column-break\">\n {% if doc.appointment %}\n\t <div class=\"row\">\n\t\t\t<div class=\"col-xs-4 text-left\">\n\t\t\t<label>Appointment</label>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-7 value\">\n\t\t\t<strong>: </strong>{{doc.appointment}}\n\t\t\t</div>\n\t\t</div>\n\t\t{%- endif -%}\n\n <div class=\"row\">\n\t\t <div class=\"col-xs-4 text-left\">\n\t\t\t <label>Patient</label>\n\t\t </div>\n {% if doc.patient %}\n\t\t <div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong>{{doc.patient}}\n\t\t </div>\n {% else %}\n <div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong><em>Patient Name</em>\n\t\t </div>\n {%- endif -%}\n\t\t</div>\n\t <div class=\"row\">\n\t\t\t<div class=\"col-xs-4 text-left\">\n\t\t\t\t<label>Age</label>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong> {{doc.patient_age}}\n\t\t\t</div>\n\t\t</div>\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n\t\t\t\t<label>Gender</label>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong> {{doc.patient_sex}}\n\t\t\t</div>\n </div>\n\n </div>\n <div class=\"col-xs-6 column-break\">\n\n <div class=\"row\">\n\t <div class=\"col-xs-4 text-left\">\n\t\t <label>Healthcare Practitioner</label>\n\t </div>\n {% if doc.practitioner %}\n\t <div class=\"col-xs-7 text-left value\">\n\t\t\t<strong>: </strong>{{doc.practitioner}}\n\t </div>\n {%- endif -%}\n\t</div>\n\n {% if doc.encounter_date %}\n\t <div class=\"row\">\n\t\t<div class=\"col-xs-4 text-left\">\n\t\t<label>Date</label>\n\t\t</div>\n\t\t<div class=\"col-xs-7 text-left value\">\n\t\t<strong>: </strong>{{doc.encounter_date}}\n\t\t</div>\n </div>\n\t {%- endif -%}\n {% if doc.encounter_time %}\n\t <div class=\"row\">\n\t\t<div class=\"col-xs-4 text-left\">\n\t\t<label>Time</label>\n\t\t</div>\n\t\t<div class=\"col-xs-7 text-left value\">\n\t\t<strong>: </strong>{{doc.encounter_time}}\n\t\t</div>\n </div>\n\t {%- endif -%}\n {% if doc.visit_department %}\n\t <div class=\"row\">\n\t\t<div class=\"col-xs-4 text-left\">\n\t\t<label>Department</label>\n\t\t</div>\n\t\t<div class=\"col-xs-7 text-left value\">\n\t\t<strong>: </strong>{{doc.visit_department}}\n\t\t</div>\n </div>\n {%- endif -%}\n </div>\n\n </div>\n\n</div>\n<div>\n <hr>\n {% if doc.symptoms_in_print%}\n {% if doc.symptoms %}\n Complaints:\n <strong>{{doc.symptoms}}</strong>\n \t <br>\n {%- endif -%}\n {%- endif -%}\n\n {% if doc.diagnosis_in_print%}\n {% if doc.diagnosis %}\n \t Diagnosis:\n <strong>{{doc.diagnosis}}</strong>\n <br>\n {%- endif -%}\n {%- endif -%}\n\n</div>\n\n<div>\n {% if doc.drug_prescription %}\n <br>\n Rx,\n <table class=\"table\">\n <tbody>\n <!--<tr>\n <th>Drug</th>\n <th class=\"text-left\">Dosage</th>\n <th class=\"text-left\">Period</th>\n <th>Remark</th>\n </tr>-->\n\n {%- for row in doc.drug_prescription -%}\n <tr>\n <td style=\"width: 30%;border:none;\">\n {%- if row.drug_name -%}<b>{{ row.drug_name }}</b>{%- endif -%}\n </td>\n \t<td style=\"width: 20%;text-align: left;border:none;\">\n {%- if row.dosage -%}{{ row.dosage }}{%- endif -%}\n </td>\n \t<td style=\"width: 20%;text-align: left;border:none;\">\n {%- if row.period -%}{{ row.period }}{%- endif -%}\n\t\t </td>\n <td style=\"width: 30%;text-align: left;border:none;\">\n\t\t\t <div style=\"border: 0px;\">\n {%- if row.comment -%}{{ row.comment }}{%- endif -%}\n </div>\n\t\t </td>\n </tr>\n\t {%- endfor -%}\n </tbody>\n </table>\n\n\n {%- endif -%}\n</div>\n\n\n<div>\n {% if doc.lab_test_prescription %}\n Investigations,\n <table class=\"table\">\n <tbody>\n <!--<tr>\n <th>Test</th>\n <th>Remark</th>\n </tr>-->\n\n {%- for row in doc.lab_test_prescription -%}\n <tr>\n <td style=\"width: 30%;border:none;\">\n {%- if row.lab_test_name -%}<b>{{ row.lab_test_name }}</b>{%- endif -%}\n </td>\n <td style=\"width: 30%;text-align: left;border:none;\">\n\t\t\t <div style=\"border: 0px;\">\n {%- if row.lab_test_comment -%}{{ row.lab_test_comment }}{%- endif -%}\n </div>\n\t\t </td>\n </tr>\n\n\t {%- endfor -%}\n </tbody>\n </table>\n\n\n {%- endif -%}\n</div>\n<div>\n {% if doc.encounter_comment %}\n <br>\n {{doc.encounter_comment}}\n {%- endif -%}\n</div>\n",
- "idx": 0,
- "line_breaks": 0,
- "modified": "2018-09-04 11:52:54.473702",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Encounter Print",
- "owner": "Administrator",
- "print_format_builder": 0,
- "print_format_type": "Server",
- "show_section_headings": 0,
+ "align_labels_right": 0,
+ "creation": "2017-04-10 14:05:53.355863",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "Patient Encounter",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "<div >\n {% if letter_head and not no_letterhead -%}\n <div class=\"letter-head\">{{ letter_head }}</div>\n <hr>\n {% else %}\n <div align=\"right\">\n <h1>{{doc.name}}</h1>\n </div>\n {%- endif %}\n <div class=\"row section-break\">\n <div class=\"col-xs-6 column-break\">\n {% if doc.appointment %}\n\t <div class=\"row\">\n\t\t\t<div class=\"col-xs-4 text-left\">\n\t\t\t<label>Appointment</label>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-7 value\">\n\t\t\t<strong>: </strong>{{doc.appointment}}\n\t\t\t</div>\n\t\t</div>\n\t\t{%- endif -%}\n\n <div class=\"row\">\n\t\t <div class=\"col-xs-4 text-left\">\n\t\t\t <label>Patient</label>\n\t\t </div>\n {% if doc.patient %}\n\t\t <div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong>{{doc.patient}}\n\t\t </div>\n {% else %}\n <div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong><em>Patient Name</em>\n\t\t </div>\n {%- endif -%}\n\t\t</div>\n\t <div class=\"row\">\n\t\t\t<div class=\"col-xs-4 text-left\">\n\t\t\t\t<label>Age</label>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong> {{doc.patient_age}}\n\t\t\t</div>\n\t\t</div>\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n\t\t\t\t<label>Gender</label>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-7 value\">\n\t\t\t <strong>: </strong> {{doc.patient_sex}}\n\t\t\t</div>\n </div>\n\n </div>\n <div class=\"col-xs-6 column-break\">\n\n <div class=\"row\">\n\t <div class=\"col-xs-4 text-left\">\n\t\t <label>Healthcare Practitioner</label>\n\t </div>\n {% if doc.practitioner %}\n\t <div class=\"col-xs-7 text-left value\">\n\t\t\t<strong>: </strong>{{doc.practitioner}}\n\t </div>\n {%- endif -%}\n\t</div>\n\n {% if doc.encounter_date %}\n\t <div class=\"row\">\n\t\t<div class=\"col-xs-4 text-left\">\n\t\t<label>Date</label>\n\t\t</div>\n\t\t<div class=\"col-xs-7 text-left value\">\n\t\t<strong>: </strong>{{doc.encounter_date}}\n\t\t</div>\n </div>\n\t {%- endif -%}\n {% if doc.encounter_time %}\n\t <div class=\"row\">\n\t\t<div class=\"col-xs-4 text-left\">\n\t\t<label>Time</label>\n\t\t</div>\n\t\t<div class=\"col-xs-7 text-left value\">\n\t\t<strong>: </strong>{{doc.encounter_time}}\n\t\t</div>\n </div>\n\t {%- endif -%}\n {% if doc.medical_department %}\n\t <div class=\"row\">\n\t\t<div class=\"col-xs-4 text-left\">\n\t\t<label>Department</label>\n\t\t</div>\n\t\t<div class=\"col-xs-7 text-left value\">\n\t\t<strong>: </strong>{{doc.visit_department}}\n\t\t</div>\n </div>\n {%- endif -%}\n </div>\n\n </div>\n\n</div>\n<div>\n <hr>\n {% if doc.symptoms_in_print%}\n {% if doc.symptoms %}\n Complaints:\n <strong>{{doc.symptoms}}</strong>\n \t <br>\n {%- endif -%}\n {%- endif -%}\n\n {% if doc.diagnosis_in_print%}\n {% if doc.diagnosis %}\n \t Diagnosis:\n <strong>{{doc.diagnosis}}</strong>\n <br>\n {%- endif -%}\n {%- endif -%}\n\n</div>\n\n<div>\n {% if doc.drug_prescription %}\n <br>\n Rx,\n <table class=\"table\">\n <tbody>\n <!--<tr>\n <th>Drug</th>\n <th class=\"text-left\">Dosage</th>\n <th class=\"text-left\">Period</th>\n <th>Remark</th>\n </tr>-->\n\n {%- for row in doc.drug_prescription -%}\n <tr>\n <td style=\"width: 30%;border:none;\">\n {%- if row.drug_name -%}<b>{{ row.drug_name }}</b>{%- endif -%}\n </td>\n \t<td style=\"width: 20%;text-align: left;border:none;\">\n {%- if row.dosage -%}{{ row.dosage }}{%- endif -%}\n </td>\n \t<td style=\"width: 20%;text-align: left;border:none;\">\n {%- if row.period -%}{{ row.period }}{%- endif -%}\n\t\t </td>\n <td style=\"width: 30%;text-align: left;border:none;\">\n\t\t\t <div style=\"border: 0px;\">\n {%- if row.comment -%}{{ row.comment }}{%- endif -%}\n </div>\n\t\t </td>\n </tr>\n\t {%- endfor -%}\n </tbody>\n </table>\n\n\n {%- endif -%}\n</div>\n\n\n<div>\n {% if doc.lab_test_prescription %}\n Investigations,\n <table class=\"table\">\n <tbody>\n <!--<tr>\n <th>Test</th>\n <th>Remark</th>\n </tr>-->\n\n {%- for row in doc.lab_test_prescription -%}\n <tr>\n <td style=\"width: 30%;border:none;\">\n {%- if row.lab_test_name -%}<b>{{ row.lab_test_name }}</b>{%- endif -%}\n </td>\n <td style=\"width: 30%;text-align: left;border:none;\">\n\t\t\t <div style=\"border: 0px;\">\n {%- if row.lab_test_comment -%}{{ row.lab_test_comment }}{%- endif -%}\n </div>\n\t\t </td>\n </tr>\n\n\t {%- endfor -%}\n </tbody>\n </table>\n\n\n {%- endif -%}\n</div>\n<div>\n {% if doc.encounter_comment %}\n <br>\n {{doc.encounter_comment}}\n {%- endif -%}\n</div>\n",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2018-09-04 11:52:54.473702",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Encounter Print",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Server",
+ "show_section_headings": 0,
"standard": "Yes"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json b/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
index 6badc6f..e8e95d8 100644
--- a/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
+++ b/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
@@ -1,22 +1,22 @@
{
- "align_labels_right": 0,
- "creation": "2017-04-24 15:38:45.332473",
- "custom_format": 1,
- "disabled": 0,
- "doc_type": "Lab Test",
- "docstatus": 0,
- "doctype": "Print Format",
- "font": "Default",
- "html": "<div >\n {% if letter_head and not no_letterhead -%}\n <div class=\"letter-head\">{{ letter_head }}</div>\n <hr>\n {%- endif %}\n\n {% if (doc.docstatus != 1) %}\n <b>Lab Tests have to be Submitted for Print .. !</b>\n {% elif (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"require_test_result_approval\") == '1' and doc.approval_status != \"Approved\") %}\n <b>Lab Tests have to be Approved for Print .. !</b>\n {%- else -%}\n <div class=\"row section-break\">\n <div class=\"col-xs-6 column-break\">\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Patient</label>\n </div>\n {% if doc.patient %}\n <div class=\"col-xs-7 value\">\n <strong>: </strong>{{doc.patient}}\n </div>\n {% else %}\n <div class=\"col-xs-7 value\">\n <strong>: </strong><em>Patient Name</em>\n </div>\n {%- endif -%}\n </div>\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Age</label>\n </div>\n <div class=\"col-xs-7 value\">\n <strong>: </strong> {{doc.patient_age}}\n </div>\n </div>\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Gender</label>\n </div>\n <div class=\"col-xs-7 value\">\n <strong>: </strong> {{doc.patient_sex}}\n </div>\n </div>\n\n </div>\n\n <div class=\"col-xs-6 column-break\">\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Practitioner</label>\n </div>\n {% if doc.practitioner %}\n <div class=\"col-xs-7 text-left value\">\n <strong>: </strong>{{doc.practitioner}}\n </div>\n {%- endif -%}\n </div>\n\n {% if doc.sample_date %}\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Sample Date</label>\n </div>\n <div class=\"col-xs-7 text-left value\">\n <strong>: </strong>{{doc.sample_date}}\n </div>\n </div>\n {%- endif -%}\n\n {% if doc.result_date %}\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Result Date</label>\n </div>\n <div class=\"col-xs-7 text-left value\">\n <strong>: </strong>{{doc.result_date}}\n </div>\n </div>\n {%- endif -%}\n\n </div>\n\n </div>\n\n <div align=\"center\">\n <hr><h4 class=\"text-uppercase\"><b><u>Department of {{doc.department}}</u></b></h4>\n </div>\n\n <table class=\"table\">\n <tbody>\n {%- if doc.normal_test_items -%}\n <tr>\n <th>Name of Test</th>\n <th class=\"text-left\">Result</th>\n <th class=\"text-right\">Normal Range</th>\n </tr>\n\n {%- if doc.normal_test_items|length > 1 %}\n <tr><td style=\"width: 40%;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n {%- endif -%}\n\n {%- for row in doc.normal_test_items -%}\n <tr>\n <td style=\"width: 40%;border:none;\">\n {%- if doc.normal_test_items|length > 1 %}  {%- endif -%}\n {%- if row.lab_test_name -%}<b>{{ row.lab_test_name }}</b>\n {%- else -%}   {%- endif -%}\n {%- if row.lab_test_event -%}   {{ row.lab_test_event }}{%- endif -%}\n </td>\n\n <td style=\"width: 20%;text-align: left;border:none;\">\n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%} \n {%- if row.lab_test_uom -%}{{ row.lab_test_uom }}{%- endif -%}\n </td>\n\n <td style=\"width: 30%;text-align: right;border:none;\">\n <div style=\"border: 0px;\">\n {%- if row.normal_range -%}{{ row.normal_range }}{%- endif -%}\n </div>\n </td>\n </tr>\n\n {%- endfor -%}\n {%- endif -%}\n </tbody>\n </table>\n\n <table class=\"table\">\n <tbody>\n {%- if doc.special_test_items -%}\n <tr>\n <th>Name of Test</th>\n <th class=\"text-left\">Result</th>\n </tr>\n <tr><td style=\"width: 30%;border:none;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n {%- for row in doc.special_test_items -%}\n <tr>\n <td style=\"width: 30%;border:none;\">   {{ row.lab_test_particulars }} </td>\n <td style=\"width: 70%;text-align: left;border:none;\">\n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%}\n </td>\n </tr>\n\n {%- endfor -%}\n {%- endif -%}\n\n {%- if doc.sensitivity_test_items -%}\n <tr>\n <th>Antibiotic</th>\n <th class=\"text-left\">Sensitivity</th>\n </tr>\n {%- for row in doc.sensitivity_test_items -%}\n <tr>\n <td style=\"width: 30%;border:none;\"> {{ row.antibiotic }} </td>\n <td style=\"width: 70%;text-align: left;border:none;\">{{ row.antibiotic_sensitivity }}</td>\n </tr>\n\n {%- endfor -%}\n {%- endif -%}\n\n </tbody>\n </table>\n {%- endif -%}\n\n <div align=\"right\">\n {%- if (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"employee_name_and_designation_in_print\") == '1') -%}\n <h6 class=\"text-uppercase\"><b>{{doc.employee_name}}</b></h6>\n <h6 class=\"text-uppercase\"><b>{{doc.employee_designation}}</b></h6>\n {%- else -%}\n <h6 ><b>{{frappe.db.get_value(\"Healthcare Settings\", \"None\", \"custom_signature_in_print\") }}</b></h6>\n {%- endif -%}\n </div>\n</div>\n",
- "idx": 0,
- "line_breaks": 0,
- "modified": "2018-09-04 12:03:47.066918",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Lab Test Print",
- "owner": "Administrator",
- "print_format_builder": 0,
- "print_format_type": "Server",
- "show_section_headings": 0,
+ "align_labels_right": 0,
+ "creation": "2017-04-24 15:38:45.332473",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "Lab Test",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "<div >\n {% if letter_head and not no_letterhead -%}\n <div class=\"letter-head\">{{ letter_head }}</div>\n <hr>\n {%- endif %}\n\n {% if (doc.docstatus != 1) %}\n <b>Lab Tests have to be Submitted for Print .. !</b>\n {% elif (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"lab_test_approval_required\") == '1' and doc.approval_status != \"Approved\") %}\n <b>Lab Tests have to be Approved for Print .. !</b>\n {%- else -%}\n <div class=\"row section-break\">\n <div class=\"col-xs-6 column-break\">\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Patient</label>\n </div>\n {% if doc.patient %}\n <div class=\"col-xs-7 value\">\n <strong>: </strong>{{doc.patient}}\n </div>\n {% else %}\n <div class=\"col-xs-7 value\">\n <strong>: </strong><em>Patient Name</em>\n </div>\n {%- endif -%}\n </div>\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Age</label>\n </div>\n <div class=\"col-xs-7 value\">\n <strong>: </strong> {{doc.patient_age}}\n </div>\n </div>\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Gender</label>\n </div>\n <div class=\"col-xs-7 value\">\n <strong>: </strong> {{doc.patient_sex}}\n </div>\n </div>\n\n </div>\n\n <div class=\"col-xs-6 column-break\">\n\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Practitioner</label>\n </div>\n {% if doc.practitioner %}\n <div class=\"col-xs-7 text-left value\">\n <strong>: </strong>{{doc.practitioner}}\n </div>\n {%- endif -%}\n </div>\n\n {% if doc.sample_date %}\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Sample Date</label>\n </div>\n <div class=\"col-xs-7 text-left value\">\n <strong>: </strong>{{doc.sample_date}}\n </div>\n </div>\n {%- endif -%}\n\n {% if doc.result_date %}\n <div class=\"row\">\n <div class=\"col-xs-4 text-left\">\n <label>Result Date</label>\n </div>\n <div class=\"col-xs-7 text-left value\">\n <strong>: </strong>{{doc.result_date}}\n </div>\n </div>\n {%- endif -%}\n\n </div>\n\n </div>\n\n <div align=\"center\">\n <hr><h4 class=\"text-uppercase\"><b><u>Department of {{doc.department}}</u></b></h4>\n </div>\n\n <table class=\"table\">\n <tbody>\n {%- if doc.normal_test_items -%}\n <tr>\n <th>Name of Test</th>\n <th class=\"text-left\">Result</th>\n <th class=\"text-right\">Normal Range</th>\n </tr>\n\n {%- if doc.normal_test_items|length > 1 %}\n <tr><td style=\"width: 40%;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n {%- endif -%}\n\n {%- for row in doc.normal_test_items -%}\n <tr>\n <td style=\"width: 40%;border:none;\">\n {%- if doc.normal_test_items|length > 1 %}  {%- endif -%}\n {%- if row.lab_test_name -%}<b>{{ row.lab_test_name }}</b>\n {%- else -%}   {%- endif -%}\n {%- if row.lab_test_event -%}   {{ row.lab_test_event }}{%- endif -%}\n </td>\n\n <td style=\"width: 20%;text-align: left;border:none;\">\n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%} \n {%- if row.lab_test_uom -%}{{ row.lab_test_uom }}{%- endif -%}\n </td>\n\n <td style=\"width: 30%;text-align: right;border:none;\">\n <div style=\"border: 0px;\">\n {%- if row.normal_range -%}{{ row.normal_range }}{%- endif -%}\n </div>\n </td>\n </tr>\n\n {%- endfor -%}\n {%- endif -%}\n </tbody>\n </table>\n\n <table class=\"table\">\n <tbody>\n {%- if doc.special_test_items -%}\n <tr>\n <th>Name of Test</th>\n <th class=\"text-left\">Result</th>\n </tr>\n <tr><td style=\"width: 30%;border:none;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n {%- for row in doc.special_test_items -%}\n <tr>\n <td style=\"width: 30%;border:none;\">   {{ row.lab_test_particulars }} </td>\n <td style=\"width: 70%;text-align: left;border:none;\">\n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%}\n </td>\n </tr>\n\n {%- endfor -%}\n {%- endif -%}\n\n {%- if doc.sensitivity_test_items -%}\n <tr>\n <th>Antibiotic</th>\n <th class=\"text-left\">Sensitivity</th>\n </tr>\n {%- for row in doc.sensitivity_test_items -%}\n <tr>\n <td style=\"width: 30%;border:none;\"> {{ row.antibiotic }} </td>\n <td style=\"width: 70%;text-align: left;border:none;\">{{ row.antibiotic_sensitivity }}</td>\n </tr>\n\n {%- endfor -%}\n {%- endif -%}\n\n </tbody>\n </table>\n {%- endif -%}\n\n <div align=\"right\">\n {%- if (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"employee_name_and_designation_in_print\") == '1') -%}\n <h6 class=\"text-uppercase\"><b>{{doc.employee_name}}</b></h6>\n <h6 class=\"text-uppercase\"><b>{{doc.employee_designation}}</b></h6>\n {%- else -%}\n <h6 ><b>{{frappe.db.get_value(\"Healthcare Settings\", \"None\", \"custom_signature_in_print\") }}</b></h6>\n {%- endif -%}\n </div>\n</div>\n",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2018-09-04 12:03:47.066918",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Lab Test Print",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Server",
+ "show_section_headings": 0,
"standard": "Yes"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/page/appointment_analytic/__init__.py b/erpnext/healthcare/report/patient_appointment_analytics/__init__.py
similarity index 100%
copy from erpnext/healthcare/page/appointment_analytic/__init__.py
copy to erpnext/healthcare/report/patient_appointment_analytics/__init__.py
diff --git a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.js b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.js
new file mode 100644
index 0000000..18d252e
--- /dev/null
+++ b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.js
@@ -0,0 +1,128 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports['Patient Appointment Analytics'] = {
+ "filters": [
+ {
+ fieldname: 'tree_type',
+ label: __('Tree Type'),
+ fieldtype: 'Select',
+ options: ['Healthcare Practitioner', 'Medical Department'],
+ default: 'Healthcare Practitioner',
+ reqd: 1
+ },
+ {
+ fieldname: 'status',
+ label: __('Appointment Status'),
+ fieldtype: 'Select',
+ options:[
+ {label: __('Scheduled'), value: 'Scheduled'},
+ {label: __('Open'), value: 'Open'},
+ {label: __('Closed'), value: 'Closed'},
+ {label: __('Expired'), value: 'Expired'},
+ {label: __('Cancelled'), value: 'Cancelled'}
+ ]
+ },
+ {
+ fieldname: 'appointment_type',
+ label: __('Appointment Type'),
+ fieldtype: 'Link',
+ options: 'Appointment Type'
+ },
+ {
+ fieldname: 'practitioner',
+ label: __('Healthcare Practitioner'),
+ fieldtype: 'Link',
+ options: 'Healthcare Practitioner'
+ },
+ {
+ fieldname: 'department',
+ label: __('Medical Department'),
+ fieldtype: 'Link',
+ options: 'Medical Department'
+ },
+ {
+ fieldname: 'from_date',
+ label: __('From Date'),
+ fieldtype: 'Date',
+ default: frappe.defaults.get_user_default('year_start_date'),
+ reqd: 1
+ },
+ {
+ fieldname: 'to_date',
+ label: __('To Date'),
+ fieldtype: 'Date',
+ default: frappe.defaults.get_user_default('year_end_date'),
+ reqd: 1
+ },
+ {
+ fieldname: 'range',
+ label: __('Range'),
+ fieldtype: 'Select',
+ options:[
+ {label: __('Weekly'), value: 'Weekly'},
+ {label: __('Monthly'), value: 'Monthly'},
+ {label: __('Quarterly'), value: 'Quarterly'},
+ {label: __('Yearly'), value: 'Yearly'}
+ ],
+ default: 'Monthly',
+ reqd: 1
+ }
+ ],
+ after_datatable_render: function(datatable_obj) {
+ $(datatable_obj.wrapper).find(".dt-row-0").find('input[type=checkbox]').click();
+ },
+ get_datatable_options(options) {
+ return Object.assign(options, {
+ checkboxColumn: true,
+ events: {
+ onCheckRow: function(data) {
+ row_name = data[2].content;
+ length = data.length;
+
+ row_values = data.slice(3,length-1).map(function (column) {
+ return column.content;
+ })
+
+ entry = {
+ 'name': row_name,
+ 'values': row_values
+ }
+
+ let raw_data = frappe.query_report.chart.data;
+ let new_datasets = raw_data.datasets;
+
+ let found = false;
+ for (let i=0; i < new_datasets.length;i++) {
+ if (new_datasets[i].name == row_name) {
+ found = true;
+ new_datasets.splice(i,1);
+ break;
+ }
+ }
+
+ if (!found) {
+ new_datasets.push(entry);
+ }
+
+ let new_data = {
+ labels: raw_data.labels,
+ datasets: new_datasets
+ }
+
+ setTimeout(() => {
+ frappe.query_report.chart.update(new_data)
+ }, 500)
+
+
+ setTimeout(() => {
+ frappe.query_report.chart.draw(true);
+ }, 1000)
+
+ frappe.query_report.raw_chart_data = new_data;
+ },
+ }
+ })
+ },
+};
diff --git a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.json b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.json
new file mode 100644
index 0000000..64750c0
--- /dev/null
+++ b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.json
@@ -0,0 +1,36 @@
+{
+ "add_total_row": 1,
+ "creation": "2020-03-02 15:13:16.273493",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-03-02 15:13:16.273493",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Appointment Analytics",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Patient Appointment",
+ "report_name": "Patient Appointment Analytics",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Healthcare Administrator"
+ },
+ {
+ "role": "LabTest Approver"
+ },
+ {
+ "role": "Physician"
+ },
+ {
+ "role": "Nursing User"
+ },
+ {
+ "role": "Laboratory User"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py
new file mode 100644
index 0000000..9c35dbb
--- /dev/null
+++ b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py
@@ -0,0 +1,194 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import getdate, flt, add_to_date, add_days
+from frappe import _ , scrub
+from six import iteritems
+from erpnext.accounts.utils import get_fiscal_year
+
+def execute(filters=None):
+ return Analytics(filters).run()
+
+class Analytics(object):
+ def __init__(self, filters=None):
+ """Patient Appointment Analytics Report."""
+ self.filters = frappe._dict(filters or {})
+ self.months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+ self.get_period_date_ranges()
+
+ def run(self):
+ self.get_columns()
+ self.get_data()
+ self.get_chart_data()
+
+ return self.columns, self.data, None, self.chart
+
+ def get_period_date_ranges(self):
+ from dateutil.relativedelta import relativedelta, MO
+ from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date)
+
+ increment = {
+ 'Monthly': 1,
+ 'Quarterly': 3,
+ 'Half-Yearly': 6,
+ 'Yearly': 12
+ }.get(self.filters.range, 1)
+
+ if self.filters.range in ['Monthly', 'Quarterly']:
+ from_date = from_date.replace(day=1)
+ elif self.filters.range == 'Yearly':
+ from_date = get_fiscal_year(from_date)[1]
+ else:
+ from_date = from_date + relativedelta(from_date, weekday=MO(-1))
+
+ self.periodic_daterange = []
+ for dummy in range(1, 53):
+ if self.filters.range == 'Weekly':
+ period_end_date = add_days(from_date, 6)
+ else:
+ period_end_date = add_to_date(from_date, months=increment, days=-1)
+
+ if period_end_date > to_date:
+ period_end_date = to_date
+
+ self.periodic_daterange.append(period_end_date)
+
+ from_date = add_days(period_end_date, 1)
+ if period_end_date == to_date:
+ break
+
+ def get_columns(self):
+ self.columns = []
+
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ self.columns.append({
+ 'label': _('Healthcare Practitioner'),
+ 'options': 'Healthcare Practitioner',
+ 'fieldname': 'practitioner',
+ 'fieldtype': 'Link',
+ 'width': 200
+ })
+
+ elif self.filters.tree_type == 'Medical Department':
+ self.columns.append({
+ 'label': _('Medical Department'),
+ 'fieldname': 'department',
+ 'fieldtype': 'Link',
+ 'options': 'Medical Department',
+ 'width': 150
+ })
+
+ for end_date in self.periodic_daterange:
+ period = self.get_period(end_date)
+ self.columns.append({
+ 'label': _(period),
+ 'fieldname': scrub(period),
+ 'fieldtype': 'Int',
+ 'width': 120
+ })
+
+ self.columns.append({
+ 'label': _('Total'),
+ 'fieldname': 'total',
+ 'fieldtype': 'Int',
+ 'width': 120
+ })
+
+ def get_data(self):
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ self.get_appointments_based_on_healthcare_practitioner()
+ self.get_rows()
+
+ elif self.filters.tree_type == 'Medical Department':
+ self.get_appointments_based_on_medical_department()
+ self.get_rows()
+
+ def get_period(self, appointment_date):
+ if self.filters.range == 'Weekly':
+ period = 'Week ' + str(appointment_date.isocalendar()[1])
+ elif self.filters.range == 'Monthly':
+ period = str(self.months[appointment_date.month - 1])
+ elif self.filters.range == 'Quarterly':
+ period = 'Quarter ' + str(((appointment_date.month - 1) // 3) + 1)
+ else:
+ year = get_fiscal_year(appointment_date, company=self.filters.company)
+ period = str(year[0])
+
+ if getdate(self.filters.from_date).year != getdate(self.filters.to_date).year:
+ period += ' ' + str(appointment_date.year)
+
+ return period
+
+ def get_appointments_based_on_healthcare_practitioner(self):
+ filters = self.get_common_filters()
+
+ self.entries = frappe.db.get_all('Patient Appointment',
+ fields=['appointment_date', 'name', 'patient', 'practitioner'],
+ filters=filters
+ )
+
+ def get_appointments_based_on_medical_department(self):
+ filters = self.get_common_filters()
+ if not filters.get('department'):
+ filters['department'] = ('!=', '')
+
+ self.entries = frappe.db.get_all('Patient Appointment',
+ fields=['appointment_date', 'name', 'patient', 'practitioner', 'department'],
+ filters=filters
+ )
+
+ def get_common_filters(self):
+ filters = {}
+ filters['appointment_date'] = ('between', [self.filters.from_date, self.filters.to_date])
+ for entry in ['appointment_type', 'practitioner', 'department', 'status']:
+ if self.filters.get(entry):
+ filters[entry] = self.filters.get(entry)
+
+ return filters
+
+ def get_rows(self):
+ self.data = []
+ self.get_periodic_data()
+
+ for entity, period_data in iteritems(self.appointment_periodic_data):
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ row = {'practitioner': entity}
+ elif self.filters.tree_type == 'Medical Department':
+ row = {'department': entity}
+
+ total = 0
+ for end_date in self.periodic_daterange:
+ period = self.get_period(end_date)
+ amount = flt(period_data.get(period, 0.0))
+ row[scrub(period)] = amount
+ total += amount
+
+ row['total'] = total
+
+ self.data.append(row)
+
+ def get_periodic_data(self):
+ self.appointment_periodic_data = frappe._dict()
+
+ for d in self.entries:
+ period = self.get_period(d.get('appointment_date'))
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ self.appointment_periodic_data.setdefault(d.practitioner, frappe._dict()).setdefault(period, 0.0)
+ self.appointment_periodic_data[d.practitioner][period] += 1
+
+ elif self.filters.tree_type == 'Medical Department':
+ self.appointment_periodic_data.setdefault(d.department, frappe._dict()).setdefault(period, 0.0)
+ self.appointment_periodic_data[d.department][period] += 1
+
+ def get_chart_data(self):
+ length = len(self.columns)
+ labels = [d.get("label") for d in self.columns[1:length - 1]]
+ self.chart = {
+ "data": {
+ 'labels': labels,
+ 'datasets': []
+ },
+ "type": "line"
+ }
\ No newline at end of file
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index 97bb98f..246242a 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -4,417 +4,471 @@
from __future__ import unicode_literals
import frappe
-import datetime
from frappe import _
import math
-from frappe.utils import time_diff_in_hours, rounded, getdate, add_days
+from frappe.utils import time_diff_in_hours, rounded
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account
-from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity, update_fee_validity
+from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
@frappe.whitelist()
def get_healthcare_services_to_invoice(patient):
- patient = frappe.get_doc("Patient", patient)
+ patient = frappe.get_doc('Patient', patient)
if patient:
- if patient.customer:
- item_to_invoice = []
- patient_appointments = frappe.get_list("Patient Appointment",{'patient': patient.name, 'invoiced': False},
- order_by="appointment_date")
- if patient_appointments:
- fee_validity_details = []
- valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
- max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
- for patient_appointment in patient_appointments:
- patient_appointment_obj = frappe.get_doc("Patient Appointment", patient_appointment['name'])
+ validate_customer_created(patient)
+ items_to_invoice = []
+ patient_appointments = frappe.get_list(
+ 'Patient Appointment',
+ fields='*',
+ filters={'patient': patient.name, 'invoiced': 0},
+ order_by='appointment_date'
+ )
+ if patient_appointments:
+ items_to_invoice = get_fee_validity(patient_appointments)
- if patient_appointment_obj.procedure_template:
- if frappe.db.get_value("Clinical Procedure Template", patient_appointment_obj.procedure_template, "is_billable") == 1:
- item_to_invoice.append({'reference_type': 'Patient Appointment', 'reference_name': patient_appointment_obj.name, 'service': patient_appointment_obj.procedure_template})
- else:
- practitioner_exist_in_list = False
- skip_invoice = False
- if fee_validity_details:
- for validity in fee_validity_details:
- if validity['practitioner'] == patient_appointment_obj.practitioner:
- practitioner_exist_in_list = True
- if validity['valid_till'] >= patient_appointment_obj.appointment_date:
- validity['visits'] = validity['visits']+1
- if int(max_visit) > validity['visits']:
- skip_invoice = True
- if not skip_invoice:
- validity['visits'] = 1
- validity['valid_till'] = patient_appointment_obj.appointment_date + datetime.timedelta(days=int(valid_days))
- if not practitioner_exist_in_list:
- valid_till = patient_appointment_obj.appointment_date + datetime.timedelta(days=int(valid_days))
- visits = 0
- validity_exist = validity_exists(patient_appointment_obj.practitioner, patient_appointment_obj.patient)
- if validity_exist:
- fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
- valid_till = fee_validity.valid_till
- visits = fee_validity.visited
- fee_validity_details.append({'practitioner': patient_appointment_obj.practitioner,
- 'valid_till': valid_till, 'visits': visits})
+ encounters = get_encounters_to_invoice(patient)
+ lab_tests = get_lab_tests_to_invoice(patient)
+ clinical_procedures = get_clinical_procedures_to_invoice(patient)
+ inpatient_services = get_inpatient_services_to_invoice(patient)
- if not skip_invoice:
- practitioner_charge = 0
- income_account = None
- service_item = None
- if patient_appointment_obj.practitioner:
- service_item, practitioner_charge = service_item_and_practitioner_charge(patient_appointment_obj)
- income_account = get_income_account(patient_appointment_obj.practitioner, patient_appointment_obj.company)
- item_to_invoice.append({'reference_type': 'Patient Appointment', 'reference_name': patient_appointment_obj.name,
- 'service': service_item, 'rate': practitioner_charge,
- 'income_account': income_account})
+ items_to_invoice += encounters + lab_tests + clinical_procedures + inpatient_services
+ return items_to_invoice
- encounters = frappe.get_list("Patient Encounter", {'patient': patient.name, 'invoiced': False, 'docstatus': 1})
- if encounters:
- for encounter in encounters:
- encounter_obj = frappe.get_doc("Patient Encounter", encounter['name'])
- if not encounter_obj.appointment:
- practitioner_charge = 0
- income_account = None
- service_item = None
- if encounter_obj.practitioner:
- service_item, practitioner_charge = service_item_and_practitioner_charge(encounter_obj)
- income_account = get_income_account(encounter_obj.practitioner, encounter_obj.company)
+def validate_customer_created(patient):
+ if not frappe.db.get_value('Patient', patient.name, 'customer'):
+ msg = _("Please set a Customer linked to the Patient")
+ msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(patient.name)
+ frappe.throw(msg, title=_('Customer Not Found'))
- item_to_invoice.append({'reference_type': 'Patient Encounter', 'reference_name': encounter_obj.name,
- 'service': service_item, 'rate': practitioner_charge,
- 'income_account': income_account})
+def get_fee_validity(patient_appointments):
+ if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
+ return
- lab_tests = frappe.get_list("Lab Test", {'patient': patient.name, 'invoiced': False, 'docstatus': 1})
- if lab_tests:
- for lab_test in lab_tests:
- lab_test_obj = frappe.get_doc("Lab Test", lab_test['name'])
- if frappe.db.get_value("Lab Test Template", lab_test_obj.template, "is_billable") == 1:
- item_to_invoice.append({'reference_type': 'Lab Test', 'reference_name': lab_test_obj.name,
- 'service': frappe.db.get_value("Lab Test Template", lab_test_obj.template, "item")})
-
- lab_rxs = frappe.db.sql("""select lp.name from `tabPatient Encounter` et, `tabLab Prescription` lp
- where et.patient=%s and lp.parent=et.name and lp.lab_test_created=0 and lp.invoiced=0""", (patient.name))
- if lab_rxs:
- for lab_rx in lab_rxs:
- rx_obj = frappe.get_doc("Lab Prescription", lab_rx[0])
- if rx_obj.lab_test_code and (frappe.db.get_value("Lab Test Template", rx_obj.lab_test_code, "is_billable") == 1):
- item_to_invoice.append({'reference_type': 'Lab Prescription', 'reference_name': rx_obj.name,
- 'service': frappe.db.get_value("Lab Test Template", rx_obj.lab_test_code, "item")})
-
- procedures = frappe.get_list("Clinical Procedure", {'patient': patient.name, 'invoiced': False})
- if procedures:
- for procedure in procedures:
- procedure_obj = frappe.get_doc("Clinical Procedure", procedure['name'])
- if not procedure_obj.appointment:
- if procedure_obj.procedure_template and (frappe.db.get_value("Clinical Procedure Template", procedure_obj.procedure_template, "is_billable") == 1):
- item_to_invoice.append({'reference_type': 'Clinical Procedure', 'reference_name': procedure_obj.name,
- 'service': frappe.db.get_value("Clinical Procedure Template", procedure_obj.procedure_template, "item")})
-
- procedure_rxs = frappe.db.sql("""select pp.name from `tabPatient Encounter` et,
- `tabProcedure Prescription` pp where et.patient=%s and pp.parent=et.name and
- pp.procedure_created=0 and pp.invoiced=0 and pp.appointment_booked=0""", (patient.name))
- if procedure_rxs:
- for procedure_rx in procedure_rxs:
- rx_obj = frappe.get_doc("Procedure Prescription", procedure_rx[0])
- if frappe.db.get_value("Clinical Procedure Template", rx_obj.procedure, "is_billable") == 1:
- item_to_invoice.append({'reference_type': 'Procedure Prescription', 'reference_name': rx_obj.name,
- 'service': frappe.db.get_value("Clinical Procedure Template", rx_obj.procedure, "item")})
-
- procedures = frappe.get_list("Clinical Procedure",
- {'patient': patient.name, 'invoice_separately_as_consumables': True, 'consumption_invoiced': False,
- 'consume_stock': True, 'status': 'Completed'})
- if procedures:
- service_item = get_healthcare_service_item('clinical_procedure_consumable_item')
- if not service_item:
- msg = _(("Please Configure {0} in ").format("Clinical Procedure Consumable Item") \
- + """<b><a href="#Form/Healthcare Settings">Healthcare Settings</a></b>""")
- frappe.throw(msg)
- for procedure in procedures:
- procedure_obj = frappe.get_doc("Clinical Procedure", procedure['name'])
- item_to_invoice.append({'reference_type': 'Clinical Procedure', 'reference_name': procedure_obj.name,
- 'service': service_item, 'rate': procedure_obj.consumable_total_amount, 'description': procedure_obj.consumption_details})
-
- inpatient_services = frappe.db.sql("""select io.name, io.parent from `tabInpatient Record` ip,
- `tabInpatient Occupancy` io where ip.patient=%s and io.parent=ip.name and
- io.left=1 and io.invoiced=0""", (patient.name))
- if inpatient_services:
- for inpatient_service in inpatient_services:
- inpatient_occupancy = frappe.get_doc("Inpatient Occupancy", inpatient_service[0])
- service_unit_type = frappe.get_doc("Healthcare Service Unit Type", frappe.db.get_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "service_unit_type"))
- if service_unit_type and service_unit_type.is_billable == 1:
- hours_occupied = time_diff_in_hours(inpatient_occupancy.check_out, inpatient_occupancy.check_in)
- qty = 0.5
- if hours_occupied > 0:
- actual_qty = hours_occupied / service_unit_type.no_of_hours
- floor = math.floor(actual_qty)
- decimal_part = actual_qty - floor
- if decimal_part > 0.5:
- qty = rounded(floor + 1, 1)
- elif decimal_part < 0.5 and decimal_part > 0:
- qty = rounded(floor + 0.5, 1)
- if qty <= 0:
- qty = 0.5
- item_to_invoice.append({'reference_type': 'Inpatient Occupancy', 'reference_name': inpatient_occupancy.name,
- 'service': service_unit_type.item, 'qty': qty})
-
- return item_to_invoice
+ items_to_invoice = []
+ for appointment in patient_appointments:
+ if appointment.procedure_template:
+ if frappe.db.get_value('Clinical Procedure Template', appointment.procedure_template, 'is_billable'):
+ items_to_invoice.append({
+ 'reference_type': 'Patient Appointment',
+ 'reference_name': appointment.name,
+ 'service': appointment.procedure_template
+ })
else:
- frappe.throw(_("The Patient {0} do not have customer refrence to invoice").format(patient.name))
+ fee_validity = frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name})
+ if not fee_validity:
+ practitioner_charge = 0
+ income_account = None
+ service_item = None
+ if appointment.practitioner:
+ service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment)
+ income_account = get_income_account(appointment.practitioner, appointment.company)
+ items_to_invoice.append({
+ 'reference_type': 'Patient Appointment',
+ 'reference_name': appointment.name,
+ 'service': service_item,
+ 'rate': practitioner_charge,
+ 'income_account': income_account
+ })
-def service_item_and_practitioner_charge(doc):
- is_ip = doc_is_ip(doc)
- if is_ip:
- service_item = get_practitioner_service_item(doc.practitioner, "inpatient_visit_charge_item")
+ return items_to_invoice
+
+
+def get_encounters_to_invoice(patient):
+ encounters_to_invoice = []
+ encounters = frappe.get_list(
+ 'Patient Encounter',
+ fields=['*'],
+ filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
+ )
+ if encounters:
+ for encounter in encounters:
+ if not encounter.appointment:
+ practitioner_charge = 0
+ income_account = None
+ service_item = None
+ if encounter.practitioner:
+ service_item, practitioner_charge = get_service_item_and_practitioner_charge(encounter)
+ income_account = get_income_account(encounter.practitioner, encounter.company)
+
+ encounters_to_invoice.append({
+ 'reference_type': 'Patient Encounter',
+ 'reference_name': encounter.name,
+ 'service': service_item,
+ 'rate': practitioner_charge,
+ 'income_account': income_account
+ })
+
+ return encounters_to_invoice
+
+
+def get_lab_tests_to_invoice(patient):
+ lab_tests_to_invoice = []
+ lab_tests = frappe.get_list(
+ 'Lab Test',
+ fields=['name', 'template'],
+ filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
+ )
+ for lab_test in lab_tests:
+ item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.lab_test_code, ['item', 'is_billable'])
+ if is_billable:
+ lab_tests_to_invoice.append({
+ 'reference_type': 'Lab Test',
+ 'reference_name': lab_test.name,
+ 'service': item
+ })
+
+ lab_prescriptions = frappe.db.sql(
+ '''
+ SELECT
+ lp.name, lp.lab_test_code
+ FROM
+ `tabPatient Encounter` et, `tabLab Prescription` lp
+ WHERE
+ et.patient=%s
+ and lp.parent=et.name
+ and lp.lab_test_created=0
+ and lp.invoiced=0
+ ''', (patient.name), as_dict=1)
+
+ for prescription in lab_prescriptions:
+ item, is_billable = frappe.get_cached_value('Lab Test Template', prescription.lab_test_code, ['item', 'is_billable'])
+ if prescription.lab_test_code and is_billable:
+ lab_tests_to_invoice.append({
+ 'reference_type': 'Lab Prescription',
+ 'reference_name': prescription.name,
+ 'service': item
+ })
+
+ return lab_tests_to_invoice
+
+
+def get_clinical_procedures_to_invoice(patient):
+ clinical_procedures_to_invoice = []
+ procedures = frappe.get_list(
+ 'Clinical Procedure',
+ fields='*',
+ filters={'patient': patient.name, 'invoiced': False}
+ )
+ for procedure in procedures:
+ if not procedure.appointment:
+ item, is_billable = frappe.get_cached_value('Clinical Procedure Template', procedure.procedure_template, ['item', 'is_billable'])
+ if procedure.procedure_template and is_billable:
+ clinical_procedures_to_invoice.append({
+ 'reference_type': 'Clinical Procedure',
+ 'reference_name': procedure.name,
+ 'service': item
+ })
+
+ # consumables
+ if procedure.invoice_separately_as_consumables and procedure.consume_stock \
+ and procedure.status == 'Completed' and not procedure.consumption_invoiced:
+
+ service_item = get_healthcare_service_item('clinical_procedure_consumable_item')
+ if not service_item:
+ msg = _('Please Configure Clinical Procedure Consumable Item in ')
+ msg += '''<b><a href='#Form/Healthcare Settings'>Healthcare Settings</a></b>'''
+ frappe.throw(msg, title=_('Missing Configuration'))
+
+ clinical_procedures_to_invoice.append({
+ 'reference_type': 'Clinical Procedure',
+ 'reference_name': procedure.name,
+ 'service': service_item,
+ 'rate': procedure.consumable_total_amount,
+ 'description': procedure.consumption_details
+ })
+
+ procedure_prescriptions = frappe.db.sql(
+ '''
+ SELECT
+ pp.name, pp.procedure
+ FROM
+ `tabPatient Encounter` et, `tabProcedure Prescription` pp
+ WHERE
+ et.patient=%s
+ and pp.parent=et.name
+ and pp.procedure_created=0
+ and pp.invoiced=0
+ and pp.appointment_booked=0
+ ''', (patient.name), as_dict=1)
+
+ for prescription in procedure_prescriptions:
+ item, is_billable = frappe.get_cached_value('Clinical Procedure Template', prescription.procedure, ['item', 'is_billable'])
+ if is_billable:
+ clinical_procedures_to_invoice.append({
+ 'reference_type': 'Procedure Prescription',
+ 'reference_name': prescription.name,
+ 'service': item
+ })
+
+ return clinical_procedures_to_invoice
+
+
+def get_inpatient_services_to_invoice(patient):
+ services_to_invoice = []
+ inpatient_services = frappe.db.sql(
+ '''
+ SELECT
+ io.*
+ FROM
+ `tabInpatient Record` ip, `tabInpatient Occupancy` io
+ WHERE
+ ip.patient=%s
+ and io.parent=ip.name
+ and io.left=1
+ and io.invoiced=0
+ ''', (patient.name), as_dict=1)
+
+ for inpatient_occupancy in inpatient_services:
+ service_unit_type = frappe.db.get_value('Healthcare Service Unit', inpatient_occupancy.service_unit, 'service_unit_type')
+ service_unit_type = frappe.get_cached_doc('Healthcare Service Unit Type', service_unit_type)
+ if service_unit_type and service_unit_type.is_billable:
+ hours_occupied = time_diff_in_hours(inpatient_occupancy.check_out, inpatient_occupancy.check_in)
+ qty = 0.5
+ if hours_occupied > 0:
+ actual_qty = hours_occupied / service_unit_type.no_of_hours
+ floor = math.floor(actual_qty)
+ decimal_part = actual_qty - floor
+ if decimal_part > 0.5:
+ qty = rounded(floor + 1, 1)
+ elif decimal_part < 0.5 and decimal_part > 0:
+ qty = rounded(floor + 0.5, 1)
+ if qty <= 0:
+ qty = 0.5
+ services_to_invoice.append({
+ 'reference_type': 'Inpatient Occupancy',
+ 'reference_name': inpatient_occupancy.name,
+ 'service': service_unit_type.item, 'qty': qty
+ })
+
+ return services_to_invoice
+
+
+def get_service_item_and_practitioner_charge(doc):
+ is_inpatient = doc.inpatient_record
+ if is_inpatient:
+ service_item = get_practitioner_service_item(doc.practitioner, 'inpatient_visit_charge_item')
if not service_item:
- service_item = get_healthcare_service_item("inpatient_visit_charge_item")
+ service_item = get_healthcare_service_item('inpatient_visit_charge_item')
else:
- service_item = get_practitioner_service_item(doc.practitioner, "op_consulting_charge_item")
+ service_item = get_practitioner_service_item(doc.practitioner, 'op_consulting_charge_item')
if not service_item:
- service_item = get_healthcare_service_item("op_consulting_charge_item")
+ service_item = get_healthcare_service_item('op_consulting_charge_item')
if not service_item:
- throw_config_service_item(is_ip)
+ throw_config_service_item(is_inpatient)
- practitioner_charge = get_practitioner_charge(doc.practitioner, is_ip)
+ practitioner_charge = get_practitioner_charge(doc.practitioner, is_inpatient)
if not practitioner_charge:
- throw_config_practitioner_charge(is_ip, doc.practitioner)
+ throw_config_practitioner_charge(is_inpatient, doc.practitioner)
return service_item, practitioner_charge
-def throw_config_service_item(is_ip):
- service_item_lable = "Out Patient Consulting Charge Item"
- if is_ip:
- service_item_lable = "Inpatient Visit Charge Item"
- msg = _(("Please Configure {0} in ").format(service_item_lable) \
- + """<b><a href="#Form/Healthcare Settings">Healthcare Settings</a></b>""")
- frappe.throw(msg)
+def throw_config_service_item(is_inpatient):
+ service_item_label = _('Out Patient Consulting Charge Item')
+ if is_inpatient:
+ service_item_label = _('Inpatient Visit Charge Item')
-def throw_config_practitioner_charge(is_ip, practitioner):
- charge_name = "OP Consulting Charge"
- if is_ip:
- charge_name = "Inpatient Visit Charge"
+ msg = _(('Please Configure {0} in ').format(service_item_label) \
+ + '''<b><a href='#Form/Healthcare Settings'>Healthcare Settings</a></b>''')
+ frappe.throw(msg, title=_('Missing Configuration'))
- msg = _(("Please Configure {0} for Healthcare Practitioner").format(charge_name) \
- + """ <b><a href="#Form/Healthcare Practitioner/{0}">{0}</a></b>""".format(practitioner))
- frappe.throw(msg)
+
+def throw_config_practitioner_charge(is_inpatient, practitioner):
+ charge_name = _('OP Consulting Charge')
+ if is_inpatient:
+ charge_name = _('Inpatient Visit Charge')
+
+ msg = _(('Please Configure {0} for Healthcare Practitioner').format(charge_name) \
+ + ''' <b><a href='#Form/Healthcare Practitioner/{0}'>{0}</a></b>'''.format(practitioner))
+ frappe.throw(msg, title=_('Missing Configuration'))
+
def get_practitioner_service_item(practitioner, service_item_field):
- return frappe.db.get_value("Healthcare Practitioner", practitioner, service_item_field)
+ return frappe.db.get_value('Healthcare Practitioner', practitioner, service_item_field)
+
def get_healthcare_service_item(service_item_field):
- return frappe.db.get_value("Healthcare Settings", None, service_item_field)
+ return frappe.db.get_single_value('Healthcare Settings', service_item_field)
-def doc_is_ip(doc):
- is_ip = False
- if doc.inpatient_record:
- is_ip = True
- return is_ip
-def get_practitioner_charge(practitioner, is_ip):
- if is_ip:
- practitioner_charge = frappe.db.get_value("Healthcare Practitioner", practitioner, "inpatient_visit_charge")
+def get_practitioner_charge(practitioner, is_inpatient):
+ if is_inpatient:
+ practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'inpatient_visit_charge')
else:
- practitioner_charge = frappe.db.get_value("Healthcare Practitioner", practitioner, "op_consulting_charge")
+ practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'op_consulting_charge')
if practitioner_charge:
return practitioner_charge
return False
+
def manage_invoice_submit_cancel(doc, method):
if doc.items:
for item in doc.items:
- if item.get("reference_dt") and item.get("reference_dn"):
- if frappe.get_meta(item.reference_dt).has_field("invoiced"):
+ if item.get('reference_dt') and item.get('reference_dn'):
+ if frappe.get_meta(item.reference_dt).has_field('invoiced'):
set_invoiced(item, method, doc.name)
- if method=="on_submit" and frappe.db.get_value("Healthcare Settings", None, "create_test_on_si_submit") == '1':
- create_multiple("Sales Invoice", doc.name)
+ if method=='on_submit' and frappe.db.get_single_value('Healthcare Settings', 'create_lab_test_on_si_submit'):
+ create_multiple('Sales Invoice', doc.name)
+
def set_invoiced(item, method, ref_invoice=None):
invoiced = False
- if(method=="on_submit"):
+ if method=='on_submit':
validate_invoiced_on_submit(item)
invoiced = True
if item.reference_dt == 'Clinical Procedure':
if get_healthcare_service_item('clinical_procedure_consumable_item') == item.item_code:
- frappe.db.set_value(item.reference_dt, item.reference_dn, "consumption_invoiced", invoiced)
+ frappe.db.set_value(item.reference_dt, item.reference_dn, 'consumption_invoiced', invoiced)
else:
- frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
+ frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)
else:
- frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
+ frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)
if item.reference_dt == 'Patient Appointment':
if frappe.db.get_value('Patient Appointment', item.reference_dn, 'procedure_template'):
- dt_from_appointment = "Clinical Procedure"
+ dt_from_appointment = 'Clinical Procedure'
else:
- manage_fee_validity(item.reference_dn, method, ref_invoice)
- dt_from_appointment = "Patient Encounter"
- manage_doc_for_appoitnment(dt_from_appointment, item.reference_dn, invoiced)
+ dt_from_appointment = 'Patient Encounter'
+ manage_doc_for_appointment(dt_from_appointment, item.reference_dn, invoiced)
elif item.reference_dt == 'Lab Prescription':
- manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, "Lab Test", "lab_test_created")
+ manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Lab Test', 'lab_test_created')
elif item.reference_dt == 'Procedure Prescription':
- manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, "Clinical Procedure", "procedure_created")
+ manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Clinical Procedure', 'procedure_created')
+
def validate_invoiced_on_submit(item):
if item.reference_dt == 'Clinical Procedure' and get_healthcare_service_item('clinical_procedure_consumable_item') == item.item_code:
- is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "consumption_invoiced")
+ is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'consumption_invoiced')
else:
- is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "invoiced")
- if is_invoiced == 1:
- frappe.throw(_("The item referenced by {0} - {1} is already invoiced"\
+ is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'invoiced')
+ if is_invoiced:
+ frappe.throw(_('The item referenced by {0} - {1} is already invoiced'\
).format(item.reference_dt, item.reference_dn))
+
def manage_prescriptions(invoiced, ref_dt, ref_dn, dt, created_check_field):
created = frappe.db.get_value(ref_dt, ref_dn, created_check_field)
- if created == 1:
+ if created:
# Fetch the doc created for the prescription
doc_created = frappe.db.get_value(dt, {'prescription': ref_dn})
frappe.db.set_value(dt, doc_created, 'invoiced', invoiced)
-def validity_exists(practitioner, patient):
- return frappe.db.exists({
- "doctype": "Fee Validity",
- "practitioner": practitioner,
- "patient": patient})
-def manage_fee_validity(appointment_name, method, ref_invoice=None):
- appointment_doc = frappe.get_doc("Patient Appointment", appointment_name)
- validity_exist = validity_exists(appointment_doc.practitioner, appointment_doc.patient)
- do_not_update = False
- visited = 0
- if validity_exist:
- fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
- # Check if the validity is valid
- if (fee_validity.valid_till >= appointment_doc.appointment_date):
- if (method == "on_cancel" and appointment_doc.status != "Closed"):
- if ref_invoice == fee_validity.ref_invoice:
- visited = fee_validity.visited - 1
- if visited < 0:
- visited = 0
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- do_not_update = True
- elif (method == "on_submit" and fee_validity.visited < fee_validity.max_visit):
- visited = fee_validity.visited + 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- do_not_update = True
- else:
- do_not_update = False
+def check_fee_validity(appointment):
+ if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
+ return
- if not do_not_update:
- fee_validity = update_fee_validity(fee_validity, appointment_doc.appointment_date, ref_invoice)
- visited = fee_validity.visited
+ validity = frappe.db.exists('Fee Validity', {
+ 'practitioner': appointment.practitioner,
+ 'patient': appointment.patient,
+ 'valid_till': ('>=', appointment.appointment_date)
+ })
+ if not validity:
+ return
+
+ validity = frappe.get_doc('Fee Validity', validity)
+ return validity
+
+
+def manage_fee_validity(appointment):
+ fee_validity = check_fee_validity(appointment)
+ if fee_validity:
+ if appointment.status == 'Cancelled' and fee_validity.visited > 0:
+ fee_validity.visited -= 1
+ frappe.db.delete('Fee Validity Reference', {'appointment': appointment.name})
+ elif fee_validity.status == 'Completed':
+ return
+ else:
+ fee_validity.visited += 1
+ fee_validity.append('ref_appointments', {
+ 'appointment': appointment.name
+ })
+ fee_validity.save(ignore_permissions=True)
else:
- fee_validity = create_fee_validity(appointment_doc.practitioner, appointment_doc.patient, appointment_doc.appointment_date, ref_invoice)
- visited = fee_validity.visited
+ fee_validity = create_fee_validity(appointment)
+ return fee_validity
- # Mark All Patient Appointment invoiced = True in the validity range do not cross the max visit
- if (method == "on_cancel"):
- invoiced = True
- else:
- invoiced = False
- patient_appointments = appointments_valid_in_fee_validity(appointment_doc, invoiced)
- if patient_appointments and fee_validity:
- visit = visited
- for appointment in patient_appointments:
- if (method == "on_cancel" and appointment.status != "Closed"):
- if ref_invoice == fee_validity.ref_invoice:
- visited = visited - 1
- if visited < 0:
- visited = 0
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", False)
- manage_doc_for_appoitnment("Patient Encounter", appointment.name, False)
- elif method == "on_submit" and int(fee_validity.max_visit) > visit:
- if ref_invoice == fee_validity.ref_invoice:
- visited = visited + 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", True)
- manage_doc_for_appoitnment("Patient Encounter", appointment.name, True)
- if ref_invoice == fee_validity.ref_invoice:
- visit = visit + 1
-
- if method == "on_cancel":
- ref_invoice_in_fee_validity = frappe.db.get_value("Fee Validity", fee_validity.name, 'ref_invoice')
- if ref_invoice_in_fee_validity == ref_invoice:
- frappe.delete_doc("Fee Validity", fee_validity.name)
-
-def appointments_valid_in_fee_validity(appointment, invoiced):
- valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
- max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
- if int(max_visit) < 1:
- max_visit = 1
- valid_days_date = add_days(getdate(appointment.appointment_date), int(valid_days))
- return frappe.get_list("Patient Appointment",{'patient': appointment.patient, 'invoiced': invoiced,
- 'appointment_date':("<=", valid_days_date), 'appointment_date':(">=", getdate(appointment.appointment_date)),
- 'practitioner': appointment.practitioner}, order_by="appointment_date", limit=int(max_visit)-1)
-
-def manage_doc_for_appoitnment(dt_from_appointment, appointment, invoiced):
- dn_from_appointment = frappe.db.exists(
+def manage_doc_for_appointment(dt_from_appointment, appointment, invoiced):
+ dn_from_appointment = frappe.db.get_value(
dt_from_appointment,
- {
- "appointment": appointment
- }
+ filters={'appointment': appointment}
)
if dn_from_appointment:
- frappe.db.set_value(dt_from_appointment, dn_from_appointment, "invoiced", invoiced)
+ frappe.db.set_value(dt_from_appointment, dn_from_appointment, 'invoiced', invoiced)
+
@frappe.whitelist()
def get_drugs_to_invoice(encounter):
- encounter = frappe.get_doc("Patient Encounter", encounter)
+ encounter = frappe.get_doc('Patient Encounter', encounter)
if encounter:
- patient = frappe.get_doc("Patient", encounter.patient)
- if patient and patient.customer:
- item_to_invoice = []
+ patient = frappe.get_doc('Patient', encounter.patient)
+ if patient:
+ if patient.customer:
+ items_to_invoice = []
for drug_line in encounter.drug_prescription:
if drug_line.drug_code:
qty = 1
- if frappe.db.get_value("Item", drug_line.drug_code, "stock_uom") == "Nos":
+ if frappe.db.get_value('Item', drug_line.drug_code, 'stock_uom') == 'Nos':
qty = drug_line.get_quantity()
- description = False
- if drug_line.dosage:
- description = drug_line.dosage
- if description and drug_line.period:
- description += " for "+drug_line.period
- if not description:
- description = ""
- item_to_invoice.append({'drug_code': drug_line.drug_code, 'quantity': qty,
- 'description': description})
- return item_to_invoice
+
+ description = ''
+ if drug_line.dosage and drug_line.period:
+ description = _('{0} for {1}').format(drug_line.dosage, drug_line.period)
+
+ items_to_invoice.append({
+ 'drug_code': drug_line.drug_code,
+ 'quantity': qty,
+ 'description': description
+ })
+ return items_to_invoice
+ else:
+ validate_customer_created(patient)
+
@frappe.whitelist()
def get_children(doctype, parent, company, is_root=False):
- parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
+ parent_fieldname = "parent_" + doctype.lower().replace(" ", "_")
fields = [
- 'name as value',
- 'is_group as expandable',
- 'lft',
- 'rgt'
+ "name as value",
+ "is_group as expandable",
+ "lft",
+ "rgt"
]
- # fields = [ 'name', 'is_group', 'lft', 'rgt' ]
- filters = [['ifnull(`{0}`,"")'.format(parent_fieldname), '=', '' if is_root else parent]]
+ # fields = [ "name", "is_group", "lft", "rgt" ]
+ filters = [["ifnull(`{0}`,'')".format(parent_fieldname), "=", "" if is_root else parent]]
if is_root:
- fields += ['service_unit_type'] if doctype == 'Healthcare Service Unit' else []
- filters.append(['company', '=', company])
+ fields += ["service_unit_type"] if doctype == "Healthcare Service Unit" else []
+ filters.append(["company", "=", company])
else:
- fields += ['service_unit_type', 'allow_appointments', 'inpatient_occupancy', 'occupancy_status'] if doctype == 'Healthcare Service Unit' else []
- fields += [parent_fieldname + ' as parent']
+ fields += ["service_unit_type", "allow_appointments", "inpatient_occupancy", "occupancy_status"] if doctype == "Healthcare Service Unit" else []
+ fields += [parent_fieldname + " as parent"]
hc_service_units = frappe.get_list(doctype, fields=fields, filters=filters)
- if doctype == 'Healthcare Service Unit':
+ if doctype == "Healthcare Service Unit":
for each in hc_service_units:
occupancy_msg = ""
- if each['expandable'] == 1:
+ if each["expandable"] == 1:
occupied = False
vacant = False
- child_list = frappe.db.sql("""
- select name, occupancy_status from `tabHealthcare Service Unit`
- where inpatient_occupancy = 1 and
- lft > %s and rgt < %s""",
- (each['lft'], each['rgt']))
+ child_list = frappe.db.sql(
+ '''
+ SELECT
+ name, occupancy_status
+ FROM
+ `tabHealthcare Service Unit`
+ WHERE
+ inpatient_occupancy = 1
+ and lft > %s and rgt < %s
+ ''', (each['lft'], each['rgt']))
+
for child in child_list:
if not occupied:
occupied = 0
@@ -425,39 +479,44 @@
if child[1] == "Vacant":
vacant += 1
if vacant and occupied:
- occupancy_total = vacant+occupied
+ occupancy_total = vacant + occupied
occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
each["occupied_out_of_vacant"] = occupancy_msg
return hc_service_units
+
@frappe.whitelist()
def get_patient_vitals(patient, from_date=None, to_date=None):
if not patient: return
- vitals = frappe.db.sql("""select * from `tabVital Signs` where \
- docstatus=1 and patient=%s order by signs_date, signs_time""", \
- (patient), as_dict=1)
- if vitals and vitals[0]:
+
+ vitals = frappe.db.get_all('Vital Signs', {
+ 'docstatus': 1,
+ 'patient': patient
+ }, order_by='signs_date, signs_time')
+
+ if len(vitals):
return vitals
- else:
- return False
+ return False
+
@frappe.whitelist()
def render_docs_as_html(docs):
# docs key value pair {doctype: docname}
docs_html = "<div class='col-md-12 col-sm-12 text-muted'>"
for doc in docs:
- docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + "<br/>"
+ docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + '<br/>'
return {'html': docs_html}
+
@frappe.whitelist()
def render_doc_as_html(doctype, docname, exclude_fields = []):
#render document as html, three column layout will break
doc = frappe.get_doc(doctype, docname)
meta = frappe.get_meta(doctype)
doc_html = "<div class='col-md-12 col-sm-12'>"
- section_html = ""
- section_label = ""
- html = ""
+ section_html = ''
+ section_label = ''
+ html = ''
sec_on = False
col_on = 0
has_data = False
@@ -476,8 +535,8 @@
sec_on = True
has_data= False
col_on = 0
- section_html = ""
- html = ""
+ section_html = ''
+ html = ''
if df.label:
section_label = df.label
continue
@@ -493,19 +552,19 @@
d-6 col-sm-6'>" + html + "</div><div class='col-md-6 col-sm-6'>"
elif sec_on and not col_on:
section_html += "<div class='col-md-6 col-sm-6'>"
- html = ""
+ html = ''
col_on += 1
if df.label:
html += '<br>' + df.label
continue
#on table iterate in items and create table based on in_list_view, append to section html or doc html
- if df.fieldtype == "Table":
+ if df.fieldtype == 'Table':
items = doc.get(df.fieldname)
if not items: continue
child_meta = frappe.get_meta(df.options)
if not has_data : has_data = True
- table_head = ""
- table_row = ""
+ table_head = ''
+ table_row = ''
create_head = True
for item in items:
table_row += '<tr>'
@@ -521,24 +580,24 @@
create_head = False
table_row += '</tr>'
if sec_on:
- section_html += '<table class="table table-condensed \
- bordered">' + table_head + table_row + '</table>'
+ section_html += "<table class='table table-condensed \
+ bordered'>" + table_head + table_row + '</table>'
else:
- html += '<table class="table table-condensed table-bordered">' \
- + table_head + table_row + '</table>'
+ html += "<table class='table table-condensed table-bordered'>" \
+ + table_head + table_row + "</table>"
continue
#on other field types add label and value to html
if not df.hidden and not df.print_hide and doc.get(df.fieldname) and df.fieldname not in exclude_fields:
- html += "<br>{0} : {1}".format(df.label or df.fieldname, \
+ html += '<br>{0} : {1}'.format(df.label or df.fieldname, \
doc.get(df.fieldname))
if not has_data : has_data = True
if sec_on and col_on and has_data:
- doc_html += section_html + html + "</div></div>"
+ doc_html += section_html + html + '</div></div>'
elif sec_on and not col_on and has_data:
doc_html += "<div class='col-md-12 col-sm-12'\
><div class='col-md-12 col-sm-12'>" \
- + section_html + html +"</div></div>"
+ + section_html + html +'</div></div>'
if doc_html:
- doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='#Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + "</div>"
+ doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='#Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + '</div>'
return {'html': doc_html}
diff --git a/erpnext/healthcare/page/appointment_analytic/__init__.py b/erpnext/healthcare/web_form/patient_registration/__init__.py
similarity index 100%
copy from erpnext/healthcare/page/appointment_analytic/__init__.py
copy to erpnext/healthcare/web_form/patient_registration/__init__.py
diff --git a/erpnext/healthcare/web_form/patient_registration/patient_registration.js b/erpnext/healthcare/web_form/patient_registration/patient_registration.js
new file mode 100644
index 0000000..7da3f1f
--- /dev/null
+++ b/erpnext/healthcare/web_form/patient_registration/patient_registration.js
@@ -0,0 +1,3 @@
+frappe.ready(function() {
+ // bind events here
+});
\ No newline at end of file
diff --git a/erpnext/healthcare/web_form/patient_registration/patient_registration.json b/erpnext/healthcare/web_form/patient_registration/patient_registration.json
new file mode 100644
index 0000000..9ed92de
--- /dev/null
+++ b/erpnext/healthcare/web_form/patient_registration/patient_registration.json
@@ -0,0 +1,397 @@
+{
+ "accept_payment": 0,
+ "allow_comments": 0,
+ "allow_delete": 0,
+ "allow_edit": 1,
+ "allow_incomplete": 0,
+ "allow_multiple": 0,
+ "allow_print": 0,
+ "amount": 0.0,
+ "amount_based_on_field": 0,
+ "button_label": "Register",
+ "creation": "2020-03-03 01:01:16.250607",
+ "currency": "INR",
+ "doc_type": "Patient",
+ "docstatus": 0,
+ "doctype": "Web Form",
+ "idx": 0,
+ "introduction_text": "",
+ "is_standard": 1,
+ "login_required": 0,
+ "max_attachment_size": 0,
+ "modified": "2020-03-26 17:25:15.361918",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "patient-registration",
+ "owner": "Administrator",
+ "payment_button_label": "Buy Now",
+ "published": 1,
+ "route": "patient-registration",
+ "route_to_success_link": 0,
+ "show_attachments": 0,
+ "show_in_grid": 0,
+ "show_sidebar": 1,
+ "sidebar_items": [],
+ "success_message": "Registration Successfully. Thank You!",
+ "success_url": "/patient-registration",
+ "title": "Patient Registration",
+ "web_form_fields": [
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "basic_info",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "label": "Patient Demographics",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "fa fa-user",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "first_name",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "First Name",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 1,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "middle_name",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "Middle Name (optional)",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "last_name",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "Last Name",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 1,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "sex",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "label": "Gender",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "Gender",
+ "read_only": 0,
+ "reqd": 1,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "blood_group",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "label": "Blood Group",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "\nA Positive\nA Negative\nAB Positive\nAB Negative\nB Positive\nB Negative\nO Positive\nO Negative",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "dob",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "label": "Date of birth",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "mobile",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "Mobile",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "email",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "Email",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "Email",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "phone",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "Phone",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "label": "Personal Details",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "occupation",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "Occupation",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "marital_status",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "label": "Marital Status",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "\nSingle\nMarried\nDivorced\nWidow",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "allergy_medical_and_surgical_history",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "label": "Allergies, Medical and Surgical History",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "allergies",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "label": "Allergies",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "medication",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "label": "Medication",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "column_break_20",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "medical_history",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "label": "Medical History",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "surgical_history",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "label": "Surgical History",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "risk_factors",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "label": "Risk Factors",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "default": "0",
+ "fieldname": "tobacco_past_use",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "label": "Check if you have a history of Tobacco Consumption",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "default": "0",
+ "fieldname": "tobacco_current_use",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "label": "Check if you consume Tobacco",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "default": "0",
+ "fieldname": "alcohol_past_use",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "label": "Check if you have a history of Alcohol Consumption",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "default": "0",
+ "fieldname": "alcohol_current_use",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "label": "Check if you consume Alcohol",
+ "max_length": 0,
+ "max_value": 0,
+ "options": "",
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "column_break_32",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "surrounding_factors",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "label": "Occupational Hazards and Environmental Factors",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ },
+ {
+ "allow_read_on_all_link_options": 0,
+ "fieldname": "other_risk_factors",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "label": "Other Risk Factors",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0,
+ "show_in_filter": 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/web_form/patient_registration/patient_registration.py b/erpnext/healthcare/web_form/patient_registration/patient_registration.py
new file mode 100644
index 0000000..1bc4d18
--- /dev/null
+++ b/erpnext/healthcare/web_form/patient_registration/patient_registration.py
@@ -0,0 +1,5 @@
+from __future__ import unicode_literals
+
+def get_context(context):
+ # do your magic here
+ pass
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index b2dc961..6b6d1e2 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -239,7 +239,7 @@
"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': {
@@ -269,7 +269,8 @@
scheduler_events = {
"all": [
- "erpnext.projects.doctype.project.project.project_status_update_reminder"
+ "erpnext.projects.doctype.project.project.project_status_update_reminder",
+ "erpnext.healthcare_healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder"
],
"hourly": [
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
@@ -304,21 +305,22 @@
"erpnext.support.doctype.service_level_agreement.service_level_agreement.check_agreement_status",
"erpnext.crm.doctype.email_campaign.email_campaign.send_email_to_leads_or_contacts",
"erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status",
- "erpnext.selling.doctype.quotation.quotation.set_expired_status"
+ "erpnext.selling.doctype.quotation.quotation.set_expired_status",
+ "erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_appointment_status"
],
"daily_long": [
"erpnext.setup.doctype.email_digest.email_digest.send",
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
"erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
"erpnext.hr.utils.generate_leave_encashment",
- "erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.check_for_ltv_shortfall",
- "erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.make_accrual_interest_entry_for_term_loans"
+ "erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.create_process_loan_security_shortfall",
+ "erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans"
],
"monthly_long": [
"erpnext.accounts.deferred_revenue.convert_deferred_revenue_to_income",
"erpnext.accounts.deferred_revenue.convert_deferred_expense_to_expense",
"erpnext.hr.utils.allocate_earned_leaves",
- "erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual"
+ "erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_demand_loans"
]
}
@@ -345,6 +347,8 @@
payment_gateway_enabled = "erpnext.accounts.utils.create_payment_gateway_account"
+communication_doctypes = ["Customer", "Supplier"]
+
regional_overrides = {
'France': {
'erpnext.tests.test_regional.test_method': 'erpnext.regional.france.utils.test_method'
diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json
index ec38ef0..743aa23 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.js b/erpnext/hr/doctype/employee/employee.js
index 7d153d4..c21d4b8 100755
--- a/erpnext/hr/doctype/employee/employee.js
+++ b/erpnext/hr/doctype/employee/employee.js
@@ -55,8 +55,8 @@
};
});
},
- prefered_contact_email:function(frm){
- frm.events.update_contact(frm)
+ prefered_contact_email:function(frm){
+ frm.events.update_contact(frm)
},
personal_email:function(frm){
frm.events.update_contact(frm)
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index 3f0b9c4..13c202c 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/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index f78e17f..c441751 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -580,19 +580,22 @@
return leave_days
def skip_expiry_leaves(leave_entry, date):
- ''' Checks whether the expired leaves coincide with the to_date of leave balance check '''
+ ''' Checks whether the expired leaves coincide with the to_date of leave balance check.
+ This allows backdated leave entry creation for non carry forwarded allocation '''
end_date = frappe.db.get_value("Leave Allocation", {'name': leave_entry.transaction_name}, ['to_date'])
return True if end_date == date and not leave_entry.is_carry_forward else False
def get_leave_entries(employee, leave_type, from_date, to_date):
- ''' Returns leave entries between from_date and to_date '''
+ ''' Returns leave entries between from_date and to_date. '''
return frappe.db.sql("""
SELECT
employee, leave_type, from_date, to_date, leaves, transaction_name, transaction_type,
is_carry_forward, is_expired
FROM `tabLeave Ledger Entry`
WHERE employee=%(employee)s AND leave_type=%(leave_type)s
- AND docstatus=1 AND leaves<0
+ AND docstatus=1
+ AND (leaves<0
+ OR is_expired=1)
AND (from_date between %(from_date)s AND %(to_date)s
OR to_date between %(from_date)s AND %(to_date)s
OR (from_date < %(from_date)s AND to_date > %(to_date)s))
@@ -687,8 +690,7 @@
"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/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
index ad2cc02..7d6fd42 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
@@ -8,7 +8,6 @@
from frappe.model.document import Document
from frappe.utils import getdate, nowdate, flt
from erpnext.hr.utils import set_employee_name
-from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on
from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure
from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry
from erpnext.hr.doctype.leave_allocation.leave_allocation import get_unused_leaves
diff --git a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py
index bfc6d95..9ed58c9 100644
--- a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py
+++ b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py
@@ -141,6 +141,7 @@
leaves = get_remaining_leaves(allocation)
expiry_date = expiry_date if expiry_date else allocation.to_date
+ # allows expired leaves entry to be created/reverted
if leaves:
args = dict(
leaves=flt(leaves) * -1,
@@ -160,6 +161,8 @@
from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period
leaves_taken = get_leaves_for_period(allocation.employee, allocation.leave_type, allocation.from_date, allocation.to_date)
leaves = flt(allocation.leaves) + flt(leaves_taken)
+
+ # allow expired leaves entry to be created
if leaves > 0:
args = frappe._dict(
transaction_name=allocation.name,
diff --git a/erpnext/hr/doctype/payroll_entry/test_payroll_entry.py b/erpnext/hr/doctype/payroll_entry/test_payroll_entry.py
index 35f5a57..49671d5 100644
--- a/erpnext/hr/doctype/payroll_entry/test_payroll_entry.py
+++ b/erpnext/hr/doctype/payroll_entry/test_payroll_entry.py
@@ -13,7 +13,7 @@
make_earning_salary_component, make_deduction_salary_component
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure
from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry
-from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import make_accrual_interest_entry_for_term_loans
+from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
class TestPayrollEntry(unittest.TestCase):
def setUp(self):
@@ -81,7 +81,7 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1))
- make_accrual_interest_entry_for_term_loans(posting_date=nowdate())
+ process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
dates = get_start_end_dates('Monthly', nowdate())
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.json b/erpnext/hr/doctype/salary_slip/salary_slip.json
index e73d41a..097d3a0 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.json
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.json
@@ -372,8 +372,7 @@
"fieldtype": "Table",
"label": "Employee Loan",
"options": "Salary Slip Loan",
- "print_hide": 1,
- "read_only": 1
+ "print_hide": 1
},
{
"fieldname": "section_break_43",
@@ -464,7 +463,7 @@
"idx": 9,
"is_submittable": 1,
"links": [],
- "modified": "2019-12-31 17:13:45.146271",
+ "modified": "2020-04-09 20:02:53.159827",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip",
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index d03a3dd..223c4e3 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -356,13 +356,13 @@
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:
@@ -755,30 +755,37 @@
d.amount = self.get_amount_based_on_payment_days(d, joining_date, relieving_date)[0]
def set_loan_repayment(self):
- self.set('loans', [])
self.total_loan_repayment = 0
self.total_interest_amount = 0
self.total_principal_amount = 0
- for loan in self.get_loan_details():
+ if not self.get('loans'):
+ for loan in self.get_loan_details():
- amounts = calculate_amounts(loan.name, self.posting_date, "Regular Payment")
+ amounts = calculate_amounts(loan.name, self.posting_date, "Regular Payment")
- total_payment = amounts['interest_amount'] + amounts['payable_principal_amount']
+ if amounts['interest_amount'] or amounts['payable_principal_amount']:
+ self.append('loans', {
+ 'loan': loan.name,
+ 'total_payment': amounts['interest_amount'] + amounts['payable_principal_amount'],
+ 'interest_amount': amounts['interest_amount'],
+ 'principal_amount': amounts['payable_principal_amount'],
+ 'loan_account': loan.loan_account,
+ 'interest_income_account': loan.interest_income_account
+ })
- if total_payment:
- self.append('loans', {
- 'loan': loan.name,
- 'total_payment': total_payment,
- 'interest_amount': amounts['interest_amount'],
- 'principal_amount': amounts['payable_principal_amount'],
- 'loan_account': loan.loan_account,
- 'interest_income_account': loan.interest_income_account
- })
+ for payment in self.get('loans'):
+ amounts = calculate_amounts(payment.loan, self.posting_date, "Regular Payment")
+ total_amount = amounts['interest_amount'] + amounts['payable_principal_amount']
+ if payment.total_payment > total_amount:
+ frappe.throw(_("""Row {0}: Paid amount {1} is greater than pending accrued amount {2}
+ against loan {3}""").format(payment.idx, frappe.bold(payment.total_payment),
+ frappe.bold(total_amount), frappe.bold(payment.loan)))
- self.total_loan_repayment += total_payment
- self.total_interest_amount += amounts['interest_amount']
- self.total_principal_amount += amounts['payable_principal_amount']
+ self.total_interest_amount += payment.interest_amount
+ self.total_principal_amount += payment.principal_amount
+
+ self.total_loan_repayment += payment.total_payment
def get_loan_details(self):
diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
index 9acfd1f..ecccac7 100644
--- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
@@ -146,7 +146,7 @@
def test_loan_repayment_salary_slip(self):
from erpnext.loan_management.doctype.loan.test_loan import create_loan_type, create_loan, make_loan_disbursement_entry, create_loan_accounts
- from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import make_accrual_interest_entry_for_term_loans
+ from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
applicant = make_employee("test_loanemployee@salary.com", company="_Test Company")
@@ -166,7 +166,7 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1))
- make_accrual_interest_entry_for_term_loans(posting_date=nowdate())
+ process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
ss = make_employee_salary_slip("test_loanemployee@salary.com", "Monthly")
ss.submit()
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 1d60ca4..691d2c1 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/loan.js b/erpnext/loan_management/doctype/loan/loan.js
index 8b22017..9cd8b2e 100644
--- a/erpnext/loan_management/doctype/loan/loan.js
+++ b/erpnext/loan_management/doctype/loan/loan.js
@@ -97,6 +97,8 @@
"company": frm.doc.company,
"applicant_type": frm.doc.applicant_type,
"applicant": frm.doc.applicant,
+ "pending_amount": frm.doc.loan_amount - frm.doc.disbursed_amount > 0 ?
+ frm.doc.loan_amount - frm.doc.disbursed_amount : 0,
"as_dict": 1
},
method: "erpnext.loan_management.doctype.loan.loan.make_loan_disbursement",
@@ -149,10 +151,10 @@
return frappe.call({
method: "erpnext.loan_management.doctype.loan.loan.get_loan_application",
args: {
- "loan_application": frm.doc.loan_application
- },
- callback: function (r) {
- if (!r.exc && r.message) {
+ "loan_application": frm.doc.loan_application
+ },
+ callback: function (r) {
+ if (!r.exc && r.message) {
let loan_fields = ["loan_type", "loan_amount", "repayment_method",
"monthly_repayment_amount", "repayment_periods", "rate_of_interest", "is_secured_loan"]
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index 2834e5b..b04e822 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -126,7 +126,7 @@
"depends_on": "eval:doc.applicant_type==\"Employee\"",
"fieldname": "repay_from_salary",
"fieldtype": "Check",
- "label": "Repay from Salary"
+ "label": "Repay From Salary"
},
{
"fieldname": "section_break_8",
@@ -178,6 +178,8 @@
},
{
"depends_on": "is_term_loan",
+ "fetch_from": "loan_application.repayment_amount",
+ "fetch_if_empty": 1,
"fieldname": "monthly_repayment_amount",
"fieldtype": "Currency",
"label": "Monthly Repayment Amount",
@@ -350,7 +352,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-02-07 01:31:25.172173",
+ "modified": "2020-04-13 13:16:10.192624",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan",
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index 696410b..c7a2fba 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -19,6 +19,7 @@
self.validate_loan_security_pledge()
self.validate_loan_amount()
self.check_sanctioned_amount_limit()
+ self.validate_repay_from_salary()
if self.is_term_loan:
validate_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount,
@@ -77,6 +78,10 @@
if sanctioned_amount_limit and flt(self.loan_amount) + flt(total_loan_amount) > flt(sanctioned_amount_limit):
frappe.throw(_("Sanctioned Amount limit crossed for {0} {1}").format(self.applicant_type, frappe.bold(self.applicant)))
+ def validate_repay_from_salary(self):
+ if not self.is_term_loan and self.repay_from_salary:
+ frappe.throw(_("Repay From Salary can be selected only for term loans"))
+
def make_repayment_schedule(self):
if not self.repayment_start_date:
@@ -198,7 +203,7 @@
frappe.db.set_value("Loan", loan, "status", "Closed")
@frappe.whitelist()
-def make_loan_disbursement(loan, company, applicant_type, applicant, disbursed_amount=0, as_dict=0):
+def make_loan_disbursement(loan, company, applicant_type, applicant, pending_amount=0, as_dict=0):
disbursement_entry = frappe.new_doc("Loan Disbursement")
disbursement_entry.against_loan = loan
disbursement_entry.applicant_type = applicant_type
@@ -206,8 +211,7 @@
disbursement_entry.company = company
disbursement_entry.disbursement_date = nowdate()
- if disbursed_amount:
- disbursement_entry.disbursed_amount = disbursed_amount
+ disbursement_entry.disbursed_amount = pending_amount
if as_dict:
return disbursement_entry.as_dict()
else:
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 759b0d8..2d1ad33 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -10,10 +10,10 @@
add_months, get_first_day, get_last_day, flt, date_diff)
from erpnext.selling.doctype.customer.test_customer import get_customer_dict
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_employee
-from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual
-from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import (make_accrual_interest_entry_for_term_loans, days_in_year)
-
-from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import check_for_ltv_shortfall
+from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import (process_loan_interest_accrual_for_demand_loans,
+ process_loan_interest_accrual_for_term_loans)
+from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
+from erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall import create_process_loan_security_shortfall
class TestLoan(unittest.TestCase):
def setUp(self):
@@ -145,17 +145,23 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
- process_loan_interest_accrual(posting_date = last_date)
+ process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 10), "Regular Payment", 111118.68)
repayment_entry.save()
+ repayment_entry.submit()
penalty_amount = (accrued_interest_amount * 5 * 25) / (100 * days_in_year(get_datetime(first_date).year))
-
- self.assertEquals(flt(repayment_entry.interest_payable, 2), flt(accrued_interest_amount, 2))
self.assertEquals(flt(repayment_entry.penalty_amount, 2), flt(penalty_amount, 2))
- repayment_entry.submit()
+ amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
+ 'paid_principal_amount'])
+
+ loan.load_from_db()
+
+ self.assertEquals(amounts[0], repayment_entry.interest_payable)
+ self.assertEquals(flt(loan.total_principal_paid, 2), flt(repayment_entry.amount_paid -
+ penalty_amount - amounts[0], 2))
def test_loan_closure_repayment(self):
pledges = []
@@ -186,18 +192,22 @@
/ (days_in_year(get_datetime(first_date).year) * 100)
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
- process_loan_interest_accrual(posting_date = last_date)
+ process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
- "Loan Closure", 13315.0681)
- repayment_entry.save()
+ "Loan Closure", flt(loan.loan_amount + accrued_interest_amount))
+ repayment_entry.submit()
- repayment_entry.amount_paid = repayment_entry.payable_amount
+ amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
+ 'paid_principal_amount'])
- self.assertEquals(flt(repayment_entry.interest_payable, 3), flt(accrued_interest_amount, 3))
+ unaccrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * 6) \
+ / (days_in_year(get_datetime(first_date).year) * 100)
+
+ self.assertEquals(flt(amounts[0] + unaccrued_interest_amount, 3),
+ flt(accrued_interest_amount, 3))
self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
- repayment_entry.submit()
loan.load_from_db()
self.assertEquals(loan.status, "Loan Closure Requested")
@@ -224,60 +234,18 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1))
- make_accrual_interest_entry_for_term_loans(posting_date=nowdate())
+ process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(get_last_day(nowdate()), 5),
- "Regular Payment", 89768.7534247)
+ "Regular Payment", 89768.75)
- repayment_entry.save()
repayment_entry.submit()
- repayment_entry.load_from_db()
+ amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
+ 'paid_principal_amount'])
- self.assertEquals(repayment_entry.interest_payable, 11250.00)
- self.assertEquals(repayment_entry.payable_principal_amount, 78303.00)
-
- def test_partial_loan_repayment(self):
- pledges = []
- pledges.append({
- "loan_security": "Test Security 1",
- "qty": 4000.00,
- "haircut": 50
- })
-
- loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
-
- loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name,
- posting_date=get_first_day(nowdate()))
-
- loan.submit()
-
- self.assertEquals(loan.loan_amount, 1000000)
-
- first_date = '2019-10-01'
- last_date = '2019-10-30'
-
- no_of_days = date_diff(last_date, first_date) + 1
-
- accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
- / (days_in_year(get_datetime().year) * 100)
-
- make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
-
- process_loan_interest_accrual(posting_date = add_days(first_date, 15))
- process_loan_interest_accrual(posting_date = add_days(first_date, 30))
-
- repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 1), "Regular Payment", 6500)
- repayment_entry.save()
- repayment_entry.submit()
-
- penalty_amount = (accrued_interest_amount * 4 * 25) / (100 * days_in_year(get_datetime(first_date).year))
-
- 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(lia1)
- self.assertTrue(lia2)
+ self.assertEquals(amounts[0], 11250.00)
+ self.assertEquals(amounts[1], 78303.00)
def test_security_shortfall(self):
pledges = []
@@ -294,10 +262,10 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount)
- frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 100
+ frappe.db.sql("""UPDATE `tabLoan Security Price` SET loan_security_price = 100
where loan_security='Test Security 2'""")
- check_for_ltv_shortfall()
+ create_process_loan_security_shortfall()
loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
self.assertTrue(loan_security_shortfall)
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js
index 57050d8..aba5f42 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.js
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.js
@@ -31,13 +31,15 @@
add_toolbar_buttons: function(frm) {
if (frm.doc.status == "Approved") {
- frappe.db.get_value("Loan Security Pledge", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
- if (!r) {
- frm.add_custom_button(__('Loan Security Pledge'), function() {
- frm.trigger('create_loan_security_pledge')
- },__('Create'))
- }
- });
+ if (frm.doc.is_secured) {
+ frappe.db.get_value("Loan Security Pledge", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
+ if (!r) {
+ frm.add_custom_button(__('Loan Security Pledge'), function() {
+ frm.trigger('create_loan_security_pledge')
+ },__('Create'))
+ }
+ });
+ }
frappe.db.get_value("Loan", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
if (!r) {
@@ -61,6 +63,11 @@
});
},
create_loan_security_pledge: function(frm) {
+
+ if(!frm.doc.is_secured_loan) {
+ frappe.throw(__("Loan Security Pledge can only be created for secured loans"));
+ }
+
frappe.call({
method: "erpnext.loan_management.doctype.loan_application.loan_application.create_pledge",
args: {
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
index 72a4ddc..2d9c45d 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "LM-DIS-.#####",
"creation": "2019-09-07 12:44:49.125452",
"doctype": "DocType",
@@ -13,7 +14,6 @@
"applicant_type",
"applicant",
"section_break_7",
- "pending_amount_for_disbursal",
"disbursed_amount",
"accounting_dimensions_section",
"cost_center",
@@ -84,13 +84,6 @@
"read_only": 1
},
{
- "fieldname": "pending_amount_for_disbursal",
- "fieldtype": "Currency",
- "label": "Pending Amount For Disbursal",
- "options": "Company:company:default_currency",
- "read_only": 1
- },
- {
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
@@ -99,6 +92,7 @@
"fieldtype": "Section Break"
},
{
+ "collapsible": 1,
"fieldname": "section_break_13",
"fieldtype": "Section Break"
},
@@ -123,7 +117,8 @@
}
],
"is_submittable": 1,
- "modified": "2019-10-24 12:32:32.230881",
+ "links": [],
+ "modified": "2020-04-09 14:44:28.527271",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Disbursement",
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index fa7db2d..2918486 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -4,21 +4,24 @@
from __future__ import unicode_literals
import frappe, erpnext
+from frappe import _
from frappe.model.document import Document
from frappe.utils import nowdate, getdate, add_days, flt
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.general_ledger import make_gl_entries
-from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual
+from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
class LoanDisbursement(AccountsController):
def validate(self):
self.set_missing_values()
- self.set_pending_amount_for_disbursal()
def before_submit(self):
self.set_status_and_amounts()
+ def before_cancel(self):
+ self.set_status_and_amounts(cancel=1)
+
def on_submit(self):
self.make_gl_entries()
@@ -38,13 +41,7 @@
if not self.bank_account and self.applicant_type == "Customer":
self.bank_account = frappe.db.get_value("Customer", self.applicant, "default_bank_account")
- def set_pending_amount_for_disbursal(self):
- loan_amount, disbursed_amount = frappe.db.get_value('Loan',
- {'name': self.against_loan}, ['loan_amount', 'disbursed_amount'])
-
- self.pending_amount_for_disbursal = loan_amount - disbursed_amount
-
- def set_status_and_amounts(self):
+ def set_status_and_amounts(self, cancel=0):
loan_details = frappe.get_all("Loan",
fields = ["loan_amount", "disbursed_amount", "total_principal_paid", "status", "is_term_loan"],
@@ -52,26 +49,32 @@
)[0]
if loan_details.status == "Disbursed" and not loan_details.is_term_loan:
- process_loan_interest_accrual(posting_date=add_days(self.disbursement_date, -1),
+ process_loan_interest_accrual_for_demand_loans(posting_date=add_days(self.disbursement_date, -1),
loan=self.against_loan)
- disbursed_amount = self.disbursed_amount + loan_details.disbursed_amount
-
- if flt(disbursed_amount) - flt(loan_details.total_principal_paid) > flt(loan_details.loan_amount):
- frappe.throw(_("Disbursed Amount cannot be greater than loan amount"))
-
- if flt(disbursed_amount) > flt(loan_details.loan_amount):
- total_principal_paid = loan_details.total_principal_paid - (disbursed_amount - loan_details.loan_amount)
- frappe.db.set_value("Loan", self.against_loan, "total_principal_paid", total_principal_paid)
-
- if flt(loan_details.loan_amount) == flt(disbursed_amount):
- frappe.db.set_value("Loan", self.against_loan, "status", "Disbursed")
+ if cancel:
+ disbursed_amount = loan_details.disbursed_amount - self.disbursed_amount
+ if disbursed_amount == 0:
+ status = "Sanctioned"
+ elif disbursed_amount >= loan_details.disbursed_amount:
+ status = "Disbursed"
+ else:
+ status = "Partially Disbursed"
else:
- frappe.db.set_value("Loan", self.against_loan, "status", "Partially Disbursed")
+ disbursed_amount = self.disbursed_amount + loan_details.disbursed_amount
+
+ if flt(disbursed_amount) - flt(loan_details.total_principal_paid) > flt(loan_details.loan_amount):
+ frappe.throw(_("Disbursed Amount cannot be greater than loan amount"))
+
+ if flt(disbursed_amount) >= loan_details.disbursed_amount:
+ status = "Disbursed"
+ else:
+ status = "Partially Disbursed"
frappe.db.set_value("Loan", self.against_loan, {
"disbursement_date": self.disbursement_date,
- "disbursed_amount": disbursed_amount
+ "disbursed_amount": disbursed_amount,
+ "status": status
})
def make_gl_entries(self, cancel=0, adv_adj=0):
diff --git a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
index 968e377..0c1578f 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
@@ -7,8 +7,8 @@
from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date)
from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_repayment_entry,
make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_security_price)
-from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual
-from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import (make_accrual_interest_entry_for_term_loans, days_in_year)
+from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
+from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
from erpnext.selling.doctype.customer.test_customer import get_customer_dict
class TestLoanDisbursement(unittest.TestCase):
@@ -56,20 +56,18 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
- process_loan_interest_accrual(posting_date=add_days(last_date, 1))
+ process_loan_interest_accrual_for_demand_loans(posting_date=add_days(last_date, 1))
- # Paid 511095.89 amount includes 5,00,000 principal amount and 11095.89 interest amount
+ # Should not be able to create loan disbursement entry before repayment
+ self.assertRaises(frappe.ValidationError, make_loan_disbursement_entry, loan.name,
+ 500000, first_date)
+
repayment_entry = create_repayment_entry(loan.name, self.applicant, add_days(get_last_day(nowdate()), 5),
"Regular Payment", 611095.89)
- repayment_entry.submit()
+ repayment_entry.submit()
loan.reload()
+ # After repayment loan disbursement entry should go through
make_loan_disbursement_entry(loan.name, 500000, disbursement_date=add_days(last_date, 16))
- total_principal_paid = loan.total_principal_paid
-
- loan.reload()
-
- # Loan Topup will result in decreasing the Total Principal Paid
- self.assertEqual(flt(loan.total_principal_paid, 2), flt(total_principal_paid - 500000, 2))
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
index 33f496f..5fc3e8f 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
@@ -15,14 +15,16 @@
"company",
"posting_date",
"is_term_loan",
- "is_paid",
"section_break_7",
"pending_principal_amount",
"payable_principal_amount",
+ "paid_principal_amount",
"column_break_14",
"interest_amount",
+ "paid_interest_amount",
"section_break_15",
"process_loan_interest_accrual",
+ "repayment_schedule_name",
"amended_from"
],
"fields": [
@@ -102,13 +104,6 @@
},
{
"default": "0",
- "fieldname": "is_paid",
- "fieldtype": "Check",
- "label": "Is Paid",
- "read_only": 1
- },
- {
- "default": "0",
"fetch_from": "loan.is_term_loan",
"fieldname": "is_term_loan",
"fieldtype": "Check",
@@ -135,12 +130,31 @@
{
"fieldname": "column_break_14",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "repayment_schedule_name",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Repayment Schedule Name",
+ "read_only": 1
+ },
+ {
+ "fieldname": "paid_principal_amount",
+ "fieldtype": "Currency",
+ "label": "Paid Principal Amount",
+ "options": "Company:company:default_currency"
+ },
+ {
+ "fieldname": "paid_interest_amount",
+ "fieldtype": "Currency",
+ "label": "Paid Interest Amount",
+ "options": "Company:company:default_currency"
}
],
"in_create": 1,
"is_submittable": 1,
"links": [],
- "modified": "2020-02-07 01:22:06.924125",
+ "modified": "2020-04-16 11:24:23.258404",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Interest Accrual",
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
index b8e6dab..094b9c6 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
@@ -27,8 +27,14 @@
self.make_gl_entries()
def on_cancel(self):
+ if self.repayment_schedule_name:
+ self.update_is_accrued()
+
self.make_gl_entries(cancel=1)
+ def update_is_accrued(self):
+ frappe.db.set_value('Repayment Schedule', self.repayment_schedule_name, 'is_accrued', 0)
+
def make_gl_entries(self, cancel=0, adv_adj=0):
gle_map = []
@@ -83,9 +89,19 @@
interest_per_day = (pending_principal_amount * loan.rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100)
payable_interest = interest_per_day * no_of_days
- make_loan_interest_accrual_entry(loan.name, loan.applicant_type, loan.applicant,loan.interest_income_account,
- loan.loan_account, pending_principal_amount, payable_interest, process_loan_interest = process_loan_interest,
- posting_date=posting_date)
+ args = frappe._dict({
+ 'loan': loan.name,
+ 'applicant_type': loan.applicant_type,
+ 'applicant': loan.applicant,
+ 'interest_income_account': loan.interest_income_account,
+ 'loan_account': loan.loan_account,
+ 'pending_principal_amount': pending_principal_amount,
+ 'interest_amount': payable_interest,
+ 'process_loan_interest': process_loan_interest,
+ 'posting_date': posting_date
+ })
+
+ make_loan_interest_accrual_entry(args)
def make_accrual_interest_entry_for_demand_loans(posting_date, process_loan_interest, open_loans=None, loan_type=None):
query_filters = {
@@ -107,49 +123,71 @@
for loan in open_loans:
calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest)
-def make_accrual_interest_entry_for_term_loans(posting_date=None):
+def make_accrual_interest_entry_for_term_loans(posting_date, process_loan_interest, term_loan=None, loan_type=None):
curr_date = posting_date or add_days(nowdate(), 1)
- term_loans = frappe.db.sql("""SELECT l.name, l.total_payment, l.total_amount_paid, l.loan_account,
- l.interest_income_account, l.is_term_loan, l.disbursement_date, l.applicant_type, l.applicant,
- l.rate_of_interest, l.total_interest_payable, l.repayment_start_date, rs.name as payment_entry,
- rs.payment_date, rs.principal_amount, rs.interest_amount, rs.is_accrued , rs.balance_loan_amount
- FROM `tabLoan` l, `tabRepayment Schedule` rs
- WHERE rs.parent = l.name
- AND l.docstatus=1
- AND l.is_term_loan =1
- AND rs.payment_date <= %s
- AND rs.is_accrued=0
- AND l.status = 'Disbursed'""", (curr_date), as_dict=1)
+ term_loans = get_term_loans(curr_date, term_loan, loan_type)
accrued_entries = []
for loan in term_loans:
accrued_entries.append(loan.payment_entry)
- make_loan_interest_accrual_entry(loan.name, loan.applicant_type, loan.applicant,loan.interest_income_account,
- loan.loan_account, loan.principal_amount + loan.balance_loan_amount, loan.interest_amount,
- payable_principal = loan.principal_amount , posting_date=posting_date)
+ args = frappe._dict({
+ 'loan': loan.name,
+ 'applicant_type': loan.applicant_type,
+ 'applicant': loan.applicant,
+ 'interest_income_account': loan.interest_income_account,
+ 'loan_account': loan.loan_account,
+ 'interest_amount': loan.interest_amount,
+ 'payable_principal': loan.principal_amount,
+ 'process_loan_interest': process_loan_interest,
+ 'repayment_schedule_name': loan.payment_entry,
+ 'posting_date': posting_date
+ })
+
+ make_loan_interest_accrual_entry(args)
if accrued_entries:
frappe.db.sql("""UPDATE `tabRepayment Schedule`
SET is_accrued = 1 where name in (%s)""" #nosec
% ", ".join(['%s']*len(accrued_entries)), tuple(accrued_entries))
-def make_loan_interest_accrual_entry(loan, applicant_type, applicant, interest_income_account, loan_account,
- pending_principal_amount, interest_amount, payable_principal=None, process_loan_interest=None, posting_date=None):
- loan_interest_accrual = frappe.new_doc("Loan Interest Accrual")
- loan_interest_accrual.loan = loan
- loan_interest_accrual.applicant_type = applicant_type
- loan_interest_accrual.applicant = applicant
- loan_interest_accrual.interest_income_account = interest_income_account
- loan_interest_accrual.loan_account = loan_account
- loan_interest_accrual.pending_principal_amount = flt(pending_principal_amount, 2)
- loan_interest_accrual.interest_amount = flt(interest_amount, 2)
- loan_interest_accrual.posting_date = posting_date or nowdate()
- loan_interest_accrual.process_loan_interest_accrual = process_loan_interest
+def get_term_loans(date, term_loan=None, loan_type=None):
+ condition = ''
- if payable_principal:
- loan_interest_accrual.payable_principal_amount = payable_principal
+ if term_loan:
+ condition +=' AND l.name = %s' % frappe.db.escape(term_loan)
+
+ if loan_type:
+ condition += ' AND l.loan_type = %s' % frappe.db.escape(loan_type)
+
+ term_loans = frappe.db.sql("""SELECT l.name, l.total_payment, l.total_amount_paid, l.loan_account,
+ l.interest_income_account, l.is_term_loan, l.disbursement_date, l.applicant_type, l.applicant,
+ l.rate_of_interest, l.total_interest_payable, l.repayment_start_date, rs.name as payment_entry,
+ rs.payment_date, rs.principal_amount, rs.interest_amount, rs.is_accrued , rs.balance_loan_amount
+ FROM `tabLoan` l, `tabRepayment Schedule` rs
+ WHERE rs.parent = l.name
+ AND l.docstatus=1
+ AND l.is_term_loan =1
+ AND rs.payment_date <= %s
+ AND rs.is_accrued=0 {0}
+ AND l.status = 'Disbursed'""".format(condition), (getdate(date)), as_dict=1)
+
+ return term_loans
+
+def make_loan_interest_accrual_entry(args):
+ loan_interest_accrual = frappe.new_doc("Loan Interest Accrual")
+ loan_interest_accrual.loan = args.loan
+ loan_interest_accrual.applicant_type = args.applicant_type
+ loan_interest_accrual.applicant = args.applicant
+ loan_interest_accrual.interest_income_account = args.interest_income_account
+ loan_interest_accrual.loan_account = args.loan_account
+ loan_interest_accrual.pending_principal_amount = flt(args.pending_principal_amount, 2)
+ loan_interest_accrual.interest_amount = flt(args.interest_amount, 2)
+ loan_interest_accrual.posting_date = args.posting_date or nowdate()
+ loan_interest_accrual.process_loan_interest_accrual = args.process_loan_interest
+ loan_interest_accrual.repayment_schedule_name = args.repayment_schedule_name
+ loan_interest_accrual.payable_principal_amount = args.payable_principal
loan_interest_accrual.save()
loan_interest_accrual.submit()
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
index e681ae4..2afed08 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
@@ -7,8 +7,8 @@
from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date)
from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_loan_security_price,
make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan)
-from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual
-from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import (make_accrual_interest_entry_for_term_loans, days_in_year)
+from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
+from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
from erpnext.selling.doctype.customer.test_customer import get_customer_dict
class TestLoanInterestAccrual(unittest.TestCase):
@@ -54,7 +54,7 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
- process_loan_interest_accrual(posting_date=last_date)
+ process_loan_interest_accrual_for_demand_loans(posting_date=last_date)
loan_interest_accural = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name})
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 4b930c5..789c129 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -30,9 +30,8 @@
"reference_number",
"column_break_21",
"reference_date",
- "paid_accrual_entries",
- "partial_paid_entry",
"principal_amount_paid",
+ "repayment_details",
"amended_from"
],
"fields": [
@@ -156,13 +155,6 @@
"read_only": 1
},
{
- "fieldname": "paid_accrual_entries",
- "fieldtype": "Text",
- "hidden": 1,
- "label": "Paid Accrual Entries",
- "read_only": 1
- },
- {
"default": "0",
"fetch_from": "against_loan.is_term_loan",
"fieldname": "is_term_loan",
@@ -198,13 +190,6 @@
"fieldtype": "Column Break"
},
{
- "fieldname": "partial_paid_entry",
- "fieldtype": "Text",
- "hidden": 1,
- "label": "Partial Paid Entry",
- "read_only": 1
- },
- {
"default": "0.0",
"fieldname": "principal_amount_paid",
"fieldtype": "Currency",
@@ -225,11 +210,18 @@
"fieldtype": "Date",
"label": "Due Date",
"read_only": 1
+ },
+ {
+ "fieldname": "repayment_details",
+ "fieldtype": "Table",
+ "hidden": 1,
+ "label": "Repayment Details",
+ "options": "Loan Repayment Detail"
}
],
"is_submittable": 1,
"links": [],
- "modified": "2020-02-26 06:18:54.934538",
+ "modified": "2020-04-16 18:14:45.166754",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Repayment",
@@ -264,7 +256,6 @@
"write": 1
}
],
- "quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index a70e312..87e8a15 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -19,11 +19,11 @@
def validate(self):
amounts = calculate_amounts(self.against_loan, self.posting_date, self.payment_type)
self.set_missing_values(amounts)
-
- def before_submit(self):
- self.mark_as_paid()
+ self.validate_amount()
+ self.allocate_amounts(amounts['pending_accrual_entries'])
def on_submit(self):
+ self.update_paid_amount()
self.make_gl_entries()
def on_cancel(self):
@@ -38,32 +38,25 @@
self.cost_center = erpnext.get_default_cost_center(self.company)
if not self.interest_payable:
- self.interest_payable = amounts['interest_amount']
+ self.interest_payable = flt(amounts['interest_amount'], 2)
if not self.penalty_amount:
- self.penalty_amount = amounts['penalty_amount']
+ self.penalty_amount = flt(amounts['penalty_amount'], 2)
if not self.pending_principal_amount:
- self.pending_principal_amount = amounts['pending_principal_amount']
+ self.pending_principal_amount = flt(amounts['pending_principal_amount'], 2)
if not self.payable_principal_amount and self.is_term_loan:
- self.payable_principal_amount = amounts['payable_principal_amount']
+ self.payable_principal_amount = flt(amounts['payable_principal_amount'], 2)
if not self.payable_amount:
- self.payable_amount = amounts['payable_amount']
-
- if amounts.get('paid_accrual_entries'):
- self.paid_accrual_entries = frappe.as_json(amounts.get('paid_accrual_entries'))
+ self.payable_amount = flt(amounts['payable_amount'], 2)
if amounts.get('due_date'):
self.due_date = amounts.get('due_date')
- def mark_as_paid(self):
- paid_entries = []
- paid_amount = self.amount_paid
- interest_paid = paid_amount
-
- if not paid_amount:
+ def validate_amount(self):
+ if not self.amount_paid:
frappe.throw(_("Amount paid cannot be zero"))
if self.amount_paid < self.penalty_amount:
@@ -74,37 +67,15 @@
msg = _("Amount of {0} is required for Loan closure").format(self.payable_amount)
frappe.throw(msg)
+ def update_paid_amount(self):
loan = frappe.get_doc("Loan", self.against_loan)
- if self.paid_accrual_entries:
- paid_accrual_entries = json.loads(self.paid_accrual_entries)
-
- if paid_amount - self.penalty_amount > 0 and self.paid_accrual_entries:
-
- interest_paid = paid_amount - self.penalty_amount
-
- for lia, interest_amount in iteritems(paid_accrual_entries):
- if interest_amount <= interest_paid:
- paid_entries.append(lia)
- interest_paid -= interest_amount
- elif interest_paid:
- self.partial_paid_entry = frappe.as_json({"name": lia, "interest_amount": interest_amount})
- frappe.db.set_value("Loan Interest Accrual", lia, "interest_amount",
- interest_amount - interest_paid)
- interest_paid = 0
-
- if paid_entries:
- self.paid_accrual_entries = frappe.as_json(paid_entries)
- else:
- self.paid_accrual_entries = ""
-
- if interest_paid:
- self.principal_amount_paid = interest_paid
-
- if paid_entries:
- frappe.db.sql("""UPDATE `tabLoan Interest Accrual`
- SET is_paid = 1 where name in (%s)""" #nosec
- % ", ".join(['%s']*len(paid_entries)), tuple(paid_entries))
+ for payment in self.repayment_details:
+ frappe.db.sql(""" UPDATE `tabLoan Interest Accrual`
+ SET paid_principal_amount = `paid_principal_amount` + %s,
+ paid_interest_amount = `paid_interest_amount` + %s
+ WHERE name = %s""",
+ (flt(payment.paid_principal_amount), flt(payment.paid_interest_amount), payment.loan_interest_accrual))
if flt(loan.total_principal_paid + self.principal_amount_paid, 2) >= flt(loan.total_payment, 2):
frappe.db.set_value("Loan", self.against_loan, "status", "Loan Closure Requested")
@@ -116,21 +87,14 @@
update_shortfall_status(self.against_loan, self.principal_amount_paid)
def mark_as_unpaid(self):
-
loan = frappe.get_doc("Loan", self.against_loan)
- if self.paid_accrual_entries:
- paid_accrual_entries = json.loads(self.paid_accrual_entries)
-
- if self.paid_accrual_entries:
- frappe.db.sql("""UPDATE `tabLoan Interest Accrual`
- SET is_paid = 0 where name in (%s)""" #nosec
- % ", ".join(['%s']*len(paid_accrual_entries)), tuple(paid_accrual_entries))
-
- if self.partial_paid_entry:
- partial_paid_entry = json.loads(self.partial_paid_entry)
- frappe.db.set_value("Loan Interest Accrual", partial_paid_entry["name"], "interest_amount",
- partial_paid_entry["interest_amount"])
+ for payment in self.repayment_details:
+ frappe.db.sql(""" UPDATE `tabLoan Interest Accrual`
+ SET paid_principal_amount = `paid_principal_amount` - %s,
+ paid_interest_amount = `paid_interest_amount` - %s
+ WHERE name = %s""",
+ (payment.paid_principal_amount, payment.paid_interest_amount, payment.loan_interest_accrual))
frappe.db.sql(""" UPDATE `tabLoan` SET total_amount_paid = %s, total_principal_paid = %s
WHERE name = %s """, (loan.total_amount_paid - self.amount_paid,
@@ -139,6 +103,38 @@
if loan.status == "Loan Closure Requested":
frappe.db.set_value("Loan", self.against_loan, "status", "Disbursed")
+ def allocate_amounts(self, paid_entries):
+ self.set('repayment_details', [])
+ self.principal_amount_paid = 0
+
+ if self.amount_paid - self.penalty_amount > 0 and paid_entries:
+ interest_paid = self.amount_paid - self.penalty_amount
+ for lia, amounts in iteritems(paid_entries):
+ if amounts['interest_amount'] + amounts['payable_principal_amount'] <= interest_paid:
+ interest_amount = amounts['interest_amount']
+ paid_principal = amounts['payable_principal_amount']
+ self.principal_amount_paid += paid_principal
+ interest_paid -= (interest_amount + paid_principal)
+ elif interest_paid:
+ if interest_paid >= amounts['interest_amount']:
+ interest_amount = amounts['interest_amount']
+ paid_principal = interest_paid - interest_amount
+ self.principal_amount_paid += paid_principal
+ interest_paid = 0
+ else:
+ interest_amount = interest_paid
+ interest_paid = 0
+ paid_principal=0
+
+ self.append('repayment_details', {
+ 'loan_interest_accrual': lia,
+ 'paid_interest_amount': interest_amount,
+ 'paid_principal_amount': paid_principal
+ })
+
+ if interest_paid:
+ self.principal_amount_paid += interest_paid
+
def make_gl_entries(self, cancel=0, adv_adj=0):
gle_map = []
loan_details = frappe.get_doc("Loan", self.against_loan)
@@ -210,7 +206,7 @@
)
if gle_map:
- make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj)
+ make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj, merge_entries=False)
def create_repayment_entry(loan, applicant, company, posting_date, loan_type,
payment_type, interest_payable, payable_principal_amount, amount_paid, penalty_amount=None):
@@ -223,7 +219,7 @@
"posting_date": posting_date,
"applicant": applicant,
"penalty_amount": penalty_amount,
- "interets_payable": interest_payable,
+ "interest_payable": interest_payable,
"payable_principal_amount": payable_principal_amount,
"amount_paid": amount_paid,
"loan_type": loan_type
@@ -232,14 +228,22 @@
return lr
def get_accrued_interest_entries(against_loan):
- accrued_interest_entries = frappe.get_all("Loan Interest Accrual",
- fields=["name", "interest_amount", "posting_date", "payable_principal_amount"],
- filters = {
- "loan": against_loan,
- "is_paid": 0
- }, order_by="posting_date")
- return accrued_interest_entries
+ unpaid_accrued_entries = frappe.db.sql(
+ """
+ SELECT name, posting_date, interest_amount - paid_interest_amount as interest_amount,
+ payable_principal_amount - paid_principal_amount as payable_principal_amount
+ FROM
+ `tabLoan Interest Accrual`
+ WHERE
+ loan = %s
+ AND (interest_amount - paid_interest_amount > 0 OR
+ payable_principal_amount - paid_principal_amount > 0)
+ AND
+ docstatus = 1
+ """, (against_loan), as_dict=1)
+
+ return unpaid_accrued_entries
# This function returns the amounts that are payable at the time of loan repayment based on posting date
# So it pulls all the unpaid Loan Interest Accrual Entries and calculates the penalty if applicable
@@ -272,7 +276,11 @@
total_pending_interest += entry.interest_amount
payable_principal_amount += entry.payable_principal_amount
- pending_accrual_entries.setdefault(entry.name, entry.interest_amount)
+ pending_accrual_entries.setdefault(entry.name, {
+ 'interest_amount': flt(entry.interest_amount),
+ 'payable_principal_amount': flt(entry.payable_principal_amount)
+ })
+
final_due_date = due_date
pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
@@ -288,7 +296,7 @@
amounts["interest_amount"] = total_pending_interest
amounts["penalty_amount"] = penalty_amount
amounts["payable_amount"] = payable_principal_amount + total_pending_interest + penalty_amount
- amounts["paid_accrual_entries"] = pending_accrual_entries
+ amounts["pending_accrual_entries"] = pending_accrual_entries
if final_due_date:
amounts["due_date"] = final_due_date
diff --git a/erpnext/healthcare/page/appointment_analytic/__init__.py b/erpnext/loan_management/doctype/loan_repayment_detail/__init__.py
similarity index 100%
copy from erpnext/healthcare/page/appointment_analytic/__init__.py
copy to erpnext/loan_management/doctype/loan_repayment_detail/__init__.py
diff --git a/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.json b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.json
new file mode 100644
index 0000000..cff1dbb
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.json
@@ -0,0 +1,43 @@
+{
+ "actions": [],
+ "creation": "2020-04-15 18:31:54.026923",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "loan_interest_accrual",
+ "paid_principal_amount",
+ "paid_interest_amount"
+ ],
+ "fields": [
+ {
+ "fieldname": "loan_interest_accrual",
+ "fieldtype": "Link",
+ "label": "Loan Interest Accrual",
+ "options": "Loan Interest Accrual"
+ },
+ {
+ "fieldname": "paid_principal_amount",
+ "fieldtype": "Currency",
+ "label": "Paid Principal Amount",
+ "options": "Company:company:default_currency"
+ },
+ {
+ "fieldname": "paid_interest_amount",
+ "fieldtype": "Currency",
+ "label": "Paid Interest Amount",
+ "options": "Company:company:default_currency"
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-15 21:50:03.837019",
+ "modified_by": "Administrator",
+ "module": "Loan Management",
+ "name": "Loan Repayment Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.py b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.py
new file mode 100644
index 0000000..a83b9b5
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class LoanRepaymentDetail(Document):
+ pass
diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
index b7be84f..ab040f1 100644
--- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
+++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
@@ -37,17 +37,10 @@
return loan_security_pledge.as_dict()
-def check_for_ltv_shortfall(process_loan_security_shortfall=None):
+def check_for_ltv_shortfall(process_loan_security_shortfall):
update_time = get_datetime()
- if not process_loan_security_shortfall:
- process = frappe.new_doc("Process Loan Security Shortfall")
- process.update_time = update_time
- process.submit()
-
- process_loan_security_shortfall = process.name
-
loan_security_price_map = frappe._dict(frappe.get_all("Loan Security Price",
fields=["loan_security", "loan_security_price"],
filters = {
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index a3525db..51c5cb9 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -119,6 +119,7 @@
"label": "Penalty Interest Rate (%) Per Day"
},
{
+ "description": "No. of days from due date until which penalty won't be charged in case of delay in loan repayment",
"fieldname": "grace_period_in_days",
"fieldtype": "Int",
"label": "Grace Period in Days"
@@ -142,7 +143,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-02-03 05:03:00.334813",
+ "modified": "2020-04-15 00:24:43.259963",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Type",
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.py b/erpnext/loan_management/doctype/loan_type/loan_type.py
index 14b18ab..208cb19 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.py
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.py
@@ -19,3 +19,6 @@
frappe.throw(_("Account {0} does not belong to company {1}").format(frappe.bold(self.get(fieldname)),
frappe.bold(self.company)))
+ if self.get('loan_account') == self.get('payment_account'):
+ frappe.throw(_('Loan Account and Payment Account cannot be same'))
+
diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
index 7f79cb1..0ef098f 100644
--- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
+++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
@@ -9,6 +9,7 @@
"posting_date",
"loan_type",
"loan",
+ "process_type",
"amended_from"
],
"fields": [
@@ -39,11 +40,18 @@
"fieldtype": "Link",
"label": "Loan ",
"options": "Loan"
+ },
+ {
+ "fieldname": "process_type",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Process Type",
+ "read_only": 1
}
],
"is_submittable": 1,
"links": [],
- "modified": "2020-02-01 08:14:33.978636",
+ "modified": "2020-04-09 22:52:53.911416",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Process Loan Interest Accrual",
@@ -74,7 +82,6 @@
"write": 1
}
],
- "quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
index 0f33da9..cd3cf7e 100644
--- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
@@ -6,7 +6,8 @@
import frappe
from frappe.utils import nowdate
from frappe.model.document import Document
-from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import make_accrual_interest_entry_for_demand_loans
+from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import (make_accrual_interest_entry_for_demand_loans,
+ make_accrual_interest_entry_for_term_loans)
class ProcessLoanInterestAccrual(Document):
def on_submit(self):
@@ -14,16 +15,45 @@
if self.loan:
loan_doc = frappe.get_doc('Loan', self.loan)
- open_loans.append(loan_doc)
+ if loan_doc:
+ open_loans.append(loan_doc)
- make_accrual_interest_entry_for_demand_loans(self.posting_date, self.name,
- open_loans = open_loans, loan_type = self.loan_type)
+ if (not self.loan or not loan_doc.is_term_loan) and self.process_type != 'Term Loans':
+ make_accrual_interest_entry_for_demand_loans(self.posting_date, self.name,
+ open_loans = open_loans, loan_type = self.loan_type)
-def process_loan_interest_accrual(posting_date=None, loan_type=None, loan=None):
+ if (not self.loan or loan_doc.is_term_loan) and self.process_type != 'Demand Loans':
+ make_accrual_interest_entry_for_term_loans(self.posting_date, self.name, term_loan=self.loan,
+ loan_type=self.loan_type)
+
+
+def process_loan_interest_accrual_for_demand_loans(posting_date=None, loan_type=None, loan=None):
loan_process = frappe.new_doc('Process Loan Interest Accrual')
loan_process.posting_date = posting_date or nowdate()
loan_process.loan_type = loan_type
+ loan_process.process_type = 'Demand Loans'
loan_process.loan = loan
loan_process.submit()
+def process_loan_interest_accrual_for_term_loans(posting_date=None, loan_type=None, loan=None):
+
+ if not term_loan_accrual_pending(posting_date or nowdate()):
+ return
+
+ loan_process = frappe.new_doc('Process Loan Interest Accrual')
+ loan_process.posting_date = posting_date or nowdate()
+ loan_process.loan_type = loan_type
+ loan_process.process_type = 'Term Loans'
+ loan_process.loan = loan
+
+ loan_process.submit()
+
+def term_loan_accrual_pending(date):
+ pending_accrual = frappe.db.get_value('Repayment Schedule', {
+ 'payment_date': ('<=', date),
+ 'is_accrued': 0
+ })
+
+ return pending_accrual
+
diff --git a/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py b/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py
index 417e367..b4aad25 100644
--- a/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py
+++ b/erpnext/loan_management/doctype/process_loan_security_shortfall/process_loan_security_shortfall.py
@@ -14,4 +14,13 @@
self.set_onload('update_time', get_datetime())
def on_submit(self):
- check_for_ltv_shortfall(process_loan_security_shortfall = self.name)
+ check_for_ltv_shortfall(self.name)
+
+def create_process_loan_security_shortfall():
+ if check_for_secured_loans():
+ process = frappe.new_doc("Process Loan Security Shortfall")
+ process.update_time = get_datetime()
+ process.submit()
+
+def check_for_secured_loans():
+ return frappe.db.count('Loan', {'docstatus': 1, 'is_secured_loan': 1})
diff --git a/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json b/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json
index ce020ff..2f4fe24 100644
--- a/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json
+++ b/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"creation": "2019-08-29 18:11:36.829526",
"doctype": "DocType",
"editable_grid": 1,
@@ -27,7 +28,6 @@
{
"fieldname": "loan_account",
"fieldtype": "Link",
- "in_list_view": 1,
"label": "Loan Account",
"options": "Account",
"read_only": 1
@@ -63,9 +63,9 @@
{
"fieldname": "total_payment",
"fieldtype": "Currency",
+ "in_list_view": 1,
"label": "Total Payment",
- "options": "Company:company:default_currency",
- "read_only": 1
+ "options": "Company:company:default_currency"
},
{
"fieldname": "loan_repayment_entry",
@@ -79,11 +79,13 @@
"fieldname": "loan_type",
"fieldtype": "Link",
"label": "Loan Type",
- "options": "Loan Type"
+ "options": "Loan Type",
+ "read_only": 1
}
],
"istable": 1,
- "modified": "2019-10-28 09:15:31.174244",
+ "links": [],
+ "modified": "2020-04-16 13:17:04.798335",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Salary Slip Loan",
diff --git a/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json b/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json
index 6127ef6..18604e2 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/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js
index 8c7876d..bab0dfb 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card.js
@@ -82,7 +82,9 @@
frm.set_value('current_time' , 0);
}
- frm.save();
+ frm.save("Save", () => {}, "", () => {
+ frm.doc.time_logs.pop(-1);
+ });
},
complete_job: function(frm, completed_time, completed_qty) {
@@ -105,6 +107,24 @@
});
},
+ validate: function(frm) {
+ if ((!frm.doc.time_logs || !frm.doc.time_logs.length) && frm.doc.started_time) {
+ frm.trigger("reset_timer");
+ }
+ },
+
+ employee: function(frm) {
+ if (frm.doc.job_started && !frm.doc.current_time) {
+ frm.trigger("reset_timer");
+ }
+ },
+
+ reset_timer: function(frm) {
+ frm.set_value('started_time' , '');
+ frm.set_value('job_started', 0);
+ frm.set_value('current_time' , 0);
+ },
+
make_dashboard: function(frm) {
if(frm.doc.__islocal)
return;
@@ -137,12 +157,12 @@
updateStopwatch(current);
}, 1000);
}
-
+
function updateStopwatch(increment) {
var hours = Math.floor(increment / 3600);
var minutes = Math.floor((increment - (hours * 3600)) / 60);
var seconds = increment - (hours * 3600) - (minutes * 60);
-
+
$(section).find(".hours").text(hours < 10 ? ("0" + hours.toString()) : hours.toString());
$(section).find(".minutes").text(minutes < 10 ? ("0" + minutes.toString()) : minutes.toString());
$(section).find(".seconds").text(seconds < 10 ? ("0" + seconds.toString()) : seconds.toString());
@@ -205,5 +225,10 @@
frappe.ui.form.on('Job Card Time Log', {
completed_qty: function(frm) {
frm.events.set_total_completed_qty(frm);
+ },
+
+ to_time: function(frm) {
+ frm.set_value('job_started', 0);
+ frm.set_value('started_time', '');
}
})
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index f8c60f2..e9627a5 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -9,7 +9,7 @@
from frappe.model.mapper import get_mapped_doc
from frappe.model.document import Document
from frappe.utils import (flt, cint, time_diff_in_hours, get_datetime, getdate,
- get_time, add_to_date, time_diff, add_days, get_datetime_str)
+ get_time, add_to_date, time_diff, add_days, get_datetime_str, get_link_to_form)
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
@@ -189,11 +189,15 @@
def validate_job_card(self):
if not self.time_logs:
- frappe.throw(_("Time logs are required for job card {0}").format(self.name))
+ frappe.throw(_("Time logs are required for {0} {1}")
+ .format(frappe.bold("Job Card"), get_link_to_form("Job Card", self.name)))
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))))
+ total_completed_qty = frappe.bold(_("Total Completed Qty"))
+ qty_to_manufacture = frappe.bold(_("Qty to Manufacture"))
+
+ frappe.throw(_("The {0} ({1}) must be equal to {2} ({3})"
+ .format(total_completed_qty, frappe.bold(self.total_completed_qty), qty_to_manufacture,frappe.bold(self.for_quantity))))
def update_work_order(self):
if not self.work_order:
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 9c8aa45..d541866 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -240,6 +240,8 @@
});
}, __("Job Card"), __("Create"));
+ dialog.fields_dict["operations"].grid.wrapper.find('.grid-add-row').hide();
+
var pending_qty = 0;
frm.doc.operations.forEach(data => {
if(data.completed_qty != frm.doc.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 5d759ba..a476857 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 ff58f40..86af3de 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -662,4 +662,9 @@
erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
erpnext.patches.v12_0.rename_bank_reconciliation
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
\ No newline at end of file
+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.update_healthcare_refactored_changes
+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 145ed45..1ddca93 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/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py
index 31d500e..8889056 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 @@
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 0000000..8267df9
--- /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 0000000..e08e376
--- /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_against_blanket_order_in_sales_and_purchase_order.py b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
index 3fccbfa..85202bf 100644
--- a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
+++ b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
@@ -1,10 +1,11 @@
import frappe
+
def execute():
- frappe.reload_doc('selling', 'doctype', frappe.scrub('Sales Order Item'))
- frappe.reload_doc('buying', 'doctype', frappe.scrub('Purchase Order Item'))
+ frappe.reload_doc('selling', 'doctype', 'sales_order_item', force=True)
+ frappe.reload_doc('buying', 'doctype', 'purchase_order_item', force=True)
- for doctype in ['Sales Order Item', 'Purchase Order Item']:
+ for doctype in ('Sales Order Item', 'Purchase Order Item'):
frappe.db.sql("""
UPDATE `tab{0}`
SET against_blanket_order = 1
diff --git a/erpnext/patches/v12_0/set_task_status.py b/erpnext/patches/v12_0/set_task_status.py
index 70f6509..dbd7e5a 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 0000000..d373275
--- /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 0000000..63ca540
--- /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/v12_0/update_healthcare_refactored_changes.py b/erpnext/patches/v12_0/update_healthcare_refactored_changes.py
new file mode 100644
index 0000000..d06c571
--- /dev/null
+++ b/erpnext/patches/v12_0/update_healthcare_refactored_changes.py
@@ -0,0 +1,137 @@
+from __future__ import unicode_literals
+import frappe
+from frappe.model.utils.rename_field import rename_field
+from frappe.modules import scrub, get_doctype_module
+
+field_rename_map = {
+ 'Healthcare Settings': [
+ ['patient_master_name', 'patient_name_by'],
+ ['max_visit', 'max_visits'],
+ ['reg_sms', 'send_registration_msg'],
+ ['reg_msg', 'registration_msg'],
+ ['app_con', 'send_appointment_confirmation'],
+ ['app_con_msg', 'appointment_confirmation_msg'],
+ ['no_con', 'avoid_confirmation'],
+ ['app_rem', 'send_appointment_reminder'],
+ ['app_rem_msg', 'appointment_reminder_msg'],
+ ['rem_before', 'remind_before'],
+ ['manage_customer', 'link_customer_to_patient'],
+ ['create_test_on_si_submit', 'create_lab_test_on_si_submit'],
+ ['require_sample_collection', 'create_sample_collection_for_lab_test'],
+ ['require_test_result_approval', 'lab_test_approval_required'],
+ ['manage_appointment_invoice_automatically', 'automate_appointment_invoicing']
+ ],
+ 'Drug Prescription':[
+ ['use_interval', 'usage_interval'],
+ ['in_every', 'interval_uom']
+ ],
+ 'Lab Test Template':[
+ ['sample_quantity', 'sample_qty'],
+ ['sample_collection_details', 'sample_details']
+ ],
+ 'Sample Collection':[
+ ['sample_quantity', 'sample_qty'],
+ ['sample_collection_details', 'sample_details']
+ ],
+ 'Fee Validity': [
+ ['max_visit', 'max_visits']
+ ]
+}
+
+def execute():
+ for dn in field_rename_map:
+ if frappe.db.exists('DocType', dn):
+ if dn == 'Healthcare Settings':
+ frappe.reload_doctype('Healthcare Settings')
+ else:
+ frappe.reload_doc(get_doctype_module(dn), "doctype", scrub(dn))
+
+ for dt, field_list in field_rename_map.items():
+ if frappe.db.exists('DocType', dt):
+ for field in field_list:
+ if dt == 'Healthcare Settings':
+ rename_field(dt, field[0], field[1])
+ elif frappe.db.has_column(dt, field[0]):
+ rename_field(dt, field[0], field[1])
+
+ # first name mandatory in Patient
+ if frappe.db.exists('DocType', 'Patient'):
+ patients = frappe.db.sql("select name, patient_name from `tabPatient`", as_dict=1)
+ frappe.reload_doc('healthcare', 'doctype', 'patient')
+ for entry in patients:
+ name = entry.patient_name.split(' ')
+ frappe.db.set_value('Patient', entry.name, 'first_name', name[0])
+
+ # mark Healthcare Practitioner status as Disabled
+ if frappe.db.exists('DocType', 'Healthcare Practitioner'):
+ practitioners = frappe.db.sql("select name from `tabHealthcare Practitioner` where 'active'= 0", as_dict=1)
+ practitioners_lst = [p.name for p in practitioners]
+ frappe.reload_doc('healthcare', 'doctype', 'healthcare_practitioner')
+ if practitioners_lst:
+ frappe.db.sql("update `tabHealthcare Practitioner` set status = 'Disabled' where name IN %(practitioners)s""", {"practitioners": practitioners_lst})
+
+ # set Clinical Procedure status
+ if frappe.db.exists('DocType', 'Clinical Procedure'):
+ frappe.reload_doc('healthcare', 'doctype', 'clinical_procedure')
+ frappe.db.sql("""
+ UPDATE
+ `tabClinical Procedure`
+ SET
+ docstatus = (CASE WHEN status = 'Cancelled' THEN 2
+ WHEN status = 'Draft' THEN 0
+ ELSE 1
+ END)
+ """)
+
+ # set complaints and diagnosis in table multiselect in Patient Encounter
+ if frappe.db.exists('DocType', 'Patient Encounter'):
+ field_list = [
+ ['visit_department', 'medical_department'],
+ ['type', 'appointment_type']
+ ]
+ encounter_details = frappe.db.sql("""select symptoms, diagnosis, name from `tabPatient Encounter`""", as_dict=True)
+ frappe.reload_doc('healthcare', 'doctype', 'patient_encounter')
+ frappe.reload_doc('healthcare', 'doctype', 'patient_encounter_symptom')
+ frappe.reload_doc('healthcare', 'doctype', 'patient_encounter_diagnosis')
+
+ for field in field_list:
+ if frappe.db.has_column(dt, field[0]):
+ rename_field(dt, field[0], field[1])
+
+ for entry in encounter_details:
+ doc = frappe.get_doc('Patient Encounter', entry.name)
+ symptoms = entry.symptoms.split('\n') if entry.symptoms else []
+ for symptom in symptoms:
+ if not frappe.db.exists('Complaint', symptom):
+ frappe.get_doc({
+ 'doctype': 'Complaint',
+ 'complaints': symptom
+ }).insert()
+ row = doc.append('symptoms', {
+ 'complaint': symptom
+ })
+ row.db_update()
+
+ diagnosis = entry.diagnosis.split('\n') if entry.diagnosis else []
+ for d in diagnosis:
+ if not frappe.db.exists('Diagnosis', d):
+ frappe.get_doc({
+ 'doctype': 'Diagnosis',
+ 'diagnosis': d
+ }).insert()
+ row = doc.append('diagnosis', {
+ 'diagnosis': d
+ })
+ row.db_update()
+ doc.db_update()
+
+ if frappe.db.exists('DocType', 'Fee Validity'):
+ # update fee validity status
+ frappe.db.sql("""
+ UPDATE
+ `tabFee Validity`
+ SET
+ status = (CASE WHEN visited >= max_visits THEN 'Completed'
+ ELSE 'Pending'
+ END)
+ """)
\ 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 22fa53b..34255eb 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 @@
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 @@
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 13fd1b8..a07cdff 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.json b/erpnext/projects/doctype/project/project.json
index 7d47db3..f3cecd9 100644
--- a/erpnext/projects/doctype/project/project.json
+++ b/erpnext/projects/doctype/project/project.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:project_name",
@@ -82,7 +83,6 @@
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "Open\nCompleted\nCancelled",
- "reqd": 1,
"search_index": 1
},
{
@@ -435,16 +435,18 @@
},
{
"depends_on": "collect_progress",
- "description": "Message will sent to users to get their status on the project",
+ "description": "Message will be sent to the users to get their status on the Project",
"fieldname": "message",
"fieldtype": "Text",
- "label": "Message"
+ "label": "Message",
+ "mandatory_depends_on": "collect_progress"
}
],
"icon": "fa fa-puzzle-piece",
"idx": 29,
+ "links": [],
"max_attachments": 4,
- "modified": "2019-09-24 15:02:50.208301",
+ "modified": "2020-04-08 22:11:14.552615",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",
@@ -487,4 +489,4 @@
"sort_order": "DESC",
"timeline_field": "customer",
"track_seen": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/projects/report/billing_summary.py b/erpnext/projects/report/billing_summary.py
index 76379f1..b808268 100644
--- a/erpnext/projects/report/billing_summary.py
+++ b/erpnext/projects/report/billing_summary.py
@@ -53,7 +53,7 @@
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 615f6a4..9870f81 100644
--- a/erpnext/public/js/conf.js
+++ b/erpnext/public/js/conf.js
@@ -43,7 +43,6 @@
$.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 3d4c4a6..afbdbc6 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -85,12 +85,6 @@
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",
@@ -385,7 +379,31 @@
}
});
}
- }
+ },
+
+ manufacturer_part_no: function(doc, cdt, cdn) {
+ const row = locals[cdt][cdn];
+
+ if (row.manufacturer_part_no) {
+ frappe.model.get_value('Item Manufacturer',
+ {
+ 'item_code': row.item_code,
+ 'manufacturer': row.manufacturer,
+ 'manufacturer_part_no': row.manufacturer_part_no
+ },
+ 'name',
+ function(data) {
+ if (!data) {
+ let msg = {
+ message: __("Manufacturer Part Number <b>{0}</b> is invalid", [row.manufacturer_part_no]),
+ title: __("Invalid Part Number")
+ }
+ frappe.throw(msg);
+ }
+ });
+
+ }
+ }
});
cur_frm.add_fetch('project', 'cost_center', 'cost_center');
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 4397fe4..f126f6a 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -473,6 +473,7 @@
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,
@@ -550,6 +551,10 @@
if(!d[k]) d[k] = v;
});
+ if (d.has_batch_no && d.has_serial_no) {
+ d.batch_no = undefined;
+ }
+
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)
@@ -558,7 +563,13 @@
}
},
() => me.conversion_factor(doc, cdt, cdn, true),
- () => me.remove_pricing_rule(item)
+ () => me.remove_pricing_rule(item),
+ () => {
+ if (item.apply_rule_on_other_items) {
+ let key = item.name;
+ me.apply_rule_on_other_items({key: item});
+ }
+ }
]);
}
}
@@ -637,6 +648,7 @@
// 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)) {
@@ -892,7 +904,7 @@
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",
@@ -1392,20 +1404,22 @@
apply_rule_on_other_items: function(args) {
const me = this;
- const fields = ["discount_percentage", "discount_amount", "rate"];
+ const fields = ["discount_percentage", "pricing_rules", "discount_amount", "rate"];
for(var k in args) {
let data = args[k];
- me.frm.doc.items.forEach(d => {
- if (in_list(data.apply_rule_on_other_items, d[data.apply_rule_on])) {
- for(var k in data) {
- if (in_list(fields, k)) {
- frappe.model.set_value(d.doctype, d.name, k, data[k]);
+ if (data && data.apply_rule_on_other_items) {
+ me.frm.doc.items.forEach(d => {
+ if (in_list(data.apply_rule_on_other_items, d[data.apply_rule_on])) {
+ for(var k in data) {
+ if (in_list(fields, k) && data[k]) {
+ frappe.model.set_value(d.doctype, d.name, k, data[k]);
+ }
}
}
- }
- });
+ });
+ }
}
},
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index dead309..296c628 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -79,6 +79,39 @@
"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"),
"fieldtype": "Link",
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 4d44eae..58969f2 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -436,6 +436,44 @@
const cannot_add_row = (typeof opts.cannot_add_row === 'undefined') ? true : opts.cannot_add_row;
const child_docname = (typeof opts.cannot_add_row === 'undefined') ? "items" : opts.child_docname;
this.data = [];
+ const fields = [{
+ fieldtype:'Data',
+ fieldname:"docname",
+ read_only: 1,
+ hidden: 1,
+ }, {
+ fieldtype:'Link',
+ fieldname:"item_code",
+ options: 'Item',
+ in_list_view: 1,
+ read_only: 0,
+ disabled: 0,
+ label: __('Item Code')
+ }, {
+ fieldtype:'Float',
+ fieldname:"qty",
+ default: 0,
+ read_only: 0,
+ in_list_view: 1,
+ label: __('Qty')
+ }, {
+ fieldtype:'Currency',
+ fieldname:"rate",
+ default: 0,
+ read_only: 0,
+ in_list_view: 1,
+ label: __('Rate')
+ }];
+
+ if (frm.doc.doctype == 'Sales Order' || frm.doc.doctype == 'Purchase Order' ) {
+ fields.splice(2, 0, {
+ fieldtype: 'Date',
+ fieldname: frm.doc.doctype == 'Sales Order' ? "delivery_date" : "schedule_date",
+ in_list_view: 1,
+ label: frm.doc.doctype == 'Sales Order' ? __("Delivery Date") : __("Reqd by date")
+ })
+ }
+
const dialog = new frappe.ui.Dialog({
title: __("Update Items"),
fields: [
@@ -450,34 +488,7 @@
get_data: () => {
return this.data;
},
- fields: [{
- fieldtype:'Data',
- fieldname:"docname",
- read_only: 1,
- hidden: 1,
- }, {
- fieldtype:'Link',
- fieldname:"item_code",
- options: 'Item',
- in_list_view: 1,
- read_only: 0,
- disabled: 0,
- label: __('Item Code')
- }, {
- fieldtype:'Float',
- fieldname:"qty",
- default: 0,
- read_only: 0,
- in_list_view: 1,
- label: __('Qty')
- }, {
- fieldtype:'Currency',
- fieldname:"rate",
- default: 0,
- read_only: 0,
- in_list_view: 1,
- label: __('Rate')
- }]
+ fields: fields
},
],
primary_action: function() {
@@ -506,6 +517,8 @@
"docname": d.name,
"name": d.name,
"item_code": d.item_code,
+ "delivery_date": d.delivery_date,
+ "schedule_date": d.schedule_date,
"qty": d.qty,
"rate": d.rate,
});
diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss
index 7b9a70d..735b417 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 5193e0c..5ee7000 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 0000000..9915734
--- /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 }}<br>
+{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}
+{{ city }}<br>
+{% if state %}{{ state }}<br>{% endif -%}
+{% if pincode %} PIN: {{ pincode }}<br>{% endif -%}
+{{ country }}<br>
+{% if phone %}Phone: {{ phone }}<br>{% endif -%}
+{% if fax %}Fax: {{ fax }}<br>{% endif -%}
+{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
+```
diff --git a/erpnext/healthcare/page/appointment_analytic/__init__.py b/erpnext/regional/address_template/__init__.py
similarity index 100%
copy from erpnext/healthcare/page/appointment_analytic/__init__.py
copy to erpnext/regional/address_template/__init__.py
diff --git a/erpnext/regional/address_template/setup.py b/erpnext/regional/address_template/setup.py
new file mode 100644
index 0000000..9f318de
--- /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 99%
rename from erpnext/regional/india/address_template.html
rename to erpnext/regional/address_template/templates/india.html
index 55cc9af..ffb9d05 100644
--- a/erpnext/regional/india/address_template.html
+++ b/erpnext/regional/address_template/templates/india.html
@@ -6,4 +6,4 @@
{% if phone %}Phone: {{ phone }}<br>{% endif -%}
{% if fax %}Fax: {{ fax }}<br>{% endif -%}
{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
-{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}
\ No newline at end of file
+{% if gstin %}GSTIN: {{ gstin }}<br>{% 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 0000000..8a05ea2
--- /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.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index a2b32fe..9e7a023 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 @@
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 @@
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 @@
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 a547136..d6047e8 100644
--- a/erpnext/regional/germany/setup.py
+++ b/erpnext/regional/germany/setup.py
@@ -3,29 +3,4 @@
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 75f29b8..28b1f8f 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -13,7 +13,6 @@
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 @@
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:
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index a657912..a8e40cc 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -13,6 +13,7 @@
import zlib
import zipfile
import six
+from csv import QUOTE_NONNUMERIC
from six import BytesIO
from six import string_types
import frappe
@@ -80,7 +81,7 @@
gl.posting_date as 'Belegdatum',
gl.voucher_no as 'Belegfeld 1',
- gl.remarks as 'Buchungstext',
+ 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',
@@ -268,7 +269,9 @@
# 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:
@@ -285,6 +288,7 @@
def get_header(filters, csv_class):
coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts")
+ description = filters.get("voucher_type", csv_class.FORMAT_NAME)
coa_used = "04" if "SKR04" in coa else ("03" if "SKR03" in coa else "")
header = [
@@ -323,12 +327,8 @@
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
diff --git a/erpnext/regional/united_states/setup.py b/erpnext/regional/united_states/setup.py
index cb82b63..6d34402 100644
--- a/erpnext/regional/united_states/setup.py
+++ b/erpnext/regional/united_states/setup.py
@@ -5,12 +5,9 @@
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 @@
}
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 }}<br>
- {% if address_line2 %}{{ address_line2 }}<br>{% endif -%}
- {{ city }}, {% if state %}{{ state }}{% endif -%}{% if pincode %} {{ pincode }}<br>{% 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 9838462..9f3912d 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 7a0111c..a20806b 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.py b/erpnext/selling/doctype/customer/customer.py
index 02667e8..50e719f 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -150,7 +150,7 @@
contact.save()
else:
- lead.lead_name = lead.lead_name.split(" ")
+ lead.lead_name = lead.lead_name.lstrip().split(" ")
lead.first_name = lead.lead_name[0]
lead.last_name = " ".join(lead.lead_name[1:])
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 54e87f7..6462d3b 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -60,9 +60,9 @@
"base_total",
"base_net_total",
"column_break_33",
+ "total_net_weight",
"total",
"net_total",
- "total_net_weight",
"taxes_section",
"tax_category",
"column_break_38",
@@ -1196,7 +1196,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2019-12-30 19:15:28.605085",
+ "modified": "2020-04-17 12:50:39.640534",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index ef2d19a..05e4aa8 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -1036,7 +1036,7 @@
},
}, 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.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index df48783..7011cf9 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -287,7 +287,7 @@
if (in_list(['serial_no', 'batch_no'], field)) {
args[field] = value;
}
-
+
// add to cur_frm
const item = this.frm.add_child('items', args);
frappe.flags.hide_serial_batch_dialog = true;
@@ -1176,7 +1176,7 @@
return `
<div class="list-item indicator ${indicator_class}" data-item-code="${escape(item.item_code)}"
- data-batch-no="${batch_no}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
+ data-batch-no="${batch_no}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty} ${item.stock_uom}">
<div class="item-name list-item__content list-item__content--flex-1.5 ellipsis">
${item.item_name}
</div>
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 17136e0..dfa0f7f 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -37,20 +37,33 @@
lft, rgt = frappe.db.get_value('Item Group', item_group, ['lft', 'rgt'])
# locate function is used to sort by closest match from the beginning of the value
-
result = []
- items_data = frappe.db.sql(""" SELECT name as item_code,
- item_name, image as item_image, idx as idx,is_stock_item
+ items_data = frappe.db.sql("""
+ SELECT
+ name AS item_code,
+ item_name,
+ stock_uom,
+ image AS item_image,
+ idx AS idx,
+ is_stock_item
FROM
`tabItem`
WHERE
- disabled = 0 and has_variants = 0 and is_sales_item = 1
- and item_group in (select name from `tabItem Group` where lft >= {lft} and rgt <= {rgt})
- and {condition} order by idx desc limit {start}, {page_length}"""
+ disabled = 0
+ AND has_variants = 0
+ AND is_sales_item = 1
+ AND item_group in (SELECT name FROM `tabItem Group` WHERE lft >= {lft} AND rgt <= {rgt})
+ AND {condition}
+ ORDER BY
+ idx desc
+ LIMIT
+ {start}, {page_length}"""
.format(
- start=start, page_length=page_length,
- lft=lft, rgt=rgt,
+ start=start,
+ page_length=page_length,
+ lft=lft,
+ rgt=rgt,
condition=condition
), as_dict=1)
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index af10069..095b7c3 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -228,9 +228,15 @@
warehouse: function(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
+
+ if (item.serial_no && item.qty === item.serial_no.split(`\n`).length) {
+ return;
+ }
+
if (item.serial_no && !item.batch_no) {
item.serial_no = null;
}
+
var has_batch_no;
frappe.db.get_value('Item', {'item_code': item.item_code}, 'has_batch_no', (r) => {
has_batch_no = r && r.has_batch_no;
diff --git a/erpnext/setup/desk_page/erpnext_settings/erpnext_settings.json b/erpnext/setup/desk_page/erpnext_settings/erpnext_settings.json
index ac0a4b2..253d711 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 b045b5d..63d8984 100644
--- a/erpnext/setup/desk_page/getting_started/getting_started.json
+++ b/erpnext/setup/desk_page/getting_started/getting_started.json
@@ -1,40 +1,49 @@
{
"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",
@@ -54,7 +63,7 @@
"idx": 0,
"is_standard": 1,
"label": "Getting Started",
- "modified": "2020-03-23 11:20:49.161823",
+ "modified": "2020-04-01 11:30:19.763099",
"modified_by": "Administrator",
"module": "Setup",
"name": "Getting Started",
@@ -63,32 +72,32 @@
"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"
},
{
- "is_query_report": 0,
+ "label": "Dashboard",
"link_to": "dashboard",
"type": "Page"
},
{
- "is_query_report": 0,
+ "label": "Leaderboard",
"link_to": "leaderboard",
"type": "Page"
}
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index ebd7b50..e4986e3 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -8,9 +8,11 @@
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 @@
{ '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 @@
# 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 1dac9bd..e11e1bb 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -38,14 +38,14 @@
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 @@
# 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 @@
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/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js
index 1bfa2cf..9bd03d4 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -108,8 +108,8 @@
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")
- $("<span class='text-muted small'>"+message+"</span>").appendTo(this.result);
+ var message = __("Currently no stock available in any warehouse");
+ $(`<span class='text-muted small'> ${message} </span>`).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 779e61f..38475a6 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 e6d4e9d..1eb4577 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"
},
{
- "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"
+ },
+ {
"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_dashboard.py b/erpnext/stock/doctype/batch/batch_dashboard.py
new file mode 100644
index 0000000..eb6a97e
--- /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 7ee81aa..d4f74c3 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 32445a6..1fce504 100644
--- a/erpnext/stock/doctype/batch/test_batch.py
+++ b/erpnext/stock/doctype/batch/test_batch.py
@@ -7,7 +7,7 @@
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 @@
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 @@
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 @@
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.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 6f9d83d..9f5dee9 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -66,9 +66,9 @@
"base_total",
"base_net_total",
"column_break_33",
+ "total_net_weight",
"total",
"net_total",
- "total_net_weight",
"taxes_section",
"tax_category",
"column_break_39",
@@ -1256,7 +1256,7 @@
"idx": 146,
"is_submittable": 1,
"links": [],
- "modified": "2019-12-31 19:17:13.122644",
+ "modified": "2020-04-17 12:51:41.288600",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 30d82ca..dc96e7b 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -112,7 +112,6 @@
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 @@
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 dc92c5c..d7a93fb 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.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):
@@ -671,7 +672,7 @@
"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/item/item.json b/erpnext/stock/doctype/item/item.json
index aa6b2fe..7d2e311 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -114,6 +114,8 @@
"is_sub_contracted_item",
"column_break_74",
"customer_code",
+ "default_item_manufacturer",
+ "default_manufacturer_part_no",
"website_section",
"show_in_website",
"show_variant_in_website",
@@ -1038,6 +1040,18 @@
"fieldname": "auto_create_assets",
"fieldtype": "Check",
"label": "Auto Create Assets on Purchase"
+ },
+ {
+ "fieldname": "default_item_manufacturer",
+ "fieldtype": "Data",
+ "label": "Default Item Manufacturer",
+ "read_only": 1
+ },
+ {
+ "fieldname": "default_manufacturer_part_no",
+ "fieldtype": "Data",
+ "label": "Default Manufacturer Part No",
+ "read_only": 1
}
],
"has_web_view": 1,
@@ -1046,7 +1060,7 @@
"image_field": "image",
"links": [],
"max_attachments": 1,
- "modified": "2020-03-24 16:14:36.950677",
+ "modified": "2020-04-07 15:56:06.195722",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index e2e84c4..c62b3ab 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -101,6 +101,7 @@
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 @@
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 @@
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 @@
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")
@@ -1007,8 +1015,6 @@
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
@@ -1016,7 +1022,7 @@
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
@@ -1036,7 +1042,7 @@
"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/item_manufacturer/item_manufacturer.json b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.json
index 956c92e..0cef6ea 100644
--- a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.json
+++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"creation": "2019-06-02 04:41:37.332911",
"doctype": "DocType",
@@ -10,7 +11,8 @@
"manufacturer_part_no",
"column_break_3",
"item_name",
- "description"
+ "description",
+ "is_default"
],
"fields": [
{
@@ -52,9 +54,17 @@
"fieldtype": "Small Text",
"label": "Description",
"read_only": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "is_default",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Is Default"
}
],
- "modified": "2019-06-06 19:07:31.175919",
+ "links": [],
+ "modified": "2020-04-07 20:25:55.507905",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Manufacturer",
diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py
index 67eab82..c27d1be 100644
--- a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py
+++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py
@@ -11,6 +11,10 @@
class ItemManufacturer(Document):
def validate(self):
self.validate_duplicate_entry()
+ self.manage_default_item_manufacturer()
+
+ def on_trash(self):
+ self.manage_default_item_manufacturer(delete=True)
def validate_duplicate_entry(self):
if self.is_new():
@@ -24,6 +28,40 @@
frappe.throw(_("Duplicate entry against the item code {0} and manufacturer {1}")
.format(self.item_code, self.manufacturer))
+ def manage_default_item_manufacturer(self, delete=False):
+ from frappe.model.utils import set_default
+
+ item = frappe.get_doc("Item", self.item_code)
+ default_manufacturer = item.default_item_manufacturer
+ default_part_no = item.default_manufacturer_part_no
+
+ if not self.is_default:
+ # if unchecked and default in Item master, clear it.
+ if default_manufacturer == self.manufacturer and default_part_no == self.manufacturer_part_no:
+ frappe.db.set_value("Item", item.name,
+ {
+ "default_item_manufacturer": None,
+ "default_manufacturer_part_no": None
+ })
+
+ elif self.is_default:
+ set_default(self, "item_code")
+ manufacturer, manufacturer_part_no = default_manufacturer, default_part_no
+
+ if delete:
+ manufacturer, manufacturer_part_no = None, None
+
+ elif (default_manufacturer != self.manufacturer) or \
+ (default_manufacturer == self.manufacturer and default_part_no != self.manufacturer_part_no):
+ manufacturer = self.manufacturer
+ manufacturer_part_no = self.manufacturer_part_no
+
+ frappe.db.set_value("Item", item.name,
+ {
+ "default_item_manufacturer": manufacturer,
+ "default_manufacturer_part_no": manufacturer_part_no
+ })
+
@frappe.whitelist()
def get_item_manufacturer_part_no(item_code, manufacturer):
return frappe.db.get_value("Item Manufacturer",
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 6b26d38..6110ea8 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -19,11 +19,6 @@
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 @@
},
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 @@
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 285643d..2d98557 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -175,12 +175,11 @@
frappe.db.set_value(d.doctype, d.name, "ordered_qty", d.ordered_qty)
- target_ref_field = 'qty' if self.material_request_type == "Manufacture" else 'stock_qty'
self._update_percent_field({
"target_dt": "Material Request Item",
"target_parent_dt": self.doctype,
"target_parent_field": "per_ordered",
- "target_ref_field": target_ref_field,
+ "target_ref_field": "stock_qty",
"target_field": "ordered_qty",
"name": self.name,
}, update_modified)
@@ -454,6 +453,9 @@
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 +473,7 @@
"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": {
@@ -496,7 +498,7 @@
default_wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
for d in mr.items:
- if (d.qty - d.ordered_qty) >0:
+ if (d.stock_qty - d.ordered_qty) > 0:
if frappe.db.exists("BOM", {"item": d.item_code, "is_default": 1}):
wo_order = frappe.new_doc("Work Order")
wo_order.update({
@@ -528,7 +530,7 @@
msgprint(_("The following Work Orders were created:") + '\n' + new_line_sep(message))
if errors:
- frappe.throw(_("Productions Orders cannot be raised for:") + '\n' + new_line_sep(errors))
+ frappe.throw(_("Work Order cannot be created for following reason:") + '\n' + new_line_sep(errors))
return work_orders
diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py
index 79cdc1a..19924b1 100644
--- a/erpnext/stock/doctype/material_request/test_material_request.py
+++ b/erpnext/stock/doctype/material_request/test_material_request.py
@@ -7,7 +7,8 @@
from __future__ import unicode_literals
import frappe, unittest, erpnext
from frappe.utils import flt, today
-from erpnext.stock.doctype.material_request.material_request import raise_work_orders
+from erpnext.stock.doctype.material_request.material_request \
+ import raise_work_orders, make_stock_entry, make_purchase_order, make_supplier_quotation
from erpnext.stock.doctype.item.test_item import create_item
class TestMaterialRequest(unittest.TestCase):
@@ -15,8 +16,6 @@
erpnext.set_perpetual_inventory(0)
def test_make_purchase_order(self):
- from erpnext.stock.doctype.material_request.material_request import make_purchase_order
-
mr = frappe.copy_doc(test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_purchase_order,
@@ -30,8 +29,6 @@
self.assertEqual(len(po.get("items")), len(mr.get("items")))
def test_make_supplier_quotation(self):
- from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation
-
mr = frappe.copy_doc(test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_supplier_quotation, mr.name)
@@ -45,12 +42,9 @@
def test_make_stock_entry(self):
- from erpnext.stock.doctype.material_request.material_request import make_stock_entry
-
mr = frappe.copy_doc(test_records[0]).insert()
- self.assertRaises(frappe.ValidationError, make_stock_entry,
- mr.name)
+ self.assertRaises(frappe.ValidationError, make_stock_entry, mr.name)
mr = frappe.get_doc("Material Request", mr.name)
mr.material_request_type = "Material Transfer"
@@ -62,40 +56,40 @@
def _insert_stock_entry(self, qty1, qty2, warehouse = None ):
se = frappe.get_doc({
- "company": "_Test Company",
- "doctype": "Stock Entry",
- "posting_date": "2013-03-01",
- "posting_time": "00:00:00",
- "purpose": "Material Receipt",
- "items": [
- {
- "conversion_factor": 1.0,
- "doctype": "Stock Entry Detail",
- "item_code": "_Test Item Home Desktop 100",
- "parentfield": "items",
- "basic_rate": 100,
- "qty": qty1,
- "stock_uom": "_Test UOM 1",
- "transfer_qty": qty1,
- "uom": "_Test UOM 1",
- "t_warehouse": warehouse or "_Test Warehouse 1 - _TC",
- "cost_center": "_Test Cost Center - _TC"
- },
- {
- "conversion_factor": 1.0,
- "doctype": "Stock Entry Detail",
- "item_code": "_Test Item Home Desktop 200",
- "parentfield": "items",
- "basic_rate": 100,
- "qty": qty2,
- "stock_uom": "_Test UOM 1",
- "transfer_qty": qty2,
- "uom": "_Test UOM 1",
- "t_warehouse": warehouse or "_Test Warehouse 1 - _TC",
- "cost_center": "_Test Cost Center - _TC"
- }
- ]
- })
+ "company": "_Test Company",
+ "doctype": "Stock Entry",
+ "posting_date": "2013-03-01",
+ "posting_time": "00:00:00",
+ "purpose": "Material Receipt",
+ "items": [
+ {
+ "conversion_factor": 1.0,
+ "doctype": "Stock Entry Detail",
+ "item_code": "_Test Item Home Desktop 100",
+ "parentfield": "items",
+ "basic_rate": 100,
+ "qty": qty1,
+ "stock_uom": "_Test UOM 1",
+ "transfer_qty": qty1,
+ "uom": "_Test UOM 1",
+ "t_warehouse": warehouse or "_Test Warehouse 1 - _TC",
+ "cost_center": "_Test Cost Center - _TC"
+ },
+ {
+ "conversion_factor": 1.0,
+ "doctype": "Stock Entry Detail",
+ "item_code": "_Test Item Home Desktop 200",
+ "parentfield": "items",
+ "basic_rate": 100,
+ "qty": qty2,
+ "stock_uom": "_Test UOM 1",
+ "transfer_qty": qty2,
+ "uom": "_Test UOM 1",
+ "t_warehouse": warehouse or "_Test Warehouse 1 - _TC",
+ "cost_center": "_Test Cost Center - _TC"
+ }
+ ]
+ })
se.set_stock_entry_type()
se.insert()
@@ -198,14 +192,7 @@
mr.insert()
mr.submit()
- # check if per complete is None
- mr.load_from_db()
- self.assertEqual(mr.per_ordered, 0)
- self.assertEqual(mr.get("items")[0].ordered_qty, 0)
- self.assertEqual(mr.get("items")[1].ordered_qty, 0)
-
# map a purchase order
- from erpnext.stock.doctype.material_request.material_request import make_purchase_order
po_doc = make_purchase_order(mr.name)
po_doc.supplier = "_Test Supplier"
po_doc.transaction_date = "2013-07-07"
@@ -279,8 +266,6 @@
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
-
# map a stock entry
se_doc = make_stock_entry(mr.name)
se_doc.update({
@@ -357,14 +342,7 @@
mr.insert()
mr.submit()
- # check if per complete is None
- mr.load_from_db()
- self.assertEqual(mr.per_ordered, 0)
- self.assertEqual(mr.get("items")[0].ordered_qty, 0)
- self.assertEqual(mr.get("items")[1].ordered_qty, 0)
-
# map a stock entry
- from erpnext.stock.doctype.material_request.material_request import make_stock_entry
se_doc = make_stock_entry(mr.name)
se_doc.update({
@@ -435,9 +413,6 @@
mr.insert()
mr.submit()
- # map a stock entry
- from erpnext.stock.doctype.material_request.material_request import make_stock_entry
-
se_doc = make_stock_entry(mr.name)
se_doc.update({
"posting_date": "2013-03-01",
@@ -468,8 +443,6 @@
mr.insert()
mr.submit()
- # map a stock entry
- from erpnext.stock.doctype.material_request.material_request import make_stock_entry
se_doc = make_stock_entry(mr.name)
self.assertEqual(se_doc.get("items")[0].s_warehouse, "_Test Warehouse - _TC")
@@ -483,8 +456,6 @@
return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "indented_qty"))
def test_make_stock_entry_for_material_issue(self):
- from erpnext.stock.doctype.material_request.material_request import make_stock_entry
-
mr = frappe.copy_doc(test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_stock_entry,
@@ -503,8 +474,6 @@
return flt(frappe.db.get_value("Bin", {"item_code": "_Test Item Home Desktop 100",
"warehouse": "_Test Warehouse - _TC"}, "indented_qty"))
- from erpnext.stock.doctype.material_request.material_request import make_stock_entry
-
existing_requested_qty = _get_requested_qty()
mr = frappe.copy_doc(test_records[0])
@@ -512,7 +481,7 @@
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")
@@ -563,9 +532,37 @@
item_code= %s and warehouse= %s """, (mr.items[0].item_code, mr.items[0].warehouse))[0][0]
self.assertEqual(requested_qty, new_requested_qty)
- def test_multi_uom_for_purchase(self):
- from erpnext.stock.doctype.material_request.material_request import make_purchase_order
+ def test_requested_qty_multi_uom(self):
+ existing_requested_qty = self._get_requested_qty('_Test FG Item', '_Test Warehouse - _TC')
+ mr = make_material_request(item_code='_Test FG Item', material_request_type='Manufacture',
+ uom="_Test UOM 1", conversion_factor=12)
+
+ requested_qty = self._get_requested_qty('_Test FG Item', '_Test Warehouse - _TC')
+
+ self.assertEqual(requested_qty, existing_requested_qty + 120)
+
+ work_order = raise_work_orders(mr.name)
+ wo = frappe.get_doc("Work Order", work_order[0])
+ wo.qty = 50
+ wo.wip_warehouse = "_Test Warehouse 1 - _TC"
+ wo.submit()
+
+ requested_qty = self._get_requested_qty('_Test FG Item', '_Test Warehouse - _TC')
+ self.assertEqual(requested_qty, existing_requested_qty + 70)
+
+ wo.cancel()
+
+ requested_qty = self._get_requested_qty('_Test FG Item', '_Test Warehouse - _TC')
+ self.assertEqual(requested_qty, existing_requested_qty + 120)
+
+ mr.reload()
+ mr.cancel()
+ requested_qty = self._get_requested_qty('_Test FG Item', '_Test Warehouse - _TC')
+ self.assertEqual(requested_qty, existing_requested_qty)
+
+
+ def test_multi_uom_for_purchase(self):
mr = frappe.copy_doc(test_records[0])
mr.material_request_type = 'Purchase'
item = mr.items[0]
@@ -607,8 +604,9 @@
self.assertEqual(mr.per_ordered, 100)
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 +615,10 @@
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)
@@ -628,6 +629,8 @@
mr.append("items", {
"item_code": args.item_code or "_Test Item",
"qty": args.qty or 10,
+ "uom": args.uom or "_Test UOM",
+ "conversion_factor": args.conversion_factor or 1,
"schedule_date": args.schedule_date or today(),
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC"
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json
index 9d1dafb..5604913 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -1,5 +1,4 @@
{
- "actions": [],
"autoname": "hash",
"creation": "2013-02-22 01:28:02",
"doctype": "DocType",
@@ -374,7 +373,10 @@
{
"fieldname": "received_qty",
"fieldtype": "Float",
- "label": "Received Quantity"
+ "label": "Received Quantity",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
},
{
"collapsible": 1,
@@ -404,14 +406,13 @@
{
"fieldname": "manufacturer_part_no",
"fieldtype": "Data",
- "label": "Manufacturer Part Number",
- "read_only": 1
+ "label": "Manufacturer Part Number"
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-02-25 03:09:10.698967",
+ "modified": "2020-04-16 09:00:00.992835",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request Item",
diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js
index 2789711..d46b98b 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.js
+++ b/erpnext/stock/doctype/pick_list/pick_list.js
@@ -38,13 +38,17 @@
};
});
},
- 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 @@
'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 @@
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.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 8d5ef3d..c01388d 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 c4d8c41..616de5e 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -29,7 +29,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
@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 @@
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 @@
'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 @@
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 @@
@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 @@
@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/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py
index 6b4f73b..1b9ff41 100644
--- a/erpnext/stock/doctype/pick_list/test_pick_list.py
+++ b/erpnext/stock/doctype/pick_list/test_pick_list.py
@@ -111,6 +111,7 @@
stock_reconciliation = frappe.get_doc({
'doctype': 'Stock Reconciliation',
+ 'purpose': 'Stock Reconciliation',
'company': '_Test Company',
'items': [{
'item_code': '_Test Serialized Item',
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 c7a35df..71fbf9a 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 35446ec..eed5749 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",
@@ -58,9 +59,9 @@
"base_total",
"base_net_total",
"column_break_27",
+ "total_net_weight",
"total",
"net_total",
- "total_net_weight",
"taxes_charges_section",
"tax_category",
"shipping_col",
@@ -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-17 13:06:26.970288",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index cba7f20..40d7cc2 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -356,8 +356,8 @@
'accounts': [{
'company_name': '_Test Company',
'fixed_asset_account': '_Test Fixed Asset - _TC',
- 'accumulated_depreciation_account': 'Depreciation - _TC',
- 'depreciation_expense_account': 'Depreciation - _TC'
+ 'accumulated_depreciation_account': '_Test Accumulated Depreciations - _TC',
+ 'depreciation_expense_account': '_Test Depreciation - _TC'
}]
}).insert()
@@ -375,6 +375,33 @@
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/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index a8b9c81..b15f23c 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -801,8 +801,7 @@
{
"fieldname": "manufacturer_part_no",
"fieldtype": "Data",
- "label": "Manufacturer Part Number",
- "read_only": 1
+ "label": "Manufacturer Part Number"
},
{
"depends_on": "is_fixed_asset",
@@ -832,7 +831,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-03-11 14:19:48.799370",
+ "modified": "2020-04-07 18:38:21.141558",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index fb28b5c..731a730 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": [
{
@@ -307,16 +308,6 @@
"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",
"width": "50%"
@@ -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 772ac58..b32c709 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -35,6 +35,15 @@
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 @@
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)
diff --git a/erpnext/stock/doctype/serial_no/serial_no_list.js b/erpnext/stock/doctype/serial_no/serial_no_list.js
index 5b1e312..651f790 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 3bb9415..d1048fc 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -220,8 +220,8 @@
},
get_query_filters: {
docstatus: 1,
- material_request_type: "Material Transfer",
- status: ['!=', 'Transferred']
+ material_request_type: ["in", ["Material Transfer", "Material Issue"]],
+ status: ["not in", ["Transferred", "Issued"]]
}
})
}, __("Get items from"));
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index be4c78b..7cf822b 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -50,6 +50,7 @@
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")
@@ -203,10 +204,6 @@
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"]
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index ee5f237..2afabe1 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 @@
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_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index 5fe89d6..dab5a7b 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 @@
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"):
@@ -64,7 +72,7 @@
frappe.throw(_("Actual Qty is mandatory"))
def validate_item(self):
- item_det = frappe.db.sql("""select name, has_batch_no, docstatus,
+ item_det = frappe.db.sql("""select name, item_name, has_batch_no, docstatus,
is_stock_item, has_variants, stock_uom, create_new_batch
from tabItem where name=%s""", self.item_code, as_dict=True)
@@ -79,10 +87,11 @@
# check if batch number is required
if self.voucher_type != 'Stock Reconciliation':
if item_det.has_batch_no ==1:
+ batch_item = self.item_code if self.item_code == item_det.item_name else self.item_code + ":" + item_det.item_name
if not self.batch_no:
- frappe.throw(_("Batch number is mandatory for Item {0}").format(self.item_code))
+ frappe.throw(_("Batch number is mandatory for Item {0}").format(batch_item))
elif not frappe.db.get_value("Batch",{"item": self.item_code, "name": self.batch_no}):
- frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, self.item_code))
+ frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, batch_item))
elif item_det.has_batch_no ==0 and self.batch_no and self.is_cancelled == "No":
frappe.throw(_("The Item {0} cannot have Batch").format(self.item_code))
@@ -139,4 +148,3 @@
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.json b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
index 7f4efba..b7d1497 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
@@ -4,6 +4,7 @@
"description": "This tool helps you to update or fix the quantity and valuation of stock in the system. It is typically used to synchronise the system values and what actually exists in your warehouses.",
"doctype": "DocType",
"document_type": "Document",
+ "engine": "InnoDB",
"field_order": [
"naming_series",
"company",
@@ -44,11 +45,11 @@
"reqd": 1
},
{
- "default": "Stock Reconciliation",
"fieldname": "purpose",
"fieldtype": "Select",
"label": "Purpose",
- "options": "Opening Stock\nStock Reconciliation"
+ "options": "\nOpening Stock\nStock Reconciliation",
+ "reqd": 1
},
{
"fieldname": "col1",
@@ -153,7 +154,7 @@
"idx": 1,
"is_submittable": 1,
"max_attachments": 1,
- "modified": "2019-05-26 09:03:09.542141",
+ "modified": "2020-04-08 17:02:47.196206",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Reconciliation",
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index afa2394..0a49c26 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -488,12 +488,14 @@
["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 @@
'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_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index e6d7e3f..51d027f 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -240,6 +240,7 @@
def create_stock_reconciliation(**args):
args = frappe._dict(args)
sr = frappe.new_doc("Stock Reconciliation")
+ sr.purpose = args.purpose or "Stock Reconciliation"
sr.posting_date = args.posting_date or nowdate()
sr.posting_time = args.posting_time or nowtime()
sr.set_posting_time = 1
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 9c5a8e1..61429cc 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -245,7 +245,7 @@
'item_group_defaults': item_group_defaults,
'brand_defaults': brand_defaults
})
-
+
warehouse = get_item_warehouse(item, args, overwrite_warehouse, defaults)
if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
@@ -279,7 +279,7 @@
"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,
@@ -341,6 +341,9 @@
else:
out["manufacturer_part_no"] = None
out["manufacturer"] = None
+ else:
+ out["manufacturer"], out["manufacturer_part_no"] = frappe.get_value("Item", item.name,
+ ["default_item_manufacturer", "default_manufacturer_part_no"] )
child_doctype = args.doctype + ' Item'
meta = frappe.get_meta(child_doctype)
@@ -377,7 +380,7 @@
else:
warehouse = args.get('warehouse')
-
+
return warehouse
def update_barcode_value(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 94ec314..1af68dd 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 @@
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/stock_balance.py b/erpnext/stock/stock_balance.py
index e5dc6b1..5697315 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -113,13 +113,30 @@
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)
+ # Ordered Qty is always maintained in stock UOM
+ inward_qty = frappe.db.sql("""
+ select sum(mr_item.stock_qty - mr_item.ordered_qty)
from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr
where mr_item.item_code=%s and mr_item.warehouse=%s
- 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))
+ and mr.material_request_type in ('Purchase', 'Manufacture', 'Customer Provided', 'Material Transfer')
+ and mr_item.stock_qty > mr_item.ordered_qty and mr_item.parent=mr.name
+ and mr.status!='Stopped' and mr.docstatus=1
+ """, (item_code, warehouse))
+ inward_qty = flt(inward_qty[0][0]) if inward_qty else 0
- return flt(indented_qty[0][0]) if indented_qty else 0
+ outward_qty = frappe.db.sql("""
+ select sum(mr_item.stock_qty - mr_item.ordered_qty)
+ 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 = 'Material Issue'
+ and mr_item.stock_qty > mr_item.ordered_qty and mr_item.parent=mr.name
+ and mr.status!='Stopped' and mr.docstatus=1
+ """, (item_code, warehouse))
+ outward_qty = flt(outward_qty[0][0]) if outward_qty else 0
+
+ requested_qty = inward_qty - outward_qty
+
+ return requested_qty
def get_ordered_qty(item_code, warehouse):
ordered_qty = frappe.db.sql("""
@@ -145,9 +162,9 @@
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/utils.py b/erpnext/stock/utils.py
index f3381c7..7f32b8d 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -74,7 +74,8 @@
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 @@
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 4a7885e..596987f 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.py b/erpnext/support/doctype/issue/issue.py
index fd72807..117267f 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -335,8 +335,13 @@
ignore_permissions = False
if is_website_user():
- if not filters: filters = []
- filters.append(("Issue", "customer", "=", customer)) if customer else filters.append(("Issue", "raised_by", "=", user))
+ if not filters: filters = {}
+
+ if customer:
+ filters["customer"] = customer
+ else:
+ filters["raised_by"] = user
+
ignore_permissions = True
return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=ignore_permissions)
diff --git a/erpnext/templates/includes/cart.js b/erpnext/templates/includes/cart.js
index 456bc7e..c6dfd35 100644
--- a/erpnext/templates/includes/cart.js
+++ b/erpnext/templates/includes/cart.js
@@ -26,15 +26,14 @@
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 f7f3548..60de3af 100644
--- a/erpnext/templates/includes/cart/cart_address.html
+++ b/erpnext/templates/includes/cart/cart_address.html
@@ -18,7 +18,7 @@
<h6 class="text-uppercase">{{ _("Shipping Address") }}</h6>
<div class="row no-gutters" data-fieldname="shipping_address_name">
{% for address in shipping_addresses %}
- <div class="mr-3 mb-3 w-25" data-address-name="{{address.name}}" {% if doc.shipping_address_name == address.name %} data-active {% endif %}>
+ <div class="mr-3 mb-3 w-25" data-address-name="{{address.name}}" data-address-type="shipping" {% if doc.shipping_address_name == address.name %} data-active {% endif %}>
{% include "templates/includes/cart/address_card.html" %}
</div>
{% endfor %}
@@ -28,7 +28,7 @@
<h6 class="text-uppercase">{{ _("Billing Address") }}</h6>
<div class="row no-gutters" data-fieldname="customer_address">
{% for address in billing_addresses %}
- <div class="mr-3 mb-3 w-25" data-address-name="{{address.name}}" {% if doc.customer_address == address.name %} data-active {% endif %}>
+ <div class="mr-3 mb-3 w-25" data-address-name="{{address.name}}" data-address-type="billing" {% if doc.customer_address == address.name %} data-active {% endif %}>
{% include "templates/includes/cart/address_card.html" %}
</div>
{% endfor %}
@@ -123,9 +123,19 @@
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/itemised_tax_breakup.html b/erpnext/templates/includes/itemised_tax_breakup.html
index c27e4ce..c2f1353 100644
--- a/erpnext/templates/includes/itemised_tax_breakup.html
+++ b/erpnext/templates/includes/itemised_tax_breakup.html
@@ -16,7 +16,11 @@
<tr>
<td>{{ item }}</td>
<td class='text-right'>
- {{ frappe.utils.fmt_money(itemised_taxable_amount.get(item, 0), None, currency) }}
+ {% if doc.get('is_return') %}
+ {{ frappe.utils.fmt_money((itemised_taxable_amount.get(item, 0))|abs, None, doc.currency) }}
+ {% else %}
+ {{ frappe.utils.fmt_money(itemised_taxable_amount.get(item, 0), None, doc.currency) }}
+ {% endif %}
</td>
{% for tax_account in tax_accounts %}
{% set tax_details = taxes.get(tax_account) %}
@@ -25,7 +29,11 @@
{% if tax_details.tax_rate or not tax_details.tax_amount %}
({{ tax_details.tax_rate }}%)
{% endif %}
- {{ frappe.utils.fmt_money(tax_details.tax_amount / conversion_rate, None, currency) }}
+ {% if doc.get('is_return') %}
+ {{ frappe.utils.fmt_money((tax_details.tax_amount / doc.conversion_rate)|abs, None, doc.currency) }}
+ {% else %}
+ {{ frappe.utils.fmt_money(tax_details.tax_amount / doc.conversion_rate, None, doc.currency) }}
+ {% endif %}
</td>
{% else %}
<td></td>
diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html
index 4a32aa4..ebec838 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 %}
-<tr>
- <td class="text-right" colspan="2">
- {{ d.description }}
- </td>
- <td class="text-right">
- {{ d.get_formatted("base_tax_amount") }}
- </td>
-</tr>
-{% endif %}
+ {% if d.base_tax_amount %}
+ <tr>
+ <td class="text-right" colspan="2">
+ {{ d.description }}
+ </td>
+ <td class="text-right">
+ {{ d.get_formatted("base_tax_amount") }}
+ </td>
+ </tr>
+ {% endif %}
{% endfor %}
{% if doc.doctype == 'Quotation' %}
diff --git a/erpnext/templates/pages/cart.html b/erpnext/templates/pages/cart.html
index 912702e..3033d15 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 %}
-<button class="btn btn-primary btn-place-order" type="button">
- {{ _("Place Order") }}
-</button>
-{% endif %}
-{% if doc.items and not cart_settings.enable_checkout %}
-<button class="btn btn-primary btn-request-for-quotation" type="button">
- {{ _("Request for Quotation") }}
-</button>
-{% endif %}
{% endblock %}
{% block page_content %}
@@ -56,6 +46,20 @@
{% endif %}
{% if doc.items %}
+ <div class="place-order-container">
+ {% if cart_settings.enable_checkout %}
+ <button class="btn btn-primary btn-place-order" type="button">
+ {{ _("Place Order") }}
+ </button>
+ {% else %}
+ <button class="btn btn-primary btn-request-for-quotation" type="button">
+ {{ _("Request for Quotation") }}
+ </button>
+ {% endif %}
+ </div>
+ {% endif %}
+
+ {% if doc.items %}
{% if doc.tc_name %}
<div class="terms-and-conditions-link">
<a href class="link-terms-and-conditions" data-terms-name="{{ doc.tc_name }}">
diff --git a/yarn.lock b/yarn.lock
index 9b31518..c5509d6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1133,9 +1133,9 @@
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"