diff --git a/.travis.yml b/.travis.yml
index beab4e119a..a70062fea3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -53,6 +53,9 @@ before_script:
script:
- set -e
- - bench --verbose run-tests
+ - bench run-tests
- sleep 5
- - bench --verbose run-ui-tests --app erpnext
+ - bench reinstall --yes
+ - bench execute erpnext.setup.setup_wizard.utils.complete
+ - bench execute erpnext.setup.utils.enable_all_roles_and_domains
+ - bench run-ui-tests --app erpnext
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 48296e7e33..cf6ca02e7f 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -4,7 +4,7 @@ import inspect
import frappe
from erpnext.hooks import regional_overrides
-__version__ = '8.9.2'
+__version__ = '8.10.0'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json
index 0489f9a5f0..8de923f2e0 100644
--- a/erpnext/accounts/doctype/account/account.json
+++ b/erpnext/accounts/doctype/account/account.json
@@ -13,6 +13,7 @@
"editable_grid": 0,
"fields": [
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -42,6 +43,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -70,6 +72,7 @@
"width": "50%"
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -100,6 +103,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -130,6 +134,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -161,6 +166,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -190,6 +196,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -219,6 +226,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -250,6 +258,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -278,6 +287,7 @@
"width": "50%"
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -309,6 +319,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -341,6 +352,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -372,6 +384,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -404,6 +417,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -433,6 +447,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -461,6 +476,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -489,6 +505,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -528,7 +545,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-04-21 17:22:41.150984",
+ "modified": "2017-08-11 15:28:35.855809",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
@@ -641,6 +658,6 @@
"search_fields": "",
"show_name_in_global_search": 1,
"sort_order": "ASC",
- "track_changes": 0,
+ "track_changes": 1,
"track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/tw_chart_of_accounts.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/tw_chart_of_accounts.json
new file mode 100644
index 0000000000..a79283a40a
--- /dev/null
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/tw_chart_of_accounts.json
@@ -0,0 +1,722 @@
+{
+ "country_code": "tw",
+ "name": "Taiwan - Chart of Accounts",
+ "tree": {
+ "1-\u8cc7\u7522": {
+ "11~12-\u6d41\u52d5\u8cc7\u7522": {
+ "111-\u73fe\u91d1\u53ca\u7d04\u7576\u73fe\u91d1": {
+ "1111-\u5eab\u5b58\u73fe\u91d1": {
+ "account_type": "Cash"
+ },
+ "1112-\u96f6\u7528\u91d1/\u9031\u8f49\u91d1": {
+ "account_type": "Cash"
+ },
+ "1113-\u9280\u884c\u5b58\u6b3e": {
+ "account_type": "Bank",
+ "\u4e2d\u570b\u4fe1\u8a17": {
+ "account_type": "Bank"
+ },
+ "\u53f0\u5317\u5bcc\u90a6": {
+ "account_type": "Bank"
+ }
+ },
+ "1116-\u5728\u9014\u73fe\u91d1": {
+ "account_type": "Cash"
+ },
+ "1117-\u7d04\u7576\u73fe\u91d1": {
+ "account_type": "Cash"
+ },
+ "1118-\u5176\u4ed6\u73fe\u91d1\u53ca\u7d04\u7576\u73fe\u91d1": {
+ "account_type": "Cash"
+ },
+ "account_type": "Cash"
+ },
+ "112-\u77ed\u671f\u6295\u8cc7": {
+ "1121-\u77ed\u671f\u6295\u8cc7 \u2014\u80a1\u7968": {}
+ },
+ "113-\u61c9\u6536\u7968\u64da": {
+ "1131-\u61c9\u6536\u7968\u64da": {
+ "account_type": "Receivable"
+ },
+ "1132-\u61c9\u6536\u7968\u64da\u8cbc\u73fe ": {
+ "account_type": "Receivable"
+ },
+ "1138-\u5176\u4ed6\u61c9\u6536\u7968\u64da ": {
+ "account_type": "Receivable"
+ },
+ "1139-\u5099\u62b5\u5446\u5e33 \uff0d\u61c9\u6536\u7968\u64da ": {
+ "account_type": "Receivable"
+ },
+ "account_type": "Receivable"
+ },
+ "114-\u61c9\u6536\u5e33\u6b3e": {
+ "1141-\u61c9\u6536\u5e33\u6b3e ": {
+ "account_type": "Receivable"
+ },
+ "1142-\u61c9\u6536\u5206\u671f\u5e33\u6b3e ": {
+ "account_type": "Receivable"
+ },
+ "1149-\u5099\u62b5\u5446\u5e33 \uff0d\u61c9\u6536\u5e33\u6b3e ": {
+ "account_type": "Receivable"
+ },
+ "account_type": "Receivable"
+ },
+ "118-\u5176\u4ed6\u61c9\u6536\u6b3e": {
+ "1184-\u61c9\u6536\u6536\u76ca": {
+ "account_type": "Receivable"
+ },
+ "1185-\u61c9\u6536\u9000\u7a05\u6b3e": {
+ "account_type": "Receivable"
+ },
+ "1189-\u5099\u62b5\u5446\u5e33 \u2014 \u5176\u4ed6\u61c9\u6536\u6b3e ": {
+ "account_type": "Receivable"
+ },
+ "account_type": "Receivable"
+ },
+ "121~122-\u5b58\u8ca8": {
+ "1219-\u5099\u62b5\u5b58\u8ca8\u8dcc\u50f9\u640d\u5931": {},
+ "1229-\u5099\u62b5\u5b58\u8ca8\u8dcc\u50f9\u640d\u5931": {},
+ "account_type": "Stock",
+ "is_group": 1
+ },
+ "125-\u9810\u4ed8\u8cbb\u7528": {
+ "1251-\u9810\u4ed8\u85aa\u8cc7": {},
+ "1252-\u9810\u4ed8\u79df\u91d1": {},
+ "1253-\u9810\u4ed8\u4fdd\u96aa\u8cbb": {},
+ "1254-\u7528\u54c1\u76e4\u5b58": {},
+ "1255-\u9810\u4ed8\u6240\u5f97\u7a05": {},
+ "1258-\u5176\u4ed6\u9810\u4ed8\u8cbb\u7528": {}
+ },
+ "126-\u9810\u4ed8\u6b3e\u9805": {
+ "1261-\u9810\u4ed8\u8ca8\u6b3e": {},
+ "1268-\u5176\u4ed6\u9810\u4ed8\u6b3e\u9805": {}
+ },
+ "128~129-\u5176\u4ed6\u6d41\u52d5\u8cc7\u7522": {
+ "1281-\u9032\u9805\u7a05\u984d": {},
+ "1282-\u7559\u62b5\u7a05\u984d": {},
+ "1283-\u66ab\u4ed8\u6b3e": {},
+ "1284-\u4ee3\u4ed8\u6b3e": {},
+ "1285-\u54e1\u5de5\u501f\u652f": {}
+ }
+ },
+ "13-\u57fa\u91d1\u53ca\u9577\u671f\u6295\u8cc7": {
+ "131-\u57fa\u91d1": {
+ "1311-\u511f\u50b5\u57fa\u91d1": {},
+ "1313-\u610f\u5916\u640d\u5931\u6e96\u5099\u57fa\u91d1": {},
+ "1314-\u9000\u4f11\u57fa\u91d1": {},
+ "1318-\u5176\u4ed6\u57fa\u91d1": {}
+ },
+ "132-\u9577\u671f\u6295\u8cc7": {
+ "1321-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7": {},
+ "1322-\u9577\u671f\u50b5\u5238\u6295\u8cc7": {},
+ "1323-\u9577\u671f\u4e0d\u52d5\u7522\u6295\u8cc7": {},
+ "1328-\u5176\u4ed6\u9577\u671f\u6295\u8cc7": {}
+ }
+ },
+ "14~15-\u56fa\u5b9a\u8cc7\u7522": {
+ "141-\u571f\u5730": {
+ "1411-\u571f\u5730": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "142-\u571f\u5730\u6539\u826f\u7269": {
+ "1421-\u571f\u5730\u6539\u826f\u7269": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "143-\u623f\u5c4b\u53ca\u5efa\u7269": {
+ "1431-\u623f\u5c4b\u53ca\u5efa\u7269": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "144~146-\u6a5f(\u5668)\u5177\u53ca\u8a2d\u5099": {
+ "1441-\u6a5f(\u5668)\u5177": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "151-\u79df\u8cc3\u8cc7\u7522": {
+ "1511-\u79df\u8cc3\u8cc7\u7522": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "152-\u79df\u8cc3\u6b0a\u76ca\u6539\u826f": {
+ "1521-\u79df\u8cc3\u6b0a\u76ca\u6539\u826f": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "156-\u672a\u5b8c\u5de5\u7a0b\u53ca\u9810\u4ed8\u8cfc\u7f6e\u8a2d\u5099\u6b3e": {
+ "1561-\u672a\u5b8c\u5de5\u7a0b": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "158-\u96dc\u9805\u56fa\u5b9a\u8cc7\u7522": {
+ "1581-\u96dc\u9805\u56fa\u5b9a\u8cc7\u7522": {
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "account_type": "Fixed Asset"
+ },
+ "16-\u905e\u8017\u8cc7\u7522": {
+ "161-\u905e\u8017\u8cc7\u7522": {
+ "is_group": 1
+ }
+ },
+ "17-\u7121\u5f62\u8cc7\u7522": {
+ "171-\u5546\u6a19\u6b0a": {
+ "1711-\u5546\u6a19\u6b0a": {}
+ },
+ "172-\u5c08\u5229\u6b0a": {
+ "1721-\u5c08\u5229\u6b0a": {}
+ },
+ "176-\u5546\u8b7d": {
+ "1761-\u5546\u8b7d": {}
+ },
+ "177-\u958b\u8fa6\u8cbb": {
+ "1771-\u958b\u8fa6\u8cbb": {}
+ },
+ "178-\u5176\u4ed6\u7121\u5f62\u8cc7\u7522": {
+ "1781-\u905e\u5ef6\u9000\u4f11\u91d1\u6210\u672c": {}
+ }
+ },
+ "18-\u5176\u4ed6\u8cc7\u7522": {
+ "181-\u905e\u5ef6\u8cc7\u7522": {
+ "1811-\u50b5\u5238\u767c\u884c\u6210\u672c": {},
+ "1812-\u9577\u671f\u9810\u4ed8\u79df\u91d1": {},
+ "1813-\u9577\u671f\u9810\u4ed8\u4fdd\u96aa\u8cbb": {},
+ "1814-\u905e\u5ef6\u6240\u5f97\u7a05\u8cc7\u7522": {},
+ "1815-\u9810\u4ed8\u9000\u4f11\u91d1": {},
+ "1818-\u5176\u4ed6\u905e\u5ef6\u8cc7\u7522": {}
+ },
+ "182-\u9592\u7f6e\u8cc7\u7522": {
+ "1821-\u9592\u7f6e\u8cc7\u7522": {}
+ },
+ "184-\u9577\u671f\u61c9\u6536\u7968\u64da\u53ca\u6b3e\u9805\u8207\u50ac\u6536\u5e33\u6b3e": {
+ "1841-\u9577\u671f\u61c9\u6536\u7968\u64da": {
+ "account_type": "Receivable"
+ },
+ "1842-\u9577\u671f\u61c9\u6536\u5e33\u6b3e": {
+ "account_type": "Receivable"
+ },
+ "1843-\u50ac\u6536\u5e33\u6b3e": {
+ "account_type": "Receivable"
+ },
+ "1848-\u5176\u4ed6\u9577\u671f\u61c9\u6536\u6b3e\u9805": {
+ "account_type": "Receivable"
+ },
+ "1849-\u5099\u62b5\u5446\u5e33\u2014\u9577\u671f\u61c9\u6536\u7968\u64da\u53ca\u6b3e\u9805\u8207\u50ac\u6536\u5e33\u6b3e": {
+ "account_type": "Receivable"
+ },
+ "account_type": "Receivable"
+ },
+ "185-\u51fa\u79df\u8cc7\u7522": {
+ "1851-\u51fa\u79df\u8cc7\u7522": {},
+ "1858-\u51fa\u79df\u8cc7\u7522 \u2014\u91cd\u4f30\u589e\u503c": {},
+ "1859-\u7d2f\u7a4d\u6298\u820a \u2014\u51fa\u79df\u8cc7\u7522": {
+ "account_type": "Accumulated Depreciation"
+ }
+ },
+ "186-\u5b58\u51fa\u4fdd\u8b49\u91d1": {
+ "1861-\u5b58\u51fa\u4fdd\u8b49\u91d1": {}
+ },
+ "188-\u96dc\u9805\u8cc7\u7522": {
+ "1881-\u53d7\u9650\u5236\u5b58\u6b3e": {},
+ "1888-\u96dc\u9805\u8cc7\u7522 \u2014\u5176\u4ed6": {}
+ }
+ },
+ "Temporary Accounts": {
+ "Temporary Opening": {
+ "account_type": "Temporary"
+ },
+ "account_type": "Temporary"
+ },
+ "root_type": "Asset"
+ },
+ "2-\u8ca0\u50b5": {
+ "21~22-\u6d41\u52d5\u8ca0\u50b5": {
+ "211-\u77ed\u671f\u501f\u6b3e": {
+ "2111-\u9280\u884c\u900f\u652f": {},
+ "2112-\u9280\u884c\u501f\u6b3e": {}
+ },
+ "212-\u61c9\u4ed8\u77ed\u671f\u7968\u5238": {
+ "2121-\u61c9\u4ed8\u5546\u696d\u672c\u7968": {
+ "account_type": "Payable"
+ },
+ "2122-\u9280\u884c\u627f\u514c\u532f\u7968": {
+ "account_type": "Payable"
+ },
+ "account_type": "Payable"
+ },
+ "213-\u61c9\u4ed8\u7968\u64da": {
+ "2131-\u61c9\u4ed8\u7968\u64da": {
+ "account_type": "Payable"
+ },
+ "account_type": "Payable"
+ },
+ "214-\u61c9\u4ed8\u5e33\u6b3e": {
+ "2141-\u61c9\u4ed8\u5e33\u6b3e": {
+ "account_type": "Payable"
+ },
+ "account_type": "Payable"
+ },
+ "216-\u61c9\u4ed8\u6240\u5f97\u7a05": {
+ "2161-\u61c9\u4ed8\u6240\u5f97\u7a05": {
+ "account_type": "Tax",
+ "tax_rate": 5.0
+ },
+ "account_type": "Tax",
+ "tax_rate": 5.0
+ },
+ "217-\u61c9\u4ed8\u8cbb\u7528": {
+ "2171-\u61c9\u4ed8\u85aa\u5de5": {},
+ "2172-\u61c9\u4ed8\u79df\u91d1": {},
+ "2173-\u61c9\u4ed8\u5229\u606f": {},
+ "2174-\u61c9\u4ed8\u71df\u696d\u7a05": {},
+ "2175-\u61c9\u4ed8\u7a05\u6350 \u2014\u5176\u4ed6": {
+ "account_type": "Tax",
+ "tax_rate": 5.0
+ },
+ "2178-\u5176\u4ed6\u61c9\u4ed8\u8cbb\u7528": {}
+ },
+ "218~219-\u5176\u4ed6\u61c9\u4ed8\u6b3e": {
+ "2184-\u61c9\u4ed8\u571f\u5730\u623f\u5c4b\u6b3e": {},
+ "2185-\u61c9\u4ed8\u8a2d\u5099\u6b3e": {},
+ "2192-\u61c9\u4ed8\u80a1\u5229": {}
+ },
+ "226-\u9810\u6536\u6b3e\u9805": {
+ "2261-\u9810\u6536\u8ca8\u6b3e": {},
+ "2262-\u9810\u6536\u6536\u5165": {},
+ "2268-\u5176\u4ed6\u9810\u6536\u6b3e": {}
+ },
+ "227-\u4e00\u5e74\u6216\u4e00\u71df\u696d\u9031\u671f\u5167\u5230\u671f\u9577\u671f\u8ca0\u50b5": {
+ "is_group": 1
+ },
+ "228~229-\u5176\u4ed6\u6d41\u52d5\u8ca0\u50b5": {
+ "2281-\u92b7\u9805\u7a05\u984d": {},
+ "2283-\u66ab\u6536\u6b3e ": {},
+ "2284-\u4ee3\u6536\u6b3e": {},
+ "2285-\u4f30\u8a08\u552e\u5f8c\u670d\u52d9/\u4fdd\u56fa\u8ca0\u50b5": {},
+ "2291-\u905e\u5ef6\u6240\u5f97\u7a05\u8ca0\u50b5": {},
+ "2292-\u905e\u5ef6\u514c\u63db\u5229\u76ca": {}
+ }
+ },
+ "23-\u9577\u671f\u8ca0\u50b5": {
+ "231-\u61c9\u4ed8\u516c\u53f8\u50b5": {
+ "2311-\u61c9\u4ed8\u516c\u53f8\u50b5": {},
+ "2319-\u61c9\u4ed8\u516c\u53f8\u50b5\u6ea2(\u6298)\u50f9": {}
+ },
+ "232-\u9577\u671f\u501f\u6b3e": {
+ "2321-\u9577\u671f\u9280\u884c\u501f\u6b3e": {},
+ "2324-\u9577\u671f\u501f\u6b3e \u2014\u696d\u4e3b": {},
+ "2325-\u9577\u671f\u501f\u6b3e \u2014\u54e1\u5de5": {},
+ "2327-\u9577\u671f\u501f\u6b3e \u2014\u95dc\u4fc2\u4eba": {},
+ "2328-\u9577\u671f\u501f\u6b3e \u2014\u5176\u4ed6": {}
+ },
+ "233-\u9577\u671f\u61c9\u4ed8\u7968\u64da\u53ca\u6b3e\u9805": {
+ "2331-\u9577\u671f\u61c9\u4ed8\u7968\u64da": {
+ "account_type": "Payable"
+ },
+ "2332-\u9577\u671f\u61c9\u4ed8\u5e33\u6b3e": {
+ "account_type": "Payable"
+ },
+ "2333-\u9577\u671f\u61c9\u4ed8\u79df\u8cc3\u8ca0\u50b5": {
+ "account_type": "Payable"
+ },
+ "account_type": "Payable"
+ },
+ "234-\u4f30\u8a08\u61c9\u4ed8\u571f\u5730\u589e\u503c\u7a05": {
+ "2341-\u4f30\u8a08\u61c9\u4ed8\u571f\u5730\u589e\u503c\u7a05": {}
+ },
+ "235-\u61c9\u8a08\u9000\u4f11\u91d1\u8ca0\u50b5": {
+ "2351-\u61c9\u8a08\u9000\u4f11\u91d1\u8ca0\u50b5": {}
+ },
+ "238-\u5176\u4ed6\u9577\u671f\u8ca0\u50b5": {
+ "2388-\u5176\u4ed6\u9577\u671f\u8ca0\u50b5\u2014\u5176\u4ed6": {}
+ }
+ },
+ "28-\u5176\u4ed6\u8ca0\u50b5": {
+ "281-\u905e\u5ef6\u8ca0\u50b5": {
+ "2811-\u905e\u5ef6\u6536\u5165": {},
+ "2814-\u905e\u5ef6\u6240\u5f97\u7a05\u8ca0\u50b5": {},
+ "2818-\u5176\u4ed6\u905e\u5ef6\u8ca0\u50b5": {}
+ },
+ "286-\u5b58\u5165\u4fdd\u8b49\u91d1": {
+ "2861-\u5b58\u5165\u4fdd\u8b49\u91d1": {}
+ },
+ "288-\u96dc\u9805\u8ca0\u50b5": {
+ "2888-\u96dc\u9805\u8ca0\u50b5 \u2014\u5176\u4ed6": {}
+ }
+ },
+ "Stock Received But Not Billed": {
+ "account_type": "Stock Received But Not Billed"
+ },
+ "root_type": "Liability"
+ },
+ "3-\u696d\u4e3b\u6b0a\u76ca": {
+ "31-\u8cc7\u672c": {
+ "311-\u8cc7\u672c\uff08\u80a1\u672c\uff09 ": {
+ "3111-\u666e\u901a\u80a1\u80a1\u672c": {},
+ "3112-\u7279\u5225\u80a1\u80a1\u672c": {},
+ "3113-\u9810\u6536\u80a1\u672c": {},
+ "3114-\u5f85\u5206\u914d\u80a1\u7968\u80a1\u5229": {},
+ "3115-\u8cc7\u672c": {}
+ }
+ },
+ "32-\u8cc7\u672c\u516c\u7a4d": {
+ "321-\u80a1\u7968\u6ea2\u50f9": {
+ "3211-\u666e\u901a\u80a1\u80a1\u7968\u6ea2\u50f9": {},
+ "3212-\u7279\u5225\u80a1\u80a1\u7968\u6ea2\u50f9": {}
+ },
+ "323-\u8cc7\u7522\u91cd\u4f30\u589e\u503c\u6e96\u5099": {
+ "3231-\u8cc7\u7522\u91cd\u4f30\u589e\u503c\u6e96\u5099": {}
+ },
+ "324-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u516c\u7a4d": {
+ "3241-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u516c\u7a4d": {}
+ },
+ "325-\u5408\u4f75\u516c\u7a4d": {
+ "3251-\u5408\u4f75\u516c\u7a4d": {}
+ },
+ "326-\u53d7\u8d08\u516c\u7a4d": {
+ "3261-\u53d7\u8d08\u516c\u7a4d": {}
+ },
+ "328-\u5176\u4ed6\u8cc7\u672c\u516c\u7a4d": {
+ "3281-\u6b0a\u76ca\u6cd5\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u8cc7\u672c\u516c\u7a4d": {},
+ "3282-\u8cc7\u672c\u516c\u7a4d\u2014 \u5eab\u85cf\u80a1\u7968\u4ea4\u6613": {}
+ }
+ },
+ "33-\u4fdd\u7559\u76c8\u9918(\u7d2f\u7a4d\u8667\u640d)": {
+ "331-\u6cd5\u5b9a\u76c8\u9918\u516c\u7a4d": {
+ "3311-\u6cd5\u5b9a\u76c8\u9918\u516c\u7a4d": {}
+ },
+ "332-\u7279\u5225\u76c8\u9918\u516c\u7a4d": {
+ "3321-\u610f\u5916\u640d\u5931\u6e96\u5099": {},
+ "3322-\u6539\u826f\u64f4\u5145\u6e96\u5099": {},
+ "3323-\u511f\u50b5\u6e96\u5099": {},
+ "3328-\u5176\u4ed6\u7279\u5225\u76c8\u9918\u516c\u7a4d": {}
+ },
+ "335-\u672a\u5206\u914d\u76c8\u9918(\u7d2f\u7a4d\u8667\u640d) ": {
+ "is_group": 1
+ }
+ },
+ "34-\u6b0a\u76ca\u8abf\u6574": {
+ "341-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {
+ "3411-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {}
+ },
+ "342-\u7d2f\u7a4d\u63db\u7b97\u8abf\u6574\u6578": {
+ "3421-\u7d2f\u7a4d\u63db\u7b97\u8abf\u6574\u6578": {}
+ },
+ "343-\u672a\u8a8d\u5217\u70ba\u9000\u4f11\u91d1\u6210\u672c\u4e4b\u6de8\u640d\u5931": {
+ "3431-\u672a\u8a8d\u5217\u70ba\u9000\u4f11\u91d1\u6210\u672c\u4e4b\u6de8\u640d\u5931": {}
+ }
+ },
+ "35-\u5eab\u85cf\u80a1": {
+ "351-\u5eab\u85cf\u80a1": {
+ "3511-\u5eab\u85cf\u80a1": {}
+ }
+ },
+ "36-\u5c11\u6578\u80a1\u6b0a": {
+ "361-\u5c11\u6578\u80a1\u6b0a": {
+ "3611-\u5c11\u6578\u80a1\u6b0a": {}
+ }
+ },
+ "root_type": "Equity"
+ },
+ "4-\u71df\u696d\u6536\u5165": {
+ "41-\u92b7\u8ca8\u6536\u5165": {
+ "411-\u92b7\u8ca8\u6536\u5165": {
+ "4111-\u92b7\u8ca8\u6536\u5165": {},
+ "4112-\u5206\u671f\u4ed8\u6b3e\u92b7\u8ca8\u6536\u5165": {}
+ },
+ "417-\u92b7\u8ca8\u9000\u56de": {
+ "4171-\u92b7\u8ca8\u9000\u56de": {}
+ },
+ "419-\u92b7\u8ca8\u6298\u8b93": {
+ "4191-\u92b7\u8ca8\u6298\u8b93": {}
+ }
+ },
+ "46-\u52de\u52d9\u6536\u5165": {
+ "461-\u52de\u52d9\u6536\u5165": {
+ "4611-\u52de\u52d9\u6536\u5165": {}
+ }
+ },
+ "47-\u696d\u52d9\u6536\u5165": {
+ "471-\u696d\u52d9\u6536\u5165": {
+ "4711-\u696d\u52d9\u6536\u5165": {}
+ }
+ },
+ "48-\u5176\u4ed6\u71df\u696d\u6536\u5165": {
+ "488-\u5176\u4ed6\u71df\u696d\u6536\u5165\u2014\u5176\u4ed6": {
+ "4888-\u5176\u4ed6\u71df\u696d\u6536\u5165\u2014\u5176\u4ed6": {}
+ }
+ },
+ "root_type": "Income"
+ },
+ "5-\u71df\u696d\u6210\u672c": {
+ "51-\u92b7\u8ca8\u6210\u672c": {
+ "511-\u92b7\u8ca8\u6210\u672c": {
+ "5111-\u92b7\u8ca8\u6210\u672c": {
+ "account_type": "Cost of Goods Sold"
+ },
+ "5112-\u5206\u671f\u4ed8\u6b3e\u92b7\u8ca8\u6210\u672c": {
+ "account_type": "Cost of Goods Sold"
+ },
+ "account_type": "Cost of Goods Sold"
+ },
+ "512-\u9032\u8ca8": {
+ "5121-\u9032\u8ca8": {},
+ "5122-\u9032\u8ca8\u8cbb\u7528": {},
+ "5123-\u9032\u8ca8\u9000\u51fa": {},
+ "5124-\u9032\u8ca8\u6298\u8b93": {}
+ },
+ "513-\u9032\u6599": {
+ "5131-\u9032\u6599": {},
+ "5132-\u9032\u6599\u8cbb\u7528": {},
+ "5133-\u9032\u6599\u9000\u51fa": {},
+ "5134-\u9032\u6599\u6298\u8b93": {}
+ },
+ "514-\u76f4\u63a5\u4eba\u5de5": {
+ "5141-\u76f4\u63a5\u4eba\u5de5": {}
+ },
+ "515~518-\u88fd\u9020\u8cbb\u7528": {
+ "5151-\u9593\u63a5\u4eba\u5de5": {},
+ "5152-\u79df\u91d1\u652f\u51fa": {},
+ "5153-\u6587\u5177\u7528\u54c1": {},
+ "5154-\u65c5\u8cbb": {},
+ "5155-\u904b\u8cbb": {},
+ "5156-\u90f5\u96fb\u8cbb": {},
+ "5157-\u4fee\u7e55\u8cbb": {},
+ "5158-\u5305\u88dd\u8cbb": {},
+ "5161-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
+ "5162-\u4fdd\u96aa\u8cbb": {},
+ "5163-\u52a0\u5de5\u8cbb": {},
+ "5166-\u7a05\u6350": {
+ "account_type": "Tax",
+ "tax_rate": 5.0
+ },
+ "5168-\u6298\u820a ": {
+ "account_type": "Depreciation"
+ },
+ "5169-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
+ "5172-\u4f19\u98df\u8cbb": {},
+ "5173-\u8077\u5de5\u798f\u5229": {},
+ "5176-\u8a13\u7df4\u8cbb": {},
+ "5177-\u9593\u63a5\u6750\u6599": {},
+ "5188-\u5176\u4ed6\u88fd\u9020\u8cbb\u7528": {}
+ },
+ "Expenses Included In Valuation": {
+ "account_type": "Expenses Included In Valuation"
+ },
+ "account_type": "Cost of Goods Sold"
+ },
+ "56-\u52de\u52d9\u6210\u672c\u88fd": {
+ "561-\u52de\u52d9\u6210\u672c": {
+ "5611-\u52de\u52d9\u6210\u672c": {}
+ }
+ },
+ "57-\u696d\u52d9\u6210\u672c": {
+ "571-\u696d\u52d9\u6210\u672c": {
+ "5711-\u696d\u52d9\u6210\u672c": {}
+ }
+ },
+ "58-\u5176\u4ed6\u71df\u696d\u6210\u672c": {
+ "588-\u5176\u4ed6\u71df\u696d\u6210\u672c\u2014\u5176\u4ed6 ": {
+ "5888-\u5176\u4ed6\u71df\u696d\u6210\u672c\u2014\u5176\u4ed6": {}
+ }
+ },
+ "Stock Adjustment": {
+ "account_type": "Stock Adjustment"
+ },
+ "root_type": "Expense"
+ },
+ "6-\u71df\u696d\u8cbb\u7528": {
+ "61-\u63a8\u92b7\u8cbb\u7528": {
+ "615~618-\u63a8\u92b7\u8cbb\u7528": {
+ "6151-\u85aa\u8cc7\u652f\u51fa": {},
+ "6152-\u79df\u91d1\u652f\u51fa": {},
+ "6153-\u6587\u5177\u7528\u54c1": {},
+ "6154-\u65c5\u8cbb": {},
+ "6155-\u904b\u8cbb": {},
+ "6156-\u90f5\u96fb\u8cbb": {},
+ "6157-\u4fee\u7e55\u8cbb": {},
+ "6159-\u5ee3\u544a\u8cbb": {},
+ "6161-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
+ "6162-\u4fdd\u96aa\u8cbb": {},
+ "6164-\u4ea4\u969b\u8cbb": {},
+ "6165-\u6350\u8d08": {},
+ "6166-\u7a05\u6350": {
+ "account_type": "Tax",
+ "tax_rate": 5.0
+ },
+ "6167-\u5446\u5e33\u640d\u5931": {},
+ "6168-\u6298\u820a ": {
+ "account_type": "Depreciation"
+ },
+ "6169-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
+ "6172-\u4f19\u98df\u8cbb": {},
+ "6173-\u8077\u5de5\u798f\u5229": {},
+ "6175-\u4f63\u91d1\u652f\u51fa": {},
+ "6176-\u8a13\u7df4\u8cbb": {},
+ "6188-\u5176\u4ed6\u63a8\u92b7\u8cbb\u7528": {}
+ }
+ },
+ "62-\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": {
+ "625~628-\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": {
+ "6251-\u85aa\u8cc7\u652f\u51fa": {},
+ "6252-\u79df\u91d1\u652f\u51fa": {},
+ "6253-\u6587\u5177\u7528\u54c1": {},
+ "6254-\u65c5\u8cbb": {},
+ "6255-\u904b\u8cbb": {},
+ "6256-\u90f5\u96fb\u8cbb": {},
+ "6257-\u4fee\u7e55\u8cbb": {},
+ "6259-\u5ee3\u544a\u8cbb": {},
+ "6261-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
+ "6262-\u4fdd\u96aa\u8cbb": {},
+ "6264-\u4ea4\u969b\u8cbb": {},
+ "6265-\u6350\u8d08": {},
+ "6266-\u7a05\u6350": {
+ "account_type": "Tax",
+ "tax_rate": 5.0
+ },
+ "6267-\u5446\u5e33\u640d\u5931": {},
+ "6268-\u6298\u820a": {
+ "account_type": "Depreciation"
+ },
+ "6269-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
+ "6271-\u5916\u92b7\u640d\u5931": {},
+ "6272-\u4f19\u98df\u8cbb": {},
+ "6273-\u8077\u5de5\u798f\u5229": {},
+ "6274-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {},
+ "6275-\u4f63\u91d1\u652f\u51fa": {},
+ "6276-\u8a13\u7df4\u8cbb": {},
+ "6278-\u52de\u52d9\u8cbb": {},
+ "6288-\u5176\u4ed6\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": {}
+ }
+ },
+ "63-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {
+ "635~638-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {
+ "6351-\u85aa\u8cc7\u652f\u51fa": {},
+ "6352-\u79df\u91d1\u652f\u51fa": {},
+ "6353-\u6587\u5177\u7528\u54c1": {},
+ "6354-\u65c5\u8cbb": {},
+ "6355-\u904b\u8cbb": {},
+ "6356-\u90f5\u96fb\u8cbb": {},
+ "6357-\u4fee\u7e55\u8cbb": {},
+ "6361-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
+ "6362-\u4fdd\u96aa\u8cbb": {},
+ "6364-\u4ea4\u969b\u8cbb": {},
+ "6366-\u7a05\u6350": {
+ "account_type": "Tax",
+ "tax_rate": 5.0
+ },
+ "6368-\u6298\u820a": {
+ "account_type": "Depreciation"
+ },
+ "6369-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
+ "6372-\u4f19\u98df\u8cbb": {},
+ "6373-\u8077\u5de5\u798f\u5229": {},
+ "6376-\u8a13\u7df4\u8cbb": {},
+ "6378-\u5176\u4ed6\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {}
+ }
+ },
+ "root_type": "Expense"
+ },
+ "7-\u71df\u696d\u5916\u6536\u5165\u53ca\u8cbb\u7528": {
+ "71~74-\u71df\u696d\u5916\u6536\u5165": {
+ "711-\u5229\u606f\u6536\u5165": {
+ "7111-\u5229\u606f\u6536\u5165": {}
+ },
+ "712-\u6295\u8cc7\u6536\u76ca": {
+ "7121-\u6b0a\u76ca\u6cd5\u8a8d\u5217\u4e4b\u6295\u8cc7\u6536\u76ca": {},
+ "7122-\u80a1\u5229\u6536\u5165": {},
+ "7123-\u77ed\u671f\u6295\u8cc7\u5e02\u50f9\u56de\u5347\u5229\u76ca": {}
+ },
+ "713-\u514c\u63db\u5229\u76ca": {
+ "7131-\u514c\u63db\u5229\u76ca": {}
+ },
+ "714-\u8655\u5206\u6295\u8cc7\u6536\u76ca": {
+ "7141-\u8655\u5206\u6295\u8cc7\u6536\u76ca": {}
+ },
+ "715-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u6536\u5165": {
+ "7151-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u6536\u5165": {}
+ },
+ "748-\u5176\u4ed6\u71df\u696d\u5916\u6536\u5165": {
+ "7481-\u6350\u8d08\u6536\u5165": {},
+ "7482-\u79df\u91d1\u6536\u5165": {},
+ "7483-\u4f63\u91d1\u6536\u5165": {},
+ "7484-\u51fa\u552e\u4e0b\u8173\u53ca\u5ee2\u6599\u6536\u5165": {},
+ "7485-\u5b58\u8ca8\u76e4\u76c8": {},
+ "7486-\u5b58\u8ca8\u8dcc\u50f9\u56de\u5347\u5229\u76ca": {},
+ "7487-\u58de\u5e33\u8f49\u56de\u5229\u76ca": {},
+ "7488-\u5176\u4ed6\u71df\u696d\u5916\u6536\u5165\u2014\u5176\u4ed6": {}
+ }
+ },
+ "75~78-\u71df\u696d\u5916\u8cbb\u7528": {
+ "751-\u5229\u606f\u8cbb\u7528": {
+ "7511-\u5229\u606f\u8cbb\u7528": {}
+ },
+ "752-\u6295\u8cc7\u640d\u5931": {
+ "7521-\u6b0a\u76ca\u6cd5\u8a8d\u5217\u4e4b\u6295\u8cc7\u640d\u5931": {},
+ "7523-\u77ed\u671f\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {}
+ },
+ "753-\u514c\u63db\u640d\u5931": {
+ "7531-\u514c\u63db\u640d\u5931": {}
+ },
+ "754-\u8655\u5206\u6295\u8cc7\u640d\u5931": {
+ "7541-\u8655\u5206\u6295\u8cc7\u640d\u5931": {}
+ },
+ "755-\u8655\u5206\u8cc7\u7522\u640d\u5931": {
+ "7551-\u8655\u5206\u8cc7\u7522\u640d\u5931 ": {}
+ },
+ "788-\u5176\u4ed6\u71df\u696d\u5916\u8cbb\u7528": {
+ "7881-\u505c\u5de5\u640d\u5931": {},
+ "7882-\u707d\u5bb3\u640d\u5931": {},
+ "7885-\u5b58\u8ca8\u76e4\u640d": {},
+ "7886-\u5b58\u8ca8\u8dcc\u50f9\u53ca\u5446\u6eef\u640d\u5931": {},
+ "7888-\u5176\u4ed6\u71df\u696d\u5916\u8cbb\u7528\u2014\u5176\u4ed6": {}
+ }
+ },
+ "root_type": "Income"
+ },
+ "8-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca)": {
+ "81-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca)": {
+ "811-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca) ": {
+ "8111-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca) ": {}
+ }
+ },
+ "root_type": "Expense"
+ },
+ "9-\u975e\u7d93\u5e38\u71df\u696d\u640d\u76ca": {
+ "91-\u505c\u696d\u90e8\u9580\u640d\u76ca": {
+ "911-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u505c\u696d\u524d\u71df\u696d\u640d\u76ca": {
+ "9111-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u505c\u696d\u524d\u71df\u696d\u640d\u76ca": {}
+ },
+ "912-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u8655\u5206\u640d\u76ca": {
+ "9121-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u8655\u5206\u640d\u76ca": {}
+ }
+ },
+ "92-\u975e\u5e38\u640d\u76ca": {
+ "921-\u975e\u5e38\u640d\u76ca": {
+ "9211-\u975e\u5e38\u640d\u76ca": {}
+ }
+ },
+ "93-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": {
+ "931-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": {
+ "9311-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": {}
+ }
+ },
+ "94-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": {
+ "941-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": {
+ "9411-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": {}
+ }
+ },
+ "root_type": "Expense"
+ }
+ }
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js
new file mode 100644
index 0000000000..6e33e1d7f2
--- /dev/null
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js
@@ -0,0 +1,43 @@
+QUnit.module('Purchaes Invoice');
+
+QUnit.test("test purchase invoice", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Invoice', [
+ {supplier: 'Test Supplier'},
+ {items: [
+ [
+ {'qty': 5},
+ {'item_code': 'Test Product 1'},
+ {'rate':100},
+ ]
+ ]},
+ {update_stock:1},
+ {supplier_address: 'Test1-Billing'},
+ {contact_person: 'Contact 3-Test Supplier'},
+ {taxes_and_charges: 'TEST In State GST'},
+ {tc_name: 'Test Term 1'},
+ {terms: 'This is Test'}
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
+ // get tax details
+ assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
+ // get tax account head details
+ assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
+ // grand_total Calculated
+ assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
+
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js
new file mode 100644
index 0000000000..5e357ca2ad
--- /dev/null
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js
@@ -0,0 +1,26 @@
+QUnit.module('Sales Taxes and Charges Template');
+
+QUnit.test("test sales taxes and charges template", function(assert) {
+ assert.expect(1);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Taxes and Charges Template', [
+ {title: "TEST In State GST"},
+ {taxes:[
+ [
+ {charge_type:"On Net Total"},
+ {account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
+ ],
+ [
+ {charge_type:"On Net Total"},
+ {account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
+ ]
+ ]}
+ ]);
+ },
+ () => {assert.ok(cur_frm.doc.title=='TEST In State GST');},
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js
new file mode 100644
index 0000000000..35b255875e
--- /dev/null
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js
@@ -0,0 +1,43 @@
+QUnit.module('Sales Invoice');
+
+QUnit.test("test sales Invoice", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Sales Invoice', [
+ {customer: 'Test Customer 1'},
+ {items: [
+ [
+ {'qty': 5},
+ {'item_code': 'Test Product 1'},
+ ]
+ ]},
+ {update_stock:1},
+ {customer_address: 'Test1-Billing'},
+ {shipping_address_name: 'Test1-Shipping'},
+ {contact_person: 'Contact 1-Test Customer 1'},
+ {taxes_and_charges: 'TEST In State GST'},
+ {tc_name: 'Test Term 1'},
+ {terms: 'This is Test'}
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
+ // get tax details
+ assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
+ // get tax account head details
+ assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
+ // grand_total Calculated
+ assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
+
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js
new file mode 100644
index 0000000000..35b255875e
--- /dev/null
+++ b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js
@@ -0,0 +1,43 @@
+QUnit.module('Sales Invoice');
+
+QUnit.test("test sales Invoice", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Sales Invoice', [
+ {customer: 'Test Customer 1'},
+ {items: [
+ [
+ {'qty': 5},
+ {'item_code': 'Test Product 1'},
+ ]
+ ]},
+ {update_stock:1},
+ {customer_address: 'Test1-Billing'},
+ {shipping_address_name: 'Test1-Shipping'},
+ {contact_person: 'Contact 1-Test Customer 1'},
+ {taxes_and_charges: 'TEST In State GST'},
+ {tc_name: 'Test Term 1'},
+ {terms: 'This is Test'}
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
+ // get tax details
+ assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
+ // get tax account head details
+ assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
+ // grand_total Calculated
+ assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
+
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js
new file mode 100644
index 0000000000..736443e260
--- /dev/null
+++ b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js
@@ -0,0 +1,56 @@
+QUnit.module('Sales Invoice');
+
+QUnit.test("test sales Invoice with payment", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Sales Invoice', [
+ {customer: 'Test Customer 1'},
+ {items: [
+ [
+ {'qty': 5},
+ {'item_code': 'Test Product 1'},
+ ]
+ ]},
+ {update_stock:1},
+ {customer_address: 'Test1-Billing'},
+ {shipping_address_name: 'Test1-Shipping'},
+ {contact_person: 'Contact 1-Test Customer 1'},
+ {taxes_and_charges: 'TEST In State GST'},
+ {tc_name: 'Test Term 1'},
+ {terms: 'This is Test'}
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
+ // get tax details
+ assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
+ // grand_total Calculated
+ assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
+
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(2),
+ () => frappe.tests.click_button('Close'),
+ () => frappe.tests.click_button('Make'),
+ () => frappe.tests.click_link('Payment'),
+ () => frappe.timeout(0.2),
+ () => { cur_frm.set_value('mode_of_payment','Cash');},
+ () => { cur_frm.set_value('paid_to','Cash - '+frappe.get_abbr(frappe.defaults.get_default('Company')));},
+ () => {cur_frm.set_value('reference_no','TEST1234');},
+ () => {cur_frm.set_value('reference_date',frappe.datetime.add_days(frappe.datetime.nowdate(), 0));},
+ () => cur_frm.save(),
+ () => {
+ // get payment details
+ assert.ok(cur_frm.doc.paid_amount==590, "Paid Amount Correct");
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/accounts/page/pos/test_pos.js b/erpnext/accounts/page/pos/test_pos.js
index 62c6e31eb5..bc5edc9f2a 100644
--- a/erpnext/accounts/page/pos/test_pos.js
+++ b/erpnext/accounts/page/pos/test_pos.js
@@ -6,11 +6,11 @@ QUnit.test("test:POS Profile", function(assert) {
() => {
return frappe.tests.make("POS Profile", [
{naming_series: "SINV"},
- {company: "_Test Company"},
+ {company: "Test Company"},
{country: "India"},
{currency: "INR"},
- {write_off_account: "Write Off - _TC"},
- {write_off_cost_center: "Main - _TC"},
+ {write_off_account: "Write Off - TC"},
+ {write_off_cost_center: "Main - TC"},
{payments: [
[
{"default": 1},
@@ -35,15 +35,16 @@ QUnit.test("test:Sales Invoice", function(assert) {
frappe.run_serially([
() => {
return frappe.tests.make("Sales Invoice", [
- {customer: "_Test Customer 2"},
- {company: "_Test Company"},
+ {customer: "Test Customer 2"},
+ {company: "Test Company"},
{is_pos: 1},
{posting_date: frappe.datetime.get_today()},
{due_date: frappe.datetime.get_today()},
{items: [
[
- {"item_code": "_Test Item"},
- {"qty": 5}
+ {"item_code": "Test Product 1"},
+ {"qty": 5},
+ {"warehouse":'Stores - TC'}
]]
}
]);
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
index 8d33524abb..46ed9dab39 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
@@ -7,7 +7,7 @@ frappe.query_reports["Item-wise Purchase Register"] = {
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
- "default": frappe.defaults.get_user_default("year_start_date"),
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
index 65cec518fe..b57a7fce9d 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
@@ -7,7 +7,7 @@ frappe.query_reports["Item-wise Sales Register"] = frappe.query_reports["Sales R
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
- "default": frappe.defaults.get_default("year_start_date"),
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.js b/erpnext/accounts/report/purchase_register/purchase_register.js
index cd795310da..42b35c2a99 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.js
+++ b/erpnext/accounts/report/purchase_register/purchase_register.js
@@ -7,7 +7,7 @@ frappe.query_reports["Purchase Register"] = {
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
- "default": frappe.defaults.get_user_default("year_start_date"),
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{
diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js
index 2ac4ae8b2a..0495976cf1 100644
--- a/erpnext/accounts/report/sales_register/sales_register.js
+++ b/erpnext/accounts/report/sales_register/sales_register.js
@@ -7,7 +7,7 @@ frappe.query_reports["Sales Register"] = {
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
- "default": frappe.defaults.get_default("year_start_date"),
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
new file mode 100644
index 0000000000..e6529e60db
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
@@ -0,0 +1,65 @@
+QUnit.module('Buying');
+
+QUnit.test("test: purchase order", function(assert) {
+ assert.expect(11);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Order', [
+ {supplier: 'Test Supplier'},
+ {is_subcontracted: 'No'},
+ {currency: 'INR'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+ {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"rate": 100},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]},
+
+ {tc_name: 'Test Term 1'},
+ {terms: 'This is a term.'}
+ ]);
+ },
+
+ () => {
+ // Get supplier details
+ assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
+ assert.ok($('div.control-value.like-disabled-input.for-description').text().includes('Contact 3'), "Contact display correct");
+ assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Contact email correct");
+ // Get item details
+ assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct");
+ assert.ok(cur_frm.doc.items[0].description == 'Test Product 4', "Description correct");
+ assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct");
+ // Calculate total
+ assert.ok(cur_frm.doc.total == 500, "Total correct");
+ // Get terms
+ assert.ok(cur_frm.doc.terms == 'This is a term.', "Terms correct");
+ },
+
+ () => cur_frm.print_doc(),
+ () => frappe.timeout(2),
+ () => {
+ assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
+ assert.ok($('div > div:nth-child(5) > div > div > table > tbody > tr > td:nth-child(4) > div').text().includes('Test Product 4'), "Print Preview Works");
+ },
+
+ () => cur_frm.print_doc(),
+ () => frappe.timeout(1),
+
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+
+ () => {
+ assert.ok(cur_frm.doc.status == 'To Receive and Bill', "Submitted successfully");
+ },
+
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js
new file mode 100644
index 0000000000..8c0c144314
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js
@@ -0,0 +1,61 @@
+QUnit.module('Buying');
+
+QUnit.test("test: purchase order with get items", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Order', [
+ {supplier: 'Test Supplier'},
+ {is_subcontracted: 'No'},
+ {buying_price_list: 'Test-Buying-USD'},
+ {currency: 'USD'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+ {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]}
+ ]);
+ },
+
+ () => {
+ assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
+ },
+
+ () => frappe.timeout(0.3),
+ () => frappe.click_button('Get items from'),
+ () => frappe.timeout(0.3),
+
+ () => frappe.click_link('Product Bundle'),
+ () => frappe.timeout(0.5),
+
+ () => cur_dialog.set_value('product_bundle', 'Computer'),
+ () => frappe.click_button('Get Items'),
+ () => frappe.timeout(1),
+
+ // Check if items are fetched from Product Bundle
+ () => {
+ assert.ok(cur_frm.doc.items[1].item_name == 'CPU', "Product bundle item 1 correct");
+ assert.ok(cur_frm.doc.items[2].item_name == 'Screen', "Product bundle item 2 correct");
+ assert.ok(cur_frm.doc.items[3].item_name == 'Keyboard', "Product bundle item 3 correct");
+ },
+
+ () => cur_frm.doc.items[1].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
+ () => cur_frm.doc.items[2].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
+ () => cur_frm.doc.items[3].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
+
+ () => cur_frm.save(),
+ () => frappe.timeout(1),
+
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js
new file mode 100644
index 0000000000..daf8d6c259
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js
@@ -0,0 +1,74 @@
+QUnit.module('Buying');
+
+QUnit.test("test: purchase order receipt", function(assert) {
+ assert.expect(5);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Order', [
+ {supplier: 'Test Supplier'},
+ {is_subcontracted: 'No'},
+ {buying_price_list: 'Test-Buying-USD'},
+ {currency: 'USD'},
+ {items: [
+ [
+ {"item_code": 'Test Product 1'},
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+ {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"rate": 100},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]},
+ ]);
+ },
+
+ () => {
+
+ // Check supplier and item details
+ assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
+ assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 1', "Item name correct");
+ assert.ok(cur_frm.doc.items[0].description == 'Test Product 1', "Description correct");
+ assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct");
+
+ },
+
+ () => frappe.timeout(1),
+
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+
+ () => frappe.timeout(1.5),
+ () => frappe.click_button('Close'),
+ () => frappe.timeout(0.3),
+
+ // Make Purchase Receipt
+ () => frappe.click_button('Make'),
+ () => frappe.timeout(0.3),
+
+ () => frappe.click_link('Receipt'),
+ () => frappe.timeout(2),
+
+ () => cur_frm.save(),
+
+ // Save and submit Purchase Receipt
+ () => frappe.timeout(1),
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(1),
+
+ // View Purchase order in Stock Ledger
+ () => frappe.click_button('View'),
+ () => frappe.timeout(0.3),
+
+ () => frappe.click_link('Stock Ledger'),
+ () => frappe.timeout(2),
+ () => {
+ assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1')
+ && $('div.slick-cell.l9.r9 > div').text().includes(5), "Stock ledger entry correct");
+ },
+ () => done()
+ ]);
+});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js
new file mode 100644
index 0000000000..4e73ab8ef4
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js
@@ -0,0 +1,47 @@
+QUnit.module('Buying');
+
+QUnit.test("test: purchase order with discount on grand total", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Order', [
+ {supplier: 'Test Supplier'},
+ {is_subcontracted: 'No'},
+ {buying_price_list: 'Test-Buying-EUR'},
+ {currency: 'EUR'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"rate": 500 },
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+ {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]},
+ {apply_discount_on: 'Grand Total'},
+ {additional_discount_percentage: 10}
+ ]);
+ },
+
+ () => frappe.timeout(1),
+
+ () => {
+ assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
+ assert.ok(cur_frm.doc.items[0].rate == 500, "Rate correct");
+ // Calculate total
+ assert.ok(cur_frm.doc.total == 2500, "Total correct");
+ // Calculate grand total after discount
+ assert.ok(cur_frm.doc.grand_total == 2250, "Grand total correct");
+ },
+
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js
new file mode 100644
index 0000000000..1e54e50dda
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js
@@ -0,0 +1,44 @@
+QUnit.module('Buying');
+
+QUnit.test("test: purchase order with item wise discount", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Order', [
+ {supplier: 'Test Supplier'},
+ {is_subcontracted: 'No'},
+ {buying_price_list: 'Test-Buying-EUR'},
+ {currency: 'EUR'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+ {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))},
+ {"discount_percentage": 20}
+ ]
+ ]}
+ ]);
+ },
+
+ () => frappe.timeout(1),
+
+ () => {
+ assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
+ assert.ok(cur_frm.doc.items[0].discount_percentage == 20, "Discount correct");
+ // Calculate totals after discount
+ assert.ok(cur_frm.doc.total == 2000, "Total correct");
+ assert.ok(cur_frm.doc.grand_total == 2000, "Grand total correct");
+ },
+
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js
new file mode 100644
index 0000000000..bf2dfeb37b
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js
@@ -0,0 +1,39 @@
+QUnit.module('Buying');
+
+QUnit.test("test: purchase order with multi UOM", function(assert) {
+ assert.expect(3);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Order', [
+ {supplier: 'Test Supplier'},
+ {is_subcontracted: 'No'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"rate": 100},
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+ {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]}
+ ]);
+ },
+
+ () => {
+ assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
+ assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct");
+ assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi UOM correct");
+ },
+
+ () => frappe.timeout(1),
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js
new file mode 100644
index 0000000000..9d87af2342
--- /dev/null
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js
@@ -0,0 +1,43 @@
+QUnit.module('Buying');
+
+QUnit.test("test: purchase order with taxes and charges", function(assert) {
+ assert.expect(3);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Purchase Order', [
+ {supplier: 'Test Supplier'},
+ {is_subcontracted: 'No'},
+ {buying_price_list: 'Test-Buying-USD'},
+ {currency: 'USD'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"rate": 500 },
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+ {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]},
+
+ {taxes_and_charges: 'TEST In State GST'}
+ ]);
+ },
+
+ () => {
+ // Check taxes and calculate grand total
+ assert.ok(cur_frm.doc.taxes[1].account_head=='SGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), "Account Head abbr correct");
+ assert.ok(cur_frm.doc.total_taxes_and_charges == 225, "Taxes and charges correct");
+ assert.ok(cur_frm.doc.grand_total == 2725, "Grand total correct");
+ },
+
+ () => frappe.timeout(0.3),
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index 558e072cad..8509d77e20 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -138,7 +138,6 @@ frappe.ui.form.on("Request for Quotation",{
dialog.show();
},
-
make_suppplier_quotation: function(frm) {
var doc = frm.doc;
var dialog = new frappe.ui.Dialog({
@@ -207,6 +206,29 @@ frappe.ui.form.on("Request for Quotation Supplier",{
if(!w) {
frappe.msgprint(__("Please enable pop-ups")); return;
}
+ },
+ no_quote: function(frm, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ if (d.no_quote) {
+ if (d.quote_status != __('Received')) {
+ frappe.model.set_value(cdt, cdn, 'quote_status', 'No Quote');
+ } else {
+ frappe.msgprint(__("Cannot set a received RFQ to No Quote"));
+ frappe.model.set_value(cdt, cdn, 'no_quote', 0);
+ }
+ } else {
+ d.quote_status = __('Pending');
+ frm.call({
+ method:"update_rfq_supplier_status",
+ doc: frm.doc,
+ args: {
+ sup_name: d.supplier
+ },
+ callback: function(r) {
+ frm.refresh_field("suppliers");
+ }
+ });
+ }
}
})
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index e9603fbcae..a775f5f345 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -54,6 +54,7 @@ class RequestforQuotation(BuyingController):
frappe.db.set(self, 'status', 'Submitted')
for supplier in self.suppliers:
supplier.email_sent = 0
+ supplier.quote_status = 'Pending'
def on_cancel(self):
frappe.db.set(self, 'status', 'Cancelled')
@@ -157,6 +158,28 @@ class RequestforQuotation(BuyingController):
attachments.append(frappe.attach_print(self.doctype, self.name, doc=self))
return attachments
+ def update_rfq_supplier_status(self, sup_name=None):
+ for supplier in self.suppliers:
+ if sup_name == None or supplier.supplier == sup_name:
+ if supplier.quote_status != _('No Quote'):
+ quote_status = _('Received')
+ for item in self.items:
+ sqi_count = frappe.db.sql("""
+ SELECT
+ COUNT(sqi.name) as count
+ FROM
+ `tabSupplier Quotation Item` as sqi,
+ `tabSupplier Quotation` as sq
+ WHERE sq.supplier = %(supplier)s
+ AND sqi.docstatus = 1
+ AND sqi.request_for_quotation_item = %(rqi)s
+ AND sqi.parent = sq.name""",
+ {"supplier": supplier.supplier, "rqi": item.name}, as_dict=1)[0]
+ if (sqi_count.count) == 0:
+ quote_status = _('Pending')
+ supplier.quote_status = quote_status
+
+
@frappe.whitelist()
def send_supplier_emails(rfq_name):
check_portal_enabled('Request for Quotation')
@@ -172,7 +195,12 @@ def check_portal_enabled(reference_doctype):
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)
- list_context["show_sidebar"] = True
+ list_context.update({
+ 'show_sidebar': True,
+ 'show_search': True,
+ 'no_breadcrumbs': True,
+ 'title': _('Request for Quotation'),
+ })
return list_context
def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
index 2e8b946f9d..5c9fb13209 100644
--- a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
@@ -10,21 +10,41 @@ from erpnext.templates.pages.rfq import check_supplier_has_docname_access
from frappe.utils import nowdate
class TestRequestforQuotation(unittest.TestCase):
+ def test_quote_status(self):
+ from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
+ rfq = make_request_for_quotation()
+
+ self.assertEquals(rfq.get('suppliers')[0].quote_status, 'Pending')
+ self.assertEquals(rfq.get('suppliers')[1].quote_status, 'Pending')
+
+ # Submit the first supplier quotation
+ sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
+ sq.submit()
+
+ # No Quote first supplier quotation
+ rfq.get('suppliers')[1].no_quote = 1
+ rfq.get('suppliers')[1].quote_status = 'No Quote'
+
+ rfq.update_rfq_supplier_status() #rfq.get('suppliers')[1].supplier)
+
+ self.assertEquals(rfq.get('suppliers')[0].quote_status, 'Received')
+ self.assertEquals(rfq.get('suppliers')[1].quote_status, 'No Quote')
+
def test_make_supplier_quotation(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
rfq = make_request_for_quotation()
-
+
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
sq.submit()
-
+
sq1 = make_supplier_quotation(rfq.name, rfq.get('suppliers')[1].supplier)
sq1.submit()
-
+
self.assertEquals(sq.supplier, rfq.get('suppliers')[0].supplier)
self.assertEquals(sq.get('items')[0].request_for_quotation, rfq.name)
self.assertEquals(sq.get('items')[0].item_code, "_Test Item")
self.assertEquals(sq.get('items')[0].qty, 5)
-
+
self.assertEquals(sq1.supplier, rfq.get('suppliers')[1].supplier)
self.assertEquals(sq1.get('items')[0].request_for_quotation, rfq.name)
self.assertEquals(sq1.get('items')[0].item_code, "_Test Item")
@@ -61,15 +81,15 @@ class TestRequestforQuotation(unittest.TestCase):
rfq.get('items')[0].rate = 100
rfq.supplier = rfq.suppliers[0].supplier
supplier_quotation_name = create_supplier_quotation(rfq)
-
+
supplier_quotation_doc = frappe.get_doc('Supplier Quotation', supplier_quotation_name)
-
+
self.assertEquals(supplier_quotation_doc.supplier, rfq.get('suppliers')[0].supplier)
self.assertEquals(supplier_quotation_doc.get('items')[0].request_for_quotation, rfq.name)
self.assertEquals(supplier_quotation_doc.get('items')[0].item_code, "_Test Item")
self.assertEquals(supplier_quotation_doc.get('items')[0].qty, 5)
self.assertEquals(supplier_quotation_doc.get('items')[0].amount, 500)
-
+
def make_request_for_quotation(supplier_data=None):
"""
@@ -81,10 +101,10 @@ def make_request_for_quotation(supplier_data=None):
rfq.status = 'Draft'
rfq.company = '_Test Company'
rfq.message_for_supplier = 'Please supply the specified items at the best possible rates.'
-
+
for data in supplier_data:
rfq.append('suppliers', data)
-
+
rfq.append("items", {
"item_code": "_Test Item",
"description": "_Test Item",
@@ -93,11 +113,11 @@ def make_request_for_quotation(supplier_data=None):
"warehouse": "_Test Warehouse - _TC",
"schedule_date": nowdate()
})
-
+
rfq.submit()
-
+
return rfq
-
+
def get_supplier_data():
return [{
"supplier": "_Test Supplier",
diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js
new file mode 100644
index 0000000000..46e8d1f2d6
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js
@@ -0,0 +1,75 @@
+QUnit.module('Buying');
+
+QUnit.test("test: request_for_quotation", function(assert) {
+ assert.expect(14);
+ let done = assert.async();
+ let date;
+ frappe.run_serially([
+ () => {
+ date = frappe.datetime.add_days(frappe.datetime.now_date(), 10);
+ return frappe.tests.make('Request for Quotation', [
+ {transaction_date: date},
+ {suppliers: [
+ [
+ {"supplier": 'Test Supplier'},
+ {"email_id": 'test@supplier.com'}
+ ]
+ ]},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(),20)},
+ {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]},
+ {message_for_supplier: 'Please supply the specified items at the best possible rates'},
+ {tc_name: 'Test Term 1'}
+ ]);
+ },
+ () => {
+ assert.ok(cur_frm.doc.transaction_date == date, "Date correct");
+ assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct");
+ assert.ok(cur_frm.doc.suppliers[0].supplier_name == 'Test Supplier', "Supplier name correct");
+ assert.ok(cur_frm.doc.suppliers[0].contact == 'Contact 3-Test Supplier', "Contact correct");
+ assert.ok(cur_frm.doc.suppliers[0].email_id == 'test@supplier.com', "Email id correct");
+ assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item Name correct");
+ assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company")), "Warehouse correct");
+ assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct");
+ assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct");
+ },
+ () => frappe.timeout(0.3),
+ () => cur_frm.print_doc(),
+ () => frappe.timeout(1),
+ () => {
+ assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
+ assert.ok($('.section-break+ .section-break .column-break:nth-child(1) .value').text().includes("Test Product 4"), "Print Preview Works");
+ },
+ () => cur_frm.print_doc(),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Get items from'),
+ () => frappe.timeout(0.3),
+ () => frappe.click_link('Material Request'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Get Items'),
+ () => frappe.timeout(1),
+ () => {
+ assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work");
+ },
+ () => cur_frm.save(),
+ () => frappe.timeout(1),
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(1),
+ () => {
+ assert.ok(cur_frm.doc.docstatus == 1, "Quotation request submitted");
+ },
+ () => frappe.click_button('Send Supplier Emails'),
+ () => frappe.timeout(3),
+ () => {
+ assert.ok($('div.modal.fade.in > div.modal-dialog > div > div.modal-body.ui-front > div.msgprint').text().includes("Email sent to supplier Test Supplier"), "Send emails working");
+ },
+ () => frappe.click_button('Close'),
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js
new file mode 100644
index 0000000000..f831b4f42f
--- /dev/null
+++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js
@@ -0,0 +1,132 @@
+QUnit.module('buying');
+
+QUnit.test("Test: Request for Quotation", function (assert) {
+ assert.expect(5);
+ let done = assert.async();
+ let rfq_name = "";
+
+ frappe.run_serially([
+ // Go to RFQ list
+ () => frappe.set_route("List", "Request for Quotation"),
+ // Create a new RFQ
+ () => frappe.new_doc("Request for Quotation"),
+ () => frappe.timeout(1),
+ () => cur_frm.set_value("transaction_date", "04-04-2017"),
+ () => cur_frm.set_value("company", "_Test Company"),
+ // Add Suppliers
+ () => {
+ cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view();
+ },
+ () => frappe.timeout(1),
+ () => {
+ cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.supplier = "_Test Supplier";
+ frappe.click_check('Send Email');
+ cur_frm.cur_grid.frm.script_manager.trigger('supplier');
+ },
+ () => frappe.timeout(1),
+ () => {
+ cur_frm.cur_grid.toggle_view();
+ },
+ () => frappe.timeout(1),
+ () => frappe.click_button('Add Row',0),
+ () => frappe.timeout(1),
+ () => {
+ cur_frm.fields_dict.suppliers.grid.grid_rows[1].toggle_view();
+ },
+ () => frappe.timeout(1),
+ () => {
+ cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1";
+ frappe.click_check('Send Email');
+ cur_frm.cur_grid.frm.script_manager.trigger('supplier');
+ },
+ () => frappe.timeout(1),
+ () => {
+ cur_frm.cur_grid.toggle_view();
+ },
+ () => frappe.timeout(1),
+ // Add Item
+ () => {
+ cur_frm.fields_dict.items.grid.grid_rows[0].toggle_view();
+ },
+ () => frappe.timeout(1),
+ () => {
+ cur_frm.fields_dict.items.grid.grid_rows[0].doc.item_code = "_Test Item";
+ frappe.set_control('item_code',"_Test Item");
+ frappe.set_control('qty',5);
+ frappe.set_control('schedule_date', "05-05-2017");
+ cur_frm.cur_grid.frm.script_manager.trigger('supplier');
+ },
+ () => frappe.timeout(2),
+ () => {
+ cur_frm.cur_grid.toggle_view();
+ },
+ () => frappe.timeout(2),
+ () => {
+ cur_frm.fields_dict.items.grid.grid_rows[0].doc.warehouse = "_Test Warehouse - _TC";
+ },
+ () => frappe.click_button('Save'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Submit'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Menu'),
+ () => frappe.timeout(1),
+ () => frappe.click_link('Reload'),
+ () => frappe.timeout(1),
+ () => {
+ assert.equal(cur_frm.doc.docstatus, 1);
+ rfq_name = cur_frm.doc.name;
+ assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.quote_status == "Pending");
+ assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Pending");
+ },
+ () => {
+ cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view();
+ },
+ () => frappe.timeout(1),
+ () => {
+ frappe.click_check('No Quote');
+ },
+ () => frappe.timeout(1),
+ () => {
+ cur_frm.cur_grid.toggle_view();
+ },
+ () => frappe.click_button('Update'),
+ () => frappe.timeout(1),
+
+ () => frappe.click_button('Supplier Quotation'),
+ () => frappe.timeout(1),
+ () => frappe.click_link('Make'),
+ () => frappe.timeout(1),
+ () => {
+ frappe.set_control('supplier',"_Test Supplier 1");
+ },
+ () => frappe.timeout(1),
+ () => frappe.click_button('Make Supplier Quotation'),
+ () => frappe.timeout(1),
+ () => cur_frm.set_value("company", "_Test Company"),
+ () => cur_frm.fields_dict.items.grid.grid_rows[0].doc.rate = 4.99,
+ () => frappe.timeout(1),
+ () => frappe.click_button('Save'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Submit'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(1),
+ () => frappe.set_route("List", "Request for Quotation"),
+ () => frappe.timeout(2),
+ () => frappe.set_route("List", "Request for Quotation"),
+ () => frappe.timeout(2),
+ () => frappe.click_link(rfq_name),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Menu'),
+ () => frappe.timeout(1),
+ () => frappe.click_link('Reload'),
+ () => frappe.timeout(1),
+ () => {
+ assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Received");
+ assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.no_quote == 1);
+ },
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json
index a7c5a37683..4babbe92d5 100644
--- a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json
+++ b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json
@@ -137,6 +137,69 @@
"set_only_once": 0,
"unique": 0
},
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.docstatus >= 1 && doc.quote_status != 'Received'",
+ "fieldname": "no_quote",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "No Quote",
+ "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
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.docstatus >= 1 && !doc.no_quote",
+ "fieldname": "quote_status",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Quote Status",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Pending\nReceived\nNo Quote",
+ "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,
+ "unique": 0
+ },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -269,7 +332,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-07-24 06:52:19.542717",
+ "modified": "2017-07-26 22:25:58.096584",
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation Supplier",
diff --git a/erpnext/buying/doctype/supplier/test_supplier.js b/erpnext/buying/doctype/supplier/test_supplier.js
index 6be40a52bf..a953a8dd13 100644
--- a/erpnext/buying/doctype/supplier/test_supplier.js
+++ b/erpnext/buying/doctype/supplier/test_supplier.js
@@ -8,9 +8,8 @@ QUnit.test("test: supplier", function(assert) {
return frappe.tests.make('Supplier', [
{supplier_name: 'Test Supplier'},
{supplier_type: 'Hardware'},
- {country: 'United States'},
- {default_currency: 'USD'},
- {default_price_list: 'Test-Buying-USD'},
+ {country: 'India'},
+ {default_currency: 'INR'},
{credit_days_based_on: 'Fixed Days'},
{accounts: [
[
@@ -68,7 +67,7 @@ QUnit.test("test: supplier", function(assert) {
() => {
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Name correct");
assert.ok(cur_frm.doc.supplier_type == 'Hardware', "Type correct");
- assert.ok(cur_frm.doc.default_currency == 'USD', "Currency correct");
+ assert.ok(cur_frm.doc.default_currency == 'INR', "Currency correct");
assert.ok(cur_frm.doc.accounts[0].account == 'Creditors - '+frappe.get_abbr('Test Company'), " Account Head abbr correct");
assert.ok($('.address-box:nth-child(3) p').text().includes('Shipping City 3'), "Address correct");
assert.ok($('.col-sm-6+ .col-sm-6 .h6').text().includes('Contact 3'), "Contact correct");
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
index 1cb5a18662..b3d92be4b6 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
@@ -31,9 +31,11 @@ class SupplierQuotation(BuyingController):
def on_submit(self):
frappe.db.set(self, "status", "Submitted")
+ self.update_rfq_supplier_status(1)
def on_cancel(self):
frappe.db.set(self, "status", "Cancelled")
+ self.update_rfq_supplier_status(0)
def on_trash(self):
pass
@@ -50,6 +52,41 @@ class SupplierQuotation(BuyingController):
"is_child_table": True
}
})
+ def update_rfq_supplier_status(self, include_me):
+ rfq_list = set([])
+ for item in self.items:
+ if item.request_for_quotation:
+ rfq_list.add(item.request_for_quotation)
+ for rfq in rfq_list:
+ doc = frappe.get_doc('Request for Quotation', rfq)
+ doc_sup = frappe.get_all('Request for Quotation Supplier', filters=
+ {'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])[0]
+
+ quote_status = _('Received')
+ for item in doc.items:
+ sqi_count = frappe.db.sql("""
+ SELECT
+ COUNT(sqi.name) as count
+ FROM
+ `tabSupplier Quotation Item` as sqi,
+ `tabSupplier Quotation` as sq
+ WHERE sq.supplier = %(supplier)s
+ AND sqi.docstatus = 1
+ AND sq.name != %(me)s
+ AND sqi.request_for_quotation_item = %(rqi)s
+ AND sqi.parent = sq.name""",
+ {"supplier": self.supplier, "rqi": item.name, 'me': self.name}, as_dict=1)[0]
+ self_count = sum(my_item.request_for_quotation_item == item.name
+ for my_item in self.items) if include_me else 0
+ if (sqi_count.count + self_count) == 0:
+ quote_status = _('Pending')
+ if quote_status == _('Received') and doc_sup.quote_status == _('No Quote'):
+ frappe.msgprint(_("{0} indicates that {1} will not provide a quotation, but all items \
+ have been quoted. Updating the RFQ quote status.").format(doc.name, self.supplier))
+ frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status)
+ frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'no_quote', 0)
+ elif doc_sup.quote_status != _('No Quote'):
+ frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status)
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js
new file mode 100644
index 0000000000..76be06c6fb
--- /dev/null
+++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js
@@ -0,0 +1,73 @@
+QUnit.module('Buying');
+
+QUnit.test("test: supplier quotation", function(assert) {
+ assert.expect(11);
+ let done = assert.async();
+ let date;
+
+ frappe.run_serially([
+ () => {
+ date = frappe.datetime.add_days(frappe.datetime.now_date(), 10);
+ return frappe.tests.make('Supplier Quotation', [
+ {supplier: 'Test Supplier'},
+ {transaction_date: date},
+ {currency: 'INR'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"rate": 200},
+ {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+ ]
+ ]},
+ {apply_discount_on: 'Grand Total'},
+ {additional_discount_percentage: 10},
+ {tc_name: 'Test Term 1'},
+ {terms: 'This is a term'}
+ ]);
+ },
+ () => {
+ // Get Supplier details
+ assert.ok(cur_frm.doc.supplier == 'Test Supplier', "Supplier correct");
+ assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct");
+ // Get Contact details
+ assert.ok(cur_frm.doc.contact_display == 'Contact 3', "Conatct correct");
+ assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Email correct");
+ // Get uom
+ assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi uom correct");
+ assert.ok(cur_frm.doc.total == 1000, "Total correct");
+ // Calculate total after discount
+ assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct");
+ // Get terms
+ assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Terms correct");
+ },
+
+ () => cur_frm.print_doc(),
+ () => frappe.timeout(2),
+ () => {
+ assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
+ assert.ok($("table > tbody > tr > td:nth-child(3) > div").text().includes("Test Product 4"), "Print Preview Works As Expected");
+ },
+ () => cur_frm.print_doc(),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Get items from'),
+ () => frappe.timeout(0.3),
+ () => frappe.click_link('Material Request'),
+ () => frappe.timeout(0.3),
+ () => frappe.click_button('Get Items'),
+ () => frappe.timeout(1),
+ () => {
+ // Get item from Material Requests
+ assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work");
+ },
+
+ () => cur_frm.save(),
+ () => frappe.timeout(1),
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js
new file mode 100644
index 0000000000..bc07b753b3
--- /dev/null
+++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js
@@ -0,0 +1,34 @@
+QUnit.module('Buying');
+
+QUnit.test("test: supplier quotation with item wise discount", function(assert){
+ assert.expect(2);
+ let done = assert.async();
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Supplier Quotation', [
+ {supplier: 'Test Supplier'},
+ {company: 'Test Company'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"uom": 'Unit'},
+ {"warehouse": 'All Warehouses - TC'},
+ {'discount_percentage': 10},
+ ]
+ ]}
+ ]);
+ },
+
+ () => {
+ assert.ok(cur_frm.doc.total == 900, "Total correct");
+ assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct");
+ },
+
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js
new file mode 100644
index 0000000000..c4b341952c
--- /dev/null
+++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js
@@ -0,0 +1,37 @@
+QUnit.module('Buying');
+
+QUnit.test("test: supplier quotation with taxes and charges", function(assert) {
+ assert.expect(3);
+ let done = assert.async();
+ let supplier_quotation_name;
+
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Supplier Quotation', [
+ {supplier: 'Test Supplier'},
+ {items: [
+ [
+ {"item_code": 'Test Product 4'},
+ {"qty": 5},
+ {"rate": 100},
+ {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ ]
+ ]},
+ {taxes_and_charges:'TEST In State GST'},
+ ]);
+ },
+ () => {supplier_quotation_name = cur_frm.doc.name;},
+ () => {
+ assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
+ assert.ok(cur_frm.doc.total_taxes_and_charges == 45, "Taxes and charges correct");
+ assert.ok(cur_frm.doc.grand_total == 545, "Grand total correct");
+ },
+
+ () => cur_frm.save(),
+ () => frappe.timeout(0.3),
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/config/manufacturing.py b/erpnext/config/manufacturing.py
index a930ddc6ef..11711ad004 100644
--- a/erpnext/config/manufacturing.py
+++ b/erpnext/config/manufacturing.py
@@ -70,8 +70,8 @@ def get_data():
"items": [
{
"type": "doctype",
- "name": "BOM Replace Tool",
- "description": _("Replace Item / BOM in all BOMs"),
+ "name": "BOM Update Tool",
+ "description": _("Replace BOM and update latest price in all BOMs"),
},
]
},
diff --git a/erpnext/docs/assets/img/manufacturing/bom-replace-tool.png b/erpnext/docs/assets/img/manufacturing/bom-replace-tool.png
deleted file mode 100644
index 51ac99324b..0000000000
Binary files a/erpnext/docs/assets/img/manufacturing/bom-replace-tool.png and /dev/null differ
diff --git a/erpnext/docs/assets/img/manufacturing/bom-update-tool.png b/erpnext/docs/assets/img/manufacturing/bom-update-tool.png
new file mode 100644
index 0000000000..7dbd47fe0e
Binary files /dev/null and b/erpnext/docs/assets/img/manufacturing/bom-update-tool.png differ
diff --git a/erpnext/docs/assets/img/setup/print/print-style.png b/erpnext/docs/assets/img/setup/print/print-style.png
new file mode 100644
index 0000000000..db93ceb0e6
Binary files /dev/null and b/erpnext/docs/assets/img/setup/print/print-style.png differ
diff --git a/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md b/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md
index 598aa0e7f6..060cd17d99 100644
--- a/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md
+++ b/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md
@@ -23,6 +23,15 @@ You can change accounting currency in Party / Account record, until making any t
In case of multi-company setup, accounting currency of Party must be same for all the companies.
+### Exchange Rates
+When dealing with multiple currencies, ERPNext has the Currency Exchange module for managing exchange rates. It allows you to save the exchange rate quotes you require.
+
+For foreign currency transactions, ERPNext checks Currency Exchange for any matching record. If this fails, ERPNext will attempt to get the exchange rate quote from [fixer.io](http://fixer.io). If this still fails, then the exchange rate will have to be entered manually.
+
+#### Exchange Rate Selection
+ERPNext automatically fetches the latest exchange rate available.
+
+
## Transactions
### Sales Invoice
@@ -50,61 +59,6 @@ In Accounts table, on selection of foreign currency account, system will show Cu
-#### Example 1: Payment Entry Against Customer With Alternate Currency
-
-Suppose, default currency of the company is INR and customer's accounting currency is USD. Customer made full payment against an outstanding invoice of USD 100. Exchange Rate (USD -> INR) in Sales Invoice was 60.
-
-Exchange Rate in the payment entry should always be same as invoice (60), even if exchange rate on the payment date is 62. The bank account will be credited by the amount considering exchange rate as 62. Hence, Exchnage Gain / Loss will be booked based on exchange rate difference.
-
-
-
-#### Example 2: Inter-bank Transfer (USD -> INR)
-
-Suppose the default currency of the company is INR. You have a Paypal account for which Currency is USD. You receive payments in the paypal account and lets say, paypal transfers amount once in a week to your other bank account which is managed in INR.
-
-Paypal account gets debited on different date with different exchange rate, but on transfer date the exchange rate can be different. Hence, there is generally Exchange Loss / Gain on the transfer entry.
-In the bank transfer entry, system sets exchange rate of the credit account (Paypal) based on the average incoming exchange rate. This is to maintain Paypal balance properly in company currency. In case you modify the average exchange rate, you need to adjust the exchange rate manually in the future entries, so that balance in account currency and company currency are in sync.
-Then you should calculate and enter Exchange Loss / Gain based on the Paypal exchange rate and the exchange rate on the transfer date.
-
-Lets say, Paypal account debited by following amounts over the week, which has not been transferred to your other bank account.
-
-
Date | -Account | -Debit (USD) | -Exchange Rate | -
2015-09-02 | -Paypal | -100 | -60 | -
2015-09-02 | -Paypal | -100 | -61 | -
2015-09-02 | -Paypal | -100 | -64 | -
+ {{ _("Valid Till") }}: {{ frappe.utils.formatdate(doc.valid_till, 'medium') }} +
+ {% endif %}
+{% if doc.doctype == 'Supplier Quotation' %}
+ {{ doc.supplier_name}}
+{% else %}
+ {{ doc.customer_name}}
+{% endif %}
+{% if doc.contact_display %}
+
+ {{ doc.contact_display }}
+{% endif %}
+
{{ _("Delivered: {0}").format(d.delivered_qty) }}
{% endif %}{{ _("@ {0}").format(d.get_formatted("rate")) }}
@@ -72,8 +95,8 @@{{ doc.terms }}
+