diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index cccced8e0b..cf1748f6a7 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -109,12 +109,13 @@ class Account(NestedSet):
if not descendants: return
parent_acc_name_map = {}
- parent_acc_name = frappe.db.get_value('Account', self.parent_account, "account_name")
+ parent_acc_name, parent_acc_number = frappe.db.get_value('Account', self.parent_account, \
+ ["account_name", "account_number"])
for d in frappe.db.get_values('Account',
- {"company": ["in", descendants], "account_name": parent_acc_name},
+ { "company": ["in", descendants], "account_name": parent_acc_name,
+ "account_number": parent_acc_number },
["company", "name"], as_dict=True):
parent_acc_name_map[d["company"]] = d["name"]
-
if not parent_acc_name_map: return
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 7b2061ac16..917acba92c 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -248,7 +248,7 @@ class PurchaseInvoice(BuyingController):
def set_against_expense_account(self):
against_accounts = []
for item in self.get("items"):
- if item.expense_account not in against_accounts:
+ if item.expense_account and (item.expense_account not in against_accounts):
against_accounts.append(item.expense_account)
self.against_expense_account = ",".join(against_accounts)
diff --git a/erpnext/accounts/doctype/purchase_invoice/regional/india.js b/erpnext/accounts/doctype/purchase_invoice/regional/india.js
new file mode 100644
index 0000000000..81488a2c52
--- /dev/null
+++ b/erpnext/accounts/doctype/purchase_invoice/regional/india.js
@@ -0,0 +1,3 @@
+{% include "erpnext/regional/india/taxes.js" %}
+
+erpnext.setup_auto_gst_taxation('Purchase Invoice');
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.json b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.json
index bc42630d47..a18fec61cf 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.json
@@ -1,300 +1,108 @@
{
- "allow_copy": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:title",
- "beta": 0,
- "creation": "2013-01-10 16:34:08",
- "custom": 0,
- "description": "Standard tax template that can be applied to all Purchase Transactions. This template can contain list of tax heads and also other expense heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.\n10. Add or Deduct: Whether you want to add or deduct the tax.",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "creation": "2013-01-10 16:34:08",
+ "description": "Standard tax template that can be applied to all Purchase Transactions. This template can contain list of tax heads and also other expense heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.\n10. Add or Deduct: Whether you want to add or deduct the tax.",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "field_order": [
+ "title",
+ "is_default",
+ "disabled",
+ "column_break4",
+ "company",
+ "tax_category",
+ "section_break6",
+ "taxes"
+ ],
"fields": [
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "title",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Title",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "title",
- "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,
- "unique": 0
- },
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "label": "Title",
+ "no_copy": 1,
+ "oldfieldname": "title",
+ "oldfieldtype": "Data",
+ "reqd": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "is_default",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Default",
- "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,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "is_default",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Default"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "disabled",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Disabled",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Disabled"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break4",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "column_break4",
+ "fieldtype": "Column Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Company",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break6",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "section_break6",
+ "fieldtype": "Section Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "taxes",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Purchase Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "purchase_tax_details",
- "oldfieldtype": "Table",
- "options": "Purchase Taxes and Charges",
- "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,
- "unique": 0
+ "fieldname": "taxes",
+ "fieldtype": "Table",
+ "label": "Purchase Taxes and Charges",
+ "oldfieldname": "purchase_tax_details",
+ "oldfieldtype": "Table",
+ "options": "Purchase Taxes and Charges"
+ },
+ {
+ "fieldname": "tax_category",
+ "fieldtype": "Link",
+ "label": "Tax Category",
+ "options": "Tax Category"
}
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-money",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
-
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2016-11-07 05:18:44.095798",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Purchase Taxes and Charges Template",
- "owner": "wasim@webnotestech.com",
+ ],
+ "icon": "fa fa-money",
+ "idx": 1,
+ "modified": "2019-11-25 13:05:26.220275",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Purchase Taxes and Charges Template",
+ "owner": "wasim@webnotestech.com",
"permissions": [
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Purchase Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Purchase Manager"
+ },
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Purchase Master Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Purchase Master Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Purchase User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "read": 1,
+ "role": "Purchase User"
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "sort_order": "DESC",
- "track_seen": 0
+ ],
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india.js b/erpnext/accounts/doctype/sales_invoice/regional/india.js
index c8305e325f..48fa364faf 100644
--- a/erpnext/accounts/doctype/sales_invoice/regional/india.js
+++ b/erpnext/accounts/doctype/sales_invoice/regional/india.js
@@ -1,3 +1,7 @@
+{% include "erpnext/regional/india/taxes.js" %}
+
+erpnext.setup_auto_gst_taxation('Sales Invoice');
+
frappe.ui.form.on("Sales Invoice", {
setup: function(frm) {
frm.set_query('transporter', function() {
@@ -35,4 +39,5 @@ frappe.ui.form.on("Sales Invoice", {
}, __("Make"));
}
}
+
});
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 2ea74f6d85..7f4ae3c1fc 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -697,8 +697,8 @@ frappe.ui.form.on('Sales Invoice', {
if (frm.doc.company)
{
frappe.call({
- method:"frappe.contacts.doctype.address.address.get_default_address",
- args:{ doctype:'Company',name:frm.doc.company},
+ method:"erpnext.setup.doctype.company.company.get_default_company_address",
+ args:{name:frm.doc.company, existing_address: frm.doc.company_address},
callback: function(r){
if (r.message){
frm.set_value("company_address",r.message)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index c4d64a72fd..0f4d4451be 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -535,10 +535,8 @@ class SalesInvoice(SellingController):
for i in dic:
if frappe.db.get_single_value('Selling Settings', dic[i][0]) == 'Yes':
for d in self.get('items'):
- is_stock_item = frappe.get_cached_value('Item', d.item_code, 'is_stock_item')
- if (d.item_code and is_stock_item == 1\
- and not d.get(i.lower().replace(' ','_')) and not self.get(dic[i][1])):
- msgprint(_("{0} is mandatory for Stock Item {1}").format(i,d.item_code), raise_exception=1)
+ if (d.item_code and not d.get(i.lower().replace(' ','_')) and not self.get(dic[i][1])):
+ msgprint(_("{0} is mandatory for Item {1}").format(i,d.item_code), raise_exception=1)
def validate_proj_cust(self):
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json
index 29e15d165f..19781bdffa 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json
@@ -1,299 +1,119 @@
{
- "allow_copy": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:title",
- "beta": 0,
- "creation": "2013-01-10 16:34:09",
- "custom": 0,
- "description": "Standard tax template that can be applied to all Sales Transactions. This template can contain list of tax heads and also other expense / income heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "creation": "2013-01-10 16:34:09",
+ "description": "Standard tax template that can be applied to all Sales Transactions. This template can contain list of tax heads and also other expense / income heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "title",
+ "is_default",
+ "disabled",
+ "column_break_3",
+ "company",
+ "tax_category",
+ "section_break_5",
+ "taxes"
+ ],
"fields": [
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "title",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Title",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "title",
- "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,
- "unique": 0
- },
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "label": "Title",
+ "no_copy": 1,
+ "oldfieldname": "title",
+ "oldfieldtype": "Data",
+ "reqd": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "is_default",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Default",
- "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,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "is_default",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Default"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "disabled",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Disabled",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "label": "Disabled"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_3",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "company",
- "oldfieldtype": "Link",
- "options": "Company",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Company",
+ "oldfieldname": "company",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_5",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "* Will be calculated in the transaction.",
- "fieldname": "taxes",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Sales Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "other_charges",
- "oldfieldtype": "Table",
- "options": "Sales Taxes and Charges",
- "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,
- "unique": 0
+ "description": "* Will be calculated in the transaction.",
+ "fieldname": "taxes",
+ "fieldtype": "Table",
+ "label": "Sales Taxes and Charges",
+ "oldfieldname": "other_charges",
+ "oldfieldtype": "Table",
+ "options": "Sales Taxes and Charges"
+ },
+ {
+ "fieldname": "tax_category",
+ "fieldtype": "Link",
+ "label": "Tax Category",
+ "options": "Tax Category"
}
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-money",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
-
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2016-11-07 05:18:41.743257",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Sales Taxes and Charges Template",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-money",
+ "idx": 1,
+ "modified": "2019-11-25 13:06:03.279099",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Sales Taxes and Charges Template",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "apply_user_permissions": 1,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Sales User"
+ },
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales Master Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Sales Master Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "sort_order": "ASC",
- "track_seen": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 59936d5116..156f2181b8 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -23,7 +23,7 @@ class DuplicatePartyAccountError(frappe.ValidationError): pass
@frappe.whitelist()
def get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False, fetch_payment_terms_template=True,
- party_address=None, shipping_address=None, pos_profile=None):
+ party_address=None, company_address=None, shipping_address=None, pos_profile=None):
if not party:
return {}
@@ -31,14 +31,14 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
return _get_party_details(party, account, party_type,
company, posting_date, bill_date, price_list, currency, doctype, ignore_permissions,
- fetch_payment_terms_template, party_address, shipping_address, pos_profile)
+ fetch_payment_terms_template, party_address, company_address, shipping_address, pos_profile)
def _get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False,
- fetch_payment_terms_template=True, party_address=None, shipping_address=None, pos_profile=None):
+ fetch_payment_terms_template=True, party_address=None, company_address=None,shipping_address=None, pos_profile=None):
- out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype))
- party = out[party_type.lower()]
+ party_details = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype))
+ party = party_details[party_type.lower()]
if not ignore_permissions and not frappe.has_permission(party_type, "read", party):
frappe.throw(_("Not permitted for {0}").format(party), frappe.PermissionError)
@@ -46,76 +46,81 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
party = frappe.get_doc(party_type, party)
currency = party.default_currency if party.get("default_currency") else get_company_currency(company)
- party_address, shipping_address = set_address_details(out, party, party_type, doctype, company, party_address, shipping_address)
- set_contact_details(out, party, party_type)
- set_other_values(out, party, party_type)
- set_price_list(out, party, party_type, price_list, pos_profile)
+ party_address, shipping_address = set_address_details(party_details, party, party_type, doctype, company, party_address, company_address, shipping_address)
+ set_contact_details(party_details, party, party_type)
+ set_other_values(party_details, party, party_type)
+ set_price_list(party_details, party, party_type, price_list, pos_profile)
- out["tax_category"] = get_address_tax_category(party.get("tax_category"),
+ party_details["tax_category"] = get_address_tax_category(party.get("tax_category"),
party_address, shipping_address if party_type != "Supplier" else party_address)
- out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company,
- customer_group=out.customer_group, supplier_group=out.supplier_group, tax_category=out.tax_category,
- billing_address=party_address, shipping_address=shipping_address)
+
+ if not party_details.get("taxes_and_charges"):
+ party_details["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company,
+ customer_group=party_details.customer_group, supplier_group=party_details.supplier_group, tax_category=party_details.tax_category,
+ billing_address=party_address, shipping_address=shipping_address)
if fetch_payment_terms_template:
- out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
+ party_details["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
- if not out.get("currency"):
- out["currency"] = currency
+ if not party_details.get("currency"):
+ party_details["currency"] = currency
# sales team
if party_type=="Customer":
- out["sales_team"] = [{
+ party_details["sales_team"] = [{
"sales_person": d.sales_person,
"allocated_percentage": d.allocated_percentage or None
} for d in party.get("sales_team")]
# supplier tax withholding category
if party_type == "Supplier" and party:
- out["supplier_tds"] = frappe.get_value(party_type, party.name, "tax_withholding_category")
+ party_details["supplier_tds"] = frappe.get_value(party_type, party.name, "tax_withholding_category")
- return out
+ return party_details
-def set_address_details(out, party, party_type, doctype=None, company=None, party_address=None, shipping_address=None):
+def set_address_details(party_details, party, party_type, doctype=None, company=None, party_address=None, company_address=None, shipping_address=None):
billing_address_field = "customer_address" if party_type == "Lead" \
else party_type.lower() + "_address"
- out[billing_address_field] = party_address or get_default_address(party_type, party.name)
+ party_details[billing_address_field] = party_address or get_default_address(party_type, party.name)
if doctype:
- out.update(get_fetch_values(doctype, billing_address_field, out[billing_address_field]))
+ party_details.update(get_fetch_values(doctype, billing_address_field, party_details[billing_address_field]))
# address display
- out.address_display = get_address_display(out[billing_address_field])
+ party_details.address_display = get_address_display(party_details[billing_address_field])
# shipping address
if party_type in ["Customer", "Lead"]:
- out.shipping_address_name = shipping_address or get_party_shipping_address(party_type, party.name)
- out.shipping_address = get_address_display(out["shipping_address_name"])
+ party_details.shipping_address_name = shipping_address or get_party_shipping_address(party_type, party.name)
+ party_details.shipping_address = get_address_display(party_details["shipping_address_name"])
if doctype:
- out.update(get_fetch_values(doctype, 'shipping_address_name', out.shipping_address_name))
+ party_details.update(get_fetch_values(doctype, 'shipping_address_name', party_details.shipping_address_name))
- if doctype and doctype in ['Delivery Note', 'Sales Invoice']:
- out.update(get_company_address(company))
- if out.company_address:
- out.update(get_fetch_values(doctype, 'company_address', out.company_address))
- get_regional_address_details(out, doctype, company)
+ if company_address:
+ party_details.update({'company_address': company_address})
+ else:
+ party_details.update(get_company_address(company))
- elif doctype and doctype == "Purchase Invoice":
- out.update(get_company_address(company))
- if out.company_address:
- out["shipping_address"] = shipping_address or out["company_address"]
- out.shipping_address_display = get_address_display(out["shipping_address"])
- out.update(get_fetch_values(doctype, 'shipping_address', out.shipping_address))
- get_regional_address_details(out, doctype, company)
+ if doctype and doctype in ['Delivery Note', 'Sales Invoice', 'Sales Order']:
+ if party_details.company_address:
+ party_details.update(get_fetch_values(doctype, 'company_address', party_details.company_address))
+ get_regional_address_details(party_details, doctype, company)
- return out.get(billing_address_field), out.shipping_address_name
+ elif doctype and doctype in ["Purchase Invoice", "Purchase Order", "Purchase Receipt"]:
+ if party_details.company_address:
+ party_details["shipping_address"] = shipping_address or party_details["company_address"]
+ party_details.shipping_address_display = get_address_display(party_details["shipping_address"])
+ party_details.update(get_fetch_values(doctype, 'shipping_address', party_details.shipping_address))
+ get_regional_address_details(party_details, doctype, company)
+
+ return party_details.get(billing_address_field), party_details.shipping_address_name
@erpnext.allow_regional
-def get_regional_address_details(out, doctype, company):
+def get_regional_address_details(party_details, doctype, company):
pass
-def set_contact_details(out, party, party_type):
- out.contact_person = get_default_contact(party_type, party.name)
+def set_contact_details(party_details, party, party_type):
+ party_details.contact_person = get_default_contact(party_type, party.name)
- if not out.contact_person:
- out.update({
+ if not party_details.contact_person:
+ party_details.update({
"contact_person": None,
"contact_display": None,
"contact_email": None,
@@ -125,22 +130,22 @@ def set_contact_details(out, party, party_type):
"contact_department": None
})
else:
- out.update(get_contact_details(out.contact_person))
+ party_details.update(get_contact_details(party_details.contact_person))
-def set_other_values(out, party, party_type):
+def set_other_values(party_details, party, party_type):
# copy
if party_type=="Customer":
to_copy = ["customer_name", "customer_group", "territory", "language"]
else:
to_copy = ["supplier_name", "supplier_group", "language"]
for f in to_copy:
- out[f] = party.get(f)
+ party_details[f] = party.get(f)
# fields prepended with default in Customer doctype
for f in ['currency'] \
+ (['sales_partner', 'commission_rate'] if party_type=="Customer" else []):
if party.get("default_" + f):
- out[f] = party.get("default_" + f)
+ party_details[f] = party.get("default_" + f)
def get_default_price_list(party):
"""Return default price list for party (Document object)"""
@@ -155,7 +160,7 @@ def get_default_price_list(party):
return None
-def set_price_list(out, party, party_type, given_price_list, pos=None):
+def set_price_list(party_details, party, party_type, given_price_list, pos=None):
# price list
price_list = get_permitted_documents('Price List')
@@ -173,9 +178,9 @@ def set_price_list(out, party, party_type, given_price_list, pos=None):
price_list = get_default_price_list(party) or given_price_list
if price_list:
- out.price_list_currency = frappe.db.get_value("Price List", price_list, "currency", cache=True)
+ party_details.price_list_currency = frappe.db.get_value("Price List", price_list, "currency", cache=True)
- out["selling_price_list" if party.doctype=="Customer" else "buying_price_list"] = price_list
+ party_details["selling_price_list" if party.doctype=="Customer" else "buying_price_list"] = price_list
def set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype):
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index d32f834f0f..3e7f6833a0 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -610,13 +610,19 @@ def get_asset_account(account_name, asset=None, asset_category=None, company=Non
if asset:
account = get_asset_category_account(account_name, asset=asset,
asset_category = asset_category, company = company)
+
+ if not asset and not account:
+ account = get_asset_category_account(account_name, asset_category = asset_category, company = company)
if not account:
account = frappe.get_cached_value('Company', company, account_name)
if not account:
- frappe.throw(_("Set {0} in asset category {1} or company {2}")
- .format(account_name.replace('_', ' ').title(), asset_category, company))
+ if not asset_category:
+ frappe.throw(_("Set {0} in company {2}").format(account_name.replace('_', ' ').title(), company))
+ else:
+ frappe.throw(_("Set {0} in asset category {1} or company {2}")
+ .format(account_name.replace('_', ' ').title(), asset_category, company))
return account
diff --git a/erpnext/buying/doctype/purchase_order/regional/india.js b/erpnext/buying/doctype/purchase_order/regional/india.js
new file mode 100644
index 0000000000..42d3995907
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/regional/india.js
@@ -0,0 +1,3 @@
+{% include "erpnext/regional/india/taxes.js" %}
+
+erpnext.setup_auto_gst_taxation('Purchase Order');
\ No newline at end of file
diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py
index 2affba2ac4..b6c4c4707d 100644
--- a/erpnext/crm/doctype/appointment/appointment.py
+++ b/erpnext/crm/doctype/appointment/appointment.py
@@ -171,7 +171,7 @@ class Appointment(Document):
self.save(ignore_permissions=True)
def _get_verify_url(self):
- verify_route = '/book-appointment/verify'
+ verify_route = '/book_appointment/verify'
params = {
'email': self.customer_email,
'appointment': self.name
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index ed5bf9b5d8..2a5e6d8f49 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -246,10 +246,10 @@ doc_events = {
"on_trash": "erpnext.regional.check_deletion_permission"
},
'Address': {
- 'validate': ['erpnext.regional.india.utils.validate_gstin_for_india', 'erpnext.regional.italy.utils.set_state_code']
+ 'validate': ['erpnext.regional.india.utils.validate_gstin_for_india', 'erpnext.regional.italy.utils.set_state_code', 'erpnext.regional.india.utils.update_gst_category']
},
- ('Sales Invoice', 'Purchase Invoice', 'Delivery Note'): {
- 'validate': 'erpnext.regional.india.utils.set_place_of_supply'
+ ('Sales Invoice', 'Sales Order', 'Delivery Note', 'Purchase Invoice', 'Purchase Order', 'Purchase Receipt'): {
+ 'validate': ['erpnext.regional.india.utils.set_place_of_supply']
},
"Contact": {
"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 0d37c10e9c..570f2ef4c7 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -42,12 +42,6 @@ cur_frm.cscript.onload = function(doc) {
cur_frm.set_value("posting_date", frappe.datetime.get_today());
cur_frm.cscript.clear_sanctioned(doc);
}
-
- cur_frm.fields_dict.employee.get_query = function() {
- return {
- query: "erpnext.controllers.queries.employee_query"
- };
- };
};
cur_frm.cscript.clear_sanctioned = function(doc) {
@@ -119,7 +113,7 @@ cur_frm.cscript.calculate_total_amount = function(doc,cdt,cdn){
};
erpnext.expense_claim = {
- set_title :function(frm) {
+ set_title: function(frm) {
if (!frm.doc.task) {
frm.set_value("title", frm.doc.employee_name);
}
@@ -131,20 +125,20 @@ erpnext.expense_claim = {
frappe.ui.form.on("Expense Claim", {
setup: function(frm) {
- frm.trigger("set_query_for_cost_center");
- frm.trigger("set_query_for_payable_account");
frm.add_fetch("company", "cost_center", "cost_center");
frm.add_fetch("company", "default_expense_claim_payable_account", "payable_account");
- frm.set_query("employee_advance", "advances", function(doc) {
+
+ frm.set_query("employee_advance", "advances", function() {
return {
filters: [
['docstatus', '=', 1],
- ['employee', '=', doc.employee],
+ ['employee', '=', frm.doc.employee],
['paid_amount', '>', 0],
['paid_amount', '>', 'claimed_amount']
]
};
});
+
frm.set_query("expense_approver", function() {
return {
query: "erpnext.hr.doctype.department_approver.department_approver.get_approvers",
@@ -154,14 +148,49 @@ frappe.ui.form.on("Expense Claim", {
}
};
});
- frm.set_query("account_head", "taxes", function(doc) {
+
+ frm.set_query("account_head", "taxes", function() {
return {
filters: [
- ['company', '=', doc.company],
+ ['company', '=', frm.doc.company],
['account_type', 'in', ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation"]]
]
};
});
+
+ frm.set_query("cost_center", "expenses", function() {
+ return {
+ filters: {
+ "company": frm.doc.company,
+ "is_group": 0
+ }
+ };
+ });
+
+ frm.set_query("payable_account", function() {
+ return {
+ filters: {
+ "report_type": "Balance Sheet",
+ "account_type": "Payable",
+ "company": frm.doc.company,
+ "is_group": 0
+ }
+ };
+ });
+
+ frm.set_query("task", function() {
+ return {
+ filters: {
+ 'project': frm.doc.project
+ }
+ };
+ });
+
+ frm.set_query("employee", function() {
+ return {
+ query: "erpnext.controllers.queries.employee_query"
+ };
+ });
},
onload: function(frm) {
@@ -244,30 +273,6 @@ frappe.ui.form.on("Expense Claim", {
});
},
- set_query_for_cost_center: function(frm) {
- frm.fields_dict["cost_center"].get_query = function() {
- return {
- filters: {
- "company": frm.doc.company,
- "is_group": 0
- }
- };
- };
- },
-
- set_query_for_payable_account: function(frm) {
- frm.fields_dict["payable_account"].get_query = function() {
- return {
- filters: {
- "report_type": "Balance Sheet",
- "account_type": "Payable",
- "company": frm.doc.company,
- "is_group": 0
- }
- };
- };
- },
-
is_paid: function(frm) {
frm.trigger("toggle_fields");
},
@@ -329,6 +334,10 @@ frappe.ui.form.on("Expense Claim", {
});
frappe.ui.form.on("Expense Claim Detail", {
+ expenses_add: function(frm, cdt, cdn) {
+ var row = frappe.get_doc(cdt, cdn);
+ frm.script_manager.copy_from_first_row("expenses", row, ["cost_center"]);
+ },
amount: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
var doc = frm.doc;
@@ -341,6 +350,9 @@ frappe.ui.form.on("Expense Claim Detail", {
cur_frm.cscript.calculate_total(doc,cdt,cdn);
frm.trigger("get_taxes");
frm.trigger("calculate_grand_total");
+ },
+ cost_center: function(frm, cdt, cdn) {
+ erpnext.utils.copy_value_in_all_rows(frm.doc, cdt, cdn, "expenses", "cost_center");
}
});
@@ -411,12 +423,4 @@ frappe.ui.form.on("Expense Taxes and Charges", {
tax_amount: function(frm, cdt, cdn) {
frm.trigger("calculate_total_tax", cdt, cdn);
}
-});
-
-cur_frm.fields_dict['task'].get_query = function(doc) {
- return {
- filters:{
- 'project': doc.project
- }
- };
-};
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json
index 5c2f490171..b5b6823e1c 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.json
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.json
@@ -43,7 +43,6 @@
"accounting_dimensions_section",
"project",
"dimension_col_break",
- "cost_center",
"more_details",
"status",
"amended_from",
@@ -366,7 +365,7 @@
"icon": "fa fa-money",
"idx": 1,
"is_submittable": 1,
- "modified": "2019-11-08 14:13:08.964547",
+ "modified": "2019-11-09 14:13:08.964547",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim",
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index 59391505fa..dfb0bb96d8 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -127,7 +127,7 @@ class ExpenseClaim(AccountsController):
"debit": data.sanctioned_amount,
"debit_in_account_currency": data.sanctioned_amount,
"against": self.employee,
- "cost_center": self.cost_center
+ "cost_center": data.cost_center
})
)
@@ -190,8 +190,9 @@ class ExpenseClaim(AccountsController):
)
def validate_account_details(self):
- if not self.cost_center:
- frappe.throw(_("Cost center is required to book an expense claim"))
+ for data in self.expenses:
+ if not data.cost_center:
+ frappe.throw(_("Cost center is required to book an expense claim"))
if self.is_paid:
if not self.mode_of_payment:
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
index b559dfd81d..6e97f0513d 100644
--- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
@@ -126,7 +126,7 @@ def generate_taxes():
def make_expense_claim(payable_account, amount, sanctioned_amount, company, account, project=None, task_name=None, do_not_submit=False, taxes=None):
employee = frappe.db.get_value("Employee", {"status": "Active"})
- currency = frappe.db.get_value('Company', company, 'default_currency')
+ currency, cost_center = frappe.db.get_value('Company', company, ['default_currency', 'cost_center'])
expense_claim = {
"doctype": "Expense Claim",
"employee": employee,
@@ -134,12 +134,15 @@ def make_expense_claim(payable_account, amount, sanctioned_amount, company, acco
"approval_status": "Approved",
"company": company,
'currency': currency,
- "expenses":
- [{"expense_type": "Travel",
+ "expenses": [{
+ "expense_type": "Travel",
"default_account": account,
- 'currency': currency,
+ "currency": currency,
"amount": amount,
- "sanctioned_amount": sanctioned_amount}]}
+ "sanctioned_amount": sanctioned_amount,
+ "cost_center": cost_center
+ }]
+ }
if taxes:
expense_claim.update(taxes)
diff --git a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json
index b23fb6af0f..b60db2c3af 100644
--- a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json
+++ b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json
@@ -1,378 +1,118 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
"creation": "2013-02-22 01:27:46",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "expense_date",
+ "column_break_2",
+ "expense_type",
+ "default_account",
+ "section_break_4",
+ "description",
+ "section_break_6",
+ "amount",
+ "column_break_8",
+ "sanctioned_amount",
+ "cost_center"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "expense_date",
"fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Expense Date",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "expense_date",
"oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"print_width": "150px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
"width": "150px"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "expense_type",
"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": "Expense Claim Type",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "expense_type",
"oldfieldtype": "Link",
"options": "Expense Claim Type",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"print_width": "150px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
"width": "150px"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "expense_type",
"fieldname": "default_account",
"fieldtype": "Link",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Default Account",
- "length": 0,
- "no_copy": 0,
"options": "Account",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "section_break_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
+ "fieldtype": "Section Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "",
"fieldname": "description",
"fieldtype": "Text Editor",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Description",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Small Text",
- "options": "",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"print_width": "300px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
"width": "300px"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "section_break_6",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldtype": "Section Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "amount",
"fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Amount",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "claim_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"print_width": "150px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
"width": "150px"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_8",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "sanctioned_amount",
"fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Sanctioned Amount",
- "length": 0,
"no_copy": 1,
"oldfieldname": "sanctioned_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"print_width": "150px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
"width": "150px"
+ },
+ {
+ "fieldname": "cost_center",
+ "fieldtype": "Link",
+ "label": "Cost Center",
+ "options": "Cost Center"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
"idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
"istable": 1,
- "max_attachments": 0,
- "modified": "2019-06-10 08:41:36.122565",
- "modified_by": "Administrator",
+ "modified": "2019-11-22 11:57:25.110942",
+ "modified_by": "jangeles@bai.ph",
"module": "HR",
"name": "Expense Claim Detail",
"owner": "harshada@webnotestech.com",
"permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
"sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/expense_claim_type/expense_claim_type.js b/erpnext/hr/doctype/expense_claim_type/expense_claim_type.js
index fda6809e6b..c487797677 100644
--- a/erpnext/hr/doctype/expense_claim_type/expense_claim_type.js
+++ b/erpnext/hr/doctype/expense_claim_type/expense_claim_type.js
@@ -8,7 +8,7 @@ frappe.ui.form.on("Expense Claim Type", {
return{
filters: {
"is_group": 0,
- "root_type": "Expense",
+ "root_type": frm.doc.deferred_expense_account ? "Asset" : "Expense",
'company': d.company
}
}
diff --git a/erpnext/hr/doctype/expense_claim_type/expense_claim_type.json b/erpnext/hr/doctype/expense_claim_type/expense_claim_type.json
index d0c41221cc..e45f640c07 100644
--- a/erpnext/hr/doctype/expense_claim_type/expense_claim_type.json
+++ b/erpnext/hr/doctype/expense_claim_type/expense_claim_type.json
@@ -1,181 +1,72 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:expense_type",
- "beta": 0,
- "creation": "2012-03-27 14:35:55",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:expense_type",
+ "creation": "2012-03-27 14:35:55",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "deferred_expense_account",
+ "expense_type",
+ "description",
+ "accounts"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "expense_type",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Expense Claim Type",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "expense_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,
+ "fieldname": "expense_type",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Expense Claim Type",
+ "oldfieldname": "expense_type",
+ "oldfieldtype": "Data",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "description",
- "oldfieldtype": "Small Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description",
+ "oldfieldname": "description",
+ "oldfieldtype": "Small Text",
"width": "300px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "accounts",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Accounts",
- "length": 0,
- "no_copy": 0,
- "options": "Expense Claim Account",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "accounts",
+ "fieldtype": "Table",
+ "label": "Accounts",
+ "options": "Expense Claim Account"
+ },
+ {
+ "default": "0",
+ "fieldname": "deferred_expense_account",
+ "fieldtype": "Check",
+ "label": "Deferred Expense Account"
}
- ],
- "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-09-18 14:13:43.770829",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Expense Claim Type",
- "owner": "harshada@webnotestech.com",
+ ],
+ "icon": "fa fa-flag",
+ "idx": 1,
+ "modified": "2019-11-22 12:00:18.710408",
+ "modified_by": "jangeles@bai.ph",
+ "module": "HR",
+ "name": "Expense Claim Type",
+ "owner": "harshada@webnotestech.com",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Employee",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "read": 1,
+ "role": "Employee"
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_order": "ASC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC"
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js
index e32d57011d..14ffa0ed1f 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.js
+++ b/erpnext/hr/doctype/leave_application/leave_application.js
@@ -60,6 +60,7 @@ frappe.ui.form.on("Leave Application", {
}
}
});
+ $("div").remove(".form-dashboard-section.custom");
frm.dashboard.add_section(
frappe.render_template('leave_application_dashboard', {
data: leave_details
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 65fcbf7a99..915cea149d 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -351,7 +351,7 @@ class LeaveApplication(Document):
pass
def create_leave_ledger_entry(self, submit=True):
- if self.status != 'Approved':
+ if self.status != 'Approved' and submit:
return
expiry_date = get_allocation_expiry(self.employee, self.leave_type,
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index daedca7a28..e26b1c88a8 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -645,6 +645,9 @@ erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings
erpnext.patches.v12_0.set_payment_entry_status
erpnext.patches.v12_0.update_owner_fields_in_acc_dimension_custom_fields
erpnext.patches.v12_0.set_default_for_add_taxes_from_item_tax_template
+erpnext.patches.v12_0.add_export_type_field_in_party_master
erpnext.patches.v12_0.remove_denied_leaves_from_leave_ledger
erpnext.patches.v12_0.update_price_or_product_discount
-erpnext.patches.v12_0.set_production_capacity_in_workstation
\ No newline at end of file
+erpnext.patches.v12_0.set_production_capacity_in_workstation
+erpnext.patches.v12_0.set_against_blanket_order_in_sales_and_purchase_order
+erpnext.patches.v12_0.set_cost_center_in_child_table_of_expense_claim
diff --git a/erpnext/patches/v12_0/add_export_type_field_in_party_master.py b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py
new file mode 100644
index 0000000000..c565b7ecd8
--- /dev/null
+++ b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py
@@ -0,0 +1,40 @@
+from __future__ import unicode_literals
+import frappe
+from erpnext.regional.india.setup import make_custom_fields
+
+def execute():
+
+ company = frappe.get_all('Company', filters = {'country': 'India'})
+ if not company:
+ return
+
+ make_custom_fields()
+
+ frappe.reload_doctype('Tax Category')
+ frappe.reload_doctype('Sales Taxes and Charges Template')
+ frappe.reload_doctype('Purchase Taxes and Charges Template')
+
+ # Create tax category with inter state field checked
+ tax_category = frappe.db.get_value('Tax Category', {'name': 'OUT OF STATE'}, 'name')
+
+ if not tax_category:
+ inter_state_category = frappe.get_doc({
+ 'doctype': 'Tax Category',
+ 'title': 'OUT OF STATE',
+ 'is_inter_state': 1
+ }).insert()
+
+ tax_category = inter_state_category.name
+
+ for doctype in ('Sales Taxes and Charges Template', 'Purchase Taxes and Charges Template'):
+ template = frappe.db.get_value(doctype, {'is_inter_state': 1, 'disabled': 0}, ['name'])
+ if template:
+ frappe.db.set_value(doctype, template, 'tax_category', tax_category)
+
+ frappe.db.sql("""
+ DELETE FROM `tabCustom Field`
+ WHERE fieldname = 'is_inter_state'
+ AND dt IN ('Sales Taxes and Charges Template', 'Purchase Taxes and Charges Template')
+ """)
+
+
diff --git a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
new file mode 100644
index 0000000000..555d8ae797
--- /dev/null
+++ b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
@@ -0,0 +1,9 @@
+import frappe
+def execute():
+ for doctype in ['Sales Order Item', 'Purchase Order Item']:
+ frappe.reload_doctype(doctype)
+ frappe.db.sql("""
+ UPDATE `tab{0}`
+ SET against_blanket_order = 1
+ WHERE ifnull(blanket_order, '') != ''
+ """.format(doctype))
diff --git a/erpnext/patches/v12_0/set_cost_center_in_child_table_of_expense_claim.py b/erpnext/patches/v12_0/set_cost_center_in_child_table_of_expense_claim.py
new file mode 100644
index 0000000000..8ba0d79a83
--- /dev/null
+++ b/erpnext/patches/v12_0/set_cost_center_in_child_table_of_expense_claim.py
@@ -0,0 +1,8 @@
+import frappe
+def execute():
+ frappe.reload_doc('hr', 'doctype', 'expense_claim_detail')
+ frappe.db.sql("""
+ UPDATE `tabExpense Claim Detail` child, `tabExpense Claim` par
+ SET child.cost_center = par.cost_center
+ WHERE child.parent = par.name
+ """)
\ No newline at end of file
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 63e057c39d..dead309a5d 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -4,7 +4,7 @@ erpnext.financial_statements = {
"filters": get_filters(),
"formatter": function(value, row, column, data, default_formatter) {
if (column.fieldname=="account") {
- value = data.account_name;
+ value = data.account_name || value;
column.link_onclick =
"erpnext.financial_statements.open_general_ledger(" + JSON.stringify(data) + ")";
diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js
index 84d2113c06..560a5617da 100644
--- a/erpnext/public/js/queries.js
+++ b/erpnext/public/js/queries.js
@@ -65,7 +65,7 @@ $.extend(erpnext.queries, {
frappe.throw(__("Please set {0}",
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
}
- console.log(frappe.dynamic_link)
+
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: {
diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js
index a8d3888ba0..99c1b8ae8f 100644
--- a/erpnext/public/js/utils/party.js
+++ b/erpnext/public/js/utils/party.js
@@ -7,6 +7,21 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
if(!method) {
method = "erpnext.accounts.party.get_party_details";
}
+
+ if (args) {
+ if (in_list(['Sales Invoice', 'Sales Order', 'Delivery Note'], frm.doc.doctype)) {
+ if (frm.doc.company_address && (!args.company_address)) {
+ args.company_address = frm.doc.company_address;
+ }
+ }
+
+ if (in_list(['Purchase Invoice', 'Purchase Order', 'Purchase Receipt'], frm.doc.doctype)) {
+ if (frm.doc.shipping_address && (!args.shipping_address)) {
+ args.shipping_address = frm.doc.shipping_address;
+ }
+ }
+ }
+
if(!args) {
if((frm.doctype != "Purchase Order" && frm.doc.customer)
|| (frm.doc.party_name && in_list(['Quotation', 'Opportunity'], frm.doc.doctype))) {
@@ -30,6 +45,35 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
};
}
+ if (in_list(['Sales Invoice', 'Sales Order', 'Delivery Note'], frm.doc.doctype)) {
+ if (!args) {
+ args = {
+ party: frm.doc.customer || frm.doc.party_name,
+ party_type: 'Customer'
+ }
+ }
+ if (frm.doc.company_address && (!args.company_address)) {
+ args.company_address = frm.doc.company_address;
+ }
+
+ if (frm.doc.shipping_address_name &&(!args.shipping_address_name)) {
+ args.shipping_address_name = frm.doc.shipping_address_name;
+ }
+ }
+
+ if (in_list(['Purchase Invoice', 'Purchase Order', 'Purchase Receipt'], frm.doc.doctype)) {
+ if (!args) {
+ args = {
+ party: frm.doc.supplier,
+ party_type: 'Supplier'
+ }
+ }
+
+ if (frm.doc.shipping_address && (!args.shipping_address)) {
+ args.shipping_address = frm.doc.shipping_address;
+ }
+ }
+
if (args) {
args.posting_date = frm.doc.posting_date || frm.doc.transaction_date;
}
diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py
index fef73d9a0a..fa6fb706e9 100644
--- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py
@@ -64,7 +64,8 @@ class TestGSTR3BReport(unittest.TestCase):
self.assertEqual(output["inter_sup"]["unreg_details"][0]["iamt"], 18),
self.assertEqual(output["sup_details"]["osup_nil_exmp"]["txval"], 100),
self.assertEqual(output["inward_sup"]["isup_details"][0]["inter"], 250)
- self.assertEqual(output["itc_elg"]["itc_avl"][4]["iamt"], 45)
+ self.assertEqual(output["itc_elg"]["itc_avl"][4]["samt"], 22.50)
+ self.assertEqual(output["itc_elg"]["itc_avl"][4]["camt"], 22.50)
def make_sales_invoice():
si = create_sales_invoice(company="_Test Company GST",
@@ -158,10 +159,18 @@ def create_purchase_invoices():
pi.append("taxes", {
"charge_type": "On Net Total",
- "account_head": "IGST - _GST",
+ "account_head": "CGST - _GST",
"cost_center": "Main - _GST",
- "description": "IGST @ 18.0",
- "rate": 18
+ "description": "CGST @ 9.0",
+ "rate": 9
+ })
+
+ pi.append("taxes", {
+ "charge_type": "On Net Total",
+ "account_head": "SGST - _GST",
+ "cost_center": "Main - _GST",
+ "description": "SGST @ 9.0",
+ "rate": 9
})
pi.submit()
diff --git a/erpnext/regional/germany/address_template.html b/erpnext/regional/germany/address_template.html
index 0df786713c..7fa4c32612 100644
--- a/erpnext/regional/germany/address_template.html
+++ b/erpnext/regional/germany/address_template.html
@@ -1,8 +1,8 @@
{{ address_line1 }}
{% if address_line2 %}{{ address_line2 }}
{% endif -%}
-{{ pincode }} {{ city }}
-{% if country %}{{ country }}
{% endif -%}
-
-{% if phone %}Tel: {{ phone }}
{% endif -%}
-{% if fax %}Fax: {{ fax }}
{% endif -%}
-{% if email_id %}E-Mail: {{ email_id }}
{% endif -%}
+{% if country in ["Germany", "Deutschland"] %}
+ {{ pincode }} {{ city }}
+{% else %}
+ {{ pincode }} {{ city | upper }}
+ {{ country | upper }}
+{% endif %}
diff --git a/erpnext/regional/india/__init__.py b/erpnext/regional/india/__init__.py
index 46c874b252..0ed98b74ee 100644
--- a/erpnext/regional/india/__init__.py
+++ b/erpnext/regional/india/__init__.py
@@ -1,4 +1,5 @@
from __future__ import unicode_literals
+from six import iteritems
states = [
'',
@@ -79,4 +80,6 @@ state_numbers = {
"Uttar Pradesh": "09",
"Uttarakhand": "05",
"West Bengal": "19",
-}
\ No newline at end of file
+}
+
+number_state_mapping = {v: k for k, v in iteritems(state_numbers)}
\ No newline at end of file
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 756c17dc3b..14fdba013c 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -107,7 +107,12 @@ def make_custom_fields(update=True):
dict(fieldname='gst_category', label='GST Category',
fieldtype='Select', insert_after='gst_section', print_hide=1,
options='\nRegistered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nUIN Holders',
- fetch_from='supplier.gst_category', fetch_if_empty=1)
+ fetch_from='supplier.gst_category', fetch_if_empty=1),
+ dict(fieldname='export_type', label='Export Type',
+ fieldtype='Select', insert_after='gst_category', print_hide=1,
+ depends_on='eval:in_list(["SEZ", "Overseas"], doc.gst_category)',
+ options='\nWith Payment of Tax\nWithout Payment of Tax', fetch_from='supplier.export_type',
+ fetch_if_empty=1),
]
sales_invoice_gst_category = [
@@ -116,20 +121,21 @@ def make_custom_fields(update=True):
dict(fieldname='gst_category', label='GST Category',
fieldtype='Select', insert_after='gst_section', print_hide=1,
options='\nRegistered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders',
- fetch_from='customer.gst_category', fetch_if_empty=1)
+ fetch_from='customer.gst_category', fetch_if_empty=1),
+ dict(fieldname='export_type', label='Export Type',
+ fieldtype='Select', insert_after='gst_category', print_hide=1,
+ depends_on='eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)',
+ options='\nWith Payment of Tax\nWithout Payment of Tax', fetch_from='customer.export_type',
+ fetch_if_empty=1),
]
invoice_gst_fields = [
dict(fieldname='invoice_copy', label='Invoice Copy',
- fieldtype='Select', insert_after='gst_category', print_hide=1, allow_on_submit=1,
+ fieldtype='Select', insert_after='export_type', print_hide=1, allow_on_submit=1,
options='Original for Recipient\nDuplicate for Transporter\nDuplicate for Supplier\nTriplicate for Supplier'),
dict(fieldname='reverse_charge', label='Reverse Charge',
fieldtype='Select', insert_after='invoice_copy', print_hide=1,
options='Y\nN', default='N'),
- dict(fieldname='export_type', label='Export Type',
- fieldtype='Select', insert_after='reverse_charge', print_hide=1,
- depends_on='eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)',
- options='\nWith Payment of Tax\nWithout Payment of Tax'),
dict(fieldname='ecommerce_gstin', label='E-commerce GSTIN',
fieldtype='Data', insert_after='export_type', print_hide=1),
dict(fieldname='gst_col_break', fieldtype='Column Break', insert_after='ecommerce_gstin'),
@@ -142,13 +148,13 @@ def make_custom_fields(update=True):
purchase_invoice_gst_fields = [
dict(fieldname='supplier_gstin', label='Supplier GSTIN',
fieldtype='Data', insert_after='supplier_address',
- fetch_from='supplier_address.gstin', print_hide=1),
+ fetch_from='supplier_address.gstin', print_hide=1, read_only=1),
dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='shipping_address_display',
- fetch_from='shipping_address.gstin', print_hide=1),
+ fetch_from='shipping_address.gstin', print_hide=1, read_only=1),
dict(fieldname='place_of_supply', label='Place of Supply',
fieldtype='Data', insert_after='shipping_address',
- print_hide=1, read_only=0),
+ print_hide=1, read_only=1),
]
purchase_invoice_itc_fields = [
@@ -167,17 +173,17 @@ def make_custom_fields(update=True):
sales_invoice_gst_fields = [
dict(fieldname='billing_address_gstin', label='Billing Address GSTIN',
- fieldtype='Data', insert_after='customer_address',
+ fieldtype='Data', insert_after='customer_address', read_only=1,
fetch_from='customer_address.gstin', print_hide=1),
dict(fieldname='customer_gstin', label='Customer GSTIN',
fieldtype='Data', insert_after='shipping_address_name',
fetch_from='shipping_address_name.gstin', print_hide=1),
dict(fieldname='place_of_supply', label='Place of Supply',
fieldtype='Data', insert_after='customer_gstin',
- print_hide=1, read_only=0),
+ print_hide=1, read_only=1),
dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='company_address',
- fetch_from='company_address.gstin', print_hide=1),
+ fetch_from='company_address.gstin', print_hide=1, read_only=1),
]
sales_invoice_shipping_fields = [
@@ -194,7 +200,11 @@ def make_custom_fields(update=True):
inter_state_gst_field = [
dict(fieldname='is_inter_state', label='Is Inter State',
- fieldtype='Check', insert_after='disabled', print_hide=1)
+ fieldtype='Check', insert_after='disabled', print_hide=1),
+ dict(fieldname='tax_category_column_break', fieldtype='Column Break',
+ insert_after='is_inter_state'),
+ dict(fieldname='gst_state', label='Source State', fieldtype='Select',
+ options='\n'.join(states), insert_after='company')
]
ewaybill_fields = [
@@ -374,8 +384,7 @@ def make_custom_fields(update=True):
'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields,
'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields,
'Sales Order': sales_invoice_gst_fields,
- 'Sales Taxes and Charges Template': inter_state_gst_field,
- 'Purchase Taxes and Charges Template': inter_state_gst_field,
+ 'Tax Category': inter_state_gst_field,
'Item': [
dict(fieldname='gst_hsn_code', label='HSN/SAC',
fieldtype='Link', options='GST HSN Code', insert_after='item_group'),
@@ -459,6 +468,15 @@ def make_custom_fields(update=True):
'insert_after': 'gst_transporter_id',
'options': 'Registered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nUIN Holders',
'default': 'Unregistered'
+ },
+ {
+ 'fieldname': 'export_type',
+ 'label': 'Export Type',
+ 'fieldtype': 'Select',
+ 'insert_after': 'gst_category',
+ 'default': 'Without Payment of Tax',
+ 'depends_on':'eval:in_list(["SEZ", "Overseas"], doc.gst_category)',
+ 'options': '\nWith Payment of Tax\nWithout Payment of Tax'
}
],
'Customer': [
@@ -469,6 +487,15 @@ def make_custom_fields(update=True):
'insert_after': 'customer_type',
'options': 'Registered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders',
'default': 'Unregistered'
+ },
+ {
+ 'fieldname': 'export_type',
+ 'label': 'Export Type',
+ 'fieldtype': 'Select',
+ 'insert_after': 'gst_category',
+ 'default': 'Without Payment of Tax',
+ 'depends_on':'eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)',
+ 'options': '\nWith Payment of Tax\nWithout Payment of Tax'
}
]
}
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
new file mode 100644
index 0000000000..1e59032db1
--- /dev/null
+++ b/erpnext/regional/india/taxes.js
@@ -0,0 +1,41 @@
+erpnext.setup_auto_gst_taxation = (doctype) => {
+ frappe.ui.form.on(doctype, {
+ company_address: function(frm) {
+ frm.trigger('get_tax_template');
+ },
+ shipping_address: function(frm) {
+ frm.trigger('get_tax_template');
+ },
+ tax_category: function(frm) {
+ frm.trigger('get_tax_template');
+ },
+ get_tax_template: function(frm) {
+ let party_details = {
+ 'shipping_address': frm.doc.shipping_address || '',
+ 'shipping_address_name': frm.doc.shipping_address_name || '',
+ 'customer_address': frm.doc.customer_address || '',
+ 'customer': frm.doc.customer,
+ 'supplier': frm.doc.supplier,
+ 'supplier_gstin': frm.doc.supplier_gstin,
+ 'company_gstin': frm.doc.company_gstin,
+ 'tax_category': frm.doc.tax_category
+ };
+
+ frappe.call({
+ method: 'erpnext.regional.india.utils.get_regional_address_details',
+ args: {
+ party_details: JSON.stringify(party_details),
+ doctype: frm.doc.doctype,
+ company: frm.doc.company,
+ return_taxes: 1
+ },
+ callback: function(r) {
+ if(r.message) {
+ frm.set_value('taxes_and_charges', r.message.taxes_and_charges);
+ }
+ }
+ });
+ }
+ });
+};
+
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index aae07797a1..77bcc80aba 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -7,6 +7,8 @@ from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_
from erpnext.controllers.accounts_controller import get_taxes_and_charges
from erpnext.hr.utils import get_salary_assignment
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
+from erpnext.regional.india import number_state_mapping
+from six import string_types
def validate_gstin_for_india(doc, method):
if hasattr(doc, 'gst_state') and doc.gst_state:
@@ -46,6 +48,14 @@ def validate_gstin_for_india(doc, method):
frappe.throw(_("Invalid GSTIN! First 2 digits of GSTIN should match with State number {0}.")
.format(doc.gst_state_number))
+def update_gst_category(doc, method):
+ for link in doc.links:
+ if link.link_doctype in ['Customer', 'Supplier']:
+ if doc.get('gstin'):
+ frappe.db.sql("""
+ UPDATE `tab{0}` SET gst_category = %s WHERE name = %s AND gst_category = 'Unregistered'
+ """.format(link.link_doctype), ("Registered Regular", link.link_name)) #nosec
+
def set_gst_state_and_state_number(doc):
if not doc.gst_state:
if not doc.state:
@@ -122,44 +132,106 @@ def test_method():
'''test function'''
return 'overridden'
-def get_place_of_supply(out, doctype):
+def get_place_of_supply(party_details, doctype):
if not frappe.get_meta('Address').has_field('gst_state'): return
- if doctype in ("Sales Invoice", "Delivery Note"):
- address_name = out.shipping_address_name or out.customer_address
- elif doctype == "Purchase Invoice":
- address_name = out.shipping_address or out.supplier_address
+ if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
+ address_name = party_details.shipping_address_name or party_details.customer_address
+ elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
+ address_name = party_details.shipping_address or party_details.supplier_address
if address_name:
address = frappe.db.get_value("Address", address_name, ["gst_state", "gst_state_number"], as_dict=1)
if address and address.gst_state and address.gst_state_number:
return cstr(address.gst_state_number) + "-" + cstr(address.gst_state)
-def get_regional_address_details(out, doctype, company):
- out.place_of_supply = get_place_of_supply(out, doctype)
+@frappe.whitelist()
+def get_regional_address_details(party_details, doctype, company, return_taxes=None):
- if not out.place_of_supply: return
+ if isinstance(party_details, string_types):
+ party_details = json.loads(party_details)
+ party_details = frappe._dict(party_details)
- if doctype in ("Sales Invoice", "Delivery Note"):
+ party_details.place_of_supply = get_place_of_supply(party_details, doctype)
+ if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
master_doctype = "Sales Taxes and Charges Template"
- if not out.company_gstin:
- return
- elif doctype == "Purchase Invoice":
- master_doctype = "Purchase Taxes and Charges Template"
- if not out.supplier_gstin:
+
+ get_tax_template_for_sez(party_details, master_doctype, company, 'Customer')
+ get_tax_template_based_on_category(master_doctype, company, party_details)
+
+ if party_details.get('taxes_and_charges') and return_taxes:
+ return party_details
+
+ if not party_details.company_gstin:
return
- if ((doctype in ("Sales Invoice", "Delivery Note") and out.company_gstin
- and out.company_gstin[:2] != out.place_of_supply[:2]) or (doctype == "Purchase Invoice"
- and out.supplier_gstin and out.supplier_gstin[:2] != out.place_of_supply[:2])):
- default_tax = frappe.db.get_value(master_doctype, {"company": company, "is_inter_state":1, "disabled":0})
+ elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
+ master_doctype = "Purchase Taxes and Charges Template"
+
+ get_tax_template_for_sez(party_details, master_doctype, company, 'Supplier')
+ get_tax_template_based_on_category(master_doctype, company, party_details)
+
+ if party_details.get('taxes_and_charges') and return_taxes:
+ return party_details
+
+ if not party_details.supplier_gstin:
+ return
+
+ if not party_details.place_of_supply: return
+
+ if ((doctype in ("Sales Invoice", "Delivery Note", "Sales Order") and party_details.company_gstin
+ and party_details.company_gstin[:2] != party_details.place_of_supply[:2]) or (doctype in ("Purchase Invoice",
+ "Purchase Order", "Purchase Receipt") and party_details.supplier_gstin and party_details.supplier_gstin[:2] != party_details.place_of_supply[:2])):
+ default_tax = get_tax_template(master_doctype, company, 1, party_details.company_gstin[:2])
else:
- default_tax = frappe.db.get_value(master_doctype, {"company": company, "disabled":0, "is_default": 1})
+ default_tax = get_tax_template(master_doctype, company, 0, party_details.company_gstin[:2])
if not default_tax:
return
- out["taxes_and_charges"] = default_tax
- out.taxes = get_taxes_and_charges(master_doctype, default_tax)
+ party_details["taxes_and_charges"] = default_tax
+ party_details.taxes = get_taxes_and_charges(master_doctype, default_tax)
+
+ if return_taxes:
+ return party_details
+
+def get_tax_template_based_on_category(master_doctype, company, party_details):
+ if not party_details.get('tax_category'):
+ return
+
+ default_tax = frappe.db.get_value(master_doctype, {'company': company, 'tax_category': party_details.get('tax_category')},
+ 'name')
+
+ if default_tax:
+ party_details["taxes_and_charges"] = default_tax
+ party_details.taxes = get_taxes_and_charges(master_doctype, default_tax)
+
+def get_tax_template(master_doctype, company, is_inter_state, state_code):
+ tax_categories = frappe.get_all('Tax Category', fields = ['name', 'is_inter_state', 'gst_state'],
+ filters = {'is_inter_state': is_inter_state})
+
+ default_tax = ''
+
+ for tax_category in tax_categories:
+ if tax_category.gst_state == number_state_mapping[state_code] or \
+ (not default_tax and not tax_category.gst_state):
+ default_tax = frappe.db.get_value(master_doctype,
+ {'disabled': 0, 'tax_category': tax_category.name}, 'name')
+
+ return default_tax
+
+def get_tax_template_for_sez(party_details, master_doctype, company, party_type):
+
+ gst_details = frappe.db.get_value(party_type, {'name': party_details.get(frappe.scrub(party_type))},
+ ['gst_category', 'export_type'], as_dict=1)
+
+ if gst_details:
+ if gst_details.gst_category == 'SEZ' and gst_details.export_type == 'With Payment of Tax':
+ default_tax = frappe.db.get_value(master_doctype, {"company": company, "is_inter_state":1, "disabled":0,
+ "gst_state": number_state_mapping[party_details.company_gstin[:2]]})
+
+ party_details["taxes_and_charges"] = default_tax
+ party_details.taxes = get_taxes_and_charges(master_doctype, default_tax)
+
def calculate_annual_eligible_hra_exemption(doc):
basic_component = frappe.get_cached_value('Company', doc.company, "basic_component")
@@ -555,7 +627,7 @@ def get_gst_accounts(company, account_wise=False):
filters={"parent": "GST Settings", "company": company},
fields=["cgst_account", "sgst_account", "igst_account", "cess_account"])
- if not gst_settings_accounts:
+ if not gst_settings_accounts and not frappe.flags.in_test:
frappe.throw(_("Please set GST Accounts in GST Settings"))
for d in gst_settings_accounts:
diff --git a/erpnext/selling/doctype/sales_order/regional/india.js b/erpnext/selling/doctype/sales_order/regional/india.js
new file mode 100644
index 0000000000..c11cfcc50b
--- /dev/null
+++ b/erpnext/selling/doctype/sales_order/regional/india.js
@@ -0,0 +1,3 @@
+{% include "erpnext/regional/india/taxes.js" %}
+
+erpnext.setup_auto_gst_taxation('Sales Order');
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index e97a4ee461..2112a4174b 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -578,8 +578,12 @@ def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False):
target.run_method("set_po_nos")
target.run_method("calculate_taxes_and_totals")
- # set company address
- target.update(get_company_address(target.company))
+ if source.company_address:
+ target.update({'company_address': source.company_address})
+ else:
+ # set company address
+ target.update(get_company_address(target.company))
+
if target.company_address:
target.update(get_fetch_values("Delivery Note", 'company_address', target.company_address))
@@ -645,8 +649,12 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
target.run_method("set_po_nos")
target.run_method("calculate_taxes_and_totals")
- # set company address
- target.update(get_company_address(target.company))
+ if source.company_address:
+ target.update({'company_address': source.company_address})
+ else:
+ # set company address
+ target.update(get_company_address(target.company))
+
if target.company_address:
target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 5033d7aa7f..c04bfd281e 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -77,7 +77,6 @@
"fieldtype": "Column Break"
},
{
- "description": "Only for Stock Items",
"fieldname": "so_required",
"fieldtype": "Select",
"label": "Sales Order Required",
@@ -138,7 +137,7 @@
"icon": "fa fa-cog",
"idx": 1,
"issingle": 1,
- "modified": "2019-11-25 18:35:51.472653",
+ "modified": "2019-12-09 13:38:36.486298",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling Settings",
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
index ee806a78fb..daca2e3bd0 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
@@ -20,11 +20,15 @@ frappe.query_reports["Item-wise Sales History"] = {
},
{
fieldname:"from_date",
+ reqd: 1,
label: __("From Date"),
fieldtype: "Date",
+ default: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
},
{
fieldname:"to_date",
+ reqd: 1,
+ default: frappe.datetime.get_today(),
label: __("To Date"),
fieldtype: "Date",
},
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
index 226c34f735..1fc3663bed 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
@@ -196,6 +196,7 @@ def get_customer_details():
def get_sales_order_details(company_list, filters):
conditions = get_conditions(filters)
+
return frappe.db.sql("""
SELECT
so_item.item_code, so_item.item_name, so_item.item_group,
@@ -208,7 +209,6 @@ def get_sales_order_details(company_list, filters):
`tabSales Order` so, `tabSales Order Item` so_item
WHERE
so.name = so_item.parent
- AND so.company in (%s)
- AND so.docstatus = 1
- {0}
- """.format(conditions), company_list, as_dict=1) #nosec
+ AND so.company in ({0})
+ AND so.docstatus = 1 {1}
+ """.format(','.join(["%s"] * len(company_list)), conditions), tuple(company_list), as_dict=1)
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 04e8a83e7f..2eee919b53 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -14,6 +14,8 @@ from frappe.model.document import Document
from frappe.contacts.address_and_contact import load_address_and_contact
from frappe.utils.nestedset import NestedSet
+import functools
+
class Company(NestedSet):
nsm_parent_field = 'parent_company'
@@ -560,3 +562,26 @@ def get_timeline_data(doctype, name):
return json.loads(history) if history and '{' in history else {}
return date_to_value_dict
+
+@frappe.whitelist()
+def get_default_company_address(name, sort_key='is_primary_address', existing_address=None):
+ if sort_key not in ['is_shipping_address', 'is_primary_address']:
+ return None
+
+ out = frappe.db.sql(""" SELECT
+ addr.name, addr.%s
+ FROM
+ `tabAddress` addr, `tabDynamic Link` dl
+ WHERE
+ dl.parent = addr.name and dl.link_doctype = 'Company' and
+ dl.link_name = %s and ifnull(addr.disabled, 0) = 0
+ """ %(sort_key, '%s'), (name)) #nosec
+
+ if existing_address:
+ if existing_address in [d[0] for d in out]:
+ return existing_address
+
+ if out:
+ return sorted(out, key = functools.cmp_to_key(lambda x,y: cmp(y[1], x[1])))[0][0]
+ else:
+ return None
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index c98dfe35fb..39aad2e007 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -424,7 +424,12 @@ def make_sales_invoice(source_name, target_doc=None):
target.run_method("calculate_taxes_and_totals")
# set company address
- target.update(get_company_address(target.company))
+ if source.company_address:
+ target.update({'company_address': source.company_address})
+ else:
+ # set company address
+ target.update(get_company_address(target.company))
+
if target.company_address:
target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
diff --git a/erpnext/stock/doctype/delivery_note/regional/india.js b/erpnext/stock/doctype/delivery_note/regional/india.js
new file mode 100644
index 0000000000..22f4716ea5
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_note/regional/india.js
@@ -0,0 +1,4 @@
+{% include "erpnext/regional/india/taxes.js" %}
+
+erpnext.setup_auto_gst_taxation('Delivery Note');
+
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index d0fae6a227..9b73d0f271 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -95,7 +95,8 @@ class PurchaseReceipt(BuyingController):
# check cwip accounts before making auto assets
# Improves UX by not giving messages of "Assets Created" before throwing error of not finding arbnb account
arbnb_account = self.get_company_default("asset_received_but_not_billed")
- cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company)
+ cwip_account = get_asset_account("capital_work_in_progress_account", asset_category = item.asset_category, \
+ company = self.company)
break
def validate_with_previous_doc(self):
@@ -364,8 +365,9 @@ class PurchaseReceipt(BuyingController):
def add_asset_gl_entries(self, item, gl_entries):
arbnb_account = self.get_company_default("asset_received_but_not_billed")
- # This returns company's default cwip account
- cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company)
+ # This returns category's cwip account if not then fallback to company's default cwip account
+ cwip_account = get_asset_account("capital_work_in_progress_account", asset_category = item.asset_category, \
+ company = self.company)
asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate)
base_asset_amount = flt(item.base_net_amount + item.item_tax_amount)
diff --git a/erpnext/stock/doctype/purchase_receipt/regional/india.js b/erpnext/stock/doctype/purchase_receipt/regional/india.js
new file mode 100644
index 0000000000..b4f1201f36
--- /dev/null
+++ b/erpnext/stock/doctype/purchase_receipt/regional/india.js
@@ -0,0 +1,3 @@
+{% include "erpnext/regional/india/taxes.js" %}
+
+erpnext.setup_auto_gst_taxation('Purchase Receipt');
\ No newline at end of file
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 19eb398130..23d00da7c1 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -353,17 +353,19 @@ def get_auto_serial_nos(serial_no_series, qty):
def auto_make_serial_nos(args):
serial_nos = get_serial_nos(args.get('serial_no'))
created_numbers = []
+ voucher_type = args.get('voucher_type')
+ item_code = args.get('item_code')
for serial_no in serial_nos:
if frappe.db.exists("Serial No", serial_no):
sr = frappe.get_doc("Serial No", serial_no)
sr.via_stock_ledger = True
- sr.item_code = args.get('item_code')
+ sr.item_code = item_code
sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None
sr.batch_no = args.get('batch_no')
sr.location = args.get('location')
sr.company = args.get('company')
sr.supplier = args.get('supplier')
- if sr.sales_order and args.get('voucher_type') == "Stock Entry" \
+ if sr.sales_order and voucher_type == "Stock Entry" \
and not args.get('actual_qty', 0) > 0:
sr.sales_order = None
sr.save(ignore_permissions=True)
@@ -371,10 +373,28 @@ def auto_make_serial_nos(args):
created_numbers.append(make_serial_no(serial_no, args))
form_links = list(map(lambda d: frappe.utils.get_link_to_form('Serial No', d), created_numbers))
+
+ # Setting up tranlated title field for all cases
+ singular_title = _("Serial Number Created")
+ multiple_title = _("Serial Numbers Created")
+
+ if voucher_type:
+ multiple_title = singular_title = _("{0} Created").format(voucher_type)
+
if len(form_links) == 1:
- frappe.msgprint(_("Serial No {0} created").format(form_links[0]))
+ frappe.msgprint(_("Serial No {0} Created").format(form_links[0]), singular_title)
elif len(form_links) > 0:
- frappe.msgprint(_("The following serial numbers were created:
{0}").format(', '.join(form_links)))
+ message = _("The following serial numbers were created:
{0}").format(get_items_html(form_links, item_code))
+ frappe.msgprint(message, multiple_title)
+
+def get_items_html(serial_nos, item_code):
+ body = ', '.join(serial_nos)
+ return '''
+ {0}: {1} Serial Numbers
+
+ {2}
+ '''.format(item_code, len(serial_nos), body)
+
def get_item_details(item_code):
return frappe.db.sql("""select name, has_batch_no, docstatus,
@@ -397,7 +417,7 @@ def make_serial_no(serial_no, args):
sr.via_stock_ledger = args.get('via_stock_ledger') or True
sr.asset = args.get('asset')
sr.location = args.get('location')
-
+
if args.get('purchase_document_type'):
sr.purchase_document_type = args.get('purchase_document_type')
diff --git a/erpnext/support/web_form/issues/issues.json b/erpnext/support/web_form/issues/issues.json
index 652114f738..9b904ad796 100644
--- a/erpnext/support/web_form/issues/issues.json
+++ b/erpnext/support/web_form/issues/issues.json
@@ -18,7 +18,7 @@
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
- "modified": "2019-06-27 22:58:49.609672",
+ "modified": "2019-12-10 13:48:19.894186",
"modified_by": "Administrator",
"module": "Support",
"name": "issues",
diff --git a/erpnext/www/book_appointment/__init__.py b/erpnext/www/book_appointment/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/www/book-appointment/index.css b/erpnext/www/book_appointment/index.css
similarity index 100%
rename from erpnext/www/book-appointment/index.css
rename to erpnext/www/book_appointment/index.css
diff --git a/erpnext/www/book-appointment/index.html b/erpnext/www/book_appointment/index.html
similarity index 98%
rename from erpnext/www/book-appointment/index.html
rename to erpnext/www/book_appointment/index.html
index 96774d5656..f242f43ad5 100644
--- a/erpnext/www/book-appointment/index.html
+++ b/erpnext/www/book_appointment/index.html
@@ -4,7 +4,7 @@
{% block script %}
-
+
{% endblock %}
{% block page_content %}
diff --git a/erpnext/www/book-appointment/index.js b/erpnext/www/book_appointment/index.js
similarity index 96%
rename from erpnext/www/book-appointment/index.js
rename to erpnext/www/book_appointment/index.js
index 13c87ddbcf..c8dd5013d5 100644
--- a/erpnext/www/book-appointment/index.js
+++ b/erpnext/www/book_appointment/index.js
@@ -15,10 +15,10 @@ async function initialise_select_date() {
async function get_global_variables() {
// Using await through this file instead of then.
window.appointment_settings = (await frappe.call({
- method: 'erpnext.www.book-appointment.index.get_appointment_settings'
+ method: 'erpnext.www.book_appointment.index.get_appointment_settings'
})).message;
window.timezones = (await frappe.call({
- method:'erpnext.www.book-appointment.index.get_timezones'
+ method:'erpnext.www.book_appointment.index.get_timezones'
})).message;
window.holiday_list = window.appointment_settings.holiday_list;
}
@@ -79,7 +79,7 @@ function on_date_or_timezone_select() {
async function get_time_slots(date, timezone) {
let slots = (await frappe.call({
- method: 'erpnext.www.book-appointment.index.get_appointment_slots',
+ method: 'erpnext.www.book_appointment.index.get_appointment_slots',
args: {
date: date,
timezone: timezone
@@ -201,7 +201,7 @@ async function submit() {
}
let contact = get_form_data();
let appointment = frappe.call({
- method: 'erpnext.www.book-appointment.index.create_appointment',
+ method: 'erpnext.www.book_appointment.index.create_appointment',
args: {
'date': window.selected_date,
'time': window.selected_time,
diff --git a/erpnext/www/book-appointment/index.py b/erpnext/www/book_appointment/index.py
similarity index 100%
rename from erpnext/www/book-appointment/index.py
rename to erpnext/www/book_appointment/index.py
diff --git a/erpnext/www/book_appointment/verify/__init__.py b/erpnext/www/book_appointment/verify/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/www/book-appointment/verify/index.html b/erpnext/www/book_appointment/verify/index.html
similarity index 100%
rename from erpnext/www/book-appointment/verify/index.html
rename to erpnext/www/book_appointment/verify/index.html
diff --git a/erpnext/www/book-appointment/verify/index.py b/erpnext/www/book_appointment/verify/index.py
similarity index 100%
rename from erpnext/www/book-appointment/verify/index.py
rename to erpnext/www/book_appointment/verify/index.py