Merge pull request #21099 from anupamvs/item-wise-sales-history-billed-amount-bug
bug: Item-wise Sales History - Billed amount
diff --git a/README.md b/README.md
index ed57a17..80ebdb6 100644
--- a/README.md
+++ b/README.md
@@ -15,18 +15,18 @@
ERPNext as a monolith includes the following areas for managing businesses:
-1. [Accounting](https://erpnext.com/docs/user/manual/en/accounts)
-1. [Inventory](https://erpnext.com/docs/user/manual/en/stock)
-1. [CRM](https://erpnext.com/docs/user/manual/en/CRM)
-1. [Sales](https://erpnext.com/docs/user/manual/en/selling)
-1. [Purchase](https://erpnext.com/docs/user/manual/en/buying)
-1. [HRMS](https://erpnext.com/docs/user/manual/en/human-resources)
-1. [Project Management](https://erpnext.com/docs/user/manual/en/projects)
-1. [Support](https://erpnext.com/docs/user/manual/en/support)
-1. [Asset Management](https://erpnext.com/docs/user/manual/en/asset)
+1. [Accounting](https://erpnext.com/open-source-accounting)
+1. [Inventory](https://erpnext.com/distribution/inventory-management-system)
+1. [CRM](https://erpnext.com/open-source-crm)
+1. [Sales](https://erpnext.com/open-source-sales-purchase)
+1. [Purchase](https://erpnext.com/open-source-sales-purchase)
+1. [HRMS](https://erpnext.com/open-source-hrms)
+1. [Project Management](https://erpnext.com/open-source-projects)
+1. [Support](https://erpnext.com/open-source-help-desk-software)
+1. [Asset Management](https://erpnext.com/open-source-asset-management-software)
1. [Quality Management](https://erpnext.com/docs/user/manual/en/quality-management)
-1. [Manufacturing](https://erpnext.com/docs/user/manual/en/manufacturing)
-1. [Website Management](https://erpnext.com/docs/user/manual/en/website)
+1. [Manufacturing](https://erpnext.com/open-source-manufacturing-erp-software)
+1. [Website Management](https://erpnext.com/open-source-website-builder-software)
1. [Customize ERPNext](https://erpnext.com/docs/user/manual/en/customize-erpnext)
1. [And More](https://erpnext.com/docs/user/manual/en/)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index f40b957..786b9cf 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '12.2.0'
+__version__ = '12.0.0-dev'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
index 569767e..c3e2f7d 100644
--- a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
+++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
@@ -26,7 +26,7 @@
to_date = chart.to_date
timegrain = chart.time_interval
- filters = frappe.parse_json(chart.filters_json)
+ filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
account = filters.get("account")
company = filters.get("company")
diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json
index 64efc27..af252e6 100644
--- a/erpnext/accounts/doctype/account/account.json
+++ b/erpnext/accounts/doctype/account/account.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_copy": 1,
"allow_import": 1,
"creation": "2013-01-30 12:49:46",
@@ -196,10 +197,13 @@
],
"icon": "fa fa-money",
"idx": 1,
- "modified": "2019-10-10 19:10:02.967554",
+ "is_tree": 1,
+ "links": [],
+ "modified": "2020-03-18 17:57:52.063233",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
+ "nsm_parent_field": "parent_account",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
index 275374a..ff95c5a 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
@@ -917,17 +917,31 @@
"is_group": 1,
"I - Gezeichnetes Kapital": {
"account_type": "Equity",
- "is_group": 1
+ "is_group": 1,
+ "Gezeichnetes Kapital": {
+ "account_type": "Equity",
+ "account_number": "2900"
+ },
+ "Ausstehende Einlagen auf das gezeichnete Kapital": {
+ "account_number": "2910",
+ "is_group": 1
+ }
},
"II - Kapitalr\u00fccklage": {
"account_type": "Equity",
- "is_group": 1
+ "is_group": 1,
+ "Kapitalr\u00fccklage": {
+ "account_number": "2920"
+ }
},
"III - Gewinnr\u00fccklagen": {
"account_type": "Equity",
"1 - gesetzliche R\u00fccklage": {
"account_type": "Equity",
- "is_group": 1
+ "is_group": 1,
+ "Gesetzliche R\u00fccklage": {
+ "account_number": "2930"
+ }
},
"2 - R\u00fccklage f. Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen": {
"account_type": "Equity",
@@ -935,7 +949,10 @@
},
"3 - satzungsm\u00e4\u00dfige R\u00fccklagen": {
"account_type": "Equity",
- "is_group": 1
+ "is_group": 1,
+ "Satzungsm\u00e4\u00dfige R\u00fccklagen": {
+ "account_number": "2950"
+ }
},
"4 - andere Gewinnr\u00fccklagen": {
"account_type": "Equity",
@@ -969,7 +986,13 @@
},
"IV - Gewinnvortrag/Verlustvortrag": {
"account_type": "Equity",
- "is_group": 1
+ "is_group": 1,
+ "Gewinnvortrag vor Verwendung": {
+ "account_number": "2970"
+ },
+ "Verlustvortrag vor Verwendung": {
+ "account_number": "2978"
+ }
},
"V - Jahres\u00fcberschu\u00df/Jahresfehlbetrag": {
"account_type": "Equity",
@@ -1663,7 +1686,15 @@
"Erl\u00f6se 7 % USt": {
"account_number": "4300",
"account_type": "Income Account"
- },
+ },
+ "Erl\u00f6se 16 % USt": {
+ "account_number": "4340",
+ "account_type": "Income Account"
+ },
+ "Erl\u00f6se 19 % USt": {
+ "account_number": "4400",
+ "account_type": "Income Account"
+ },
"Erl\u00f6se aus im Inland steuerpfl. EU-Lieferungen 7 % USt": {
"account_number": "4310"
},
@@ -1691,19 +1722,6 @@
"Erl\u00f6se aus im anderen EU-Land steuerbaren Leistungen, im Inland nicht steuerbare Ums\u00e4tze": {
"account_number": "4339"
},
- "Erl\u00f6se 16 % USt (Gruppe)": {
- "is_group": 1,
- "Erl\u00f6se 16 % USt": {
- "account_number": "4340"
- }
- },
- "Erl\u00f6se 19 % USt (Gruppe)": {
- "is_group": 1,
- "Erl\u00f6se 19 % USt": {
- "account_number": "4400",
- "account_type": "Income Account"
- }
- },
"Grundst\u00fccksertr\u00e4ge (Gruppe)": {
"is_group": 1,
"Grundst\u00fccksertr\u00e4ge": {
@@ -1762,14 +1780,12 @@
"2 - Herstellungskosten der zur Erzielung der Umsatzerl\u00f6se erbrachten Leistungen": {
"root_type": "Expense",
"is_group": 1,
- "Herstellungskosten (Gruppe)": {
- "Herstellungskosten": {
- "account_number": "6990",
- "account_type": "Cost of Goods Sold"
- },
- "Herstellungskosten: Schwund": {
- "account_type": "Stock Adjustment"
- }
+ "Herstellungskosten": {
+ "account_number": "6990",
+ "account_type": "Cost of Goods Sold"
+ },
+ "Herstellungskosten: Schwund": {
+ "account_type": "Stock Adjustment"
},
"Aufwendungen f. Roh-, Hilfs- und Betriebsstoffe und f. bezogene Waren": {
"account_number": "5000",
@@ -1819,10 +1835,10 @@
"Energiestoffe (Fertigung)": {
"account_number": "5190"
},
- "Energiestoffe (Fertigung)7% Vorsteuer": {
+ "Energiestoffe (Fertigung) 7% Vorsteuer": {
"account_number": "5191"
},
- "Energiestoffe (Fertigung)19% Vorsteuer": {
+ "Energiestoffe (Fertigung) 19% Vorsteuer": {
"account_number": "5192"
}
}
@@ -1945,49 +1961,49 @@
},
"Nachl\u00e4sse aus innergem. Erwerb 15 % Vorsteuer und 15 % Umsatzsteuer": {
"account_number": "5727"
- },
- "Erhaltene Skonti (Gruppe)": {
- "is_group": 1,
- "Erh. Skonti": {
- "account_number": "5730"
- },
- "Erh. Skonti 7 % Vorsteuer": {
- "account_number": "5731"
- },
- "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
- "account_number": "5733"
- },
- "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
- "account_number": "5734"
- },
- "Erh. Skonti 19 % Vorsteuer": {
- "account_number": "5736"
- },
- "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
- "account_number": "5738"
- },
- "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 19% Vorst. u. 19% Ust.": {
- "account_number": "5741"
- },
- "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 7% Vorst. u. 7% Ust.": {
- "account_number": "5743"
- },
- "Erh. Skonti aus steuerpflichtigem innergem. Erwerb": {
- "account_number": "5745"
- },
- "Erh. Skonti aus steuerpflichtigem innergem. Erwerb 7% Vorst. u. 7% Ust.": {
- "account_number": "5746"
- },
- "Erh. Skonti aus steuerpflichtigem innergem. Erwerb 19% Vorst. u. 19% Ust.": {
- "account_number": "5748"
- },
- "Erh. Skonti aus Erwerb Roh-,Hilfs-,Betriebsstoff letzter Abn.innerh.Dreiecksg. 19% Vorst. und 19% Ust.": {
- "account_number": "5792"
- },
- "Erh. Skonti aus Erwerb Waren als letzter Abnehmer innerh. Dreiecksgesch. 19% Vorst. u. 19% Ust.": {
- "account_number": "5793"
- }
- }
+ }
+ },
+ "Erhaltene Skonti (Gruppe)": {
+ "is_group": 1,
+ "Erh. Skonti": {
+ "account_number": "5730"
+ },
+ "Erh. Skonti 7 % Vorsteuer": {
+ "account_number": "5731"
+ },
+ "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
+ "account_number": "5733"
+ },
+ "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
+ "account_number": "5734"
+ },
+ "Erh. Skonti 19 % Vorsteuer": {
+ "account_number": "5736"
+ },
+ "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
+ "account_number": "5738"
+ },
+ "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 19% Vorst. u. 19% Ust.": {
+ "account_number": "5741"
+ },
+ "Erh. Skonti aus Einkauf Roh-, Hilfs- und Betriebsstoffe aus steuerpfl. innergem. Erwerb 7% Vorst. u. 7% Ust.": {
+ "account_number": "5743"
+ },
+ "Erh. Skonti aus steuerpflichtigem innergem. Erwerb": {
+ "account_number": "5745"
+ },
+ "Erh. Skonti aus steuerpflichtigem innergem. Erwerb 7% Vorst. u. 7% Ust.": {
+ "account_number": "5746"
+ },
+ "Erh. Skonti aus steuerpflichtigem innergem. Erwerb 19% Vorst. u. 19% Ust.": {
+ "account_number": "5748"
+ },
+ "Erh. Skonti aus Erwerb Roh-,Hilfs-,Betriebsstoff letzter Abn.innerh.Dreiecksg. 19% Vorst. und 19% Ust.": {
+ "account_number": "5792"
+ },
+ "Erh. Skonti aus Erwerb Waren als letzter Abnehmer innerh. Dreiecksgesch. 19% Vorst. u. 19% Ust.": {
+ "account_number": "5793"
+ }
},
"Bezugsnebenkosten (Gruppe)": {
"is_group": 1,
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
index a36f421..3c12f85 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
@@ -48,12 +48,6 @@
frm.set_value('label', frm.doc.document_type);
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
- if (frm.is_new()){
- let row = frappe.model.add_child(frm.doc, "Accounting Dimension Detail", "dimension_defaults");
- row.reference_document = frm.doc.document_type;
- frm.refresh_fields("dimension_defaults");
- }
-
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
if (r && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
index cf6dc7a..cf55d55 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "field:label",
"creation": "2019-05-04 18:13:37.002352",
"doctype": "DocType",
@@ -46,7 +47,8 @@
"options": "Accounting Dimension Detail"
}
],
- "modified": "2019-07-17 16:49:31.134385",
+ "links": [],
+ "modified": "2020-03-22 20:34:39.805728",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension",
@@ -63,9 +65,20 @@
"role": "System Manager",
"share": 1,
"write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
+ "write": 1
}
],
- "quick_entry": 1,
"sort_field": "modified",
"sort_order": "ASC",
"track_changes": 1
diff --git a/erpnext/accounts/doctype/accounts_settings/regional/united_states.js b/erpnext/accounts/doctype/accounts_settings/regional/united_states.js
new file mode 100644
index 0000000..d47d6e5
--- /dev/null
+++ b/erpnext/accounts/doctype/accounts_settings/regional/united_states.js
@@ -0,0 +1,8 @@
+
+frappe.ui.form.on('Accounts Settings', {
+ refresh: function(frm) {
+ frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through");
+ frm.set_df_property("frozen_accounts_modifier", "label", "Role Allowed to Close Books & Make Changes to Closed Periods");
+ frm.set_df_property("credit_controller", "label", "Credit Manager");
+ }
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank/bank.js b/erpnext/accounts/doctype/bank/bank.js
index 463d29c..de9498e 100644
--- a/erpnext/accounts/doctype/bank/bank.js
+++ b/erpnext/accounts/doctype/bank/bank.js
@@ -7,7 +7,20 @@
},
refresh: function(frm) {
add_fields_to_mapping_table(frm);
- }
+
+ frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' };
+
+ frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
+
+ if (frm.doc.__islocal) {
+ frm.set_df_property('address_and_contact', 'hidden', 1);
+ frappe.contacts.clear_address_and_contact(frm);
+ }
+ else {
+ frm.set_df_property('address_and_contact', 'hidden', 0);
+ frappe.contacts.render_address_and_contact(frm);
+ }
+ },
});
diff --git a/erpnext/accounts/doctype/bank/bank.json b/erpnext/accounts/doctype/bank/bank.json
index 4fa0e4f..99978e6 100644
--- a/erpnext/accounts/doctype/bank/bank.json
+++ b/erpnext/accounts/doctype/bank/bank.json
@@ -1,224 +1,137 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "field:bank_name",
- "beta": 0,
- "creation": "2018-04-07 16:59:59.496668",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:bank_name",
+ "creation": "2018-04-07 16:59:59.496668",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "bank_details_section",
+ "bank_name",
+ "swift_number",
+ "column_break_1",
+ "branch_code",
+ "website",
+ "address_and_contact",
+ "address_html",
+ "column_break_13",
+ "contact_html",
+ "data_import_configuration_section",
+ "bank_transaction_mapping",
+ "section_break_4",
+ "plaid_access_token"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "bank_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Bank Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "fieldname": "bank_name",
+ "fieldtype": "Data",
+ "label": "Bank Name",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "data_import_configuration_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Data Import Configuration",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "bank_details_section",
+ "fieldtype": "Section Break",
+ "label": "Bank Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "bank_transaction_mapping",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Bank Transaction Mapping",
- "length": 0,
- "no_copy": 0,
- "options": "Bank Transaction Mapping",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_in_quick_entry": 1,
+ "fieldname": "swift_number",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "SWIFT number",
+ "unique": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_4",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_1",
+ "fieldtype": "Column Break",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "plaid_access_token",
- "fieldtype": "Data",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Plaid Access Token",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "allow_in_quick_entry": 1,
+ "fieldname": "branch_code",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Branch Code",
+ "unique": 1
+ },
+ {
+ "fieldname": "address_and_contact",
+ "fieldtype": "Section Break",
+ "label": "Address and Contact",
+ "options": "fa fa-map-marker"
+ },
+ {
+ "fieldname": "address_html",
+ "fieldtype": "HTML",
+ "label": "Address HTML"
+ },
+ {
+ "fieldname": "website",
+ "fieldtype": "Data",
+ "label": "Website"
+ },
+ {
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "contact_html",
+ "fieldtype": "HTML",
+ "label": "Contact HTML"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "data_import_configuration_section",
+ "fieldtype": "Section Break",
+ "label": "Data Import Configuration"
+ },
+ {
+ "fieldname": "bank_transaction_mapping",
+ "fieldtype": "Table",
+ "label": "Bank Transaction Mapping",
+ "options": "Bank Transaction Mapping"
+ },
+ {
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "plaid_access_token",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Plaid Access Token",
+ "no_copy": 1,
+ "read_only": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-27 16:12:13.938776",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Bank",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "links": [],
+ "modified": "2020-03-25 21:22:33.496264",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank/bank.py b/erpnext/accounts/doctype/bank/bank.py
index b205d56..41aae14 100644
--- a/erpnext/accounts/doctype/bank/bank.py
+++ b/erpnext/accounts/doctype/bank/bank.py
@@ -5,6 +5,12 @@
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
+from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address
class Bank(Document):
- pass
+ def onload(self):
+ """Load address and contacts in `__onload`"""
+ load_address_and_contact(self)
+
+ def on_trash(self):
+ delete_contact_and_address('Bank', self.name)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json
index c8ae26d..aa9c434 100644
--- a/erpnext/accounts/doctype/bank_account/bank_account.json
+++ b/erpnext/accounts/doctype/bank_account/bank_account.json
@@ -24,8 +24,6 @@
"iban",
"column_break_12",
"bank_account_no",
- "branch_code",
- "swift_number",
"address_and_contact",
"address_html",
"website",
@@ -146,17 +144,6 @@
"length": 30
},
{
- "fieldname": "branch_code",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Branch Code"
- },
- {
- "fieldname": "swift_number",
- "fieldtype": "Data",
- "label": "SWIFT number"
- },
- {
"fieldname": "address_and_contact",
"fieldtype": "Section Break",
"label": "Address and Contact",
@@ -213,7 +200,7 @@
}
],
"links": [],
- "modified": "2020-01-29 20:42:26.458316",
+ "modified": "2020-01-30 20:42:26.458316",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",
diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js
index 0acbe20..065d25e 100644
--- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js
+++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js
@@ -4,8 +4,8 @@
cur_frm.add_fetch('bank_account','account','account');
cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no');
cur_frm.add_fetch('bank_account','iban','iban');
-cur_frm.add_fetch('bank_account','branch_code','branch_code');
-cur_frm.add_fetch('bank_account','swift_number','swift_number');
+cur_frm.add_fetch('bank','branch_code','branch_code');
+cur_frm.add_fetch('bank','swift_number','swift_number');
frappe.ui.form.on('Bank Guarantee', {
setup: function(frm) {
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.json b/erpnext/accounts/doctype/cost_center/cost_center.json
index 976f05a..99b89d1 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.json
+++ b/erpnext/accounts/doctype/cost_center/cost_center.json
@@ -124,11 +124,13 @@
],
"icon": "fa fa-money",
"idx": 1,
+ "is_tree": 1,
"links": [],
- "modified": "2020-01-28 13:50:23.430434",
+ "modified": "2020-03-18 17:59:04.321637",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
+ "nsm_parent_field": "parent_cost_center",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index f9e4fd7..14d0531 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -233,35 +233,14 @@
frappe.throw(_("Outstanding for {0} cannot be less than zero ({1})").format(against_voucher, fmt_money(bal)))
if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]:
- update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal)
-
-def update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal):
- data = []
- # Update outstanding amt on against voucher
- if against_voucher_type == "Fees":
ref_doc = frappe.get_doc(against_voucher_type, against_voucher)
- ref_doc.db_set('outstanding_amount', bal)
- ref_doc.set_status(update=True)
- return
- elif against_voucher_type == "Purchase Invoice":
- from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_status
- data = frappe.db.get_value(against_voucher_type, against_voucher,
- ["name as purchase_invoice", "outstanding_amount",
- "is_return", "due_date", "docstatus"])
- elif against_voucher_type == "Sales Invoice":
- from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_status
- data = frappe.db.get_value(against_voucher_type, against_voucher,
- ["name as sales_invoice", "outstanding_amount", "is_discounted",
- "is_return", "due_date", "docstatus"])
- precision = frappe.get_precision(against_voucher_type, "outstanding_amount")
- data = list(data)
- data.append(precision)
- status = get_status(data)
- frappe.db.set_value(against_voucher_type, against_voucher, {
- 'outstanding_amount': bal,
- 'status': status
- })
+ # Didn't use db_set for optimisation purpose
+ ref_doc.outstanding_amount = bal
+ frappe.db.set_value(against_voucher_type, against_voucher, 'outstanding_amount', bal)
+
+ ref_doc.set_status(update=True)
+
def validate_frozen_account(account, adv_adj=None):
frozen_account = frappe.db.get_value("Account", account, "freeze_account")
diff --git a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py
index 01ddd29..b4a547b 100644
--- a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py
@@ -38,6 +38,7 @@
filters={"voucher_type": "Journal Entry", "voucher_no": je.name},
order_by="creation"
)
+
self.assertTrue(all(entry.to_rename == 1 for entry in gl_entries))
old_naming_series_current_value = frappe.db.sql("SELECT current from tabSeries where name = %s", naming_series)[0][0]
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 2cbd40b..eb3017a 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -454,8 +454,10 @@
def set_print_format_fields(self):
bank_amount = party_amount = total_amount = 0.0
currency = bank_account_currency = party_account_currency = pay_to_recd_from= None
+ party_type = None
for d in self.get('accounts'):
if d.party_type in ['Customer', 'Supplier'] and d.party:
+ party_type = d.party_type
if not pay_to_recd_from:
pay_to_recd_from = d.party
@@ -467,9 +469,9 @@
bank_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
bank_account_currency = d.account_currency
- if pay_to_recd_from:
- self.pay_to_recd_from = frappe.db.get_value(d.party_type, pay_to_recd_from,
- "customer_name" if d.party_type=="Customer" else "supplier_name")
+ if party_type and pay_to_recd_from:
+ self.pay_to_recd_from = frappe.db.get_value(party_type, pay_to_recd_from,
+ "customer_name" if party_type=="Customer" else "supplier_name")
if bank_amount:
total_amount = bank_amount
currency = bank_account_currency
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 968fb60..d208087 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -33,7 +33,9 @@
frm.set_query("party_bank_account", function() {
return {
filters: {
- "is_company_account":0
+ "is_company_account":0,
+ party_type: frm.doc.party_type,
+ party: frm.doc.party
}
}
});
diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
index 5303743..a25e0e3 100644
--- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
@@ -161,15 +161,15 @@
pe.insert()
pe.submit()
- outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
- self.assertEqual(outstanding_amount, 0)
- self.assertEqual(si.status, 'Paid')
+ outstanding_amount, status = frappe.db.get_value("Sales Invoice", si.name, ["outstanding_amount", "status"])
+ self.assertEqual(flt(outstanding_amount), 0)
+ self.assertEqual(status, 'Paid')
pe.cancel()
- outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
- self.assertEqual(outstanding_amount, 100)
- self.assertEqual(si.status, 'Unpaid')
+ outstanding_amount, status = frappe.db.get_value("Sales Invoice", si.name, ["outstanding_amount", "status"])
+ self.assertEqual(flt(outstanding_amount), 100)
+ self.assertEqual(status, 'Unpaid')
def test_payment_against_purchase_invoice_to_check_status(self):
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
@@ -182,15 +182,15 @@
pe.insert()
pe.submit()
- outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
- self.assertEqual(outstanding_amount, 0)
- self.assertEqual(pi.status, 'Paid')
+ outstanding_amount, status = frappe.db.get_value("Purchase Invoice", pi.name, ["outstanding_amount", "status"])
+ self.assertEqual(flt(outstanding_amount), 0)
+ self.assertEqual(status, 'Paid')
pe.cancel()
- outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
- self.assertEqual(outstanding_amount, 100)
- self.assertEqual(pi.status, 'Unpaid')
+ outstanding_amount, status = frappe.db.get_value("Purchase Invoice", pi.name, ["outstanding_amount", "status"])
+ self.assertEqual(flt(outstanding_amount), 250)
+ self.assertEqual(status, 'Unpaid')
def test_payment_entry_against_ec(self):
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
index bff995e..c1559a7 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.json
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -839,7 +839,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fetch_from": "bank_account.branch_code",
+ "fetch_from": "bank.branch_code",
"fieldname": "branch_code",
"fieldtype": "Read Only",
"hidden": 0,
@@ -873,7 +873,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fetch_from": "bank_account.swift_number",
+ "fetch_from": "bank.swift_number",
"fieldname": "swift_number",
"fieldtype": "Read Only",
"hidden": 0,
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index cc992ce..87d40fc 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -125,27 +125,6 @@
else:
self.remarks = _("No Remarks")
- def set_status(self, update=False, status=None, update_modified=True):
- if self.is_new():
- if self.get('amended_from'):
- self.status = 'Draft'
- return
-
- if not status:
- precision = self.precision("outstanding_amount")
- args = [
- self.name,
- self.outstanding_amount,
- self.is_return,
- self.due_date,
- self.docstatus,
- precision
- ]
- self.status = get_status(args)
-
- if update:
- self.db_set('status', self.status, update_modified = update_modified)
-
def set_missing_values(self, for_validate=False):
if not self.credit_to:
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
@@ -1028,34 +1007,6 @@
# calculate totals again after applying TDS
self.calculate_taxes_and_totals()
-def get_status(*args):
- purchase_invoice, outstanding_amount, is_return, due_date, docstatus, precision = args[0]
-
- outstanding_amount = flt(outstanding_amount, precision)
- due_date = getdate(due_date)
- now_date = getdate()
-
- if docstatus == 2:
- status = "Cancelled"
- elif docstatus == 1:
- if outstanding_amount > 0 and due_date < now_date:
- status = "Overdue"
- elif outstanding_amount > 0 and due_date >= now_date:
- status = "Unpaid"
- #Check if outstanding amount is 0 due to debit note issued against invoice
- elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Purchase Invoice', {'is_return': 1, 'return_against': purchase_invoice, 'docstatus': 1}):
- status = "Debit Note Issued"
- elif is_return == 1:
- status = "Return"
- elif outstanding_amount <=0:
- status = "Paid"
- else:
- status = "Submitted"
- else:
- status = "Draft"
-
- return status
-
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)
@@ -1116,3 +1067,6 @@
def make_inter_company_sales_invoice(source_name, target_doc=None):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction
return make_inter_company_transaction("Purchase Invoice", source_name, target_doc)
+
+def on_doctype_update():
+ frappe.db.add_index("Purchase Invoice", ["supplier", "is_return", "return_against"])
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 4a7322d..ef90b94 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -777,7 +777,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-03-05 14:20:17.297284",
+ "modified": "2020-03-11 14:20:17.297284",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index c0e1285..c49ac29 100755
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -423,7 +423,10 @@
name_list.append(name)
email_queue = make_email_queue(email_queue_list)
- pos_profile = json.loads(pos_profile)
+
+ if isinstance(pos_profile, string_types):
+ pos_profile = json.loads(pos_profile)
+
customers = get_customers_list(pos_profile)
return {
'invoice': name_list,
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 7f7938d..ba1ceff 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1223,18 +1223,38 @@
self.status = 'Draft'
return
+ precision = self.precision("outstanding_amount")
+ outstanding_amount = flt(self.outstanding_amount, precision)
+ due_date = getdate(self.due_date)
+ nowdate = getdate()
+
+ discounting_status = None
+ if self.is_discounted:
+ discountng_status = get_discounting_status(self.name)
+
if not status:
- precision = self.precision("outstanding_amount")
- args = [
- self.name,
- self.outstanding_amount,
- self.is_discounted,
- self.is_return,
- self.due_date,
- self.docstatus,
- precision,
- ]
- self.status = get_status(args)
+ if self.docstatus == 2:
+ status = "Cancelled"
+ elif self.docstatus == 1:
+ if outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed':
+ self.status = "Overdue and Discounted"
+ elif outstanding_amount > 0 and due_date < nowdate:
+ self.status = "Overdue"
+ elif outstanding_amount > 0 and due_date >= nowdate and self.is_discounted and discountng_status=='Disbursed':
+ self.status = "Unpaid and Discounted"
+ elif outstanding_amount > 0 and due_date >= nowdate:
+ self.status = "Unpaid"
+ #Check if outstanding amount is 0 due to credit note issued against invoice
+ elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
+ self.status = "Credit Note Issued"
+ elif self.is_return == 1:
+ self.status = "Return"
+ elif outstanding_amount<=0:
+ self.status = "Paid"
+ else:
+ self.status = "Submitted"
+ else:
+ self.status = "Draft"
if update:
self.db_set('status', self.status, update_modified = update_modified)
@@ -1259,42 +1279,6 @@
return status
-def get_status(*args):
- sales_invoice, outstanding_amount, is_discounted, is_return, due_date, docstatus, precision = args[0]
-
- discounting_status = None
- if is_discounted:
- discounting_status = get_discounting_status(sales_invoice)
-
- outstanding_amount = flt(outstanding_amount, precision)
- due_date = getdate(due_date)
- now_date = getdate()
-
- if docstatus == 2:
- status = "Cancelled"
- elif docstatus == 1:
- if outstanding_amount > 0 and due_date < now_date and is_discounted and discounting_status=='Disbursed':
- status = "Overdue and Discounted"
- elif outstanding_amount > 0 and due_date < now_date:
- status = "Overdue"
- elif outstanding_amount > 0 and due_date >= now_date and is_discounted and discounting_status=='Disbursed':
- status = "Unpaid and Discounted"
- elif outstanding_amount > 0 and due_date >= now_date:
- status = "Unpaid"
- #Check if outstanding amount is 0 due to credit note issued against invoice
- elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': sales_invoice, 'docstatus': 1}):
- status = "Credit Note Issued"
- elif is_return == 1:
- status = "Return"
- elif outstanding_amount <=0:
- status = "Paid"
- else:
- status = "Submitted"
- else:
- status = "Draft"
-
- return status
-
def validate_inter_company_party(doctype, party, company, inter_company_reference):
if not party:
return
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index e48e6c9..3d5ce8a 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -786,7 +786,7 @@
def test_make_pos_invoice(self):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
- make_pos_profile()
+ pos_profile = make_pos_profile()
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
@@ -802,7 +802,7 @@
pos.append("taxes", tax)
invoice_data = [{'09052016142': pos}]
- si = make_invoice(invoice_data).get('invoice')
+ si = make_invoice(pos_profile, invoice_data).get('invoice')
self.assertEqual(si[0], '09052016142')
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1})
@@ -820,7 +820,7 @@
if allow_negative_stock:
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
- make_pos_profile()
+ pos_profile = make_pos_profile()
timestamp = cint(time.time())
item = make_item("_Test POS Item")
@@ -834,7 +834,7 @@
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
invoice_data = [{timestamp: pos}]
- si = make_invoice(invoice_data).get('invoice')
+ si = make_invoice(pos_profile, invoice_data).get('invoice')
self.assertEqual(si[0], timestamp)
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
@@ -843,7 +843,7 @@
timestamp = cint(time.time())
pos["offline_pos_name"] = timestamp
invoice_data = [{timestamp: pos}]
- si1 = make_invoice(invoice_data).get('invoice')
+ si1 = make_invoice(pos_profile, invoice_data).get('invoice')
self.assertEqual(si1[0], timestamp)
sales_invoice1 = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 6d53530..5ba455c 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -136,12 +136,11 @@
def make_entry(args, adv_adj, update_outstanding, from_repost=False):
- args.update({"doctype": "GL Entry"})
- gle = frappe.get_doc(args)
+ gle = frappe.new_doc("GL Entry")
+ gle.update(args)
gle.flags.ignore_permissions = 1
gle.flags.from_repost = from_repost
gle.validate()
- gle.flags.ignore_permissions = True
gle.db_insert()
gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost)
gle.flags.ignore_validate = True
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html
index 40469ae..9a2205a 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 && filters.show_name) { %}
+ {% } else if (filters.party) { %}
{%= 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 8750c23..898ac13 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -131,7 +131,7 @@
gl_entries = frappe.db.sql(
"""
select
- posting_date, account, party_type, party,
+ name as gl_entry, posting_date, account, party_type, party,
voucher_type, voucher_no, cost_center, project,
against_voucher_type, against_voucher, account_currency,
remarks, against, is_opening {select_fields}
@@ -363,6 +363,12 @@
columns = [
{
+ "fieldname": "gl_entry",
+ "fieldtype": "Link",
+ "options": "GL Entry",
+ "hidden": 1
+ },
+ {
"label": _("Posting Date"),
"fieldname": "posting_date",
"fieldtype": "Date",
diff --git a/erpnext/assets/doctype/location/location.json b/erpnext/assets/doctype/location/location.json
index 3323dae..6a35130 100644
--- a/erpnext/assets/doctype/location/location.json
+++ b/erpnext/assets/doctype/location/location.json
@@ -139,12 +139,14 @@
"read_only": 1
}
],
+ "is_tree": 1,
"links": [],
- "modified": "2020-03-02 19:34:28.362267",
+ "modified": "2020-03-18 18:00:08.885805",
"modified_by": "Administrator",
"module": "Assets",
"name": "Location",
"name_case": "Title Case",
+ "nsm_parent_field": "parent_location",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/buying/doctype/supplier/supplier_dashboard.py b/erpnext/buying/doctype/supplier/supplier_dashboard.py
index b3b294d..d0d5b73 100644
--- a/erpnext/buying/doctype/supplier/supplier_dashboard.py
+++ b/erpnext/buying/doctype/supplier/supplier_dashboard.py
@@ -34,4 +34,4 @@
'items': ['Pricing Rule']
}
]
- }
+ }
\ No newline at end of file
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index b465a10..4d0520a 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -69,6 +69,17 @@
["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"],
+ ],
"Material Request": [
["Draft", None],
["Stopped", "eval:self.status == 'Stopped'"],
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index d452fe4..f6908c0 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -238,7 +238,7 @@
for d in self.items:
if not d.batch_no: continue
- serial_nos = [d.name for d in frappe.get_all("Serial No", {'batch_no': d.batch_no})]
+ serial_nos = [sr.name for sr in frappe.get_all("Serial No", {'batch_no': d.batch_no})]
if serial_nos:
frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index 0e2068a..08be34e 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
@@ -214,7 +215,8 @@
{
"fieldname": "opportunity_amount",
"fieldtype": "Currency",
- "label": "Opportunity Amount"
+ "label": "Opportunity Amount",
+ "options": "currency"
},
{
"default": "0",
@@ -418,7 +420,8 @@
],
"icon": "fa fa-info-sign",
"idx": 195,
- "modified": "2019-09-30 12:58:37.385400",
+ "links": [],
+ "modified": "2020-03-20 12:28:45.228994",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",
diff --git a/erpnext/demo/user/fixed_asset.py b/erpnext/demo/user/fixed_asset.py
index e6d1687..dc094e1 100644
--- a/erpnext/demo/user/fixed_asset.py
+++ b/erpnext/demo/user/fixed_asset.py
@@ -6,46 +6,28 @@
import frappe
from frappe.utils.make_random import get_random
-from erpnext.assets.doctype.asset.asset import make_purchase_invoice, make_sales_invoice
+from erpnext.assets.doctype.asset.asset import make_sales_invoice
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset
+
def work():
frappe.set_user(frappe.db.get_global('demo_accounts_user'))
- asset_list = make_asset_purchase_entry()
-
- if not asset_list:
- # fixed_asset.work() already run
- return
-
# Enable booking asset depreciation entry automatically
frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1)
-
+
# post depreciation entries as on today
post_depreciation_entries()
-
+
# scrap a random asset
frappe.db.set_value("Company", "Wind Power LLC", "disposal_account", "Gain/Loss on Asset Disposal - WPL")
-
+
asset = get_random_asset()
scrap_asset(asset.name)
-
- # Sell a random asset
- sell_an_asset()
-def make_asset_purchase_entry():
- asset_list = frappe.get_all("Asset", filters={"purchase_invoice": ["in", ("", None)]},
- fields=["name", "item_code", "gross_purchase_amount", "company", "purchase_date"])
-
- # make purchase invoice
- for asset in asset_list:
- pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount,
- asset.company, asset.purchase_date)
- pi.supplier = get_random("Supplier")
- pi.save()
- pi.submit()
-
- return asset_list
+ # Sell a random asset
+ sell_an_asset()
+
def sell_an_asset():
asset = get_random_asset()
@@ -55,8 +37,9 @@
if asset.value_after_depreciation else asset.gross_purchase_amount * 0.9
si.save()
si.submit()
-
+
+
def get_random_asset():
return frappe.db.sql(""" select name, item_code, value_after_depreciation, gross_purchase_amount
- from `tabAsset`
+ from `tabAsset`
where docstatus=1 and status not in ("Scrapped", "Sold") order by rand() limit 1""", as_dict=1)[0]
diff --git a/erpnext/education/doctype/assessment_group/assessment_group.json b/erpnext/education/doctype/assessment_group/assessment_group.json
index 56917d2..a8ffaf4 100644
--- a/erpnext/education/doctype/assessment_group/assessment_group.json
+++ b/erpnext/education/doctype/assessment_group/assessment_group.json
@@ -1,274 +1,90 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:assessment_group_name",
- "beta": 0,
- "creation": "2016-08-04 04:42:48.319388",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:assessment_group_name",
+ "creation": "2016-08-04 04:42:48.319388",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "field_order": [
+ "assessment_group_name",
+ "is_group",
+ "section_break_2",
+ "parent_assessment_group",
+ "lft",
+ "rgt",
+ "old_parent"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "assessment_group_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": "Assessment Group 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,
- "unique": 0
- },
+ "fieldname": "assessment_group_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Assessment Group Name",
+ "reqd": 1,
+ "unique": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "is_group",
- "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 Group",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "is_group",
+ "fieldtype": "Check",
+ "label": "Is Group"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_2",
- "fieldtype": "Section Break",
- "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": 0,
- "print_hide_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": "section_break_2",
+ "fieldtype": "Section Break",
+ "hidden": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "parent_assessment_group",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Parent Assessment Group",
- "length": 0,
- "no_copy": 0,
- "options": "Assessment 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,
- "unique": 0
- },
+ "fieldname": "parent_assessment_group",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Parent Assessment Group",
+ "options": "Assessment Group",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lft",
- "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": "lft",
- "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": "lft",
+ "fieldtype": "Int",
+ "label": "lft"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "rgt",
- "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": "rgt",
- "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": "rgt",
+ "fieldtype": "Int",
+ "label": "rgt"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "old_parent",
- "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": "old_parent",
- "length": 0,
- "no_copy": 0,
- "options": "Assessment 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,
- "unique": 0
+ "fieldname": "old_parent",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "old_parent",
+ "options": "Assessment Group"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-11-10 19:09:25.366400",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Assessment Group",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_tree": 1,
+ "links": [],
+ "modified": "2020-03-18 18:01:14.710416",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Assessment Group",
+ "nsm_parent_field": "parent_assessment_group",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Academics User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Academics User",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Education",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "restrict_to_domain": "Education",
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
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 6e92455..8601f69 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
+++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
@@ -1,542 +1,205 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
+ "actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:healthcare_service_unit_name",
"beta": 1,
"creation": "2016-09-21 13:48:14.731437",
- "custom": 0,
"description": "Healthcare Service Unit",
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
+ "field_order": [
+ "healthcare_service_unit_name",
+ "parent_healthcare_service_unit",
+ "is_group",
+ "service_unit_type",
+ "allow_appointments",
+ "overlap_appointments",
+ "inpatient_occupancy",
+ "occupancy_status",
+ "warehouse",
+ "company",
+ "lft",
+ "rgt",
+ "old_parent"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "healthcare_service_unit_name",
"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": "Service Unit",
- "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": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
"bold": 1,
- "collapsible": 0,
- "columns": 0,
"fieldname": "parent_healthcare_service_unit",
"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": "Parent 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": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Healthcare Service Unit"
},
{
- "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 && doc.allow_appointments != 1",
"fieldname": "is_group",
"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": "Is Group",
- "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": "Is Group"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
"bold": 1,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:doc.is_group != 1",
"fieldname": "service_unit_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": "Service Unit Type",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Service Unit 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
+ "options": "Healthcare Service Unit Type"
},
{
- "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.is_group != 1 && doc.inpatient_occupancy != 1",
"fetch_from": "service_unit_type.allow_appointments",
"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": 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": "0",
"depends_on": "eval:doc.is_group != 1 && doc.allow_appointments == 1 && doc.inpatient_occupany != 1",
"fetch_from": "service_unit_type.overlap_appointments",
"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": 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": 1,
- "collapsible": 0,
- "columns": 0,
"default": "0",
"depends_on": "eval:doc.allow_appointments != 1 && doc.is_group != 1",
"fetch_from": "service_unit_type.inpatient_occupancy",
"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": 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,
- "default": "",
"depends_on": "eval:doc.inpatient_occupancy == 1",
"fieldname": "occupancy_status",
"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": "Occupancy Status",
- "length": 0,
"no_copy": 1,
"options": "Vacant\nOccupied",
- "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": 1,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:doc.is_group != 1",
"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": 1,
- "options": "Warehouse",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Warehouse"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "company",
"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": "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": 1,
- "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": "lft",
"fieldtype": "Int",
"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": "lft",
- "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": 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": "rgt",
"fieldtype": "Int",
"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": "rgt",
- "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": 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": "old_parent",
"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": "Old Parent",
- "length": 0,
"no_copy": 1,
"options": "Healthcare Service Unit",
- "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
}
],
- "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-10-04 21:09:52.261882",
+ "is_tree": 1,
+ "links": [],
+ "modified": "2020-03-18 18:02:23.713439",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Service Unit",
- "name_case": "",
+ "nsm_parent_field": "parent_healthcare_service_unit",
"owner": "Administrator",
"permissions": [
{
- "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
+ "share": 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,
"write": 1
},
{
- "amend": 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": "Physician",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
}
],
"quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Healthcare",
"search_fields": "healthcare_service_unit_name",
- "show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "healthcare_service_unit_name",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/department/department.json b/erpnext/hr/doctype/department/department.json
index a191b6b..6469f4c 100644
--- a/erpnext/hr/doctype/department/department.json
+++ b/erpnext/hr/doctype/department/department.json
@@ -129,11 +129,13 @@
],
"icon": "fa fa-sitemap",
"idx": 1,
+ "is_tree": 1,
"links": [],
- "modified": "2019-12-12 14:48:35.254308",
+ "modified": "2020-03-18 18:03:27.784362",
"modified_by": "Administrator",
"module": "HR",
"name": "Department",
+ "nsm_parent_field": "parent_department",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
index 3770da7..e9dc776 100644
--- a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
+++ b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
@@ -6,11 +6,14 @@
import frappe
import unittest
from frappe.utils import nowdate,flt, cstr,random_string
-# test_records = frappe.get_test_records('Vehicle Log')
+
class TestVehicleLog(unittest.TestCase):
def test_make_vehicle_log_and_syncing_of_odometer_value(self):
- employee_id=frappe.db.sql("""select name from `tabEmployee` order by modified desc limit 1""")[0][0]
+ employee_id = frappe.db.sql("""select name from `tabEmployee` where status='Active' order by modified desc limit 1""")
+ employee_id = employee_id[0][0] if employee_id else None
+
license_plate = get_vehicle(employee_id)
+
vehicle_log = frappe.get_doc({
"doctype": "Vehicle Log",
"license_plate": cstr(license_plate),
diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.js b/erpnext/hr/doctype/vehicle_log/vehicle_log.js
index bdb37d2..6f3a0dc 100644
--- a/erpnext/hr/doctype/vehicle_log/vehicle_log.js
+++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.js
@@ -3,11 +3,6 @@
frappe.ui.form.on("Vehicle Log", {
refresh: function(frm) {
-
- if(frm.doc.license_plate && frm.doc.__islocal){
- frm.events.set_vehicle_details(frm);
- }
-
if(frm.doc.docstatus == 1) {
frm.add_custom_button(__('Expense Claim'), function() {
frm.events.expense_claim(frm);
@@ -16,27 +11,6 @@
}
},
- license_plate: function(frm) {
- if(frm.doc.license_plate){
- frm.events.set_vehicle_details(frm);
- }
- },
-
- set_vehicle_details: function(frm) {
- frappe.call({
- method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model",
- args: {
- license_plate: frm.doc.license_plate
- },
- callback: function(r) {
- frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "make", r.message[0]);
- frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "model", r.message[1]);
- frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "last_odometer", r.message[2]);
- frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "employee", r.message[3]);
- }
- });
- },
-
expense_claim: function(frm){
frappe.call({
method: "erpnext.hr.doctype.vehicle_log.vehicle_log.make_expense_claim",
diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.json b/erpnext/hr/doctype/vehicle_log/vehicle_log.json
index 52effff..619e295 100644
--- a/erpnext/hr/doctype/vehicle_log/vehicle_log.json
+++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.json
@@ -1,5 +1,4 @@
{
- "actions": [],
"autoname": "naming_series:",
"creation": "2016-09-03 14:14:51.788550",
"doctype": "DocType",
@@ -56,6 +55,8 @@
"reqd": 1
},
{
+ "fetch_from": "license_plate.employee",
+ "fetch_if_empty": 1,
"fieldname": "employee",
"fieldtype": "Link",
"in_list_view": 1,
@@ -73,11 +74,13 @@
"fieldtype": "Column Break"
},
{
+ "fetch_from": "license_plate.model",
"fieldname": "model",
"fieldtype": "Read Only",
"label": "Model"
},
{
+ "fetch_from": "license_plate.make",
"fieldname": "make",
"fieldtype": "Read Only",
"label": "Make"
@@ -152,6 +155,7 @@
"read_only": 1
},
{
+ "fetch_from": "license_plate.last_odometer",
"fieldname": "last_odometer",
"fieldtype": "Int",
"label": "last Odometer Value ",
@@ -164,8 +168,7 @@
}
],
"is_submittable": 1,
- "links": [],
- "modified": "2020-01-28 12:43:34.419647",
+ "modified": "2020-03-18 16:45:45.060761",
"modified_by": "Administrator",
"module": "HR",
"name": "Vehicle Log",
diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.py b/erpnext/hr/doctype/vehicle_log/vehicle_log.py
index 12cc1dd..8affab2 100644
--- a/erpnext/hr/doctype/vehicle_log/vehicle_log.py
+++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.py
@@ -12,18 +12,7 @@
class VehicleLog(Document):
def validate(self):
if flt(self.odometer) < flt(self.last_odometer):
- frappe.throw(_("Current Odometer reading entered should be greater than initial Vehicle Odometer {0}").format(self.last_odometer))
- for service_detail in self.service_detail:
- if (service_detail.service_item or service_detail.type or service_detail.frequency or service_detail.expense_amount):
- if not (service_detail.service_item and service_detail.type and service_detail.frequency and service_detail.expense_amount):
- frappe.throw(_("Service Item,Type,frequency and expense amount are required"))
-
- def before_insert(self):
- model_details = get_make_model(self.license_plate)
- self.make = model_details[0]
- self.model = model_details[1]
- self.last_odometer = model_details[2]
- self.employee = model_details[3]
+ frappe.throw(_("Current Odometer Value should be greater than Last Odometer Value {0}").format(self.last_odometer))
def on_submit(self):
frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", self.odometer)
@@ -35,34 +24,25 @@
frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", updated_odometer_value)
@frappe.whitelist()
-def get_make_model(license_plate):
- vehicle=frappe.get_doc("Vehicle",license_plate)
- return (vehicle.make, vehicle.model, vehicle.last_odometer, vehicle.employee)
-
-@frappe.whitelist()
def make_expense_claim(docname):
- def check_exp_claim_exists():
- exp_claim = frappe.db.sql("""select name from `tabExpense Claim` where vehicle_log=%s""",vehicle_log.name)
- return exp_claim[0][0] if exp_claim else ""
- def calc_service_exp():
- total_exp_amt=0
- exp_claim = check_exp_claim_exists()
- if exp_claim:
- frappe.throw(_("Expense Claim {0} already exists for the Vehicle Log").format(exp_claim))
- for serdetail in vehicle_log.service_detail:
- total_exp_amt = total_exp_amt + serdetail.expense_amount
- return total_exp_amt
+ expense_claim = frappe.db.exists("Expense Claim", {"vehicle_log": docname})
+ if expense_claim:
+ frappe.throw(_("Expense Claim {0} already exists for the Vehicle Log").format(expense_claim))
vehicle_log = frappe.get_doc("Vehicle Log", docname)
+ service_expense = sum([flt(d.expense_amount) for d in vehicle_log.service_detail])
+
+ claim_amount = service_expense + flt(vehicle_log.price)
+ if not claim_amount:
+ frappe.throw(_("No additional expenses has been added"))
+
exp_claim = frappe.new_doc("Expense Claim")
- exp_claim.employee=vehicle_log.employee
- exp_claim.vehicle_log=vehicle_log.name
- exp_claim.remark=_("Expense Claim for Vehicle Log {0}").format(vehicle_log.name)
- fuel_price=vehicle_log.price
- total_claim_amt=calc_service_exp() + fuel_price
- exp_claim.append("expenses",{
- "expense_date":vehicle_log.date,
- "description":_("Vehicle Expenses"),
- "amount":total_claim_amt
+ exp_claim.employee = vehicle_log.employee
+ exp_claim.vehicle_log = vehicle_log.name
+ exp_claim.remark = _("Expense Claim for Vehicle Log {0}").format(vehicle_log.name)
+ exp_claim.append("expenses", {
+ "expense_date": vehicle_log.date,
+ "description": _("Vehicle Expenses"),
+ "amount": claim_amount
})
return exp_claim.as_dict()
diff --git a/erpnext/hr/doctype/vehicle_service/vehicle_service.json b/erpnext/hr/doctype/vehicle_service/vehicle_service.json
index 7d9d0df..e0bce2b 100644
--- a/erpnext/hr/doctype/vehicle_service/vehicle_service.json
+++ b/erpnext/hr/doctype/vehicle_service/vehicle_service.json
@@ -1,153 +1,57 @@
{
- "allow_copy": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2016-09-03 19:20:14.561962",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
+ "creation": "2016-09-03 19:20:14.561962",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "service_item",
+ "type",
+ "frequency",
+ "expense_amount"
+ ],
"fields": [
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "service_item",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Service Item",
- "length": 0,
- "no_copy": 0,
- "options": "\nBrake Oil\nBrake Pad\nClutch Plate\nEngine Oil\nOil Change\nWheels",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_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": "service_item",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Service Item",
+ "options": "\nBrake Oil\nBrake Pad\nClutch Plate\nEngine Oil\nOil Change\nWheels",
+ "reqd": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "type",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Type",
- "length": 0,
- "no_copy": 0,
- "options": "\nInspection\nService\nChange",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_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": "type",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Type",
+ "options": "\nInspection\nService\nChange",
+ "reqd": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "frequency",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Frequency",
- "length": 0,
- "no_copy": 0,
- "options": "\nMileage\nMonthly\nQuarterly\nHalf Yearly\nYearly",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_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": "frequency",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Frequency",
+ "options": "\nMileage\nMonthly\nQuarterly\nHalf Yearly\nYearly",
+ "reqd": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "expense_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Expense",
- "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": "expense_amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Expense",
+ "reqd": 1
}
- ],
- "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-01-09 11:10:29.476907",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Vehicle Service",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "istable": 1,
+ "modified": "2020-03-18 16:49:46.645004",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Vehicle Service",
+ "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/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 08c2f22..759b0d8 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -273,11 +273,11 @@
penalty_amount = (accrued_interest_amount * 4 * 25) / (100 * days_in_year(get_datetime(first_date).year))
- lia = frappe.get_all("Loan Interest Accrual", fields=["is_paid"],
- filters={"loan": loan.name}, order_by="posting_date")
+ lia1 = frappe.get_value("Loan Interest Accrual", {"loan": loan.name, "is_paid": 1}, 'name')
+ lia2 = frappe.get_value("Loan Interest Accrual", {"loan": loan.name, "is_paid": 0}, 'name')
- self.assertTrue(lia[0].get('is_paid'))
- self.assertFalse(lia[1].get('is_paid'))
+ self.assertTrue(lia1)
+ self.assertTrue(lia2)
def test_security_shortfall(self):
pledges = []
@@ -294,18 +294,21 @@
make_loan_disbursement_entry(loan.name, loan.loan_amount)
- frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = %s
- where loan_security=%s""", (100, 'Test Security 2'))
+ frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 100
+ where loan_security='Test Security 2'""")
check_for_ltv_shortfall()
loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
-
self.assertTrue(loan_security_shortfall)
self.assertEquals(loan_security_shortfall.loan_amount, 1000000.00)
self.assertEquals(loan_security_shortfall.security_value, 400000.00)
self.assertEquals(loan_security_shortfall.shortfall_amount, 600000.00)
+ frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
+ where loan_security='Test Security 2'""")
+
+
def create_loan_accounts():
if not frappe.db.exists("Account", "Loans and Advances (Assets) - _TC"):
frappe.get_doc({
@@ -399,7 +402,8 @@
"doctype": "Loan Security Type",
"loan_security_type": "Stock",
"unit_of_measure": "Nos",
- "haircut": 50.00
+ "haircut": 50.00,
+ "loan_to_value_ratio": 50
}).insert(ignore_permissions=True)
def create_loan_security():
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 a3442e4..b8e6dab 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
@@ -130,9 +130,10 @@
loan.loan_account, loan.principal_amount + loan.balance_loan_amount, loan.interest_amount,
payable_principal = loan.principal_amount , posting_date=posting_date)
- frappe.db.sql("""UPDATE `tabRepayment Schedule`
- SET is_accrued = 1 where name in (%s)""" #nosec
- % ", ".join(['%s']*len(accrued_entries)), tuple(accrued_entries))
+ 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):
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 7f8bd67..f6cdb2e 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -498,6 +498,14 @@
self.scrap_material_cost = total_sm_cost
self.base_scrap_material_cost = base_total_sm_cost
+ def update_new_bom(self, old_bom, new_bom, rate):
+ for d in self.get("items"):
+ if d.bom_no != old_bom: continue
+
+ d.bom_no = new_bom
+ d.rate = rate
+ d.amount = (d.stock_qty or d.qty) * rate
+
def update_exploded_items(self):
""" Update Flat BOM, following will be correct data"""
self.get_exploded_items()
@@ -827,6 +835,10 @@
def get_bom_diff(bom1, bom2):
from frappe.model import table_fields
+ if bom1 == bom2:
+ frappe.throw(_("BOM 1 {0} and BOM 2 {1} should not be same")
+ .format(frappe.bold(bom1), frappe.bold(bom2)))
+
doc1 = frappe.get_doc('BOM', bom1)
doc2 = frappe.get_doc('BOM', bom2)
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index 31a9fdb..2758a42 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -14,10 +14,13 @@
class BOMUpdateTool(Document):
def replace_bom(self):
self.validate_bom()
- self.update_new_bom()
+
+ unit_cost = get_new_bom_unit_cost(self.new_bom)
+ self.update_new_bom(unit_cost)
+
frappe.cache().delete_key('bom_children')
bom_list = self.get_parent_boms(self.new_bom)
- updated_bom = []
+
with click.progressbar(bom_list) as bom_list:
pass
for bom in bom_list:
@@ -26,7 +29,9 @@
# this is only used for versioning and we do not want
# to make separate db calls by using load_doc_before_save
# which proves to be expensive while doing bulk replace
- bom_obj._doc_before_save = bom_obj.as_dict()
+ bom_obj._doc_before_save = bom_obj
+ bom_obj.update_new_bom(self.current_bom, self.new_bom, unit_cost)
+ bom_obj.update_exploded_items()
bom_obj.calculate_cost()
bom_obj.update_parent_cost()
bom_obj.db_update()
@@ -43,14 +48,10 @@
!= frappe.db.get_value("BOM", self.new_bom, "item"):
frappe.throw(_("The selected BOMs are not for the same item"))
- def update_new_bom(self):
- new_bom_unitcost = frappe.db.sql("""SELECT `total_cost`/`quantity`
- FROM `tabBOM` WHERE name = %s""", self.new_bom)
- new_bom_unitcost = flt(new_bom_unitcost[0][0]) if new_bom_unitcost else 0
-
+ def update_new_bom(self, unit_cost):
frappe.db.sql("""update `tabBOM Item` set bom_no=%s,
rate=%s, amount=stock_qty*%s where bom_no = %s and docstatus < 2 and parenttype='BOM'""",
- (self.new_bom, new_bom_unitcost, new_bom_unitcost, self.current_bom))
+ (self.new_bom, unit_cost, unit_cost, self.current_bom))
def get_parent_boms(self, bom, bom_list=[]):
data = frappe.db.sql("""SELECT DISTINCT parent FROM `tabBOM Item`
@@ -65,12 +66,18 @@
return list(set(bom_list))
+def get_new_bom_unit_cost(bom):
+ new_bom_unitcost = frappe.db.sql("""SELECT `total_cost`/`quantity`
+ FROM `tabBOM` WHERE name = %s""", bom)
+
+ return flt(new_bom_unitcost[0][0]) if new_bom_unitcost else 0
+
@frappe.whitelist()
def enqueue_replace_bom(args):
if isinstance(args, string_types):
args = json.loads(args)
- frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args, timeout=4000)
+ frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args, timeout=40000)
frappe.msgprint(_("Queued for replacing the BOM. It may take a few minutes."))
@frappe.whitelist()
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 0a8f41f..2260bef 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -14,6 +14,7 @@
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
class TestWorkOrder(unittest.TestCase):
def setUp(self):
@@ -82,6 +83,37 @@
wo_order.set_work_order_operations()
self.assertEqual(wo_order.planned_operating_cost, cost*2)
+ def test_resered_qty_for_partial_completion(self):
+ item = "_Test Item"
+ warehouse = create_warehouse("Test Warehouse for reserved_qty - _TC")
+
+ bin1_at_start = get_bin(item, warehouse)
+
+ # reset to correct value
+ bin1_at_start.update_reserved_qty_for_production()
+
+ wo_order = make_wo_order_test_record(item="_Test FG Item", qty=2,
+ source_warehouse=warehouse, skip_transfer=1)
+
+ bin1_on_submit = get_bin(item, warehouse)
+
+ # reserved qty for production is updated
+ self.assertEqual(cint(bin1_at_start.reserved_qty_for_production) + 2,
+ cint(bin1_on_submit.reserved_qty_for_production))
+
+ test_stock_entry.make_stock_entry(item_code="_Test Item",
+ target=warehouse, qty=100, basic_rate=100)
+ test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
+ target=warehouse, qty=100, basic_rate=100)
+
+ s = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 1))
+ s.submit()
+
+ bin1_at_completion = get_bin(item, warehouse)
+
+ self.assertEqual(cint(bin1_at_completion.reserved_qty_for_production),
+ cint(bin1_on_submit.reserved_qty_for_production) - 1)
+
def test_production_item(self):
wo_order = make_wo_order_test_record(item="_Test FG Item", qty=1, do_not_save=True)
frappe.db.set_value("Item", "_Test FG Item", "end_of_life", "2000-1-1")
@@ -404,7 +436,7 @@
wo_order.company = args.company or "_Test Company"
wo_order.stock_uom = args.stock_uom or "_Test UOM"
wo_order.use_multi_level_bom=0
- wo_order.skip_transfer=1
+ wo_order.skip_transfer=args.skip_transfer or 0
wo_order.get_items_and_operations_from_bom()
wo_order.sales_order = args.sales_order or None
wo_order.planned_start_date = args.planned_start_date or now()
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index dd4a872..98149ae 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -279,7 +279,7 @@
if enable_capacity_planning and job_card_doc:
row.planned_start_time = job_card_doc.time_logs[-1].from_time
row.planned_end_time = job_card_doc.time_logs[-1].to_time
-
+ print(row.planned_start_time, original_start_time, plan_days)
if date_diff(row.planned_start_time, original_start_time) > plan_days:
frappe.message_log.pop()
frappe.throw(_("Unable to find the time slot in the next {0} days for the operation {1}.")
@@ -468,6 +468,9 @@
update bin reserved_qty_for_production
called from Stock Entry for production, after submit, cancel
'''
+ # calculate consumed qty based on submitted stock entries
+ self.update_consumed_qty_for_required_items()
+
if self.docstatus==1:
# calculate transferred qty based on submitted stock entries
self.update_transaferred_qty_for_required_items()
@@ -475,9 +478,6 @@
# update in bin
self.update_reserved_qty_for_production()
- # calculate consumed qty based on submitted stock entries
- self.update_consumed_qty_for_required_items()
-
def update_reserved_qty_for_production(self, items=None):
'''update reserved_qty_for_production in bins'''
for d in self.required_items:
diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
index 7152d3d..1bcb1ef 100644
--- a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
+++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
@@ -22,7 +22,14 @@
fieldname: 'name1',
fieldtype: 'Link',
options: 'BOM',
- change: () => this.fetch_and_render()
+ change: () => this.fetch_and_render(),
+ get_query: () => {
+ return {
+ filters: {
+ "name": ["not in", [this.form.get_value("name2") || ""]]
+ }
+ }
+ }
},
{
fieldtype: 'Column Break'
@@ -32,7 +39,14 @@
fieldname: 'name2',
fieldtype: 'Link',
options: 'BOM',
- change: () => this.fetch_and_render()
+ change: () => this.fetch_and_render(),
+ get_query: () => {
+ return {
+ filters: {
+ "name": ["not in", [this.form.get_value("name1") || ""]]
+ }
+ }
+ }
},
{
fieldtype: 'Section Break'
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index b0fc7ea..8aec8bd 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -658,4 +658,5 @@
erpnext.patches.v12_0.set_published_in_hub_tracked_item
erpnext.patches.v12_0.set_job_offer_applicant_email
erpnext.patches.v12_0.create_irs_1099_field_united_states
+erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
new file mode 100644
index 0000000..4aad142
--- /dev/null
+++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
@@ -0,0 +1,14 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.reload_doc('accounts', 'doctype', 'bank', force=1)
+
+ frappe.db.sql("""
+ UPDATE `tabBank` b, `tabBank Account` ba
+ SET b.swift_number = ba.swift_number, b.branch_code = ba.branch_code
+ WHERE b.name = ba.bank
+ """)
+
+ frappe.reload_doc('accounts', 'doctype', 'bank_account')
+ frappe.reload_doc('accounts', 'doctype', 'payment_request')
\ No newline at end of file
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index 794d816..f4b3d3e 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"autoname": "TASK-.YYYY.-.#####",
"creation": "2013-01-29 19:25:50",
@@ -200,7 +201,6 @@
{
"fieldname": "description",
"fieldtype": "Text Editor",
- "in_preview": 1,
"label": "Task Description",
"oldfieldname": "description",
"oldfieldtype": "Text Editor",
@@ -361,11 +361,14 @@
],
"icon": "fa fa-check",
"idx": 1,
+ "is_tree": 1,
+ "links": [],
"max_attachments": 5,
- "modified": "2019-09-10 13:46:24.631754",
+ "modified": "2020-03-18 18:08:44.153211",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
+ "nsm_parent_field": "parent_task",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index fea2d5e..fc4541a 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -4,7 +4,7 @@
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
setup: function() {
this._super();
- frappe.flags.hide_serial_batch_dialog = false;
+ frappe.flags.hide_serial_batch_dialog = true;
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
var has_margin_field = frappe.meta.has_field(cdt, 'margin_type');
@@ -165,6 +165,16 @@
return (doc.rule_applied) ? "green" : "red";
});
}
+
+ let batch_no_field = this.frm.get_docfield("items", "batch_no");
+ if (batch_no_field) {
+ batch_no_field.get_route_options_for_new_doc = function(row) {
+ return {
+ "item": row.doc.item_code
+ }
+ };
+ }
+
},
onload: function() {
var me = this;
@@ -520,6 +530,15 @@
},
() => me.toggle_conversion_factor(item),
() => {
+ if (show_batch_dialog)
+ return frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"])
+ .then((r) => {
+ if(r.message.has_batch_no || r.message.has_serial_no) {
+ frappe.flags.hide_serial_batch_dialog = false;
+ }
+ });
+ },
+ () => {
if(show_batch_dialog && !frappe.flags.hide_serial_batch_dialog) {
var d = locals[cdt][cdn];
$.each(r.message, function(k, v) {
@@ -528,7 +547,9 @@
erpnext.show_serial_batch_selector(me.frm, d, (item) => {
me.frm.script_manager.trigger('qty', item.doctype, item.name);
- });
+ if (!me.frm.doc.set_warehouse)
+ me.frm.script_manager.trigger('warehouse', item.doctype, item.name);
+ }, undefined, !frappe.flags.hide_serial_batch_dialog);
}
},
() => me.conversion_factor(doc, cdt, cdn, true),
diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js
index 8b6de0f..75c5a82 100644
--- a/erpnext/public/js/utils/dimension_tree_filter.js
+++ b/erpnext/public/js/utils/dimension_tree_filter.js
@@ -1,23 +1,25 @@
frappe.provide('frappe.ui.form');
-erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
+let default_dimensions = {};
+
+let doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
"Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Shipping Rule", "Loyalty Program",
"Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool",
"Subscription", "Purchase Order", "Journal Entry", "Material Request", "Purchase Receipt", "Landed Cost Item", "Asset"];
-erpnext.child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account",
+let child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account",
"Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction",
"Landed Cost Item", "Asset Value Adjustment", "Opening Invoice Creation Tool Item", "Subscription Plan"];
frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters",
- callback: function(r){
+ callback: function(r) {
erpnext.dimension_filters = r.message[0];
- erpnext.default_dimensions = r.message[1];
+ default_dimensions = r.message[1];
}
});
-erpnext.doctypes_with_dimensions.forEach((doctype) => {
+doctypes_with_dimensions.forEach((doctype) => {
frappe.ui.form.on(doctype, {
onload: function(frm) {
erpnext.dimension_filters.forEach((dimension) => {
@@ -27,41 +29,40 @@
"is_group": 0
});
}
-
- if (Object.keys(erpnext.default_dimensions).length > 0) {
- if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
- if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) {
- frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
- }
- }
-
- if (frm.doc.items && frm.doc.items.length && frm.doc.docstatus === 0
- && (!frm.doc.items[0][dimension['fieldname']])) {
- frm.doc.items[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
- }
-
- if (frm.doc.accounts && frm.doc.accounts.length && frm.doc.docstatus === 0
- && (!frm.doc.items[0][dimension['fieldname']])) {
- frm.doc.accounts[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
- }
- }
});
});
},
company: function(frm) {
- if(frm.doc.company && (Object.keys(erpnext.default_dimensions).length > 0)) {
- erpnext.dimension_filters.forEach((dimension) => {
- if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
- frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
- }
- });
+ if(frm.doc.company && (Object.keys(default_dimensions || {}).length > 0)
+ && default_dimensions[frm.doc.company]) {
+ frm.trigger('update_dimension');
}
},
+
+ update_dimension: function(frm) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ if (frm.is_new()) {
+ if (frm.doc.company && Object.keys(default_dimensions || {}).length > 0
+ && default_dimensions[frm.doc.company]) {
+
+ if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
+ frm.set_value(dimension['fieldname'],
+ default_dimensions[frm.doc.company][dimension['document_type']]);
+ }
+
+ $.each(frm.doc.items || frm.doc.accounts || [], function(i, row) {
+ frappe.model.set_value(row.doctype, row.name, dimension['fieldname'],
+ default_dimensions[frm.doc.company][dimension['document_type']])
+ });
+ }
+ }
+ });
+ }
});
});
-erpnext.child_docs.forEach((doctype) => {
+child_docs.forEach((doctype) => {
frappe.ui.form.on(doctype, {
items_add: function(frm, cdt, cdn) {
erpnext.dimension_filters.forEach((dimension) => {
@@ -77,14 +78,6 @@
});
},
- company: function(frm) {
- if(frm.doc.company) {
- erpnext.dimension_filters.forEach((dimension) => {
- frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
- });
- }
- },
-
items_add: function(frm, cdt, cdn) {
erpnext.dimension_filters.forEach((dimension) => {
var row = frappe.get_doc(cdt, cdn);
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index a240e49..d75633e 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -5,14 +5,13 @@
this.show_dialog = show_dialog;
// frm, item, warehouse_details, has_batch, oldest
let d = this.item;
- if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) {
- this.has_batch = 1;
- this.setup();
+ this.has_batch = 0; this.has_serial_no = 0;
+
+ if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) this.has_batch = 1;
// !(this.show_dialog == false) ensures that show_dialog is implictly true, even when undefined
- } else if(d && d.has_serial_no && !(this.show_dialog == false)) {
- this.has_batch = 0;
- this.setup();
- }
+ if(d && d.has_serial_no && !(this.show_dialog == false)) this.has_serial_no = 1;
+
+ this.setup();
},
setup: function() {
@@ -36,16 +35,16 @@
label: __('Item Code'),
default: me.item_code
},
- {fieldtype:'Column Break'},
{
fieldname: 'warehouse',
fieldtype:'Link',
options: 'Warehouse',
+ reqd: me.has_batch && !me.has_serial_no ? 0 : 1,
label: __(me.warehouse_details.type),
- default: me.warehouse_details.name,
+ default: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '',
onchange: function(e) {
- if(me.has_batch) {
+ if(me.has_batch && !me.has_serial_no) {
fields = fields.concat(me.get_batch_fields());
} else {
fields = fields.concat(me.get_serial_no_fields());
@@ -74,15 +73,16 @@
{
fieldname: 'qty',
fieldtype:'Float',
- read_only: me.has_batch,
- label: __(me.has_batch ? 'Total Qty' : 'Qty'),
+ read_only: me.has_batch && !me.has_serial_no,
+ label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'),
default: 0
},
{
fieldname: 'auto_fetch_button',
fieldtype:'Button',
- hidden: me.has_batch,
- label: __('Fetch based on FIFO'),
+ hidden: me.has_batch && !me.has_serial_no,
+ label: __('Auto Fetch'),
+ description: __('Fetch Serial Numbers based on FIFO'),
click: () => {
let qty = this.dialog.fields_dict.qty.get_value();
let numbers = frappe.call({
@@ -90,7 +90,7 @@
args: {
qty: qty,
item_code: me.item_code,
- warehouse: me.warehouse_details.name,
+ warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '',
batch_no: me.item.batch_no || null
}
});
@@ -109,10 +109,12 @@
}
];
- if (this.has_batch) {
+ if (this.has_batch && !this.has_serial_no) {
title = __("Select Batch Numbers");
fields = fields.concat(this.get_batch_fields());
} else {
+ // if only serial no OR
+ // if both batch_no & serial_no then only select serial_no and auto set batches nos
title = __("Select Serial Numbers");
fields = fields.concat(this.get_serial_no_fields());
}
@@ -122,25 +124,31 @@
fields: fields
});
- if (this.item.serial_no) {
- this.dialog.fields_dict.serial_no.set_value(this.item.serial_no);
- }
-
this.dialog.set_primary_action(__('Insert'), function() {
me.values = me.dialog.get_values();
if(me.validate()) {
- me.set_items();
- me.dialog.hide();
+ frappe.run_serially([
+ () => me.update_batch_items(),
+ () => me.update_serial_no_item(),
+ () => me.update_batch_serial_no_items(),
+ () => {
+ refresh_field("items");
+ if (me.callback) {
+ return me.callback(me.item);
+ }
+ },
+ () => me.dialog.hide()
+ ])
}
});
if(this.show_dialog) {
let d = this.item;
- if (d.has_serial_no && d.serial_no) {
- this.dialog.set_value('serial_no', d.serial_no);
+ if (this.item.serial_no) {
+ this.dialog.fields_dict.serial_no.set_value(this.item.serial_no);
}
-
- if (d.has_batch_no && d.batch_no) {
+
+ if (this.has_batch && !this.has_serial_no && d.batch_no) {
this.frm.doc.items.forEach(data => {
if(data.item_code == d.item_code) {
this.dialog.fields_dict.batches.df.data.push({
@@ -155,7 +163,7 @@
}
}
- if (this.has_batch) {
+ if (this.has_batch && !this.has_serial_no) {
this.update_total_qty();
}
@@ -174,7 +182,7 @@
frappe.throw(__("Please select a warehouse"));
return false;
}
- if(this.has_batch) {
+ if(this.has_batch && !this.has_serial_no) {
if(values.batches.length === 0 || !values.batches) {
frappe.throw(__("Please select batches for batched item "
+ values.item_code));
@@ -193,34 +201,23 @@
} else {
let serial_nos = values.serial_no || '';
if (!serial_nos || !serial_nos.replace(/\s/g, '').length) {
- if (!this.show_dialog) {
- frappe.throw(__("Please enter serial numbers for serialized item "
- + values.item_code));
- return false;
- }
+ frappe.throw(__("Please enter serial numbers for serialized item "
+ + values.item_code));
+ return false;
}
return true;
}
},
- set_items: function() {
- var me = this;
- if(this.has_batch) {
+ update_batch_items() {
+ // clones an items if muliple batches are selected.
+ if(this.has_batch && !this.has_serial_no) {
this.values.batches.map((batch, i) => {
let batch_no = batch.batch_no;
let row = '';
if (i !== 0 && !this.batch_exists(batch_no)) {
- row = this.frm.add_child("items", {
- 'item_code': this.item.item_code,
- 'item_name': this.item.item_name,
- 'price_list_rate': this.item.price_list_rate,
- 'rate': this.item.rate,
- 'qty': batch.selected_qty,
- 'batch_no': batch_no,
- 'actual_qty': this.item.actual_qty,
- 'discount_percentage': this.item.discount_percentage
- });
+ row = this.frm.add_child("items", { ...this.item });
} else {
row = this.frm.doc.items.find(i => i.batch_no === batch_no);
}
@@ -228,16 +225,59 @@
if (!row) {
row = this.item;
}
-
+ // this ensures that qty & batch no is set
this.map_row_values(row, batch, 'batch_no',
'selected_qty', this.values.warehouse);
});
- } else {
+ }
+ },
+
+ update_serial_no_item() {
+ // just updates serial no for the item
+ if(this.has_serial_no && !this.has_batch) {
this.map_row_values(this.item, this.values, 'serial_no', 'qty');
}
+ },
- refresh_field("items");
- this.callback && this.callback(this.item);
+ update_batch_serial_no_items() {
+ // if serial no selected is from different batches, adds new rows for each batch.
+ if(this.has_batch && this.has_serial_no) {
+ const selected_serial_nos = this.values.serial_no.split(/\n/g).filter(s => s);
+
+ return frappe.db.get_list("Serial No", {
+ filters: { 'name': ["in", selected_serial_nos]},
+ fields: ["batch_no", "name"]
+ }).then((data) => {
+ // data = [{batch_no: 'batch-1', name: "SR-001"},
+ // {batch_no: 'batch-2', name: "SR-003"}, {batch_no: 'batch-2', name: "SR-004"}]
+ const batch_serial_map = data.reduce((acc, d) => {
+ if (!acc[d['batch_no']]) acc[d['batch_no']] = [];
+ acc[d['batch_no']].push(d['name'])
+ return acc
+ }, {})
+ // batch_serial_map = { "batch-1": ['SR-001'], "batch-2": ["SR-003", "SR-004"]}
+ Object.keys(batch_serial_map).map((batch_no, i) => {
+ let row = '';
+ const serial_no = batch_serial_map[batch_no];
+ if (i == 0) {
+ row = this.item;
+ this.map_row_values(row, {qty: serial_no.length, batch_no: batch_no}, 'batch_no',
+ 'qty', this.values.warehouse);
+ } else if (!this.batch_exists(batch_no)) {
+ row = this.frm.add_child("items", { ...this.item });
+ row.batch_no = batch_no;
+ } else {
+ row = this.frm.doc.items.find(i => i.batch_no === batch_no);
+ }
+ const values = {
+ 'qty': serial_no.length,
+ 'serial_no': serial_no.join('\n')
+ }
+ this.map_row_values(row, values, 'serial_no',
+ 'qty', this.values.warehouse);
+ });
+ })
+ }
},
batch_exists: function(batch) {
@@ -287,7 +327,7 @@
return {
filters: {
item_code: me.item_code,
- warehouse: me.warehouse || me.warehouse_details.name
+ warehouse: me.warehouse || typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : ''
},
query: 'erpnext.controllers.queries.get_batch_no'
};
@@ -313,11 +353,15 @@
frappe.throw(__(`Batch ${val} already selected.`));
return;
}
+
+ let batch_number = me.item.batch_no ||
+ this.grid_row.on_grid_fields_dict.batch_no.get_value();
+
if (me.warehouse_details.name) {
frappe.call({
method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
args: {
- batch_no: me.item.batch_no,
+ batch_no: batch_number,
warehouse: me.warehouse_details.name,
item_code: me.item_code
},
@@ -444,7 +488,7 @@
{
fieldname: 'serial_no',
fieldtype: 'Small Text',
- label: __(me.has_batch ? 'Selected Batch Numbers' : 'Selected Serial Numbers'),
+ label: __(me.has_batch && !me.has_serial_no ? 'Selected Batch Numbers' : 'Selected Serial Numbers'),
onchange: function() {
me.serial_list = this.get_value()
.replace(/\n/g, ' ').match(/\S+/g) || [];
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
index 472b751..6df116c 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "format:PRC-{quality_procedure_name}",
"creation": "2018-10-06 00:06:29.756804",
"doctype": "DocType",
@@ -69,10 +70,13 @@
"reqd": 1
}
],
- "modified": "2019-08-05 13:09:29.945082",
+ "is_tree": 1,
+ "links": [],
+ "modified": "2020-03-18 18:09:29.371627",
"modified_by": "Administrator",
"module": "Quality Management",
"name": "Quality Procedure",
+ "nsm_parent_field": "parent_quality_procedure",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index 7ceaf50..e9b4235 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -109,7 +109,7 @@
WHERE gl.company = %(company)s
AND DATE(gl.posting_date) >= %(from_date)s
AND DATE(gl.posting_date) <= %(to_date)s
- ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1)
+ ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict)
return gl_entries
@@ -160,7 +160,7 @@
and ccl.company = par.company
WHERE par.company = %(company)s
- AND par.parenttype = 'Customer'""", filters, as_dict=1, as_utf8=1)
+ AND par.parenttype = 'Customer'""", filters, as_dict=1)
def get_suppliers(filters):
@@ -217,7 +217,7 @@
and con.is_primary_contact = '1'
WHERE par.company = %(company)s
- AND par.parenttype = 'Supplier'""", filters, as_dict=1, as_utf8=1)
+ AND par.parenttype = 'Supplier'""", filters, as_dict=1)
def get_account_names(filters):
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 2c5ab7c..fd1cc58 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -54,8 +54,8 @@
return self.columns, self.data
def get_data(self):
- if self.filters.get("type_of_business") == "B2C Small":
- self.get_b2cs_data()
+ if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"):
+ self.get_b2c_data()
else:
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
invoice_details = self.invoices.get(inv)
@@ -69,7 +69,7 @@
if taxable_value:
self.data.append(row)
- def get_b2cs_data(self):
+ def get_b2c_data(self):
b2cs_output = {}
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
@@ -84,7 +84,10 @@
"rate": "",
"taxable_value": 0,
"cess_amount": 0,
- "type": ""
+ "type": "",
+ "invoice_number": invoice_details.get("invoice_number"),
+ "posting_date": invoice_details.get("posting_date"),
+ "invoice_value": invoice_details.get("base_grand_total"),
})
row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin))
@@ -164,7 +167,7 @@
frappe.throw(_("Please set B2C Limit in GST Settings."))
if self.filters.get("type_of_business") == "B2C Large":
- conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
+ conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'')
and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit))
elif self.filters.get("type_of_business") == "B2C Small":
@@ -581,6 +584,11 @@
if not gst_in: continue
for number, invoice in iteritems(res[gst_in]):
+ if not invoice[0]["place_of_supply"]:
+ frappe.throw(_("""{0} not entered in Invoice {1}.
+ Please update and try again""").format(frappe.bold("Place Of Supply"),
+ frappe.bold(invoice[0]['invoice_number'])))
+
inv_item = get_basic_invoice_detail(invoice[0])
inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0])
inv_item["rchrg"] = invoice[0]["reverse_charge"]
@@ -606,6 +614,9 @@
out = []
for d in data:
+ if not d.get("place_of_supply"):
+ frappe.throw(_("""{0} not entered in some invoices.
+ Please update and try again""").format(frappe.bold("Place Of Supply")))
pos = d.get('place_of_supply').split('-')[0]
tax_details = {}
@@ -642,6 +653,10 @@
def get_b2cl_json(res, gstin):
out = []
for pos in res:
+ if not pos:
+ frappe.throw(_("""{0} not entered in some invoices.
+ Please update and try again""").format(frappe.bold("Place Of Supply")))
+
b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, []
for row in res[pos]:
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 9261289..02667e8 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -76,7 +76,8 @@
def validate_default_bank_account(self):
if self.default_bank_account:
is_company_account = frappe.db.get_value('Bank Account', self.default_bank_account, 'is_company_account')
- frappe.throw(_("{0} is not a company bank account").format(frappe.bold(self.default_bank_account)))
+ if not is_company_account:
+ frappe.throw(_("{0} is not a company bank account").format(frappe.bold(self.default_bank_account)))
def on_update(self):
self.validate_name_with_customer_group()
@@ -267,9 +268,11 @@
target_doc.run_method("set_other_charges")
target_doc.run_method("calculate_taxes_and_totals")
- price_list = frappe.get_value("Customer", source_name, 'default_price_list')
+ price_list, currency = frappe.db.get_value("Customer", {'name': source_name}, ['default_price_list', 'default_currency'])
if price_list:
target_doc.selling_price_list = price_list
+ if currency:
+ target_doc.currency = currency
return target_doc
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 8278745..af10069 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -413,15 +413,20 @@
*/
set_batch_number: function(cdt, cdn) {
const doc = frappe.get_doc(cdt, cdn);
- if (doc && doc.has_batch_no) {
+ if (doc && doc.has_batch_no && doc.warehouse) {
this._set_batch_number(doc);
}
},
_set_batch_number: function(doc) {
+ let args = {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)};
+ if (doc.has_serial_no && doc.serial_no) {
+ args['serial_no'] = doc.serial_no
+ }
+
return frappe.call({
method: 'erpnext.stock.doctype.batch.batch.get_batch_no',
- args: {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)},
+ args: args,
callback: function(r) {
if(r.message) {
frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message);
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index dd602ec..020a93f 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:company_name",
@@ -156,6 +157,7 @@
{
"fieldname": "parent_company",
"fieldtype": "Link",
+ "ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Parent Company",
"options": "Company"
@@ -276,6 +278,7 @@
"depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"",
"fieldname": "existing_company",
"fieldtype": "Link",
+ "ignore_user_permissions": 1,
"label": "Existing Company ",
"no_copy": 1,
"options": "Company"
@@ -725,10 +728,13 @@
"icon": "fa fa-building",
"idx": 1,
"image_field": "company_logo",
- "modified": "2019-11-22 13:04:47.470768",
+ "is_tree": 1,
+ "links": [],
+ "modified": "2020-03-21 18:09:53.534211",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",
+ "nsm_parent_field": "parent_company",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py
index af30abd..b37cc17 100644
--- a/erpnext/setup/doctype/company/test_company.py
+++ b/erpnext/setup/doctype/company/test_company.py
@@ -9,7 +9,7 @@
from frappe.utils import random_string
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import get_charts_for_country
-test_ignore = ["Account", "Cost Center", "Payment Terms Template", "Salary Component"]
+test_ignore = ["Account", "Cost Center", "Payment Terms Template", "Salary Component", "Warehouse"]
test_dependencies = ["Fiscal Year"]
test_records = frappe.get_test_records('Company')
diff --git a/erpnext/setup/doctype/customer_group/customer_group.json b/erpnext/setup/doctype/customer_group/customer_group.json
index 7fa242a..10f9bd0 100644
--- a/erpnext/setup/doctype/customer_group/customer_group.json
+++ b/erpnext/setup/doctype/customer_group/customer_group.json
@@ -137,11 +137,13 @@
],
"icon": "fa fa-sitemap",
"idx": 1,
+ "is_tree": 1,
"links": [],
- "modified": "2020-01-28 13:49:23.961708",
+ "modified": "2020-03-18 18:10:13.048492",
"modified_by": "Administrator",
"module": "Setup",
"name": "Customer Group",
+ "nsm_parent_field": "parent_customer_group",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/setup/doctype/item_group/item_group.json b/erpnext/setup/doctype/item_group/item_group.json
index 36e3e68..004421d 100644
--- a/erpnext/setup/doctype/item_group/item_group.json
+++ b/erpnext/setup/doctype/item_group/item_group.json
@@ -185,13 +185,15 @@
"icon": "fa fa-sitemap",
"idx": 1,
"image_field": "image",
+ "is_tree": 1,
"links": [],
"max_attachments": 3,
- "modified": "2020-01-28 13:51:05.456014",
+ "modified": "2020-03-18 18:10:34.383363",
"modified_by": "Administrator",
"module": "Setup",
"name": "Item Group",
"name_case": "Title Case",
+ "nsm_parent_field": "parent_item_group",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/setup/doctype/sales_person/sales_person.json b/erpnext/setup/doctype/sales_person/sales_person.json
index b05365d..e526ac4 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.json
+++ b/erpnext/setup/doctype/sales_person/sales_person.json
@@ -143,11 +143,13 @@
],
"icon": "icon-user",
"idx": 1,
+ "is_tree": 1,
"links": [],
- "modified": "2020-01-28 13:50:31.891050",
+ "modified": "2020-03-18 18:11:13.968024",
"modified_by": "Administrator",
"module": "Setup",
"name": "Sales Person",
+ "nsm_parent_field": "parent_sales_person",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.json b/erpnext/setup/doctype/supplier_group/supplier_group.json
index 5c41334..9119bb9 100644
--- a/erpnext/setup/doctype/supplier_group/supplier_group.json
+++ b/erpnext/setup/doctype/supplier_group/supplier_group.json
@@ -1,481 +1,163 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
+ "actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:supplier_group_name",
- "beta": 0,
"creation": "2013-01-10 16:34:24",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
- "editable_grid": 0,
+ "field_order": [
+ "supplier_group_name",
+ "parent_supplier_group",
+ "is_group",
+ "section_credit_limit",
+ "payment_terms",
+ "default_payable_account",
+ "accounts",
+ "lft",
+ "rgt",
+ "old_parent"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "supplier_group_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": "Supplier Group Name",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "supplier_type",
"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": 1,
- "collapsible": 0,
- "columns": 0,
"fieldname": "parent_supplier_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": 0,
"label": "Parent Supplier Group",
- "length": 0,
- "no_copy": 0,
- "options": "Supplier 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
+ "options": "Supplier Group"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
"bold": 1,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "is_group",
"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": "Is Group",
- "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": "Is Group"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
"fieldname": "section_credit_limit",
"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": "Credit 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
+ "label": "Credit Limit"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "payment_terms",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Default Payment Terms Template",
- "length": 0,
- "no_copy": 0,
- "options": "Payment Terms Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Payment Terms Template"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "default_payable_account",
"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": "Default Payable Account",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Default Payable Account"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:!doc.__islocal",
"description": "Mention if non-standard receivable account applicable",
"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": "Accounts",
- "length": 0,
- "no_copy": 0,
- "options": "Party Account",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Party Account"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "lft",
"fieldtype": "Int",
"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": "lft",
- "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
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"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": "rgt",
- "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
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "old_parent",
"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": "Old Parent",
- "length": 0,
"no_copy": 1,
"options": "Supplier 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
+ "report_hide": 1
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
"icon": "fa fa-flag",
"idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-29 06:25:57.589824",
+ "is_tree": 1,
+ "links": [],
+ "modified": "2020-03-18 18:10:49.228407",
"modified_by": "Administrator",
"module": "Setup",
"name": "Supplier Group",
+ "nsm_parent_field": "parent_supplier_group",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Purchase Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Purchase Manager"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Purchase User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Purchase User"
},
{
- "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": "Purchase Master Manager",
"set_user_permissions": 1,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
"role": "Purchase Master Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
- "role": "Purchase Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Purchase Manager"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
- "role": "Purchase User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Purchase User"
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"show_name_in_global_search": 1,
- "sort_order": "ASC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "sort_order": "ASC"
}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/territory/territory.json b/erpnext/setup/doctype/territory/territory.json
index 91a3dda..aa8e048 100644
--- a/erpnext/setup/doctype/territory/territory.json
+++ b/erpnext/setup/doctype/territory/territory.json
@@ -121,12 +121,14 @@
],
"icon": "fa fa-map-marker",
"idx": 1,
+ "is_tree": 1,
"links": [],
- "modified": "2020-01-28 13:49:31.905800",
+ "modified": "2020-03-18 18:11:36.623555",
"modified_by": "Administrator",
"module": "Setup",
"name": "Territory",
"name_case": "Title Case",
+ "nsm_parent_field": "parent_territory",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index 8ae978e..9b7249e 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -122,8 +122,11 @@
self.expiry_date = add_days(self.manufacturing_date, shelf_life_in_days)
if has_expiry_date and not self.expiry_date:
- frappe.msgprint(_('Expiry date is mandatory for selected item.'))
- frappe.throw(_("Set item's shelf life in days, to set expiry based on manufacturing date plus shelf-life."))
+ frappe.throw(msg=_("Please set {0} for Batched Item {1}, which is used to set {2} on Submit.") \
+ .format(frappe.bold("Shelf Life in Days"),
+ frappe.utils.get_link_to_form("Item", self.item),
+ frappe.bold("Batch Expiry Date")),
+ title=_("Expiry Date Mandatory"))
def get_name_from_naming_series(self):
"""
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 97a8472..73b36e3 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -69,15 +69,21 @@
'''Update qty reserved for production from Production Item tables
in open work orders'''
self.reserved_qty_for_production = frappe.db.sql('''
- select sum(item.required_qty - item.transferred_qty)
- from `tabWork Order` pro, `tabWork Order Item` item
- where
+ SELECT
+ CASE WHEN ifnull(skip_transfer, 0) = 0 THEN
+ SUM(item.required_qty - item.transferred_qty)
+ ELSE
+ SUM(item.required_qty - item.consumed_qty)
+ END
+ FROM `tabWork Order` pro, `tabWork Order Item` item
+ WHERE
item.item_code = %s
and item.parent = pro.name
and pro.docstatus = 1
and item.source_warehouse = %s
and pro.status not in ("Stopped", "Completed")
- and item.required_qty > item.transferred_qty''', (self.item_code, self.warehouse))[0][0]
+ and (item.required_qty > item.transferred_qty or item.required_qty > item.consumed_qty)
+ ''', (self.item_code, self.warehouse))[0][0]
self.set_projected_qty()
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index a34db45..28e9533 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -238,7 +238,7 @@
try:
directions = maps_client.directions(**directions_data)
except Exception as e:
- frappe.throw(_(e))
+ frappe.throw(_(str(e)))
return directions[0] if directions else False
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 3503e7c..aa6b2fe 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -343,7 +343,8 @@
{
"fieldname": "shelf_life_in_days",
"fieldtype": "Int",
- "label": "Shelf Life In Days"
+ "label": "Shelf Life In Days",
+ "mandatory_depends_on": "eval:doc.has_batch_no && doc.has_expiry_date"
},
{
"default": "2099-12-31",
@@ -1045,7 +1046,7 @@
"image_field": "image",
"links": [],
"max_attachments": 1,
- "modified": "2020-01-02 19:13:59.295963",
+ "modified": "2020-03-24 16:14:36.950677",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 74ae627..f805a67 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -183,12 +183,17 @@
# default warehouse, or Stores
for default in self.item_defaults or [frappe._dict({'company': frappe.defaults.get_defaults().company})]:
default_warehouse = (default.default_warehouse
- or frappe.db.get_single_value('Stock Settings', 'default_warehouse')
- or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}))
+ 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})
if default_warehouse:
stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock,
- rate=self.valuation_rate, company=default.company)
+ rate=self.valuation_rate, company=default.company)
stock_entry.add_comment("Comment", _("Opening Stock"))
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index 7df40fb..d97b699 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -104,7 +104,6 @@
def update_landed_cost(self):
for d in self.get("purchase_receipts"):
doc = frappe.get_doc(d.receipt_document_type, d.receipt_document)
-
# check if there are {qty} assets created and linked to this receipt document
self.validate_asset_qty_and_status(d.receipt_document_type, doc)
@@ -123,6 +122,8 @@
# update latest valuation rate in serial no
self.update_rate_in_serial_no_for_non_asset_items(doc)
+ for d in self.get("purchase_receipts"):
+ doc = frappe.get_doc(d.receipt_document_type, d.receipt_document)
# update stock & gl entries for cancelled state of PR
doc.docstatus = 2
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index d80e8f2..cba7f20 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -53,7 +53,7 @@
self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
def test_batched_serial_no_purchase(self):
- item = frappe.get_doc("Item", { 'item_name': 'Batched Serialized Item' })
+ item = frappe.db.exists("Item", {'item_name': 'Batched Serialized Item'})
if not item:
item = create_item("Batched Serialized Item")
item.has_batch_no = 1
@@ -62,6 +62,8 @@
item.batch_number_series = "BS-BATCH-.##"
item.serial_no_series = "BS-.####"
item.save()
+ else:
+ item = frappe.get_doc("Item", {'item_name': 'Batched Serialized Item'})
pr = make_purchase_receipt(item_code=item.name, qty=5, rate=500)
@@ -302,6 +304,8 @@
self.assertEqual(serial_no, frappe.db.get_value("Serial No",
{"purchase_document_type": "Purchase Receipt", "purchase_document_no": pr_doc.name}, "name"))
+ pr_doc.cancel()
+
#check for the auto created serial nos
item_code = "Test Auto Created Serial No"
if not frappe.db.exists("Item", item_code):
@@ -317,9 +321,9 @@
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
- item_code = frappe.db.get_value('Item', {'has_serial_no': 1, 'is_fixed_asset': 0})
+ item_code = frappe.db.get_value('Item', {'has_serial_no': 1, 'is_fixed_asset': 0, "has_batch_no": 0})
if not item_code:
- item = make_item("Test Serial Item 1", dict(has_serial_no=1))
+ item = make_item("Test Serial Item 1", dict(has_serial_no=1, has_batch_no=0))
item_code = item.name
serial_no = random_string(5)
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 a876d16..a8b9c81 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -832,7 +832,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-03-05 14:19:48.799370",
+ "modified": "2020-03-11 14:19:48.799370",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 64d4c6c..772ac58 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -523,12 +523,15 @@
return serial_nos
@frappe.whitelist()
-def auto_fetch_serial_number(qty, item_code, warehouse, batch_no=None):
- serial_numbers = frappe.get_list("Serial No", filters={
+def auto_fetch_serial_number(qty, item_code, warehouse, batch_nos=None):
+ import json
+ filters = {
"item_code": item_code,
"warehouse": warehouse,
- "batch_no": batch_no,
"delivery_document_no": "",
"sales_invoice": ""
- }, limit=qty, order_by="creation")
+ }
+ if batch_nos: filters["batch_no"] = ["in", json.loads(batch_nos)]
+
+ serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation")
return [item['name'] for item in serial_numbers]
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 2840a70..3af3524 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -60,7 +60,8 @@
}
}
- if(item.s_warehouse) filters["warehouse"] = item.s_warehouse;
+ filters["warehouse"] = item.s_warehouse || item.t_warehouse;
+
return {
query : "erpnext.controllers.queries.get_batch_no",
filters: filters
@@ -964,7 +965,7 @@
}
}
- if(item && !item.has_serial_no && item.has_batch_no) return;
+ if(item && !item.has_serial_no && !item.has_batch_no) return;
if (frm.doc.purpose === 'Material Receipt') return;
frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() {
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 8b072c6..8d746ba 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -177,6 +177,10 @@
stock_items = self.get_stock_items()
serialized_items = self.get_serialized_items()
for item in self.get("items"):
+ if item.qty and item.qty < 0:
+ frappe.throw(_("Row {0}: The item {1}, quantity must be positive number")
+ .format(item.idx, frappe.bold(item.item_code)))
+
if item.item_code not in stock_items:
frappe.throw(_("{0} is not a stock Item").format(item.item_code))
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
index d86e68b..a848c80 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "hash",
"creation": "2013-03-29 18:22:12",
"doctype": "DocType",
@@ -479,8 +480,7 @@
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
- "options": "Project",
- "read_only": 1
+ "options": "Project"
},
{
"fieldname": "po_detail",
@@ -494,7 +494,8 @@
],
"idx": 1,
"istable": 1,
- "modified": "2019-08-20 14:01:02.319754",
+ "links": [],
+ "modified": "2020-03-19 12:34:09.836295",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",
diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json
index 2bf1ed8..5d534af 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.json
+++ b/erpnext/stock/doctype/warehouse/warehouse.json
@@ -228,11 +228,13 @@
],
"icon": "fa fa-building",
"idx": 1,
+ "is_tree": 1,
"links": [],
- "modified": "2020-01-28 13:50:59.368846",
+ "modified": "2020-03-18 18:11:53.282358",
"modified_by": "Administrator",
"module": "Stock",
"name": "Warehouse",
+ "nsm_parent_field": "parent_warehouse",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
index 913d7d8..c8efb16 100644
--- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
+++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
@@ -44,7 +44,9 @@
re_order_level = d.warehouse_reorder_level
re_order_qty = d.warehouse_reorder_qty
- shortage_qty = re_order_level - flt(bin.projected_qty) if (re_order_level or re_order_qty) else 0
+ shortage_qty = 0
+ if (re_order_level or re_order_qty) and re_order_level > bin.projected_qty:
+ shortage_qty = re_order_level - flt(bin.projected_qty)
data.append([item.name, item.item_name, item.description, item.item_group, item.brand, bin.warehouse,
item.stock_uom, bin.actual_qty, bin.planned_qty, bin.indented_qty, bin.ordered_qty,
diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py
index dfd3ed7..16ecd51 100644
--- a/erpnext/tests/utils.py
+++ b/erpnext/tests/utils.py
@@ -7,6 +7,8 @@
def create_test_contact_and_address():
frappe.db.sql('delete from tabContact')
+ frappe.db.sql('delete from `tabContact Email`')
+ frappe.db.sql('delete from `tabContact Phone`')
frappe.db.sql('delete from tabAddress')
frappe.db.sql('delete from `tabDynamic Link`')
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 2099810..f88ffd4 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -5,7 +5,7 @@
import frappe
import frappe.share
from frappe import _
-from frappe.utils import cstr, now_datetime, cint, flt, get_time
+from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_link_to_form
from erpnext.controllers.status_updater import StatusUpdater
from six import string_types
@@ -123,8 +123,11 @@
ref_rate = frappe.db.get_value(ref_dt + " Item", d.get(ref_link_field), "rate")
if abs(flt(d.rate - ref_rate, d.precision("rate"))) >= .01:
- frappe.throw(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ")
+ frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ")
.format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate))
+ frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.")
+ .format(frappe.bold("Maintain Same Rate Throughout Sales Cycle"),
+ get_link_to_form("Selling Settings", "Selling Settings", frappe.bold("Selling Settings"))))
def get_link_filters(self, for_doctype):
if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype):