Merge pull request #29193 from ruthra-kumar/bug_deferred_report

fix: deferred report division by zero exception
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index 85f146d..9031968 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -12,17 +12,30 @@
 bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
 
 mkdir ~/frappe-bench/sites/test_site
-cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/test_site/
 
-mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
-mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
+if [ "$DB" == "mariadb" ];then
+    cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config_mariadb.json" ~/frappe-bench/sites/test_site/site_config.json
+else
+    cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config_postgres.json" ~/frappe-bench/sites/test_site/site_config.json
+fi
 
-mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
-mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_frappe"
-mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
 
-mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
-mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
+if [ "$DB" == "mariadb" ];then
+    mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
+    mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
+
+    mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
+    mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_frappe"
+    mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
+
+    mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
+    mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
+fi
+
+if [ "$DB" == "postgres" ];then
+    echo "travis" | psql -h 127.0.0.1 -p 5432 -c "CREATE DATABASE test_frappe" -U postgres;
+    echo "travis" | psql -h 127.0.0.1 -p 5432 -c "CREATE USER test_frappe WITH PASSWORD 'test_frappe'" -U postgres;
+fi
 
 wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
 tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
diff --git a/.github/helper/site_config.json b/.github/helper/site_config_mariadb.json
similarity index 99%
rename from .github/helper/site_config.json
rename to .github/helper/site_config_mariadb.json
index 60ef80c..948ad08 100644
--- a/.github/helper/site_config.json
+++ b/.github/helper/site_config_mariadb.json
@@ -13,4 +13,4 @@
  "host_name": "http://test_site:8000",
  "install_apps": ["erpnext"],
  "throttle_user_limit": 100
-}
\ No newline at end of file
+}
diff --git a/.github/helper/site_config.json b/.github/helper/site_config_postgres.json
similarity index 80%
copy from .github/helper/site_config.json
copy to .github/helper/site_config_postgres.json
index 60ef80c..c82905f 100644
--- a/.github/helper/site_config.json
+++ b/.github/helper/site_config_postgres.json
@@ -1,16 +1,18 @@
 {
  "db_host": "127.0.0.1",
- "db_port": 3306,
+ "db_port": 5432,
  "db_name": "test_frappe",
  "db_password": "test_frappe",
+ "db_type": "postgres",
+ "allow_tests": true,
  "auto_email_id": "test@example.com",
  "mail_server": "smtp.example.com",
  "mail_login": "test@example.com",
  "mail_password": "test",
  "admin_password": "admin",
- "root_login": "root",
+ "root_login": "postgres",
  "root_password": "travis",
  "host_name": "http://test_site:8000",
  "install_apps": ["erpnext"],
  "throttle_user_limit": 100
-}
\ No newline at end of file
+}
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 0000000..fc3f06d
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,55 @@
+accounts:
+- 'erpnext/accounts/*'
+- 'erpnext/controllers/accounts_controller.py'
+- 'erpnext/controllers/taxes_and_totals.py'
+
+stock:
+- 'erpnext/stock/*'
+- 'erpnext/controllers/stock_controller.py'
+- 'erpnext/controllers/item_variant.py'
+
+assets:
+- 'erpnext/assets/*'
+
+regional:
+- 'erpnext/regional/*'
+
+selling:
+- 'erpnext/selling/*'
+- 'erpnext/controllers/selling_controller.py'
+
+buying:
+- 'erpnext/buying/*'
+- 'erpnext/controllers/buying_controller.py'
+
+support:
+- 'erpnext/support/*'
+
+POS:
+- 'pos*'
+
+ecommerce:
+- 'erpnext/e_commerce/*'
+
+maintenance:
+- 'erpnext/maintenance/*'
+
+manufacturing:
+- 'erpnext/manufacturing/*'
+
+crm:
+- 'erpnext/crm/*'
+
+HR:
+- 'erpnext/hr/*'
+
+payroll:
+- 'erpnext/payroll*'
+
+projects:
+- 'erpnext/projects/*'
+
+# Any python files modifed but no test files modified
+needs-tests:
+- any: ['erpnext/**/*.py']
+  all: ['!erpnext/**/test*.py']
diff --git a/.github/workflows/docs-checker.yml b/.github/workflows/docs-checker.yml
index db46c56..b644568 100644
--- a/.github/workflows/docs-checker.yml
+++ b/.github/workflows/docs-checker.yml
@@ -12,7 +12,7 @@
       - name: 'Setup Environment'
         uses: actions/setup-python@v2
         with:
-          python-version: 3.6
+          python-version: 3.8
 
       - name: 'Clone repo'
         uses: actions/checkout@v2
diff --git a/.github/workflows/labeller.yml b/.github/workflows/labeller.yml
new file mode 100644
index 0000000..a774400
--- /dev/null
+++ b/.github/workflows/labeller.yml
@@ -0,0 +1,12 @@
+name: "Pull Request Labeler"
+on:
+  pull_request_target:
+    types: [opened, reopened]
+
+jobs:
+  triage:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/labeler@v3
+      with:
+        repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
index 97bccf5..d05bbbe 100644
--- a/.github/workflows/patch.yml
+++ b/.github/workflows/patch.yml
@@ -34,7 +34,7 @@
       - name: Setup Python
         uses: actions/setup-python@v2
         with:
-          python-version: 3.7
+          python-version: 3.8
 
       - name: Setup Node
         uses: actions/setup-node@v2
@@ -80,6 +80,9 @@
 
       - name: Install
         run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
+        env:
+          DB: mariadb
+          TYPE: server
 
       - name: Run Patch Tests
         run: |
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests-mariadb.yml
similarity index 94%
rename from .github/workflows/server-tests.yml
rename to .github/workflows/server-tests-mariadb.yml
index 77c0aee..7347a58 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests-mariadb.yml
@@ -1,10 +1,11 @@
-name: Server
+name: Server (Mariadb)
 
 on:
   pull_request:
     paths-ignore:
       - '**.js'
       - '**.md'
+      - '**.html'
   workflow_dispatch:
   push:
     branches: [ develop ]
@@ -13,7 +14,7 @@
       - '**.md'
 
 concurrency:
-  group: server-develop-${{ github.event.number }}
+  group: server-mariadb-develop-${{ github.event.number }}
   cancel-in-progress: true
 
 jobs:
@@ -45,7 +46,7 @@
       - name: Setup Python
         uses: actions/setup-python@v2
         with:
-          python-version: 3.7
+          python-version: 3.8
 
       - name: Setup Node
         uses: actions/setup-node@v2
@@ -92,6 +93,7 @@
       - name: Install
         run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
         env:
+          DB: mariadb
           TYPE: server
 
       - name: Run Tests
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests-postgres.yml
similarity index 73%
copy from .github/workflows/server-tests.yml
copy to .github/workflows/server-tests-postgres.yml
index 77c0aee..77d3c1a 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests-postgres.yml
@@ -1,51 +1,52 @@
-name: Server
+name: Server (Postgres)
 
 on:
   pull_request:
     paths-ignore:
       - '**.js'
       - '**.md'
-  workflow_dispatch:
-  push:
-    branches: [ develop ]
-    paths-ignore:
-      - '**.js'
-      - '**.md'
+      - '**.html'
+    types: [opened, labelled, synchronize, reopened]
 
 concurrency:
-  group: server-develop-${{ github.event.number }}
+  group: server-postgres-develop-${{ github.event.number }}
   cancel-in-progress: true
 
 jobs:
   test:
+    if: ${{ contains(github.event.pull_request.labels.*.name, 'postgres') }}
     runs-on: ubuntu-latest
     timeout-minutes: 60
 
     strategy:
       fail-fast: false
-
       matrix:
-        container: [1, 2, 3]
+       container: [1, 2, 3]
 
     name: Python Unit Tests
 
     services:
-      mysql:
-        image: mariadb:10.3
+      postgres:
+        image: postgres:13.3
         env:
-          MYSQL_ALLOW_EMPTY_PASSWORD: YES
+          POSTGRES_PASSWORD: travis
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
         ports:
-          - 3306:3306
-        options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+          - 5432:5432
 
     steps:
+
       - name: Clone
         uses: actions/checkout@v2
 
       - name: Setup Python
         uses: actions/setup-python@v2
         with:
-          python-version: 3.7
+          python-version: 3.8
 
       - name: Setup Node
         uses: actions/setup-node@v2
@@ -89,22 +90,16 @@
           restore-keys: |
             ${{ runner.os }}-yarn-
 
+
       - name: Install
         run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
         env:
+          DB: postgres
           TYPE: server
 
       - name: Run Tests
-        run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --use-orchestrator --with-coverage
+        run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --use-orchestrator
         env:
           TYPE: server
           CI_BUILD_ID: ${{ github.run_id }}
           ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
-
-      - name: Upload coverage data
-        uses: codecov/codecov-action@v2
-        with:
-          name: MariaDB
-          fail_ci_if_error: true
-          files: /home/runner/frappe-bench/sites/coverage.xml
-          verbose: true
diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml
index d765f04..ab6a53b 100644
--- a/.github/workflows/ui-tests.yml
+++ b/.github/workflows/ui-tests.yml
@@ -36,7 +36,7 @@
       - name: Setup Python
         uses: actions/setup-python@v2
         with:
-          python-version: 3.7
+          python-version: 3.8
 
       - uses: actions/setup-node@v2
         with:
diff --git a/CODEOWNERS b/CODEOWNERS
index a4a14de..bfc2601 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -23,13 +23,13 @@
 
 erpnext/crm/                    @ruchamahabal @pateljannat
 erpnext/education/              @ruchamahabal @pateljannat
-erpnext/healthcare/             @ruchamahabal @pateljannat @chillaranand
 erpnext/hr/                     @ruchamahabal @pateljannat
-erpnext/non_profit/             @ruchamahabal
 erpnext/payroll                 @ruchamahabal @pateljannat
 erpnext/projects/               @ruchamahabal @pateljannat
 
-erpnext/controllers             @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination
+erpnext/controllers/            @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination @ankush
+erpnext/patches/                @deepeshgarg007 @nextchamp-saqib @marination @ankush
+erpnext/public/                 @nextchamp-saqib @marination
 
-.github/                        @surajshetty3416 @ankush
+.github/                        @ankush
 requirements.txt                @gavindsouza
diff --git a/erpnext/accounts/doctype/account/account.js b/erpnext/accounts/doctype/account/account.js
index 7a1d735..320e1ca 100644
--- a/erpnext/accounts/doctype/account/account.js
+++ b/erpnext/accounts/doctype/account/account.js
@@ -43,12 +43,12 @@
 				frm.trigger('add_toolbar_buttons');
 			}
 			if (frm.has_perm('write')) {
-				frm.add_custom_button(__('Update Account Name / Number'), function () {
-					frm.trigger("update_account_number");
-				});
 				frm.add_custom_button(__('Merge Account'), function () {
 					frm.trigger("merge_account");
-				});
+				}, __('Actions'));
+				frm.add_custom_button(__('Update Account Name / Number'), function () {
+					frm.trigger("update_account_number");
+				}, __('Actions'));
 			}
 		}
 	},
@@ -59,11 +59,12 @@
 		}
 	},
 	add_toolbar_buttons: function(frm) {
-		frm.add_custom_button(__('Chart of Accounts'),
-			function () { frappe.set_route("Tree", "Account"); });
+		frm.add_custom_button(__('Chart of Accounts'), () => {
+			frappe.set_route("Tree", "Account");
+		}, __('View'));
 
 		if (frm.doc.is_group == 1) {
-			frm.add_custom_button(__('Group to Non-Group'), function () {
+			frm.add_custom_button(__('Convert to Non-Group'), function () {
 				return frappe.call({
 					doc: frm.doc,
 					method: 'convert_group_to_ledger',
@@ -71,10 +72,11 @@
 						frm.refresh();
 					}
 				});
-			});
+			}, __('Actions'));
+
 		} else if (cint(frm.doc.is_group) == 0
 			&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
-			frm.add_custom_button(__('Ledger'), function () {
+			frm.add_custom_button(__('General Ledger'), function () {
 				frappe.route_options = {
 					"account": frm.doc.name,
 					"from_date": frappe.sys_defaults.year_start_date,
@@ -82,9 +84,9 @@
 					"company": frm.doc.company
 				};
 				frappe.set_route("query-report", "General Ledger");
-			});
+			}, __('View'));
 
-			frm.add_custom_button(__('Non-Group to Group'), function () {
+			frm.add_custom_button(__('Convert to Group'), function () {
 				return frappe.call({
 					doc: frm.doc,
 					method: 'convert_ledger_to_group',
@@ -92,7 +94,7 @@
 						frm.refresh();
 					}
 				});
-			});
+			}, __('Actions'));
 		}
 	},
 
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
index 78e7ff6..335f850 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
@@ -7,7 +7,7 @@
 		frm.set_query("bank_account", function () {
 			return {
 				filters: {
-					company: ["in", frm.doc.company],
+					company: frm.doc.company,
 					'is_company_account': 1
 				},
 			};
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
index e7371fb..4211bd0 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
@@ -218,6 +218,8 @@
 	# updated clear date of all the vouchers based on the bank transaction
 	vouchers = json.loads(vouchers)
 	transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
+	company_account = frappe.db.get_value('Bank Account', transaction.bank_account, 'account')
+
 	if transaction.unallocated_amount == 0:
 		frappe.throw(_("This bank transaction is already fully reconciled"))
 	total_amount = 0
@@ -226,7 +228,7 @@
 		total_amount += get_paid_amount(frappe._dict({
 			'payment_document': voucher['payment_doctype'],
 			'payment_entry': voucher['payment_name'],
-		}), transaction.currency)
+		}), transaction.currency, company_account)
 
 	if total_amount > transaction.unallocated_amount:
 		frappe.throw(_("The Sum Total of Amounts of All Selected Vouchers Should be Less than the Unallocated Amount of the Bank Transaction"))
@@ -261,7 +263,7 @@
 	return matching
 
 def check_matching(bank_account, company, transaction, document_types):
-	# combine all types of vocuhers
+	# combine all types of vouchers
 	subquery = get_queries(bank_account, company, transaction, document_types)
 	filters = {
 			"amount": transaction.unallocated_amount,
@@ -343,13 +345,11 @@
 def get_je_matching_query(amount_condition, transaction):
 	# get matching journal entry query
 
+	# We have mapping at the bank level
+	# So one bank could have both types of bank accounts like asset and liability
+	# So cr_or_dr should be judged only on basis of withdrawal and deposit and not account type
 	company_account = frappe.get_value("Bank Account", transaction.bank_account, "account")
-	root_type = frappe.get_value("Account", company_account, "root_type")
-
-	if root_type == "Liability":
-		cr_or_dr = "debit" if transaction.withdrawal > 0 else "credit"
-	else:
-		cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
+	cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
 
 	return f"""
 
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
index 0a2e0bc..990d6d9 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
@@ -239,7 +239,8 @@
 					"withdrawal",
 					"description",
 					"reference_number",
-					"bank_account"
+					"bank_account",
+					"currency"
 				],
 			},
 		});
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 4620087..44cea31 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -102,7 +102,7 @@
 		AND
 			bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
 
-def get_paid_amount(payment_entry, currency):
+def get_paid_amount(payment_entry, currency, bank_account):
 	if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
 
 		paid_amount_field = "paid_amount"
@@ -115,7 +115,7 @@
 			payment_entry.payment_entry, paid_amount_field)
 
 	elif payment_entry.payment_document == "Journal Entry":
-		return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_credit")
+		return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account}, "sum(credit_in_account_currency)")
 
 	elif payment_entry.payment_document == "Expense Claim":
 		return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed")
diff --git a/erpnext/agriculture/doctype/linked_plant_analysis/__init__.py b/erpnext/accounts/doctype/currency_exchange_settings/__init__.py
similarity index 100%
rename from erpnext/agriculture/doctype/linked_plant_analysis/__init__.py
rename to erpnext/accounts/doctype/currency_exchange_settings/__init__.py
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js
new file mode 100644
index 0000000..6c40f2b
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js
@@ -0,0 +1,45 @@
+// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Currency Exchange Settings', {
+	service_provider: function(frm) {
+		if (frm.doc.service_provider == "exchangerate.host") {
+			let result = ['result'];
+			let params = {
+				date: '{transaction_date}',
+				from: '{from_currency}',
+				to: '{to_currency}'
+			};
+			add_param(frm, "https://api.exchangerate.host/convert", params, result);
+		} else if (frm.doc.service_provider == "frankfurter.app") {
+			let result = ['rates', '{to_currency}'];
+			let params = {
+				base: '{from_currency}',
+				symbols: '{to_currency}'
+			};
+			add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
+		}
+	}
+});
+
+
+function add_param(frm, api, params, result) {
+	var row;
+	frm.clear_table("req_params");
+	frm.clear_table("result_key");
+
+	frm.doc.api_endpoint = api;
+
+	$.each(params, function(key, value) {
+		row = frm.add_child("req_params");
+		row.key = key;
+		row.value = value;
+	});
+
+	$.each(result, function(key, value) {
+		row = frm.add_child("result_key");
+		row.key = value;
+	});
+
+	frm.refresh_fields();
+}
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json
new file mode 100644
index 0000000..7921fcc
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json
@@ -0,0 +1,126 @@
+{
+ "actions": [],
+ "creation": "2022-01-10 13:03:26.237081",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "api_details_section",
+  "service_provider",
+  "api_endpoint",
+  "url",
+  "column_break_3",
+  "help",
+  "section_break_2",
+  "req_params",
+  "column_break_4",
+  "result_key"
+ ],
+ "fields": [
+  {
+   "fieldname": "api_details_section",
+   "fieldtype": "Section Break",
+   "label": "API Details"
+  },
+  {
+   "fieldname": "api_endpoint",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "API Endpoint",
+   "read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
+   "reqd": 1
+  },
+  {
+   "fieldname": "url",
+   "fieldtype": "Data",
+   "label": "Example URL",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "help",
+   "fieldtype": "HTML",
+   "label": "Help",
+   "options": "<h3>Currency Exchange Settings Help</h3>\n<p>There are 3 variables that could be used within the endpoint, result key and in values of the parameter.</p>\n<p>Exchange rate between {from_currency} and {to_currency} on {transaction_date} is fetched by the API.</p>\n<p>Example: If your endpoint is exchange.com/2021-08-01, then, you will have to input exchange.com/{transaction_date}</p>"
+  },
+  {
+   "fieldname": "section_break_2",
+   "fieldtype": "Section Break",
+   "label": "Request Parameters"
+  },
+  {
+   "fieldname": "req_params",
+   "fieldtype": "Table",
+   "label": "Parameters",
+   "options": "Currency Exchange Settings Details",
+   "read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "result_key",
+   "fieldtype": "Table",
+   "label": "Result Key",
+   "options": "Currency Exchange Settings Result",
+   "read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
+   "reqd": 1
+  },
+  {
+   "fieldname": "service_provider",
+   "fieldtype": "Select",
+   "label": "Service Provider",
+   "options": "frankfurter.app\nexchangerate.host\nCustom",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2022-01-10 15:51:14.521174",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Currency Exchange Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": [],
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
new file mode 100644
index 0000000..e16ff3a
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+import requests
+from frappe import _
+from frappe.model.document import Document
+from frappe.utils import nowdate
+
+
+class CurrencyExchangeSettings(Document):
+	def validate(self):
+		self.set_parameters_and_result()
+		response, value = self.validate_parameters()
+		self.validate_result(response, value)
+
+	def set_parameters_and_result(self):
+		if self.service_provider == 'exchangerate.host':
+			self.set('result_key', [])
+			self.set('req_params', [])
+
+			self.api_endpoint = "https://api.exchangerate.host/convert"
+			self.append('result_key', {'key': 'result'})
+			self.append('req_params', {'key': 'date', 'value': '{transaction_date}'})
+			self.append('req_params', {'key': 'from', 'value': '{from_currency}'})
+			self.append('req_params', {'key': 'to', 'value': '{to_currency}'})
+		elif self.service_provider == 'frankfurter.app':
+			self.set('result_key', [])
+			self.set('req_params', [])
+
+			self.api_endpoint = "https://frankfurter.app/{transaction_date}"
+			self.append('result_key', {'key': 'rates'})
+			self.append('result_key', {'key': '{to_currency}'})
+			self.append('req_params', {'key': 'base', 'value': '{from_currency}'})
+			self.append('req_params', {'key': 'symbols', 'value': '{to_currency}'})
+
+	def validate_parameters(self):
+		if frappe.flags.in_test:
+			return None, None
+
+		params = {}
+		for row in self.req_params:
+			params[row.key] = row.value.format(
+				transaction_date=nowdate(),
+				to_currency='INR',
+				from_currency='USD'
+			)
+
+		api_url = self.api_endpoint.format(
+			transaction_date=nowdate(),
+			to_currency='INR',
+			from_currency='USD'
+		)
+
+		try:
+			response = requests.get(api_url, params=params)
+		except requests.exceptions.RequestException as e:
+			frappe.throw("Error: " + str(e))
+
+		response.raise_for_status()
+		value = response.json()
+
+		return response, value
+
+	def validate_result(self, response, value):
+		if frappe.flags.in_test:
+			return
+
+		try:
+			for key in self.result_key:
+				value = value[str(key.key).format(
+					transaction_date=nowdate(),
+					to_currency='INR',
+					from_currency='USD'
+				)]
+		except Exception:
+			frappe.throw("Invalid result key. Response: " + response.text)
+		if not isinstance(value, (int, float)):
+			frappe.throw(_("Returned exchange rate is neither integer not float."))
+
+		self.url = response.url
+		frappe.msgprint("Exchange rate of USD to INR is " + str(value))
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/test_currency_exchange_settings.py b/erpnext/accounts/doctype/currency_exchange_settings/test_currency_exchange_settings.py
new file mode 100644
index 0000000..2778729
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/test_currency_exchange_settings.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+import unittest
+
+
+class TestCurrencyExchangeSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/agriculture/__init__.py b/erpnext/accounts/doctype/currency_exchange_settings_details/__init__.py
similarity index 100%
copy from erpnext/agriculture/__init__.py
copy to erpnext/accounts/doctype/currency_exchange_settings_details/__init__.py
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.json b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.json
new file mode 100644
index 0000000..3093587
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.json
@@ -0,0 +1,39 @@
+{
+ "actions": [],
+ "creation": "2021-09-02 14:54:49.033512",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "key",
+  "value"
+ ],
+ "fields": [
+  {
+   "fieldname": "key",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Key",
+   "reqd": 1
+  },
+  {
+   "fieldname": "value",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Value",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-11-03 19:14:55.889037",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Currency Exchange Settings Details",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py
new file mode 100644
index 0000000..a6ad763
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class CurrencyExchangeSettingsDetails(Document):
+	pass
diff --git a/erpnext/agriculture/__init__.py b/erpnext/accounts/doctype/currency_exchange_settings_result/__init__.py
similarity index 100%
copy from erpnext/agriculture/__init__.py
copy to erpnext/accounts/doctype/currency_exchange_settings_result/__init__.py
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.json b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.json
new file mode 100644
index 0000000..fff5337
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.json
@@ -0,0 +1,31 @@
+{
+ "actions": [],
+ "creation": "2021-09-03 13:17:22.088259",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "key"
+ ],
+ "fields": [
+  {
+   "fieldname": "key",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Key",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-11-03 19:14:40.054245",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Currency Exchange Settings Result",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py
new file mode 100644
index 0000000..1774128
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class CurrencyExchangeSettingsResult(Document):
+	pass
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 957a50f..617b376 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -31,7 +31,7 @@
 		if(frm.doc.docstatus==1) {
 			frm.add_custom_button(__('Reverse Journal Entry'), function() {
 				return erpnext.journal_entry.reverse_journal_entry(frm);
-			}, __('Make'));
+			}, __('Actions'));
 		}
 
 		if (frm.doc.__islocal) {
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json
index 20678d7..335fd35 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.json
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json
@@ -13,6 +13,7 @@
   "voucher_type",
   "naming_series",
   "finance_book",
+  "reversal_of",
   "tax_withholding_category",
   "column_break1",
   "from_template",
@@ -515,13 +516,21 @@
    "fieldname": "apply_tds",
    "fieldtype": "Check",
    "label": "Apply Tax Withholding Amount "
+  },
+  {
+   "depends_on": "eval:doc.docstatus",
+   "fieldname": "reversal_of",
+   "fieldtype": "Link",
+   "label": "Reversal Of",
+   "options": "Journal Entry",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 176,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-09-09 15:31:14.484029",
+ "modified": "2022-01-04 13:39:36.485954",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Journal Entry",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index ca17265..8fc4e8c 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -1157,9 +1157,8 @@
 def make_reverse_journal_entry(source_name, target_doc=None):
 	from frappe.model.mapper import get_mapped_doc
 
-	def update_accounts(source, target, source_parent):
-		target.reference_type = "Journal Entry"
-		target.reference_name = source_parent.name
+	def post_process(source, target):
+		target.reversal_of = source.name
 
 	doclist = get_mapped_doc("Journal Entry", source_name, {
 		"Journal Entry": {
@@ -1177,9 +1176,8 @@
 				"debit": "credit",
 				"credit_in_account_currency": "debit_in_account_currency",
 				"credit": "debit",
-			},
-			"postprocess": update_accounts,
+			}
 		},
-	}, target_doc)
+	}, target_doc, post_process)
 
 	return doclist
diff --git a/erpnext/agriculture/__init__.py b/erpnext/accounts/doctype/ledger_merge/__init__.py
similarity index 100%
rename from erpnext/agriculture/__init__.py
rename to erpnext/accounts/doctype/ledger_merge/__init__.py
diff --git a/erpnext/accounts/doctype/ledger_merge/ledger_merge.js b/erpnext/accounts/doctype/ledger_merge/ledger_merge.js
new file mode 100644
index 0000000..b2db98d
--- /dev/null
+++ b/erpnext/accounts/doctype/ledger_merge/ledger_merge.js
@@ -0,0 +1,128 @@
+// Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Ledger Merge', {
+	setup: function(frm) {
+		frappe.realtime.on('ledger_merge_refresh', ({ ledger_merge }) => {
+			if (ledger_merge !== frm.doc.name) return;
+			frappe.model.clear_doc(frm.doc.doctype, frm.doc.name);
+			frappe.model.with_doc(frm.doc.doctype, frm.doc.name).then(() => {
+				frm.refresh();
+			});
+		});
+
+		frappe.realtime.on('ledger_merge_progress', data => {
+			if (data.ledger_merge !== frm.doc.name) return;
+			let message = __('Merging {0} of {1}', [data.current, data.total]);
+			let percent = Math.floor((data.current * 100) / data.total);
+			frm.dashboard.show_progress(__('Merge Progress'), percent, message);
+			frm.page.set_indicator(__('In Progress'), 'orange');
+		});
+
+		frm.set_query("account", function(doc) {
+			if (!doc.company) frappe.throw(__('Please set Company'));
+			if (!doc.root_type) frappe.throw(__('Please set Root Type'));
+			return {
+				filters: {
+					root_type: doc.root_type,
+					company: doc.company
+				}
+			};
+		});
+
+		frm.set_query('account', 'merge_accounts', function(doc) {
+			if (!doc.company) frappe.throw(__('Please set Company'));
+			if (!doc.root_type) frappe.throw(__('Please set Root Type'));
+			if (!doc.account) frappe.throw(__('Please set Account'));
+			let acc = [doc.account];
+			frm.doc.merge_accounts.forEach((row) => {
+				acc.push(row.account);
+			});
+			return {
+				filters: {
+					is_group: doc.is_group,
+					root_type: doc.root_type,
+					name: ["not in", acc],
+					company: doc.company
+				}
+			};
+		});
+	},
+
+	refresh: function(frm) {
+		frm.page.hide_icon_group();
+		frm.trigger('set_merge_status');
+		frm.trigger('update_primary_action');
+	},
+
+	after_save: function(frm) {
+		setTimeout(() => {
+			frm.trigger('update_primary_action');
+		}, 500);
+	},
+
+	update_primary_action: function(frm) {
+		if (frm.is_dirty()) {
+			frm.enable_save();
+			return;
+		}
+		frm.disable_save();
+		if (frm.doc.status !== 'Success') {
+			if (!frm.is_new()) {
+				let label = frm.doc.status === 'Pending' ? __('Start Merge') : __('Retry');
+				frm.page.set_primary_action(label, () => frm.events.start_merge(frm));
+			} else {
+				frm.page.set_primary_action(__('Save'), () => frm.save());
+			}
+		}
+	},
+
+	start_merge: function(frm) {
+		frm.call({
+			method: 'form_start_merge',
+			args: { docname: frm.doc.name },
+			btn: frm.page.btn_primary
+		}).then(r => {
+			if (r.message === true) {
+				frm.disable_save();
+			}
+		});
+	},
+
+	set_merge_status: function(frm) {
+		if (frm.doc.status == "Pending") return;
+		let successful_records = 0;
+		frm.doc.merge_accounts.forEach((row) => {
+			if (row.merged) successful_records += 1;
+		});
+		let message_args = [successful_records, frm.doc.merge_accounts.length];
+		frm.dashboard.set_headline(__('Successfully merged {0} out of {1}.', message_args));
+	},
+
+	root_type: function(frm) {
+		frm.set_value('account', '');
+		frm.set_value('merge_accounts', []);
+	},
+
+	company: function(frm) {
+		frm.set_value('account', '');
+		frm.set_value('merge_accounts', []);
+	}
+});
+
+frappe.ui.form.on('Ledger Merge Accounts', {
+	merge_accounts_add: function(frm) {
+		frm.trigger('update_primary_action');
+	},
+
+	merge_accounts_remove: function(frm) {
+		frm.trigger('update_primary_action');
+	},
+
+	account: function(frm, cdt, cdn) {
+		let row = frappe.get_doc(cdt, cdn);
+		row.account_name = row.account;
+		frm.refresh_field('merge_accounts');
+		frm.trigger('update_primary_action');
+	}
+});
diff --git a/erpnext/accounts/doctype/ledger_merge/ledger_merge.json b/erpnext/accounts/doctype/ledger_merge/ledger_merge.json
new file mode 100644
index 0000000..dd816df
--- /dev/null
+++ b/erpnext/accounts/doctype/ledger_merge/ledger_merge.json
@@ -0,0 +1,130 @@
+{
+ "actions": [],
+ "autoname": "format:{account_name} merger on {creation}",
+ "creation": "2021-12-09 15:38:04.556584",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "section_break_1",
+  "root_type",
+  "account",
+  "account_name",
+  "column_break_3",
+  "company",
+  "status",
+  "is_group",
+  "section_break_5",
+  "merge_accounts"
+ ],
+ "fields": [
+  {
+   "depends_on": "root_type",
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "label": "Account",
+   "options": "Account",
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "section_break_1",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "merge_accounts",
+   "fieldtype": "Table",
+   "label": "Accounts to Merge",
+   "options": "Ledger Merge Accounts",
+   "reqd": 1
+  },
+  {
+   "depends_on": "account",
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Status",
+   "options": "Pending\nSuccess\nPartial Success\nError",
+   "read_only": 1
+  },
+  {
+   "fieldname": "root_type",
+   "fieldtype": "Select",
+   "label": "Root Type",
+   "options": "\nAsset\nLiability\nIncome\nExpense\nEquity",
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "depends_on": "account",
+   "fetch_from": "account.account_name",
+   "fetch_if_empty": 1,
+   "fieldname": "account_name",
+   "fieldtype": "Data",
+   "label": "Account Name",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "depends_on": "account",
+   "fetch_from": "account.is_group",
+   "fieldname": "is_group",
+   "fieldtype": "Check",
+   "label": "Is Group",
+   "read_only": 1
+  }
+ ],
+ "hide_toolbar": 1,
+ "links": [],
+ "modified": "2021-12-12 21:34:55.155146",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Ledger Merge",
+ "naming_rule": "Expression",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/ledger_merge/ledger_merge.py b/erpnext/accounts/doctype/ledger_merge/ledger_merge.py
new file mode 100644
index 0000000..830ad37
--- /dev/null
+++ b/erpnext/accounts/doctype/ledger_merge/ledger_merge.py
@@ -0,0 +1,76 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+from frappe.model.document import Document
+
+from erpnext.accounts.doctype.account.account import merge_account
+
+
+class LedgerMerge(Document):
+	def start_merge(self):
+		from frappe.core.page.background_jobs.background_jobs import get_info
+		from frappe.utils.background_jobs import enqueue
+		from frappe.utils.scheduler import is_scheduler_inactive
+
+		if is_scheduler_inactive() and not frappe.flags.in_test:
+			frappe.throw(
+				_("Scheduler is inactive. Cannot merge accounts."), title=_("Scheduler Inactive")
+			)
+
+		enqueued_jobs = [d.get("job_name") for d in get_info()]
+
+		if self.name not in enqueued_jobs:
+			enqueue(
+				start_merge,
+				queue="default",
+				timeout=6000,
+				event="ledger_merge",
+				job_name=self.name,
+				docname=self.name,
+				now=frappe.conf.developer_mode or frappe.flags.in_test,
+			)
+			return True
+
+		return False
+
+@frappe.whitelist()
+def form_start_merge(docname):
+	return frappe.get_doc("Ledger Merge", docname).start_merge()
+
+def start_merge(docname):
+	ledger_merge = frappe.get_doc("Ledger Merge", docname)
+	successful_merges = 0
+	total = len(ledger_merge.merge_accounts)
+	for row in ledger_merge.merge_accounts:
+		if not row.merged:
+			try:
+				merge_account(
+					row.account,
+					ledger_merge.account,
+					ledger_merge.is_group,
+					ledger_merge.root_type,
+					ledger_merge.company
+				)
+				row.db_set('merged', 1)
+				frappe.db.commit()
+				successful_merges += 1
+				frappe.publish_realtime("ledger_merge_progress", {
+						"ledger_merge": ledger_merge.name,
+						"current": successful_merges,
+						"total": total
+					}
+				)
+			except Exception:
+				frappe.db.rollback()
+				frappe.log_error(title=ledger_merge.name)
+			finally:
+				if successful_merges == total:
+					ledger_merge.db_set('status', 'Success')
+				elif successful_merges > 0:
+					ledger_merge.db_set('status', 'Partial Success')
+				else:
+					ledger_merge.db_set('status', 'Error')
+
+	frappe.publish_realtime("ledger_merge_refresh", {"ledger_merge": ledger_merge.name})
diff --git a/erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py b/erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py
new file mode 100644
index 0000000..f731536
--- /dev/null
+++ b/erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py
@@ -0,0 +1,118 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and Contributors
+# See license.txt
+
+import unittest
+
+import frappe
+
+from erpnext.accounts.doctype.ledger_merge.ledger_merge import start_merge
+
+
+class TestLedgerMerge(unittest.TestCase):
+	def test_merge_success(self):
+		if not frappe.db.exists("Account", "Indirect Expenses - _TC"):
+			acc = frappe.new_doc("Account")
+			acc.account_name = "Indirect Expenses"
+			acc.is_group = 1
+			acc.parent_account = "Expenses - _TC"
+			acc.company = "_Test Company"
+			acc.insert()
+		if not frappe.db.exists("Account", "Indirect Test Expenses - _TC"):
+			acc = frappe.new_doc("Account")
+			acc.account_name = "Indirect Test Expenses"
+			acc.is_group = 1
+			acc.parent_account = "Expenses - _TC"
+			acc.company = "_Test Company"
+			acc.insert()
+		if not frappe.db.exists("Account", "Administrative Test Expenses - _TC"):
+			acc = frappe.new_doc("Account")
+			acc.account_name = "Administrative Test Expenses"
+			acc.parent_account = "Indirect Test Expenses - _TC"
+			acc.company = "_Test Company"
+			acc.insert()
+
+		doc = frappe.get_doc({
+			"doctype": "Ledger Merge",
+			"company": "_Test Company",
+			"root_type": frappe.db.get_value("Account", "Indirect Test Expenses - _TC", "root_type"),
+			"account": "Indirect Expenses - _TC",
+			"merge_accounts": [
+				{
+					"account": "Indirect Test Expenses - _TC",
+					"account_name": "Indirect Expenses"
+				}
+			]
+		}).insert(ignore_permissions=True)
+
+		parent = frappe.db.get_value("Account", "Administrative Test Expenses - _TC", "parent_account")
+		self.assertEqual(parent, "Indirect Test Expenses - _TC")
+
+		start_merge(doc.name)
+
+		parent = frappe.db.get_value("Account", "Administrative Test Expenses - _TC", "parent_account")
+		self.assertEqual(parent, "Indirect Expenses - _TC")
+
+		self.assertFalse(frappe.db.exists("Account", "Indirect Test Expenses - _TC"))
+
+	def test_partial_merge_success(self):
+		if not frappe.db.exists("Account", "Indirect Income - _TC"):
+			acc = frappe.new_doc("Account")
+			acc.account_name = "Indirect Income"
+			acc.is_group = 1
+			acc.parent_account = "Income - _TC"
+			acc.company = "_Test Company"
+			acc.insert()
+		if not frappe.db.exists("Account", "Indirect Test Income - _TC"):
+			acc = frappe.new_doc("Account")
+			acc.account_name = "Indirect Test Income"
+			acc.is_group = 1
+			acc.parent_account = "Income - _TC"
+			acc.company = "_Test Company"
+			acc.insert()
+		if not frappe.db.exists("Account", "Administrative Test Income - _TC"):
+			acc = frappe.new_doc("Account")
+			acc.account_name = "Administrative Test Income"
+			acc.parent_account = "Indirect Test Income - _TC"
+			acc.company = "_Test Company"
+			acc.insert()
+
+		doc = frappe.get_doc({
+			"doctype": "Ledger Merge",
+			"company": "_Test Company",
+			"root_type": frappe.db.get_value("Account", "Indirect Income - _TC", "root_type"),
+			"account": "Indirect Income - _TC",
+			"merge_accounts": [
+				{
+					"account": "Indirect Test Income - _TC",
+					"account_name": "Indirect Test Income"
+				},
+				{
+					"account": "Administrative Test Income - _TC",
+					"account_name": "Administrative Test Income"
+				}
+			]
+		}).insert(ignore_permissions=True)
+
+		parent = frappe.db.get_value("Account", "Administrative Test Income - _TC", "parent_account")
+		self.assertEqual(parent, "Indirect Test Income - _TC")
+
+		start_merge(doc.name)
+
+		parent = frappe.db.get_value("Account", "Administrative Test Income - _TC", "parent_account")
+		self.assertEqual(parent, "Indirect Income - _TC")
+
+		self.assertFalse(frappe.db.exists("Account", "Indirect Test Income - _TC"))
+		self.assertTrue(frappe.db.exists("Account", "Administrative Test Income - _TC"))
+
+	def tearDown(self):
+		for entry in frappe.db.get_all("Ledger Merge"):
+			frappe.delete_doc("Ledger Merge", entry.name)
+
+		test_accounts = [
+			"Indirect Test Expenses - _TC",
+			"Administrative Test Expenses - _TC",
+			"Indirect Test Income - _TC",
+			"Administrative Test Income - _TC"
+		]
+		for account in test_accounts:
+			frappe.delete_doc_if_exists("Account", account)
diff --git a/erpnext/agriculture/__init__.py b/erpnext/accounts/doctype/ledger_merge_accounts/__init__.py
similarity index 100%
copy from erpnext/agriculture/__init__.py
copy to erpnext/accounts/doctype/ledger_merge_accounts/__init__.py
diff --git a/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.json b/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.json
new file mode 100644
index 0000000..4ce55ad
--- /dev/null
+++ b/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.json
@@ -0,0 +1,52 @@
+{
+ "actions": [],
+ "allow_rename": 1,
+ "creation": "2021-12-09 15:44:58.033398",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account",
+  "account_name",
+  "merged"
+ ],
+ "fields": [
+  {
+   "columns": 4,
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Account",
+   "options": "Account",
+   "reqd": 1
+  },
+  {
+   "columns": 2,
+   "default": "0",
+   "fieldname": "merged",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Merged",
+   "read_only": 1
+  },
+  {
+   "columns": 4,
+   "fieldname": "account_name",
+   "fieldtype": "Data",
+   "label": "Account Name",
+   "read_only": 1,
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-12-10 15:27:24.477139",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Ledger Merge Accounts",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.py b/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.py
new file mode 100644
index 0000000..30dfd65
--- /dev/null
+++ b/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class LedgerMergeAccounts(Document):
+	pass
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
index bc92418..daee8f8 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
@@ -75,7 +75,7 @@
  ],
  "hide_toolbar": 1,
  "issingle": 1,
- "modified": "2019-07-25 14:57:33.187689",
+ "modified": "2022-01-04 15:25:06.053187",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Opening Invoice Creation Tool",
diff --git a/erpnext/accounts/doctype/party_link/party_link.py b/erpnext/accounts/doctype/party_link/party_link.py
index e9f813c..031a9fa 100644
--- a/erpnext/accounts/doctype/party_link/party_link.py
+++ b/erpnext/accounts/doctype/party_link/party_link.py
@@ -2,7 +2,7 @@
 # For license information, please see license.txt
 
 import frappe
-from frappe import _
+from frappe import _, bold
 from frappe.model.document import Document
 
 
@@ -13,6 +13,17 @@
 				title=_("Invalid Primary Role"))
 
 		existing_party_link = frappe.get_all('Party Link', {
+			'primary_party': self.primary_party,
+			'secondary_party': self.secondary_party
+		}, pluck="primary_role")
+		if existing_party_link:
+			frappe.throw(_('{} {} is already linked with {} {}')
+				.format(
+					self.primary_role, bold(self.primary_party),
+					self.secondary_role, bold(self.secondary_party)
+				))
+
+		existing_party_link = frappe.get_all('Party Link', {
 			'primary_party': self.secondary_party
 		}, pluck="primary_role")
 		if existing_party_link:
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index c1b056b..0e07abd 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1708,7 +1708,10 @@
 
 def apply_early_payment_discount(paid_amount, received_amount, doc):
 	total_discount = 0
-	if doc.doctype in ['Sales Invoice', 'Purchase Invoice'] and doc.payment_schedule:
+	eligible_for_payments = ['Sales Order', 'Sales Invoice', 'Purchase Order', 'Purchase Invoice']
+	has_payment_schedule = hasattr(doc, 'payment_schedule') and doc.payment_schedule
+
+	if doc.doctype in eligible_for_payments and has_payment_schedule:
 		for term in doc.payment_schedule:
 			if not term.discounted_amount and term.discount and getdate(nowdate()) <= term.discount_date:
 				if term.discount_type == 'Percentage':
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 0d6404c..134bccf 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -15,6 +15,7 @@
 	update_multi_mode_option,
 )
 from erpnext.accounts.party import get_due_date, get_party_account
+from erpnext.stock.doctype.batch.batch import get_batch_qty, get_pos_reserved_batch_qty
 from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos
 
 
@@ -124,9 +125,26 @@
 			frappe.throw(_("Row #{}: Serial No. {} has already been transacted into another POS Invoice. Please select valid serial no.")
 						.format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable"))
 		elif invalid_serial_nos:
-			frappe.throw(_("Row #{}: Serial Nos. {} has already been transacted into another POS Invoice. Please select valid serial no.")
+			frappe.throw(_("Row #{}: Serial Nos. {} have already been transacted into another POS Invoice. Please select valid serial no.")
 						.format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable"))
 
+	def validate_pos_reserved_batch_qty(self, item):
+		filters = {"item_code": item.item_code, "warehouse": item.warehouse, "batch_no":item.batch_no}
+
+		available_batch_qty = get_batch_qty(item.batch_no, item.warehouse, item.item_code)
+		reserved_batch_qty = get_pos_reserved_batch_qty(filters)
+
+		bold_item_name = frappe.bold(item.item_name)
+		bold_extra_batch_qty_needed = frappe.bold(abs(available_batch_qty - reserved_batch_qty - item.qty))
+		bold_invalid_batch_no = frappe.bold(item.batch_no)
+
+		if (available_batch_qty - reserved_batch_qty) == 0:
+			frappe.throw(_("Row #{}: Batch No. {} of item {} has no stock available. Please select valid batch no.")
+						.format(item.idx, bold_invalid_batch_no, bold_item_name), title=_("Item Unavailable"))
+		elif (available_batch_qty - reserved_batch_qty - item.qty) < 0:
+			frappe.throw(_("Row #{}: Batch No. {} of item {} has less than required stock available, {} more required")
+						.format(item.idx, bold_invalid_batch_no, bold_item_name, bold_extra_batch_qty_needed), title=_("Item Unavailable"))
+
 	def validate_delivered_serial_nos(self, item):
 		serial_nos = get_serial_nos(item.serial_no)
 		delivered_serial_nos = frappe.db.get_list('Serial No', {
@@ -149,6 +167,8 @@
 			if d.serial_no:
 				self.validate_pos_reserved_serial_nos(d)
 				self.validate_delivered_serial_nos(d)
+			elif d.batch_no:
+				self.validate_pos_reserved_batch_qty(d)
 			else:
 				if allow_negative_stock:
 					return
@@ -333,7 +353,6 @@
 			if not for_validate and not self.customer:
 				self.customer = profile.customer
 
-			self.ignore_pricing_rule = profile.ignore_pricing_rule
 			self.account_for_change_amount = profile.get('account_for_change_amount') or self.account_for_change_amount
 			self.set_warehouse = profile.get('warehouse') or self.set_warehouse
 
diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
index 6696333..56479a0 100644
--- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
@@ -521,6 +521,72 @@
 		rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total")
 		self.assertEqual(rounded_total, 400)
 
+	def test_pos_batch_item_qty_validation(self):
+		from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
+			create_batch_item_with_batch,
+		)
+		create_batch_item_with_batch('_BATCH ITEM', 'TestBatch 01')
+		item = frappe.get_doc('Item', '_BATCH ITEM')
+		batch = frappe.get_doc('Batch', 'TestBatch 01')
+		batch.submit()
+		item.batch_no = 'TestBatch 01'
+		item.save()
+
+		se = make_stock_entry(target="_Test Warehouse - _TC", item_code="_BATCH ITEM", qty=2, basic_rate=100, batch_no='TestBatch 01')
+
+		pos_inv1 = create_pos_invoice(item=item.name, rate=300, qty=1, do_not_submit=1)
+		pos_inv1.items[0].batch_no = 'TestBatch 01'
+		pos_inv1.save()
+		pos_inv1.submit()
+
+		pos_inv2 = create_pos_invoice(item=item.name, rate=300, qty=2, do_not_submit=1)
+		pos_inv2.items[0].batch_no = 'TestBatch 01'
+		pos_inv2.save()
+
+		self.assertRaises(frappe.ValidationError, pos_inv2.submit)
+
+		#teardown
+		pos_inv1.reload()
+		pos_inv1.cancel()
+		pos_inv1.delete()
+		pos_inv2.reload()
+		pos_inv2.delete()
+		se.cancel()
+		batch.reload()
+		batch.cancel()
+		batch.delete()
+
+	def test_ignore_pricing_rule(self):
+		from erpnext.accounts.doctype.pricing_rule.test_pricing_rule import make_pricing_rule
+
+		item_price = frappe.get_doc({
+			'doctype': 'Item Price',
+			'item_code': '_Test Item',
+			'price_list': '_Test Price List',
+			'price_list_rate': '450',
+		})
+		item_price.insert()
+		pr = make_pricing_rule(selling=1, priority=5, discount_percentage=10)
+		pr.save()
+		pos_inv = create_pos_invoice(qty=1, do_not_submit=1)
+		pos_inv.items[0].rate = 300
+		pos_inv.save()
+		self.assertEquals(pos_inv.items[0].discount_percentage, 10)
+		# rate shouldn't change
+		self.assertEquals(pos_inv.items[0].rate, 405)
+
+		pos_inv.ignore_pricing_rule = 1
+		pos_inv.items[0].rate = 300
+		pos_inv.save()
+		self.assertEquals(pos_inv.ignore_pricing_rule, 1)
+		# rate should change since pricing rules are ignored
+		self.assertEquals(pos_inv.items[0].rate, 300)
+
+		item_price.delete()
+		pos_inv.delete()
+		pr.delete()
+
+
 def create_pos_invoice(**args):
 	args = frappe._dict(args)
 	pos_profile = None
@@ -557,7 +623,8 @@
 		"income_account": args.income_account or "Sales - _TC",
 		"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
 		"cost_center": args.cost_center or "_Test Cost Center - _TC",
-		"serial_no": args.serial_no
+		"serial_no": args.serial_no,
+		"batch_no": args.batch_no
 	})
 
 	if not args.do_not_save:
@@ -570,3 +637,8 @@
 		pos_inv.payment_schedule = []
 
 	return pos_inv
+
+def make_batch_item(item_name):
+	from erpnext.stock.doctype.item.test_item import make_item
+	if not frappe.db.exists(item_name):
+		return make_item(item_name, dict(has_batch_no = 1, create_new_batch = 1, is_stock_item=1))
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index d8b8606..5746a84 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -166,7 +166,7 @@
 					"item_group": "Products",
 				},
 				{
-					"item_group": "Seed",
+					"item_group": "_Test Item Group",
 				},
 			],
 			"selling": 1,
@@ -650,7 +650,7 @@
 		"rate": args.rate or 0.0,
 		"margin_rate_or_amount": args.margin_rate_or_amount or 0.0,
 		"condition": args.condition or '',
-		"priority": 1,
+		"priority": args.priority or 1,
 		"discount_amount": args.discount_amount or 0.0,
 		"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0
 	})
@@ -676,6 +676,8 @@
 	if args.get(applicable_for):
 		doc.db_set(applicable_for, args.get(applicable_for))
 
+	return doc
+
 def setup_pricing_rule_data():
 	if not frappe.db.exists('Campaign', '_Test Campaign'):
 		frappe.get_doc({
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index df957d2..b364218 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -505,11 +505,11 @@
 		# Checked both rounding_adjustment and rounded_total
 		# because rounded_total had value even before introcution of posting GLE based on rounded total
 		grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
+		base_grand_total = flt(self.base_rounded_total if (self.base_rounding_adjustment and self.base_rounded_total)
+			else self.base_grand_total, self.precision("base_grand_total"))
 
 		if grand_total and not self.is_internal_transfer():
 				# Did not use base_grand_total to book rounding loss gle
-				grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
-					self.precision("grand_total"))
 				gl_entries.append(
 					self.get_gl_dict({
 						"account": self.credit_to,
@@ -517,8 +517,8 @@
 						"party": self.supplier,
 						"due_date": self.due_date,
 						"against": self.against_expense_account,
-						"credit": grand_total_in_company_currency,
-						"credit_in_account_currency": grand_total_in_company_currency \
+						"credit": base_grand_total,
+						"credit_in_account_currency": base_grand_total \
 							if self.party_account_currency==self.company_currency else grand_total,
 						"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
 						"against_voucher_type": self.doctype,
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index aa2408e..21846bb 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -986,7 +986,7 @@
 
 		pi = make_purchase_invoice(item=item.name, qty=1, rate=100, do_not_save=True)
 		pi.set_posting_time = 1
-		pi.posting_date = '2019-03-15'
+		pi.posting_date = '2019-01-10'
 		pi.items[0].enable_deferred_expense = 1
 		pi.items[0].service_start_date = "2019-01-10"
 		pi.items[0].service_end_date = "2019-03-15"
@@ -1236,7 +1236,7 @@
 def update_tax_witholding_category(company, account):
 	from erpnext.accounts.utils import get_fiscal_year
 
-	fiscal_year = get_fiscal_year(fiscal_year='2021')
+	fiscal_year = get_fiscal_year(date=nowdate())
 
 	if not frappe.db.get_value('Tax Withholding Rate',
 		{'parent': 'TDS - 194 - Dividends - Individual', 'from_date': ('>=', fiscal_year[1]),
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 545abf7..5062c1c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -651,7 +651,7 @@
    "hide_seconds": 1,
    "label": "Ignore Pricing Rule",
    "no_copy": 1,
-   "permlevel": 1,
+   "permlevel": 0,
    "print_hide": 1
   },
   {
@@ -2038,7 +2038,7 @@
    "link_fieldname": "consolidated_invoice"
   }
  ],
- "modified": "2021-10-21 20:19:38.667508",
+ "modified": "2021-12-23 20:19:38.667508",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 321b453..98bc953 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -862,11 +862,11 @@
 		# Checked both rounding_adjustment and rounded_total
 		# because rounded_total had value even before introcution of posting GLE based on rounded total
 		grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
+		base_grand_total = flt(self.base_rounded_total if (self.base_rounding_adjustment and self.base_rounded_total)
+			else self.base_grand_total, self.precision("base_grand_total"))
+
 		if grand_total and not self.is_internal_transfer():
 			# Didnot use base_grand_total to book rounding loss gle
-			grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
-				self.precision("grand_total"))
-
 			gl_entries.append(
 				self.get_gl_dict({
 					"account": self.debit_to,
@@ -874,8 +874,8 @@
 					"party": self.customer,
 					"due_date": self.due_date,
 					"against": self.against_income_account,
-					"debit": grand_total_in_company_currency,
-					"debit_in_account_currency": grand_total_in_company_currency \
+					"debit": base_grand_total,
+					"debit_in_account_currency": base_grand_total \
 						if self.party_account_currency==self.company_currency else grand_total,
 					"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
 					"against_voucher_type": self.doctype,
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 6a488ea..c02c80a 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -20,6 +20,7 @@
 from erpnext.accounts.utils import PaymentEntryUnlinkError
 from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
 from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data
+from erpnext.controllers.accounts_controller import update_invoice_status
 from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
 from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
 from erpnext.regional.india.utils import get_ewb_data
@@ -2385,6 +2386,41 @@
 		si.reload()
 		self.assertEqual(si.status, "Paid")
 
+	def test_update_invoice_status(self):
+		today = nowdate()
+
+		# Sales Invoice without Payment Schedule
+		si = create_sales_invoice(posting_date=add_days(today, -5))
+
+		# Sales Invoice with Payment Schedule
+		si_with_payment_schedule = create_sales_invoice(do_not_submit=True)
+		si_with_payment_schedule.extend("payment_schedule", [
+			{
+				"due_date": add_days(today, -5),
+				"invoice_portion": 50,
+				"payment_amount": si_with_payment_schedule.grand_total / 2
+			},
+			{
+				"due_date": add_days(today, 5),
+				"invoice_portion": 50,
+				"payment_amount": si_with_payment_schedule.grand_total / 2
+			}
+		])
+		si_with_payment_schedule.submit()
+
+
+		for invoice in (si, si_with_payment_schedule):
+			invoice.db_set("status", "Unpaid")
+			update_invoice_status()
+			invoice.reload()
+			self.assertEqual(invoice.status, "Overdue")
+
+			invoice.db_set("status", "Unpaid and Discounted")
+			update_invoice_status()
+			invoice.reload()
+			self.assertEqual(invoice.status, "Overdue and Discounted")
+
+
 	def test_sales_commission(self):
 		si = frappe.copy_doc(test_records[0])
 		item = copy.deepcopy(si.get('items')[0])
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
index 305cddb..715cd64 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
@@ -117,6 +117,11 @@
 			"label": __("Show Future Payments"),
 			"fieldtype": "Check",
 		},
+		{
+			"fieldname":"show_gl_balance",
+			"label": __("Show GL Balance"),
+			"fieldtype": "Check",
+		},
 	],
 
 	onload: function(report) {
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
index 3c94629..4559fa9 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
@@ -4,7 +4,8 @@
 
 import frappe
 from frappe import _, scrub
-from frappe.utils import cint
+from frappe.utils import cint, flt
+from six import iteritems
 
 from erpnext.accounts.party import get_partywise_advanced_payment_amount
 from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
@@ -36,7 +37,10 @@
 		party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
 			self.filters.report_date, self.filters.show_future_payments, self.filters.company) or {}
 
-		for party, party_dict in self.party_total.items():
+		if self.filters.show_gl_balance:
+			gl_balance_map = get_gl_balance(self.filters.report_date)
+
+		for party, party_dict in iteritems(self.party_total):
 			if party_dict.outstanding == 0:
 				continue
 
@@ -55,6 +59,10 @@
 			# but in summary report advance shown in separate column
 			row.paid -= row.advance
 
+			if self.filters.show_gl_balance:
+				row.gl_balance = gl_balance_map.get(party)
+				row.diff = flt(row.outstanding) - flt(row.gl_balance)
+
 			self.data.append(row)
 
 	def get_party_total(self, args):
@@ -114,6 +122,10 @@
 		self.add_column(_(credit_debit_label), fieldname='credit_note')
 		self.add_column(_('Outstanding Amount'), fieldname='outstanding')
 
+		if self.filters.show_gl_balance:
+			self.add_column(_('GL Balance'), fieldname='gl_balance')
+			self.add_column(_('Difference'), fieldname='diff')
+
 		self.setup_ageing_columns()
 
 		if self.party_type == "Customer":
@@ -140,3 +152,7 @@
 
 		# Add column for total due amount
 		self.add_column(label="Total Amount Due", fieldname='total_due')
+
+def get_gl_balance(report_date):
+	return frappe._dict(frappe.db.get_all("GL Entry", fields=['party', 'sum(debit -  credit)'],
+		filters={'posting_date': ("<=", report_date), 'is_cancelled': 0}, group_by='party', as_list=1))
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index b296876..010284c 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -167,7 +167,7 @@
 			"fieldname": "include_dimensions",
 			"label": __("Consider Accounting Dimensions"),
 			"fieldtype": "Check",
-			"default": 0
+			"default": 1
 		},
 		{
 			"fieldname": "show_opening_entries",
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 385c8b2..7f27920 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -448,9 +448,11 @@
 
 			elif group_by_voucher_consolidated:
 				keylist = [gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account")]
-				for dim in accounting_dimensions:
-					keylist.append(gle.get(dim))
-				keylist.append(gle.get("cost_center"))
+				if filters.get("include_dimensions"):
+					for dim in accounting_dimensions:
+						keylist.append(gle.get(dim))
+					keylist.append(gle.get("cost_center"))
+
 				key = tuple(keylist)
 				if key not in consolidated_gle:
 					consolidated_gle.setdefault(key, gle)
@@ -547,10 +549,7 @@
 			"fieldname": "balance",
 			"fieldtype": "Float",
 			"width": 130
-		}
-	]
-
-	columns.extend([
+		},
 		{
 			"label": _("Voucher Type"),
 			"fieldname": "voucher_type",
@@ -584,7 +583,7 @@
 			"fieldname": "project",
 			"width": 100
 		}
-	])
+	]
 
 	if filters.get("include_dimensions"):
 		for dim in get_accounting_dimensions(as_list = False):
@@ -594,14 +593,14 @@
 				"fieldname": dim.fieldname,
 				"width": 100
 			})
-
-	columns.extend([
-		{
+		columns.append({
 			"label": _("Cost Center"),
 			"options": "Cost Center",
 			"fieldname": "cost_center",
 			"width": 100
-		},
+		})
+
+	columns.extend([
 		{
 			"label": _("Against Voucher Type"),
 			"fieldname": "against_voucher_type",
diff --git a/erpnext/accounts/test/test_reports.py b/erpnext/accounts/test/test_reports.py
new file mode 100644
index 0000000..78c109a
--- /dev/null
+++ b/erpnext/accounts/test/test_reports.py
@@ -0,0 +1,48 @@
+import unittest
+from typing import List, Tuple
+
+from erpnext.tests.utils import ReportFilters, ReportName, execute_script_report
+
+DEFAULT_FILTERS = {
+	"company": "_Test Company",
+	"from_date": "2010-01-01",
+	"to_date": "2030-01-01",
+	"period_start_date": "2010-01-01",
+	"period_end_date": "2030-01-01"
+}
+
+
+REPORT_FILTER_TEST_CASES: List[Tuple[ReportName, ReportFilters]] = [
+	("General Ledger", {"group_by": "Group by Voucher (Consolidated)"} ),
+	("General Ledger", {"group_by": "Group by Voucher (Consolidated)", "include_dimensions": 1} ),
+	("Accounts Payable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
+	("Accounts Receivable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
+	("Consolidated Financial Statement", {"report": "Balance Sheet"} ),
+	("Consolidated Financial Statement", {"report": "Profit and Loss Statement"} ),
+	("Consolidated Financial Statement", {"report": "Cash Flow"} ),
+	("Gross Profit", {"group_by": "Invoice"}),
+	("Gross Profit", {"group_by": "Item Code"}),
+	("Gross Profit", {"group_by": "Item Group"}),
+	("Gross Profit", {"group_by": "Customer"}),
+	("Gross Profit", {"group_by": "Customer Group"}),
+	("Item-wise Sales Register", {}),
+	("Item-wise Purchase Register", {}),
+	("Sales Register", {}),
+	("Purchase Register", {}),
+	("Tax Detail", {"mode": "run", "report_name": "Tax Detail"},),
+]
+
+OPTIONAL_FILTERS = {}
+
+
+class TestReports(unittest.TestCase):
+	def test_execute_all_accounts_reports(self):
+		"""Test that all script report in stock modules are executable with supported filters"""
+		for report, filter in REPORT_FILTER_TEST_CASES:
+			execute_script_report(
+				report_name=report,
+				module="Accounts",
+				filters=filter,
+				default_filters=DEFAULT_FILTERS,
+				optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
+			)
diff --git a/erpnext/agriculture/doctype/__init__.py b/erpnext/agriculture/doctype/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/__init__.py b/erpnext/agriculture/doctype/agriculture_analysis_criteria/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.js b/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.js
deleted file mode 100644
index e236cc6..0000000
--- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Agriculture Analysis Criteria', {
-	refresh: function(frm) {
-
-	}
-});
diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.json b/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.json
deleted file mode 100644
index bb5e4d9..0000000
--- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.json
+++ /dev/null
@@ -1,182 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "field:title", 
- "beta": 0, 
- "creation": "2017-12-05 16:37:46.599982", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "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": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "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": 1
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "standard", 
-   "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": "Standard", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "linked_doctype", 
-   "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": "Linked Doctype", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "\nWater Analysis\nSoil Analysis\nPlant Analysis\nFertilizer\nSoil Texture\nWeather", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:27:36.678832", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Agriculture Analysis Criteria", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.py b/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.py
deleted file mode 100644
index 1945992..0000000
--- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/agriculture_analysis_criteria.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class AgricultureAnalysisCriteria(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.py b/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.py
deleted file mode 100644
index 91e6f3f..0000000
--- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestAgricultureAnalysisCriteria(unittest.TestCase):
-	pass
diff --git a/erpnext/agriculture/doctype/agriculture_task/__init__.py b/erpnext/agriculture/doctype/agriculture_task/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/agriculture_task/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.js b/erpnext/agriculture/doctype/agriculture_task/agriculture_task.js
deleted file mode 100644
index 4d6b959..0000000
--- a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Agriculture Task', {
-	refresh: function(frm) {
-
-	}
-});
diff --git a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.json b/erpnext/agriculture/doctype/agriculture_task/agriculture_task.json
deleted file mode 100644
index d943d77..0000000
--- a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.json
+++ /dev/null
@@ -1,212 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "AG-TASK-.#####", 
- "beta": 0, 
- "creation": "2017-10-26 15:51:19.602452", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "task_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Task Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "", 
-   "fieldname": "start_day", 
-   "fieldtype": "Int", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Start Day", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "", 
-   "fieldname": "end_day", 
-   "fieldtype": "Int", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "End Day", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "Ignore holidays", 
-   "fieldname": "holiday_management", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Holiday Management", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Ignore holidays\nPrevious Business Day\nNext Business Day", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "Low", 
-   "fieldname": "priority", 
-   "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": "Priority", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Low\nMedium\nHigh\nUrgent", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:28:08.679157", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Agriculture Task", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.py b/erpnext/agriculture/doctype/agriculture_task/agriculture_task.py
deleted file mode 100644
index dab2998..0000000
--- a/erpnext/agriculture/doctype/agriculture_task/agriculture_task.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class AgricultureTask(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.py b/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.py
deleted file mode 100644
index 94d7915..0000000
--- a/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestAgricultureTask(unittest.TestCase):
-	pass
diff --git a/erpnext/agriculture/doctype/crop/__init__.py b/erpnext/agriculture/doctype/crop/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/crop/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/crop/crop.js b/erpnext/agriculture/doctype/crop/crop.js
deleted file mode 100644
index 5508246..0000000
--- a/erpnext/agriculture/doctype/crop/crop.js
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.provide("erpnext.crop");
-
-frappe.ui.form.on('Crop', {
-	refresh: (frm) => {
-		frm.fields_dict.materials_required.grid.set_column_disp('bom_no', false);
-	}
-});
-
-frappe.ui.form.on("BOM Item", {
-	item_code: (frm, cdt, cdn) => {
-		erpnext.crop.update_item_rate_uom(frm, cdt, cdn);
-	},
-	qty: (frm, cdt, cdn) => {
-		erpnext.crop.update_item_qty_amount(frm, cdt, cdn);
-	},
-	rate: (frm, cdt, cdn) => {
-		erpnext.crop.update_item_qty_amount(frm, cdt, cdn);
-	}
-});
-
-erpnext.crop.update_item_rate_uom = function(frm, cdt, cdn) {
-	let material_list = ['materials_required', 'produce', 'byproducts'];
-	material_list.forEach((material) => {
-		frm.doc[material].forEach((item, index) => {
-			if (item.name == cdn && item.item_code){
-				frappe.call({
-					method:'erpnext.agriculture.doctype.crop.crop.get_item_details',
-					args: {
-						item_code: item.item_code
-					},
-					callback: (r) => {
-						frappe.model.set_value('BOM Item', item.name, 'uom', r.message.uom);
-						frappe.model.set_value('BOM Item', item.name, 'rate', r.message.rate);
-					}
-				});
-			}
-		});
-	});
-};
-
-erpnext.crop.update_item_qty_amount = function(frm, cdt, cdn) {
-	let material_list = ['materials_required', 'produce', 'byproducts'];
-	material_list.forEach((material) => {
-		frm.doc[material].forEach((item, index) => {
-			if (item.name == cdn){
-				if (!frappe.model.get_value('BOM Item', item.name, 'qty'))
-					frappe.model.set_value('BOM Item', item.name, 'qty', 1);
-				frappe.model.set_value('BOM Item', item.name, 'amount', item.qty * item.rate);
-			}
-		});
-	});
-};
diff --git a/erpnext/agriculture/doctype/crop/crop.json b/erpnext/agriculture/doctype/crop/crop.json
deleted file mode 100644
index e357abb..0000000
--- a/erpnext/agriculture/doctype/crop/crop.json
+++ /dev/null
@@ -1,1110 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "field:title", 
- "beta": 0, 
- "creation": "2017-10-20 01:16:17.606174", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "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": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 1
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_2", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "crop_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Crop Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_4", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "scientific_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Scientific Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "You can define all the tasks which need to carried out for this crop here. The day field is used to mention the day on which the task needs to be carried out, 1 being the 1st day, etc.. ", 
-   "fieldname": "section_break_20", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Tasks", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "agriculture_task", 
-   "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": "Agriculture Task", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Task", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "period", 
-   "fieldtype": "Int", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Period", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_9", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "crop_spacing", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Crop Spacing", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "crop_spacing_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Crop Spacing UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_12", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "row_spacing", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Row Spacing", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "row_spacing_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Row Spacing UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "type", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Annual\nPerennial\nBiennial", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_6", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "category", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Category", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_8", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "target_warehouse", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Target Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Warehouse", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_12", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "planting_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Planting UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "planting_area", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Planting Area", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_14", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "yield_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Yield UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_16", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_17", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Materials Required", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "materials_required", 
-   "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": "Materials Required", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "BOM Item", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_19", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Produced Items", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "produce", 
-   "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": "Produce", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "BOM Item", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_18", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Byproducts", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "byproducts", 
-   "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": "Byproducts", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "BOM Item", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:27:10.651075", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Crop", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/crop/crop.py b/erpnext/agriculture/doctype/crop/crop.py
deleted file mode 100644
index ed2073c..0000000
--- a/erpnext/agriculture/doctype/crop/crop.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-
-
-class Crop(Document):
-	def validate(self):
-		self.validate_crop_tasks()
-
-	def validate_crop_tasks(self):
-		for task in self.agriculture_task:
-			if task.start_day > task.end_day:
-				frappe.throw(_("Start day is greater than end day in task '{0}'").format(task.task_name))
-
-		# Verify that the crop period is correct
-		max_crop_period = max([task.end_day for task in self.agriculture_task])
-		self.period = max(self.period, max_crop_period)
-
-		# Sort the crop tasks based on start days,
-		# maintaining the order for same-day tasks
-		self.agriculture_task.sort(key=lambda task: task.start_day)
-
-
-@frappe.whitelist()
-def get_item_details(item_code):
-	item = frappe.get_doc('Item', item_code)
-	return {"uom": item.stock_uom, "rate": item.valuation_rate}
diff --git a/erpnext/agriculture/doctype/crop/crop_dashboard.py b/erpnext/agriculture/doctype/crop/crop_dashboard.py
deleted file mode 100644
index 37cdbb2..0000000
--- a/erpnext/agriculture/doctype/crop/crop_dashboard.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from frappe import _
-
-
-def get_data():
-	return {
-		'transactions': [
-			{
-				'label': _('Crop Cycle'),
-				'items': ['Crop Cycle']
-			}
-		]
-	}
diff --git a/erpnext/agriculture/doctype/crop/test_crop.py b/erpnext/agriculture/doctype/crop/test_crop.py
deleted file mode 100644
index c79a367..0000000
--- a/erpnext/agriculture/doctype/crop/test_crop.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-test_dependencies = ["Fertilizer"]
-
-class TestCrop(unittest.TestCase):
-	def test_crop_period(self):
-		basil = frappe.get_doc('Crop', 'Basil from seed')
-		self.assertEqual(basil.period, 15)
diff --git a/erpnext/agriculture/doctype/crop/test_records.json b/erpnext/agriculture/doctype/crop/test_records.json
deleted file mode 100644
index 41ddb9a..0000000
--- a/erpnext/agriculture/doctype/crop/test_records.json
+++ /dev/null
@@ -1,80 +0,0 @@
-[
-	{
-		"doctype": "Item",
-		"item_code": "Basil Seeds",
-		"item_name": "Basil Seeds",
-		"item_group": "Seed"
-	},
-	{
-		"doctype": "Item",
-		"item_code": "Twigs",
-		"item_name": "Twigs",
-		"item_group": "By-product"
-	},
-	{
-		"doctype": "Item",
-		"item_code": "Basil Leaves",
-		"item_name": "Basil Leaves",
-		"item_group": "Produce"
-	},
-	{
-		"doctype": "Crop",
-		"title": "Basil from seed",
-		"crop_name": "Basil",
-		"scientific_name": "Ocimum basilicum",
-		"materials_required": [{
-			"item_code": "Basil Seeds",
-			"qty": "25",
-			"uom": "Nos",
-			"rate": "1"
-		}, {
-			"item_code": "Urea",
-			"qty": "5",
-			"uom": "Kg",
-			"rate": "10"
-		}],
-		"byproducts": [{
-			"item_code": "Twigs",
-			"qty": "25",
-			"uom": "Nos",
-			"rate": "1"
-		}],
-		"produce": [{
-			"item_code": "Basil Leaves",
-			"qty": "100",
-			"uom": "Nos",
-			"rate": "1"
-		}],
-		"agriculture_task": [{
-			"task_name": "Plough the field",
-			"start_day": 1,
-			"end_day": 1,
-			"holiday_management": "Ignore holidays"
-		}, {
-			"task_name": "Plant the seeds",
-			"start_day": 2,
-			"end_day": 3,
-			"holiday_management": "Ignore holidays"
-		}, {
-			"task_name": "Water the field",
-			"start_day": 4,
-			"end_day": 4,
-			"holiday_management": "Ignore holidays"
-		}, {
-			"task_name": "First harvest",
-			"start_day": 8,
-			"end_day": 8,
-			"holiday_management": "Ignore holidays"
-		}, {
-			"task_name": "Add the fertilizer",
-			"start_day": 10,
-			"end_day": 12,
-			"holiday_management": "Ignore holidays"
-		}, {
-			"task_name": "Final cut",
-			"start_day": 15,
-			"end_day": 15,
-			"holiday_management": "Ignore holidays"
-		}]
-	}
-]
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/crop_cycle/__init__.py b/erpnext/agriculture/doctype/crop_cycle/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/crop_cycle/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.js b/erpnext/agriculture/doctype/crop_cycle/crop_cycle.js
deleted file mode 100644
index 94392e7..0000000
--- a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Crop Cycle', {
-	refresh: (frm) => {
-		if (!frm.doc.__islocal)
-			frm.add_custom_button(__('Reload Linked Analysis'), () => frm.call("reload_linked_analysis"));
-
-		frappe.realtime.on("List of Linked Docs", (output) => {
-			let analysis_doctypes = ['Soil Texture', 'Plant Analysis', 'Soil Analysis'];
-			let analysis_doctypes_docs = ['soil_texture', 'plant_analysis', 'soil_analysis'];
-			let obj_to_append = {soil_analysis: [], soil_texture: [], plant_analysis: []};
-			output['Location'].forEach( (land_doc) => {
-				analysis_doctypes.forEach( (doctype) => {
-					output[doctype].forEach( (analysis_doc) => {
-						let point_to_be_tested = JSON.parse(analysis_doc.location).features[0].geometry.coordinates;
-						let poly_of_land = JSON.parse(land_doc.location).features[0].geometry.coordinates[0];
-						if (is_in_land_unit(point_to_be_tested, poly_of_land)){
-							obj_to_append[analysis_doctypes_docs[analysis_doctypes.indexOf(doctype)]].push(analysis_doc.name);
-						}
-					});
-				});
-			});
-			frm.call('append_to_child', {
-				obj_to_append: obj_to_append
-			});
-		});
-	}
-});
-
-function is_in_land_unit(point, vs) {
-	// ray-casting algorithm based on
-	// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
-
-	var x = point[0], y = point[1];
-
-	var inside = false;
-	for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
-		var xi = vs[i][0], yi = vs[i][1];
-		var xj = vs[j][0], yj = vs[j][1];
-
-		var intersect = ((yi > y) != (yj > y))
-			&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
-		if (intersect) inside = !inside;
-	}
-
-	return inside;
-};
diff --git a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.json b/erpnext/agriculture/doctype/crop_cycle/crop_cycle.json
deleted file mode 100644
index a076718..0000000
--- a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.json
+++ /dev/null
@@ -1,904 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "field:title", 
- "beta": 0, 
- "creation": "2017-11-02 03:09:35.449880", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "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": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 1
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "crop", 
-   "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": "Crop", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Crop", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "", 
-   "fieldname": "column_break_3", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Linked Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "A link to all the Locations in which the Crop is growing", 
-   "fieldname": "linked_location", 
-   "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": "Linked Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Linked Location", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_3", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:!doc.__islocal", 
-   "fieldname": "project", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Project", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Project", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_12", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "This will be day 1 of the crop cycle", 
-   "fieldname": "start_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Start Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "project.expected_end_date", 
-   "fieldname": "end_date", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "End Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_7", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "iso_8601_standard", 
-   "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": "ISO 8601 standard", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_5", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "cycle_type", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Cycle Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Yearly\nLess than a year", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_12", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "The minimum length between each plant in the field for optimum growth", 
-   "fetch_from": "crop.crop_spacing", 
-   "fieldname": "crop_spacing", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Crop Spacing", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "crop_spacing_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Crop Spacing UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_11", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "The minimum distance between rows of plants for optimum growth", 
-   "fetch_from": "crop.row_spacing", 
-   "fieldname": "row_spacing", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Row Spacing", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "row_spacing_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Row Spacing UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:!doc.__islocal", 
-   "description": "List of diseases detected on the field. When selected it'll automatically add a list of tasks to deal with the disease ", 
-   "fieldname": "section_break_14", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Detected Diseases", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "detected_disease", 
-   "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": "Detected Disease", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Detected Disease", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 1, 
-   "collapsible_depends_on": "eval:false", 
-   "columns": 0, 
-   "fieldname": "section_break_22", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "LInked Analysis", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_texture", 
-   "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": "Soil Texture", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Linked Soil Texture", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_analysis", 
-   "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": "Soil Analysis", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Linked Soil Analysis", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "plant_analysis", 
-   "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": "Plant Analysis", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Linked Plant Analysis", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:31:47.602312", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Crop Cycle", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.py b/erpnext/agriculture/doctype/crop_cycle/crop_cycle.py
deleted file mode 100644
index 43c5bbd..0000000
--- a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import ast
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-from frappe.utils import add_days
-
-
-class CropCycle(Document):
-	def validate(self):
-		self.set_missing_values()
-
-	def after_insert(self):
-		self.create_crop_cycle_project()
-		self.create_tasks_for_diseases()
-
-	def on_update(self):
-		self.create_tasks_for_diseases()
-
-	def set_missing_values(self):
-		crop = frappe.get_doc('Crop', self.crop)
-
-		if not self.crop_spacing_uom:
-			self.crop_spacing_uom = crop.crop_spacing_uom
-
-		if not self.row_spacing_uom:
-			self.row_spacing_uom = crop.row_spacing_uom
-
-	def create_crop_cycle_project(self):
-		crop = frappe.get_doc('Crop', self.crop)
-
-		self.project = self.create_project(crop.period, crop.agriculture_task)
-		self.create_task(crop.agriculture_task, self.project, self.start_date)
-
-	def create_tasks_for_diseases(self):
-		for disease in self.detected_disease:
-			if not disease.tasks_created:
-				self.import_disease_tasks(disease.disease, disease.start_date)
-				disease.tasks_created = True
-
-				frappe.msgprint(_("Tasks have been created for managing the {0} disease (on row {1})").format(disease.disease, disease.idx))
-
-	def import_disease_tasks(self, disease, start_date):
-		disease_doc = frappe.get_doc('Disease', disease)
-		self.create_task(disease_doc.treatment_task, self.project, start_date)
-
-	def create_project(self, period, crop_tasks):
-		project = frappe.get_doc({
-			"doctype": "Project",
-			"project_name": self.title,
-			"expected_start_date": self.start_date,
-			"expected_end_date": add_days(self.start_date, period - 1)
-		}).insert()
-
-		return project.name
-
-	def create_task(self, crop_tasks, project_name, start_date):
-		for crop_task in crop_tasks:
-			frappe.get_doc({
-				"doctype": "Task",
-				"subject": crop_task.get("task_name"),
-				"priority": crop_task.get("priority"),
-				"project": project_name,
-				"exp_start_date": add_days(start_date, crop_task.get("start_day") - 1),
-				"exp_end_date": add_days(start_date, crop_task.get("end_day") - 1)
-			}).insert()
-
-	@frappe.whitelist()
-	def reload_linked_analysis(self):
-		linked_doctypes = ['Soil Texture', 'Soil Analysis', 'Plant Analysis']
-		required_fields = ['location', 'name', 'collection_datetime']
-		output = {}
-
-		for doctype in linked_doctypes:
-			output[doctype] = frappe.get_all(doctype, fields=required_fields)
-
-		output['Location'] = []
-
-		for location in self.linked_location:
-			output['Location'].append(frappe.get_doc('Location', location.location))
-
-		frappe.publish_realtime("List of Linked Docs",
-								output, user=frappe.session.user)
-
-	@frappe.whitelist()
-	def append_to_child(self, obj_to_append):
-		for doctype in obj_to_append:
-			for doc_name in set(obj_to_append[doctype]):
-				self.append(doctype, {doctype: doc_name})
-
-		self.save()
-
-
-def get_coordinates(doc):
-	return ast.literal_eval(doc.location).get('features')[0].get('geometry').get('coordinates')
-
-
-def get_geometry_type(doc):
-	return ast.literal_eval(doc.location).get('features')[0].get('geometry').get('type')
-
-
-def is_in_location(point, vs):
-	x, y = point
-	inside = False
-
-	j = len(vs) - 1
-	i = 0
-
-	while i < len(vs):
-		xi, yi = vs[i]
-		xj, yj = vs[j]
-
-		intersect = ((yi > y) != (yj > y)) and (
-			x < (xj - xi) * (y - yi) / (yj - yi) + xi)
-
-		if intersect:
-			inside = not inside
-
-		i = j
-		j += 1
-
-	return inside
diff --git a/erpnext/agriculture/doctype/crop_cycle/test_crop_cycle.py b/erpnext/agriculture/doctype/crop_cycle/test_crop_cycle.py
deleted file mode 100644
index e4765a5..0000000
--- a/erpnext/agriculture/doctype/crop_cycle/test_crop_cycle.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-from frappe.utils import datetime
-
-test_dependencies = ["Crop", "Fertilizer", "Location", "Disease"]
-
-
-class TestCropCycle(unittest.TestCase):
-	def test_crop_cycle_creation(self):
-		cycle = frappe.get_doc('Crop Cycle', 'Basil from seed 2017')
-		self.assertTrue(frappe.db.exists('Crop Cycle', 'Basil from seed 2017'))
-
-		# check if the tasks were created
-		self.assertEqual(check_task_creation(), True)
-		self.assertEqual(check_project_creation(), True)
-
-
-def check_task_creation():
-	all_task_dict = {
-		"Survey and find the aphid locations": {
-			"exp_start_date": datetime.date(2017, 11, 21),
-			"exp_end_date": datetime.date(2017, 11, 22)
-		},
-		"Apply Pesticides": {
-			"exp_start_date": datetime.date(2017, 11, 23),
-			"exp_end_date": datetime.date(2017, 11, 23)
-		},
-		"Plough the field": {
-			"exp_start_date": datetime.date(2017, 11, 11),
-			"exp_end_date": datetime.date(2017, 11, 11)
-		},
-		"Plant the seeds": {
-			"exp_start_date": datetime.date(2017, 11, 12),
-			"exp_end_date": datetime.date(2017, 11, 13)
-		},
-		"Water the field": {
-			"exp_start_date": datetime.date(2017, 11, 14),
-			"exp_end_date": datetime.date(2017, 11, 14)
-		},
-		"First harvest": {
-			"exp_start_date": datetime.date(2017, 11, 18),
-			"exp_end_date": datetime.date(2017, 11, 18)
-		},
-		"Add the fertilizer": {
-			"exp_start_date": datetime.date(2017, 11, 20),
-			"exp_end_date": datetime.date(2017, 11, 22)
-		},
-		"Final cut": {
-			"exp_start_date": datetime.date(2017, 11, 25),
-			"exp_end_date": datetime.date(2017, 11, 25)
-		}
-	}
-
-	all_tasks = frappe.get_all('Task')
-
-	for task in all_tasks:
-		sample_task = frappe.get_doc('Task', task.name)
-
-		if sample_task.subject in list(all_task_dict):
-			if sample_task.exp_start_date != all_task_dict[sample_task.subject]['exp_start_date'] or sample_task.exp_end_date != all_task_dict[sample_task.subject]['exp_end_date']:
-				return False
-			all_task_dict.pop(sample_task.subject)
-
-	return True if not all_task_dict else False
-
-
-def check_project_creation():
-	return True if frappe.db.exists('Project', {'project_name': 'Basil from seed 2017'}) else False
diff --git a/erpnext/agriculture/doctype/crop_cycle/test_records.json b/erpnext/agriculture/doctype/crop_cycle/test_records.json
deleted file mode 100644
index 5c79f10..0000000
--- a/erpnext/agriculture/doctype/crop_cycle/test_records.json
+++ /dev/null
@@ -1,15 +0,0 @@
-[
-	{
-		"doctype": "Crop Cycle",
-		"title": "Basil from seed 2017",
-		"linked_location": [{
-			"location": "Basil Farm"
-		}],
-		"crop": "Basil from seed",
-		"start_date": "2017-11-11",
-		"detected_disease": [{
-			"disease": "Aphids",
-			"start_date": "2017-11-21"
-		}]
-	}
-]
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/detected_disease/__init__.py b/erpnext/agriculture/doctype/detected_disease/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/detected_disease/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/detected_disease/detected_disease.json b/erpnext/agriculture/doctype/detected_disease/detected_disease.json
deleted file mode 100644
index f670cd3..0000000
--- a/erpnext/agriculture/doctype/detected_disease/detected_disease.json
+++ /dev/null
@@ -1,142 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-11-20 17:31:30.772779", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "disease", 
-   "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": "Disease", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Disease", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "start_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Start Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "tasks_created", 
-   "fieldtype": "Check", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Tasks Created", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:27:47.463994", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Detected Disease", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/detected_disease/detected_disease.py b/erpnext/agriculture/doctype/detected_disease/detected_disease.py
deleted file mode 100644
index e507add..0000000
--- a/erpnext/agriculture/doctype/detected_disease/detected_disease.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class DetectedDisease(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/disease/__init__.py b/erpnext/agriculture/doctype/disease/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/disease/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/disease/disease.js b/erpnext/agriculture/doctype/disease/disease.js
deleted file mode 100644
index f6b678c..0000000
--- a/erpnext/agriculture/doctype/disease/disease.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Disease', {
-	refresh: function(frm) {
-
-	}
-});
diff --git a/erpnext/agriculture/doctype/disease/disease.json b/erpnext/agriculture/doctype/disease/disease.json
deleted file mode 100644
index 16b735a..0000000
--- a/erpnext/agriculture/doctype/disease/disease.json
+++ /dev/null
@@ -1,308 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "field:common_name", 
- "beta": 0, 
- "creation": "2017-11-20 17:16:54.496355", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "common_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Common Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 1
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "scientific_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Scientific Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_3", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "treatment_task", 
-   "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": "Treatment Task", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Task", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "treatment_period", 
-   "fieldtype": "Int", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Treatment Period", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_2", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Treatment Task", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Long Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:27:25.076490", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Disease", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/disease/disease.py b/erpnext/agriculture/doctype/disease/disease.py
deleted file mode 100644
index 30ab298..0000000
--- a/erpnext/agriculture/doctype/disease/disease.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-
-
-class Disease(Document):
-	def validate(self):
-		max_period = 0
-		for task in self.treatment_task:
-			# validate start_day is not > end_day
-			if task.start_day > task.end_day:
-				frappe.throw(_("Start day is greater than end day in task '{0}'").format(task.task_name))
-			# to calculate the period of the Crop Cycle
-			if task.end_day > max_period: max_period = task.end_day
-		self.treatment_period = max_period
diff --git a/erpnext/agriculture/doctype/disease/test_disease.py b/erpnext/agriculture/doctype/disease/test_disease.py
deleted file mode 100644
index 6a6f1e7..0000000
--- a/erpnext/agriculture/doctype/disease/test_disease.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-
-class TestDisease(unittest.TestCase):
-	def test_treatment_period(self):
-		disease = frappe.get_doc('Disease', 'Aphids')
-		self.assertEqual(disease.treatment_period, 3)
diff --git a/erpnext/agriculture/doctype/disease/test_records.json b/erpnext/agriculture/doctype/disease/test_records.json
deleted file mode 100644
index e91a611..0000000
--- a/erpnext/agriculture/doctype/disease/test_records.json
+++ /dev/null
@@ -1,18 +0,0 @@
-[
-	{
-		"doctype": "Disease",
-		"common_name": "Aphids",
-		"scientific_name": "Aphidoidea",
-		"treatment_task": [{
-			"task_name": "Survey and find the aphid locations",
-			"start_day": 1,
-			"end_day": 2,
-			"holiday_management": "Ignore holidays"
-		}, {
-			"task_name": "Apply Pesticides",
-			"start_day": 3,
-			"end_day": 3,
-			"holiday_management": "Ignore holidays"
-		}]
-	}
-]
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/fertilizer/__init__.py b/erpnext/agriculture/doctype/fertilizer/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/fertilizer/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/fertilizer/fertilizer.js b/erpnext/agriculture/doctype/fertilizer/fertilizer.js
deleted file mode 100644
index 357e089..0000000
--- a/erpnext/agriculture/doctype/fertilizer/fertilizer.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Fertilizer', {
-	onload: (frm) => {
-		if (frm.doc.fertilizer_contents == undefined) frm.call('load_contents');
-	}
-});
diff --git a/erpnext/agriculture/doctype/fertilizer/fertilizer.json b/erpnext/agriculture/doctype/fertilizer/fertilizer.json
deleted file mode 100644
index 6a18773..0000000
--- a/erpnext/agriculture/doctype/fertilizer/fertilizer.json
+++ /dev/null
@@ -1,307 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "field:fertilizer_name", 
- "beta": 0, 
- "creation": "2017-10-17 18:17:06.175062", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "fertilizer_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Fertilizer Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 1
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Item", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Item", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_2", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "density", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Density (if liquid)", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_28", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Fertilizer Contents", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "fertilizer_contents", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Fertilizer Content", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:26:29.211792", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Fertilizer", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/fertilizer/fertilizer.py b/erpnext/agriculture/doctype/fertilizer/fertilizer.py
deleted file mode 100644
index 2408302..0000000
--- a/erpnext/agriculture/doctype/fertilizer/fertilizer.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.model.document import Document
-
-
-class Fertilizer(Document):
-	@frappe.whitelist()
-	def load_contents(self):
-		docs = frappe.get_all("Agriculture Analysis Criteria", filters={'linked_doctype':'Fertilizer'})
-		for doc in docs:
-			self.append('fertilizer_contents', {'title': str(doc.name)})
diff --git a/erpnext/agriculture/doctype/fertilizer/test_fertilizer.py b/erpnext/agriculture/doctype/fertilizer/test_fertilizer.py
deleted file mode 100644
index c8630ef..0000000
--- a/erpnext/agriculture/doctype/fertilizer/test_fertilizer.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-
-class TestFertilizer(unittest.TestCase):
-	def test_fertilizer_creation(self):
-		self.assertEqual(frappe.db.exists('Fertilizer', 'Urea'), 'Urea')
diff --git a/erpnext/agriculture/doctype/fertilizer/test_records.json b/erpnext/agriculture/doctype/fertilizer/test_records.json
deleted file mode 100644
index ba735cd..0000000
--- a/erpnext/agriculture/doctype/fertilizer/test_records.json
+++ /dev/null
@@ -1,13 +0,0 @@
-[
-	{
-		"doctype": "Item",
-		"item_code": "Urea",
-		"item_name": "Urea",
-		"item_group": "Fertilizer"
-	},
-	{
-		"doctype": "Fertilizer",
-		"fertilizer_name": "Urea",
-		"item": "Urea"
-	}
-]
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/fertilizer_content/__init__.py b/erpnext/agriculture/doctype/fertilizer_content/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/fertilizer_content/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.json b/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.json
deleted file mode 100644
index bf222ab..0000000
--- a/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.json
+++ /dev/null
@@ -1,103 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-12-05 16:54:17.071914", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "value", 
-   "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": "Value", 
-   "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
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2017-12-05 19:20:38.892231", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Fertilizer Content", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.py b/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.py
deleted file mode 100644
index 967c3e0..0000000
--- a/erpnext/agriculture/doctype/fertilizer_content/fertilizer_content.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class FertilizerContent(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/linked_location/__init__.py b/erpnext/agriculture/doctype/linked_location/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/linked_location/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/linked_location/linked_location.json b/erpnext/agriculture/doctype/linked_location/linked_location.json
deleted file mode 100644
index a14ae3d..0000000
--- a/erpnext/agriculture/doctype/linked_location/linked_location.json
+++ /dev/null
@@ -1,77 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-11-22 14:34:59.461273", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "location", 
-   "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": "Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Location", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:27:58.120962", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Linked Location", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/linked_location/linked_location.py b/erpnext/agriculture/doctype/linked_location/linked_location.py
deleted file mode 100644
index e1257f3..0000000
--- a/erpnext/agriculture/doctype/linked_location/linked_location.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class LinkedLocation(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.json b/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.json
deleted file mode 100644
index 57d2aab..0000000
--- a/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.json
+++ /dev/null
@@ -1,77 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-11-22 15:04:25.180446", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "plant_analysis", 
-   "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": "Plant Analysis", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Plant Analysis", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:25:15.359130", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Linked Plant Analysis", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.py b/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.py
deleted file mode 100644
index 0bc04af..0000000
--- a/erpnext/agriculture/doctype/linked_plant_analysis/linked_plant_analysis.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class LinkedPlantAnalysis(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/linked_soil_analysis/__init__.py b/erpnext/agriculture/doctype/linked_soil_analysis/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/linked_soil_analysis/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.json b/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.json
deleted file mode 100644
index 38e5030..0000000
--- a/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.json
+++ /dev/null
@@ -1,77 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-11-22 15:00:37.259063", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_analysis", 
-   "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": "Soil Analysis", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Soil Analysis", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:25:27.670079", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Linked Soil Analysis", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.py b/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.py
deleted file mode 100644
index 0d29055..0000000
--- a/erpnext/agriculture/doctype/linked_soil_analysis/linked_soil_analysis.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class LinkedSoilAnalysis(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/linked_soil_texture/__init__.py b/erpnext/agriculture/doctype/linked_soil_texture/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/linked_soil_texture/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.json b/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.json
deleted file mode 100644
index 80682b0..0000000
--- a/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.json
+++ /dev/null
@@ -1,77 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-11-22 14:58:52.818040", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_texture", 
-   "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": "Soil Texture", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Soil Texture", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:26:17.877616", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Linked Soil Texture", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.py b/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.py
deleted file mode 100644
index 1438853..0000000
--- a/erpnext/agriculture/doctype/linked_soil_texture/linked_soil_texture.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class LinkedSoilTexture(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/plant_analysis/__init__.py b/erpnext/agriculture/doctype/plant_analysis/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/plant_analysis/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.js b/erpnext/agriculture/doctype/plant_analysis/plant_analysis.js
deleted file mode 100644
index 3914f83..0000000
--- a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Plant Analysis', {
-	onload: (frm) => {
-		if (frm.doc.plant_analysis_criteria == undefined) frm.call('load_contents');
-	},
-	refresh: (frm) => {
-		let map_tools = ["a.leaflet-draw-draw-polyline",
-			"a.leaflet-draw-draw-polygon",
-			"a.leaflet-draw-draw-rectangle",
-			"a.leaflet-draw-draw-circle",
-			"a.leaflet-draw-draw-circlemarker"];
-
-		map_tools.forEach((element) => $(element).hide());
-	}
-});
diff --git a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.json b/erpnext/agriculture/doctype/plant_analysis/plant_analysis.json
deleted file mode 100644
index ceb1a5b..0000000
--- a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.json
+++ /dev/null
@@ -1,372 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "AG-PLA-.YYYY.-.#####", 
- "beta": 0, 
- "creation": "2017-10-18 12:45:13.575986", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "crop", 
-   "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": "Crop", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Crop", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_1", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "location", 
-   "fieldtype": "Geolocation", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "collection_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Collection Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "laboratory_testing_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Laboratory Testing Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "result_datetime", 
-   "fieldtype": "Datetime", 
-   "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": "Result Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_2", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Plant Analysis Criterias", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "plant_analysis_criteria", 
-   "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": "", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Plant Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:28:48.087828", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Plant Analysis", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.py b/erpnext/agriculture/doctype/plant_analysis/plant_analysis.py
deleted file mode 100644
index 9a939cd..0000000
--- a/erpnext/agriculture/doctype/plant_analysis/plant_analysis.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.model.document import Document
-
-
-class PlantAnalysis(Document):
-	@frappe.whitelist()
-	def load_contents(self):
-		docs = frappe.get_all("Agriculture Analysis Criteria", filters={'linked_doctype':'Plant Analysis'})
-		for doc in docs:
-			self.append('plant_analysis_criteria', {'title': str(doc.name)})
diff --git a/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.py b/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.py
deleted file mode 100644
index cee241f..0000000
--- a/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestPlantAnalysis(unittest.TestCase):
-	pass
diff --git a/erpnext/agriculture/doctype/plant_analysis_criteria/__init__.py b/erpnext/agriculture/doctype/plant_analysis_criteria/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/plant_analysis_criteria/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.json b/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.json
deleted file mode 100644
index eefc5ee..0000000
--- a/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-12-05 19:23:52.481348", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "value", 
-   "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": "Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "minimum_permissible_value", 
-   "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": "Minimum Permissible Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "maximum_permissible_value", 
-   "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": "Maximum Permissible Value", 
-   "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
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:25:43.714882", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Plant Analysis Criteria", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.py b/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.py
deleted file mode 100644
index 7e6571c..0000000
--- a/erpnext/agriculture/doctype/plant_analysis_criteria/plant_analysis_criteria.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class PlantAnalysisCriteria(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/soil_analysis/__init__.py b/erpnext/agriculture/doctype/soil_analysis/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/soil_analysis/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.js b/erpnext/agriculture/doctype/soil_analysis/soil_analysis.js
deleted file mode 100644
index 12829be..0000000
--- a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Soil Analysis', {
-	onload: (frm) => {
-		if (frm.doc.soil_analysis_criteria == undefined) frm.call('load_contents');
-	},
-	refresh: (frm) => {
-		let map_tools = ["a.leaflet-draw-draw-polyline",
-			"a.leaflet-draw-draw-polygon",
-			"a.leaflet-draw-draw-rectangle",
-			"a.leaflet-draw-draw-circle",
-			"a.leaflet-draw-draw-circlemarker"];
-
-		map_tools.forEach((element) => $(element).hide());
-	}
-});
diff --git a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.json b/erpnext/agriculture/doctype/soil_analysis/soil_analysis.json
deleted file mode 100644
index 59680fa..0000000
--- a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.json
+++ /dev/null
@@ -1,593 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "AG-ANA-.YY.-.MM.-.#####", 
- "beta": 0, 
- "creation": "2017-10-17 19:12:16.728395", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "location", 
-   "fieldtype": "Geolocation", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "collection_datetime", 
-   "fieldtype": "Datetime", 
-   "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": "Collection Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "laboratory_testing_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Laboratory Testing Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "result_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Result Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_3", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "ca_per_k", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Ca/K", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "ca_per_mg", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Ca/Mg", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "mg_per_k", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Mg/K", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_31", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "ca_mg_per_k", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "(Ca+Mg)/K", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "ca_per_k_ca_mg", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Ca/(K+Ca+Mg)", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_28", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "invoice_number", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Invoice Number", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_analysis_criterias", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Soil Analysis Criterias", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_analysis_criteria", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Soil Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:28:58.403760", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Soil Analysis", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.py b/erpnext/agriculture/doctype/soil_analysis/soil_analysis.py
deleted file mode 100644
index 03667fb..0000000
--- a/erpnext/agriculture/doctype/soil_analysis/soil_analysis.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.model.document import Document
-
-
-class SoilAnalysis(Document):
-	@frappe.whitelist()
-	def load_contents(self):
-		docs = frappe.get_all("Agriculture Analysis Criteria", filters={'linked_doctype':'Soil Analysis'})
-		for doc in docs:
-			self.append('soil_analysis_criteria', {'title': str(doc.name)})
diff --git a/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.py b/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.py
deleted file mode 100644
index bb99363..0000000
--- a/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestSoilAnalysis(unittest.TestCase):
-	pass
diff --git a/erpnext/agriculture/doctype/soil_analysis_criteria/__init__.py b/erpnext/agriculture/doctype/soil_analysis_criteria/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/soil_analysis_criteria/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.json b/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.json
deleted file mode 100644
index 860e48a..0000000
--- a/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-12-05 19:36:05.300770", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "value", 
-   "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": "Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "minimum_permissible_value", 
-   "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": "Minimum Permissible Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "maximum_permissible_value", 
-   "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": "Maximum Permissible Value", 
-   "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
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:25:54.359008", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Soil Analysis Criteria", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.py b/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.py
deleted file mode 100644
index f501820..0000000
--- a/erpnext/agriculture/doctype/soil_analysis_criteria/soil_analysis_criteria.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class SoilAnalysisCriteria(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/soil_texture/__init__.py b/erpnext/agriculture/doctype/soil_texture/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/soil_texture/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/soil_texture/soil_texture.js b/erpnext/agriculture/doctype/soil_texture/soil_texture.js
deleted file mode 100644
index 673284b..0000000
--- a/erpnext/agriculture/doctype/soil_texture/soil_texture.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.provide('agriculture');
-
-frappe.ui.form.on('Soil Texture', {
-	refresh: (frm) => {
-		let map_tools = ["a.leaflet-draw-draw-polyline",
-			"a.leaflet-draw-draw-polygon",
-			"a.leaflet-draw-draw-rectangle",
-			"a.leaflet-draw-draw-circle",
-			"a.leaflet-draw-draw-circlemarker"];
-
-		map_tools.forEach((element) => $(element).hide());
-	},
-	onload: function(frm) {
-		if (frm.doc.soil_texture_criteria == undefined) frm.call('load_contents');
-		if (frm.doc.ternary_plot) return;
-		frm.doc.ternary_plot = new agriculture.TernaryPlot({
-			parent: frm.get_field("ternary_plot").$wrapper,
-			clay: frm.doc.clay_composition,
-			sand: frm.doc.sand_composition,
-			silt: frm.doc.silt_composition,
-		});
-	},
-	soil_type: (frm) => {
-		let composition_types = ['clay_composition', 'sand_composition', 'silt_composition'];
-		composition_types.forEach((composition_type) => {
-			frm.doc[composition_type] = 0;
-			frm.refresh_field(composition_type);
-		});
-	},
-	clay_composition: function(frm) {
-		frm.call("update_soil_edit", {
-			soil_type: 'clay_composition'
-		}, () => {
-			refresh_ternary_plot(frm, this);
-		});
-	},
-	sand_composition: function(frm) {
-		frm.call("update_soil_edit", {
-			soil_type: 'sand_composition'
-		}, () => {
-			refresh_ternary_plot(frm, this);
-		});
-	},
-	silt_composition: function(frm) {
-		frm.call("update_soil_edit", {
-			soil_type: 'silt_composition'
-		}, () => {
-			refresh_ternary_plot(frm, this);
-		});
-	}
-});
-
-let refresh_ternary_plot = (frm, me) => {
-	me.ternary_plot.remove_blip();
-	me.ternary_plot.mark_blip({clay: frm.doc.clay_composition, sand: frm.doc.sand_composition, silt: frm.doc.silt_composition});
-};
diff --git a/erpnext/agriculture/doctype/soil_texture/soil_texture.json b/erpnext/agriculture/doctype/soil_texture/soil_texture.json
deleted file mode 100644
index f78c262..0000000
--- a/erpnext/agriculture/doctype/soil_texture/soil_texture.json
+++ /dev/null
@@ -1,533 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "AG-TEX-.YYYY.-.#####", 
- "beta": 0, 
- "creation": "2017-10-18 13:06:47.506762", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "location", 
-   "fieldtype": "Geolocation", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "collection_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Collection Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "laboratory_testing_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Laboratory Testing Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "result_datetime", 
-   "fieldtype": "Datetime", 
-   "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": "Result Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_type", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Soil Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Select\nSand\nLoamy Sand\nSandy Loam\nLoam\nSilt Loam\nSilt\nSandy Clay Loam\nClay Loam\nSilty Clay Loam\nSandy Clay\nSilty Clay\nClay", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "clay_composition", 
-   "fieldtype": "Percent", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Clay Composition (%)", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "sand_composition", 
-   "fieldtype": "Percent", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Sand Composition (%)", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "silt_composition", 
-   "fieldtype": "Percent", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Silt Composition (%)", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_6", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "ternary_plot", 
-   "fieldtype": "HTML", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Ternary Plot", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_15", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Soil Texture Criteria", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "soil_texture_criteria", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Soil Texture Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:29:18.221173", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Soil Texture", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/soil_texture/soil_texture.py b/erpnext/agriculture/doctype/soil_texture/soil_texture.py
deleted file mode 100644
index b1fc9a0..0000000
--- a/erpnext/agriculture/doctype/soil_texture/soil_texture.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-from frappe.utils import cint, flt
-
-
-class SoilTexture(Document):
-	soil_edit_order = [2, 1, 0]
-	soil_types = ['clay_composition', 'sand_composition', 'silt_composition']
-
-	@frappe.whitelist()
-	def load_contents(self):
-		docs = frappe.get_all("Agriculture Analysis Criteria", filters={'linked_doctype':'Soil Texture'})
-		for doc in docs:
-			self.append('soil_texture_criteria', {'title': str(doc.name)})
-
-	def validate(self):
-		self.update_soil_edit('sand_composition')
-		for soil_type in self.soil_types:
-			if self.get(soil_type) > 100 or self.get(soil_type) < 0:
-				frappe.throw(_("{0} should be a value between 0 and 100").format(soil_type))
-		if sum(self.get(soil_type) for soil_type in self.soil_types) != 100:
-			frappe.throw(_('Soil compositions do not add up to 100'))
-
-	@frappe.whitelist()
-	def update_soil_edit(self, soil_type):
-		self.soil_edit_order[self.soil_types.index(soil_type)] = max(self.soil_edit_order)+1
-		self.soil_type = self.get_soil_type()
-
-	def get_soil_type(self):
-		# update the last edited soil type
-		if sum(self.soil_edit_order) < 5: return
-		last_edit_index = self.soil_edit_order.index(min(self.soil_edit_order))
-
-		# set composition of the last edited soil
-		self.set(self.soil_types[last_edit_index],
-			100 - sum(cint(self.get(soil_type)) for soil_type in self.soil_types) + cint(self.get(self.soil_types[last_edit_index])))
-
-		# calculate soil type
-		c, sa, si = flt(self.clay_composition), flt(self.sand_composition), flt(self.silt_composition)
-
-		if si + (1.5 * c) < 15:
-			return 'Sand'
-		elif si + 1.5 * c >= 15 and si + 2 * c < 30:
-			return 'Loamy Sand'
-		elif ((c >= 7 and c < 20) or (sa > 52) and ((si + 2*c) >= 30) or (c < 7 and si < 50 and (si+2*c) >= 30)):
-			return 'Sandy Loam'
-		elif ((c >= 7 and c < 27) and (si >= 28 and si < 50) and (sa <= 52)):
-			return 'Loam'
-		elif ((si >= 50 and (c >= 12 and c < 27)) or ((si >= 50 and si < 80) and c < 12)):
-			return 'Silt Loam'
-		elif (si >= 80 and c < 12):
-			return 'Silt'
-		elif ((c >= 20 and c < 35) and (si < 28) and (sa > 45)):
-			return 'Sandy Clay Loam'
-		elif ((c >= 27 and c < 40) and (sa > 20 and sa <= 45)):
-			return 'Clay Loam'
-		elif ((c >= 27 and c < 40) and (sa  <= 20)):
-			return 'Silty Clay Loam'
-		elif (c >= 35 and sa > 45):
-			return 'Sandy Clay'
-		elif (c >= 40 and si >= 40):
-			return 'Silty Clay'
-		elif (c >= 40 and sa <= 45 and si < 40):
-			return 'Clay'
-		else:
-			return 'Select'
diff --git a/erpnext/agriculture/doctype/soil_texture/test_records.json b/erpnext/agriculture/doctype/soil_texture/test_records.json
deleted file mode 100644
index dcac7ad..0000000
--- a/erpnext/agriculture/doctype/soil_texture/test_records.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[
-	{
-		"doctype": "Soil Texture",
-		"location": "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Point\",\"coordinates\":[72.861242,19.079153]}}]}",
-		"collection_datetime": "2017-11-08",
-		"clay_composition": 20,
-		"sand_composition": 30
-	}
-]
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/soil_texture/test_soil_texture.py b/erpnext/agriculture/doctype/soil_texture/test_soil_texture.py
deleted file mode 100644
index 4549767..0000000
--- a/erpnext/agriculture/doctype/soil_texture/test_soil_texture.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-
-class TestSoilTexture(unittest.TestCase):
-	def test_texture_selection(self):
-		soil_tex = frappe.get_all('Soil Texture', fields=['name'], filters={'collection_datetime': '2017-11-08'})
-		doc = frappe.get_doc('Soil Texture', soil_tex[0].name)
-		self.assertEqual(doc.silt_composition, 50)
-		self.assertEqual(doc.soil_type, 'Silt Loam')
diff --git a/erpnext/agriculture/doctype/soil_texture_criteria/__init__.py b/erpnext/agriculture/doctype/soil_texture_criteria/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/soil_texture_criteria/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.json b/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.json
deleted file mode 100644
index 0cd72b0..0000000
--- a/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-12-05 23:45:17.419610", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "value", 
-   "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": "Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "minimum_permissible_value", 
-   "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": "Minimum Permissible Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "maximum_permissible_value", 
-   "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": "Maximum Permissible Value", 
-   "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
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:26:46.178377", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Soil Texture Criteria", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.py b/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.py
deleted file mode 100644
index 92a0cf9..0000000
--- a/erpnext/agriculture/doctype/soil_texture_criteria/soil_texture_criteria.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class SoilTextureCriteria(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/water_analysis/__init__.py b/erpnext/agriculture/doctype/water_analysis/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/water_analysis/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/water_analysis/test_water_analysis.py b/erpnext/agriculture/doctype/water_analysis/test_water_analysis.py
deleted file mode 100644
index ae144cc..0000000
--- a/erpnext/agriculture/doctype/water_analysis/test_water_analysis.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestWaterAnalysis(unittest.TestCase):
-	pass
diff --git a/erpnext/agriculture/doctype/water_analysis/water_analysis.js b/erpnext/agriculture/doctype/water_analysis/water_analysis.js
deleted file mode 100644
index 13fe3ad..0000000
--- a/erpnext/agriculture/doctype/water_analysis/water_analysis.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Water Analysis', {
-	onload: (frm) => {
-		if (frm.doc.water_analysis_criteria == undefined) frm.call('load_contents');
-	},
-	refresh: (frm) => {
-		let map_tools = ["a.leaflet-draw-draw-polyline",
-			"a.leaflet-draw-draw-polygon",
-			"a.leaflet-draw-draw-rectangle",
-			"a.leaflet-draw-draw-circle",
-			"a.leaflet-draw-draw-circlemarker"];
-
-		map_tools.forEach((element) => $(element).hide());
-	},
-	laboratory_testing_datetime: (frm) => frm.call("update_lab_result_date")
-});
diff --git a/erpnext/agriculture/doctype/water_analysis/water_analysis.json b/erpnext/agriculture/doctype/water_analysis/water_analysis.json
deleted file mode 100644
index f990fef..0000000
--- a/erpnext/agriculture/doctype/water_analysis/water_analysis.json
+++ /dev/null
@@ -1,594 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "HR-WAT-.YYYY.-.#####", 
- "beta": 0, 
- "creation": "2017-10-17 18:51:19.946950", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "location", 
-   "fieldtype": "Geolocation", 
-   "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": "Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "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, 
-   "label": "", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "collection_datetime", 
-   "fieldtype": "Datetime", 
-   "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": "Collection Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "laboratory_testing_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Laboratory Testing Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "result_datetime", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Result Datetime", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "type_of_sample", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Type of Sample", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "container", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Container", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "origin", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Origin", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "collection_temperature", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Collection Temperature ", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "storage_temperature", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Storage Temperature", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "appearance", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Appearance", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "person_responsible", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Person Responsible", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_29", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Water Analysis Criteria", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "water_analysis_criteria", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Water Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:29:08.325644", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Water Analysis", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/water_analysis/water_analysis.py b/erpnext/agriculture/doctype/water_analysis/water_analysis.py
deleted file mode 100644
index 434acec..0000000
--- a/erpnext/agriculture/doctype/water_analysis/water_analysis.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-
-
-class WaterAnalysis(Document):
-	@frappe.whitelist()
-	def load_contents(self):
-		docs = frappe.get_all("Agriculture Analysis Criteria", filters={'linked_doctype':'Water Analysis'})
-		for doc in docs:
-			self.append('water_analysis_criteria', {'title': str(doc.name)})
-
-	@frappe.whitelist()
-	def update_lab_result_date(self):
-		if not self.result_datetime:
-			self.result_datetime = self.laboratory_testing_datetime
-
-	def validate(self):
-		if self.collection_datetime > self.laboratory_testing_datetime:
-			frappe.throw(_('Lab testing datetime cannot be before collection datetime'))
-		if self.laboratory_testing_datetime > self.result_datetime:
-			frappe.throw(_('Lab result datetime cannot be before testing datetime'))
diff --git a/erpnext/agriculture/doctype/water_analysis_criteria/__init__.py b/erpnext/agriculture/doctype/water_analysis_criteria/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/water_analysis_criteria/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.json b/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.json
deleted file mode 100644
index be9f1be..0000000
--- a/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-12-05 23:36:22.723558", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "value", 
-   "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": "Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "minimum_permissible_value", 
-   "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": "Minimum Permissible Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "maximum_permissible_value", 
-   "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": "Maximum Permissible Value", 
-   "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
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:26:07.026834", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Water Analysis Criteria", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.py b/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.py
deleted file mode 100644
index 225c4f6..0000000
--- a/erpnext/agriculture/doctype/water_analysis_criteria/water_analysis_criteria.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class WaterAnalysisCriteria(Document):
-	pass
diff --git a/erpnext/agriculture/doctype/weather/__init__.py b/erpnext/agriculture/doctype/weather/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/agriculture/doctype/weather/__init__.py
+++ /dev/null
diff --git a/erpnext/agriculture/doctype/weather/test_weather.py b/erpnext/agriculture/doctype/weather/test_weather.py
deleted file mode 100644
index 345baa9..0000000
--- a/erpnext/agriculture/doctype/weather/test_weather.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestWeather(unittest.TestCase):
-	pass
diff --git a/erpnext/agriculture/doctype/weather/weather.js b/erpnext/agriculture/doctype/weather/weather.js
deleted file mode 100644
index dadb1d8..0000000
--- a/erpnext/agriculture/doctype/weather/weather.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Weather', {
-	onload: (frm) => {
-		if (frm.doc.weather_parameter == undefined) frm.call('load_contents');
-	}
-});
diff --git a/erpnext/agriculture/doctype/weather/weather.json b/erpnext/agriculture/doctype/weather/weather.json
deleted file mode 100644
index ebab78a..0000000
--- a/erpnext/agriculture/doctype/weather/weather.json
+++ /dev/null
@@ -1,307 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "format:WEA-{date}-{location}", 
- "beta": 0, 
- "creation": "2017-10-17 19:01:05.095598", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "location", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Location", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Location", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "source", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Source", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_3", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_9", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Weather Parameter", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "weather_parameter", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Weather Parameter", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:31:36.839743", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Weather", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Agriculture User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/weather/weather.py b/erpnext/agriculture/doctype/weather/weather.py
deleted file mode 100644
index 8750709..0000000
--- a/erpnext/agriculture/doctype/weather/weather.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.model.document import Document
-
-
-class Weather(Document):
-	@frappe.whitelist()
-	def load_contents(self):
-		docs = frappe.get_all("Agriculture Analysis Criteria", filters={'linked_doctype':'Weather'})
-		for doc in docs:
-			self.append('weather_parameter', {'title': str(doc.name)})
diff --git a/erpnext/agriculture/doctype/weather_parameter/weather_parameter.json b/erpnext/agriculture/doctype/weather_parameter/weather_parameter.json
deleted file mode 100644
index 45c4cfc..0000000
--- a/erpnext/agriculture/doctype/weather_parameter/weather_parameter.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-12-06 00:19:15.967334", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Agriculture Analysis Criteria", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "value", 
-   "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": "Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "minimum_permissible_value", 
-   "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": "Minimum Permissible Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "maximum_permissible_value", 
-   "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": "Maximum Permissible Value", 
-   "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
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:26:58.794373", 
- "modified_by": "Administrator", 
- "module": "Agriculture", 
- "name": "Weather Parameter", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Agriculture", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/weather_parameter/weather_parameter.py b/erpnext/agriculture/doctype/weather_parameter/weather_parameter.py
deleted file mode 100644
index 7f02ab3..0000000
--- a/erpnext/agriculture/doctype/weather_parameter/weather_parameter.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class WeatherParameter(Document):
-	pass
diff --git a/erpnext/agriculture/setup.py b/erpnext/agriculture/setup.py
deleted file mode 100644
index 70931b9..0000000
--- a/erpnext/agriculture/setup.py
+++ /dev/null
@@ -1,429 +0,0 @@
-import frappe
-from frappe import _
-from erpnext.setup.utils import insert_record
-
-def setup_agriculture():
-	if frappe.get_all('Agriculture Analysis Criteria'):
-		# already setup
-		return
-	create_agriculture_data()
-
-def create_agriculture_data():
-	records = [
-		dict(
-			doctype='Item Group',
-			item_group_name='Fertilizer',
-			is_group=0,
-			parent_item_group=_('All Item Groups')),
-		dict(
-			doctype='Item Group',
-			item_group_name='Seed',
-			is_group=0,
-			parent_item_group=_('All Item Groups')),
-		dict(
-			doctype='Item Group',
-			item_group_name='By-product',
-			is_group=0,
-			parent_item_group=_('All Item Groups')),
-		dict(
-			doctype='Item Group',
-			item_group_name='Produce',
-			is_group=0,
-			parent_item_group=_('All Item Groups')),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Nitrogen Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Phosphorous Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Potassium Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Calcium Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Sulphur Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Magnesium Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Iron Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Copper Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Zinc Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Boron Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Manganese Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Chlorine Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Molybdenum Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Sodium Content',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Humic Acid',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Fulvic Acid',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Inert',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Others',
-			standard=1,
-			linked_doctype='Fertilizer'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Nitrogen',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Phosphorous',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Potassium',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Calcium',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Magnesium',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Sulphur',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Boron',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Copper',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Iron',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Manganese',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Zinc',
-			standard=1,
-			linked_doctype='Plant Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Depth (in cm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Soil pH',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Salt Concentration (%)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Organic Matter (%)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='CEC (Cation Exchange Capacity) (MAQ/100mL)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Potassium Saturation (%)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Calcium Saturation (%)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Manganese Saturation (%)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Nirtogen (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Phosphorous (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Potassium (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Calcium (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Magnesium (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Sulphur (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Copper (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Iron (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Manganese (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Zinc (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Aluminium (ppm)',
-			standard=1,
-			linked_doctype='Soil Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Water pH',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Conductivity (mS/cm)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Hardness (mg/CaCO3)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Turbidity (NTU)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Odor',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Color',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Nitrate (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Nirtite (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Calcium (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Magnesium (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Sulphate (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Boron (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Copper (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Iron (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Manganese (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Zinc (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Chlorine (mg/L)',
-			standard=1,
-			linked_doctype='Water Analysis'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Bulk Density',
-			standard=1,
-			linked_doctype='Soil Texture'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Field Capacity',
-			standard=1,
-			linked_doctype='Soil Texture'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Wilting Point',
-			standard=1,
-			linked_doctype='Soil Texture'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Hydraulic Conductivity',
-			standard=1,
-			linked_doctype='Soil Texture'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Organic Matter',
-			standard=1,
-			linked_doctype='Soil Texture'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Temperature High',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Temperature Low',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Temperature Average',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Dew Point',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Precipitation Received',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Humidity',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Pressure',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Insolation/ PAR (Photosynthetically Active Radiation)',
-			standard=1,
-			linked_doctype='Weather'),
-		dict(
-			doctype='Agriculture Analysis Criteria',
-			title='Degree Days',
-			standard=1,
-			linked_doctype='Weather')
-	]
-	insert_record(records)
diff --git a/erpnext/agriculture/workspace/agriculture/agriculture.json b/erpnext/agriculture/workspace/agriculture/agriculture.json
deleted file mode 100644
index 6714de6..0000000
--- a/erpnext/agriculture/workspace/agriculture/agriculture.json
+++ /dev/null
@@ -1,171 +0,0 @@
-{
- "charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Crops & Lands\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Analytics\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Diseases & Fertilizers\", \"col\": 4}}]",
- "creation": "2020-03-02 17:23:34.339274",
- "docstatus": 0,
- "doctype": "Workspace",
- "for_user": "",
- "hide_custom": 0,
- "icon": "agriculture",
- "idx": 0,
- "label": "Agriculture",
- "links": [
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Crops & Lands",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Crop",
-   "link_count": 0,
-   "link_to": "Crop",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Crop Cycle",
-   "link_count": 0,
-   "link_to": "Crop Cycle",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Location",
-   "link_count": 0,
-   "link_to": "Location",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Analytics",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Plant Analysis",
-   "link_count": 0,
-   "link_to": "Plant Analysis",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Soil Analysis",
-   "link_count": 0,
-   "link_to": "Soil Analysis",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Water Analysis",
-   "link_count": 0,
-   "link_to": "Water Analysis",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Soil Texture",
-   "link_count": 0,
-   "link_to": "Soil Texture",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Weather",
-   "link_count": 0,
-   "link_to": "Weather",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Agriculture Analysis Criteria",
-   "link_count": 0,
-   "link_to": "Agriculture Analysis Criteria",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Diseases & Fertilizers",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Disease",
-   "link_count": 0,
-   "link_to": "Disease",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Fertilizer",
-   "link_count": 0,
-   "link_to": "Fertilizer",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  }
- ],
- "modified": "2021-08-05 12:15:54.595198",
- "modified_by": "Administrator",
- "module": "Agriculture",
- "name": "Agriculture",
- "owner": "Administrator",
- "parent_page": "",
- "public": 1,
- "restrict_to_domain": "Agriculture",
- "roles": [],
- "sequence_id": 3,
- "shortcuts": [],
- "title": "Agriculture"
-}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py
index 0163595..d288f88 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py
@@ -7,6 +7,7 @@
 		'non_standard_fieldnames': {
 			'Journal Entry': 'reference_name',
 			'Payment Entry': 'reference_name',
+			'Payment Request': 'reference_name',
 			'Auto Repeat': 'reference_document'
 		},
 		'internal_links': {
@@ -21,7 +22,7 @@
 			},
 			{
 				'label': _('Payment'),
-				'items': ['Payment Entry', 'Journal Entry']
+				'items': ['Payment Entry', 'Journal Entry', 'Payment Request']
 			},
 			{
 				'label': _('Reference'),
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 2c92820..eab9e12 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -7,6 +7,7 @@
 import frappe
 from frappe import _, throw
 from frappe.model.workflow import get_workflow_name, is_transition_condition_satisfied
+from frappe.query_builder.functions import Sum
 from frappe.utils import (
 	add_days,
 	add_months,
@@ -112,7 +113,7 @@
 						_('{0} is blocked so this transaction cannot proceed').format(supplier_name), raise_exception=1)
 
 	def validate(self):
-		if not self.get('is_return'):
+		if not self.get('is_return') and not self.get('is_debit_note'):
 			self.validate_qty_is_not_zero()
 
 		if self.get("_action") and self._action != "update_after_submit":
@@ -184,6 +185,8 @@
 					frappe.throw(_("Row #{0}: Service Start Date cannot be greater than Service End Date").format(d.idx))
 				elif getdate(self.posting_date) > getdate(d.service_end_date):
 					frappe.throw(_("Row #{0}: Service End Date cannot be before Invoice Posting Date").format(d.idx))
+				elif getdate(self.posting_date) > getdate(d.service_start_date):
+					frappe.throw(_("Row #{0}: Service Start Date cannot be before Invoice Posting Date").format(d.idx))
 
 	def validate_invoice_documents_schedule(self):
 		self.validate_payment_schedule_dates()
@@ -1684,58 +1687,69 @@
 def update_invoice_status():
 	"""Updates status as Overdue for applicable invoices. Runs daily."""
 	today = getdate()
-
+	payment_schedule = frappe.qb.DocType("Payment Schedule")
 	for doctype in ("Sales Invoice", "Purchase Invoice"):
-		frappe.db.sql("""
-			UPDATE `tab{doctype}` invoice SET invoice.status = 'Overdue'
-			WHERE invoice.docstatus = 1
-				AND invoice.status REGEXP '^Unpaid|^Partly Paid'
-				AND invoice.outstanding_amount > 0
-				AND (
-						{or_condition}
-						(
-							(
-								CASE
-									WHEN invoice.party_account_currency = invoice.currency
-									THEN (
-										CASE
-											WHEN invoice.disable_rounded_total
-											THEN invoice.grand_total
-											ELSE invoice.rounded_total
-										END
-									)
-									ELSE (
-										CASE
-											WHEN invoice.disable_rounded_total
-											THEN invoice.base_grand_total
-											ELSE invoice.base_rounded_total
-										END
-									)
-								END
-							) - invoice.outstanding_amount
-						) < (
-							SELECT SUM(
-								CASE
-									WHEN invoice.party_account_currency = invoice.currency
-									THEN ps.payment_amount
-									ELSE ps.base_payment_amount
-								END
-							)
-							FROM `tabPayment Schedule` ps
-							WHERE ps.parent = invoice.name
-								AND ps.due_date < %(today)s
-						)
-					)
-		""".format(
-				doctype=doctype,
-				or_condition=(
-					"invoice.is_pos AND invoice.due_date < %(today)s OR"
-					if doctype == "Sales Invoice"
-					else ""
-				)
-			), {"today": today}
+		invoice = frappe.qb.DocType(doctype)
+
+		consider_base_amount = invoice.party_account_currency != invoice.currency
+		payment_amount = (
+			frappe.qb.terms.Case()
+			.when(consider_base_amount, payment_schedule.base_payment_amount)
+			.else_(payment_schedule.payment_amount)
 		)
 
+		payable_amount = (
+			frappe.qb.from_(payment_schedule)
+			.select(Sum(payment_amount))
+			.where(
+				(payment_schedule.parent == invoice.name)
+				& (payment_schedule.due_date < today)
+			)
+		)
+
+		total = (
+			frappe.qb.terms.Case()
+			.when(invoice.disable_rounded_total, invoice.grand_total)
+			.else_(invoice.rounded_total)
+		)
+
+		base_total = (
+			frappe.qb.terms.Case()
+			.when(invoice.disable_rounded_total, invoice.base_grand_total)
+			.else_(invoice.base_rounded_total)
+		)
+
+		total_amount = (
+			frappe.qb.terms.Case()
+			.when(consider_base_amount, base_total)
+			.else_(total)
+		)
+
+		is_overdue = total_amount - invoice.outstanding_amount < payable_amount
+
+		conditions = (
+			(invoice.docstatus == 1)
+			& (invoice.outstanding_amount > 0)
+			& (
+				invoice.status.like("Unpaid%")
+				| invoice.status.like("Partly Paid%")
+			)
+			& (
+				((invoice.is_pos & invoice.due_date < today) | is_overdue)
+				if doctype == "Sales Invoice"
+				else is_overdue
+			)
+		)
+
+		status = (
+			frappe.qb.terms.Case()
+			.when(invoice.status.like("%Discounted"), "Overdue and Discounted")
+			.else_("Overdue")
+		)
+
+		frappe.qb.update(invoice).set("status", status).where(conditions).run()
+
+
 @frappe.whitelist()
 def get_payment_terms(terms_template, posting_date=None, grand_total=None, base_grand_total=None, bill_date=None):
 	if not terms_template:
@@ -2105,6 +2119,11 @@
 			parent.update_status_updater()
 	else:
 		parent.check_credit_limit()
+
+	# reset index of child table
+	for idx, row in enumerate(parent.get(child_docname), start=1):
+		row.idx = idx
+
 	parent.save()
 
 	if parent_doctype == 'Purchase Order':
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 746c6fd..075e3e3 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -139,6 +139,8 @@
 
 				if not item.qty and self.doc.get("is_return"):
 					item.amount = flt(-1 * item.rate, item.precision("amount"))
+				elif not item.qty and self.doc.get("is_debit_note"):
+					item.amount = flt(item.rate, item.precision("amount"))
 				else:
 					item.amount = flt(item.rate * item.qty,	item.precision("amount"))
 
@@ -594,13 +596,14 @@
 
 		if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
 			grand_total = self.doc.rounded_total or self.doc.grand_total
+			base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total
+
 			if self.doc.party_account_currency == self.doc.currency:
 				total_amount_to_pay = flt(grand_total - self.doc.total_advance
 					- flt(self.doc.write_off_amount), self.doc.precision("grand_total"))
 			else:
-				total_amount_to_pay = flt(flt(grand_total *
-					self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance
-						- flt(self.doc.base_write_off_amount), self.doc.precision("grand_total"))
+				total_amount_to_pay = flt(flt(base_grand_total, self.doc.precision("base_grand_total")) - self.doc.total_advance
+						- flt(self.doc.base_write_off_amount), self.doc.precision("base_grand_total"))
 
 			self.doc.round_floats_in(self.doc, ["paid_amount"])
 			change_amount = 0
diff --git a/erpnext/crm/doctype/crm_settings/crm_settings.json b/erpnext/crm/doctype/crm_settings/crm_settings.json
index 8f0fa31..a2a19b9 100644
--- a/erpnext/crm/doctype/crm_settings/crm_settings.json
+++ b/erpnext/crm/doctype/crm_settings/crm_settings.json
@@ -17,7 +17,9 @@
   "column_break_9",
   "create_event_on_next_contact_date_opportunity",
   "quotation_section",
-  "default_valid_till"
+  "default_valid_till",
+  "section_break_13",
+  "carry_forward_communication_and_comments"
  ],
  "fields": [
   {
@@ -85,13 +87,25 @@
    "fieldname": "quotation_section",
    "fieldtype": "Section Break",
    "label": "Quotation"
+  },
+  {
+   "fieldname": "section_break_13",
+   "fieldtype": "Section Break",
+   "label": "Other Settings"
+  },
+  {
+   "default": "0",
+   "description": "All the Comments and Emails will be copied from one document to another newly created document(Lead -> Opportunity -> Quotation) throughout the CRM documents.",
+   "fieldname": "carry_forward_communication_and_comments",
+   "fieldtype": "Check",
+   "label": "Carry Forward Communication and Comments"
   }
  ],
  "icon": "fa fa-cog",
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-11-03 10:00:36.883496",
+ "modified": "2021-12-20 12:51:38.894252",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "CRM Settings",
@@ -105,6 +119,26 @@
    "role": "System Manager",
    "share": 1,
    "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Sales Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Sales Master Manager",
+   "share": 1,
+   "write": 1
   }
  ],
  "sort_field": "modified",
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index fcbd4de..a4fd765 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -11,6 +11,7 @@
 from frappe.query_builder import DocType
 from frappe.utils import cint, cstr, flt, get_fullname
 
+from erpnext.crm.utils import add_link_in_communication, copy_comments
 from erpnext.setup.utils import get_exchange_rate
 from erpnext.utilities.transaction_base import TransactionBase
 
@@ -20,6 +21,11 @@
 		if self.opportunity_from == "Lead":
 			frappe.get_doc("Lead", self.party_name).set_status(update=True)
 
+		if self.opportunity_from in ["Lead", "Prospect"]:
+			if frappe.db.get_single_value("CRM Settings", "carry_forward_communication_and_comments"):
+				copy_comments(self.opportunity_from, self.party_name, self)
+				add_link_in_communication(self.opportunity_from, self.party_name, self)
+
 	def validate(self):
 		self._prev = frappe._dict({
 			"contact_date": frappe.db.get_value("Opportunity", self.name, "contact_date") if \
diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py
index 6e6fed5..db44b6a 100644
--- a/erpnext/crm/doctype/opportunity/test_opportunity.py
+++ b/erpnext/crm/doctype/opportunity/test_opportunity.py
@@ -4,10 +4,12 @@
 import unittest
 
 import frappe
-from frappe.utils import random_string, today
+from frappe.utils import now_datetime, random_string, today
 
 from erpnext.crm.doctype.lead.lead import make_customer
+from erpnext.crm.doctype.lead.test_lead import make_lead
 from erpnext.crm.doctype.opportunity.opportunity import make_quotation
+from erpnext.crm.utils import get_linked_communication_list
 
 test_records = frappe.get_test_records('Opportunity')
 
@@ -28,21 +30,11 @@
 		self.assertEqual(doc.status, "Quotation")
 
 	def test_make_new_lead_if_required(self):
-		new_lead_email_id = "new{}@example.com".format(random_string(5))
-		args = {
-			"doctype": "Opportunity",
-			"contact_email": new_lead_email_id,
-			"opportunity_type": "Sales",
-			"with_items": 0,
-			"transaction_date": today()
-		}
-		# new lead should be created against the new.opportunity@example.com
-		opp_doc = frappe.get_doc(args).insert(ignore_permissions=True)
+		opp_doc = make_opportunity_from_lead()
 
 		self.assertTrue(opp_doc.party_name)
 		self.assertEqual(opp_doc.opportunity_from, "Lead")
-		self.assertEqual(frappe.db.get_value("Lead", opp_doc.party_name, "email_id"),
-			new_lead_email_id)
+		self.assertEqual(frappe.db.get_value("Lead", opp_doc.party_name, "email_id"), opp_doc.contact_email)
 
 		# create new customer and create new contact against 'new.opportunity@example.com'
 		customer = make_customer(opp_doc.party_name).insert(ignore_permissions=True)
@@ -54,18 +46,60 @@
 				"link_name": customer.name
 			}]
 		})
-		contact.add_email(new_lead_email_id, is_primary=True)
+		contact.add_email(opp_doc.contact_email, is_primary=True)
 		contact.insert(ignore_permissions=True)
 
-		opp_doc = frappe.get_doc(args).insert(ignore_permissions=True)
-		self.assertTrue(opp_doc.party_name)
-		self.assertEqual(opp_doc.opportunity_from, "Customer")
-		self.assertEqual(opp_doc.party_name, customer.name)
-
 	def test_opportunity_item(self):
 		opportunity_doc = make_opportunity(with_items=1, rate=1100, qty=2)
 		self.assertEqual(opportunity_doc.total, 2200)
 
+	def test_carry_forward_of_email_and_comments(self):
+		frappe.db.set_value("CRM Settings", "CRM Settings", "carry_forward_communication_and_comments", 1)
+		lead_doc = make_lead()
+		lead_doc.add_comment('Comment', text='Test Comment 1')
+		lead_doc.add_comment('Comment', text='Test Comment 2')
+		create_communication(lead_doc.doctype, lead_doc.name, lead_doc.email_id)
+		create_communication(lead_doc.doctype, lead_doc.name, lead_doc.email_id)
+
+		opp_doc = make_opportunity(opportunity_from="Lead", lead=lead_doc.name)
+		opportunity_comment_count = frappe.db.count("Comment", {"reference_doctype": opp_doc.doctype, "reference_name": opp_doc.name})
+		opportunity_communication_count = len(get_linked_communication_list(opp_doc.doctype, opp_doc.name))
+		self.assertEqual(opportunity_comment_count, 2)
+		self.assertEqual(opportunity_communication_count, 2)
+
+		opp_doc.add_comment('Comment', text='Test Comment 3')
+		opp_doc.add_comment('Comment', text='Test Comment 4')
+		create_communication(opp_doc.doctype, opp_doc.name, opp_doc.contact_email)
+		create_communication(opp_doc.doctype, opp_doc.name, opp_doc.contact_email)
+
+		quotation_doc = make_quotation(opp_doc.name)
+		quotation_doc.append('items', {
+			"item_code": "_Test Item",
+			"qty": 1
+		})
+		quotation_doc.run_method("set_missing_values")
+		quotation_doc.run_method("calculate_taxes_and_totals")
+		quotation_doc.save()
+
+		quotation_comment_count = frappe.db.count("Comment", {"reference_doctype": quotation_doc.doctype, "reference_name": quotation_doc.name, "comment_type": "Comment"})
+		quotation_communication_count = len(get_linked_communication_list(quotation_doc.doctype, quotation_doc.name))
+		self.assertEqual(quotation_comment_count, 4)
+		self.assertEqual(quotation_communication_count, 4)
+
+def make_opportunity_from_lead():
+	new_lead_email_id = "new{}@example.com".format(random_string(5))
+	args = {
+		"doctype": "Opportunity",
+		"contact_email": new_lead_email_id,
+		"opportunity_type": "Sales",
+		"with_items": 0,
+		"transaction_date": today()
+	}
+	# new lead should be created against the new.opportunity@example.com
+	opp_doc = frappe.get_doc(args).insert(ignore_permissions=True)
+
+	return opp_doc
+
 def make_opportunity(**args):
 	args = frappe._dict(args)
 
@@ -95,3 +129,20 @@
 
 	opp_doc.insert()
 	return opp_doc
+
+def create_communication(reference_doctype, reference_name, sender, sent_or_received=None, creation=None):
+	communication = frappe.get_doc({
+		"doctype": "Communication",
+		"communication_type": "Communication",
+		"communication_medium": "Email",
+		"sent_or_received": sent_or_received or "Sent",
+		"email_status": "Open",
+		"subject": "Test Subject",
+		"sender": sender,
+		"content": "Test",
+		"status": "Linked",
+		"reference_doctype": reference_doctype,
+		"creation": creation or now_datetime(),
+		"reference_name": reference_name
+	})
+	communication.save()
\ No newline at end of file
diff --git a/erpnext/crm/doctype/prospect/prospect.py b/erpnext/crm/doctype/prospect/prospect.py
index 367aa3d..cc4c1d3 100644
--- a/erpnext/crm/doctype/prospect/prospect.py
+++ b/erpnext/crm/doctype/prospect/prospect.py
@@ -6,6 +6,8 @@
 from frappe.model.document import Document
 from frappe.model.mapper import get_mapped_doc
 
+from erpnext.crm.utils import add_link_in_communication, copy_comments
+
 
 class Prospect(Document):
 	def onload(self):
@@ -20,6 +22,12 @@
 	def on_trash(self):
 		self.unlink_dynamic_links()
 
+	def after_insert(self):
+		if frappe.db.get_single_value("CRM Settings", "carry_forward_communication_and_comments"):
+			for row in self.get('prospect_lead'):
+				copy_comments("Lead", row.lead, self)
+				add_link_in_communication("Lead", row.lead, self)
+
 	def update_lead_details(self):
 		for row in self.get('prospect_lead'):
 			lead = frappe.get_value('Lead', row.lead, ['lead_name', 'status', 'email_id', 'mobile_no'], as_dict=True)
diff --git a/erpnext/crm/utils.py b/erpnext/crm/utils.py
index 95b19ec..a4576a2 100644
--- a/erpnext/crm/utils.py
+++ b/erpnext/crm/utils.py
@@ -21,3 +21,30 @@
 			lead = frappe.get_doc("Lead", contact_lead)
 			lead.db_set("phone", phone)
 			lead.db_set("mobile_no", mobile_no)
+
+def copy_comments(doctype, docname, doc):
+	comments = frappe.db.get_values("Comment", filters={"reference_doctype": doctype, "reference_name": docname, "comment_type": "Comment"}, fieldname="*")
+	for comment in comments:
+		comment = frappe.get_doc(comment.update({"doctype":"Comment"}))
+		comment.name = None
+		comment.reference_doctype = doc.doctype
+		comment.reference_name = doc.name
+		comment.insert()
+
+def add_link_in_communication(doctype, docname, doc):
+	communication_list = get_linked_communication_list(doctype, docname)
+
+	for communication in communication_list:
+		communication_doc = frappe.get_doc("Communication", communication)
+		communication_doc.add_link(doc.doctype, doc.name, autosave=True)
+
+def get_linked_communication_list(doctype, docname):
+	communications = frappe.get_all("Communication", filters={"reference_doctype": doctype, "reference_name": docname}, pluck='name')
+	communication_links = frappe.get_all('Communication Link',
+		{
+			"link_doctype": doctype,
+			"link_name": docname,
+			"parent": ("not in", communications)
+		}, pluck="parent")
+
+	return communications + communication_links
diff --git a/erpnext/demo/domains.py b/erpnext/demo/domains.py
index 5fa181d..346787e 100644
--- a/erpnext/demo/domains.py
+++ b/erpnext/demo/domains.py
@@ -14,9 +14,6 @@
 	'Education': {
 		'company_name': 'Whitmore College'
 	},
-	'Agriculture': {
-		'company_name': 'Schrute Farms'
-  },
 	'Non Profit': {
 		'company_name': 'Erpnext Foundation'
 	}
diff --git a/erpnext/domains/agriculture.py b/erpnext/domains/agriculture.py
deleted file mode 100644
index e5414a9..0000000
--- a/erpnext/domains/agriculture.py
+++ /dev/null
@@ -1,26 +0,0 @@
-data = {
-	'desktop_icons': [
-		'Agriculture Task',
-		'Crop',
-		'Crop Cycle',
-		'Fertilizer',
-		'Item',
-		'Location',
-		'Disease',
-		'Plant Analysis',
-		'Soil Analysis',
-		'Soil Texture',
-		'Task',
-		'Water Analysis',
-		'Weather'
-	],
-	'restricted_roles': [
-		'Agriculture Manager',
-		'Agriculture User'
-	],
-	'modules': [
-		'Agriculture'
-	],
-	'default_portal_role': 'System Manager',
-	'on_setup': 'erpnext.agriculture.setup.setup_agriculture'
-}
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 1d11f20..f014b0e 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -65,7 +65,6 @@
 calendars = ["Task", "Work Order", "Leave Application", "Sales Order", "Holiday List", "Course Schedule"]
 
 domains = {
-	'Agriculture': 'erpnext.domains.agriculture',
 	'Distribution': 'erpnext.domains.distribution',
 	'Education': 'erpnext.domains.education',
 	'Hospitality': 'erpnext.domains.hospitality',
@@ -567,18 +566,6 @@
 		{'doctype': 'Assessment Code', 'index': 39},
 		{'doctype': 'Discussion', 'index': 40},
 	],
-	"Agriculture": [
-		{'doctype': 'Weather', 'index': 1},
-		{'doctype': 'Soil Texture', 'index': 2},
-		{'doctype': 'Water Analysis', 'index': 3},
-		{'doctype': 'Soil Analysis', 'index': 4},
-		{'doctype': 'Plant Analysis', 'index': 5},
-		{'doctype': 'Agriculture Analysis Criteria', 'index': 6},
-		{'doctype': 'Disease', 'index': 7},
-		{'doctype': 'Crop', 'index': 8},
-		{'doctype': 'Fertilizer', 'index': 9},
-		{'doctype': 'Crop Cycle', 'index': 10}
-	],
 	"Non Profit": [
 		{'doctype': 'Certified Consultant', 'index': 1},
 		{'doctype': 'Certification Application', 'index': 2},
diff --git a/erpnext/hr/doctype/department/department.js b/erpnext/hr/doctype/department/department.js
index 7db8cfb..46cfbda 100644
--- a/erpnext/hr/doctype/department/department.js
+++ b/erpnext/hr/doctype/department/department.js
@@ -6,6 +6,15 @@
 		frm.set_query("parent_department", function(){
 			return {"filters": [["Department", "is_group", "=", 1]]};
 		});
+
+		frm.set_query("payroll_cost_center", function() {
+			return {
+				filters: {
+					"company": frm.doc.company,
+					"is_group": 0
+				}
+			};
+		});
 	},
 	refresh: function(frm) {
 		// read-only for root department
diff --git a/erpnext/hr/doctype/employee/employee.js b/erpnext/hr/doctype/employee/employee.js
index 13b33e2..8c73e9c 100755
--- a/erpnext/hr/doctype/employee/employee.js
+++ b/erpnext/hr/doctype/employee/employee.js
@@ -47,6 +47,15 @@
 				}
 			};
 		});
+
+		frm.set_query("payroll_cost_center", function() {
+			return {
+				filters: {
+					"company": frm.doc.company,
+					"is_group": 0
+				}
+			};
+		});
 	},
 	onload: function (frm) {
 		frm.set_query("department", function() {
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index 88e5ca9..a2df26c 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -68,12 +68,18 @@
 		self.employee_name = ' '.join(filter(lambda x: x, [self.first_name, self.middle_name, self.last_name]))
 
 	def validate_user_details(self):
-		data = frappe.db.get_value('User',
-			self.user_id, ['enabled', 'user_image'], as_dict=1)
-		if data.get("user_image") and self.image == '':
-			self.image = data.get("user_image")
-		self.validate_for_enabled_user_id(data.get("enabled", 0))
-		self.validate_duplicate_user_id()
+		if self.user_id:
+			data = frappe.db.get_value('User',
+				self.user_id, ['enabled', 'user_image'], as_dict=1)
+
+			if not data:
+				self.user_id = None
+				return
+
+			if data.get("user_image") and self.image == '':
+				self.image = data.get("user_image")
+			self.validate_for_enabled_user_id(data.get("enabled", 0))
+			self.validate_duplicate_user_id()
 
 	def update_nsm_model(self):
 		frappe.utils.nestedset.update_nsm(self)
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 6655563..0479457 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -171,7 +171,7 @@
 					['docstatus', '=', 1],
 					['employee', '=', frm.doc.employee],
 					['paid_amount', '>', 0],
-					['paid_amount', '>', 'claimed_amount']
+					['status', '!=', 'Claimed']
 				]
 			};
 		});
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
index ec70361..2a07920 100644
--- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
@@ -10,15 +10,17 @@
 from erpnext.hr.doctype.employee.test_employee import make_employee
 from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry
 
-test_records = frappe.get_test_records('Expense Claim')
 test_dependencies = ['Employee']
-company_name = '_Test Company 4'
+company_name = '_Test Company 3'
 
 
 class TestExpenseClaim(unittest.TestCase):
+	def tearDown(self):
+		frappe.db.rollback()
+
 	def test_total_expense_claim_for_project(self):
-		frappe.db.sql("""delete from `tabTask` where project = "_Test Project 1" """)
-		frappe.db.sql("""delete from `tabProject` where name = "_Test Project 1" """)
+		frappe.db.sql("""delete from `tabTask`""")
+		frappe.db.sql("""delete from `tabProject`""")
 		frappe.db.sql("update `tabExpense Claim` set project = '', task = ''")
 
 		project = frappe.get_doc({
@@ -37,12 +39,12 @@
 		task_name = task.name
 		payable_account = get_payable_account(company_name)
 
-		make_expense_claim(payable_account, 300, 200, company_name, "Travel Expenses - _TC4", project.name, task_name)
+		make_expense_claim(payable_account, 300, 200, company_name, "Travel Expenses - _TC3", project.name, task_name)
 
 		self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 200)
 		self.assertEqual(frappe.db.get_value("Project", project.name, "total_expense_claim"), 200)
 
-		expense_claim2 = make_expense_claim(payable_account, 600, 500, company_name, "Travel Expenses - _TC4", project.name, task_name)
+		expense_claim2 = make_expense_claim(payable_account, 600, 500, company_name, "Travel Expenses - _TC3", project.name, task_name)
 
 		self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 700)
 		self.assertEqual(frappe.db.get_value("Project", project.name, "total_expense_claim"), 700)
@@ -54,7 +56,7 @@
 
 	def test_expense_claim_status(self):
 		payable_account = get_payable_account(company_name)
-		expense_claim = make_expense_claim(payable_account, 300, 200, company_name, "Travel Expenses - _TC4")
+		expense_claim = make_expense_claim(payable_account, 300, 200, company_name, "Travel Expenses - _TC3")
 
 		je_dict = make_bank_entry("Expense Claim", expense_claim.name)
 		je = frappe.get_doc(je_dict)
@@ -73,7 +75,7 @@
 	def test_expense_claim_gl_entry(self):
 		payable_account = get_payable_account(company_name)
 		taxes = generate_taxes()
-		expense_claim = make_expense_claim(payable_account, 300, 200, company_name, "Travel Expenses - _TC4",
+		expense_claim = make_expense_claim(payable_account, 300, 200, company_name, "Travel Expenses - _TC3",
 			do_not_submit=True, taxes=taxes)
 		expense_claim.submit()
 
@@ -84,9 +86,9 @@
 		self.assertTrue(gl_entries)
 
 		expected_values = dict((d[0], d) for d in [
-			['Output Tax CGST - _TC4',18.0, 0.0],
+			['Output Tax CGST - _TC3',18.0, 0.0],
 			[payable_account, 0.0, 218.0],
-			["Travel Expenses - _TC4", 200.0, 0.0]
+			["Travel Expenses - _TC3", 200.0, 0.0]
 		])
 
 		for gle in gl_entries:
@@ -102,7 +104,7 @@
 			"payable_account": payable_account,
 			"approval_status": "Rejected",
 			"expenses":
-				[{ "expense_type": "Travel", "default_account": "Travel Expenses - _TC4", "amount": 300, "sanctioned_amount": 200 }]
+				[{"expense_type": "Travel", "default_account": "Travel Expenses - _TC3", "amount": 300, "sanctioned_amount": 200}]
 		})
 		expense_claim.submit()
 
diff --git a/erpnext/hr/doctype/expense_claim/test_records.json b/erpnext/hr/doctype/expense_claim/test_records.json
deleted file mode 100644
index fe51488..0000000
--- a/erpnext/hr/doctype/expense_claim/test_records.json
+++ /dev/null
@@ -1 +0,0 @@
-[]
diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
index 6dbe2ec..1fe9139 100644
--- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
@@ -12,15 +12,11 @@
 class TestLeaveAllocation(unittest.TestCase):
 	@classmethod
 	def setUpClass(cls):
-		from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
-
 		frappe.db.sql("delete from `tabLeave Period`")
+
 		emp_id = make_employee("test_emp_leave_allocation@salary.com")
 		cls.employee = frappe.get_doc("Employee", emp_id)
 
-		make_holiday_list()
-		frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
-
 	def tearDown(self):
 		frappe.db.rollback()
 
@@ -90,6 +86,8 @@
 
 		# initial leave allocation = 15
 		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
 			leave_type="_Test_CF_leave",
 			from_date=add_months(nowdate(), -12),
 			to_date=add_months(nowdate(), -1),
@@ -99,6 +97,8 @@
 		# carry forwarded leaves considering maximum_carry_forwarded_leaves
 		# new_leaves = 15, carry_forwarded = 10
 		leave_allocation_1 = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
 			leave_type="_Test_CF_leave",
 			carry_forward=1)
 		leave_allocation_1.submit()
@@ -110,6 +110,8 @@
 		# carry forwarded leaves considering max_leave_allowed
 		# max_leave_allowed = 30, new_leaves = 25, carry_forwarded = 5
 		leave_allocation_2 = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
 			leave_type="_Test_CF_leave",
 			carry_forward=1,
 			new_leaves_allocated=25)
@@ -126,6 +128,8 @@
 
 		# initial leave allocation
 		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
 			leave_type="_Test_CF_leave_expiry",
 			from_date=add_months(nowdate(), -24),
 			to_date=add_months(nowdate(), -12),
@@ -133,6 +137,8 @@
 		leave_allocation.submit()
 
 		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
 			leave_type="_Test_CF_leave_expiry",
 			from_date=add_days(nowdate(), -90),
 			to_date=add_days(nowdate(), 100),
@@ -144,6 +150,8 @@
 
 		# leave allocation with carry forward of only new leaves allocated
 		leave_allocation_1 = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
 			leave_type="_Test_CF_leave_expiry",
 			carry_forward=1,
 			from_date=add_months(nowdate(), 6),
@@ -153,7 +161,10 @@
 		self.assertEqual(leave_allocation_1.unused_leaves, leave_allocation.new_leaves_allocated)
 
 	def test_creation_of_leave_ledger_entry_on_submit(self):
-		leave_allocation = create_leave_allocation()
+		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name
+		)
 		leave_allocation.submit()
 
 		leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_allocation.name))
@@ -168,7 +179,10 @@
 		self.assertFalse(frappe.db.exists("Leave Ledger Entry", {'transaction_name':leave_allocation.name}))
 
 	def test_leave_addition_after_submit(self):
-		leave_allocation = create_leave_allocation()
+		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name
+		)
 		leave_allocation.submit()
 		self.assertTrue(leave_allocation.total_leaves_allocated, 15)
 		leave_allocation.new_leaves_allocated = 40
@@ -176,7 +190,10 @@
 		self.assertTrue(leave_allocation.total_leaves_allocated, 40)
 
 	def test_leave_subtraction_after_submit(self):
-		leave_allocation = create_leave_allocation()
+		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name
+		)
 		leave_allocation.submit()
 		self.assertTrue(leave_allocation.total_leaves_allocated, 15)
 		leave_allocation.new_leaves_allocated = 10
@@ -184,7 +201,15 @@
 		self.assertTrue(leave_allocation.total_leaves_allocated, 10)
 
 	def test_validation_against_leave_application_after_submit(self):
-		leave_allocation = create_leave_allocation()
+		from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
+
+		make_holiday_list()
+		frappe.db.set_value("Company", self.employee.company, "default_holiday_list", "Salary Slip Test Holiday List")
+
+		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name
+		)
 		leave_allocation.submit()
 		self.assertTrue(leave_allocation.total_leaves_allocated, 15)
 
@@ -194,7 +219,7 @@
 			"leave_type": "_Test Leave Type",
 			"from_date": add_months(nowdate(), 2),
 			"to_date": add_months(add_days(nowdate(), 10), 2),
-			"company": erpnext.get_default_company() or "_Test Company",
+			"company": self.employee.company,
 			"docstatus": 1,
 			"status": "Approved",
 			"leave_approver": 'test@example.com'
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
index dca7e48..355370f 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
@@ -56,9 +56,7 @@
 						leave_policy_detail.leave_type, leave_policy_detail.annual_allocation,
 						leave_type_details, date_of_joining
 					)
-
-				leave_allocations[leave_policy_detail.leave_type] = {"name": leave_allocation, "leaves": new_leaves_allocated}
-
+					leave_allocations[leave_policy_detail.leave_type] = {"name": leave_allocation, "leaves": new_leaves_allocated}
 			self.db_set("leaves_allocated", 1)
 			return leave_allocations
 
@@ -130,6 +128,8 @@
 			monthly_earned_leave = get_monthly_earned_leave(new_leaves_allocated,
 				leave_type_details.get(leave_type).earned_leave_frequency, leave_type_details.get(leave_type).rounding)
 			new_leaves_allocated = monthly_earned_leave * months_passed
+		else:
+			new_leaves_allocated = 0
 
 		return new_leaves_allocated
 
diff --git a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
index b1861ad..8953a51 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
@@ -4,6 +4,7 @@
 import unittest
 
 import frappe
+from frappe.utils import add_months, get_first_day, getdate
 
 from erpnext.hr.doctype.leave_application.test_leave_application import (
 	get_employee,
@@ -17,9 +18,8 @@
 test_dependencies = ["Employee"]
 
 class TestLeavePolicyAssignment(unittest.TestCase):
-
 	def setUp(self):
-		for doctype in ["Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
+		for doctype in ["Leave Period", "Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
 			frappe.db.sql("delete from `tab{0}`".format(doctype)) #nosec
 
 	def test_grant_leaves(self):
@@ -54,8 +54,8 @@
 
 		self.assertEqual(leave_alloc_doc.new_leaves_allocated, 10)
 		self.assertEqual(leave_alloc_doc.leave_type, "_Test Leave Type")
-		self.assertEqual(leave_alloc_doc.from_date, leave_period.from_date)
-		self.assertEqual(leave_alloc_doc.to_date, leave_period.to_date)
+		self.assertEqual(getdate(leave_alloc_doc.from_date), getdate(leave_period.from_date))
+		self.assertEqual(getdate(leave_alloc_doc.to_date), getdate(leave_period.to_date))
 		self.assertEqual(leave_alloc_doc.leave_policy, leave_policy.name)
 		self.assertEqual(leave_alloc_doc.leave_policy_assignment, leave_policy_assignments[0])
 
@@ -101,6 +101,55 @@
 		# User are now allowed to grant leave
 		self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 0)
 
+	def test_earned_leave_allocation(self):
+		leave_period = create_leave_period("Test Earned Leave Period")
+		employee = get_employee()
+		leave_type = create_earned_leave_type("Test Earned Leave")
+
+		leave_policy = frappe.get_doc({
+			"doctype": "Leave Policy",
+			"leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 6}]
+		}).insert()
+
+		data = {
+			"assignment_based_on": "Leave Period",
+			"leave_policy": leave_policy.name,
+			"leave_period": leave_period.name
+		}
+		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+
+		# leaves allocated should be 0 since it is an earned leave and allocation happens via scheduler based on set frequency
+		leaves_allocated = frappe.db.get_value("Leave Allocation", {
+			"leave_policy_assignment": leave_policy_assignments[0]
+		}, "total_leaves_allocated")
+		self.assertEqual(leaves_allocated, 0)
+
 	def tearDown(self):
-		for doctype in ["Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
-			frappe.db.sql("delete from `tab{0}`".format(doctype)) #nosec
+		frappe.db.rollback()
+
+
+def create_earned_leave_type(leave_type):
+	frappe.delete_doc_if_exists("Leave Type", leave_type, force=1)
+
+	return frappe.get_doc(dict(
+		leave_type_name=leave_type,
+		doctype="Leave Type",
+		is_earned_leave=1,
+		earned_leave_frequency="Monthly",
+		rounding=0.5,
+		max_leaves_allowed=6
+	)).insert()
+
+
+def create_leave_period(name):
+	frappe.delete_doc_if_exists("Leave Period", name, force=1)
+	start_date = get_first_day(getdate())
+
+	return frappe.get_doc(dict(
+		name=name,
+		doctype="Leave Period",
+		from_date=start_date,
+		to_date=add_months(start_date, 12),
+		company="_Test Company",
+		is_active=1
+	)).insert()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/shift_type/shift_type.js b/erpnext/hr/doctype/shift_type/shift_type.js
index ba53312..7138e3b 100644
--- a/erpnext/hr/doctype/shift_type/shift_type.js
+++ b/erpnext/hr/doctype/shift_type/shift_type.js
@@ -4,15 +4,32 @@
 frappe.ui.form.on('Shift Type', {
 	refresh: function(frm) {
 		frm.add_custom_button(
-			'Mark Attendance',
-			() => frm.call({
-				doc: frm.doc,
-				method: 'process_auto_attendance',
-				freeze: true,
-				callback: () => {
-					frappe.msgprint(__("Attendance has been marked as per employee check-ins"));
+			__('Mark Attendance'),
+			() => {
+				if (!frm.doc.enable_auto_attendance) {
+					frm.scroll_to_field('enable_auto_attendance');
+					frappe.throw(__('Please Enable Auto Attendance and complete the setup first.'));
 				}
-			})
+
+				if (!frm.doc.process_attendance_after) {
+					frm.scroll_to_field('process_attendance_after');
+					frappe.throw(__('Please set {0}.', [__('Process Attendance After').bold()]));
+				}
+
+				if (!frm.doc.last_sync_of_checkin) {
+					frm.scroll_to_field('last_sync_of_checkin');
+					frappe.throw(__('Please set {0}.', [__('Last Sync of Checkin').bold()]));
+				}
+
+				frm.call({
+					doc: frm.doc,
+					method: 'process_auto_attendance',
+					freeze: true,
+					callback: () => {
+						frappe.msgprint(__('Attendance has been marked as per employee check-ins'));
+					}
+				});
+			}
 		);
 	}
 });
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index 5979992..af26f7b 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -240,12 +240,14 @@
    "label": "Repayment Schedule"
   },
   {
+   "allow_on_submit": 1,
    "depends_on": "eval:doc.is_term_loan == 1",
    "fieldname": "repayment_schedule",
    "fieldtype": "Table",
    "label": "Repayment Schedule",
    "no_copy": 1,
-   "options": "Repayment Schedule"
+   "options": "Repayment Schedule",
+   "read_only": 1
   },
   {
    "fieldname": "section_break_17",
@@ -363,6 +365,7 @@
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan",
+ "naming_rule": "Expression (old style)",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index 84e0f03..f660a24 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -7,7 +7,7 @@
 
 import frappe
 from frappe import _
-from frappe.utils import add_months, flt, getdate, now_datetime, nowdate
+from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate
 
 import erpnext
 from erpnext.controllers.accounts_controller import AccountsController
@@ -62,7 +62,7 @@
 			self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest")
 
 		if self.repayment_method == "Repay Over Number of Periods":
-			self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
+			self.monthly_repayment_amount = get_monthly_repayment_amount(self.loan_amount, self.rate_of_interest, self.repayment_periods)
 
 	def check_sanctioned_amount_limit(self):
 		sanctioned_amount_limit = get_sanctioned_amount_limit(self.applicant_type, self.applicant, self.company)
@@ -99,7 +99,7 @@
 				"total_payment": total_payment,
 				"balance_loan_amount": balance_amount
 			})
-			next_payment_date = add_months(payment_date, 1)
+			next_payment_date = add_single_month(payment_date)
 			payment_date = next_payment_date
 
 	def set_repayment_period(self):
@@ -211,7 +211,7 @@
 		if monthly_repayment_amount > loan_amount:
 			frappe.throw(_("Monthly Repayment Amount cannot be greater than Loan Amount"))
 
-def get_monthly_repayment_amount(repayment_method, loan_amount, rate_of_interest, repayment_periods):
+def get_monthly_repayment_amount(loan_amount, rate_of_interest, repayment_periods):
 	if rate_of_interest:
 		monthly_interest_rate = flt(rate_of_interest) / (12 *100)
 		monthly_repayment_amount = math.ceil((loan_amount * monthly_interest_rate *
@@ -395,3 +395,9 @@
 		"value": len(applicants),
 		"fieldtype": "Int"
 	}
+
+def add_single_month(date):
+	if getdate(date) == get_last_day(date):
+		return get_last_day(add_months(date, 1))
+	else:
+		return add_months(date, 1)
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index c0f058f..1676c21 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -218,6 +218,14 @@
 		self.assertEqual(flt(loan.total_principal_paid, 0), flt(repayment_entry.amount_paid -
 			 penalty_amount - total_interest_paid, 0))
 
+		# Check Repayment Entry cancel
+		repayment_entry.load_from_db()
+		repayment_entry.cancel()
+
+		loan.load_from_db()
+		self.assertEqual(loan.total_principal_paid, 0)
+		self.assertEqual(loan.total_principal_paid, 0)
+
 	def test_loan_closure(self):
 		pledge = [{
 			"loan_security": "Test Security 1",
@@ -295,6 +303,27 @@
 		self.assertEqual(amounts[0], 11250.00)
 		self.assertEqual(amounts[1], 78303.00)
 
+	def test_repayment_schedule_update(self):
+		loan = create_loan(self.applicant2, "Personal Loan", 200000, "Repay Over Number of Periods", 4,
+			applicant_type='Customer', repayment_start_date='2021-04-30', posting_date='2021-04-01')
+
+		loan.submit()
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date='2021-04-01')
+
+		process_loan_interest_accrual_for_term_loans(posting_date='2021-05-01')
+		process_loan_interest_accrual_for_term_loans(posting_date='2021-06-01')
+
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, '2021-06-05', 120000)
+		repayment_entry.submit()
+
+		loan.load_from_db()
+
+		self.assertEqual(flt(loan.get('repayment_schedule')[3].principal_amount, 2), 41369.83)
+		self.assertEqual(flt(loan.get('repayment_schedule')[3].interest_amount, 2), 289.59)
+		self.assertEqual(flt(loan.get('repayment_schedule')[3].total_payment, 2), 41659.41)
+		self.assertEqual(flt(loan.get('repayment_schedule')[3].balance_loan_amount, 2), 0)
+
 	def test_security_shortfall(self):
 		pledges = [{
 			"loan_security": "Test Security 2",
@@ -938,18 +967,18 @@
 
 
 def create_loan(applicant, loan_type, loan_amount, repayment_method, repayment_periods,
-	repayment_start_date=None, posting_date=None):
+	applicant_type=None, repayment_start_date=None, posting_date=None):
 
 	loan = frappe.get_doc({
 		"doctype": "Loan",
-		"applicant_type": "Employee",
+		"applicant_type": applicant_type or "Employee",
 		"company": "_Test Company",
 		"applicant": applicant,
 		"loan_type": loan_type,
 		"loan_amount": loan_amount,
 		"repayment_method": repayment_method,
 		"repayment_periods": repayment_periods,
-		"repayment_start_date": nowdate(),
+		"repayment_start_date": repayment_start_date or nowdate(),
 		"is_term_loan": 1,
 		"posting_date": posting_date or nowdate()
 	})
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py
index 24d8d68..a8ffcb9 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.py
@@ -80,7 +80,7 @@
 
 		if self.is_term_loan:
 			if self.repayment_method == "Repay Over Number of Periods":
-				self.repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
+				self.repayment_amount = get_monthly_repayment_amount(self.loan_amount, self.rate_of_interest, self.repayment_periods)
 
 			if self.repayment_method == "Repay Fixed Amount per Period":
 				monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index 93b4af9..e2d758b 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -176,20 +176,19 @@
 
 @frappe.whitelist()
 def get_disbursal_amount(loan, on_current_security_price=0):
+	from erpnext.loan_management.doctype.loan_repayment.loan_repayment import (
+		get_pending_principal_amount,
+	)
+
 	loan_details = frappe.get_value("Loan", loan, ["loan_amount", "disbursed_amount", "total_payment",
 		"total_principal_paid", "total_interest_payable", "status", "is_term_loan", "is_secured_loan",
-		"maximum_loan_amount"], as_dict=1)
+		"maximum_loan_amount", "written_off_amount"], as_dict=1)
 
 	if loan_details.is_secured_loan and frappe.get_all('Loan Security Shortfall', filters={'loan': loan,
 		'status': 'Pending'}):
 		return 0
 
-	if loan_details.status == 'Disbursed':
-		pending_principal_amount = flt(loan_details.total_payment) - flt(loan_details.total_interest_payable) \
-			- flt(loan_details.total_principal_paid)
-	else:
-		pending_principal_amount = flt(loan_details.disbursed_amount) - flt(loan_details.total_interest_payable) \
-			- flt(loan_details.total_principal_paid)
+	pending_principal_amount = get_pending_principal_amount(loan_details)
 
 	security_value = 0.0
 	if loan_details.is_secured_loan and on_current_security_price:
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
index e945d49..0de073f 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
@@ -74,6 +74,39 @@
 				})
 			)
 
+		if self.payable_principal_amount:
+			gle_map.append(
+				self.get_gl_dict({
+					"account": self.loan_account,
+					"party_type": self.applicant_type,
+					"party": self.applicant,
+					"against": self.interest_income_account,
+					"debit": self.payable_principal_amount,
+					"debit_in_account_currency": self.interest_amount,
+					"against_voucher_type": "Loan",
+					"against_voucher": self.loan,
+					"remarks": _("Interest accrued from {0} to {1} against loan: {2}").format(
+						self.last_accrual_date, self.posting_date, self.loan),
+					"cost_center": erpnext.get_default_cost_center(self.company),
+					"posting_date": self.posting_date
+				})
+			)
+
+			gle_map.append(
+				self.get_gl_dict({
+					"account": self.interest_income_account,
+					"against": self.loan_account,
+					"credit": self.payable_principal_amount,
+					"credit_in_account_currency":  self.interest_amount,
+					"against_voucher_type": "Loan",
+					"against_voucher": self.loan,
+					"remarks": ("Interest accrued from {0} to {1} against loan: {2}").format(
+						self.last_accrual_date, self.posting_date, self.loan),
+					"cost_center": erpnext.get_default_cost_center(self.company),
+					"posting_date": self.posting_date
+				})
+			)
+
 		if gle_map:
 			make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj)
 
@@ -82,7 +115,10 @@
 # rate of interest is 13.5 then first loan interest accural will be on '01-10-2019'
 # which means interest will be accrued for 30 days which should be equal to 11095.89
 def calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type):
-	from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
+	from erpnext.loan_management.doctype.loan_repayment.loan_repayment import (
+		calculate_amounts,
+		get_pending_principal_amount,
+	)
 
 	no_of_days = get_no_of_days_for_interest_accural(loan, posting_date)
 	precision = cint(frappe.db.get_default("currency_precision")) or 2
@@ -90,12 +126,7 @@
 	if no_of_days <= 0:
 		return
 
-	if loan.status == 'Disbursed':
-		pending_principal_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
-			- flt(loan.total_principal_paid) - flt(loan.written_off_amount)
-	else:
-		pending_principal_amount = flt(loan.disbursed_amount) - flt(loan.total_interest_payable) \
-			- flt(loan.total_principal_paid) - flt(loan.written_off_amount)
+	pending_principal_amount = get_pending_principal_amount(loan)
 
 	interest_per_day = get_per_day_interest(pending_principal_amount, loan.rate_of_interest, posting_date)
 	payable_interest = interest_per_day * no_of_days
@@ -133,7 +164,7 @@
 
 	if not open_loans:
 		open_loans = frappe.get_all("Loan",
-			fields=["name", "total_payment", "total_amount_paid", "loan_account", "interest_income_account",
+			fields=["name", "total_payment", "total_amount_paid", "loan_account", "interest_income_account", "loan_amount",
 				"is_term_loan", "status", "disbursement_date", "disbursed_amount", "applicant_type", "applicant",
 				"rate_of_interest", "total_interest_payable", "written_off_amount", "total_principal_paid", "repayment_start_date"],
 			filters=query_filters)
@@ -190,7 +221,8 @@
 			AND l.is_term_loan =1
 			AND rs.payment_date <= %s
 			AND rs.is_accrued=0 {0}
-			AND l.status = 'Disbursed'""".format(condition), (getdate(date)), as_dict=1)
+			AND l.status = 'Disbursed'
+			ORDER BY rs.payment_date""".format(condition), (getdate(date)), as_dict=1)
 
 	return term_loans
 
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 6479853..93ef217 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -13,8 +13,10 @@
   "column_break_3",
   "company",
   "posting_date",
-  "is_term_loan",
   "rate_of_interest",
+  "payroll_payable_account",
+  "is_term_loan",
+  "repay_from_salary",
   "payment_details_section",
   "due_date",
   "pending_principal_amount",
@@ -243,15 +245,31 @@
    "label": "Total Penalty Paid",
    "options": "Company:company:default_currency",
    "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.repay_from_salary",
+   "fieldname": "payroll_payable_account",
+   "fieldtype": "Link",
+   "label": "Payroll Payable Account",
+   "mandatory_depends_on": "eval:doc.repay_from_salary",
+   "options": "Account"
+  },
+  {
+   "default": "0",
+   "fetch_from": "against_loan.repay_from_salary",
+   "fieldname": "repay_from_salary",
+   "fieldtype": "Check",
+   "label": "Repay From Salary"
   }
  ],
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-04-19 18:10:00.935364",
+ "modified": "2022-01-06 01:51:06.707782",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Repayment",
+ "naming_rule": "Expression (old style)",
  "owner": "Administrator",
  "permissions": [
   {
@@ -287,5 +305,6 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 5922e4f..7e997e8 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -35,9 +35,12 @@
 
 	def on_submit(self):
 		self.update_paid_amount()
+		self.update_repayment_schedule()
 		self.make_gl_entries()
 
 	def on_cancel(self):
+		self.check_future_accruals()
+		self.update_repayment_schedule(cancel=1)
 		self.mark_as_unpaid()
 		self.ignore_linked_doctypes = ['GL Entry']
 		self.make_gl_entries(cancel=1)
@@ -90,7 +93,7 @@
 
 	def book_unaccrued_interest(self):
 		precision = cint(frappe.db.get_default("currency_precision")) or 2
-		if self.total_interest_paid > self.interest_payable:
+		if flt(self.total_interest_paid, precision) > flt(self.interest_payable, precision):
 			if not self.is_term_loan:
 				# get last loan interest accrual date
 				last_accrual_date = get_last_accrual_date(self.against_loan)
@@ -121,7 +124,18 @@
 					})
 
 	def update_paid_amount(self):
-		loan = frappe.get_doc("Loan", self.against_loan)
+		loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
+			'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'total_interest_payable',
+			'written_off_amount'], as_dict=1)
+
+		loan.update({
+			'total_amount_paid': loan.total_amount_paid + self.amount_paid,
+			'total_principal_paid': loan.total_principal_paid + self.principal_amount_paid
+		})
+
+		pending_principal_amount = get_pending_principal_amount(loan)
+		if not loan.is_secured_loan and pending_principal_amount <= 0:
+			loan.update({'status': 'Loan Closure Requested'})
 
 		for payment in self.repayment_details:
 			frappe.db.sql(""" UPDATE `tabLoan Interest Accrual`
@@ -130,17 +144,31 @@
 				WHERE name = %s""",
 				(flt(payment.paid_principal_amount), flt(payment.paid_interest_amount), payment.loan_interest_accrual))
 
-		frappe.db.sql(""" UPDATE `tabLoan` SET total_amount_paid = %s, total_principal_paid = %s
-			WHERE name = %s """, (loan.total_amount_paid + self.amount_paid,
-			loan.total_principal_paid + self.principal_amount_paid, self.against_loan))
+		frappe.db.sql(""" UPDATE `tabLoan`
+			SET total_amount_paid = %s, total_principal_paid = %s, status = %s
+			WHERE name = %s """, (loan.total_amount_paid, loan.total_principal_paid, loan.status,
+			self.against_loan))
 
 		update_shortfall_status(self.against_loan, self.principal_amount_paid)
 
 	def mark_as_unpaid(self):
-		loan = frappe.get_doc("Loan", self.against_loan)
+		loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
+			'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'total_interest_payable',
+			'written_off_amount'], as_dict=1)
 
 		no_of_repayments = len(self.repayment_details)
 
+		loan.update({
+			'total_amount_paid': loan.total_amount_paid - self.amount_paid,
+			'total_principal_paid': loan.total_principal_paid - self.principal_amount_paid
+		})
+
+		if loan.status == 'Loan Closure Requested':
+			if loan.disbursed_amount >= loan.loan_amount:
+				loan['status'] = 'Disbursed'
+			else:
+				loan['status'] = 'Partially Disbursed'
+
 		for payment in self.repayment_details:
 			frappe.db.sql(""" UPDATE `tabLoan Interest Accrual`
 				SET paid_principal_amount = `paid_principal_amount` - %s,
@@ -154,12 +182,20 @@
 				lia_doc = frappe.get_doc('Loan Interest Accrual', payment.loan_interest_accrual)
 				lia_doc.cancel()
 
-		frappe.db.sql(""" UPDATE `tabLoan` SET total_amount_paid = %s, total_principal_paid = %s
-			WHERE name = %s """, (loan.total_amount_paid - self.amount_paid,
-			loan.total_principal_paid - self.principal_amount_paid, self.against_loan))
+		frappe.db.sql(""" UPDATE `tabLoan`
+			SET total_amount_paid = %s, total_principal_paid = %s, status = %s
+			WHERE name = %s """, (loan.total_amount_paid, loan.total_principal_paid, loan.status, self.against_loan))
 
-		if loan.status == "Loan Closure Requested":
-			frappe.db.set_value("Loan", self.against_loan, "status", "Disbursed")
+	def check_future_accruals(self):
+		future_accrual_date = frappe.db.get_value("Loan Interest Accrual", {"posting_date": (">", self.posting_date),
+			"docstatus": 1, "loan": self.against_loan}, 'posting_date')
+
+		if future_accrual_date:
+			frappe.throw("Cannot cancel. Interest accruals already processed till {0}".format(get_datetime(future_accrual_date)))
+
+	def update_repayment_schedule(self, cancel=0):
+		if self.is_term_loan and self.principal_amount_paid > self.payable_principal_amount:
+			regenerate_repayment_schedule(self.against_loan, cancel)
 
 	def allocate_amounts(self, repayment_details):
 		self.set('repayment_details', [])
@@ -182,50 +218,93 @@
 
 			interest_paid -= self.total_penalty_paid
 
-		total_interest_paid = 0
-		# interest_paid = self.amount_paid - self.principal_amount_paid - self.penalty_amount
+		if self.is_term_loan:
+			interest_paid, updated_entries = self.allocate_interest_amount(interest_paid, repayment_details)
+			self.allocate_principal_amount_for_term_loans(interest_paid, repayment_details, updated_entries)
+		else:
+			interest_paid, updated_entries = self.allocate_interest_amount(interest_paid, repayment_details)
+			self.allocate_excess_payment_for_demand_loans(interest_paid, repayment_details)
+
+	def allocate_interest_amount(self, interest_paid, repayment_details):
+		updated_entries = {}
+		self.total_interest_paid = 0
+		idx = 1
 
 		if interest_paid > 0:
 			for lia, amounts in repayment_details.get('pending_accrual_entries', []).items():
-				if amounts['interest_amount'] + amounts['payable_principal_amount'] <= interest_paid:
+				interest_amount = 0
+				if amounts['interest_amount'] <= interest_paid:
 					interest_amount = amounts['interest_amount']
-					paid_principal = amounts['payable_principal_amount']
-					self.principal_amount_paid += paid_principal
-					interest_paid -= (interest_amount + paid_principal)
+					self.total_interest_paid += interest_amount
+					interest_paid -= interest_amount
 				elif interest_paid:
 					if interest_paid >= amounts['interest_amount']:
 						interest_amount = amounts['interest_amount']
-						paid_principal = interest_paid - interest_amount
-						self.principal_amount_paid += paid_principal
+						self.total_interest_paid += interest_amount
 						interest_paid = 0
 					else:
 						interest_amount = interest_paid
+						self.total_interest_paid += interest_amount
 						interest_paid = 0
-						paid_principal=0
 
-				total_interest_paid += interest_amount
-				self.append('repayment_details', {
-					'loan_interest_accrual': lia,
-					'paid_interest_amount': interest_amount,
-					'paid_principal_amount': paid_principal
-				})
+				if interest_amount:
+					self.append('repayment_details', {
+						'loan_interest_accrual': lia,
+						'paid_interest_amount': interest_amount,
+						'paid_principal_amount': 0
+					})
+					updated_entries[lia] = idx
+					idx += 1
 
+		return interest_paid, updated_entries
+
+	def allocate_principal_amount_for_term_loans(self, interest_paid, repayment_details, updated_entries):
+		if interest_paid > 0:
+			for lia, amounts in repayment_details.get('pending_accrual_entries', []).items():
+				paid_principal = 0
+				if amounts['payable_principal_amount'] <= interest_paid:
+					paid_principal = amounts['payable_principal_amount']
+					self.principal_amount_paid += paid_principal
+					interest_paid -= paid_principal
+				elif interest_paid:
+					if interest_paid >= amounts['payable_principal_amount']:
+						paid_principal = amounts['payable_principal_amount']
+						self.principal_amount_paid += paid_principal
+						interest_paid = 0
+					else:
+						paid_principal = interest_paid
+						self.principal_amount_paid += paid_principal
+						interest_paid = 0
+
+				if updated_entries.get(lia):
+					idx = updated_entries.get(lia)
+					self.get('repayment_details')[idx-1].paid_principal_amount += paid_principal
+				else:
+					self.append('repayment_details', {
+						'loan_interest_accrual': lia,
+						'paid_interest_amount': 0,
+						'paid_principal_amount': paid_principal
+					})
+
+		if interest_paid > 0:
+			self.principal_amount_paid += interest_paid
+
+	def allocate_excess_payment_for_demand_loans(self, interest_paid, repayment_details):
 		if repayment_details['unaccrued_interest'] and interest_paid > 0:
 			# no of days for which to accrue interest
 			# Interest can only be accrued for an entire day and not partial
 			if interest_paid > repayment_details['unaccrued_interest']:
 				interest_paid -= repayment_details['unaccrued_interest']
-				total_interest_paid += repayment_details['unaccrued_interest']
+				self.total_interest_paid += repayment_details['unaccrued_interest']
 			else:
 				# get no of days for which interest can be paid
 				per_day_interest = get_per_day_interest(self.pending_principal_amount,
 					self.rate_of_interest, self.posting_date)
 
 				no_of_days = cint(interest_paid/per_day_interest)
-				total_interest_paid += no_of_days * per_day_interest
+				self.total_interest_paid += no_of_days * per_day_interest
 				interest_paid -= no_of_days * per_day_interest
 
-		self.total_interest_paid = total_interest_paid
 		if interest_paid > 0:
 			self.principal_amount_paid += interest_paid
 
@@ -241,74 +320,79 @@
 		else:
 			remarks = _("Repayment against Loan: ") + self.against_loan
 
-		if not loan_details.repay_from_salary:
-			if self.total_penalty_paid:
-				gle_map.append(
-					self.get_gl_dict({
-						"account": loan_details.loan_account,
-						"against": loan_details.payment_account,
-						"debit": self.total_penalty_paid,
-						"debit_in_account_currency": self.total_penalty_paid,
-						"against_voucher_type": "Loan",
-						"against_voucher": self.against_loan,
-						"remarks": _("Penalty against loan:") + self.against_loan,
-						"cost_center": self.cost_center,
-						"party_type": self.applicant_type,
-						"party": self.applicant,
-						"posting_date": getdate(self.posting_date)
-					})
-				)
+		if self.repay_from_salary:
+			payment_account = self.payroll_payable_account
+		else:
+			payment_account = loan_details.payment_account
 
-				gle_map.append(
-					self.get_gl_dict({
-						"account": loan_details.penalty_income_account,
-						"against": loan_details.payment_account,
-						"credit": self.total_penalty_paid,
-						"credit_in_account_currency": self.total_penalty_paid,
-						"against_voucher_type": "Loan",
-						"against_voucher": self.against_loan,
-						"remarks": _("Penalty against loan:") + self.against_loan,
-						"cost_center": self.cost_center,
-						"posting_date": getdate(self.posting_date)
-					})
-				)
-
-			gle_map.append(
-				self.get_gl_dict({
-					"account": loan_details.payment_account,
-					"against": loan_details.loan_account + ", " + loan_details.interest_income_account
-							+ ", " + loan_details.penalty_income_account,
-					"debit": self.amount_paid,
-					"debit_in_account_currency": self.amount_paid,
-					"against_voucher_type": "Loan",
-					"against_voucher": self.against_loan,
-					"remarks": remarks,
-					"cost_center": self.cost_center,
-					"posting_date": getdate(self.posting_date)
-				})
-			)
-
+		if self.total_penalty_paid:
 			gle_map.append(
 				self.get_gl_dict({
 					"account": loan_details.loan_account,
-					"party_type": loan_details.applicant_type,
-					"party": loan_details.applicant,
 					"against": loan_details.payment_account,
-					"credit": self.amount_paid,
-					"credit_in_account_currency": self.amount_paid,
+					"debit": self.total_penalty_paid,
+					"debit_in_account_currency": self.total_penalty_paid,
 					"against_voucher_type": "Loan",
 					"against_voucher": self.against_loan,
-					"remarks": remarks,
+					"remarks": _("Penalty against loan:") + self.against_loan,
+					"cost_center": self.cost_center,
+					"party_type": self.applicant_type,
+					"party": self.applicant,
+					"posting_date": getdate(self.posting_date)
+				})
+			)
+
+			gle_map.append(
+				self.get_gl_dict({
+					"account": loan_details.penalty_income_account,
+					"against": payment_account,
+					"credit": self.total_penalty_paid,
+					"credit_in_account_currency": self.total_penalty_paid,
+					"against_voucher_type": "Loan",
+					"against_voucher": self.against_loan,
+					"remarks": _("Penalty against loan:") + self.against_loan,
 					"cost_center": self.cost_center,
 					"posting_date": getdate(self.posting_date)
 				})
 			)
 
-			if gle_map:
-				make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj, merge_entries=False)
+		gle_map.append(
+			self.get_gl_dict({
+				"account": payment_account,
+				"against": loan_details.loan_account + ", " + loan_details.interest_income_account
+						+ ", " + loan_details.penalty_income_account,
+				"debit": self.amount_paid,
+				"debit_in_account_currency": self.amount_paid,
+				"against_voucher_type": "Loan",
+				"against_voucher": self.against_loan,
+				"remarks": remarks,
+				"cost_center": self.cost_center,
+				"posting_date": getdate(self.posting_date)
+			})
+		)
+
+		gle_map.append(
+			self.get_gl_dict({
+				"account": loan_details.loan_account,
+				"party_type": loan_details.applicant_type,
+				"party": loan_details.applicant,
+				"against": payment_account,
+				"credit": self.amount_paid,
+				"credit_in_account_currency": self.amount_paid,
+				"against_voucher_type": "Loan",
+				"against_voucher": self.against_loan,
+				"remarks": remarks,
+				"cost_center": self.cost_center,
+				"posting_date": getdate(self.posting_date)
+			})
+		)
+
+		if gle_map:
+			make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj, merge_entries=False)
 
 def create_repayment_entry(loan, applicant, company, posting_date, loan_type,
-	payment_type, interest_payable, payable_principal_amount, amount_paid, penalty_amount=None):
+	payment_type, interest_payable, payable_principal_amount, amount_paid, penalty_amount=None,
+	payroll_payable_account=None):
 
 	lr = frappe.get_doc({
 		"doctype": "Loan Repayment",
@@ -321,7 +405,8 @@
 		"interest_payable": interest_payable,
 		"payable_principal_amount": payable_principal_amount,
 		"amount_paid": amount_paid,
-		"loan_type": loan_type
+		"loan_type": loan_type,
+		"payroll_payable_account": payroll_payable_account
 	}).insert()
 
 	return lr
@@ -361,6 +446,76 @@
 	else:
 		return None, 0
 
+def regenerate_repayment_schedule(loan, cancel=0):
+	from erpnext.loan_management.doctype.loan.loan import (
+		add_single_month,
+		get_monthly_repayment_amount,
+	)
+
+	loan_doc = frappe.get_doc('Loan', loan)
+	next_accrual_date = None
+	accrued_entries = 0
+	last_repayment_amount = 0
+	last_balance_amount = 0
+
+	for term in reversed(loan_doc.get('repayment_schedule')):
+		if not term.is_accrued:
+			next_accrual_date = term.payment_date
+			loan_doc.remove(term)
+		else:
+			accrued_entries += 1
+			if not last_repayment_amount:
+				last_repayment_amount = term.total_payment
+			if not last_balance_amount:
+				last_balance_amount = term.balance_loan_amount
+
+	loan_doc.save()
+
+	balance_amount = get_pending_principal_amount(loan_doc)
+
+	if loan_doc.repayment_method == 'Repay Fixed Amount per Period':
+		monthly_repayment_amount = flt(balance_amount/len(loan_doc.get('repayment_schedule')) - accrued_entries)
+	else:
+		if not cancel:
+			monthly_repayment_amount = get_monthly_repayment_amount(balance_amount,
+				loan_doc.rate_of_interest, loan_doc.repayment_periods - accrued_entries)
+		else:
+			monthly_repayment_amount = last_repayment_amount
+			balance_amount = last_balance_amount
+
+	payment_date = next_accrual_date
+
+	while(balance_amount > 0):
+		interest_amount = flt(balance_amount * flt(loan_doc.rate_of_interest) / (12*100))
+		principal_amount = monthly_repayment_amount - interest_amount
+		balance_amount = flt(balance_amount + interest_amount - monthly_repayment_amount)
+		if balance_amount < 0:
+			principal_amount += balance_amount
+			balance_amount = 0.0
+
+		total_payment = principal_amount + interest_amount
+		loan_doc.append("repayment_schedule", {
+			"payment_date": payment_date,
+			"principal_amount": principal_amount,
+			"interest_amount": interest_amount,
+			"total_payment": total_payment,
+			"balance_loan_amount": balance_amount
+		})
+		next_payment_date = add_single_month(payment_date)
+		payment_date = next_payment_date
+
+	loan_doc.save()
+
+def get_pending_principal_amount(loan):
+	if loan.status in ('Disbursed', 'Closed') or loan.disbursed_amount >= loan.loan_amount:
+		pending_principal_amount = flt(loan.total_payment) - flt(loan.total_principal_paid) \
+			- flt(loan.total_interest_payable) - flt(loan.written_off_amount)
+	else:
+		pending_principal_amount = flt(loan.disbursed_amount) - flt(loan.total_principal_paid) \
+			- flt(loan.total_interest_payable) - flt(loan.written_off_amount)
+
+	return pending_principal_amount
+
 # This function returns the amounts that are payable at the time of loan repayment based on posting date
 # So it pulls all the unpaid Loan Interest Accrual Entries and calculates the penalty if applicable
 
@@ -408,12 +563,7 @@
 		if due_date and not final_due_date:
 			final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
 
-	if against_loan_doc.status in ('Disbursed', 'Closed') or against_loan_doc.disbursed_amount >= against_loan_doc.loan_amount:
-		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid \
-			- against_loan_doc.total_interest_payable - against_loan_doc.written_off_amount
-	else:
-		pending_principal_amount = against_loan_doc.disbursed_amount - against_loan_doc.total_principal_paid \
-			- against_loan_doc.total_interest_payable - against_loan_doc.written_off_amount
+	pending_principal_amount = get_pending_principal_amount(against_loan_doc)
 
 	unaccrued_interest = 0
 	if due_date:
diff --git a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
index bff9d5c..4567374 100644
--- a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
+++ b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
@@ -27,6 +27,9 @@
 					d.idx, frappe.bold(d.loan_security)))
 
 	def validate_unpledge_qty(self):
+		from erpnext.loan_management.doctype.loan_repayment.loan_repayment import (
+			get_pending_principal_amount,
+		)
 		from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import (
 			get_ltv_ratio,
 		)
@@ -43,15 +46,10 @@
 				"valid_upto": (">=", get_datetime())
 			}, as_list=1))
 
-		loan_details = frappe.get_value("Loan", self.loan, ['total_payment', 'total_principal_paid',
+		loan_details = frappe.get_value("Loan", self.loan, ['total_payment', 'total_principal_paid', 'loan_amount',
 			'total_interest_payable', 'written_off_amount', 'disbursed_amount', 'status'], as_dict=1)
 
-		if loan_details.status == 'Disbursed':
-			pending_principal_amount = flt(loan_details.total_payment) - flt(loan_details.total_interest_payable) \
-				- flt(loan_details.total_principal_paid) - flt(loan_details.written_off_amount)
-		else:
-			pending_principal_amount = flt(loan_details.disbursed_amount) - flt(loan_details.total_interest_payable) \
-				- flt(loan_details.total_principal_paid) - flt(loan_details.written_off_amount)
+		pending_principal_amount = get_pending_principal_amount(loan_details)
 
 		security_value = 0
 		unpledge_qty_map = {}
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index f82d9a0..5a60fb7 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -530,16 +530,6 @@
 				row.hour_rate = (hour_rate / flt(self.conversion_rate)
 					if self.conversion_rate and hour_rate else hour_rate)
 
-			if self.routing:
-				time_in_mins = flt(frappe.db.get_value("BOM Operation", {
-						"workstation": row.workstation,
-						"operation": row.operation,
-						"parent": self.routing
-				}, ["time_in_mins"]))
-
-				if time_in_mins:
-					row.time_in_mins = time_in_mins
-
 		if row.hour_rate and row.time_in_mins:
 			row.base_hour_rate = flt(row.hour_rate) * flt(self.conversion_rate)
 			row.operating_cost = flt(row.hour_rate) * flt(row.time_in_mins) / 60.0
diff --git a/erpnext/manufacturing/doctype/routing/test_routing.py b/erpnext/manufacturing/doctype/routing/test_routing.py
index e90b0a7..8bd60ea 100644
--- a/erpnext/manufacturing/doctype/routing/test_routing.py
+++ b/erpnext/manufacturing/doctype/routing/test_routing.py
@@ -46,6 +46,7 @@
 		wo_doc.delete()
 
 	def test_update_bom_operation_time(self):
+		"""Update cost shouldn't update routing times."""
 		operations = [
 			{
 				"operation": "Test Operation A",
@@ -85,8 +86,8 @@
 		routing_doc.save()
 		bom_doc.update_cost()
 		bom_doc.reload()
-		self.assertEqual(bom_doc.operations[0].time_in_mins, 90)
-		self.assertEqual(bom_doc.operations[1].time_in_mins, 42.2)
+		self.assertEqual(bom_doc.operations[0].time_in_mins, 30)
+		self.assertEqual(bom_doc.operations[1].time_in_mins, 20)
 
 
 def setup_operations(rows):
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index 15a24a7..ae0bb2d 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -16,7 +16,6 @@
 Education
 Regional
 Restaurant
-Agriculture
 ERPNext Integrations
 Non Profit
 Hotels
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index beb38e2..f9b295a 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -409,7 +409,7 @@
 def set_expired_status():
 	frappe.db.sql("""
 		UPDATE
-			`tabMembership` SET `status` = 'Expired'
+			`tabMembership` SET `membership_status` = 'Expired'
 		WHERE
-			`status` not in ('Cancelled') AND `to_date` < %s
+			`membership_status` not in ('Cancelled') AND `to_date` < %s
 		""", (nowdate()))
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 716dcc0..821a493 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -165,7 +165,6 @@
 erpnext.patches.v12_0.set_default_payroll_based_on
 erpnext.patches.v12_0.repost_stock_ledger_entries_for_target_warehouse
 erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
-erpnext.patches.v13_0.validate_options_for_data_field
 erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab #123
 erpnext.patches.v12_0.fix_quotation_expired_status
 erpnext.patches.v12_0.rename_pos_closing_doctype
@@ -280,6 +279,7 @@
 erpnext.patches.v13_0.update_recipient_email_digest
 erpnext.patches.v13_0.shopify_deprecation_warning
 erpnext.patches.v13_0.remove_bad_selling_defaults
+erpnext.patches.v13_0.trim_whitespace_from_serial_nos
 erpnext.patches.v13_0.migrate_stripe_api
 erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries
 erpnext.patches.v13_0.einvoicing_deprecation_warning
@@ -320,3 +320,7 @@
 erpnext.patches.v14_0.add_default_exit_questionnaire_notification_template
 erpnext.patches.v13_0.update_tax_category_for_rcm
 execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')
+erpnext.patches.v14_0.set_payroll_cost_centers
+erpnext.patches.v13_0.agriculture_deprecation_warning
+erpnext.patches.v14_0.delete_agriculture_doctypes
+erpnext.patches.v13_0.update_exchange_rate_settings
diff --git a/erpnext/patches/v12_0/update_bom_in_so_mr.py b/erpnext/patches/v12_0/update_bom_in_so_mr.py
index 37d850f..132f3bd 100644
--- a/erpnext/patches/v12_0/update_bom_in_so_mr.py
+++ b/erpnext/patches/v12_0/update_bom_in_so_mr.py
@@ -6,7 +6,7 @@
 	frappe.reload_doc("selling", "doctype", "sales_order_item")
 
 	for doctype in ["Sales Order", "Material Request"]:
-		condition = " and child_doc.stock_qty > child_doc.produced_qty"
+		condition = " and child_doc.stock_qty > child_doc.produced_qty and doc.per_delivered < 100"
 		if doctype == "Material Request":
 			condition = " and doc.per_ordered < 100 and doc.material_request_type = 'Manufacture'"
 
@@ -15,5 +15,6 @@
 				child_doc.bom_no = item.default_bom
 			WHERE
 				child_doc.item_code = item.name and child_doc.docstatus < 2
+				and child_doc.parent = doc.name
 				and item.default_bom is not null and item.default_bom != '' {cond}
 		""".format(doc = doctype, cond = condition))
diff --git a/erpnext/patches/v13_0/agriculture_deprecation_warning.py b/erpnext/patches/v13_0/agriculture_deprecation_warning.py
new file mode 100644
index 0000000..512444e
--- /dev/null
+++ b/erpnext/patches/v13_0/agriculture_deprecation_warning.py
@@ -0,0 +1,10 @@
+import click
+
+
+def execute():
+
+	click.secho(
+		"Agriculture Domain is moved to a separate app and will be removed from ERPNext in version-14.\n"
+		"Please install the app to continue using the Agriculture domain: https://github.com/frappe/agriculture",
+		fg="yellow",
+	)
diff --git a/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
new file mode 100644
index 0000000..8a9633d
--- /dev/null
+++ b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
@@ -0,0 +1,65 @@
+import frappe
+
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+
+
+def execute():
+	broken_sles = frappe.db.sql("""
+			select name, serial_no
+			from `tabStock Ledger Entry`
+			where
+				is_cancelled = 0
+				and (serial_no like %s or serial_no like %s or serial_no like %s or serial_no like %s)
+			""",
+			(
+				" %",    # leading whitespace
+				"% ",    # trailing whitespace
+				"%\n %", # leading whitespace on newline
+				"% \n%", # trailing whitespace on newline
+			),
+			as_dict=True,
+		)
+
+	frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sles)
+
+	if not broken_sles:
+		return
+
+	broken_serial_nos = set()
+
+	# patch SLEs
+	for sle in broken_sles:
+		serial_no_list = get_serial_nos(sle.serial_no)
+		correct_sr_no = "\n".join(serial_no_list)
+
+		if correct_sr_no == sle.serial_no:
+			continue
+
+		frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_no", correct_sr_no, update_modified=False)
+		broken_serial_nos.update(serial_no_list)
+
+	if not broken_serial_nos:
+		return
+
+	# Patch serial No documents if they don't have purchase info
+	# Purchase info is used for fetching incoming rate
+	broken_sr_no_records = frappe.get_list("Serial No",
+			filters={
+				"status":"Active",
+				"name": ("in", broken_serial_nos),
+				"purchase_document_type": ("is", "not set")
+			},
+			pluck="name",
+		)
+
+	frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sr_no_records)
+
+	patch_savepoint = "serial_no_patch"
+	for serial_no in broken_sr_no_records:
+		try:
+			frappe.db.savepoint(patch_savepoint)
+			sn = frappe.get_doc("Serial No", serial_no)
+			sn.update_serial_no_reference()
+			sn.db_update()
+		except Exception:
+			frappe.db.rollback(save_point=patch_savepoint)
diff --git a/erpnext/patches/v13_0/update_exchange_rate_settings.py b/erpnext/patches/v13_0/update_exchange_rate_settings.py
new file mode 100644
index 0000000..b7ec232
--- /dev/null
+++ b/erpnext/patches/v13_0/update_exchange_rate_settings.py
@@ -0,0 +1,10 @@
+import frappe
+
+from erpnext.setup.install import setup_currency_exchange
+
+
+def execute():
+	frappe.reload_doc("accounts", "doctype", "currency_exchange_settings")
+	frappe.reload_doc("accounts", "doctype", "currency_exchange_settings_result")
+	frappe.reload_doc("accounts", "doctype", "currency_exchange_settings_details")
+	setup_currency_exchange()
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/validate_options_for_data_field.py b/erpnext/patches/v13_0/validate_options_for_data_field.py
deleted file mode 100644
index ad777b8..0000000
--- a/erpnext/patches/v13_0/validate_options_for_data_field.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2021, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import frappe
-from frappe.model import data_field_options
-
-
-def execute():
-
-    for field in frappe.get_all('Custom Field',
-                            fields = ['name'],
-                            filters = {
-                                'fieldtype': 'Data',
-                                'options': ['!=', None]
-                            }):
-
-        if field not in data_field_options:
-            frappe.db.sql("""
-                UPDATE
-                    `tabCustom Field`
-                SET
-                    options=NULL
-                WHERE
-                    name=%s
-            """, (field))
diff --git a/erpnext/patches/v14_0/delete_agriculture_doctypes.py b/erpnext/patches/v14_0/delete_agriculture_doctypes.py
new file mode 100644
index 0000000..d7fe832
--- /dev/null
+++ b/erpnext/patches/v14_0/delete_agriculture_doctypes.py
@@ -0,0 +1,19 @@
+import frappe
+
+
+def execute():
+	frappe.delete_doc("Module Def", "Agriculture", ignore_missing=True, force=True)
+
+	frappe.delete_doc("Workspace", "Agriculture", ignore_missing=True, force=True)
+
+	reports = frappe.get_all("Report", {"module": "agriculture", "is_standard": "Yes"}, pluck='name')
+	for report in reports:
+		frappe.delete_doc("Report", report, ignore_missing=True, force=True)
+
+	dashboards = frappe.get_all("Dashboard", {"module": "agriculture", "is_standard": 1}, pluck='name')
+	for dashboard in dashboards:
+		frappe.delete_doc("Dashboard", dashboard, ignore_missing=True, force=True)
+
+	doctypes = frappe.get_all("DocType", {"module": "agriculture", "custom": 0}, pluck='name')
+	for doctype in doctypes:
+		frappe.delete_doc("DocType", doctype, ignore_missing=True)
diff --git a/erpnext/patches/v14_0/set_payroll_cost_centers.py b/erpnext/patches/v14_0/set_payroll_cost_centers.py
new file mode 100644
index 0000000..89b305b
--- /dev/null
+++ b/erpnext/patches/v14_0/set_payroll_cost_centers.py
@@ -0,0 +1,32 @@
+import frappe
+
+
+def execute():
+	frappe.reload_doc('payroll', 'doctype', 'employee_cost_center')
+	frappe.reload_doc('payroll', 'doctype', 'salary_structure_assignment')
+
+	employees = frappe.get_all("Employee", fields=["department", "payroll_cost_center", "name"])
+
+	employee_cost_center = {}
+	for d in employees:
+		cost_center = d.payroll_cost_center
+		if not cost_center and d.department:
+			cost_center = frappe.get_cached_value("Department", d.department, "payroll_cost_center")
+
+		if cost_center:
+			employee_cost_center.setdefault(d.name, cost_center)
+
+	salary_structure_assignments = frappe.get_all("Salary Structure Assignment",
+		filters = {"docstatus": ["!=", 2]},
+		fields=["name", "employee"])
+
+	for d in salary_structure_assignments:
+		cost_center = employee_cost_center.get(d.employee)
+		if cost_center:
+			assignment = frappe.get_doc("Salary Structure Assignment", d.name)
+			if not assignment.get("payroll_cost_centers"):
+				assignment.append("payroll_cost_centers", {
+					"cost_center": cost_center,
+					"percentage": 100
+				})
+				assignment.save()
\ No newline at end of file
diff --git a/erpnext/agriculture/doctype/weather_parameter/__init__.py b/erpnext/payroll/doctype/employee_cost_center/__init__.py
similarity index 100%
rename from erpnext/agriculture/doctype/weather_parameter/__init__.py
rename to erpnext/payroll/doctype/employee_cost_center/__init__.py
diff --git a/erpnext/payroll/doctype/employee_cost_center/employee_cost_center.json b/erpnext/payroll/doctype/employee_cost_center/employee_cost_center.json
new file mode 100644
index 0000000..8fed9f7
--- /dev/null
+++ b/erpnext/payroll/doctype/employee_cost_center/employee_cost_center.json
@@ -0,0 +1,43 @@
+{
+ "actions": [],
+ "creation": "2021-12-23 12:44:38.389283",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "cost_center",
+  "percentage"
+ ],
+ "fields": [
+  {
+   "allow_on_submit": 1,
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Cost Center",
+   "options": "Cost Center",
+   "reqd": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "percentage",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Percentage (%)",
+   "non_negative": 1,
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-12-23 17:39:03.410924",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Employee Cost Center",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": []
+}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_cost_center/employee_cost_center.py b/erpnext/payroll/doctype/employee_cost_center/employee_cost_center.py
new file mode 100644
index 0000000..6c5be97
--- /dev/null
+++ b/erpnext/payroll/doctype/employee_cost_center/employee_cost_center.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class EmployeeCostCenter(Document):
+	pass
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 84c59a2..ed3fa5b 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -7,6 +7,7 @@
 from frappe import _
 from frappe.desk.reportview import get_filters_cond, get_match_cond
 from frappe.model.document import Document
+from frappe.query_builder.functions import Coalesce
 from frappe.utils import (
 	DATE_FORMAT,
 	add_days,
@@ -157,11 +158,20 @@
 			Returns list of salary slips based on selected criteria
 		"""
 
-		ss_list = frappe.db.sql("""
-			select t1.name, t1.salary_structure, t1.payroll_cost_center from `tabSalary Slip` t1
-			where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s and t1.payroll_entry = %s
-			and (t1.journal_entry is null or t1.journal_entry = "") and ifnull(salary_slip_based_on_timesheet,0) = %s
-		""", (ss_status, self.start_date, self.end_date, self.name, self.salary_slip_based_on_timesheet), as_dict=as_dict)
+		ss = frappe.qb.DocType("Salary Slip")
+		ss_list = (
+			frappe.qb.from_(ss)
+				.select(ss.name, ss.salary_structure)
+				.where(
+					(ss.docstatus == ss_status)
+					& (ss.start_date >= self.start_date)
+					& (ss.end_date <= self.end_date)
+					& (ss.payroll_entry == self.name)
+					& ((ss.journal_entry.isnull()) | (ss.journal_entry == ""))
+					& (Coalesce(ss.salary_slip_based_on_timesheet, 0) == self.salary_slip_based_on_timesheet)
+				)
+		).run(as_dict=as_dict)
+
 		return ss_list
 
 	@frappe.whitelist()
@@ -190,13 +200,20 @@
 
 	def get_salary_components(self, component_type):
 		salary_slips = self.get_sal_slip_list(ss_status = 1, as_dict = True)
+
 		if salary_slips:
-			salary_components = frappe.db.sql("""
-				select ssd.salary_component, ssd.amount, ssd.parentfield, ss.payroll_cost_center
-				from `tabSalary Slip` ss, `tabSalary Detail` ssd
-				where ss.name = ssd.parent and ssd.parentfield = '%s' and ss.name in (%s)
-			""" % (component_type, ', '.join(['%s']*len(salary_slips))),
-				tuple([d.name for d in salary_slips]), as_dict=True)
+			ss = frappe.qb.DocType("Salary Slip")
+			ssd = frappe.qb.DocType("Salary Detail")
+			salary_components = (
+				frappe.qb.from_(ss)
+					.join(ssd)
+					.on(ss.name == ssd.parent)
+					.select(ssd.salary_component, ssd.amount, ssd.parentfield, ss.salary_structure, ss.employee)
+					.where(
+						(ssd.parentfield == component_type)
+						& (ss.name.isin(tuple([d.name for d in salary_slips])))
+					)
+			).run(as_dict=True)
 
 			return salary_components
 
@@ -204,18 +221,49 @@
 		salary_components = self.get_salary_components(component_type)
 		if salary_components:
 			component_dict = {}
+			self.employee_cost_centers = {}
 			for item in salary_components:
+				employee_cost_centers = self.get_payroll_cost_centers_for_employee(item.employee, item.salary_structure)
+
 				add_component_to_accrual_jv_entry = True
 				if component_type == "earnings":
-					is_flexible_benefit, only_tax_impact = frappe.db.get_value("Salary Component", item['salary_component'], ['is_flexible_benefit', 'only_tax_impact'])
+					is_flexible_benefit, only_tax_impact = \
+						frappe.get_cached_value("Salary Component",item['salary_component'], ['is_flexible_benefit', 'only_tax_impact'])
 					if is_flexible_benefit == 1 and only_tax_impact ==1:
 						add_component_to_accrual_jv_entry = False
+
 				if add_component_to_accrual_jv_entry:
-					component_dict[(item.salary_component, item.payroll_cost_center)] \
-						= component_dict.get((item.salary_component, item.payroll_cost_center), 0) + flt(item.amount)
+					for cost_center, percentage in employee_cost_centers.items():
+						amount_against_cost_center = flt(item.amount) * percentage / 100
+						component_dict[(item.salary_component, cost_center)] \
+							= component_dict.get((item.salary_component, cost_center), 0) + amount_against_cost_center
+
 			account_details = self.get_account(component_dict = component_dict)
 			return account_details
 
+	def get_payroll_cost_centers_for_employee(self, employee, salary_structure):
+		if not self.employee_cost_centers.get(employee):
+			ss_assignment_name = frappe.db.get_value("Salary Structure Assignment",
+				{"employee": employee, "salary_structure": salary_structure, "docstatus": 1}, 'name')
+
+			if ss_assignment_name:
+				cost_centers = dict(frappe.get_all("Employee Cost Center", {"parent": ss_assignment_name},
+					["cost_center", "percentage"], as_list=1))
+				if not cost_centers:
+					default_cost_center, department = frappe.get_cached_value("Employee", employee, ["payroll_cost_center", "department"])
+					if not default_cost_center and department:
+						default_cost_center = frappe.get_cached_value("Department", department, "payroll_cost_center")
+					if not default_cost_center:
+						default_cost_center = self.cost_center
+
+					cost_centers = {
+						default_cost_center: 100
+					}
+
+				self.employee_cost_centers.setdefault(employee, cost_centers)
+
+		return self.employee_cost_centers.get(employee, {})
+
 	def get_account(self, component_dict = None):
 		account_dict = {}
 		for key, amount in component_dict.items():
@@ -350,23 +398,24 @@
 		currencies = []
 		multi_currency = 0
 		company_currency = erpnext.get_company_currency(self.company)
+		accounting_dimensions = get_accounting_dimensions() or []
 
 		exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(self.payment_account, je_payment_amount, company_currency, currencies)
-		accounts.append({
+		accounts.append(self.update_accounting_dimensions({
 			"account": self.payment_account,
 			"bank_account": self.bank_account,
 			"credit_in_account_currency": flt(amount, precision),
 			"exchange_rate": flt(exchange_rate),
-		})
+		}, accounting_dimensions))
 
 		exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(payroll_payable_account, je_payment_amount, company_currency, currencies)
-		accounts.append({
+		accounts.append(self.update_accounting_dimensions({
 			"account": payroll_payable_account,
 			"debit_in_account_currency": flt(amount, precision),
 			"exchange_rate": flt(exchange_rate),
 			"reference_type": self.doctype,
 			"reference_name": self.name
-		})
+		}, accounting_dimensions))
 
 		if len(currencies) > 1:
 				multi_currency = 1
diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
index c6f3897..4f097fa 100644
--- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
@@ -120,8 +120,7 @@
 
 		employee1 = make_employee("test_employee1@example.com", payroll_cost_center="_Test Cost Center - _TC",
 			department="cc - _TC", company="_Test Company")
-		employee2 = make_employee("test_employee2@example.com", payroll_cost_center="_Test Cost Center 2 - _TC",
-			department="cc - _TC", company="_Test Company")
+		employee2 = make_employee("test_employee2@example.com", department="cc - _TC", company="_Test Company")
 
 		if not frappe.db.exists("Account", "_Test Payroll Payable - _TC"):
 				create_account(account_name="_Test Payroll Payable",
@@ -132,8 +131,26 @@
 				frappe.db.set_value("Company", "_Test Company", "default_payroll_payable_account",
 					"_Test Payroll Payable - _TC")
 		currency=frappe.db.get_value("Company", "_Test Company", "default_currency")
+
 		make_salary_structure("_Test Salary Structure 1", "Monthly", employee1, company="_Test Company", currency=currency, test_tax=False)
-		make_salary_structure("_Test Salary Structure 2", "Monthly", employee2, company="_Test Company", currency=currency, test_tax=False)
+		ss = make_salary_structure("_Test Salary Structure 2", "Monthly", employee2, company="_Test Company", currency=currency, test_tax=False)
+
+		# update cost centers in salary structure assignment for employee2
+		ssa = frappe.db.get_value("Salary Structure Assignment",
+			{"employee": employee2, "salary_structure": ss.name, "docstatus": 1}, 'name')
+
+		ssa_doc = frappe.get_doc("Salary Structure Assignment", ssa)
+		ssa_doc.payroll_cost_centers = []
+		ssa_doc.append("payroll_cost_centers", {
+			"cost_center": "_Test Cost Center - _TC",
+			"percentage": 60
+		})
+		ssa_doc.append("payroll_cost_centers", {
+			"cost_center": "_Test Cost Center 2 - _TC",
+			"percentage": 40
+		})
+
+		ssa_doc.save()
 
 		dates = get_start_end_dates('Monthly', nowdate())
 		if not frappe.db.get_value("Salary Slip", {"start_date": dates.start_date, "end_date": dates.end_date}):
@@ -148,10 +165,10 @@
 			""", je)
 			expected_je = (
 				('_Test Payroll Payable - _TC', 'Main - _TC', 0.0, 155600.0),
-				('Salary - _TC', '_Test Cost Center - _TC', 78000.0, 0.0),
-				('Salary - _TC', '_Test Cost Center 2 - _TC', 78000.0, 0.0),
-				('Salary Deductions - _TC', '_Test Cost Center - _TC', 0.0, 200.0),
-				('Salary Deductions - _TC', '_Test Cost Center 2 - _TC', 0.0, 200.0)
+				('Salary - _TC', '_Test Cost Center - _TC', 124800.0, 0.0),
+				('Salary - _TC', '_Test Cost Center 2 - _TC', 31200.0, 0.0),
+				('Salary Deductions - _TC', '_Test Cost Center - _TC', 0.0, 320.0),
+				('Salary Deductions - _TC', '_Test Cost Center 2 - _TC', 0.0, 80.0)
 			)
 
 			self.assertEqual(je_entries, expected_je)
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 7a80e69..4e40e13 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -12,7 +12,6 @@
   "department",
   "designation",
   "branch",
-  "payroll_cost_center",
   "column_break1",
   "status",
   "journal_entry",
@@ -463,15 +462,6 @@
    "read_only": 1
   },
   {
-   "fetch_from": "employee.payroll_cost_center",
-   "fetch_if_empty": 1,
-   "fieldname": "payroll_cost_center",
-   "fieldtype": "Link",
-   "label": "Payroll Cost Center",
-   "options": "Cost Center",
-   "read_only": 1
-  },
-  {
    "fieldname": "mode_of_payment",
    "fieldtype": "Select",
    "label": "Mode Of Payment",
@@ -647,7 +637,7 @@
  "idx": 9,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-10-08 11:47:47.098248",
+ "modified": "2021-12-23 11:47:47.098248",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Slip",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index b035292..f33443d 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -932,8 +932,11 @@
 	def get_future_recurring_additional_amount(self, additional_salary, monthly_additional_amount):
 		future_recurring_additional_amount = 0
 		to_date = frappe.db.get_value("Additional Salary", additional_salary, 'to_date')
+
 		# future month count excluding current
-		future_recurring_period = (getdate(to_date).month - getdate(self.start_date).month)
+		from_date, to_date = getdate(self.start_date), getdate(to_date)
+		future_recurring_period = ((to_date.year - from_date.year) * 12) + (to_date.month - from_date.month)
+
 		if future_recurring_period > 0:
 			future_recurring_additional_amount = monthly_additional_amount * future_recurring_period # Used earning.additional_amount to consider the amount for the full month
 		return future_recurring_additional_amount
@@ -1032,7 +1035,8 @@
 		data.update({"annual_taxable_earning": annual_taxable_earning})
 		tax_amount = 0
 		for slab in tax_slab.slabs:
-			if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):
+			cond = cstr(slab.condition).strip()
+			if cond and not self.eval_tax_slab_condition(cond, data):
 				continue
 			if not slab.to_amount and annual_taxable_earning >= slab.from_amount:
 				tax_amount += (annual_taxable_earning - slab.from_amount + 1) * slab.percent_deduction *.01
@@ -1138,15 +1142,17 @@
 			})
 
 	def make_loan_repayment_entry(self):
+		payroll_payable_account = get_payroll_payable_account(self.company, self.payroll_entry)
 		for loan in self.loans:
-			repayment_entry = create_repayment_entry(loan.loan, self.employee,
-				self.company, self.posting_date, loan.loan_type, "Regular Payment", loan.interest_amount,
-				loan.principal_amount, loan.total_payment)
+			if loan.total_payment:
+				repayment_entry = create_repayment_entry(loan.loan, self.employee,
+					self.company, self.posting_date, loan.loan_type, "Regular Payment", loan.interest_amount,
+					loan.principal_amount, loan.total_payment, payroll_payable_account=payroll_payable_account)
 
-			repayment_entry.save()
-			repayment_entry.submit()
+				repayment_entry.save()
+				repayment_entry.submit()
 
-			frappe.db.set_value("Salary Slip Loan", loan.name, "loan_repayment_entry", repayment_entry.name)
+				frappe.db.set_value("Salary Slip Loan", loan.name, "loan_repayment_entry", repayment_entry.name)
 
 	def cancel_loan_repayment_entry(self):
 		for loan in self.loans:
@@ -1380,3 +1386,11 @@
 		],
 		as_dict=1,
 	)
+
+def get_payroll_payable_account(company, payroll_entry):
+	if payroll_entry:
+		payroll_payable_account = frappe.db.get_value('Payroll Entry', payroll_entry, 'payroll_payable_account')
+	else:
+		payroll_payable_account = frappe.db.get_value('Company', company, 'default_payroll_payable_account')
+
+	return payroll_payable_account
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index 3052a2b..c0e005a 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -171,6 +171,7 @@
 		salary_slip.end_date = month_end_date
 		salary_slip.save()
 		salary_slip.submit()
+		salary_slip.reload()
 
 		no_of_days = self.get_no_of_days()
 		days_in_month = no_of_days[0]
@@ -379,7 +380,7 @@
 		make_salary_structure("Test Loan Repayment Salary Structure", "Monthly", employee=applicant, currency='INR',
 			payroll_period=payroll_period)
 
-		frappe.db.sql("delete from tabLoan")
+		frappe.db.sql("delete from tabLoan where applicant = 'test_loan_repayment_salary_slip@salary.com'")
 		loan = create_loan(applicant, "Car Loan", 11000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1))
 		loan.repay_from_salary = 1
 		loan.submit()
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.py b/erpnext/payroll/doctype/salary_structure/salary_structure.py
index ae83c04..4cbf948 100644
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.py
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.py
@@ -167,15 +167,12 @@
 	def postprocess(source, target):
 		if employee:
 			employee_details = frappe.db.get_value("Employee", employee,
-				["employee_name", "branch", "designation", "department", "payroll_cost_center"], as_dict=1)
+				["employee_name", "branch", "designation", "department"], as_dict=1)
 			target.employee = employee
 			target.employee_name = employee_details.employee_name
 			target.branch = employee_details.branch
 			target.designation = employee_details.designation
 			target.department = employee_details.department
-			target.payroll_cost_center = employee_details.payroll_cost_center
-			if not target.payroll_cost_center and target.department:
-				target.payroll_cost_center = frappe.db.get_value("Department", target.department, "payroll_cost_center")
 
 		target.run_method('process_salary_structure', for_preview=for_preview)
 
diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js
index 6cd897e..220bfbf 100644
--- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js
+++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js
@@ -40,28 +40,29 @@
 				}
 			}
 		});
+
+		frm.set_query("cost_center", "payroll_cost_centers", function() {
+			return {
+				filters: {
+					"company": frm.doc.company,
+					"is_group": 0
+				}
+			};
+		});
 	},
 
 	employee: function(frm) {
-		if(frm.doc.employee){
+		if (frm.doc.employee) {
 			frappe.call({
-				method: "frappe.client.get_value",
-				args:{
-					doctype: "Employee",
-					fieldname: "company",
-					filters:{
-						name: frm.doc.employee
-					}
-				},
+				method: "set_payroll_cost_centers",
+				doc: frm.doc,
 				callback: function(data) {
-					if(data.message){
-						frm.set_value("company", data.message.company);
-					}
+					refresh_field("payroll_cost_centers");
 				}
 			});
 		}
-		else{
-			frm.set_value("company", null);
+		else {
+			frm.set_value("payroll_cost_centers", []);
 		}
 	},
 
diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
index c8b98e5..197ab5f 100644
--- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
+++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
@@ -22,7 +22,9 @@
   "base",
   "column_break_9",
   "variable",
-  "amended_from"
+  "amended_from",
+  "section_break_17",
+  "payroll_cost_centers"
  ],
  "fields": [
   {
@@ -90,7 +92,8 @@
   },
   {
    "fieldname": "section_break_7",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Base & Variable"
   },
   {
    "fieldname": "base",
@@ -141,14 +144,29 @@
    "fieldtype": "Link",
    "label": "Payroll Payable Account",
    "options": "Account"
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "employee",
+   "fieldname": "section_break_17",
+   "fieldtype": "Section Break",
+   "label": "Payroll Cost Centers"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "payroll_cost_centers",
+   "fieldtype": "Table",
+   "label": "Cost Centers",
+   "options": "Employee Cost Center"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2021-03-31 22:44:46.267974",
+ "modified": "2021-12-23 17:28:09.794444",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Structure Assignment",
+ "naming_rule": "Expression (old style)",
  "owner": "Administrator",
  "permissions": [
   {
@@ -193,6 +211,7 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "title_field": "employee_name",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py
index e1ff9ca..8359478 100644
--- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py
+++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py
@@ -5,7 +5,7 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import getdate
+from frappe.utils import flt, getdate
 
 
 class DuplicateAssignment(frappe.ValidationError): pass
@@ -15,6 +15,10 @@
 		self.validate_dates()
 		self.validate_income_tax_slab()
 		self.set_payroll_payable_account()
+		if not self.get("payroll_cost_centers"):
+			self.set_payroll_cost_centers()
+
+		self.validate_cost_center_distribution()
 
 	def validate_dates(self):
 		joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
@@ -51,6 +55,30 @@
 							"Company", self.company, "default_currency"), "is_group": 0})
 			self.payroll_payable_account = payroll_payable_account
 
+	@frappe.whitelist()
+	def set_payroll_cost_centers(self):
+		self.payroll_cost_centers = []
+		default_payroll_cost_center = self.get_payroll_cost_center()
+		if default_payroll_cost_center:
+			self.append("payroll_cost_centers", {
+				"cost_center": default_payroll_cost_center,
+				"percentage": 100
+			})
+
+	def get_payroll_cost_center(self):
+		payroll_cost_center = frappe.db.get_value("Employee", self.employee, "payroll_cost_center")
+		if not payroll_cost_center and self.department:
+			payroll_cost_center = frappe.db.get_value("Department", self.department, "payroll_cost_center")
+
+		return payroll_cost_center
+
+	def validate_cost_center_distribution(self):
+		if self.get("payroll_cost_centers"):
+			total_percentage = sum([flt(d.percentage) for d in self.get("payroll_cost_centers", [])])
+			if total_percentage != 100:
+				frappe.throw(_("Total percentage against cost centers should be 100"))
+
+
 def get_assigned_salary_structure(employee, on_date):
 	if not employee or not on_date:
 		return None
@@ -64,6 +92,7 @@
 		})
 	return salary_structure[0][0] if salary_structure else None
 
+
 @frappe.whitelist()
 def get_employee_currency(employee):
 	employee_currency = frappe.db.get_value('Salary Structure Assignment', {'employee': employee}, 'currency')
diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js
index 31460f6..4f19bbd 100644
--- a/erpnext/projects/doctype/project/project.js
+++ b/erpnext/projects/doctype/project/project.js
@@ -59,22 +59,16 @@
 
 			frm.trigger('show_dashboard');
 		}
-		frm.events.set_buttons(frm);
+		frm.trigger("set_custom_buttons");
 	},
 
-	set_buttons: function(frm) {
+	set_custom_buttons: function(frm) {
 		if (!frm.is_new()) {
 			frm.add_custom_button(__('Duplicate Project with Tasks'), () => {
 				frm.events.create_duplicate(frm);
-			});
+			}, __("Actions"));
 
-			frm.add_custom_button(__('Completed'), () => {
-				frm.events.set_status(frm, 'Completed');
-			}, __('Set Status'));
-
-			frm.add_custom_button(__('Cancelled'), () => {
-				frm.events.set_status(frm, 'Cancelled');
-			}, __('Set Status'));
+			frm.trigger("set_project_status_button");
 
 
 			if (frappe.model.can_read("Task")) {
@@ -83,7 +77,7 @@
 						"project": frm.doc.name
 					};
 					frappe.set_route("List", "Task", "Gantt");
-				});
+				}, __("View"));
 
 				frm.add_custom_button(__("Kanban Board"), () => {
 					frappe.call('erpnext.projects.doctype.project.project.create_kanban_board_if_not_exists', {
@@ -91,13 +85,35 @@
 					}).then(() => {
 						frappe.set_route('List', 'Task', 'Kanban', frm.doc.project_name);
 					});
-				});
+				}, __("View"));
 			}
 		}
 
 
 	},
 
+	set_project_status_button: function(frm) {
+		frm.add_custom_button(__('Set Project Status'), () => {
+			let d = new frappe.ui.Dialog({
+				"title": __("Set Project Status"),
+				"fields": [
+					{
+						"fieldname": "status",
+						"fieldtype": "Select",
+						"label": "Status",
+						"reqd": 1,
+						"options": "Completed\nCancelled",
+					},
+				],
+				primary_action: function() {
+					frm.events.set_status(frm, d.get_values().status);
+					d.hide();
+				},
+				primary_action_label: __("Set Project Status")
+			}).show();
+		}, __("Actions"));
+	},
+
 	create_duplicate: function(frm) {
 		return new Promise(resolve => {
 			frappe.prompt('Project Name', (data) => {
@@ -117,7 +133,9 @@
 	set_status: function(frm, status) {
 		frappe.confirm(__('Set Project and all Tasks to status {0}?', [status.bold()]), () => {
 			frappe.xcall('erpnext.projects.doctype.project.project.set_project_status',
-				{project: frm.doc.name, status: status}).then(() => { /* page will auto reload */ });
+				{project: frm.doc.name, status: status}).then(() => {
+				frm.reload_doc();
+			});
 		});
 	},
 
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 9b1ea04..8fa0538 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -102,7 +102,7 @@
 			frappe.throw(_("Completed On cannot be greater than Today"))
 
 	def update_depends_on(self):
-		depends_on_tasks = self.depends_on_tasks or ""
+		depends_on_tasks = ""
 		for d in self.depends_on:
 			if d.task and d.task not in depends_on_tasks:
 				depends_on_tasks += d.task + ","
diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py
index a0ac7c1..5f5b519 100644
--- a/erpnext/projects/doctype/task/test_task.py
+++ b/erpnext/projects/doctype/task/test_task.py
@@ -78,11 +78,11 @@
 			return frappe.db.get_value("ToDo",
 				filters={"reference_type": task.doctype, "reference_name": task.name,
 					"description": "Close this task"},
-				fieldname=("owner", "status"), as_dict=True)
+				fieldname=("allocated_to", "status"), as_dict=True)
 
 		assign()
 		todo = get_owner_and_status()
-		self.assertEqual(todo.owner, "test@example.com")
+		self.assertEqual(todo.allocated_to, "test@example.com")
 		self.assertEqual(todo.status, "Open")
 
 		# assignment should be
@@ -90,7 +90,7 @@
 		task.status = "Completed"
 		task.save()
 		todo = get_owner_and_status()
-		self.assertEqual(todo.owner, "test@example.com")
+		self.assertEqual(todo.allocated_to, "test@example.com")
 		self.assertEqual(todo.status, "Closed")
 
 	def test_overdue(self):
diff --git a/erpnext/projects/report/project_profitability/test_project_profitability.py b/erpnext/projects/report/project_profitability/test_project_profitability.py
index 0415690..1eb3d0d 100644
--- a/erpnext/projects/report/project_profitability/test_project_profitability.py
+++ b/erpnext/projects/report/project_profitability/test_project_profitability.py
@@ -25,6 +25,7 @@
 
 		self.timesheet = make_timesheet(emp, is_billable=1)
 		self.salary_slip = make_salary_slip(self.timesheet.name)
+		self.salary_slip.start_date = self.timesheet.start_date
 
 		holidays = self.salary_slip.get_holidays_for_employee(date, date)
 		if holidays:
@@ -41,8 +42,8 @@
 	def test_project_profitability(self):
 		filters = {
 			'company': '_Test Company',
-			'start_date': add_days(getdate(), -3),
-			'end_date': getdate()
+			'start_date': add_days(self.timesheet.start_date, -3),
+			'end_date': self.timesheet.start_date
 		}
 
 		report = execute(filters)
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 7c1c8c7..ae0e2a3 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -114,6 +114,8 @@
 
 				if ((!item.qty) && me.frm.doc.is_return) {
 					item.amount = flt(item.rate * -1, precision("amount", item));
+				} else if ((!item.qty) && me.frm.doc.is_debit_note) {
+					item.amount = flt(item.rate, precision("amount", item));
 				} else {
 					item.amount = flt(item.rate * item.qty, precision("amount", item));
 				}
@@ -710,14 +712,15 @@
 		frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
 
 		if(in_list(["Sales Invoice", "POS Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
-			var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+			let grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+			let base_grand_total = this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total;
 
 			if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
 				var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance
 					- this.frm.doc.write_off_amount), precision("grand_total"));
 			} else {
 				var total_amount_to_pay = flt(
-					(flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
+					(flt(base_grand_total, precision("base_grand_total"))
 						- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
 					precision("base_grand_total")
 				);
@@ -748,14 +751,15 @@
 	}
 
 	set_total_amount_to_default_mop() {
-		var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+		let grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+		let base_grand_total = this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total;
 
 		if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
 			var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance
 				- this.frm.doc.write_off_amount), precision("grand_total"));
 		} else {
 			var total_amount_to_pay = flt(
-				(flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
+				(flt(base_grand_total, precision("base_grand_total"))
 					- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
 				precision("base_grand_total")
 			);
diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js
index 38e1eb5..e746ce9 100644
--- a/erpnext/public/js/setup_wizard.js
+++ b/erpnext/public/js/setup_wizard.js
@@ -27,7 +27,6 @@
 					{ "label": __("Manufacturing"), "value": "Manufacturing" },
 					{ "label": __("Retail"), "value": "Retail" },
 					{ "label": __("Services"), "value": "Services" },
-					{ "label": __("Agriculture (beta)"), "value": "Agriculture" },
 					{ "label": __("Healthcare (beta)"), "value": "Healthcare" },
 					{ "label": __("Non Profit (beta)"), "value": "Non Profit" }
 				], reqd: 1
diff --git a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js
index 07a9301..6653141 100644
--- a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js
+++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js
@@ -2,7 +2,13 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('UAE VAT Settings', {
-	// refresh: function(frm) {
-
-	// }
+	onload: function(frm) {
+		frm.set_query('account', 'uae_vat_accounts', function() {
+			return {
+				filters: {
+					'company': frm.doc.company
+				}
+			};
+		});
+	}
 });
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 215b483..d443f9c 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -215,7 +215,7 @@
 
 	if tax_template_by_category:
 		party_details['taxes_and_charges'] = tax_template_by_category
-		return
+		return party_details
 
 	if not party_details.place_of_supply: return party_details
 	if not party_details.company_gstin: return party_details
diff --git a/erpnext/regional/report/ksa_vat/ksa_vat.py b/erpnext/regional/report/ksa_vat/ksa_vat.py
index b41b2b0..cc26bd7 100644
--- a/erpnext/regional/report/ksa_vat/ksa_vat.py
+++ b/erpnext/regional/report/ksa_vat/ksa_vat.py
@@ -20,25 +20,35 @@
 			"fieldname": "title",
 			"label": _("Title"),
 			"fieldtype": "Data",
-			"width": 300
+			"width": 300,
 		},
 		{
 			"fieldname": "amount",
 			"label": _("Amount (SAR)"),
 			"fieldtype": "Currency",
+			"options": "currency",
 			"width": 150,
 		},
 		{
 			"fieldname": "adjustment_amount",
 			"label": _("Adjustment (SAR)"),
 			"fieldtype": "Currency",
+			"options": "currency",
 			"width": 150,
 		},
 		{
 			"fieldname": "vat_amount",
 			"label": _("VAT Amount (SAR)"),
 			"fieldtype": "Currency",
+			"options": "currency",
 			"width": 150,
+		},
+		{
+			"fieldname": "currency",
+			"label": _("Currency"),
+			"fieldtype": "Currency",
+			"width": 150,
+			"hidden": 1
 		}
 	]
 
@@ -47,6 +57,8 @@
 
 	# Validate if vat settings exist
 	company = filters.get('company')
+	company_currency = frappe.get_cached_value('Company',  company, "default_currency")
+
 	if frappe.db.exists('KSA VAT Setting', company) is None:
 		url = get_url_to_list('KSA VAT Setting')
 		frappe.msgprint(_('Create <a href="{}">KSA VAT Setting</a> for this company').format(url))
@@ -55,7 +67,7 @@
 	ksa_vat_setting = frappe.get_doc('KSA VAT Setting', company)
 
 	# Sales Heading
-	append_data(data, 'VAT on Sales', '', '', '')
+	append_data(data, 'VAT on Sales', '', '', '', company_currency)
 
 	grand_total_taxable_amount = 0
 	grand_total_taxable_adjustment_amount = 0
@@ -67,7 +79,7 @@
 
 		# Adding results to data
 		append_data(data, vat_setting.title, total_taxable_amount,
-			total_taxable_adjustment_amount, total_tax)
+			total_taxable_adjustment_amount, total_tax, company_currency)
 
 		grand_total_taxable_amount += total_taxable_amount
 		grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
@@ -75,13 +87,13 @@
 
 	# Sales Grand Total
 	append_data(data, 'Grand Total', grand_total_taxable_amount,
-		grand_total_taxable_adjustment_amount, grand_total_tax)
+		grand_total_taxable_adjustment_amount, grand_total_tax, company_currency)
 
 	# Blank Line
-	append_data(data, '', '', '', '')
+	append_data(data, '', '', '', '', company_currency)
 
 	# Purchase Heading
-	append_data(data, 'VAT on Purchases', '', '', '')
+	append_data(data, 'VAT on Purchases', '', '', '', company_currency)
 
 	grand_total_taxable_amount = 0
 	grand_total_taxable_adjustment_amount = 0
@@ -93,7 +105,7 @@
 
 		# Adding results to data
 		append_data(data, vat_setting.title, total_taxable_amount,
-			total_taxable_adjustment_amount, total_tax)
+			total_taxable_adjustment_amount, total_tax, company_currency)
 
 		grand_total_taxable_amount += total_taxable_amount
 		grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
@@ -101,7 +113,7 @@
 
 	# Purchase Grand Total
 	append_data(data, 'Grand Total', grand_total_taxable_amount,
-		grand_total_taxable_adjustment_amount, grand_total_tax)
+		grand_total_taxable_adjustment_amount, grand_total_tax, company_currency)
 
 	return data
 
@@ -147,9 +159,10 @@
 
 
 
-def append_data(data, title, amount, adjustment_amount, vat_amount):
+def append_data(data, title, amount, adjustment_amount, vat_amount, company_currency):
 	"""Returns data with appended value."""
-	data.append({"title": _(title), "amount": amount, "adjustment_amount": adjustment_amount, "vat_amount": vat_amount})
+	data.append({"title": _(title), "amount": amount, "adjustment_amount": adjustment_amount, "vat_amount": vat_amount,
+		"currency": company_currency})
 
 def get_tax_amount(item_code, account_head, doctype, parent):
 	if doctype == 'Sales Invoice':
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index c4752ae..daab6fb 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -8,6 +8,7 @@
 from frappe.utils import flt, getdate, nowdate
 
 from erpnext.controllers.selling_controller import SellingController
+from erpnext.crm.utils import add_link_in_communication, copy_comments
 
 form_grid_templates = {
 	"items": "templates/form_grid/item_grid.html"
@@ -34,6 +35,16 @@
 		from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
 		make_packing_list(self)
 
+	def after_insert(self):
+		if frappe.db.get_single_value("CRM Settings", "carry_forward_communication_and_comments"):
+			if self.opportunity:
+				copy_comments("Opportunity", self.opportunity, self)
+				add_link_in_communication("Opportunity", self.opportunity, self)
+
+			elif self.quotation_to == "Lead" and self.party_name:
+				copy_comments("Lead", self.party_name, self)
+				add_link_in_communication("Lead", self.party_name, self)
+
 	def validate_valid_till(self):
 		if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date):
 			frappe.throw(_("Valid till date cannot be before transaction date"))
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index e61a634..ce74f6d 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -643,7 +643,7 @@
 				message: __('Item Code: {0} is not available under warehouse {1}.', [bold_item_code, bold_warehouse])
 			})
 		} else if (available_qty < qty_needed) {
-			frappe.show_alert({
+			frappe.throw({
 				message: __('Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2}.', [bold_item_code, bold_warehouse, bold_available_qty]),
 				indicator: 'orange'
 			});
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
index 4963852..a30bcd7 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -113,7 +113,7 @@
 			`<div class="item-wrapper"
 				data-item-code="${escape(item.item_code)}" data-serial-no="${escape(serial_no)}"
 				data-batch-no="${escape(batch_no)}" data-uom="${escape(stock_uom)}"
-				data-rate="${escape(price_list_rate)}"
+				data-rate="${escape(price_list_rate || 0)}"
 				title="${item.item_name}">
 
 				${get_item_image_html()}
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 91f60fb..45e8dcc 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -79,14 +79,11 @@
 	},
 
 	refresh: function(frm) {
-		if(!frm.doc.__islocal) {
-			frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1);
-			frm.set_df_property("parent_company", "read_only", 1);
-			disbale_coa_fields(frm);
-		}
+		frm.toggle_display('address_html', !frm.is_new());
 
-		frm.toggle_display('address_html', !frm.doc.__islocal);
-		if(!frm.doc.__islocal) {
+		if (!frm.is_new()) {
+			frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1);
+			disbale_coa_fields(frm);
 			frappe.contacts.render_address_and_contact(frm);
 
 			frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Company'}
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index e739739..0a02bcd 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -47,6 +47,7 @@
 		self.validate_perpetual_inventory()
 		self.validate_perpetual_inventory_for_non_stock_items()
 		self.check_country_change()
+		self.check_parent_changed()
 		self.set_chart_of_accounts()
 		self.validate_parent_company()
 
@@ -130,6 +131,10 @@
 			self.name in frappe.local.enable_perpetual_inventory:
 			frappe.local.enable_perpetual_inventory[self.name] = self.enable_perpetual_inventory
 
+		if frappe.flags.parent_company_changed:
+			from frappe.utils.nestedset import rebuild_tree
+			rebuild_tree("Company", "parent_company")
+
 		frappe.clear_cache()
 
 	def create_default_warehouses(self):
@@ -191,7 +196,7 @@
 	def check_country_change(self):
 		frappe.flags.country_change = False
 
-		if not self.get('__islocal') and \
+		if not self.is_new() and \
 			self.country != frappe.get_cached_value('Company',  self.name,  'country'):
 			frappe.flags.country_change = True
 
@@ -396,6 +401,13 @@
 		if not frappe.db.get_value('GL Entry', {'company': self.name}):
 			frappe.db.sql("delete from `tabProcess Deferred Accounting` where company=%s", self.name)
 
+	def check_parent_changed(self):
+		frappe.flags.parent_company_changed = False
+
+		if not self.is_new() and \
+			self.parent_company != frappe.db.get_value("Company",  self.name,  "parent_company"):
+			frappe.flags.parent_company_changed = True
+
 def get_name_with_abbr(name, company):
 	company_abbr = frappe.get_cached_value('Company',  company,  "abbr")
 	parts = name.split(" - ")
diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py
index 4ee9492..e175c54 100644
--- a/erpnext/setup/doctype/company/test_company.py
+++ b/erpnext/setup/doctype/company/test_company.py
@@ -93,6 +93,61 @@
 		frappe.db.sql(""" delete from `tabMode of Payment Account`
 			where company =%s """, (company))
 
+	def test_basic_tree(self, records=None):
+		min_lft = 1
+		max_rgt = frappe.db.sql("select max(rgt) from `tabCompany`")[0][0]
+
+		if not records:
+			records = test_records[2:]
+
+		for company in records:
+			lft, rgt, parent_company = frappe.db.get_value("Company", company["company_name"],
+				["lft", "rgt", "parent_company"])
+
+			if parent_company:
+				parent_lft, parent_rgt = frappe.db.get_value("Company", parent_company,
+					["lft", "rgt"])
+			else:
+				# root
+				parent_lft = min_lft - 1
+				parent_rgt = max_rgt + 1
+
+			self.assertTrue(lft)
+			self.assertTrue(rgt)
+			self.assertTrue(lft < rgt)
+			self.assertTrue(parent_lft < parent_rgt)
+			self.assertTrue(lft > parent_lft)
+			self.assertTrue(rgt < parent_rgt)
+			self.assertTrue(lft >= min_lft)
+			self.assertTrue(rgt <= max_rgt)
+
+	def get_no_of_children(self, company):
+		def get_no_of_children(companies, no_of_children):
+			children = []
+			for company in companies:
+				children += frappe.db.sql_list("""select name from `tabCompany`
+				where ifnull(parent_company, '')=%s""", company or '')
+
+			if len(children):
+				return get_no_of_children(children, no_of_children + len(children))
+			else:
+				return no_of_children
+
+		return get_no_of_children([company], 0)
+
+	def test_change_parent_company(self):
+		child_company = frappe.get_doc("Company", "_Test Company 5")
+
+		# changing parent of company
+		child_company.parent_company = "_Test Company 3"
+		child_company.save()
+		self.test_basic_tree()
+
+		# move it back
+		child_company.parent_company = "_Test Company 4"
+		child_company.save()
+		self.test_basic_tree()
+
 def create_company_communication(doctype, docname):
 	comm = frappe.get_doc({
 			"doctype": "Communication",
diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
index 2b007e9..06a79b4 100644
--- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
+++ b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
@@ -62,8 +62,13 @@
 		if kwargs['params'].get('date') and kwargs['params'].get('from') and kwargs['params'].get('to'):
 			if test_exchange_values.get(kwargs['params']['date']):
 				return PatchResponse({'result': test_exchange_values[kwargs['params']['date']]}, 200)
+	elif args[0].startswith("https://frankfurter.app") and kwargs.get('params'):
+		if kwargs['params'].get('base') and kwargs['params'].get('symbols'):
+			date = args[0].replace("https://frankfurter.app/", "")
+			if test_exchange_values.get(date):
+				return PatchResponse({'rates': {kwargs['params'].get('symbols'): test_exchange_values.get(date)}}, 200)
 
-	return PatchResponse({'result': None}, 404)
+	return PatchResponse({'rates': None}, 404)
 
 @mock.patch('requests.get', side_effect=patched_requests_get)
 class TestCurrencyExchange(unittest.TestCase):
@@ -102,6 +107,41 @@
 		self.assertFalse(exchange_rate == 60)
 		self.assertEqual(flt(exchange_rate, 3), 65.1)
 
+	def test_exchange_rate_via_exchangerate_host(self, mock_get):
+		save_new_records(test_records)
+
+		# Update Currency Exchange Rate
+		settings = frappe.get_single("Currency Exchange Settings")
+		settings.service_provider = 'exchangerate.host'
+		settings.save()
+
+		# Update exchange
+		frappe.db.set_value("Accounts Settings", None, "allow_stale", 1)
+
+		# Start with allow_stale is True
+		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01", "for_buying")
+		self.assertEqual(flt(exchange_rate, 3), 60.0)
+
+		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying")
+		self.assertEqual(exchange_rate, 65.1)
+
+		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30", "for_selling")
+		self.assertEqual(exchange_rate, 62.9)
+
+		# Exchange rate as on 15th Dec, 2015
+		self.clear_cache()
+		exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15", "for_selling")
+		self.assertFalse(exchange_rate == 60)
+		self.assertEqual(flt(exchange_rate, 3), 66.999)
+
+		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-20", "for_buying")
+		self.assertFalse(exchange_rate == 60)
+		self.assertEqual(flt(exchange_rate, 3), 65.1)
+
+		settings = frappe.get_single("Currency Exchange Settings")
+		settings.service_provider = 'frankfurter.app'
+		settings.save()
+
 	def test_exchange_rate_strict(self, mock_get):
 		# strict currency settings
 		frappe.db.set_value("Accounts Settings", None, "allow_stale", 0)
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index 86c9b3f..bafaab8 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -60,6 +60,22 @@
 
 	frappe.db.set_default("date_format", "dd-mm-yyyy")
 
+	setup_currency_exchange()
+
+def setup_currency_exchange():
+	ces = frappe.get_single('Currency Exchange Settings')
+	try:
+		ces.set('result_key', [])
+		ces.set('req_params', [])
+
+		ces.api_endpoint = "https://frankfurter.app/{transaction_date}"
+		ces.append('result_key', {'key': 'rates'})
+		ces.append('result_key', {'key': '{to_currency}'})
+		ces.append('req_params', {'key': 'base', 'value': '{from_currency}'})
+		ces.append('req_params', {'key': 'symbols', 'value': '{to_currency}'})
+		ces.save()
+	except frappe.ValidationError:
+		pass
 
 def create_compact_item_print_custom_field():
 	create_custom_field('Print Settings', {
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 97d850b..336b51c 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -33,7 +33,6 @@
 		{ 'doctype': 'Domain', 'domain': 'Services'},
 		{ 'doctype': 'Domain', 'domain': 'Education'},
 		{ 'doctype': 'Domain', 'domain': 'Healthcare'},
-		{ 'doctype': 'Domain', 'domain': 'Agriculture'},
 		{ 'doctype': 'Domain', 'domain': 'Non Profit'},
 
 		# ensure at least an empty Address Template exists for this Country
diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py
index cad4c54..4441bb9 100644
--- a/erpnext/setup/utils.py
+++ b/erpnext/setup/utils.py
@@ -100,15 +100,21 @@
 
 		if not value:
 			import requests
-			api_url = "https://api.exchangerate.host/convert"
-			response = requests.get(api_url, params={
-				"date": transaction_date,
-				"from": from_currency,
-				"to": to_currency
-			})
+			settings = frappe.get_cached_doc('Currency Exchange Settings')
+			req_params = {
+				"transaction_date": transaction_date,
+				"from_currency": from_currency,
+				"to_currency": to_currency
+			}
+			params = {}
+			for row in settings.req_params:
+				params[row.key] = format_ces_api(row.value, req_params)
+			response = requests.get(format_ces_api(settings.api_endpoint, req_params), params=params)
 			# expire in 6 hours
 			response.raise_for_status()
-			value = response.json()["result"]
+			value = response.json()
+			for res_key in settings.result_key:
+				value = value[format_ces_api(str(res_key.key), req_params)]
 			cache.setex(name=key, time=21600, value=flt(value))
 		return flt(value)
 	except Exception:
@@ -116,6 +122,13 @@
 		frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date))
 		return 0.0
 
+def format_ces_api(data, param):
+	return data.format(
+		transaction_date=param.get("transaction_date"),
+		to_currency=param.get("to_currency"),
+		from_currency=param.get("from_currency")
+	)
+
 def enable_all_roles_and_domains():
 	""" enable all roles and domain for testing """
 	# add all roles to users
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index fdefd24..5593101 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -312,3 +312,28 @@
 	if frappe.db.get_value("Item", args.item, "has_batch_no"):
 		args.doctype = "Batch"
 		frappe.get_doc(args).insert().name
+
+@frappe.whitelist()
+def get_pos_reserved_batch_qty(filters):
+	import json
+
+	if isinstance(filters, str):
+		filters = json.loads(filters)
+
+	p = frappe.qb.DocType("POS Invoice").as_("p")
+	item = frappe.qb.DocType("POS Invoice Item").as_("item")
+	sum_qty = frappe.query_builder.functions.Sum(item.qty).as_("qty")
+
+	reserved_batch_qty = frappe.qb.from_(p).from_(item).select(sum_qty).where(
+		(p.name == item.parent) &
+		(p.consolidated_invoice.isnull()) &
+		(p.status != "Consolidated") &
+		(p.docstatus == 1) &
+		(item.docstatus == 1) &
+		(item.item_code == filters.get('item_code')) &
+		(item.warehouse == filters.get('warehouse')) &
+		(item.batch_no == filters.get('batch_no'))
+	).run()
+
+	flt_reserved_batch_qty = flt(reserved_batch_qty[0][0])
+	return flt_reserved_batch_qty
\ No newline at end of file
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index a3d44af..6e1e0d4 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.json
+++ b/erpnext/stock/doctype/serial_no/serial_no.json
@@ -1,7 +1,6 @@
 {
  "actions": [],
  "allow_import": 1,
- "allow_rename": 1,
  "autoname": "field:serial_no",
  "creation": "2013-05-16 10:59:15",
  "description": "Distinct unit of an Item",
@@ -434,10 +433,11 @@
  "icon": "fa fa-barcode",
  "idx": 1,
  "links": [],
- "modified": "2021-01-08 14:31:15.375996",
+ "modified": "2021-12-23 10:44:30.299450",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Serial No",
+ "naming_rule": "By fieldname",
  "owner": "Administrator",
  "permissions": [
   {
@@ -476,5 +476,6 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ 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 38291d1..2947faf 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -194,23 +194,6 @@
 		if sle_exists:
 			frappe.throw(_("Cannot delete Serial No {0}, as it is used in stock transactions").format(self.name))
 
-	def before_rename(self, old, new, merge=False):
-		if merge:
-			frappe.throw(_("Sorry, Serial Nos cannot be merged"))
-
-	def after_rename(self, old, new, merge=False):
-		"""rename serial_no text fields"""
-		for dt in frappe.db.sql("""select parent from tabDocField
-			where fieldname='serial_no' and fieldtype in ('Text', 'Small Text', 'Long Text')"""):
-
-			for item in frappe.db.sql("""select name, serial_no from `tab%s`
-				where serial_no like %s""" % (dt[0], frappe.db.escape('%' + old + '%'))):
-
-				serial_nos = map(lambda i: new if i.upper()==old.upper() else i, item[1].split('\n'))
-				frappe.db.sql("""update `tab%s` set serial_no = %s
-					where name=%s""" % (dt[0], '%s', '%s'),
-					('\n'.join(list(serial_nos)), item[0]))
-
 	def update_serial_no_reference(self, serial_no=None):
 		last_sle = self.get_last_sle(serial_no)
 		self.set_purchase_details(last_sle.get("purchase_sle"))
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index a00d63e..93e303c 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -35,10 +35,16 @@
 from erpnext.stock.utils import get_bin, get_incoming_rate
 
 
-class IncorrectValuationRateError(frappe.ValidationError): pass
-class DuplicateEntryForWorkOrderError(frappe.ValidationError): pass
-class OperationsNotCompleteError(frappe.ValidationError): pass
-class MaxSampleAlreadyRetainedError(frappe.ValidationError): pass
+class FinishedGoodError(frappe.ValidationError):
+	pass
+class IncorrectValuationRateError(frappe.ValidationError):
+	pass
+class DuplicateEntryForWorkOrderError(frappe.ValidationError):
+	pass
+class OperationsNotCompleteError(frappe.ValidationError):
+	pass
+class MaxSampleAlreadyRetainedError(frappe.ValidationError):
+	pass
 
 from erpnext.controllers.stock_controller import StockController
 
@@ -701,6 +707,11 @@
 
 			finished_item = self.get_finished_item()
 
+			if not finished_item and self.purpose == "Manufacture":
+				# In case of independent Manufacture entry, don't auto set
+				# user must decide and set
+				return
+
 			for d in self.items:
 				if d.t_warehouse and not d.s_warehouse:
 					if self.purpose=="Repack" or d.item_code == finished_item:
@@ -721,38 +732,64 @@
 		return finished_item
 
 	def validate_finished_goods(self):
-		"""validation: finished good quantity should be same as manufacturing quantity"""
-		if not self.work_order: return
+		"""
+			1. Check if FG exists
+			2. Check if Multiple FG Items are present
+			3. Check FG Item and Qty against WO if present
+		"""
+		production_item, wo_qty, finished_items = None, 0, []
 
-		production_item, wo_qty = frappe.db.get_value("Work Order",
-			self.work_order, ["production_item", "qty"])
+		wo_details = frappe.db.get_value(
+			"Work Order", self.work_order, ["production_item", "qty"]
+		)
+		if wo_details:
+			production_item, wo_qty = wo_details
 
-		finished_items = []
 		for d in self.get('items'):
 			if d.is_finished_item:
+				if not self.work_order:
+					finished_items.append(d.item_code)
+					continue # Independent Manufacture Entry, no WO to match against
+
 				if d.item_code != production_item:
 					frappe.throw(_("Finished Item {0} does not match with Work Order {1}")
-						.format(d.item_code, self.work_order))
+						.format(d.item_code, self.work_order)
+					)
 				elif flt(d.transfer_qty) > flt(self.fg_completed_qty):
-					frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
-						format(d.idx, d.transfer_qty, self.fg_completed_qty))
+					frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}")
+						.format(d.idx, d.transfer_qty, self.fg_completed_qty)
+					)
+
 				finished_items.append(d.item_code)
 
 		if len(set(finished_items)) > 1:
-			frappe.throw(_("Multiple items cannot be marked as finished item"))
+			frappe.throw(
+				msg=_("Multiple items cannot be marked as finished item"),
+				title=_("Note"),
+				exc=FinishedGoodError
+			)
 
 		if self.purpose == "Manufacture":
 			if not finished_items:
-				frappe.throw(_('Finished Good has not set in the stock entry {0}')
-					.format(self.name))
+				frappe.throw(
+					msg=_("There must be atleast 1 Finished Good in this Stock Entry").format(self.name),
+					title=_("Missing Finished Good"),
+					exc=FinishedGoodError
+				)
 
-			allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
-				"overproduction_percentage_for_work_order"))
+			allowance_percentage = flt(
+				frappe.db.get_single_value(
+					"Manufacturing Settings","overproduction_percentage_for_work_order"
+				)
+			)
+			allowed_qty = wo_qty + ((allowance_percentage/100) * wo_qty)
 
-			allowed_qty = wo_qty + (allowance_percentage/100 * wo_qty)
-			if self.fg_completed_qty > allowed_qty:
-				frappe.throw(_("For quantity {0} should not be greater than work order quantity {1}")
-					.format(flt(self.fg_completed_qty), wo_qty))
+			# No work order could mean independent Manufacture entry, if so skip validation
+			if self.work_order and self.fg_completed_qty > allowed_qty:
+				frappe.throw(
+					_("For quantity {0} should not be greater than work order quantity {1}")
+					.format(flt(self.fg_completed_qty), wo_qty)
+				)
 
 	def update_stock_ledger(self):
 		sl_entries = []
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 5a9e77e..b874874 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -15,7 +15,10 @@
 	set_item_variant_settings,
 )
 from erpnext.stock.doctype.serial_no.serial_no import *  # noqa
-from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse
+from erpnext.stock.doctype.stock_entry.stock_entry import (
+	FinishedGoodError,
+	move_sample_to_retention_warehouse,
+)
 from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
 from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError
 from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import (
@@ -929,6 +932,38 @@
 		distributed_costs = [d.additional_cost for d in se.items]
 		self.assertEqual([40.0, 60.0], distributed_costs)
 
+	def test_independent_manufacture_entry(self):
+		"Test FG items and incoming rate calculation in Maniufacture Entry without WO or BOM linked."
+		se = frappe.get_doc(
+			doctype="Stock Entry",
+			purpose="Manufacture",
+			stock_entry_type="Manufacture",
+			company="_Test Company",
+			items=[
+				frappe._dict(item_code="_Test Item", qty=1, basic_rate=200, s_warehouse="_Test Warehouse - _TC"),
+				frappe._dict(item_code="_Test FG Item", qty=4, t_warehouse="_Test Warehouse 1 - _TC")
+			]
+		)
+		# SE must have atleast one FG
+		self.assertRaises(FinishedGoodError, se.save)
+
+		se.items[0].is_finished_item = 1
+		se.items[1].is_finished_item = 1
+		# SE cannot have multiple FGs
+		self.assertRaises(FinishedGoodError, se.save)
+
+		se.items[0].is_finished_item = 0
+		se.save()
+
+		# Check if FG cost is calculated based on RM total cost
+		# RM total cost = 200, FG rate = 200/4(FG qty) =  50
+		self.assertEqual(se.items[1].basic_rate, 50)
+		self.assertEqual(se.value_difference, 0.0)
+		self.assertEqual(se.total_incoming_value, se.total_outgoing_value)
+
+		# teardown
+		se.delete()
+
 	@change_settings("Stock Settings", {"allow_negative_stock": 0})
 	def test_future_negative_sle(self):
 		# Initialize item, batch, warehouse, opening qty
diff --git a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py
index d452ffd..be8597d 100644
--- a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py
+++ b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py
@@ -73,7 +73,7 @@
 	fields = ['name', 'voucher_type', 'voucher_no', 'item_code', 'serial_no as serial_nos', 'actual_qty',
 		'posting_date', 'posting_time', 'company', 'warehouse', '(stock_value_difference / actual_qty) as valuation_rate']
 
-	filters = {'serial_no': ("is", "set")}
+	filters = {'serial_no': ("is", "set"), "is_cancelled": 0}
 
 	if report_filters.get('item_code'):
 		filters['item_code'] = report_filters.get('item_code')
diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py
index 0ebe4f9..e6dfc97 100644
--- a/erpnext/stock/report/stock_ageing/stock_ageing.py
+++ b/erpnext/stock/report/stock_ageing/stock_ageing.py
@@ -3,6 +3,7 @@
 
 
 from operator import itemgetter
+from typing import Dict, List, Tuple, Union
 
 import frappe
 from frappe import _
@@ -10,19 +11,29 @@
 
 from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
 
+Filters = frappe._dict
 
-def execute(filters=None):
-	columns = get_columns(filters)
-	item_details = get_fifo_queue(filters)
+def execute(filters: Filters = None) -> Tuple:
 	to_date = filters["to_date"]
-	_func = itemgetter(1)
+	columns = get_columns(filters)
 
+	item_details = FIFOSlots(filters).generate()
+	data = format_report_data(filters, item_details, to_date)
+
+	chart_data = get_chart_data(data, filters)
+
+	return columns, data, None, chart_data
+
+def format_report_data(filters: Filters, item_details: Dict, to_date: str) -> List[Dict]:
+	"Returns ordered, formatted data with ranges."
+	_func = itemgetter(1)
 	data = []
+
 	for item, item_dict in item_details.items():
 		earliest_age, latest_age = 0, 0
+		details = item_dict["details"]
 
 		fifo_queue = sorted(filter(_func, item_dict["fifo_queue"]), key=_func)
-		details = item_dict["details"]
 
 		if not fifo_queue: continue
 
@@ -31,23 +42,22 @@
 		latest_age = date_diff(to_date, fifo_queue[-1][1])
 		range1, range2, range3, above_range3 = get_range_age(filters, fifo_queue, to_date, item_dict)
 
-		row = [details.name, details.item_name,
-			details.description, details.item_group, details.brand]
+		row = [details.name, details.item_name, details.description,
+			details.item_group, details.brand]
 
 		if filters.get("show_warehouse_wise_stock"):
 			row.append(details.warehouse)
 
 		row.extend([item_dict.get("total_qty"), average_age,
 			range1, range2, range3, above_range3,
-			earliest_age, latest_age, details.stock_uom])
+			earliest_age, latest_age,
+			details.stock_uom])
 
 		data.append(row)
 
-	chart_data = get_chart_data(data, filters)
+	return data
 
-	return columns, data, None, chart_data
-
-def get_average_age(fifo_queue, to_date):
+def get_average_age(fifo_queue: List, to_date: str) -> float:
 	batch_age = age_qty = total_qty = 0.0
 	for batch in fifo_queue:
 		batch_age = date_diff(to_date, batch[1])
@@ -61,7 +71,7 @@
 
 	return flt(age_qty / total_qty, 2) if total_qty else 0.0
 
-def get_range_age(filters, fifo_queue, to_date, item_dict):
+def get_range_age(filters: Filters, fifo_queue: List, to_date: str, item_dict: Dict) -> Tuple:
 	range1 = range2 = range3 = above_range3 = 0.0
 
 	for item in fifo_queue:
@@ -79,7 +89,7 @@
 
 	return range1, range2, range3, above_range3
 
-def get_columns(filters):
+def get_columns(filters: Filters) -> List[Dict]:
 	range_columns = []
 	setup_ageing_columns(filters, range_columns)
 	columns = [
@@ -164,106 +174,7 @@
 
 	return columns
 
-def get_fifo_queue(filters, sle=None):
-	item_details = {}
-	transferred_item_details = {}
-	serial_no_batch_purchase_details = {}
-
-	if sle == None:
-		sle = get_stock_ledger_entries(filters)
-
-	for d in sle:
-		key = (d.name, d.warehouse) if filters.get('show_warehouse_wise_stock') else d.name
-		item_details.setdefault(key, {"details": d, "fifo_queue": []})
-		fifo_queue = item_details[key]["fifo_queue"]
-
-		transferred_item_key = (d.voucher_no, d.name, d.warehouse)
-		transferred_item_details.setdefault(transferred_item_key, [])
-
-		if d.voucher_type == "Stock Reconciliation":
-			d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0))
-
-		serial_no_list = get_serial_nos(d.serial_no) if d.serial_no else []
-
-		if d.actual_qty > 0:
-			if transferred_item_details.get(transferred_item_key):
-				batch = transferred_item_details[transferred_item_key][0]
-				fifo_queue.append(batch)
-				transferred_item_details[transferred_item_key].pop(0)
-			else:
-				if serial_no_list:
-					for serial_no in serial_no_list:
-						if serial_no_batch_purchase_details.get(serial_no):
-							fifo_queue.append([serial_no, serial_no_batch_purchase_details.get(serial_no)])
-						else:
-							serial_no_batch_purchase_details.setdefault(serial_no, d.posting_date)
-							fifo_queue.append([serial_no, d.posting_date])
-				else:
-					fifo_queue.append([d.actual_qty, d.posting_date])
-		else:
-			if serial_no_list:
-				fifo_queue[:] = [serial_no for serial_no in fifo_queue if serial_no[0] not in serial_no_list]
-			else:
-				qty_to_pop = abs(d.actual_qty)
-				while qty_to_pop:
-					batch = fifo_queue[0] if fifo_queue else [0, None]
-					if 0 < flt(batch[0]) <= qty_to_pop:
-						# if batch qty > 0
-						# not enough or exactly same qty in current batch, clear batch
-						qty_to_pop -= flt(batch[0])
-						transferred_item_details[transferred_item_key].append(fifo_queue.pop(0))
-					else:
-						# all from current batch
-						batch[0] = flt(batch[0]) - qty_to_pop
-						transferred_item_details[transferred_item_key].append([qty_to_pop, batch[1]])
-						qty_to_pop = 0
-
-		item_details[key]["qty_after_transaction"] = d.qty_after_transaction
-
-		if "total_qty" not in item_details[key]:
-			item_details[key]["total_qty"] = d.actual_qty
-		else:
-			item_details[key]["total_qty"] += d.actual_qty
-
-		item_details[key]["has_serial_no"] = d.has_serial_no
-
-	return item_details
-
-def get_stock_ledger_entries(filters):
-	return frappe.db.sql("""select
-			item.name, item.item_name, item_group, brand, description, item.stock_uom, item.has_serial_no,
-			actual_qty, posting_date, voucher_type, voucher_no, serial_no, batch_no, qty_after_transaction, warehouse
-		from `tabStock Ledger Entry` sle,
-			(select name, item_name, description, stock_uom, brand, item_group, has_serial_no
-				from `tabItem` {item_conditions}) item
-		where item_code = item.name and
-			company = %(company)s and
-			posting_date <= %(to_date)s and
-			is_cancelled != 1
-			{sle_conditions}
-			order by posting_date, posting_time, sle.creation, actual_qty""" #nosec
-		.format(item_conditions=get_item_conditions(filters),
-			sle_conditions=get_sle_conditions(filters)), filters, as_dict=True)
-
-def get_item_conditions(filters):
-	conditions = []
-	if filters.get("item_code"):
-		conditions.append("item_code=%(item_code)s")
-	if filters.get("brand"):
-		conditions.append("brand=%(brand)s")
-
-	return "where {}".format(" and ".join(conditions)) if conditions else ""
-
-def get_sle_conditions(filters):
-	conditions = []
-	if filters.get("warehouse"):
-		lft, rgt = frappe.db.get_value('Warehouse', filters.get("warehouse"), ['lft', 'rgt'])
-		conditions.append("""warehouse in (select wh.name from `tabWarehouse` wh
-			where wh.lft >= {0} and rgt <= {1})""".format(lft, rgt))
-
-	return "and {}".format(" and ".join(conditions)) if conditions else ""
-
-def get_chart_data(data, filters):
+def get_chart_data(data: List, filters: Filters) -> Dict:
 	if not data:
 		return []
 
@@ -294,17 +205,201 @@
 		"type" : "bar"
 	}
 
-def setup_ageing_columns(filters, range_columns):
-	for i, label in enumerate(["0-{range1}".format(range1=filters["range1"]),
-		"{range1}-{range2}".format(range1=cint(filters["range1"])+ 1, range2=filters["range2"]),
-		"{range2}-{range3}".format(range2=cint(filters["range2"])+ 1, range3=filters["range3"]),
-		"{range3}-{above}".format(range3=cint(filters["range3"])+ 1, above=_("Above"))]):
-			add_column(range_columns, label="Age ("+ label +")", fieldname='range' + str(i+1))
+def setup_ageing_columns(filters: Filters, range_columns: List):
+	ranges = [
+		f"0 - {filters['range1']}",
+		f"{cint(filters['range1']) + 1} - {cint(filters['range2'])}",
+		f"{cint(filters['range2']) + 1} - {cint(filters['range3'])}",
+		f"{cint(filters['range3']) + 1} - {_('Above')}"
+	]
+	for i, label in enumerate(ranges):
+		fieldname = 'range' + str(i+1)
+		add_column(range_columns, label=f"Age ({label})",fieldname=fieldname)
 
-def add_column(range_columns, label, fieldname, fieldtype='Float', width=140):
+def add_column(range_columns: List, label:str, fieldname: str, fieldtype: str = 'Float', width: int = 140):
 	range_columns.append(dict(
 		label=label,
 		fieldname=fieldname,
 		fieldtype=fieldtype,
 		width=width
 	))
+
+
+class FIFOSlots:
+	"Returns FIFO computed slots of inwarded stock as per date."
+
+	def __init__(self, filters: Dict = None , sle: List = None):
+		self.item_details = {}
+		self.transferred_item_details = {}
+		self.serial_no_batch_purchase_details = {}
+		self.filters = filters
+		self.sle = sle
+
+	def generate(self) -> Dict:
+		"""
+			Returns dict of the foll.g structure:
+			Key = Item A / (Item A, Warehouse A)
+			Key: {
+				'details' -> Dict: ** item details **,
+				'fifo_queue' -> List: ** list of lists containing entries/slots for existing stock,
+					consumed/updated and maintained via FIFO. **
+			}
+		"""
+		if self.sle is None:
+			self.sle = self.__get_stock_ledger_entries()
+
+		for d in self.sle:
+			key, fifo_queue, transferred_item_key = self.__init_key_stores(d)
+
+			if d.voucher_type == "Stock Reconciliation":
+				prev_balance_qty = self.item_details[key].get("qty_after_transaction", 0)
+				d.actual_qty = flt(d.qty_after_transaction) - flt(prev_balance_qty)
+
+			serial_nos = get_serial_nos(d.serial_no) if d.serial_no else []
+
+			if d.actual_qty > 0:
+				self.__compute_incoming_stock(d, fifo_queue, transferred_item_key, serial_nos)
+			else:
+				self.__compute_outgoing_stock(d, fifo_queue, transferred_item_key, serial_nos)
+
+			self.__update_balances(d, key)
+
+		return self.item_details
+
+	def __init_key_stores(self, row: Dict) -> Tuple:
+		"Initialise keys and FIFO Queue."
+
+		key = (row.name, row.warehouse) if self.filters.get('show_warehouse_wise_stock') else row.name
+		self.item_details.setdefault(key, {"details": row, "fifo_queue": []})
+		fifo_queue = self.item_details[key]["fifo_queue"]
+
+		transferred_item_key = (row.voucher_no, row.name, row.warehouse)
+		self.transferred_item_details.setdefault(transferred_item_key, [])
+
+		return key, fifo_queue, transferred_item_key
+
+	def __compute_incoming_stock(self, row: Dict, fifo_queue: List, transfer_key: Tuple, serial_nos: List):
+		"Update FIFO Queue on inward stock."
+
+		if self.transferred_item_details.get(transfer_key):
+			# inward/outward from same voucher, item & warehouse
+			slot = self.transferred_item_details[transfer_key].pop(0)
+			fifo_queue.append(slot)
+		else:
+			if not serial_nos:
+				if fifo_queue and flt(fifo_queue[0][0]) < 0:
+					# neutralize negative stock by adding positive stock
+					fifo_queue[0][0] += flt(row.actual_qty)
+					fifo_queue[0][1] = row.posting_date
+				else:
+					fifo_queue.append([flt(row.actual_qty), row.posting_date])
+				return
+
+			for serial_no in serial_nos:
+				if self.serial_no_batch_purchase_details.get(serial_no):
+					fifo_queue.append([serial_no, self.serial_no_batch_purchase_details.get(serial_no)])
+				else:
+					self.serial_no_batch_purchase_details.setdefault(serial_no, row.posting_date)
+					fifo_queue.append([serial_no, row.posting_date])
+
+	def __compute_outgoing_stock(self, row: Dict, fifo_queue: List, transfer_key: Tuple, serial_nos: List):
+		"Update FIFO Queue on outward stock."
+		if serial_nos:
+			fifo_queue[:] = [serial_no for serial_no in fifo_queue if serial_no[0] not in serial_nos]
+			return
+
+		qty_to_pop = abs(row.actual_qty)
+		while qty_to_pop:
+			slot = fifo_queue[0] if fifo_queue else [0, None]
+			if 0 < flt(slot[0]) <= qty_to_pop:
+				# qty to pop >= slot qty
+				# if +ve and not enough or exactly same balance in current slot, consume whole slot
+				qty_to_pop -= flt(slot[0])
+				self.transferred_item_details[transfer_key].append(fifo_queue.pop(0))
+			elif not fifo_queue:
+				# negative stock, no balance but qty yet to consume
+				fifo_queue.append([-(qty_to_pop), row.posting_date])
+				self.transferred_item_details[transfer_key].append([row.actual_qty, row.posting_date])
+				qty_to_pop = 0
+			else:
+				# qty to pop < slot qty, ample balance
+				# consume actual_qty from first slot
+				slot[0] = flt(slot[0]) - qty_to_pop
+				self.transferred_item_details[transfer_key].append([qty_to_pop, slot[1]])
+				qty_to_pop = 0
+
+	def __update_balances(self, row: Dict, key: Union[Tuple, str]):
+		self.item_details[key]["qty_after_transaction"] = row.qty_after_transaction
+
+		if "total_qty" not in self.item_details[key]:
+			self.item_details[key]["total_qty"] = row.actual_qty
+		else:
+			self.item_details[key]["total_qty"] += row.actual_qty
+
+		self.item_details[key]["has_serial_no"] = row.has_serial_no
+
+	def __get_stock_ledger_entries(self) -> List[Dict]:
+		sle = frappe.qb.DocType("Stock Ledger Entry")
+		item = self.__get_item_query() # used as derived table in sle query
+
+		sle_query = (
+			frappe.qb.from_(sle).from_(item)
+			.select(
+				item.name, item.item_name, item.item_group,
+				item.brand, item.description,
+				item.stock_uom, item.has_serial_no,
+				sle.actual_qty, sle.posting_date,
+				sle.voucher_type, sle.voucher_no,
+				sle.serial_no, sle.batch_no,
+				sle.qty_after_transaction, sle.warehouse
+			).where(
+				(sle.item_code == item.name)
+				& (sle.company == self.filters.get("company"))
+				& (sle.posting_date <= self.filters.get("to_date"))
+				& (sle.is_cancelled != 1)
+			)
+		)
+
+		if self.filters.get("warehouse"):
+			sle_query = self.__get_warehouse_conditions(sle, sle_query)
+
+		sle_query = sle_query.orderby(
+			sle.posting_date, sle.posting_time, sle.creation, sle.actual_qty
+		)
+
+		return sle_query.run(as_dict=True)
+
+	def __get_item_query(self) -> str:
+		item_table = frappe.qb.DocType("Item")
+
+		item = frappe.qb.from_("Item").select(
+			"name", "item_name", "description", "stock_uom",
+			"brand", "item_group", "has_serial_no"
+		)
+
+		if self.filters.get("item_code"):
+			item = item.where(item_table.item_code == self.filters.get("item_code"))
+
+		if self.filters.get("brand"):
+			item = item.where(item_table.brand == self.filters.get("brand"))
+
+		return item
+
+	def __get_warehouse_conditions(self, sle, sle_query) -> str:
+		warehouse = frappe.qb.DocType("Warehouse")
+		lft, rgt = frappe.db.get_value(
+			"Warehouse",
+			self.filters.get("warehouse"),
+			['lft', 'rgt']
+		)
+
+		warehouse_results = (
+			frappe.qb.from_(warehouse)
+			.select("name").where(
+				(warehouse.lft >= lft)
+				& (warehouse.rgt <= rgt)
+			).run()
+		)
+		warehouse_results = [x[0] for x in warehouse_results]
+
+		return sle_query.where(sle.warehouse.isin(warehouse_results))
diff --git a/erpnext/stock/report/stock_ageing/stock_ageing_fifo_logic.md b/erpnext/stock/report/stock_ageing/stock_ageing_fifo_logic.md
new file mode 100644
index 0000000..5ffe97f
--- /dev/null
+++ b/erpnext/stock/report/stock_ageing/stock_ageing_fifo_logic.md
@@ -0,0 +1,73 @@
+### Concept of FIFO Slots
+
+Since we need to know age-wise remaining stock, we maintain all the inward entries as slots. So each time stock comes in, a slot is added for the same.
+
+Eg. For Item A:
+----------------------
+Date | Qty | Queue
+----------------------
+1st  | +50 | [[50, 1-12-2021]]
+2nd  | +20 | [[50, 1-12-2021], [20, 2-12-2021]]
+----------------------
+
+Now the queue can tell us the total stock and also how old the stock is.
+Here, the balance qty is 70.
+50 qty is (today-the 1st) days old
+20 qty is (today-the 2nd) days old
+
+### Calculation of FIFO Slots
+
+#### Case 1: Outward from sufficient balance qty
+----------------------
+Date | Qty | Queue
+----------------------
+1st  | +50 | [[50, 1-12-2021]]
+2nd  | -20 | [[30, 1-12-2021]]
+2nd  | +20 | [[30, 1-12-2021], [20, 2-12-2021]]
+
+Here after the first entry, while issuing 20 qty:
+- **since 20 is lesser than the balance**, **qty_to_pop (20)** is simply consumed from first slot (FIFO consumption)
+- Any inward entry after as usual will get its own slot added to the queue
+
+#### Case 2: Outward from sufficient cumulative (slots) balance qty
+----------------------
+Date | Qty | Queue
+----------------------
+1st  | +50 | [[50, 1-12-2021]]
+2nd  | +20 | [[50, 1-12-2021], [20, 2-12-2021]]
+2nd  | -60 | [[10, 2-12-2021]]
+
+- Consumption happens slot wise. First slot 1 is consumed
+- Since **qty_to_pop (60) is greater than slot 1 qty (50)**, the entire slot is consumed and popped
+- Now the queue is [[20, 2-12-2021]], and **qty_to_pop=10** (remaining qty to pop)
+- It then goes ahead to the next slot and consumes 10 from it
+- Now the queue is [[10, 2-12-2021]]
+
+#### Case 3: Outward from insufficient balance qty
+> This case is possible only if **Allow Negative Stock** was enabled at some point/is enabled.
+
+----------------------
+Date | Qty | Queue
+----------------------
+1st  | +50 | [[50, 1-12-2021]]
+2nd  | -60 | [[-10, 1-12-2021]]
+
+- Since **qty_to_pop (60)** is more than the balance in slot 1, the entire slot is consumed and popped
+- Now the queue is **empty**, and **qty_to_pop=10** (remaining qty to pop)
+- Since we still have more to consume, we append the balance since 60 is issued from 50 i.e. -10.
+- We register this negative value, since the stock issue has caused the balance to become negative
+
+Now when stock is inwarded:
+- Instead of adding a slot we check if there are any negative balances.
+- If yes, we keep adding positive stock to it until we make the balance positive.
+- Once the balance is positive, the next inward entry will add a new slot in the queue
+
+Eg:
+----------------------
+Date | Qty | Queue
+----------------------
+1st  | +50 | [[50, 1-12-2021]]
+2nd  | -60 | [[-10, 1-12-2021]]
+3rd  | +5  | [[-5, 3-12-2021]]
+4th  | +10 | [[5, 4-12-2021]]
+4th  | +20 | [[5, 4-12-2021], [20, 4-12-2021]]
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_ageing/test_stock_ageing.py b/erpnext/stock/report/stock_ageing/test_stock_ageing.py
new file mode 100644
index 0000000..949bb7c
--- /dev/null
+++ b/erpnext/stock/report/stock_ageing/test_stock_ageing.py
@@ -0,0 +1,126 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+
+import frappe
+
+from erpnext.stock.report.stock_ageing.stock_ageing import FIFOSlots
+from erpnext.tests.utils import ERPNextTestCase
+
+
+class TestStockAgeing(ERPNextTestCase):
+	def setUp(self) -> None:
+		self.filters = frappe._dict(
+			company="_Test Company",
+			to_date="2021-12-10"
+		)
+
+	def test_normal_inward_outward_queue(self):
+		"Reference: Case 1 in stock_ageing_fifo_logic.md"
+		sle = [
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=30, qty_after_transaction=30,
+				posting_date="2021-12-01", voucher_type="Stock Entry",
+				voucher_no="001",
+				has_serial_no=False, serial_no=None
+			),
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=20, qty_after_transaction=50,
+				posting_date="2021-12-02", voucher_type="Stock Entry",
+				voucher_no="002",
+				has_serial_no=False, serial_no=None
+			),
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=(-10), qty_after_transaction=40,
+				posting_date="2021-12-03", voucher_type="Stock Entry",
+				voucher_no="003",
+				has_serial_no=False, serial_no=None
+			)
+		]
+
+		slots = FIFOSlots(self.filters, sle).generate()
+
+		self.assertTrue(slots["Flask Item"]["fifo_queue"])
+		result = slots["Flask Item"]
+		queue = result["fifo_queue"]
+
+		self.assertEqual(result["qty_after_transaction"], result["total_qty"])
+		self.assertEqual(queue[0][0], 20.0)
+
+	def test_insufficient_balance(self):
+		"Reference: Case 3 in stock_ageing_fifo_logic.md"
+		sle = [
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=(-30), qty_after_transaction=(-30),
+				posting_date="2021-12-01", voucher_type="Stock Entry",
+				voucher_no="001",
+				has_serial_no=False, serial_no=None
+			),
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=20, qty_after_transaction=(-10),
+				posting_date="2021-12-02", voucher_type="Stock Entry",
+				voucher_no="002",
+				has_serial_no=False, serial_no=None
+			),
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=20, qty_after_transaction=10,
+				posting_date="2021-12-03", voucher_type="Stock Entry",
+				voucher_no="003",
+				has_serial_no=False, serial_no=None
+			),
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=10, qty_after_transaction=20,
+				posting_date="2021-12-03", voucher_type="Stock Entry",
+				voucher_no="004",
+				has_serial_no=False, serial_no=None
+			)
+		]
+
+		slots = FIFOSlots(self.filters, sle).generate()
+
+		result = slots["Flask Item"]
+		queue = result["fifo_queue"]
+
+		self.assertEqual(result["qty_after_transaction"], result["total_qty"])
+		self.assertEqual(queue[0][0], 10.0)
+		self.assertEqual(queue[1][0], 10.0)
+
+	def test_stock_reconciliation(self):
+		sle = [
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=30, qty_after_transaction=30,
+				posting_date="2021-12-01", voucher_type="Stock Entry",
+				voucher_no="001",
+				has_serial_no=False, serial_no=None
+			),
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=0, qty_after_transaction=50,
+				posting_date="2021-12-02", voucher_type="Stock Reconciliation",
+				voucher_no="002",
+				has_serial_no=False, serial_no=None
+			),
+			frappe._dict(
+				name="Flask Item",
+				actual_qty=(-10), qty_after_transaction=40,
+				posting_date="2021-12-03", voucher_type="Stock Entry",
+				voucher_no="003",
+				has_serial_no=False, serial_no=None
+			)
+		]
+
+		slots = FIFOSlots(self.filters, sle).generate()
+
+		result = slots["Flask Item"]
+		queue = result["fifo_queue"]
+
+		self.assertEqual(result["qty_after_transaction"], result["total_qty"])
+		self.assertEqual(queue[0][0], 20.0)
+		self.assertEqual(queue[1][0], 20.0)
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 3c7b26b..b4f43a7 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -9,7 +9,7 @@
 from frappe.utils import cint, date_diff, flt, getdate
 
 import erpnext
-from erpnext.stock.report.stock_ageing.stock_ageing import get_average_age, get_fifo_queue
+from erpnext.stock.report.stock_ageing.stock_ageing import FIFOSlots, get_average_age
 from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition
 from erpnext.stock.utils import add_additional_uom_columns, is_reposting_item_valuation_in_progress
 
@@ -33,7 +33,7 @@
 
 	if filters.get('show_stock_ageing_data'):
 		filters['show_warehouse_wise_stock'] = True
-		item_wise_fifo_queue = get_fifo_queue(filters, sle)
+		item_wise_fifo_queue = FIFOSlots(filters, sle).generate()
 
 	# if no stock ledger entry found return
 	if not sle:
diff --git a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py
index 4d1491b..22bdb89 100644
--- a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py
+++ b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py
@@ -9,7 +9,7 @@
 from frappe import _
 from frappe.utils import flt
 
-from erpnext.stock.report.stock_ageing.stock_ageing import get_average_age, get_fifo_queue
+from erpnext.stock.report.stock_ageing.stock_ageing import FIFOSlots, get_average_age
 from erpnext.stock.report.stock_balance.stock_balance import (
 	get_item_details,
 	get_item_warehouse_map,
@@ -33,7 +33,7 @@
 	item_map = get_item_details(items, sle, filters)
 	iwb_map = get_item_warehouse_map(filters, sle)
 	warehouse_list = get_warehouse_list(filters)
-	item_ageing = get_fifo_queue(filters)
+	item_ageing = FIFOSlots(filters).generate()
 	data = []
 	item_balance = {}
 	item_value = {}
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 3b1ae3b..3c70b41 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -86,8 +86,8 @@
 
 	from erpnext.stock.stock_ledger import get_previous_sle
 
-	if not posting_date: posting_date = nowdate()
-	if not posting_time: posting_time = nowtime()
+	if posting_date is None: posting_date = nowdate()
+	if posting_time is None: posting_time = nowtime()
 
 	args = {
 		"item_code": item_code,
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index d5e5b78..e211e24 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -236,7 +236,7 @@
 	return False
 
 def calculate_first_response_time(issue, first_responded_on):
-	issue_creation_date = issue.creation
+	issue_creation_date = issue.service_level_agreement_creation or issue.creation
 	issue_creation_time = get_time_in_seconds(issue_creation_date)
 	first_responded_on_in_seconds = get_time_in_seconds(first_responded_on)
 	support_hours = frappe.get_cached_doc("Service Level Agreement", issue.service_level_agreement).support_and_resolution
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
index b3348f1..ea617fd 100644
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
+++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
@@ -853,7 +853,7 @@
 @frappe.whitelist()
 def get_sla_doctypes():
 	doctypes = []
-	data = frappe.get_list('Service Level Agreement',
+	data = frappe.get_all('Service Level Agreement',
 		{'enabled': 1},
 		['document_type'],
 		distinct=1
diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py
index fbf2594..bc9f04e 100644
--- a/erpnext/tests/utils.py
+++ b/erpnext/tests/utils.py
@@ -125,17 +125,23 @@
 	if default_filters is None:
 		default_filters = {}
 
+	test_filters = []
 	report_execute_fn = frappe.get_attr(get_report_module_dotted_path(module, report_name) + ".execute")
 	report_filters = frappe._dict(default_filters).copy().update(filters)
 
-	report_data = report_execute_fn(report_filters)
+	test_filters.append(report_filters)
 
 	if optional_filters:
 		for key, value in optional_filters.items():
-			filter_with_optional_param = report_filters.copy().update({key: value})
-			report_execute_fn(filter_with_optional_param)
+			test_filters.append(report_filters.copy().update({key: value}))
 
-	return report_data
+	for test_filter in test_filters:
+		try:
+			report_execute_fn(test_filter)
+		except Exception:
+			print(f"Report failed to execute with filters: {test_filter}")
+			raise
+
 
 
 def timeout(seconds=30, error_message="Test timed out."):
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index d46ffb5..0aca1a0 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -242,7 +242,7 @@
 Appointment Confirmation,Terminbestätigung,
 Appointment Duration (mins),Termindauer (Min.),
 Appointment Type,Termin-Typ,
-Appointment {0} and Sales Invoice {1} cancelled,Termin {0} und Verkaufsrechnung {1} wurden storniert,
+Appointment {0} and Sales Invoice {1} cancelled,Termin {0} und Ausgangsrechnung {1} wurden storniert,
 Appointments and Encounters,Termine und Begegnungen,
 Appointments and Patient Encounters,Termine und Patienten-Begegnungen,
 Appraisal {0} created for Employee {1} in the given date range,Bewertung {0} für Mitarbeiter {1} im angegebenen Datumsbereich erstellt,
@@ -427,7 +427,7 @@
 Buying Rate,Kaufrate,
 "Buying must be checked, if Applicable For is selected as {0}","Einkauf muss ausgewählt sein, wenn ""Anwenden auf"" auf {0} gesetzt wurde",
 By {0},Von {0},
-Bypass credit check at Sales Order ,Kreditprüfung im Kundenauftrag umgehen,
+Bypass credit check at Sales Order ,Kreditprüfung im Auftrag umgehen,
 C-Form records,Kontakt-Formular Datensätze,
 C-form is not applicable for Invoice: {0},Kontaktformular nicht anwendbar auf  Rechnung: {0},
 CEO,CEO,
@@ -474,11 +474,11 @@
 "Cannot delete Serial No {0}, as it is used in stock transactions","Die Seriennummer {0} kann nicht gelöscht werden, da sie in Lagertransaktionen verwendet wird",
 Cannot enroll more than {0} students for this student group.,Kann nicht mehr als {0} Studenten für diese Studentengruppe einschreiben.,
 Cannot find active Leave Period,Aktive Abwesenheitszeit kann nicht gefunden werden,
-Cannot produce more Item {0} than Sales Order quantity {1},"Es können nicht mehr Artikel {0} produziert werden, als die über Kundenaufträge bestellte Stückzahl {1}",
+Cannot produce more Item {0} than Sales Order quantity {1},"Es können nicht mehr Artikel {0} produziert werden, als die über den Auftrag bestellte Stückzahl {1}",
 Cannot promote Employee with status Left,Mitarbeiter mit Status &quot;Links&quot; kann nicht gefördert werden,
 Cannot refer row number greater than or equal to current row number for this Charge type,"Für diese Berechnungsart kann keine Zeilennummern zugeschrieben werden, die größer oder gleich der aktuellen Zeilennummer ist",
 Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row,"Die Berechnungsart kann für die erste Zeile nicht auf ""bezogen auf Menge der vorhergenden Zeile"" oder auf ""bezogen auf Gesamtmenge der vorhergenden Zeile"" gesetzt werden",
-Cannot set as Lost as Sales Order is made.,"Kann nicht als verloren gekennzeichnet werden, da ein Kundenauftrag dazu existiert.",
+Cannot set as Lost as Sales Order is made.,"Kann nicht als verloren gekennzeichnet werden, da ein Auftrag dazu existiert.",
 Cannot set authorization on basis of Discount for {0},Genehmigung kann nicht auf der Basis des Rabattes für {0} festgelegt werden,
 Cannot set multiple Item Defaults for a company.,Es können nicht mehrere Artikelstandards für ein Unternehmen festgelegt werden.,
 Cannot set quantity less than delivered quantity,Menge kann nicht kleiner als gelieferte Menge sein,
@@ -663,7 +663,7 @@
 Create Maintenance Visit,Wartungsbesuch anlegen,
 Create Material Request,Materialanforderung erstellen,
 Create Multiple,Erstellen Sie mehrere,
-Create Opening Sales and Purchase Invoices,Erstellen Sie Eingangsverkaufs- und Einkaufsrechnungen,
+Create Opening Sales and Purchase Invoices,Erstellen Sie die eröffnungs Ein- und Ausgangsrechnungen,
 Create Payment Entries,Zahlungseinträge erstellen,
 Create Payment Entry,Zahlungseintrag erstellen,
 Create Print Format,Druckformat erstellen,
@@ -672,9 +672,9 @@
 Create Quotation,Angebot erstellen,
 Create Salary Slip,Gehaltsabrechnung erstellen,
 Create Salary Slips,Gehaltszettel erstellen,
-Create Sales Invoice,Verkaufsrechnung erstellen,
-Create Sales Order,Kundenauftrag anlegen,
-Create Sales Orders to help you plan your work and deliver on-time,"Erstellen Sie Kundenaufträge, um Ihre Arbeit zu planen und pünktlich zu liefern",
+Create Sales Invoice,Ausgangsrechnung erstellen,
+Create Sales Order,Auftrag anlegen,
+Create Sales Orders to help you plan your work and deliver on-time,"Erstellen Sie Aufträge, um Ihre Arbeit zu planen und pünktlich zu liefern",
 Create Sample Retention Stock Entry,Legen Sie einen Muster-Retention-Stock-Eintrag an,
 Create Student,Schüler erstellen,
 Create Student Batch,Studentenstapel erstellen,
@@ -808,7 +808,7 @@
 Delivery Note,Lieferschein,
 Delivery Note {0} is not submitted,Lieferschein {0} ist nicht gebucht,
 Delivery Note {0} must not be submitted,Lieferschein {0} darf nicht gebucht sein,
-Delivery Notes {0} must be cancelled before cancelling this Sales Order,Lieferscheine {0} müssen vor Löschung dieser Kundenaufträge storniert werden,
+Delivery Notes {0} must be cancelled before cancelling this Sales Order,Lieferscheine {0} müssen vor Löschung dieser Aufträge storniert werden,
 Delivery Notes {0} updated,Lieferhinweise {0} aktualisiert,
 Delivery Status,Lieferstatus,
 Delivery Trip,Liefertrip,
@@ -981,7 +981,7 @@
 Executive Search,Direktsuche,
 Expand All,Alle ausklappen,
 Expected Delivery Date,Geplanter Liefertermin,
-Expected Delivery Date should be after Sales Order Date,Voraussichtlicher Liefertermin sollte nach Kundenauftragsdatum erfolgen,
+Expected Delivery Date should be after Sales Order Date,Voraussichtlicher Liefertermin sollte nach Auftragsdatum erfolgen,
 Expected End Date,Voraussichtliches Enddatum,
 Expected Hrs,Erwartete Stunden,
 Expected Start Date,Voraussichtliches Startdatum,
@@ -1235,7 +1235,7 @@
 Identifying Decision Makers,Entscheidungsträger identifizieren,
 "If Auto Opt In is checked, then the customers will be automatically linked with the concerned Loyalty Program (on save)","Wenn Automatische Anmeldung aktiviert ist, werden die Kunden automatisch mit dem betreffenden Treueprogramm verknüpft (beim Speichern)",
 "If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict.","Wenn mehrere Preisregeln weiterhin gleichrangig gelten, werden die Benutzer aufgefordert, Vorrangregelungen manuell zu erstellen, um den Konflikt zu lösen.",
-"If selected Pricing Rule is made for 'Rate', it will overwrite Price List. Pricing Rule rate is the final rate, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field.","Wenn die ausgewählte Preisregel für &quot;Rate&quot; festgelegt wurde, wird die Preisliste überschrieben. Der Preisregelpreis ist der Endpreis, daher sollte kein weiterer Rabatt angewendet werden. Daher wird es in Transaktionen wie Kundenauftrag, Bestellung usw. im Feld &#39;Preis&#39; und nicht im Feld &#39;Preislistenpreis&#39; abgerufen.",
+"If selected Pricing Rule is made for 'Rate', it will overwrite Price List. Pricing Rule rate is the final rate, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field.","Wenn die ausgewählte Preisregel für &quot;Rate&quot; festgelegt wurde, wird die Preisliste überschrieben. Der Preisregelpreis ist der Endpreis, daher sollte kein weiterer Rabatt angewendet werden. Daher wird es in Transaktionen wie Auftrag, Bestellung usw. im Feld &#39;Preis&#39; und nicht im Feld &#39;Preislistenpreis&#39; abgerufen.",
 "If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions.","Wenn zwei oder mehrere Preisregeln basierend auf den oben genannten Bedingungen gefunden werden, wird eine Vorrangregelung angewandt. Priorität ist eine Zahl zwischen 0 und 20, wobei der Standardwert Null (leer) ist. Die höhere Zahl hat  Vorrang, wenn es mehrere Preisregeln zu den gleichen Bedingungen gibt.",
 "If unlimited expiry for the Loyalty Points, keep the Expiry Duration empty or 0.","Wenn die Treuepunkte unbegrenzt ablaufen, lassen Sie die Ablaufdauer leer oder 0.",
 "If you have any questions, please get back to us.","Wenn Sie Fragen haben, wenden Sie sich bitte an uns.",
@@ -1386,7 +1386,7 @@
 Item {0} must be a non-stock item,Artikel {0} darf kein Lagerartikel sein,
 Item {0} must be a stock Item,Artikel {0} muss ein Lagerartikel sein,
 Item {0} not found,Artikel {0} nicht gefunden,
-Item {0} not found in 'Raw Materials Supplied' table in Purchase Order {1},"Artikel {0} in Tabelle ""Rohmaterialien geliefert"" des Lieferantenauftrags {1} nicht gefunden",
+Item {0} not found in 'Raw Materials Supplied' table in Purchase Order {1},"Artikel {0} in Tabelle ""Rohmaterialien geliefert"" der Bestellung {1} nicht gefunden",
 Item {0}: Ordered qty {1} cannot be less than minimum order qty {2} (defined in Item).,Artikel {0}: Bestellmenge {1} kann nicht weniger als Mindestbestellmenge {2} (im Artikel definiert) sein.,
 Item: {0} does not exist in the system,Artikel: {0} ist nicht im System vorhanden,
 Items,Artikel,
@@ -1489,7 +1489,7 @@
 Loyalty Amount,Loyalitätsbetrag,
 Loyalty Point Entry,Loyalitätspunkteintrag,
 Loyalty Points,Treuepunkte,
-"Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned.","Treuepunkte werden aus dem ausgegebenen Betrag (über die Verkaufsrechnung) berechnet, basierend auf dem genannten Sammelfaktor.",
+"Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned.","Treuepunkte werden aus dem ausgegebenen Betrag (über die Ausgangsrechnung) berechnet, basierend auf dem genannten Sammelfaktor.",
 Loyalty Points: {0},Treuepunkte: {0},
 Loyalty Program,Treueprogramm,
 Main,Haupt,
@@ -1499,11 +1499,11 @@
 Maintenance Schedule,Wartungsplan,
 Maintenance Schedule is not generated for all the items. Please click on 'Generate Schedule',"Wartungsplan wird nicht für alle Elemente erzeugt. Bitte klicken Sie auf ""Zeitplan generieren""",
 Maintenance Schedule {0} exists against {1},Wartungsplan {0} existiert gegen {1},
-Maintenance Schedule {0} must be cancelled before cancelling this Sales Order,Wartungsplan {0} muss vor Stornierung dieses Kundenauftrages aufgehoben werden,
+Maintenance Schedule {0} must be cancelled before cancelling this Sales Order,Wartungsplan {0} muss vor Stornierung dieses Auftrags aufgehoben werden,
 Maintenance Status has to be Cancelled or Completed to Submit,Der Wartungsstatus muss abgebrochen oder zum Senden abgeschlossen werden,
 Maintenance User,Nutzer Instandhaltung,
 Maintenance Visit,Wartungsbesuch,
-Maintenance Visit {0} must be cancelled before cancelling this Sales Order,Wartungsbesuch {0} muss vor Stornierung dieses Kundenauftrages abgebrochen werden,
+Maintenance Visit {0} must be cancelled before cancelling this Sales Order,Wartungsbesuch {0} muss vor Stornierung dieses Auftrags abgebrochen werden,
 Maintenance start date can not be before delivery date for Serial No {0},Startdatum der Wartung kann nicht vor dem Liefertermin für Seriennummer {0} liegen,
 Make,Erstellen,
 Make Payment,Zahlung ausführen,
@@ -1549,8 +1549,8 @@
 Material Request Date,Material Auftragsdatum,
 Material Request No,Materialanfragenr.,
 "Material Request not created, as quantity for Raw Materials already available.","Materialanforderung nicht angelegt, da Menge für Rohstoffe bereits vorhanden.",
-Material Request of maximum {0} can be made for Item {1} against Sales Order {2},Materialanfrage von maximal {0} kann für Artikel {1} zum Kundenauftrag {2} gemacht werden,
-Material Request to Purchase Order,Von der Materialanfrage zum Lieferantenauftrag,
+Material Request of maximum {0} can be made for Item {1} against Sales Order {2},Materialanfrage von maximal {0} kann für Artikel {1} zum Auftrag {2} gemacht werden,
+Material Request to Purchase Order,Von der Materialanfrage zur Bestellung,
 Material Request {0} is cancelled or stopped,Materialanfrage {0} wird storniert oder gestoppt,
 Material Request {0} submitted.,Materialanfrage {0} gesendet.,
 Material Transfer,Materialübertrag,
@@ -2224,7 +2224,7 @@
 Purchase,Einkauf,
 Purchase Amount,Gesamtbetrag des Einkaufs,
 Purchase Date,Kaufdatum,
-Purchase Invoice,Einkaufsrechnung,
+Purchase Invoice,Eingangsrechnung,
 Purchase Invoice {0} is already submitted,Eingangsrechnung {0} wurde bereits übertragen,
 Purchase Manager,Einkaufsleiter,
 Purchase Master Manager,Einkaufsstammdaten-Manager,
@@ -2233,11 +2233,11 @@
 Purchase Order Amount(Company Currency),Bestellbetrag (Firmenwährung),
 Purchase Order Date,Bestelldatum,
 Purchase Order Items not received on time,Bestellpositionen nicht rechtzeitig erhalten,
-Purchase Order number required for Item {0},Lieferantenauftragsnummer ist für den Artikel {0} erforderlich,
-Purchase Order to Payment,Vom Lieferantenauftrag zur Zahlung,
-Purchase Order {0} is not submitted,Lieferantenauftrag {0} wurde nicht übertragen,
+Purchase Order number required for Item {0},Bestellnummer ist für den Artikel {0} erforderlich,
+Purchase Order to Payment,Von der Bestellung zur Zahlung,
+Purchase Order {0} is not submitted,Bestellung {0} wurde nicht übertragen,
 Purchase Orders are not allowed for {0} due to a scorecard standing of {1}.,Kaufaufträge sind für {0} wegen einer Scorecard von {1} nicht erlaubt.,
-Purchase Orders given to Suppliers.,An Lieferanten erteilte Lieferantenaufträge,
+Purchase Orders given to Suppliers.,An Lieferanten erteilte Bestellungen,
 Purchase Price List,Einkaufspreisliste,
 Purchase Receipt,Kaufbeleg,
 Purchase Receipt {0} is not submitted,Kaufbeleg {0} wurde nicht übertragen,
@@ -2440,7 +2440,7 @@
 Row #{0}: Expected Delivery Date cannot be before Purchase Order Date,Row # {0}: Voraussichtlicher Liefertermin kann nicht vor Bestelldatum sein,
 Row #{0}: Item added,Zeile # {0}: Element hinzugefügt,
 Row #{0}: Journal Entry {1} does not have account {2} or already matched against another voucher,Row # {0}: Journal Entry {1} nicht Konto {2} oder bereits abgestimmt gegen einen anderen Gutschein,
-Row #{0}: Not allowed to change Supplier as Purchase Order already exists,"Zeile #{0}: Es ist nicht erlaubt den Lieferanten zu wechseln, da bereits ein Lieferantenauftrag vorhanden ist",
+Row #{0}: Not allowed to change Supplier as Purchase Order already exists,"Zeile #{0}: Es ist nicht erlaubt den Lieferanten zu wechseln, da bereits eine Bestellung vorhanden ist",
 Row #{0}: Please set reorder quantity,Zeile #{0}: Bitte Nachbestellmenge angeben,
 Row #{0}: Please specify Serial No for Item {1},Zeile #{0}: Bitte Seriennummer für Artikel {1} angeben,
 Row #{0}: Qty increased by 1,Zeile # {0}: Menge um 1 erhöht,
@@ -2483,7 +2483,7 @@
 Row {0}: Invalid reference {1},Zeile {0}: Ungültige Referenz {1},
 Row {0}: Party / Account does not match with {1} / {2} in {3} {4},Zeile {0}: Gruppe / Konto stimmt nicht mit {1} / {2} in {3} {4} überein,
 Row {0}: Party Type and Party is required for Receivable / Payable account {1},Zeile {0}: Gruppen-Typ und Gruppe sind für Forderungen-/Verbindlichkeiten-Konto {1} zwingend erforderlich,
-Row {0}: Payment against Sales/Purchase Order should always be marked as advance,"Zeile {0}: ""Zahlung zu Kunden-/Lieferantenauftrag"" sollte immer als ""Vorkasse"" eingestellt werden",
+Row {0}: Payment against Sales/Purchase Order should always be marked as advance,"Zeile {0}: ""Zahlung zu Auftrag bzw. Bestellung"" sollte immer als ""Vorkasse"" eingestellt werden",
 Row {0}: Please check 'Is Advance' against Account {1} if this is an advance entry.,"Zeile {0}: Wenn es sich um eine Vorkasse-Buchung handelt, bitte ""Ist Vorkasse"" zu Konto {1} anklicken, .",
 Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Zeile {0}: Bitte setzen Sie den Steuerbefreiungsgrund in den Umsatzsteuern und -gebühren,
 Row {0}: Please set the Mode of Payment in Payment Schedule,Zeile {0}: Bitte legen Sie die Zahlungsart im Zahlungsplan fest,
@@ -2518,19 +2518,19 @@
 Sales Account,Verkaufskonto,
 Sales Expenses,Vertriebskosten,
 Sales Funnel,Verkaufstrichter,
-Sales Invoice,Verkaufsrechnung,
+Sales Invoice,Ausgangsrechnung,
 Sales Invoice {0} has already been submitted,Ausgangsrechnung {0} wurde bereits übertragen,
-Sales Invoice {0} must be cancelled before cancelling this Sales Order,Ausgangsrechnung {0} muss vor Stornierung dieses Kundenauftrags abgebrochen werden,
+Sales Invoice {0} must be cancelled before cancelling this Sales Order,Ausgangsrechnung {0} muss vor Stornierung dieses Auftrags abgebrochen werden,
 Sales Manager,Vertriebsleiter,
 Sales Master Manager,Hauptvertriebsleiter,
-Sales Order,Auftragsbestätigung,
-Sales Order Item,Kundenauftrags-Artikel,
-Sales Order required for Item {0},Kundenauftrag für den Artikel {0} erforderlich,
-Sales Order to Payment,Vom Kundenauftrag zum Zahlungseinang,
-Sales Order {0} is not submitted,Kundenauftrag {0} wurde nicht übertragen,
-Sales Order {0} is not valid,Kundenauftrag {0} ist nicht gültig,
-Sales Order {0} is {1},Kundenauftrag {0} ist {1},
-Sales Orders,Kundenaufträge,
+Sales Order,Auftrag,
+Sales Order Item,Auftrags-Artikel,
+Sales Order required for Item {0},Auftrag für den Artikel {0} erforderlich,
+Sales Order to Payment,Vom Auftrag zum Zahlungseinang,
+Sales Order {0} is not submitted,Auftrag {0} wurde nicht übertragen,
+Sales Order {0} is not valid,Auftrag {0} ist nicht gültig,
+Sales Order {0} is {1},Auftrag {0} ist {1},
+Sales Orders,Aufträge,
 Sales Partner,Vertriebspartner,
 Sales Pipeline,Vertriebspipeline,
 Sales Price List,Verkaufspreisliste,
@@ -2541,7 +2541,7 @@
 Sales User,Nutzer Vertrieb,
 Sales and Returns,Verkauf und Retouren,
 Sales campaigns.,Vertriebskampagnen,
-Sales orders are not available for production,Kundenaufträge sind für die Produktion nicht verfügbar,
+Sales orders are not available for production,Aufträge sind für die Produktion nicht verfügbar,
 Salutation,Anrede,
 Same Company is entered more than once,Das selbe Unternehmen wurde mehrfach angegeben,
 Same item cannot be entered multiple times.,Das gleiche Einzelteil kann nicht mehrfach eingegeben werden.,
@@ -2650,7 +2650,7 @@
 Serial No {0} not in stock,Seriennummer {0} ist nicht auf Lager,
 Serial No {0} quantity {1} cannot be a fraction,Seriennummer {0} mit Menge {1} kann nicht eine Teilmenge sein,
 Serial Nos Required for Serialized Item {0},Seriennummern sind erforderlich für den Artikel mit Seriennummer {0},
-Serial Number: {0} is already referenced in Sales Invoice: {1},Seriennummer: {0} wird bereits in der Verkaufsrechnung referenziert: {1},
+Serial Number: {0} is already referenced in Sales Invoice: {1},Seriennummer: {0} wird bereits in der Ausgangsrechnung referenziert: {1},
 Serial Numbers,Seriennummer,
 Serial Numbers in row {0} does not match with Delivery Note,Seriennummern in Zeile {0} stimmt nicht mit der Lieferschein überein,
 Serial no {0} has been already returned,Seriennr. {0} wurde bereits zurückgegeben,
@@ -3278,7 +3278,7 @@
 Warning: Invalid attachment {0},Warnung: Ungültige Anlage {0},
 Warning: Leave application contains following block dates,Achtung: Die Urlaubsverwaltung enthält die folgenden gesperrten Daten,
 Warning: Material Requested Qty is less than Minimum Order Qty,Achtung : Materialanfragemenge ist geringer als die Mindestbestellmenge,
-Warning: Sales Order {0} already exists against Customer's Purchase Order {1},Warnung: Kundenauftrag {0} zu Kunden-Bestellung bereits vorhanden {1},
+Warning: Sales Order {0} already exists against Customer's Purchase Order {1},Warnung: Auftrag {0} zu Kunden-Bestellung bereits vorhanden {1},
 Warning: System will not check overbilling since amount for Item {0} in {1} is zero,"Achtung: Das System erkennt keine überhöhten Rechnungen, da der Betrag für Artikel {0} in {1} gleich Null ist",
 Warranty,Garantie,
 Warranty Claim,Garantieanspruch,
@@ -3308,7 +3308,7 @@
 Work Order cannot be raised against a Item Template,Arbeitsauftrag kann nicht gegen eine Artikelbeschreibungsvorlage ausgelöst werden,
 Work Order has been {0},Arbeitsauftrag wurde {0},
 Work Order not created,Arbeitsauftrag wurde nicht erstellt,
-Work Order {0} must be cancelled before cancelling this Sales Order,Der Arbeitsauftrag {0} muss vor dem Stornieren dieses Kundenauftrags storniert werden,
+Work Order {0} must be cancelled before cancelling this Sales Order,Der Arbeitsauftrag {0} muss vor dem Stornieren dieses Auftrags storniert werden,
 Work Order {0} must be submitted,Arbeitsauftrag {0} muss eingereicht werden,
 Work Orders Created: {0},Arbeitsaufträge erstellt: {0},
 Work Summary for {0},Arbeitszusammenfassung für {0},
@@ -3382,9 +3382,9 @@
 {0} Student Groups created.,{0} Schülergruppen erstellt.,
 {0} Students have been enrolled,{0} Studenten wurden angemeldet,
 {0} against Bill {1} dated {2},{0} zu Rechnung {1} vom {2},
-{0} against Purchase Order {1},{0} zu Lieferantenauftrag {1},
-{0} against Sales Invoice {1},{0} zu Verkaufsrechnung {1},
-{0} against Sales Order {1},{0} zu Kundenauftrag{1},
+{0} against Purchase Order {1},{0} zu Bestellung {1},
+{0} against Sales Invoice {1},{0} zu Ausgangsrechnung {1},
+{0} against Sales Order {1},{0} zu Auftrag{1},
 {0} already allocated for Employee {1} for period {2} to {3},{0} bereits an Mitarbeiter {1} zugeteilt für den Zeitraum {2} bis {3},
 {0} applicable after {1} working days,{0} gilt nach {1} Werktagen,
 {0} asset cannot be transferred,{0} Anlagevermögen kann nicht übertragen werden,
@@ -3833,7 +3833,7 @@
 Log Type is required for check-ins falling in the shift: {0}.,Der Protokolltyp ist für Eincheckvorgänge in der Schicht erforderlich: {0}.,
 Looks like someone sent you to an incomplete URL. Please ask them to look into it.,"Sieht aus wie jemand, den Sie zu einer unvollständigen URL gesendet. Bitte fragen Sie sie, sich in sie.",
 Make Journal Entry,Buchungssatz erstellen,
-Make Purchase Invoice,Einkaufsrechnung erstellen,
+Make Purchase Invoice,Eingangsrechnung erstellen,
 Manufactured,Hergestellt,
 Mark Work From Home,Markieren Sie Work From Home,
 Master,Vorlage,
@@ -4302,7 +4302,7 @@
 Assets not created for {0}. You will have to create asset manually.,Assets nicht für {0} erstellt. Sie müssen das Asset manuell erstellen.,
 {0} {1} has accounting entries in currency {2} for company {3}. Please select a receivable or payable account with currency {2}.,{0} {1} hat Buchhaltungseinträge in Währung {2} für Firma {3}. Bitte wählen Sie ein Debitoren- oder Kreditorenkonto mit der Währung {2} aus.,
 Invalid Account,Ungültiger Account,
-Purchase Order Required,Lieferantenauftrag erforderlich,
+Purchase Order Required,Bestellung erforderlich,
 Purchase Receipt Required,Kaufbeleg notwendig,
 Account Missing,Konto fehlt,
 Requested,Angefordert,
@@ -4889,7 +4889,7 @@
 Subscription Plans,Abonnementpläne,
 SWIFT Number,SWIFT-Nummer,
 Recipient Message And Payment Details,Empfänger der Nachricht und Zahlungsdetails,
-Make Sales Invoice,Verkaufsrechnung erstellen,
+Make Sales Invoice,Ausgangsrechnung erstellen,
 Mute Email,Mute Email,
 payment_url,payment_url,
 Payment Gateway Details,Payment Gateway-Details,
@@ -4988,7 +4988,7 @@
 Accounting Dimensions ,Buchhaltung Dimensionen,
 Supplier Invoice Details,Lieferant Rechnungsdetails,
 Supplier Invoice Date,Lieferantenrechnungsdatum,
-Return Against Purchase Invoice,Zurück zur Einkaufsrechnung,
+Return Against Purchase Invoice,Zurück zur Eingangsrechnung,
 Select Supplier Address,Lieferantenadresse auswählen,
 Contact Person,Kontaktperson,
 Select Shipping Address,Lieferadresse auswählen,
@@ -5081,7 +5081,7 @@
 Allow Zero Valuation Rate,Nullbewertung zulassen,
 Item Tax Rate,Artikelsteuersatz,
 Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges,Die Tabelle Steuerdetails wird aus dem Artikelstamm als Zeichenfolge entnommen und in diesem Feld gespeichert. Wird verwendet für Steuern und Abgaben,
-Purchase Order Item,Lieferantenauftrags-Artikel,
+Purchase Order Item,Bestellartikel,
 Purchase Receipt Detail,Kaufbelegdetail,
 Item Weight Details,Artikel Gewicht Details,
 Weight Per Unit,Gewicht pro Einheit,
@@ -5110,10 +5110,10 @@
 Offline POS Name,Offline-Verkaufsstellen-Name,
 Is Return (Credit Note),ist Rücklieferung (Gutschrift),
 Return Against Sales Invoice,Zurück zur Kundenrechnung,
-Update Billed Amount in Sales Order,Aktualisierung des Rechnungsbetrags im Kundenauftrag,
-Customer PO Details,Kundenauftragsdetails,
-Customer's Purchase Order,Kundenauftrag,
-Customer's Purchase Order Date,Kundenauftragsdatum,
+Update Billed Amount in Sales Order,Aktualisierung des Rechnungsbetrags im Auftrag,
+Customer PO Details,Auftragsdetails,
+Customer's Purchase Order,Bestellung des Kunden,
+Customer's Purchase Order Date,Bestelldatum des Kunden,
 Customer Address,Kundenadresse,
 Shipping Address Name,Lieferadresse Bezeichnung,
 Company Address Name,Bezeichnung der Anschrift des Unternehmens,
@@ -5483,7 +5483,7 @@
 Supply Raw Materials,Rohmaterial bereitstellen,
 Purchase Order Pricing Rule,Preisregel für Bestellungen,
 Set Reserve Warehouse,Legen Sie das Reservelager fest,
-In Words will be visible once you save the Purchase Order.,"""In Worten"" wird sichtbar, sobald Sie den Lieferantenauftrag speichern.",
+In Words will be visible once you save the Purchase Order.,"""In Worten"" wird sichtbar, sobald Sie die Bestellung speichern.",
 Advance Paid,Angezahlt,
 Tracking,Verfolgung,
 % Billed,% verrechnet,
@@ -5500,7 +5500,7 @@
 Blanket Order,Blankoauftrag,
 Blanket Order Rate,Pauschale Bestellrate,
 Returned Qty,Zurückgegebene Menge,
-Purchase Order Item Supplied,Lieferantenauftrags-Artikel geliefert,
+Purchase Order Item Supplied,Bestellartikel geliefert,
 BOM Detail No,Stückliste Detailnr.,
 Stock Uom,Lagermaßeinheit,
 Raw Material Item Code,Rohmaterial-Artikelnummer,
@@ -6011,7 +6011,7 @@
 Sync Products,Produkte synchronisieren,
 Always sync your products from Amazon MWS before synching the Orders details,"Synchronisieren Sie Ihre Produkte immer mit Amazon MWS, bevor Sie die Bestelldetails synchronisieren",
 Sync Orders,Bestellungen synchronisieren,
-Click this button to pull your Sales Order data from Amazon MWS.,"Klicken Sie auf diese Schaltfläche, um Ihre Kundenauftragsdaten von Amazon MWS abzurufen.",
+Click this button to pull your Sales Order data from Amazon MWS.,"Klicken Sie auf diese Schaltfläche, um Ihre Auftragsdaten von Amazon MWS abzurufen.",
 Enable Scheduled Sync,Aktivieren Sie die geplante Synchronisierung,
 Check this to enable a scheduled Daily synchronization routine via scheduler,"Aktivieren Sie diese Option, um eine geplante tägliche Synchronisierungsroutine über den Scheduler zu aktivieren",
 Max Retry Limit,Max. Wiederholungslimit,
@@ -6060,14 +6060,14 @@
 Default Customer,Standardkunde,
 Customer Group will set to selected group while syncing customers from Shopify,Die Kundengruppe wird bei der Synchronisierung von Kunden von Shopify auf die ausgewählte Gruppe festgelegt,
 For Company,Für Unternehmen,
-Cash Account will used for Sales Invoice creation,Cash Account wird für die Erstellung von Verkaufsrechnungen verwendet,
+Cash Account will used for Sales Invoice creation,Cash Account wird für die Erstellung von Ausgangsrechnungen verwendet,
 Update Price from Shopify To ERPNext Price List,Preis von Shopify auf ERPNext Preisliste aktualisieren,
-Default Warehouse to to create Sales Order and Delivery Note,Standard Warehouse zum Erstellen von Kundenauftrag und Lieferschein,
-Sales Order Series,Kundenauftragsreihen,
+Default Warehouse to to create Sales Order and Delivery Note,Standard Lager zum Erstellen von Auftrag und Lieferschein,
+Sales Order Series,Auftragsnummernkreis,
 Import Delivery Notes from Shopify on Shipment,Lieferscheine von Shopify bei Versand importieren,
 Delivery Note Series,Lieferschein-Serie,
-Import Sales Invoice from Shopify if Payment is marked,"Verkaufsrechnung aus Shopify importieren, wenn Zahlung markiert ist",
-Sales Invoice Series,Verkaufsrechnung Serie,
+Import Sales Invoice from Shopify if Payment is marked,"Ausgangsrechnung aus Shopify importieren, wenn Zahlung markiert ist",
+Sales Invoice Series,Nummernkreis Ausgangsrechnung,
 Shopify Tax Account,Steuerkonto erstellen,
 Shopify Tax/Shipping Title,Steuern / Versand Titel,
 ERPNext Account,ERPNext Konto,
@@ -6106,13 +6106,13 @@
 Tax Account,Steuerkonto,
 Freight and Forwarding Account,Fracht- und Speditionskonto,
 Creation User,Erstellungsbenutzer,
-"The user that will be used to create Customers, Items and Sales Orders. This user should have the relevant permissions.","Der Benutzer, der zum Erstellen von Kunden, Artikeln und Kundenaufträgen verwendet wird. Dieser Benutzer sollte über die entsprechenden Berechtigungen verfügen.",
-"This warehouse will be used to create Sales Orders. The fallback warehouse is ""Stores"".",Dieses Lager wird zum Erstellen von Kundenaufträgen verwendet. Das Fallback-Lager ist &quot;Stores&quot;.,
+"The user that will be used to create Customers, Items and Sales Orders. This user should have the relevant permissions.","Der Benutzer, der zum Erstellen von Kunden, Artikeln und Aufträgen verwendet wird. Dieser Benutzer sollte über die entsprechenden Berechtigungen verfügen.",
+"This warehouse will be used to create Sales Orders. The fallback warehouse is ""Stores"".",Dieses Lager wird zum Erstellen von Aufträgen verwendet. Das Fallback-Lager ist &quot;Stores&quot;.,
 "The fallback series is ""SO-WOO-"".",Die Fallback-Serie heißt &quot;SO-WOO-&quot;.,
-This company will be used to create Sales Orders.,Diese Firma wird zum Erstellen von Kundenaufträgen verwendet.,
+This company will be used to create Sales Orders.,Diese Firma wird zum Erstellen von Aufträgen verwendet.,
 Delivery After (Days),Lieferung nach (Tage),
-This is the default offset (days) for the Delivery Date in Sales Orders. The fallback offset is 7 days from the order placement date.,Dies ist der Standardversatz (Tage) für das Lieferdatum in Kundenaufträgen. Der Fallback-Offset beträgt 7 Tage ab Bestelldatum.,
-"This is the default UOM used for items and Sales orders. The fallback UOM is ""Nos"".","Dies ist die Standard-ME, die für Artikel und Kundenaufträge verwendet wird. Die Fallback-UOM lautet &quot;Nos&quot;.",
+This is the default offset (days) for the Delivery Date in Sales Orders. The fallback offset is 7 days from the order placement date.,Dies ist der Standardversatz (Tage) für das Lieferdatum in Aufträgen. Der Fallback-Offset beträgt 7 Tage ab Bestelldatum.,
+"This is the default UOM used for items and Sales orders. The fallback UOM is ""Nos"".","Dies ist die Standard-ME, die für Artikel und Aufträge verwendet wird. Die Fallback-UOM lautet &quot;Nos&quot;.",
 Endpoints,Endpunkte,
 Endpoint,Endpunkt,
 Antibiotic Name,Antibiotika-Name,
@@ -6230,8 +6230,8 @@
 Reminder Message,Erinnerungsmeldung,
 Remind Before,Vorher erinnern,
 Laboratory Settings,Laboreinstellungen,
-Create Lab Test(s) on Sales Invoice Submission,Erstellen Sie Labortests für die Übermittlung von Verkaufsrechnungen,
-Checking this will create Lab Test(s) specified in the Sales Invoice on submission.,"Wenn Sie dies aktivieren, werden Labortests erstellt, die bei der Übermittlung in der Verkaufsrechnung angegeben sind.",
+Create Lab Test(s) on Sales Invoice Submission,Erstellen Sie Labortests für die Übermittlung von Ausgangsrechnungen,
+Checking this will create Lab Test(s) specified in the Sales Invoice on submission.,"Wenn Sie dies aktivieren, werden Labortests erstellt, die bei der Übermittlung in der Ausgangsrechnung angegeben sind.",
 Create Sample Collection document for Lab Test,Erstellen Sie ein Probensammeldokument für den Labortest,
 Checking this will create a Sample Collection document  every time you create a Lab Test,"Wenn Sie dies aktivieren, wird jedes Mal, wenn Sie einen Labortest erstellen, ein Probensammeldokument erstellt",
 Employee name and designation in print,Name und Bezeichnung des Mitarbeiters im Druck,
@@ -6315,7 +6315,7 @@
 Get Prescribed Therapies,Holen Sie sich verschriebene Therapien,
 Appointment Datetime,Termin Datum / Uhrzeit,
 Duration (In Minutes),Dauer (in Minuten),
-Reference Sales Invoice,Referenzverkaufsrechnung,
+Reference Sales Invoice,Referenzausgangsrechnung,
 More Info,Weitere Informationen,
 Referring Practitioner,Überweisender Praktiker,
 Reminded,Erinnert,
@@ -7268,7 +7268,7 @@
 Default Work In Progress Warehouse,Standard-Fertigungslager,
 Default Finished Goods Warehouse,Standard-Fertigwarenlager,
 Default Scrap Warehouse,Standard-Schrottlager,
-Overproduction Percentage For Sales Order,Überproduktionsprozentsatz für Kundenauftrag,
+Overproduction Percentage For Sales Order,Überproduktionsprozentsatz für Auftrag,
 Overproduction Percentage For Work Order,Überproduktionsprozentsatz für Arbeitsauftrag,
 Other Settings,Weitere Einstellungen,
 Update BOM Cost Automatically,Stücklisten-Kosten automatisch aktualisieren,
@@ -7281,7 +7281,7 @@
 Production Plan,Produktionsplan,
 MFG-PP-.YYYY.-,MFG-PP-.YYYY.-,
 Get Items From,Holen Sie Elemente aus,
-Get Sales Orders,Kundenaufträge aufrufen,
+Get Sales Orders,Aufträge aufrufen,
 Material Request Detail,Materialanforderungsdetail,
 Get Material Request,Get-Material anfordern,
 Material Requests,Materialwünsche,
@@ -7304,8 +7304,8 @@
 material_request_item,material_request_item,
 Product Bundle Item,Produkt-Bundle-Artikel,
 Production Plan Material Request,Produktionsplan-Material anfordern,
-Production Plan Sales Order,Produktionsplan für Kundenauftrag,
-Sales Order Date,Kundenauftrags-Datum,
+Production Plan Sales Order,Produktionsplan für Auftrag,
+Sales Order Date,Auftragsdatum,
 Routing Name,Routing-Name,
 MFG-WO-.YYYY.-,MFG-WO-.YYYY.-,
 Item To Manufacture,Zu fertigender Artikel,
@@ -7482,12 +7482,12 @@
 Start and End Dates,Start- und Enddatum,
 Actual Time (in Hours),Tatsächliche Zeit (in Stunden),
 Costing and Billing,Kalkulation und Abrechnung,
-Total Costing Amount (via Timesheets),Gesamtkalkulationsbetrag (über Arbeitszeittabellen),
-Total Expense Claim (via Expense Claims),Gesamtbetrag der Aufwandsabrechnung (über Aufwandsabrechnungen),
-Total Purchase Cost (via Purchase Invoice),Summe Einkaufskosten (über Einkaufsrechnung),
-Total Sales Amount (via Sales Order),Gesamtverkaufsbetrag (über Kundenauftrag),
-Total Billable Amount (via Timesheets),Gesamter abrechenbarer Betrag (über Arbeitszeittabellen),
-Total Billed Amount (via Sales Invoices),Gesamtabrechnungsbetrag (über Verkaufsrechnungen),
+Total Costing Amount (via Timesheets),Gesamtkalkulationsbetrag (über Zeiterfassung),
+Total Expense Claim (via Expense Claims),Gesamtbetrag der Auslagenabrechnung (über Auslagenabrechnungen),
+Total Purchase Cost (via Purchase Invoice),Summe Einkaufskosten (über Eingangsrechnung),
+Total Sales Amount (via Sales Order),Auftragssumme (über Auftrag),
+Total Billable Amount (via Timesheets),Abrechenbare Summe (über Zeiterfassung),
+Total Billed Amount (via Sales Invoices),Abgerechnete Summe (über Ausgangsrechnungen),
 Total Consumed Material Cost  (via Stock Entry),Summe der verbrauchten Materialkosten (über die Bestandsbuchung),
 Gross Margin,Handelsspanne,
 Gross Margin %,Handelsspanne %,
@@ -7497,9 +7497,9 @@
 Twice Daily,Zweimal täglich,
 First Email,Erste E-Mail,
 Second Email,Zweite E-Mail,
-Time to send,Zeit zu senden,
-Day to Send,Tag zum Senden,
-Message will be sent to the users to get their status on the Project,"Es wird eine Nachricht an die Benutzer gesendet, um deren Status für das Projekt zu erhalten",
+Time to send,Sendezeit,
+Day to Send,Sendetag,
+Message will be sent to the users to get their status on the Project,"Es wird eine Nachricht an die Benutzer gesendet, um über den Projektstatus zu informieren",
 Projects Manager,Projektleiter,
 Project Template,Projektvorlage,
 Project Template Task,Projektvorlagenaufgabe,
@@ -7518,27 +7518,27 @@
 Expected Time (in hours),Voraussichtliche Zeit (in Stunden),
 % Progress,% Fortschritt,
 Is Milestone,Ist Meilenstein,
-Task Description,Aufgabenbeschreibung,
+Task Description,Vorgangsbeschreibung,
 Dependencies,Abhängigkeiten,
-Dependent Tasks,Abhängige Aufgaben,
+Dependent Tasks,Abhängige Vorgänge,
 Depends on Tasks,Abhängig von Vorgang,
 Actual Start Date (via Time Sheet),Das tatsächliche Startdatum (durch Zeiterfassung),
 Actual Time (in hours),Tatsächliche Zeit (in Stunden),
 Actual End Date (via Time Sheet),Das tatsächliche Enddatum (durch Zeiterfassung),
-Total Costing Amount (via Time Sheet),Gesamtkostenbetrag (über Arbeitszeitblatt),
-Total Expense Claim (via Expense Claim),Gesamtbetrag der Aufwandsabrechnung (über Aufwandsabrechnung),
-Total Billing Amount (via Time Sheet),Gesamtrechnungsbetrag (über Arbeitszeitblatt),
+Total Costing Amount (via Time Sheet),Gesamtkosten (über Zeiterfassung),
+Total Expense Claim (via Expense Claim),Summe der Auslagen (über Auslagenabrechnung),
+Total Billing Amount (via Time Sheet),Gesamtrechnungsbetrag (über Zeiterfassung),
 Review Date,Überprüfungsdatum,
 Closing Date,Abschlussdatum,
 Task Depends On,Vorgang hängt ab von,
-Task Type,Aufgabentyp,
+Task Type,Vorgangstyp,
 TS-.YYYY.-,TS-.YYYY.-,
 Employee Detail,Mitarbeiterdetails,
 Billing Details,Rechnungsdetails,
-Total Billable Hours,Insgesamt abrechenbare Stunden,
-Total Billed Hours,Insgesamt Angekündigt Stunden,
+Total Billable Hours,Summe abrechenbare Stunden,
+Total Billed Hours,Summe abgerechneter Stunden,
 Total Costing Amount,Gesamtkalkulation Betrag,
-Total Billable Amount,Insgesamt abrechenbare Betrag,
+Total Billable Amount,Summe abrechenbarer Betrag,
 Total Billed Amount,Gesamtrechnungsbetrag,
 % Amount Billed,% des Betrages berechnet,
 Hrs,Std,
@@ -7555,10 +7555,10 @@
 Monitoring Frequency,Überwachungsfrequenz,
 Weekday,Wochentag,
 Objectives,Ziele,
-Quality Goal Objective,Qualitätsziel Ziel,
+Quality Goal Objective,Qualitätsziel,
 Objective,Zielsetzung,
 Agenda,Agenda,
-Minutes,Protokoll,
+Minutes,Protokolle,
 Quality Meeting Agenda,Qualitätstreffen Agenda,
 Quality Meeting Minutes,Qualitätssitzungsprotokoll,
 Minute,Minute,
@@ -7627,7 +7627,7 @@
 Restaurant Order Entry,Restaurantbestellung,
 Restaurant Table,Restaurant-Tisch,
 Click Enter To Add,Klicken Sie zum Hinzufügen auf Hinzufügen.,
-Last Sales Invoice,Letzte Verkaufsrechnung,
+Last Sales Invoice,Letzte Ausgangsrechnung,
 Current Order,Aktueller Auftrag,
 Restaurant Order Entry Item,Restaurantbestellzugangsposten,
 Served,Serviert,
@@ -7639,7 +7639,7 @@
 Reservation End Time,Reservierungsendzeit,
 No of Seats,Anzahl der Sitze,
 Minimum Seating,Mindestbestuhlung,
-"Keep Track of Sales Campaigns. Keep track of Leads, Quotations, Sales Order etc from Campaigns to gauge Return on Investment. ","Verkaufskampagne verfolgen: Leads, Angebote, Kundenaufträge usw. von Kampagnen beobachten um die Kapitalverzinsung (RoI) zu messen.",
+"Keep Track of Sales Campaigns. Keep track of Leads, Quotations, Sales Order etc from Campaigns to gauge Return on Investment. ","Verkaufskampagne verfolgen: Leads, Angebote, Aufträge usw. von Kampagnen beobachten um die Kapitalverzinsung (RoI) zu messen.",
 SAL-CAM-.YYYY.-,SAL-CAM-.YYYY.-,
 Campaign Schedules,Kampagnenpläne,
 Buyer of Goods and Services.,Käufer von Waren und Dienstleistungen.,
@@ -7647,8 +7647,8 @@
 Default Company Bank Account,Standard-Bankkonto des Unternehmens,
 From Lead,Von Lead,
 Account Manager,Buchhalter,
-Allow Sales Invoice Creation Without Sales Order,Ermöglichen Sie die Erstellung von Kundenrechnungen ohne Kundenauftrag,
-Allow Sales Invoice Creation Without Delivery Note,Ermöglichen Sie die Erstellung einer Verkaufsrechnung ohne Lieferschein,
+Allow Sales Invoice Creation Without Sales Order,Ermöglichen Sie die Erstellung von Kundenrechnungen ohne Auftrag,
+Allow Sales Invoice Creation Without Delivery Note,Ermöglichen Sie die Erstellung einer Ausgangsrechnung ohne Lieferschein,
 Default Price List,Standardpreisliste,
 Primary Address and Contact Detail,Primäre Adresse und Kontaktdetails,
 "Select, to make the customer searchable with these fields","Wählen Sie, um den Kunden mit diesen Feldern durchsuchbar zu machen",
@@ -7665,7 +7665,7 @@
 Sales Team Details,Verkaufsteamdetails,
 Customer POS id,Kunden-POS-ID,
 Customer Credit Limit,Kundenkreditlimit,
-Bypass Credit Limit Check at Sales Order,Kreditlimitprüfung im Kundenauftrag umgehen,
+Bypass Credit Limit Check at Sales Order,Kreditlimitprüfung im Auftrag umgehen,
 Industry Type,Wirtschaftsbranche,
 MAT-INS-.YYYY.-,MAT-INS-.YYYY.-,
 Installation Date,Datum der Installation,
@@ -7701,16 +7701,16 @@
 Additional Notes,Zusätzliche Bemerkungen,
 SAL-ORD-.YYYY.-,SAL-ORD-.YYYY.-,
 Skip Delivery Note,Lieferschein überspringen,
-In Words will be visible once you save the Sales Order.,"""In Worten"" wird sichtbar, sobald Sie den Kundenauftrag speichern.",
-Track this Sales Order against any Project,Diesen Kundenauftrag in jedem Projekt nachverfolgen,
+In Words will be visible once you save the Sales Order.,"""In Worten"" wird sichtbar, sobald Sie den Auftrag speichern.",
+Track this Sales Order against any Project,Diesen Auftrag in jedem Projekt nachverfolgen,
 Billing and Delivery Status,Abrechnungs- und Lieferstatus,
 Not Delivered,Nicht geliefert,
 Fully Delivered,Komplett geliefert,
 Partly Delivered,Teilweise geliefert,
 Not Applicable,Nicht andwendbar,
 %  Delivered,%  geliefert,
-% of materials delivered against this Sales Order,% der für diesen Kundenauftrag gelieferten Materialien,
-% of materials billed against this Sales Order,% der Materialien welche zu diesem Kundenauftrag gebucht wurden,
+% of materials delivered against this Sales Order,% der für diesen Auftrag gelieferten Materialien,
+% of materials billed against this Sales Order,% der Materialien welche zu diesem Auftrag gebucht wurden,
 Not Billed,Nicht abgerechnet,
 Fully Billed,Voll berechnet,
 Partly Billed,Teilweise abgerechnet,
@@ -7845,13 +7845,13 @@
 Bank Credit Balance,Bankguthaben,
 Receivables,Forderungen,
 Payables,Verbindlichkeiten,
-Sales Orders to Bill,Kundenaufträge an Rechnung,
+Sales Orders to Bill,Aufträge an Rechnung,
 Purchase Orders to Bill,Bestellungen an Rechnung,
-New Sales Orders,Neue Kundenaufträge,
+New Sales Orders,Neue Aufträge,
 New Purchase Orders,Neue Bestellungen an Lieferanten,
-Sales Orders to Deliver,Kundenaufträge zu liefern,
-Purchase Orders to Receive,Bestellungen zu empfangen,
-New Purchase Invoice,Neue Kaufrechnung,
+Sales Orders to Deliver,Auszuliefernde Aufträge,
+Purchase Orders to Receive,Anzuliefernde Bestellungen,
+New Purchase Invoice,Neue Eingangsrechnung,
 New Quotations,Neue Angebote,
 Open Quotations,Angebote öffnen,
 Open Issues,Offene Punkte,
@@ -7972,7 +7972,7 @@
 Is Return,Ist Rückgabe,
 Issue Credit Note,Gutschrift ausgeben,
 Return Against Delivery Note,Zurück zum Lieferschein,
-Customer's Purchase Order No,Kundenauftragsnr.,
+Customer's Purchase Order No,Bestellnummer des Kunden,
 Billing Address Name,Name der Rechnungsadresse,
 Required only for sample item.,Nur erforderlich für Probeartikel.,
 "If you have created a standard template in Sales Taxes and Charges Template, select one and click on the button below.","Wenn eine Standardvorlage unter den Vorlagen ""Steuern und Abgaben beim Verkauf"" erstellt wurde, bitte eine Vorlage auswählen und auf die Schaltfläche unten klicken.",
@@ -7989,8 +7989,8 @@
 Excise Page Number,Seitenzahl entfernen,
 Instructions,Anweisungen,
 From Warehouse,Ab Lager,
-Against Sales Order,Zu Kundenauftrag,
-Against Sales Order Item,Zu Kundenauftrags-Position,
+Against Sales Order,Zu Auftrag,
+Against Sales Order Item,Zu Auftragsposition,
 Against Sales Invoice,Zu Ausgangsrechnung,
 Against Sales Invoice Item,Zu Ausgangsrechnungs-Position,
 Available Batch Qty at From Warehouse,Verfügbare Chargenmenge im Ausgangslager,
@@ -8063,7 +8063,7 @@
 "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Beispiel: ABCD.##### \n Wenn ""Serie"" eingestellt ist und ""Seriennummer"" in den Transaktionen nicht aufgeführt ist, dann wird eine Seriennummer automatisch auf der Grundlage dieser Serie erstellt. Wenn immer explizit Seriennummern für diesen Artikel aufgeführt werden sollen, muss das Feld leer gelassen werden.",
 Variants,Varianten,
 Has Variants,Hat Varianten,
-"If this item has variants, then it cannot be selected in sales orders etc.","Wenn dieser Artikel Varianten hat, dann kann er bei den Kundenaufträgen, etc. nicht ausgewählt werden",
+"If this item has variants, then it cannot be selected in sales orders etc.","Wenn dieser Artikel Varianten hat, dann kann er bei den Aufträgen, etc. nicht ausgewählt werden",
 Variant Based On,Variante basierend auf,
 Item Attribute,Artikelattribut,
 "Sales, Purchase, Accounting Defaults","Verkauf, Einkauf, Buchhaltungsvorgaben",
@@ -8529,7 +8529,7 @@
 Qty to Deliver,Zu liefernde Menge,
 Patient Appointment Analytics,Analyse von Patiententerminen,
 Payment Period Based On Invoice Date,Zahlungszeitraum basierend auf Rechnungsdatum,
-Pending SO Items For Purchase Request,Ausstehende Artikel aus Kundenaufträgen für Lieferantenanfrage,
+Pending SO Items For Purchase Request,Ausstehende Artikel aus Aufträgen für Lieferantenanfrage,
 Procurement Tracker,Beschaffungs-Tracker,
 Product Bundle Balance,Produkt-Bundle-Balance,
 Production Analytics,Produktions-Analysen,
@@ -8544,7 +8544,7 @@
 Qty to Receive,Anzunehmende Menge,
 Received Qty Amount,Erhaltene Menge Menge,
 Billed Qty,Rechnungsmenge,
-Purchase Order Trends,Entwicklung Lieferantenaufträge,
+Purchase Order Trends,Entwicklung Bestellungen,
 Purchase Receipt Trends,Trendanalyse Kaufbelege,
 Purchase Register,Übersicht über Einkäufe,
 Quotation Trends,Trendanalyse Angebote,
@@ -8555,7 +8555,7 @@
 Salary Register,Gehalt Register,
 Sales Analytics,Vertriebsanalyse,
 Sales Invoice Trends,Ausgangsrechnung-Trendanalyse,
-Sales Order Trends,Trendanalyse Kundenaufträge,
+Sales Order Trends,Trendanalyse Aufträge,
 Sales Partner Commission Summary,Zusammenfassung der Vertriebspartnerprovision,
 Sales Partner Target Variance based on Item Group,Zielabweichung des Vertriebspartners basierend auf Artikelgruppe,
 Sales Partner Transaction Summary,Sales Partner Transaction Summary,
@@ -8706,7 +8706,7 @@
 Reference Detail No,Referenz Detail Nr,
 Custom Remarks,Benutzerdefinierte Bemerkungen,
 Please select a Company first.,Bitte wählen Sie zuerst eine Firma aus.,
-"Row #{0}: Reference Document Type must be one of Sales Order, Sales Invoice, Journal Entry or Dunning","Zeile # {0}: Der Referenzdokumenttyp muss Kundenauftrag, Verkaufsrechnung, Journaleintrag oder Mahnwesen sein",
+"Row #{0}: Reference Document Type must be one of Sales Order, Sales Invoice, Journal Entry or Dunning","Zeile # {0}: Der Referenzdokumenttyp muss Auftrag, Ausgangsrechnung, Journaleintrag oder Mahnwesen sein",
 POS Closing Entry,POS Closing Entry,
 POS Opening Entry,POS-Eröffnungseintrag,
 POS Transactions,POS-Transaktionen,
@@ -8716,7 +8716,7 @@
 POS Closing Entry Taxes,POS Closing Entry Taxes,
 POS Invoice,POS-Rechnung,
 ACC-PSINV-.YYYY.-,ACC-PSINV-.YYYY.-,
-Consolidated Sales Invoice,Konsolidierte Verkaufsrechnung,
+Consolidated Sales Invoice,Konsolidierte Ausgangsrechnung,
 Return Against POS Invoice,Gegen POS-Rechnung zurücksenden,
 Consolidated,Konsolidiert,
 POS Invoice Item,POS-Rechnungsposition,
@@ -8826,7 +8826,7 @@
 "By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a  ","Standardmäßig wird der Lieferantenname gemäß dem eingegebenen Lieferantennamen festgelegt. Wenn Sie möchten, dass Lieferanten von a benannt werden",
  choose the 'Naming Series' option.,Wählen Sie die Option &quot;Naming Series&quot;.,
 Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.,Konfigurieren Sie die Standardpreisliste beim Erstellen einer neuen Kauftransaktion. Artikelpreise werden aus dieser Preisliste abgerufen.,
-"If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice or Receipt without creating a Purchase Order first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Order' checkbox in the Supplier master.","Wenn diese Option auf &quot;Ja&quot; konfiguriert ist, verhindert ERPNext, dass Sie eine Kaufrechnung oder einen Beleg erstellen können, ohne zuvor eine Bestellung zu erstellen. Diese Konfiguration kann für einen bestimmten Lieferanten überschrieben werden, indem das Kontrollkästchen &quot;Erstellung von Einkaufsrechnungen ohne Bestellung zulassen&quot; im Lieferantenstamm aktiviert wird.",
+"If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice or Receipt without creating a Purchase Order first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Order' checkbox in the Supplier master.","Wenn diese Option auf &quot;Ja&quot; konfiguriert ist, verhindert ERPNext, dass Sie eine Kaufrechnung oder einen Beleg erstellen können, ohne zuvor eine Bestellung zu erstellen. Diese Konfiguration kann für einen bestimmten Lieferanten überschrieben werden, indem das Kontrollkästchen &quot;Erstellung von Eingangsrechnungen ohne Bestellung zulassen&quot; im Lieferantenstamm aktiviert wird.",
 "If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice without creating a Purchase Receipt first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Receipt' checkbox in the Supplier master.","Wenn diese Option auf &quot;Ja&quot; konfiguriert ist, verhindert ERPNext, dass Sie eine Kaufrechnung erstellen können, ohne zuvor einen Kaufbeleg zu erstellen. Diese Konfiguration kann für einen bestimmten Lieferanten überschrieben werden, indem das Kontrollkästchen &quot;Erstellung von Kaufrechnungen ohne Kaufbeleg zulassen&quot; im Lieferantenstamm aktiviert wird.",
 Quantity & Stock,Menge &amp; Lager,
 Call Details,Anrufdetails,
@@ -8903,7 +8903,7 @@
 "If checked, a customer will be created for every Patient. Patient Invoices will be created against this Customer. You can also select existing Customer while creating a Patient. This field is checked by default.","Wenn diese Option aktiviert ist, wird für jeden Patienten ein Kunde erstellt. Für diesen Kunden werden Patientenrechnungen erstellt. Sie können beim Erstellen eines Patienten auch einen vorhandenen Kunden auswählen. Dieses Feld ist standardmäßig aktiviert.",
 Collect Registration Fee,Registrierungsgebühr sammeln,
 "If your Healthcare facility bills registrations of Patients, you can check this and set the Registration Fee in the field below. Checking this will create new Patients with a Disabled status by default and will only be enabled after invoicing the Registration Fee.","Wenn Ihre Gesundheitseinrichtung die Registrierung von Patienten in Rechnung stellt, können Sie dies überprüfen und die Registrierungsgebühr im Feld unten festlegen. Wenn Sie dies aktivieren, werden standardmäßig neue Patienten mit dem Status &quot;Deaktiviert&quot; erstellt und erst nach Rechnungsstellung der Registrierungsgebühr aktiviert.",
-Checking this will automatically create a Sales Invoice whenever an appointment is booked for a Patient.,"Wenn Sie dies aktivieren, wird automatisch eine Verkaufsrechnung erstellt, wenn ein Termin für einen Patienten gebucht wird.",
+Checking this will automatically create a Sales Invoice whenever an appointment is booked for a Patient.,"Wenn Sie dies aktivieren, wird automatisch eine Ausgangsrechnung erstellt, wenn ein Termin für einen Patienten gebucht wird.",
 Healthcare Service Items,Artikel im Gesundheitswesen,
 "You can create a service item for Inpatient Visit Charge and set it here. Similarly, you can set up other Healthcare Service Items for billing in this section. Click ",Sie können ein Serviceelement für die Gebühr für stationäre Besuche erstellen und hier festlegen. Ebenso können Sie in diesem Abschnitt andere Gesundheitsposten für die Abrechnung einrichten. Klicken,
 Set up default Accounts for the Healthcare Facility,Richten Sie Standardkonten für die Gesundheitseinrichtung ein,
@@ -8958,7 +8958,7 @@
 Add New Line,Neue Zeile hinzufügen,
 Secondary UOM,Sekundäre UOM,
 "<b>Single</b>: Results which require only a single input.\n<br>\n<b>Compound</b>: Results which require multiple event inputs.\n<br>\n<b>Descriptive</b>: Tests which have multiple result components with manual result entry.\n<br>\n<b>Grouped</b>: Test templates which are a group of other test templates.\n<br>\n<b>No Result</b>: Tests with no results, can be ordered and billed but no Lab Test will be created. e.g.. Sub Tests for Grouped results","<b>Single</b> : Ergebnisse, die nur eine einzige Eingabe erfordern.<br> <b>Verbindung</b> : Ergebnisse, die mehrere Ereigniseingaben erfordern.<br> <b>Beschreibend</b> : Tests mit mehreren Ergebniskomponenten mit manueller Ergebniseingabe.<br> <b>Gruppiert</b> : <b>Testvorlagen,</b> die eine Gruppe anderer <b>Testvorlagen</b> sind.<br> <b>Kein Ergebnis</b> : Tests ohne Ergebnisse können bestellt und in Rechnung gestellt werden, es wird jedoch kein Labortest erstellt. z.B. Untertests für gruppierte Ergebnisse",
-"If unchecked, the item will not be available in Sales Invoices for billing but can be used in group test creation. ","Wenn diese Option deaktiviert ist, ist der Artikel in den Verkaufsrechnungen nicht zur Abrechnung verfügbar, kann jedoch für die Erstellung von Gruppentests verwendet werden.",
+"If unchecked, the item will not be available in Sales Invoices for billing but can be used in group test creation. ","Wenn diese Option deaktiviert ist, ist der Artikel in den Ausgangsrechnungen nicht zur Abrechnung verfügbar, kann jedoch für die Erstellung von Gruppentests verwendet werden.",
 Description ,Beschreibung,
 Descriptive Test,Beschreibender Test,
 Group Tests,Gruppentests,
@@ -9084,8 +9084,8 @@
 Manufacturing Section,Fertigungsabteilung,
 "By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ","Standardmäßig wird der Kundenname gemäß dem eingegebenen vollständigen Namen festgelegt. Wenn Sie möchten, dass Kunden von a benannt werden",
 Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.,Konfigurieren Sie die Standardpreisliste beim Erstellen einer neuen Verkaufstransaktion. Artikelpreise werden aus dieser Preisliste abgerufen.,
-"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.","Wenn diese Option auf &quot;Ja&quot; konfiguriert ist, verhindert ERPNext, dass Sie eine Verkaufsrechnung oder einen Lieferschein erstellen, ohne zuvor einen Kundenauftrag zu erstellen. Diese Konfiguration kann für einen bestimmten Kunden überschrieben werden, indem das Kontrollkästchen &quot;Erstellung von Verkaufsrechnungen ohne Kundenauftrag zulassen&quot; im Kundenstamm aktiviert wird.",
-"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice without creating a Delivery Note first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Delivery Note' checkbox in the Customer master.","Wenn diese Option auf &quot;Ja&quot; konfiguriert ist, verhindert ERPNext, dass Sie eine Verkaufsrechnung erstellen, ohne zuvor einen Lieferschein zu erstellen. Diese Konfiguration kann für einen bestimmten Kunden überschrieben werden, indem das Kontrollkästchen &quot;Erstellung von Verkaufsrechnungen ohne Lieferschein zulassen&quot; im Kundenstamm aktiviert wird.",
+"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.","Wenn diese Option auf &quot;Ja&quot; konfiguriert ist, verhindert ERPNext, dass Sie eine Ausgangsrechnung oder einen Lieferschein erstellen, ohne zuvor einen Auftrag zu erstellen. Diese Konfiguration kann für einen bestimmten Kunden überschrieben werden, indem das Kontrollkästchen &quot;Erstellung von Ausgangsrechnung ohne Auftrag zulassen&quot; im Kundenstamm aktiviert wird.",
+"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice without creating a Delivery Note first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Delivery Note' checkbox in the Customer master.","Wenn diese Option auf &quot;Ja&quot; konfiguriert ist, verhindert ERPNext, dass Sie eine Ausgangsrechnung erstellen, ohne zuvor einen Lieferschein zu erstellen. Diese Konfiguration kann für einen bestimmten Kunden überschrieben werden, indem das Kontrollkästchen &quot;Erstellung von Ausgangsrechnungen ohne Lieferschein zulassen&quot; im Kundenstamm aktiviert wird.",
 Default Warehouse for Sales Return,Standardlager für Retouren,
 Default In Transit Warehouse,Standard im Transit Warehouse,
 Enable Perpetual Inventory For Non Stock Items,Aktivieren Sie das ewige Inventar für nicht vorrätige Artikel,
@@ -9114,7 +9114,7 @@
 Choose between FIFO and Moving Average Valuation Methods. Click ,Wählen Sie zwischen FIFO- und Moving Average-Bewertungsmethoden. Klicken,
  to know more about them.,um mehr über sie zu erfahren.,
 Show 'Scan Barcode' field above every child table to insert Items with ease.,"Zeigen Sie das Feld &quot;Barcode scannen&quot; über jeder untergeordneten Tabelle an, um Elemente problemlos einzufügen.",
-"Serial numbers for stock will be set automatically based on the Items entered based on first in first out in transactions like Purchase/Sales Invoices, Delivery Notes, etc.","Seriennummern für Lagerbestände werden automatisch basierend auf den Artikeln festgelegt, die basierend auf First-In-First-Out in Transaktionen wie Kauf- / Verkaufsrechnungen, Lieferscheinen usw. eingegeben wurden.",
+"Serial numbers for stock will be set automatically based on the Items entered based on first in first out in transactions like Purchase/Sales Invoices, Delivery Notes, etc.","Seriennummern für Lagerbestände werden automatisch basierend auf den Artikeln festgelegt, die basierend auf First-In-First-Out in Transaktionen wie Ein- und Ausgangsrechnungen, Lieferscheinen usw. eingegeben wurden.",
 "If blank, parent Warehouse Account or company default will be considered in transactions","Wenn leer, wird das übergeordnete Lagerkonto oder der Firmenstandard bei Transaktionen berücksichtigt",
 Service Level Agreement Details,Details zum Service Level Agreement,
 Service Level Agreement Status,Status des Service Level Agreements,
@@ -9263,10 +9263,10 @@
 Account No,Konto Nr,
 IFSC,IFSC,
 MICR,MICR,
-Sales Order Analysis,Kundenauftragsanalyse,
+Sales Order Analysis,Auftragsanalyse,
 Amount Delivered,Gelieferter Betrag,
 Delay (in Days),Verzögerung (in Tagen),
-Group by Sales Order,Nach Kundenauftrag gruppieren,
+Group by Sales Order,Nach Auftrag gruppieren,
  Sales Value,Verkaufswert,
 Stock Qty vs Serial No Count,Lagermenge vs Seriennummer,
 Serial No Count,Seriennummer nicht gezählt,
@@ -9456,8 +9456,8 @@
 Based On Document,Basierend auf Dokument,
 Based On Data ( in years ),Basierend auf Daten (in Jahren),
 Smoothing Constant,Glättungskonstante,
-Please fill the Sales Orders table,Bitte füllen Sie die Tabelle Kundenaufträge aus,
-Sales Orders Required,Kundenaufträge erforderlich,
+Please fill the Sales Orders table,Bitte füllen Sie die Tabelle Aufträge aus,
+Sales Orders Required,Aufträge erforderlich,
 Please fill the Material Requests table,Bitte füllen Sie die Materialanforderungstabelle aus,
 Material Requests Required,Materialanforderungen erforderlich,
 Items to Manufacture are required to pull the Raw Materials associated with it.,"Zu fertigende Gegenstände sind erforderlich, um die damit verbundenen Rohstoffe zu ziehen.",
@@ -9486,7 +9486,7 @@
 Payroll date can not be greater than employee's relieving date.,Das Abrechnungsdatum darf nicht größer sein als das Entlastungsdatum des Mitarbeiters.,
 Row #{0}: Please enter the result value for {1},Zeile # {0}: Bitte geben Sie den Ergebniswert für {1} ein,
 Mandatory Results,Obligatorische Ergebnisse,
-Sales Invoice or Patient Encounter is required to create Lab Tests,Für die Erstellung von Labortests ist eine Verkaufsrechnung oder eine Patientenbegegnung erforderlich,
+Sales Invoice or Patient Encounter is required to create Lab Tests,Für die Erstellung von Labortests ist eine Ausgangsrechnung oder eine Patientenbegegnung erforderlich,
 Insufficient Data,Unzureichende Daten,
 Lab Test(s) {0} created successfully,Labortest (e) {0} erfolgreich erstellt,
 Test :,Prüfung :,
@@ -9634,16 +9634,16 @@
 Default: 10 mins,Standard: 10 Minuten,
 Overproduction for Sales and Work Order,Überproduktion für Kunden- und Arbeitsauftrag,
 "Update BOM cost automatically via scheduler, based on the latest Valuation Rate/Price List Rate/Last Purchase Rate of raw materials","Aktualisieren Sie die Stücklistenkosten automatisch über den Planer, basierend auf der neuesten Bewertungsrate / Preislistenrate / letzten Kaufrate der Rohstoffe",
-Purchase Order already created for all Sales Order items,Bestellung bereits für alle Kundenauftragspositionen angelegt,
+Purchase Order already created for all Sales Order items,Bestellung bereits für alle Auftragspositionen angelegt,
 Select Items,Gegenstände auswählen,
 Against Default Supplier,Gegen Standardlieferanten,
 Auto close Opportunity after the no. of days mentioned above,Gelegenheit zum automatischen Schließen nach der Nr. der oben genannten Tage,
-Is Sales Order Required for Sales Invoice & Delivery Note Creation?,Ist ein Kundenauftrag für die Erstellung von Kundenrechnungen und Lieferscheinen erforderlich?,
-Is Delivery Note Required for Sales Invoice Creation?,Ist für die Erstellung der Verkaufsrechnung ein Lieferschein erforderlich?,
+Is Sales Order Required for Sales Invoice & Delivery Note Creation?,Ist ein Auftrag für die Erstellung von Kundenrechnungen und Lieferscheinen erforderlich?,
+Is Delivery Note Required for Sales Invoice Creation?,Ist für die Erstellung der Ausgangsrechnung ein Lieferschein erforderlich?,
 How often should Project and Company be updated based on Sales Transactions?,Wie oft sollten Projekt und Unternehmen basierend auf Verkaufstransaktionen aktualisiert werden?,
 Allow User to Edit Price List Rate in Transactions,Benutzer darf Preisliste in Transaktionen bearbeiten,
 Allow Item to Be Added Multiple Times in a Transaction,"Zulassen, dass ein Element in einer Transaktion mehrmals hinzugefügt wird",
-Allow Multiple Sales Orders Against a Customer's Purchase Order,Erlauben Sie mehrere Kundenaufträge für die Bestellung eines Kunden,
+Allow Multiple Sales Orders Against a Customer's Purchase Order,Erlauben Sie mehrere Aufträge für die Bestellung eines Kunden,
 Validate Selling Price for Item Against Purchase Rate or Valuation Rate,Überprüfen Sie den Verkaufspreis für den Artikel anhand der Kauf- oder Bewertungsrate,
 Hide Customer's Tax ID from Sales Transactions,Steuer-ID des Kunden vor Verkaufstransaktionen ausblenden,
 "The percentage you are allowed to receive or deliver more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed to receive 110 units.","Der Prozentsatz, den Sie mehr gegen die bestellte Menge erhalten oder liefern dürfen. Wenn Sie beispielsweise 100 Einheiten bestellt haben und Ihre Zulage 10% beträgt, können Sie 110 Einheiten erhalten.",
@@ -9653,8 +9653,8 @@
 Set Qty in Transactions Based on Serial No Input,Stellen Sie die Menge in Transaktionen basierend auf Seriennummer ohne Eingabe ein,
 Raise Material Request When Stock Reaches Re-order Level,"Erhöhen Sie die Materialanforderung, wenn der Lagerbestand die Nachbestellmenge erreicht",
 Notify by Email on Creation of Automatic Material Request,Benachrichtigen Sie per E-Mail über die Erstellung einer automatischen Materialanforderung,
-Allow Material Transfer from Delivery Note to Sales Invoice,Materialübertragung vom Lieferschein zur Verkaufsrechnung zulassen,
-Allow Material Transfer from Purchase Receipt to Purchase Invoice,Materialübertragung vom Kaufbeleg zur Kaufrechnung zulassen,
+Allow Material Transfer from Delivery Note to Sales Invoice,Materialübertragung vom Lieferschein zur Ausgangsrechnung zulassen,
+Allow Material Transfer from Purchase Receipt to Purchase Invoice,Materialübertragung vom Kaufbeleg zur Eingangsrechnung zulassen,
 Freeze Stocks Older Than (Days),Aktien einfrieren älter als (Tage),
 Role Allowed to Edit Frozen Stock,Rolle darf eingefrorenes Material bearbeiten,
 The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,Der nicht zugewiesene Betrag der Zahlungseingabe {0} ist größer als der nicht zugewiesene Betrag der Banküberweisung,
@@ -9694,7 +9694,7 @@
 Error Occured,Fehler aufgetreten,
 Opening Invoice Creation In Progress,Öffnen der Rechnungserstellung läuft,
 Creating {} out of {} {},{} Aus {} {} erstellen,
-(Serial No: {0}) cannot be consumed as it's reserverd to fullfill Sales Order {1}.,"(Seriennummer: {0}) kann nicht verwendet werden, da es zum Ausfüllen des Kundenauftrags {1} reserviert ist.",
+(Serial No: {0}) cannot be consumed as it's reserverd to fullfill Sales Order {1}.,"(Seriennummer: {0}) kann nicht verwendet werden, da es zum Ausfüllen des Auftrags {1} reserviert ist.",
 Item {0} {1},Gegenstand {0} {1},
 Last Stock Transaction for item {0} under warehouse {1} was on {2}.,Die letzte Lagertransaktion für Artikel {0} unter Lager {1} war am {2}.,
 Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.,Lagertransaktionen für Artikel {0} unter Lager {1} können nicht vor diesem Zeitpunkt gebucht werden.,
@@ -9822,8 +9822,8 @@
 "If you {0} {1} worth item {2}, the scheme {3} will be applied on the item.","Wenn Sie {0} {1} Gegenstand {2} wert sind, wird das Schema {3} auf den Gegenstand angewendet.",
 "As the field {0} is enabled, the field {1} is mandatory.","Da das Feld {0} aktiviert ist, ist das Feld {1} obligatorisch.",
 "As the field {0} is enabled, the value of the field {1} should be more than 1.","Wenn das Feld {0} aktiviert ist, sollte der Wert des Feldes {1} größer als 1 sein.",
-Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2},"Die Seriennummer {0} von Artikel {1} kann nicht geliefert werden, da sie für die Erfüllung des Kundenauftrags {2} reserviert ist.",
-"Sales Order {0} has reservation for the item {1}, you can only deliver reserved {1} against {0}.","Kundenauftrag {0} hat eine Reservierung für den Artikel {1}, Sie können reservierte {1} nur gegen {0} liefern.",
+Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2},"Die Seriennummer {0} von Artikel {1} kann nicht geliefert werden, da sie für die Erfüllung des Auftrags {2} reserviert ist.",
+"Sales Order {0} has reservation for the item {1}, you can only deliver reserved {1} against {0}.","Auftrag {0} hat eine Reservierung für den Artikel {1}, Sie können reservierte {1} nur gegen {0} liefern.",
 {0} Serial No {1} cannot be delivered,{0} Seriennummer {1} kann nicht zugestellt werden,
 Row {0}: Subcontracted Item is mandatory for the raw material {1},Zeile {0}: Unterauftragsartikel sind für den Rohstoff {1} obligatorisch.,
 "As there are sufficient raw materials, Material Request is not required for Warehouse {0}.","Da genügend Rohstoffe vorhanden sind, ist für Warehouse {0} keine Materialanforderung erforderlich.",
diff --git a/requirements.txt b/requirements.txt
index faefb77..f447fac 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
 # frappe   # https://github.com/frappe/frappe is installed during bench-init
 gocardless-pro~=1.22.0
-googlemaps  # used in ERPNext, but dependency is defined in Frappe
+googlemaps
 pandas~=1.1.5
 plaid-python~=7.2.1
 pycountry~=20.7.3