Merge branch 'develop' of https://github.com/frappe/erpnext into develop
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json
index 8856c8c..a8afb55 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json
@@ -1,465 +1,466 @@
 {
-    "country_code": "ae", 
-    "name": "U.A.E - Chart of Accounts", 
+    "country_code": "ae",
+    "name": "U.A.E - Chart of Accounts",
     "tree": {
         "Assets": {
             "Current Assets": {
                 "Accounts Receivable": {
                     "Corporate Credit Cards": {
                         "account_type": "Receivable"
-                    }, 
+                    },
                     "Other Receivable": {
                         "Accrued Rebates Due from Suppliers": {
                             "account_type": "Receivable"
-                        }, 
+                        },
                         "Accrued Income from Suppliers": {
                             "account_type": "Receivable"
-                        }, 
+                        },
                         "Other Debtors": {
                             "account_type": "Receivable"
-                        }, 
+                        },
                         "account_type": "Receivable"
-                    }, 
+                    },
                     "Post Dated Cheques Received": {
                         "account_type": "Receivable"
-                    }, 
+                    },
                     "Staff Receivable": {
                         "account_type": "Receivable"
-                    }, 
+                    },
                     "Trade Receivable": {
                         "account_type": "Receivable"
-                    }, 
+                    },
                     "Trade in Opening Fees": {
                         "account_type": "Receivable"
-                    }, 
+                    },
                     "account_type": "Receivable"
-                }, 
+                },
                 "Cash in Hand & Banks": {
                     "Banks": {
-                        "Bank Margin On LC & LG": {}, 
-                        "Banks Blocked Deposits": {}, 
-                        "Banks Call Deposit Accounts": {}, 
+                        "Bank Margin On LC & LG": {},
+                        "Banks Blocked Deposits": {},
+                        "Banks Call Deposit Accounts": {},
                         "Banks Current Accounts": {
                             "account_type": "Bank"
-                        }, 
+                        },
                         "account_type": "Bank"
-                    }, 
+                    },
                     "Cash in Hand": {
                         "Cash in Safe": {
                             "Main Safe": {
                                 "account_type": "Cash"
-                            }, 
+                            },
                             "Main Safe - Foreign Currency": {
                                 "account_type": "Cash"
                             }
-                        }, 
+                        },
                         "Petty Cash": {
                             "Petty Cash - Administration": {
                                 "account_type": "Cash"
-                            }, 
+                            },
                             "Petty Cash - Others": {
                                 "account_type": "Cash"
                             }
-                        }, 
+                        },
                         "account_type": "Cash"
-                    }, 
+                    },
                     "Cash in Transit": {
                         "Credit Cards": {
                             "Gateway Credit Cards": {
                                 "account_type": "Bank"
-                            }, 
+                            },
                             "Manual Visa & Master Cards": {
                                 "account_type": "Bank"
-                            }, 
+                            },
                             "PayPal Account": {
                                 "account_type": "Bank"
-                            }, 
+                            },
                             "Visa & Master Credit Cards": {
                                 "account_type": "Bank"
                             }
                         }
                     }
-                }, 
+                },
                 "Inventory": {
                     "Consigned Stock": {
-                        "Handling Difference in Inventory": {
-                            "account_type": "Stock Adjustment"
-                        }, 
+                        "Handling Difference in Inventory": {},
                         "Items Delivered to Customs on temporary Base": {}
-                    }, 
+                    },
                     "Stock in Hand": {
                         "account_type": "Stock"
                     }
-                }, 
+                },
                 "Preliminary and Preoperating Expenses": {
                     "Preoperating Expenses": {}
-                }, 
+                },
                 "Prepayments & Deposits": {
                     "Deposits": {
-                        "Deposit - Office Rent": {}, 
-                        "Deposit Others": {}, 
-                        "Deposit to Immigration (Visa)": {}, 
+                        "Deposit - Office Rent": {},
+                        "Deposit Others": {},
+                        "Deposit to Immigration (Visa)": {},
                         "Deposits - Customs": {}
-                    }, 
+                    },
                     "Prepaid Taxes": {
-                        "Sales Taxes Receivables": {}, 
+                        "Sales Taxes Receivables": {},
                         "Withholding Tax Receivables": {}
-                    }, 
+                    },
                     "Prepayments": {
-                        "Other Prepayments": {}, 
-                        "PrePaid Advertisement Expenses": {}, 
-                        "Prepaid Bank Guarantee": {}, 
-                        "Prepaid Consultancy Fees": {}, 
-                        "Prepaid Employees Housing": {}, 
-                        "Prepaid Finance charge for Loans": {}, 
-                        "Prepaid Legal Fees": {}, 
-                        "Prepaid License Fees": {}, 
-                        "Prepaid Life Insurance": {}, 
-                        "Prepaid Maintenance": {}, 
-                        "Prepaid Medical Insurance": {}, 
-                        "Prepaid Office Rent": {}, 
-                        "Prepaid Other Insurance": {}, 
-                        "Prepaid Schooling Fees": {}, 
-                        "Prepaid Site Hosting Fees": {}, 
+                        "Other Prepayments": {},
+                        "PrePaid Advertisement Expenses": {},
+                        "Prepaid Bank Guarantee": {},
+                        "Prepaid Consultancy Fees": {},
+                        "Prepaid Employees Housing": {},
+                        "Prepaid Finance charge for Loans": {},
+                        "Prepaid Legal Fees": {},
+                        "Prepaid License Fees": {},
+                        "Prepaid Life Insurance": {},
+                        "Prepaid Maintenance": {},
+                        "Prepaid Medical Insurance": {},
+                        "Prepaid Office Rent": {},
+                        "Prepaid Other Insurance": {},
+                        "Prepaid Schooling Fees": {},
+                        "Prepaid Site Hosting Fees": {},
                         "Prepaid Sponsorship Fees": {}
                     }
                 }
-            }, 
+            },
             "Long Term Assets": {
                 "Fixed Assets": {
                     "Accumulated Depreciation": {
                         "Acc. Depreciation of Motor Vehicles": {
                             "account_type": "Accumulated Depreciation"
-                        }, 
+                        },
                         "Acc. Deprn.Computer Hardware & Software": {
                             "account_type": "Accumulated Depreciation"
-                        }, 
+                        },
                         "Acc.Deprn.of Furniture & Office Equipment": {
                             "account_type": "Accumulated Depreciation"
-                        }, 
+                        },
                         "Amortisation on Leasehold Improvement": {
                             "account_type": "Accumulated Depreciation"
-                        }, 
+                        },
                         "account_type": "Accumulated Depreciation"
-                    }, 
+                    },
                     "Fixed Assets (Cost Price)": {
                         "Computer Hardware & Software": {
                             "account_type": "Fixed Asset"
-                        }, 
+                        },
                         "Furniture and Equipment": {
                             "account_type": "Fixed Asset"
-                        }, 
-                        "Leasehold Improvement": {}, 
+                        },
+                        "Leasehold Improvement": {},
                         "Motor Vehicles": {
                             "account_type": "Fixed Asset"
-                        }, 
-                        "Work In Progress": {}, 
+                        },
+                        "Work In Progress": {},
                         "account_type": "Fixed Asset"
                     }
-                }, 
+                },
                 "Intangible Assets": {
-                    "Computer Card Renewal": {}, 
-                    "Disposal of Outlets": {}, 
+                    "Computer Card Renewal": {},
+                    "Disposal of Outlets": {},
                     "Registration of Trademarks": {}
-                }, 
-                "Intercompany Accounts": {}, 
+                },
+                "Intercompany Accounts": {},
                 "Investments": {
                     "Investments in Subsidiaries": {}
                 }
-            }, 
+            },
             "root_type": "Asset"
-        }, 
+        },
         "Closing And Temporary Accounts": {
             "Closing Accounts": {
                 "Closing Account": {}
-            }, 
+            },
             "root_type": "Liability"
-        }, 
+        },
         "Expenses": {
             "Commercial Expenses": {
-                "Consultancy Fees": {}, 
+                "Consultancy Fees": {},
                 "Provision for Doubtful Debts": {}
-            }, 
+            },
             "Cost of Sale": {
                 "Cost Of Goods Sold": {
-                    "Cost Of Goods Sold I/C Sales": {}, 
+                    "Cost Of Goods Sold I/C Sales": {},
                     "Cost of Goods Sold in Trading": {
                         "account_type": "Cost of Goods Sold"
-                    }, 
+                    },
                     "account_type": "Cost of Goods Sold"
-                }, 
+                },
                 "Expenses Included In Valuation": {
                     "account_type": "Expenses Included In Valuation"
+                },
+                "Stock Adjustment": {
+                    "account_type": "Stock Adjustment"
                 }
-            }, 
+            },
             "Depreciation": {
                 "Depreciation & Amortization": {
-                    "Amortization on Leasehold Improvement": {}, 
+                    "Amortization on Leasehold Improvement": {},
                     "Depreciation Of Computer Hard & Soft": {
                         "account_type": "Depreciation"
-                    }, 
+                    },
                     "Depreciation Of Furniture & Office Equipment\n\t\t\t": {
                         "account_type": "Depreciation"
-                    }, 
+                    },
                     "Depreciation Of Motor Vehicles": {
                         "account_type": "Depreciation"
                     }
                 }
-            }, 
+            },
             "Direct Expenses": {
                 "Financial Charges": {
-                    "Air Miles Card Charges": {}, 
-                    "Amex Credit Cards Charges": {}, 
-                    "Bank Finance & Loan Charges": {}, 
-                    "Credit Card Charges": {}, 
-                    "Credit Card Swipe Charges": {}, 
+                    "Air Miles Card Charges": {},
+                    "Amex Credit Cards Charges": {},
+                    "Bank Finance & Loan Charges": {},
+                    "Credit Card Charges": {},
+                    "Credit Card Swipe Charges": {},
                     "PayPal Charges": {}
                 }
-            }, 
+            },
             "MISC Charges": {
                 "Other Charges": {
                     "Capital Loss": {
-                        "Disposal of Business Branch": {}, 
-                        "Loss On Fixed Assets Disposal": {}, 
+                        "Disposal of Business Branch": {},
+                        "Loss On Fixed Assets Disposal": {},
                         "Loss on Difference on Exchange": {}
-                    }, 
+                    },
                     "Other Non Operating Exp": {
                         "Other Non Operating Expenses": {}
-                    }, 
+                    },
                     "Previous Year Adjustments": {
                         "Previous Year Adjustments Account": {}
-                    }, 
+                    },
                     "Royalty Fees": {
                         "Royalty to Parent Co.": {}
-                    }, 
+                    },
                     "Tax / Zakat Expenses": {
                         "Income Tax": {
                             "account_type": "Tax"
-                        }, 
-                        "Zakat": {}, 
+                        },
+                        "Zakat": {},
                         "account_type": "Tax"
                     }
                 }
-            }, 
+            },
             "Share Resources": {
                 "Share Resource Expenses Account": {}
-            }, 
+            },
             "Store Operating Expenses": {
                 "Selling, General & Admin Expenses": {
                     "Advertising Expenses": {
                         "Other - Advertising Expenses": {}
-                    }, 
+                    },
                     "Bank & Finance Charges": {
                         "Other Bank Charges": {}
-                    }, 
+                    },
                     "Communications": {
-                        "Courier": {}, 
-                        "Others - Communication": {}, 
-                        "Telephone": {}, 
+                        "Courier": {},
+                        "Others - Communication": {},
+                        "Telephone": {},
                         "Web Site Hosting Fees": {}
-                    }, 
+                    },
                     "Office & Various Expenses": {
-                        "Cleaning": {}, 
-                        "Conveyance Expenses": {}, 
-                        "Gifts & Donations": {}, 
-                        "Insurance": {}, 
-                        "Kitchen and Buffet Expenses": {}, 
-                        "Maintenance": {}, 
-                        "Others - Office Various Expenses": {}, 
-                        "Security & Guard": {}, 
-                        "Stationary From Suppliers": {}, 
-                        "Stationary Out Of Stock": {}, 
-                        "Subscriptions": {}, 
-                        "Training": {}, 
+                        "Cleaning": {},
+                        "Conveyance Expenses": {},
+                        "Gifts & Donations": {},
+                        "Insurance": {},
+                        "Kitchen and Buffet Expenses": {},
+                        "Maintenance": {},
+                        "Others - Office Various Expenses": {},
+                        "Security & Guard": {},
+                        "Stationary From Suppliers": {},
+                        "Stationary Out Of Stock": {},
+                        "Subscriptions": {},
+                        "Training": {},
                         "Vehicle Expenses": {}
-                    }, 
+                    },
                     "Personnel Cost": {
-                        "Basic Salary": {}, 
-                        "End Of Service Indemnity": {}, 
-                        "Housing Allowance": {}, 
-                        "Leave Salary": {}, 
-                        "Leave Ticket": {}, 
-                        "Life Insurance": {}, 
-                        "Medical Insurance": {}, 
-                        "Personnel Cost Others": {}, 
-                        "Sales Commission": {}, 
-                        "Staff School Allowances": {}, 
-                        "Transportation Allowance": {}, 
-                        "Uniform": {}, 
+                        "Basic Salary": {},
+                        "End Of Service Indemnity": {},
+                        "Housing Allowance": {},
+                        "Leave Salary": {},
+                        "Leave Ticket": {},
+                        "Life Insurance": {},
+                        "Medical Insurance": {},
+                        "Personnel Cost Others": {},
+                        "Sales Commission": {},
+                        "Staff School Allowances": {},
+                        "Transportation Allowance": {},
+                        "Uniform": {},
                         "Visa Expenses": {}
-                    }, 
+                    },
                     "Professional & Legal Fees": {
-                        "Audit Fees": {}, 
-                        "Legal fees": {}, 
-                        "Others - Professional Fees": {}, 
-                        "Sponsorship Fees": {}, 
+                        "Audit Fees": {},
+                        "Legal fees": {},
+                        "Others - Professional Fees": {},
+                        "Sponsorship Fees": {},
                         "Trade License Fees": {}
-                    }, 
+                    },
                     "Provision & Write Off": {
-                        "Amortisation of Preoperating Expenses": {}, 
-                        "Cash Shortage": {}, 
-                        "Others - Provision & Write off": {}, 
-                        "Write Off Inventory": {}, 
+                        "Amortisation of Preoperating Expenses": {},
+                        "Cash Shortage": {},
+                        "Others - Provision & Write off": {},
+                        "Write Off Inventory": {},
                         "Write Off Receivables & Payables": {}
-                    }, 
+                    },
                     "Rent Expenses": {
-                        "Office Rent": {}, 
+                        "Office Rent": {},
                         "Warehouse Rent": {}
-                    }, 
+                    },
                     "Travel Expenses": {
-                        "Air tickets": {}, 
-                        "Hotel": {}, 
-                        "Meals": {}, 
-                        "Others": {}, 
+                        "Air tickets": {},
+                        "Hotel": {},
+                        "Meals": {},
+                        "Others": {},
                         "Per Diem": {}
-                    }, 
+                    },
                     "Utilities": {
-                        "Other Utility Cahrges": {}, 
+                        "Other Utility Cahrges": {},
                         "Water & Electricity": {}
                     }
                 }
-            }, 
+            },
             "root_type": "Expense"
-        }, 
+        },
         "Liabilities": {
             "Current Liabilities": {
                 "Accounts Payable": {
                     "Payables": {
                         "Advance Payable to Suppliers": {
                             "account_type": "Payable"
-                        }, 
+                        },
                         "Consigned Payable": {
                             "account_type": "Payable"
-                        }, 
+                        },
                         "Other Payable": {
                             "account_type": "Payable"
-                        }, 
+                        },
                         "Post Dated Cheques Paid": {
                             "account_type": "Payable"
-                        }, 
-                        "Staff Payable": {}, 
+                        },
+                        "Staff Payable": {},
                         "Suppliers Price Protection": {
                             "account_type": "Payable"
-                        }, 
+                        },
                         "Trade Payable": {
                             "account_type": "Payable"
-                        }, 
+                        },
                         "account_type": "Payable"
                     }
-                }, 
+                },
                 "Accruals & Provisions": {
                     "Accruals": {
                         "Accrued Personnel Cost": {
-                            "Accrued - Commissions": {}, 
-                            "Accrued - Leave Salary": {}, 
-                            "Accrued - Leave Tickets": {}, 
-                            "Accrued - Salaries": {}, 
-                            "Accrued Other Personnel Cost": {}, 
-                            "Accrued Salaries Increment": {}, 
+                            "Accrued - Commissions": {},
+                            "Accrued - Leave Salary": {},
+                            "Accrued - Leave Tickets": {},
+                            "Accrued - Salaries": {},
+                            "Accrued Other Personnel Cost": {},
+                            "Accrued Salaries Increment": {},
                             "Accrued-Staff Bonus": {}
                         }
-                    }, 
+                    },
                     "Accrued Expenses": {
                         "Accrued Other Expenses": {
-                            "Accrued - Audit Fees": {}, 
-                            "Accrued - Office Rent": {}, 
-                            "Accrued - Sponsorship": {}, 
-                            "Accrued - Telephone": {}, 
-                            "Accrued - Utilities": {}, 
+                            "Accrued - Audit Fees": {},
+                            "Accrued - Office Rent": {},
+                            "Accrued - Sponsorship": {},
+                            "Accrued - Telephone": {},
+                            "Accrued - Utilities": {},
                             "Accrued Others": {}
                         }
-                    }, 
+                    },
                     "Other Current Liabilities": {
-                        "Accrued Dubai Customs": {}, 
-                        "Deferred income": {}, 
+                        "Accrued Dubai Customs": {},
+                        "Deferred income": {},
                         "Shipping & Handling": {}
-                    }, 
+                    },
                     "Provisions": {
                         "Tax Payables": {
-                            "Income Tax Payable": {}, 
-                            "Sales Tax Payable": {}, 
+                            "Income Tax Payable": {},
+                            "Sales Tax Payable": {},
                             "Withholding Tax Payable": {}
                         }
-                    }, 
+                    },
                     "Short Term Loan": {}
-                }, 
+                },
                 "Duties and Taxes": {
-                    "account_type": "Tax", 
+                    "account_type": "Tax",
                     "is_group": 1
-                }, 
+                },
                 "Reservations & Credit Notes": {
                     "Credit Notes": {
-                        "Credit Notes to Customers": {}, 
+                        "Credit Notes to Customers": {},
                         "Reservations": {}
                     }
-                }, 
+                },
                 "Stock Liabilities": {
                     "Stock Received But Not Billed": {
                         "account_type": "Stock Received But Not Billed"
                     }
-                }, 
+                },
                 "Unearned Income": {}
-            }, 
+            },
             "Long Term Liabilities": {
                 "Long Term Loans & Provisions": {}
-            }, 
+            },
             "root_type": "Liability"
-        }, 
+        },
         "Revenue": {
             "Direct Revenue": {
                 "Other Direct Revenue": {
                     "Other Revenue - Operating": {
-                        "Advertising Income": {}, 
-                        "Branding Income": {}, 
-                        "Early Setmt Margin from Suppliers": {}, 
-                        "Marketing Rebate from Suppliers": {}, 
-                        "Rebate from Suppliers": {}, 
-                        "Service Income": {}, 
+                        "Advertising Income": {},
+                        "Branding Income": {},
+                        "Early Setmt Margin from Suppliers": {},
+                        "Marketing Rebate from Suppliers": {},
+                        "Rebate from Suppliers": {},
+                        "Service Income": {},
                         "Space Rental Income": {}
                     }
                 }
-            }, 
+            },
             "Indirect Revenue": {
                 "Other Indirect Revenue": {
-                    "Capital Gain": {}, 
-                    "Excess In Till": {}, 
-                    "Gain On Difference Of Exchange": {}, 
-                    "Management Consultancy Fees": {}, 
+                    "Capital Gain": {},
+                    "Excess In Till": {},
+                    "Gain On Difference Of Exchange": {},
+                    "Management Consultancy Fees": {},
                     "Other Income": {}
-                }, 
+                },
                 "Other Revenue - Non Operating": {
-                    "Interest Revenue": {}, 
-                    "Interest from FD": {}, 
-                    "Products Listing Fees from Suppliers": {}, 
+                    "Interest Revenue": {},
+                    "Interest from FD": {},
+                    "Products Listing Fees from Suppliers": {},
                     "Trade Opening Fees from suppliers": {}
                 }
-            }, 
+            },
             "Sales": {
                 "Sales from Other Regions": {
                     "Sales from Other Region": {}
-                }, 
+                },
                 "Sales of same region": {
-                    "Management Consultancy Fees 1": {}, 
-                    "Sales Account": {}, 
+                    "Management Consultancy Fees 1": {},
+                    "Sales Account": {},
                     "Sales of I/C": {}
                 }
-            }, 
+            },
             "root_type": "Income"
-        }, 
+        },
         "Share Holder Equity": {
             "Capital": {
-                "Contributed Capital": {}, 
-                "Share Capital": {}, 
-                "Shareholders Current A/c": {}, 
-                "Sub Ordinated Loan": {}, 
+                "Contributed Capital": {},
+                "Share Capital": {},
+                "Shareholders Current A/c": {},
+                "Sub Ordinated Loan": {},
                 "Treasury Stocks": {}
-            }, 
+            },
             "Retained Earnings": {
-                "Current Year Results": {}, 
-                "Dividends Paid": {}, 
+                "Current Year Results": {},
+                "Dividends Paid": {},
                 "Previous Years Results": {}
-            }, 
-            "account_type": "Equity", 
+            },
+            "account_type": "Equity",
             "root_type": "Equity"
         }
     }
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index 9bf5887..34070b0 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -185,7 +185,8 @@
 		return _("Please identify/create Account (Ledger) for type - {0}").format(' , '.join(missing))
 
 	account_types_for_group = ["Bank", "Cash", "Stock"]
-	account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group'] not in ('', 1)]
+	# fix logic bug
+	account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group'] == 1]
 
 	missing = list(set(account_types_for_group) - set(account_groups))
 	if missing:
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.py b/erpnext/accounts/doctype/cost_center/cost_center.py
index 584e11c..0294e78 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.py
+++ b/erpnext/accounts/doctype/cost_center/cost_center.py
@@ -18,6 +18,7 @@
 
 	def validate(self):
 		self.validate_mandatory()
+		self.validate_parent_cost_center()
 
 	def validate_mandatory(self):
 		if self.cost_center_name != self.company and not self.parent_cost_center:
@@ -25,6 +26,12 @@
 		elif self.cost_center_name == self.company and self.parent_cost_center:
 			frappe.throw(_("Root cannot have a parent cost center"))
 
+	def validate_parent_cost_center(self):
+		if self.parent_cost_center:
+			if not frappe.db.get_value('Cost Center', self.parent_cost_center, 'is_group'):
+				frappe.throw(_("{0} is not a group node. Please select a group node as parent cost center").format(
+					frappe.bold(self.parent_cost_center)))
+
 	def convert_group_to_ledger(self):
 		if self.check_if_child_exists():
 			frappe.throw(_("Cannot convert Cost Center to ledger as it has child nodes"))
diff --git a/erpnext/accounts/doctype/cost_center/test_cost_center.py b/erpnext/accounts/doctype/cost_center/test_cost_center.py
index c4fad75..8f23d90 100644
--- a/erpnext/accounts/doctype/cost_center/test_cost_center.py
+++ b/erpnext/accounts/doctype/cost_center/test_cost_center.py
@@ -1,12 +1,26 @@
 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 # License: GNU General Public License v3. See license.txt
 from __future__ import unicode_literals
-
-
+import unittest
 import frappe
+
 test_records = frappe.get_test_records('Cost Center')
 
+class TestCostCenter(unittest.TestCase):
+	def test_cost_center_creation_against_child_node(self):
 
+		if not frappe.db.get_value('Cost Center', {'name': '_Test Cost Center 2 - _TC'}):
+			frappe.get_doc(test_records[1]).insert()
+
+		cost_center = frappe.get_doc({
+			'doctype': 'Cost Center',
+			'cost_center_name': '_Test Cost Center 3',
+			'parent_cost_center': '_Test Cost Center 2 - _TC',
+			'is_group': 0,
+			'company': '_Test Company'
+		})
+
+		self.assertRaises(frappe.ValidationError, cost_center.save)
 
 def create_cost_center(**args):
 	args = frappe._dict(args)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index e4e2c7b..d7e64cf 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -330,23 +330,6 @@
 			frm: cur_frm
 		})
 	},
-
-	item_code: function(frm, cdt, cdn) {
-		var row = locals[cdt][cdn];
-		if(row.item_code) {
-			frappe.call({
-				method: "erpnext.assets.doctype.asset_category.asset_category.get_asset_category_account",
-				args: {
-					"item": row.item_code,
-					"fieldname": "fixed_asset_account",
-					"company": frm.doc.company
-				},
-				callback: function(r, rt) {
-					frappe.model.set_value(cdt, cdn, "expense_account", r.message);
-				}
-			})
-		}
-	}
 });
 
 cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 3c85210..2ea74f6 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -789,22 +789,21 @@
 					method: "frappe.client.get_value",
 					args:{
 						doctype: "Patient",
-						filters: {"name": frm.doc.patient},
+						filters: {
+							"name": frm.doc.patient
+						},
 						fieldname: "customer"
 					},
-					callback:function(patient_customer) {
-						if(patient_customer){
-							frm.set_value("customer", patient_customer.message.customer);
-							frm.refresh_fields();
+					callback:function(r) {
+						if(r && r.message.customer){
+							frm.set_value("customer", r.message.customer);
 						}
 					}
 				});
 			}
-			else{
-					frm.set_value("customer", '');
-			}
 		}
 	},
+
 	refresh: function(frm) {
 		if (frappe.boot.active_domains.includes("Healthcare")){
 			frm.set_df_property("patient", "hidden", 0);
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 70a80ca..def671c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1048,13 +1048,18 @@
 				continue
 
 			for serial_no in item.serial_no.split("\n"):
-				sales_invoice, item_code = frappe.db.get_value("Serial No", serial_no,
-					["sales_invoice", "item_code"])
-				if sales_invoice and item_code == item.item_code and self.name != sales_invoice:
-					sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company")
+				serial_no_details = frappe.db.get_value("Serial No", serial_no,
+					["sales_invoice", "item_code"], as_dict=1)
+
+				if not serial_no_details:
+					continue
+
+				if serial_no_details.sales_invoice and serial_no_details.item_code == item.item_code \
+					and self.name != serial_no_details.sales_invoice:
+					sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company")
 					if sales_invoice_company == self.company:
 						frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
-							.format(serial_no, sales_invoice)))
+							.format(serial_no, serial_no_details.sales_invoice)))
 
 	def update_project(self):
 		if self.project:
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index 8eb670de..b1f427c 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -101,6 +101,11 @@
 			"options": "Supplier Group"
 		},
 		{
+			"fieldname":"based_on_payment_terms",
+			"label": __("Based On Payment Terms"),
+			"fieldtype": "Check",
+		},
+		{
 			"fieldname":"tax_id",
 			"label": __("Tax Id"),
 			"fieldtype": "Data",
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 14906f2..41989bf 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -318,7 +318,7 @@
 			self.append_payment_term(row, d, term)
 
 	def append_payment_term(self, row, d, term):
-		if self.filters.get("customer") and d.currency == d.party_account_currency:
+		if (self.filters.get("customer") or self.filters.get("supplier")) and d.currency == d.party_account_currency:
 			invoiced = d.payment_amount
 		else:
 			invoiced = flt(flt(d.payment_amount) * flt(d.conversion_rate), self.currency_precision)
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 94697be..89c8467 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -569,7 +569,7 @@
 
 	warehouse_account = get_warehouse_account_map(company)
 
-	account_balance = get_balance_on(account, posting_date, in_account_currency=False)
+	account_balance = get_balance_on(account, posting_date, in_account_currency=False, ignore_account_permission=True)
 
 	related_warehouses = [wh for wh, wh_details in warehouse_account.items()
 		if wh_details.account == account and not wh_details.is_group]
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 40f1e1e..d32f834 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -517,15 +517,18 @@
 			asset.set_status('Out of Order')
 
 def make_post_gl_entry():
-	if not is_cwip_accounting_enabled(self.asset_category):
-		return
 
-	assets = frappe.db.sql_list(""" select name from `tabAsset`
-		where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
+	asset_categories = frappe.db.get_all('Asset Category', fields = ['name', 'enable_cwip_accounting'])
 
-	for asset in assets:
-		doc = frappe.get_doc('Asset', asset)
-		doc.make_gl_entries()
+	for asset_category in asset_categories:
+		if cint(asset_category.enable_cwip_accounting):
+			assets = frappe.db.sql_list(""" select name from `tabAsset`
+				where asset_category = %s and ifnull(booked_fixed_asset, 0) = 0
+				and available_for_use_date = %s""", (asset_category.name, nowdate()))
+
+			for asset in assets:
+				doc = frappe.get_doc('Asset', asset)
+				doc.make_gl_entries()
 
 def get_asset_naming_series():
 	meta = frappe.get_meta('Asset')
diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 2a42894..fc08841 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -29,7 +29,8 @@
 				account=None
 
 		if not account:
-			asset_category, company = frappe.db.get_value("Asset", asset, ["asset_category", "company"])
+			asset_details = frappe.db.get_value("Asset", asset, ["asset_category", "company"])
+			asset_category, company = asset_details or [None, None]
 
 	account = frappe.db.get_value("Asset Category Account",
 		filters={"parent": asset_category, "company_name": company}, fieldname=fieldname)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index c5fa98d..7b5e5c5 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -18,6 +18,7 @@
 			return {
 				filters: {
 					"company": frm.doc.company,
+					"name": ['!=', frm.doc.supplier_warehouse],
 					"is_group": 0
 				}
 			}
@@ -283,6 +284,8 @@
 			})
 		}
 
+		me.dialog.get_field('sub_con_rm_items').check_all_rows()
+
 		me.dialog.show()
 		this.dialog.set_primary_action(__('Transfer'), function() {
 			me.values = me.dialog.get_values();
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 4506db6..a0a1e8e 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -519,47 +519,62 @@
 	def test_backflush_based_on_stock_entry(self):
 		item_code = "_Test Subcontracted FG Item 1"
 		make_subcontracted_item(item_code)
+		make_item('Sub Contracted Raw Material 1', {
+			'is_stock_item': 1,
+			'is_sub_contracted_item': 1
+		})
 
 		update_backflush_based_on("Material Transferred for Subcontract")
-		po = create_purchase_order(item_code=item_code, qty=1,
+
+		order_qty = 5
+		po = create_purchase_order(item_code=item_code, qty=order_qty,
 			is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
 
-		make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
 		make_stock_entry(target="_Test Warehouse - _TC",
 			item_code="_Test Item Home Desktop 100", qty=10, basic_rate=100)
 		make_stock_entry(target="_Test Warehouse - _TC",
 			item_code = "Test Extra Item 1", qty=100, basic_rate=100)
 		make_stock_entry(target="_Test Warehouse - _TC",
 			item_code = "Test Extra Item 2", qty=10, basic_rate=100)
+		make_stock_entry(target="_Test Warehouse - _TC",
+			item_code = "Sub Contracted Raw Material 1", qty=10, basic_rate=100)
 
-		rm_item = [
-			{"item_code":item_code,"rm_item_code":"_Test Item","item_name":"_Test Item",
-				"qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":100,"stock_uom":"Nos"},
+		rm_items = [
+			{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 1","item_name":"_Test Item",
+				"qty":10,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
 			{"item_code":item_code,"rm_item_code":"_Test Item Home Desktop 100","item_name":"_Test Item Home Desktop 100",
-				"qty":2,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"},
+				"qty":20,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
 			{"item_code":item_code,"rm_item_code":"Test Extra Item 1","item_name":"Test Extra Item 1",
-				"qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"}]
+				"qty":10,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
+			{'item_code': item_code, 'rm_item_code': 'Test Extra Item 2', 'stock_uom':'Nos',
+				'qty': 10, 'warehouse': '_Test Warehouse - _TC', 'item_name':'Test Extra Item 2'}]
 
-		rm_item_string = json.dumps(rm_item)
+		rm_item_string = json.dumps(rm_items)
 		se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
-		se.append('items', {
-			'item_code': "Test Extra Item 2",
-			"qty": 1,
-			"rate": 100,
-			"s_warehouse": "_Test Warehouse - _TC",
-			"t_warehouse": "_Test Warehouse 1 - _TC"
-		})
-		se.set_missing_values()
 		se.submit()
 
 		pr = make_purchase_receipt(po.name)
+
+		received_qty = 2
+		# partial receipt
+		pr.get('items')[0].qty = received_qty
 		pr.save()
 		pr.submit()
 
-		se_items = sorted([d.item_code for d in se.get('items')])
-		supplied_items = sorted([d.rm_item_code for d in pr.get('supplied_items')])
+		transferred_items = sorted([d.item_code for d in se.get('items') if se.purchase_order == po.name])
+		issued_items = sorted([d.rm_item_code for d in pr.get('supplied_items')])
 
-		self.assertEquals(se_items, supplied_items)
+		self.assertEquals(transferred_items, issued_items)
+		self.assertEquals(pr.get('items')[0].rm_supp_cost, 2000)
+
+
+		transferred_rm_map = frappe._dict()
+		for item in rm_items:
+			transferred_rm_map[item.get('rm_item_code')] = item
+
+		for item in pr.get('supplied_items'):
+			self.assertEqual(item.get('required_qty'), (transferred_rm_map[item.get('rm_item_code')].get('qty') / order_qty) * received_qty)
+
 		update_backflush_based_on("BOM")
 
 	def test_advance_payment_entry_unlink_against_purchase_order(self):
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index ab75f21..08711fc 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -197,6 +197,11 @@
 					"name": "Bank Reconciliation Statement",
 					"is_query_report": True,
 					"doctype": "Journal Entry"
+				},{
+					"type": "page",
+					"name": "bank-reconciliation",
+					"label": _("Bank Reconciliation"),
+					"icon": "fa fa-bar-chart"
 				},
 				{
 					"type": "report",
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index d12643a..3ec7aff 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -221,7 +221,7 @@
 				"backflush_raw_materials_of_subcontract_based_on")
 			if (self.doctype == 'Purchase Receipt' and
 				backflush_raw_materials_based_on != 'BOM'):
-				self.update_raw_materials_supplied_based_on_stock_entries(raw_material_table)
+				self.update_raw_materials_supplied_based_on_stock_entries()
 			else:
 				for item in self.get("items"):
 					if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
@@ -241,41 +241,95 @@
 		if self.is_subcontracted == "No" and self.get("supplied_items"):
 			self.set('supplied_items', [])
 
-	def update_raw_materials_supplied_based_on_stock_entries(self, raw_material_table):
-		self.set(raw_material_table, [])
-		purchase_orders = [d.purchase_order for d in self.items]
-		if purchase_orders:
-			items = get_subcontracted_raw_materials_from_se(purchase_orders)
-			backflushed_raw_materials = get_backflushed_subcontracted_raw_materials_from_se(purchase_orders, self.name)
+	def update_raw_materials_supplied_based_on_stock_entries(self):
+		self.set('supplied_items', [])
 
-			for d in items:
-				qty = d.qty - backflushed_raw_materials.get(d.item_code, 0)
-				rm = self.append(raw_material_table, {})
-				rm.rm_item_code = d.item_code
-				rm.item_name = d.item_name
-				rm.main_item_code = d.main_item_code
-				rm.description = d.description
-				rm.stock_uom = d.stock_uom
-				rm.required_qty = qty
-				rm.consumed_qty = qty
-				rm.serial_no = d.serial_no
-				rm.batch_no = d.batch_no
+		purchase_orders = set([d.purchase_order for d in self.items])
 
-				# get raw materials rate
-				from erpnext.stock.utils import get_incoming_rate
-				rm.rate = get_incoming_rate({
-					"item_code": d.item_code,
-					"warehouse": self.supplier_warehouse,
-					"posting_date": self.posting_date,
-					"posting_time": self.posting_time,
-					"qty": -1 * qty,
-					"serial_no": rm.serial_no
-				})
-				if not rm.rate:
-					rm.rate = get_valuation_rate(d.item_code, self.supplier_warehouse,
-						self.doctype, self.name, currency=self.company_currency, company = self.company)
+		# qty of raw materials backflushed (for each item per purchase order)
+		backflushed_raw_materials_map = get_backflushed_subcontracted_raw_materials(purchase_orders)
 
-				rm.amount = qty * flt(rm.rate)
+		# qty of "finished good" item yet to be received
+		qty_to_be_received_map = get_qty_to_be_received(purchase_orders)
+
+		for item in self.get('items'):
+			# reset raw_material cost
+			item.rm_supp_cost = 0
+
+			# qty of raw materials transferred to the supplier
+			transferred_raw_materials = get_subcontracted_raw_materials_from_se(item.purchase_order, item.item_code)
+
+			non_stock_items = get_non_stock_items(item.purchase_order, item.item_code)
+
+			item_key = '{}{}'.format(item.item_code, item.purchase_order)
+
+			fg_yet_to_be_received = qty_to_be_received_map.get(item_key)
+
+			raw_material_data = backflushed_raw_materials_map.get(item_key, {})
+
+			consumed_qty = raw_material_data.get('qty', 0)
+			consumed_serial_nos = raw_material_data.get('serial_nos', '')
+			consumed_batch_nos = raw_material_data.get('batch_nos', '')
+
+			transferred_batch_qty_map = get_transferred_batch_qty_map(item.purchase_order, item.item_code)
+			backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
+
+			for raw_material in transferred_raw_materials + non_stock_items:
+				transferred_qty = raw_material.qty
+
+				rm_qty_to_be_consumed = transferred_qty - consumed_qty
+
+				# backflush all remaining transferred qty in the last Purchase Receipt
+				if fg_yet_to_be_received == item.qty:
+					qty = rm_qty_to_be_consumed
+				else:
+					qty = (rm_qty_to_be_consumed / fg_yet_to_be_received) * item.qty
+
+					if frappe.get_cached_value('UOM', raw_material.stock_uom, 'must_be_whole_number'):
+						qty = frappe.utils.ceil(qty)
+
+				if qty > rm_qty_to_be_consumed:
+					qty = rm_qty_to_be_consumed
+
+				if not qty: continue
+
+				if raw_material.serial_nos:
+					set_serial_nos(raw_material, consumed_serial_nos, qty)
+
+				if raw_material.batch_nos:
+					batches_qty = get_batches_with_qty(raw_material.rm_item_code, raw_material.main_item_code,
+						qty, transferred_batch_qty_map, backflushed_batch_qty_map)
+					for batch_data in batches_qty:
+						qty = batch_data['qty']
+						raw_material.batch_no = batch_data['batch']
+						self.append_raw_material_to_be_backflushed(item, raw_material, qty)
+				else:
+					self.append_raw_material_to_be_backflushed(item, raw_material, qty)
+
+	def append_raw_material_to_be_backflushed(self, fg_item_doc, raw_material_data, qty):
+		rm = self.append('supplied_items', {})
+		rm.update(raw_material_data)
+
+		rm.required_qty = qty
+		rm.consumed_qty = qty
+
+		if not raw_material_data.get('non_stock_item'):
+			from erpnext.stock.utils import get_incoming_rate
+			rm.rate = get_incoming_rate({
+				"item_code": raw_material_data.rm_item_code,
+				"warehouse": self.supplier_warehouse,
+				"posting_date": self.posting_date,
+				"posting_time": self.posting_time,
+				"qty": -1 * qty,
+				"serial_no": rm.serial_no
+			})
+
+			if not rm.rate:
+				rm.rate = get_valuation_rate(raw_material_data.item_code, self.supplier_warehouse,
+					self.doctype, self.name, currency=self.company_currency, company=self.company)
+
+		rm.amount = qty * flt(rm.rate)
+		fg_item_doc.rm_supp_cost += rm.amount
 
 	def update_raw_materials_supplied_based_on_bom(self, item, raw_material_table):
 		exploded_item = 1
@@ -387,9 +441,11 @@
 			item_codes = list(set(item.item_code for item in
 				self.get("items")))
 			if item_codes:
-				self._sub_contracted_items = [r[0] for r in frappe.db.sql("""select name
-					from `tabItem` where name in (%s) and is_sub_contracted_item=1""" % \
-					(", ".join((["%s"]*len(item_codes))),), item_codes)]
+				items = frappe.get_all('Item', filters={
+					'name': ['in', item_codes],
+					'is_sub_contracted_item': 1
+				})
+				self._sub_contracted_items = [item.name for item in items]
 
 		return self._sub_contracted_items
 
@@ -722,28 +778,72 @@
 
 	return bom_items
 
-def get_subcontracted_raw_materials_from_se(purchase_orders):
-	return frappe.db.sql("""
-		select
-			sed.item_name, sed.item_code, sum(sed.qty) as qty, sed.description,
-			sed.stock_uom, sed.subcontracted_item as main_item_code, sed.serial_no, sed.batch_no
-		from `tabStock Entry` se,`tabStock Entry Detail` sed
-		where
-			se.name = sed.parent and se.docstatus=1 and se.purpose='Send to Subcontractor'
-			and se.purchase_order in (%s) and ifnull(sed.t_warehouse, '') != ''
-		group by sed.item_code, sed.t_warehouse
-	""" % (','.join(['%s'] * len(purchase_orders))), tuple(purchase_orders), as_dict=1)
+def get_subcontracted_raw_materials_from_se(purchase_order, fg_item):
+	common_query = """
+		SELECT
+			sed.item_code AS rm_item_code,
+			SUM(sed.qty) AS qty,
+			sed.description,
+			sed.stock_uom,
+			sed.subcontracted_item AS main_item_code,
+			{serial_no_concat_syntax} AS serial_nos,
+			{batch_no_concat_syntax} AS batch_nos
+		FROM `tabStock Entry` se,`tabStock Entry Detail` sed
+		WHERE
+			se.name = sed.parent
+			AND se.docstatus=1
+			AND se.purpose='Send to Subcontractor'
+			AND se.purchase_order = %s
+			AND IFNULL(sed.t_warehouse, '') != ''
+			AND sed.subcontracted_item = %s
+		GROUP BY sed.item_code, sed.subcontracted_item
+	"""
+	raw_materials = frappe.db.multisql({
+		'mariadb': common_query.format(
+			serial_no_concat_syntax="GROUP_CONCAT(sed.serial_no)",
+			batch_no_concat_syntax="GROUP_CONCAT(sed.batch_no)"
+		),
+		'postgres': common_query.format(
+			serial_no_concat_syntax="STRING_AGG(sed.serial_no, ',')",
+			batch_no_concat_syntax="STRING_AGG(sed.batch_no, ',')"
+		)
+	}, (purchase_order, fg_item), as_dict=1)
 
-def get_backflushed_subcontracted_raw_materials_from_se(purchase_orders, purchase_receipt):
-	return frappe._dict(frappe.db.sql("""
-		select
-			prsi.rm_item_code as item_code, sum(prsi.consumed_qty) as qty
-		from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` prsi
-		where
-			pr.name = pri.parent and pr.name = prsi.parent and pri.purchase_order in (%s)
-			and pri.item_code = prsi.main_item_code and pr.name != '%s' and pr.docstatus = 1
-		group by prsi.rm_item_code
-	""" % (','.join(['%s'] * len(purchase_orders)), purchase_receipt), tuple(purchase_orders)))
+	return raw_materials
+
+def get_backflushed_subcontracted_raw_materials(purchase_orders):
+	common_query = """
+		SELECT
+			CONCAT(prsi.rm_item_code, pri.purchase_order) AS item_key,
+			SUM(prsi.consumed_qty) AS qty,
+			{serial_no_concat_syntax} AS serial_nos,
+			{batch_no_concat_syntax} AS batch_nos
+		FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` prsi
+		WHERE
+			pr.name = pri.parent
+			AND pr.name = prsi.parent
+			AND pri.purchase_order IN %s
+			AND pri.item_code = prsi.main_item_code
+			AND pr.docstatus = 1
+		GROUP BY prsi.rm_item_code, pri.purchase_order
+	"""
+
+	backflushed_raw_materials = frappe.db.multisql({
+		'mariadb': common_query.format(
+			serial_no_concat_syntax="GROUP_CONCAT(prsi.serial_no)",
+			batch_no_concat_syntax="GROUP_CONCAT(prsi.batch_no)"
+		),
+		'postgres': common_query.format(
+			serial_no_concat_syntax="STRING_AGG(prsi.serial_no, ',')",
+			batch_no_concat_syntax="STRING_AGG(prsi.batch_no, ',')"
+		)
+	}, (purchase_orders, ), as_dict=1)
+
+	backflushed_raw_materials_map = frappe._dict()
+	for item in backflushed_raw_materials:
+		backflushed_raw_materials_map.setdefault(item.item_key, item)
+
+	return backflushed_raw_materials_map
 
 def get_asset_item_details(asset_items):
 	asset_items_data = {}
@@ -776,3 +876,125 @@
 			error_message = _("Following item {0} is not marked as {1} item. You can enable them as {1} item from its Item master".format(items, message))
 
 		frappe.throw(error_message)
+
+def get_qty_to_be_received(purchase_orders):
+	return frappe._dict(frappe.db.sql("""
+		SELECT CONCAT(poi.`item_code`, poi.`parent`) AS item_key,
+		SUM(poi.`qty`) - SUM(poi.`received_qty`) AS qty_to_be_received
+		FROM `tabPurchase Order Item` poi
+		WHERE
+			poi.`parent` in %s
+		GROUP BY poi.`item_code`, poi.`parent`
+		HAVING SUM(poi.`qty`) > SUM(poi.`received_qty`)
+	""", (purchase_orders)))
+
+def get_non_stock_items(purchase_order, fg_item_code):
+	return frappe.db.sql("""
+		SELECT
+			pois.main_item_code,
+			pois.rm_item_code,
+			item.description,
+			pois.required_qty AS qty,
+			pois.rate,
+			1 as non_stock_item,
+			pois.stock_uom
+		FROM `tabPurchase Order Item Supplied` pois, `tabItem` item
+		WHERE
+			pois.`rm_item_code` = item.`name`
+			AND item.is_stock_item = 0
+			AND pois.`parent` = %s
+			AND pois.`main_item_code` = %s
+	""", (purchase_order, fg_item_code), as_dict=1)
+
+
+def set_serial_nos(raw_material, consumed_serial_nos, qty):
+	serial_nos = set(get_serial_nos(raw_material.serial_nos)) - \
+		set(get_serial_nos(consumed_serial_nos))
+	if serial_nos and qty <= len(serial_nos):
+		raw_material.serial_no = '\n'.join(list(serial_nos)[0:frappe.utils.cint(qty)])
+
+def get_transferred_batch_qty_map(purchase_order, fg_item):
+	# returns
+	# {
+	# 	(item_code, fg_code): {
+	# 		batch1: 10, # qty
+	# 		batch2: 16
+	# 	},
+	# }
+	transferred_batch_qty_map = {}
+	transferred_batches = frappe.db.sql("""
+		SELECT
+			sed.batch_no,
+			SUM(sed.qty) AS qty,
+			sed.item_code
+		FROM `tabStock Entry` se,`tabStock Entry Detail` sed
+		WHERE
+			se.name = sed.parent
+			AND se.docstatus=1
+			AND se.purpose='Send to Subcontractor'
+			AND se.purchase_order = %s
+			AND sed.subcontracted_item = %s
+			AND sed.batch_no IS NOT NULL
+		GROUP BY
+			sed.batch_no,
+			sed.item_code
+	""", (purchase_order, fg_item), as_dict=1)
+
+	for batch_data in transferred_batches:
+		transferred_batch_qty_map.setdefault((batch_data.item_code, fg_item), {})
+		transferred_batch_qty_map[(batch_data.item_code, fg_item)][batch_data.batch_no] = batch_data.qty
+
+	return transferred_batch_qty_map
+
+def get_backflushed_batch_qty_map(purchase_order, fg_item):
+	# returns
+	# {
+	# 	(item_code, fg_code): {
+	# 		batch1: 10, # qty
+	# 		batch2: 16
+	# 	},
+	# }
+	backflushed_batch_qty_map = {}
+	backflushed_batches = frappe.db.sql("""
+		SELECT
+			pris.batch_no,
+			SUM(pris.consumed_qty) AS qty,
+			pris.rm_item_code AS item_code
+		FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` pris
+		WHERE
+			pr.name = pri.parent
+			AND pri.parent = pris.parent
+			AND pri.purchase_order = %s
+			AND pri.item_code = pris.main_item_code
+			AND pr.docstatus = 1
+			AND pris.main_item_code = %s
+			AND pris.batch_no IS NOT NULL
+		GROUP BY
+			pris.rm_item_code, pris.batch_no
+	""", (purchase_order, fg_item), as_dict=1)
+
+	for batch_data in backflushed_batches:
+		backflushed_batch_qty_map.setdefault((batch_data.item_code, fg_item), {})
+		backflushed_batch_qty_map[(batch_data.item_code, fg_item)][batch_data.batch_no] = batch_data.qty
+
+	return backflushed_batch_qty_map
+
+def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty_map, backflushed_batch_qty_map):
+	# Returns available batches to be backflushed based on requirements
+	transferred_batches = transferred_batch_qty_map.get((item_code, fg_item), {})
+	backflushed_batches = backflushed_batch_qty_map.get((item_code, fg_item), {})
+
+	available_batches = []
+
+	for (batch, transferred_qty) in transferred_batches.items():
+		backflushed_qty = backflushed_batches.get(batch, 0)
+		available_qty = transferred_qty - backflushed_qty
+
+		if available_qty >= required_qty:
+			available_batches.append({'batch': batch, 'qty': required_qty})
+			break
+		else:
+			available_batches.append({'batch': batch, 'qty': available_qty})
+			required_qty -= available_qty
+
+	return available_batches
\ No newline at end of file
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py
index d5348ff..7536172 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py
@@ -71,7 +71,7 @@
 	def create_course_enrollments(self):
 		student = frappe.get_doc("Student", self.student)
 		program = frappe.get_doc("Program", self.program)
-		course_list = [course.course for course in program.get_all_children()]
+		course_list = [course.course for course in program.courses]
 		for course_name in course_list:
 			student.enroll_in_course(course_name=course_name, program_enrollment=self.name)
 
diff --git a/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json b/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json
index a116185..5bb2d37 100644
--- a/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json
+++ b/erpnext/hr/doctype/repayment_schedule/repayment_schedule.json
@@ -1,231 +1,82 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2016-12-20 15:32:25.078334", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "creation": "2016-12-20 15:32:25.078334",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "payment_date",
+  "principal_amount",
+  "interest_amount",
+  "total_payment",
+  "balance_loan_amount",
+  "paid"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "payment_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": "Payment Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "allow_on_submit": 1,
+   "columns": 2,
+   "fieldname": "payment_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Payment Date"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "principal_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Principal Amount", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Company:company:default_currency", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "principal_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Principal Amount",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "interest_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Interest Amount", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Company:company:default_currency", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "interest_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Interest Amount",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "total_payment", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Total Payment", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company:company:default_currency", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "total_payment",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Total Payment",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "balance_loan_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Balance Loan Amount", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Company:company:default_currency", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "balance_loan_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Balance Loan Amount",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "paid", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Paid", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "default": "0",
+   "fieldname": "paid",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Paid",
+   "read_only": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-03-30 17:37:31.834792", 
- "modified_by": "Administrator", 
- "module": "HR", 
- "name": "Repayment Schedule", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "istable": 1,
+ "modified": "2019-10-29 11:45:10.694557",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Repayment Schedule",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index 2ca4d16..31a9fdb 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -9,6 +9,7 @@
 from six import string_types
 from erpnext.manufacturing.doctype.bom.bom import get_boms_in_bottom_up_order
 from frappe.model.document import Document
+import click
 
 class BOMUpdateTool(Document):
 	def replace_bom(self):
@@ -17,7 +18,8 @@
 		frappe.cache().delete_key('bom_children')
 		bom_list = self.get_parent_boms(self.new_bom)
 		updated_bom = []
-
+		with click.progressbar(bom_list) as bom_list:
+			pass
 		for bom in bom_list:
 			try:
 				bom_obj = frappe.get_cached_doc('BOM', bom)
diff --git a/erpnext/manufacturing/report/bom_explorer/bom_explorer.py b/erpnext/manufacturing/report/bom_explorer/bom_explorer.py
index 875d115..48907ad 100644
--- a/erpnext/manufacturing/report/bom_explorer/bom_explorer.py
+++ b/erpnext/manufacturing/report/bom_explorer/bom_explorer.py
@@ -14,7 +14,7 @@
 def get_data(filters, data):
 	get_exploded_items(filters.bom, data)
 
-def get_exploded_items(bom, data, indent=0):
+def get_exploded_items(bom, data, indent=0, qty=1):
 	exploded_items = frappe.get_all("BOM Item",
 		filters={"parent": bom},
 		fields= ['qty','bom_no','qty','scrap','item_code','item_name','description','uom'])
@@ -26,13 +26,13 @@
 			'item_name': item.item_name,
 			'indent': indent,
 			'bom': item.bom_no,
-			'qty': item.qty,
+			'qty': item.qty * qty,
 			'uom': item.uom,
 			'description': item.description,
 			'scrap': item.scrap
 			})
 		if item.bom_no:
-			get_exploded_items(item.bom_no, data, indent=indent+1)
+			get_exploded_items(item.bom_no, data, indent=indent+1, qty=item.qty)
 
 def get_columns():
 	return [
diff --git a/erpnext/portal/doctype/homepage/test_homepage.py b/erpnext/portal/doctype/homepage/test_homepage.py
index b262c46..bf5c402 100644
--- a/erpnext/portal/doctype/homepage/test_homepage.py
+++ b/erpnext/portal/doctype/homepage/test_homepage.py
@@ -5,7 +5,7 @@
 
 import frappe
 import unittest
-from frappe.tests.test_website import set_request
+from frappe.utils import set_request
 from frappe.website.render import render
 
 class TestHomepage(unittest.TestCase):
diff --git a/erpnext/portal/doctype/homepage_section/test_homepage_section.py b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
index c52b7a9..5b3196d 100644
--- a/erpnext/portal/doctype/homepage_section/test_homepage_section.py
+++ b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
@@ -6,7 +6,7 @@
 import frappe
 import unittest
 from bs4 import BeautifulSoup
-from frappe.tests.test_website import set_request
+from frappe.utils import set_request
 from frappe.website.render import render
 
 class TestHomepageSection(unittest.TestCase):
diff --git a/erpnext/portal/product_configurator/test_product_configurator.py b/erpnext/portal/product_configurator/test_product_configurator.py
index a534e5f..97042db 100644
--- a/erpnext/portal/product_configurator/test_product_configurator.py
+++ b/erpnext/portal/product_configurator/test_product_configurator.py
@@ -2,7 +2,7 @@
 
 from bs4 import BeautifulSoup
 import frappe, unittest
-from frappe.tests.test_website import set_request, get_html_for_route
+from frappe.utils import set_request, get_html_for_route
 from frappe.website.render import render
 from erpnext.portal.product_configurator.utils import get_products_for_website
 from erpnext.stock.doctype.item.test_item import make_item_variant
diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js
index e7cc919..7ff4de4 100644
--- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js
+++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.js
@@ -3,6 +3,26 @@
 
 frappe.ui.form.on('GST HSN Code', {
 	refresh: function(frm) {
-
+		if(! frm.doc.__islocal && frm.doc.taxes.length){
+			frm.add_custom_button(__('Update Taxes for Items'), function(){
+				frappe.confirm(
+					'Are you sure? It will overwrite taxes for all items with HSN Code <b>'+frm.doc.name+'</b>.',
+					function(){
+						frappe.call({
+							args:{
+								taxes: frm.doc.taxes,
+								hsn_code: frm.doc.name
+							},
+							method: 'erpnext.regional.doctype.gst_hsn_code.gst_hsn_code.update_taxes_in_item_master',
+							callback: function(r) {
+								if(r.message){
+									frappe.show_alert(__('Item taxes updated'));
+								}
+							}
+						});
+					}
+				);
+			});
+		}
 	}
-});
+});
\ No newline at end of file
diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json
index 2a2145c..06dab37 100644
--- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json
+++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json
@@ -1,104 +1,46 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "field:hsn_code", 
- "beta": 0, 
- "creation": "2017-06-21 10:48:56.422086", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "autoname": "field:hsn_code",
+ "creation": "2017-06-21 10:48:56.422086",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "hsn_code",
+  "description",
+  "taxes"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "hsn_code", 
-   "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": "HSN Code", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "hsn_code",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "HSN Code",
+   "reqd": 1,
+   "unique": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Small Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "in_list_view": 1,
+   "label": "Description"
+  },
+  {
+   "fieldname": "taxes",
+   "fieldtype": "Table",
+   "label": "Taxes",
+   "options": "Item Tax"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2017-09-29 14:38:52.220743", 
- "modified_by": "Administrator", 
- "module": "Regional", 
- "name": "GST HSN Code", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "search_fields": "hsn_code, description", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "hsn_code", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "modified": "2019-11-01 11:18:59.556931",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "GST HSN Code",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "search_fields": "hsn_code, description",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "hsn_code",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py
index 9637c2e..fa2cb12 100644
--- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py
+++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.py
@@ -8,3 +8,22 @@
 
 class GSTHSNCode(Document):
 	pass
+
+@frappe.whitelist()
+def update_taxes_in_item_master(taxes, hsn_code):
+	items = frappe.get_list("Item", filters={
+		'gst_hsn_code': hsn_code
+	})
+
+	taxes = frappe.parse_json(taxes)
+	frappe.enqueue(update_item_document, items=items, taxes=taxes)
+	return 1
+
+def update_item_document(items, taxes):
+	for item in items:
+		item_to_be_updated=frappe.get_doc("Item", item.name)
+		item_to_be_updated.taxes = []
+		for tax in taxes:
+			tax = frappe._dict(tax)
+			item_to_be_updated.append("taxes", {'item_tax_template': tax.item_tax_template, 'tax_category': tax.tax_category})
+			item_to_be_updated.save()
\ No newline at end of file
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index ee8735f..bd70639 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -10,17 +10,26 @@
 from __future__ import unicode_literals
 import datetime
 import json
+import zlib
+import zipfile
+import six
+from six import BytesIO
 from six import string_types
 import frappe
 from frappe import _
 import pandas as pd
+from .datev_constants import DataCategory
+from .datev_constants import Transactions
+from .datev_constants import DebtorsCreditors
+from .datev_constants import AccountNames
+from .datev_constants import QUERY_REPORT_COLUMNS
 
 
 def execute(filters=None):
 	"""Entry point for frappe."""
 	validate(filters)
-	result = get_gl_entries(filters, as_dict=0)
-	columns = get_columns()
+	result = get_transactions(filters, as_dict=0)
+	columns = QUERY_REPORT_COLUMNS
 
 	return columns, result
 
@@ -41,65 +50,8 @@
 	except frappe.DoesNotExistError:
 		frappe.throw(_('Please create <b>DATEV Settings</b> for Company <b>{}</b>.').format(filters.get('company')))
 
-def get_columns():
-	"""Return the list of columns that will be shown in query report."""
-	columns = [
-		{
-			"label": "Umsatz (ohne Soll/Haben-Kz)",
-			"fieldname": "Umsatz (ohne Soll/Haben-Kz)",
-			"fieldtype": "Currency",
-		},
-		{
-			"label": "Soll/Haben-Kennzeichen",
-			"fieldname": "Soll/Haben-Kennzeichen",
-			"fieldtype": "Data",
-		},
-		{
-			"label": "Kontonummer",
-			"fieldname": "Kontonummer",
-			"fieldtype": "Data",
-		},
-		{
-			"label": "Gegenkonto (ohne BU-Schlüssel)",
-			"fieldname": "Gegenkonto (ohne BU-Schlüssel)",
-			"fieldtype": "Data",
-		},
-		{
-			"label": "Belegdatum",
-			"fieldname": "Belegdatum",
-			"fieldtype": "Date",
-		},
-		{
-			"label": "Buchungstext",
-			"fieldname": "Buchungstext",
-			"fieldtype": "Text",
-		},
-		{
-			"label": "Beleginfo - Art 1",
-			"fieldname": "Beleginfo - Art 1",
-			"fieldtype": "Data",
-		},
-		{
-			"label": "Beleginfo - Inhalt 1",
-			"fieldname": "Beleginfo - Inhalt 1",
-			"fieldtype": "Data",
-		},
-		{
-			"label": "Beleginfo - Art 2",
-			"fieldname": "Beleginfo - Art 2",
-			"fieldtype": "Data",
-		},
-		{
-			"label": "Beleginfo - Inhalt 2",
-			"fieldname": "Beleginfo - Inhalt 2",
-			"fieldtype": "Data",
-		}
-	]
 
-	return columns
-
-
-def get_gl_entries(filters, as_dict):
+def get_transactions(filters, as_dict=1):
 	"""
 	Get a list of accounting entries.
 
@@ -111,7 +63,7 @@
 	as_dict -- return as list of dicts [0,1]
 	"""
 	gl_entries = frappe.db.sql("""
-		select
+		SELECT
 
 			/* either debit or credit amount; always positive */
 			case gl.debit when 0 then gl.credit else gl.debit end as 'Umsatz (ohne Soll/Haben-Kz)',
@@ -132,7 +84,7 @@
 			gl.against_voucher_type as 'Beleginfo - Art 2',
 			gl.against_voucher as 'Beleginfo - Inhalt 2'
 
-		from `tabGL Entry` gl
+		FROM `tabGL Entry` gl
 
 			/* Statistisches Konto (Debitoren/Kreditoren) */
 			left join `tabParty Account` pa
@@ -155,15 +107,127 @@
 			left join `tabAccount` acc_against_pa 
 			on pa.account = acc_against_pa.name
 
-		where gl.company = %(company)s 
-		and DATE(gl.posting_date) >= %(from_date)s
-		and DATE(gl.posting_date) <= %(to_date)s
-		order by 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict)
+		WHERE gl.company = %(company)s 
+		AND DATE(gl.posting_date) >= %(from_date)s
+		AND DATE(gl.posting_date) <= %(to_date)s
+		ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1)
 
 	return gl_entries
 
 
-def get_datev_csv(data, filters):
+def get_customers(filters):
+	"""
+	Get a list of Customers.
+
+	Arguments:
+	filters -- dict of filters to be passed to the sql query
+	"""
+	return frappe.db.sql("""
+		SELECT
+
+			acc.account_number as 'Konto',
+			cus.customer_name as 'Name (Adressatentyp Unternehmen)',
+			case cus.customer_type when 'Individual' then 1 when 'Company' then 2 else 0 end as 'Adressatentyp',
+			adr.address_line1 as 'Straße',
+			adr.pincode as 'Postleitzahl',
+			adr.city as 'Ort',
+			UPPER(country.code) as 'Land',
+			adr.address_line2 as 'Adresszusatz',
+			con.email_id as 'E-Mail',
+			coalesce(con.mobile_no, con.phone) as 'Telefon',
+			cus.website as 'Internet',
+			cus.tax_id as 'Steuernummer',
+			ccl.credit_limit as 'Kreditlimit (Debitor)'
+
+		FROM `tabParty Account` par
+
+			left join `tabAccount` acc
+			on acc.name = par.account
+
+			left join `tabCustomer` cus
+			on cus.name = par.parent
+
+			left join `tabAddress` adr
+			on adr.name = cus.customer_primary_address
+
+			left join `tabCountry` country
+			on country.name = adr.country
+
+			left join `tabContact` con
+			on con.name = cus.customer_primary_contact
+
+			left join `tabCustomer Credit Limit` ccl
+			on ccl.parent = cus.name
+			and ccl.company = par.company
+
+		WHERE par.company = %(company)s
+		AND par.parenttype = 'Customer'""", filters, as_dict=1, as_utf8=1)
+
+
+def get_suppliers(filters):
+	"""
+	Get a list of Suppliers.
+
+	Arguments:
+	filters -- dict of filters to be passed to the sql query
+	"""
+	return frappe.db.sql("""
+		SELECT
+
+			acc.account_number as 'Konto',
+			sup.supplier_name as 'Name (Adressatentyp Unternehmen)',
+			case sup.supplier_type when 'Individual' then '1' when 'Company' then '2' else '0' end as 'Adressatentyp',
+			adr.address_line1 as 'Straße',
+			adr.pincode as 'Postleitzahl',
+			adr.city as 'Ort',
+			UPPER(country.code) as 'Land',
+			adr.address_line2 as 'Adresszusatz',
+			con.email_id as 'E-Mail',
+			coalesce(con.mobile_no, con.phone) as 'Telefon',
+			sup.website as 'Internet',
+			sup.tax_id as 'Steuernummer',
+			case sup.on_hold when 1 then sup.release_date else null end as 'Zahlungssperre bis'
+
+		FROM `tabParty Account` par
+
+			left join `tabAccount` acc
+			on acc.name = par.account
+
+			left join `tabSupplier` sup
+			on sup.name = par.parent
+
+			left join `tabDynamic Link` dyn_adr
+			on dyn_adr.link_name = sup.name
+			and dyn_adr.link_doctype = 'Supplier'
+			and dyn_adr.parenttype = 'Address'
+			
+			left join `tabAddress` adr
+			on adr.name = dyn_adr.parent
+			and adr.is_primary_address = '1'
+
+			left join `tabCountry` country
+			on country.name = adr.country
+
+			left join `tabDynamic Link` dyn_con
+			on dyn_con.link_name = sup.name
+			and dyn_con.link_doctype = 'Supplier'
+			and dyn_con.parenttype = 'Contact'
+
+			left join `tabContact` con
+			on con.name = dyn_con.parent
+			and con.is_primary_contact = '1'
+
+		WHERE par.company = %(company)s
+		AND par.parenttype = 'Supplier'""", filters, as_dict=1, as_utf8=1)
+
+
+def get_account_names(filters):
+	return frappe.get_list("Account", 
+		fields=["account_number as Konto", "name as Kontenbeschriftung"], 
+		filters={"company": filters.get("company"), "is_group": "0"})
+
+
+def get_datev_csv(data, filters, csv_class):
 	"""
 	Fill in missing columns and return a CSV in DATEV Format.
 
@@ -174,7 +238,46 @@
 	Arguments:
 	data -- array of dictionaries
 	filters -- dict
+	csv_class -- defines DATA_CATEGORY, FORMAT_NAME and COLUMNS
 	"""
+	header = get_header(filters, csv_class)
+
+	empty_df = pd.DataFrame(columns=csv_class.COLUMNS)
+	data_df = pd.DataFrame.from_records(data)
+
+	result = empty_df.append(data_df, sort=True)
+
+	if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS:
+		result['Belegdatum'] = pd.to_datetime(result['Belegdatum'])
+
+	if csv_class.DATA_CATEGORY == DataCategory.ACCOUNT_NAMES:
+		result['Sprach-ID'] = 'de-DE'
+
+	header = ';'.join(header).encode('latin_1')
+	data = result.to_csv(
+		# Reason for str(';'): https://github.com/pandas-dev/pandas/issues/6035
+		sep=str(';'),
+		# European decimal seperator
+		decimal=',',
+		# Windows "ANSI" encoding
+		encoding='latin_1',
+		# format date as DDMM
+		date_format='%d%m',
+		# Windows line terminator
+		line_terminator='\r\n',
+		# Do not number rows
+		index=False,
+		# Use all columns defined above
+		columns=csv_class.COLUMNS
+	)
+
+	if not six.PY2:
+		data = data.encode('latin_1')
+
+	return header + b'\r\n' + data
+
+
+def get_header(filters, csv_class):
 	header = [
 		# A = DATEV format
 		#   DTVF = created by DATEV software,
@@ -185,18 +288,8 @@
 		#   510 = 5.10,
 		#   720 = 7.20
 		"510",
-		# C = Data category
-		#   21 = Transaction batch (Buchungsstapel),
-		#   67 = Buchungstextkonstanten,
-		#   16 = Debitors/Creditors,
-		#   20 = Account names (Kontenbeschriftungen)
-		"21",
-		# D = Format name
-		#   Buchungsstapel,
-		#   Buchungstextkonstanten,
-		#   Debitoren/Kreditoren,
-		#   Kontenbeschriftungen
-		"Buchungsstapel",
+		csv_class.DATA_CATEGORY,
+		csv_class.FORMAT_NAME,
 		# E = Format version (regarding format name)
 		"",
 		# F = Generated on
@@ -224,16 +317,17 @@
 		# P = Transaction batch end date (YYYYMMDD)
 		frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"),
 		# Q = Description (for example, "January - February 2019 Transactions")
-		"{} - {} Buchungsstapel".format(
-			frappe.utils.formatdate(filters.get('from_date'), "MMMM yyyy"),
-			frappe.utils.formatdate(filters.get('to_date'), "MMMM yyyy")
+		"{} - {} {}".format(
+				frappe.utils.formatdate(filters.get('from_date'), "MMMM yyyy"),
+				frappe.utils.formatdate(filters.get('to_date'), "MMMM yyyy"),
+				csv_class.FORMAT_NAME
 		),
 		# R = Diktatkürzel
 		"",
 		# S = Buchungstyp
 		#   1 = Transaction batch (Buchungsstapel),
 		#   2 = Annual financial statement (Jahresabschluss)
-		"1",
+		"1" if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else "",
 		# T = Rechnungslegungszweck
 		"",
 		# U = Festschreibung
@@ -241,185 +335,8 @@
 		# V = Kontoführungs-Währungskennzeichen des Geldkontos
 		frappe.get_value("Company", filters.get("company"), "default_currency")
 	]
-	columns = [
-		# All possible columns must tbe listed here, because DATEV requires them to
-		# be present in the CSV.
-		# ---
-		# Umsatz
-		"Umsatz (ohne Soll/Haben-Kz)",
-		"Soll/Haben-Kennzeichen",
-		"WKZ Umsatz",
-		"Kurs",
-		"Basis-Umsatz",
-		"WKZ Basis-Umsatz",
-		# Konto/Gegenkonto
-		"Kontonummer",
-		"Gegenkonto (ohne BU-Schlüssel)",
-		"BU-Schlüssel",
-		# Datum
-		"Belegdatum",
-		# Belegfelder
-		"Belegfeld 1",
-		"Belegfeld 2",
-		# Weitere Felder
-		"Skonto",
-		"Buchungstext",
-		# OPOS-Informationen
-		"Postensperre",
-		"Diverse Adressnummer",
-		"Geschäftspartnerbank",
-		"Sachverhalt",
-		"Zinssperre",
-		# Digitaler Beleg
-		"Beleglink",
-		# Beleginfo
-		"Beleginfo - Art 1",
-		"Beleginfo - Inhalt 1",
-		"Beleginfo - Art 2",
-		"Beleginfo - Inhalt 2",
-		"Beleginfo - Art 3",
-		"Beleginfo - Inhalt 3",
-		"Beleginfo - Art 4",
-		"Beleginfo - Inhalt 4",
-		"Beleginfo - Art 5",
-		"Beleginfo - Inhalt 5",
-		"Beleginfo - Art 6",
-		"Beleginfo - Inhalt 6",
-		"Beleginfo - Art 7",
-		"Beleginfo - Inhalt 7",
-		"Beleginfo - Art 8",
-		"Beleginfo - Inhalt 8",
-		# Kostenrechnung
-		"Kost 1 - Kostenstelle",
-		"Kost 2 - Kostenstelle",
-		"Kost-Menge",
-		# Steuerrechnung
-		"EU-Land u. UStID",
-		"EU-Steuersatz",
-		"Abw. Versteuerungsart",
-		# L+L Sachverhalt
-		"Sachverhalt L+L",
-		"Funktionsergänzung L+L",
-		# Funktion Steuerschlüssel 49
-		"BU 49 Hauptfunktionstyp",
-		"BU 49 Hauptfunktionsnummer",
-		"BU 49 Funktionsergänzung",
-		# Zusatzinformationen
-		"Zusatzinformation - Art 1",
-		"Zusatzinformation - Inhalt 1",
-		"Zusatzinformation - Art 2",
-		"Zusatzinformation - Inhalt 2",
-		"Zusatzinformation - Art 3",
-		"Zusatzinformation - Inhalt 3",
-		"Zusatzinformation - Art 4",
-		"Zusatzinformation - Inhalt 4",
-		"Zusatzinformation - Art 5",
-		"Zusatzinformation - Inhalt 5",
-		"Zusatzinformation - Art 6",
-		"Zusatzinformation - Inhalt 6",
-		"Zusatzinformation - Art 7",
-		"Zusatzinformation - Inhalt 7",
-		"Zusatzinformation - Art 8",
-		"Zusatzinformation - Inhalt 8",
-		"Zusatzinformation - Art 9",
-		"Zusatzinformation - Inhalt 9",
-		"Zusatzinformation - Art 10",
-		"Zusatzinformation - Inhalt 10",
-		"Zusatzinformation - Art 11",
-		"Zusatzinformation - Inhalt 11",
-		"Zusatzinformation - Art 12",
-		"Zusatzinformation - Inhalt 12",
-		"Zusatzinformation - Art 13",
-		"Zusatzinformation - Inhalt 13",
-		"Zusatzinformation - Art 14",
-		"Zusatzinformation - Inhalt 14",
-		"Zusatzinformation - Art 15",
-		"Zusatzinformation - Inhalt 15",
-		"Zusatzinformation - Art 16",
-		"Zusatzinformation - Inhalt 16",
-		"Zusatzinformation - Art 17",
-		"Zusatzinformation - Inhalt 17",
-		"Zusatzinformation - Art 18",
-		"Zusatzinformation - Inhalt 18",
-		"Zusatzinformation - Art 19",
-		"Zusatzinformation - Inhalt 19",
-		"Zusatzinformation - Art 20",
-		"Zusatzinformation - Inhalt 20",
-		# Mengenfelder LuF
-		"Stück",
-		"Gewicht",
-		# Forderungsart
-		"Zahlweise",
-		"Forderungsart",
-		"Veranlagungsjahr",
-		"Zugeordnete Fälligkeit",
-		# Weitere Felder
-		"Skontotyp",
-		# Anzahlungen
-		"Auftragsnummer",
-		"Buchungstyp",
-		"USt-Schlüssel (Anzahlungen)",
-		"EU-Land (Anzahlungen)",
-		"Sachverhalt L+L (Anzahlungen)",
-		"EU-Steuersatz (Anzahlungen)",
-		"Erlöskonto (Anzahlungen)",
-		# Stapelinformationen
-		"Herkunft-Kz",
-		# Technische Identifikation
-		"Buchungs GUID",
-		# Kostenrechnung
-		"Kost-Datum",
-		# OPOS-Informationen
-		"SEPA-Mandatsreferenz",
-		"Skontosperre",
-		# Gesellschafter und Sonderbilanzsachverhalt
-		"Gesellschaftername",
-		"Beteiligtennummer",
-		"Identifikationsnummer",
-		"Zeichnernummer",
-		# OPOS-Informationen
-		"Postensperre bis",
-		# Gesellschafter und Sonderbilanzsachverhalt
-		"Bezeichnung SoBil-Sachverhalt",
-		"Kennzeichen SoBil-Buchung",
-		# Stapelinformationen
-		"Festschreibung",
-		# Datum
-		"Leistungsdatum",
-		"Datum Zuord. Steuerperiode",
-		# OPOS-Informationen
-		"Fälligkeit",
-		# Konto/Gegenkonto
-		"Generalumkehr (GU)",
-		# Steuersatz für Steuerschlüssel
-		"Steuersatz",
-		"Land"
-	]
+	return header
 
-	empty_df = pd.DataFrame(columns=columns)
-	data_df = pd.DataFrame.from_records(data)
-
-	result = empty_df.append(data_df)
-	result['Belegdatum'] = pd.to_datetime(result['Belegdatum'])
-
-	header = ';'.join(header).encode('latin_1')
-	data = result.to_csv(
-		sep=b';',
-		# European decimal seperator
-		decimal=',',
-		# Windows "ANSI" encoding
-		encoding='latin_1',
-		# format date as DDMM
-		date_format='%d%m',
-		# Windows line terminator
-		line_terminator=b'\r\n',
-		# Do not number rows
-		index=False,
-		# Use all columns defined above
-		columns=columns
-	)
-
-	return header + b'\r\n' + data
 
 @frappe.whitelist()
 def download_datev_csv(filters=None):
@@ -438,8 +355,31 @@
 		filters = json.loads(filters)
 
 	validate(filters)
-	data = get_gl_entries(filters, as_dict=1)
 
-	frappe.response['result'] = get_datev_csv(data, filters)
-	frappe.response['doctype'] = 'EXTF_Buchungsstapel'
-	frappe.response['type'] = 'csv'
+	# This is where my zip will be written
+	zip_buffer = BytesIO()
+	# This is my zip file
+	datev_zip = zipfile.ZipFile(zip_buffer, mode='w', compression=zipfile.ZIP_DEFLATED)
+
+	transactions = get_transactions(filters)
+	transactions_csv = get_datev_csv(transactions, filters, csv_class=Transactions)
+	datev_zip.writestr('EXTF_Buchungsstapel.csv', transactions_csv)
+
+	account_names = get_account_names(filters)
+	account_names_csv = get_datev_csv(account_names, filters, csv_class=AccountNames)
+	datev_zip.writestr('EXTF_Kontenbeschriftungen.csv', account_names_csv)
+
+	customers = get_customers(filters)
+	customers_csv = get_datev_csv(customers, filters, csv_class=DebtorsCreditors)
+	datev_zip.writestr('EXTF_Kunden.csv', customers_csv)
+
+	suppliers = get_suppliers(filters)
+	suppliers_csv = get_datev_csv(suppliers, filters, csv_class=DebtorsCreditors)
+	datev_zip.writestr('EXTF_Lieferanten.csv', suppliers_csv)
+	
+	# You must call close() before exiting your program or essential records will not be written.
+	datev_zip.close()
+
+	frappe.response['filecontent'] = zip_buffer.getvalue()
+	frappe.response['filename'] = 'DATEV.zip'
+	frappe.response['type'] = 'binary'
diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py
new file mode 100644
index 0000000..1c9bd23
--- /dev/null
+++ b/erpnext/regional/report/datev/datev_constants.py
@@ -0,0 +1,512 @@
+# coding: utf-8
+"""Constants used in datev.py."""
+
+TRANSACTION_COLUMNS = [
+	# All possible columns must tbe listed here, because DATEV requires them to
+	# be present in the CSV.
+	# ---
+	# Umsatz
+	"Umsatz (ohne Soll/Haben-Kz)",
+	"Soll/Haben-Kennzeichen",
+	"WKZ Umsatz",
+	"Kurs",
+	"Basis-Umsatz",
+	"WKZ Basis-Umsatz",
+	# Konto/Gegenkonto
+	"Kontonummer",
+	"Gegenkonto (ohne BU-Schlüssel)",
+	"BU-Schlüssel",
+	# Datum
+	"Belegdatum",
+	# Belegfelder
+	"Belegfeld 1",
+	"Belegfeld 2",
+	# Weitere Felder
+	"Skonto",
+	"Buchungstext",
+	# OPOS-Informationen
+	"Postensperre",
+	"Diverse Adressnummer",
+	"Geschäftspartnerbank",
+	"Sachverhalt",
+	"Zinssperre",
+	# Digitaler Beleg
+	"Beleglink",
+	# Beleginfo
+	"Beleginfo - Art 1",
+	"Beleginfo - Inhalt 1",
+	"Beleginfo - Art 2",
+	"Beleginfo - Inhalt 2",
+	"Beleginfo - Art 3",
+	"Beleginfo - Inhalt 3",
+	"Beleginfo - Art 4",
+	"Beleginfo - Inhalt 4",
+	"Beleginfo - Art 5",
+	"Beleginfo - Inhalt 5",
+	"Beleginfo - Art 6",
+	"Beleginfo - Inhalt 6",
+	"Beleginfo - Art 7",
+	"Beleginfo - Inhalt 7",
+	"Beleginfo - Art 8",
+	"Beleginfo - Inhalt 8",
+	# Kostenrechnung
+	"Kost 1 - Kostenstelle",
+	"Kost 2 - Kostenstelle",
+	"Kost-Menge",
+	# Steuerrechnung
+	"EU-Land u. UStID",
+	"EU-Steuersatz",
+	"Abw. Versteuerungsart",
+	# L+L Sachverhalt
+	"Sachverhalt L+L",
+	"Funktionsergänzung L+L",
+	# Funktion Steuerschlüssel 49
+	"BU 49 Hauptfunktionstyp",
+	"BU 49 Hauptfunktionsnummer",
+	"BU 49 Funktionsergänzung",
+	# Zusatzinformationen
+	"Zusatzinformation - Art 1",
+	"Zusatzinformation - Inhalt 1",
+	"Zusatzinformation - Art 2",
+	"Zusatzinformation - Inhalt 2",
+	"Zusatzinformation - Art 3",
+	"Zusatzinformation - Inhalt 3",
+	"Zusatzinformation - Art 4",
+	"Zusatzinformation - Inhalt 4",
+	"Zusatzinformation - Art 5",
+	"Zusatzinformation - Inhalt 5",
+	"Zusatzinformation - Art 6",
+	"Zusatzinformation - Inhalt 6",
+	"Zusatzinformation - Art 7",
+	"Zusatzinformation - Inhalt 7",
+	"Zusatzinformation - Art 8",
+	"Zusatzinformation - Inhalt 8",
+	"Zusatzinformation - Art 9",
+	"Zusatzinformation - Inhalt 9",
+	"Zusatzinformation - Art 10",
+	"Zusatzinformation - Inhalt 10",
+	"Zusatzinformation - Art 11",
+	"Zusatzinformation - Inhalt 11",
+	"Zusatzinformation - Art 12",
+	"Zusatzinformation - Inhalt 12",
+	"Zusatzinformation - Art 13",
+	"Zusatzinformation - Inhalt 13",
+	"Zusatzinformation - Art 14",
+	"Zusatzinformation - Inhalt 14",
+	"Zusatzinformation - Art 15",
+	"Zusatzinformation - Inhalt 15",
+	"Zusatzinformation - Art 16",
+	"Zusatzinformation - Inhalt 16",
+	"Zusatzinformation - Art 17",
+	"Zusatzinformation - Inhalt 17",
+	"Zusatzinformation - Art 18",
+	"Zusatzinformation - Inhalt 18",
+	"Zusatzinformation - Art 19",
+	"Zusatzinformation - Inhalt 19",
+	"Zusatzinformation - Art 20",
+	"Zusatzinformation - Inhalt 20",
+	# Mengenfelder LuF
+	"Stück",
+	"Gewicht",
+	# Forderungsart
+	"Zahlweise",
+	"Forderungsart",
+	"Veranlagungsjahr",
+	"Zugeordnete Fälligkeit",
+	# Weitere Felder
+	"Skontotyp",
+	# Anzahlungen
+	"Auftragsnummer",
+	"Buchungstyp",
+	"USt-Schlüssel (Anzahlungen)",
+	"EU-Land (Anzahlungen)",
+	"Sachverhalt L+L (Anzahlungen)",
+	"EU-Steuersatz (Anzahlungen)",
+	"Erlöskonto (Anzahlungen)",
+	# Stapelinformationen
+	"Herkunft-Kz",
+	# Technische Identifikation
+	"Buchungs GUID",
+	# Kostenrechnung
+	"Kost-Datum",
+	# OPOS-Informationen
+	"SEPA-Mandatsreferenz",
+	"Skontosperre",
+	# Gesellschafter und Sonderbilanzsachverhalt
+	"Gesellschaftername",
+	"Beteiligtennummer",
+	"Identifikationsnummer",
+	"Zeichnernummer",
+	# OPOS-Informationen
+	"Postensperre bis",
+	# Gesellschafter und Sonderbilanzsachverhalt
+	"Bezeichnung SoBil-Sachverhalt",
+	"Kennzeichen SoBil-Buchung",
+	# Stapelinformationen
+	"Festschreibung",
+	# Datum
+	"Leistungsdatum",
+	"Datum Zuord. Steuerperiode",
+	# OPOS-Informationen
+	"Fälligkeit",
+	# Konto/Gegenkonto
+	"Generalumkehr (GU)",
+	# Steuersatz für Steuerschlüssel
+	"Steuersatz",
+	"Land"
+]
+
+DEBTOR_CREDITOR_COLUMNS = [
+	# All possible columns must tbe listed here, because DATEV requires them to
+	# be present in the CSV.
+	# Columns "Leerfeld" have been replaced with "Leerfeld #" to not confuse pandas
+	# ---
+	"Konto",
+	"Name (Adressatentyp Unternehmen)",
+	"Unternehmensgegenstand",
+	"Name (Adressatentyp natürl. Person)",
+	"Vorname (Adressatentyp natürl. Person)",
+	"Name (Adressatentyp keine Angabe)",
+	"Adressatentyp",
+	"Kurzbezeichnung",
+	"EU-Land",
+	"EU-USt-IdNr.",
+	"Anrede",
+	"Titel/Akad. Grad",
+	"Adelstitel",
+	"Namensvorsatz",
+	"Adressart",
+	"Straße",
+	"Postfach",
+	"Postleitzahl",
+	"Ort",
+	"Land",
+	"Versandzusatz",
+	"Adresszusatz",
+	"Abweichende Anrede",
+	"Abw. Zustellbezeichnung 1",
+	"Abw. Zustellbezeichnung 2",
+	"Kennz. Korrespondenzadresse",
+	"Adresse gültig von",
+	"Adresse gültig bis",
+	"Telefon",
+	"Bemerkung (Telefon)",
+	"Telefon Geschäftsleitung",
+	"Bemerkung (Telefon GL)",
+	"E-Mail",
+	"Bemerkung (E-Mail)",
+	"Internet",
+	"Bemerkung (Internet)",
+	"Fax",
+	"Bemerkung (Fax)",
+	"Sonstige",
+	"Bemerkung (Sonstige)",
+	"Bankleitzahl 1",
+	"Bankbezeichnung 1",
+	"Bankkonto-Nummer 1",
+	"Länderkennzeichen 1",
+	"IBAN 1",
+	"Leerfeld 1",
+	"SWIFT-Code 1",
+	"Abw. Kontoinhaber 1",
+	"Kennz. Haupt-Bankverb. 1",
+	"Bankverb. 1 Gültig von",
+	"Bankverb. 1 Gültig bis",
+	"Bankleitzahl 2",
+	"Bankbezeichnung 2",
+	"Bankkonto-Nummer 2",
+	"Länderkennzeichen 2",
+	"IBAN 2",
+	"Leerfeld 2",
+	"SWIFT-Code 2",
+	"Abw. Kontoinhaber 2",
+	"Kennz. Haupt-Bankverb. 2",
+	"Bankverb. 2 gültig von",
+	"Bankverb. 2 gültig bis",
+	"Bankleitzahl 3",
+	"Bankbezeichnung 3",
+	"Bankkonto-Nummer 3",
+	"Länderkennzeichen 3",
+	"IBAN 3",
+	"Leerfeld 3",
+	"SWIFT-Code 3",
+	"Abw. Kontoinhaber 3",
+	"Kennz. Haupt-Bankverb. 3",
+	"Bankverb. 3 gültig von",
+	"Bankverb. 3 gültig bis",
+	"Bankleitzahl 4",
+	"Bankbezeichnung 4",
+	"Bankkonto-Nummer 4",
+	"Länderkennzeichen 4",
+	"IBAN 4",
+	"Leerfeld 4",
+	"SWIFT-Code 4",
+	"Abw. Kontoinhaber 4",
+	"Kennz. Haupt-Bankverb. 4",
+	"Bankverb. 4 Gültig von",
+	"Bankverb. 4 Gültig bis",
+	"Bankleitzahl 5",
+	"Bankbezeichnung 5",
+	"Bankkonto-Nummer 5",
+	"Länderkennzeichen 5",
+	"IBAN 5",
+	"Leerfeld 5",
+	"SWIFT-Code 5",
+	"Abw. Kontoinhaber 5",
+	"Kennz. Haupt-Bankverb. 5",
+	"Bankverb. 5 gültig von",
+	"Bankverb. 5 gültig bis",
+	"Leerfeld 6",
+	"Briefanrede",
+	"Grußformel",
+	"Kundennummer",
+	"Steuernummer",
+	"Sprache",
+	"Ansprechpartner",
+	"Vertreter",
+	"Sachbearbeiter",
+	"Diverse-Konto",
+	"Ausgabeziel",
+	"Währungssteuerung",
+	"Kreditlimit (Debitor)",
+	"Zahlungsbedingung",
+	"Fälligkeit in Tagen (Debitor)",
+	"Skonto in Prozent (Debitor)",
+	"Kreditoren-Ziel 1 (Tage)",
+	"Kreditoren-Skonto 1 (%)",
+	"Kreditoren-Ziel 2 (Tage)",
+	"Kreditoren-Skonto 2 (%)",
+	"Kreditoren-Ziel 3 Brutto (Tage)",
+	"Kreditoren-Ziel 4 (Tage)",
+	"Kreditoren-Skonto 4 (%)",
+	"Kreditoren-Ziel 5 (Tage)",
+	"Kreditoren-Skonto 5 (%)",
+	"Mahnung",
+	"Kontoauszug",
+	"Mahntext 1",
+	"Mahntext 2",
+	"Mahntext 3",
+	"Kontoauszugstext",
+	"Mahnlimit Betrag",
+	"Mahnlimit %",
+	"Zinsberechnung",
+	"Mahnzinssatz 1",
+	"Mahnzinssatz 2",
+	"Mahnzinssatz 3",
+	"Lastschrift",
+	"Verfahren",
+	"Mandantenbank",
+	"Zahlungsträger",
+	"Indiv. Feld 1",
+	"Indiv. Feld 2",
+	"Indiv. Feld 3",
+	"Indiv. Feld 4",
+	"Indiv. Feld 5",
+	"Indiv. Feld 6",
+	"Indiv. Feld 7",
+	"Indiv. Feld 8",
+	"Indiv. Feld 9",
+	"Indiv. Feld 10",
+	"Indiv. Feld 11",
+	"Indiv. Feld 12",
+	"Indiv. Feld 13",
+	"Indiv. Feld 14",
+	"Indiv. Feld 15",
+	"Abweichende Anrede (Rechnungsadresse)",
+	"Adressart (Rechnungsadresse)",
+	"Straße (Rechnungsadresse)",
+	"Postfach (Rechnungsadresse)",
+	"Postleitzahl (Rechnungsadresse)",
+	"Ort (Rechnungsadresse)",
+	"Land (Rechnungsadresse)",
+	"Versandzusatz (Rechnungsadresse)",
+	"Adresszusatz (Rechnungsadresse)",
+	"Abw. Zustellbezeichnung 1 (Rechnungsadresse)",
+	"Abw. Zustellbezeichnung 2 (Rechnungsadresse)",
+	"Adresse Gültig von (Rechnungsadresse)",
+	"Adresse Gültig bis (Rechnungsadresse)",
+	"Bankleitzahl 6",
+	"Bankbezeichnung 6",
+	"Bankkonto-Nummer 6",
+	"Länderkennzeichen 6",
+	"IBAN 6",
+	"Leerfeld 7",
+	"SWIFT-Code 6",
+	"Abw. Kontoinhaber 6",
+	"Kennz. Haupt-Bankverb. 6",
+	"Bankverb 6 gültig von",
+	"Bankverb 6 gültig bis",
+	"Bankleitzahl 7",
+	"Bankbezeichnung 7",
+	"Bankkonto-Nummer 7",
+	"Länderkennzeichen 7",
+	"IBAN 7",
+	"Leerfeld 8",
+	"SWIFT-Code 7",
+	"Abw. Kontoinhaber 7",
+	"Kennz. Haupt-Bankverb. 7",
+	"Bankverb 7 gültig von",
+	"Bankverb 7 gültig bis",
+	"Bankleitzahl 8",
+	"Bankbezeichnung 8",
+	"Bankkonto-Nummer 8",
+	"Länderkennzeichen 8",
+	"IBAN 8",
+	"Leerfeld 9",
+	"SWIFT-Code 8",
+	"Abw. Kontoinhaber 8",
+	"Kennz. Haupt-Bankverb. 8",
+	"Bankverb 8 gültig von",
+	"Bankverb 8 gültig bis",
+	"Bankleitzahl 9",
+	"Bankbezeichnung 9",
+	"Bankkonto-Nummer 9",
+	"Länderkennzeichen 9",
+	"IBAN 9",
+	"Leerfeld 10",
+	"SWIFT-Code 9",
+	"Abw. Kontoinhaber 9",
+	"Kennz. Haupt-Bankverb. 9",
+	"Bankverb 9 gültig von",
+	"Bankverb 9 gültig bis",
+	"Bankleitzahl 10",
+	"Bankbezeichnung 10",
+	"Bankkonto-Nummer 10",
+	"Länderkennzeichen 10",
+	"IBAN 10",
+	"Leerfeld 11",
+	"SWIFT-Code 10",
+	"Abw. Kontoinhaber 10",
+	"Kennz. Haupt-Bankverb. 10",
+	"Bankverb 10 gültig von",
+	"Bankverb 10 gültig bis",
+	"Nummer Fremdsystem",
+	"Insolvent",
+	"SEPA-Mandatsreferenz 1",
+	"SEPA-Mandatsreferenz 2",
+	"SEPA-Mandatsreferenz 3",
+	"SEPA-Mandatsreferenz 4",
+	"SEPA-Mandatsreferenz 5",
+	"SEPA-Mandatsreferenz 6",
+	"SEPA-Mandatsreferenz 7",
+	"SEPA-Mandatsreferenz 8",
+	"SEPA-Mandatsreferenz 9",
+	"SEPA-Mandatsreferenz 10",
+	"Verknüpftes OPOS-Konto",
+	"Mahnsperre bis",
+	"Lastschriftsperre bis",
+	"Zahlungssperre bis",
+	"Gebührenberechnung",
+	"Mahngebühr 1",
+	"Mahngebühr 2",
+	"Mahngebühr 3",
+	"Pauschalberechnung",
+	"Verzugspauschale 1",
+	"Verzugspauschale 2",
+	"Verzugspauschale 3",
+	"Alternativer Suchname",
+	"Status",
+	"Anschrift manuell geändert (Korrespondenzadresse)",
+	"Anschrift individuell (Korrespondenzadresse)",
+	"Anschrift manuell geändert (Rechnungsadresse)",
+	"Anschrift individuell (Rechnungsadresse)",
+	"Fristberechnung bei Debitor",
+	"Mahnfrist 1",
+	"Mahnfrist 2",
+	"Mahnfrist 3",
+	"Letzte Frist"
+]
+
+ACCOUNT_NAME_COLUMNS = [
+	# Account number
+	"Konto",
+	# Account name
+	"Kontenbeschriftung",
+	# Language of the account name 
+	# "de-DE" or "en-GB"
+	"Sprach-ID"
+]
+
+QUERY_REPORT_COLUMNS = [
+	{
+		"label": "Umsatz (ohne Soll/Haben-Kz)",
+		"fieldname": "Umsatz (ohne Soll/Haben-Kz)",
+		"fieldtype": "Currency",
+	},
+	{
+		"label": "Soll/Haben-Kennzeichen",
+		"fieldname": "Soll/Haben-Kennzeichen",
+		"fieldtype": "Data",
+	},
+	{
+		"label": "Kontonummer",
+		"fieldname": "Kontonummer",
+		"fieldtype": "Data",
+	},
+	{
+		"label": "Gegenkonto (ohne BU-Schlüssel)",
+		"fieldname": "Gegenkonto (ohne BU-Schlüssel)",
+		"fieldtype": "Data",
+	},
+	{
+		"label": "Belegdatum",
+		"fieldname": "Belegdatum",
+		"fieldtype": "Date",
+	},
+	{
+		"label": "Buchungstext",
+		"fieldname": "Buchungstext",
+		"fieldtype": "Text",
+	},
+	{
+		"label": "Beleginfo - Art 1",
+		"fieldname": "Beleginfo - Art 1",
+		"fieldtype": "Data",
+	},
+	{
+		"label": "Beleginfo - Inhalt 1",
+		"fieldname": "Beleginfo - Inhalt 1",
+		"fieldtype": "Data",
+	},
+	{
+		"label": "Beleginfo - Art 2",
+		"fieldname": "Beleginfo - Art 2",
+		"fieldtype": "Data",
+	},
+	{
+		"label": "Beleginfo - Inhalt 2",
+		"fieldname": "Beleginfo - Inhalt 2",
+		"fieldtype": "Data",
+	}
+]
+
+class DataCategory():
+	"""Field of the CSV Header."""
+
+	DEBTORS_CREDITORS = "16"
+	ACCOUNT_NAMES = "20"
+	TRANSACTIONS = "21"
+	POSTING_TEXT_CONSTANTS = "67"
+
+class FormatName():
+	"""Field of the CSV Header, corresponds to DataCategory."""
+
+	DEBTORS_CREDITORS = "Debitoren/Kreditoren"
+	ACCOUNT_NAMES = "Kontenbeschriftungen"
+	TRANSACTIONS = "Buchungsstapel"
+	POSTING_TEXT_CONSTANTS = "Buchungstextkonstanten"
+
+class Transactions():
+	DATA_CATEGORY = DataCategory.TRANSACTIONS
+	FORMAT_NAME = FormatName.TRANSACTIONS
+	COLUMNS = TRANSACTION_COLUMNS
+
+class DebtorsCreditors():
+	DATA_CATEGORY = DataCategory.DEBTORS_CREDITORS
+	FORMAT_NAME = FormatName.DEBTORS_CREDITORS
+	COLUMNS = DEBTOR_CREDITOR_COLUMNS
+
+class AccountNames():
+	DATA_CATEGORY = DataCategory.ACCOUNT_NAMES
+	FORMAT_NAME = FormatName.ACCOUNT_NAMES
+	COLUMNS = ACCOUNT_NAME_COLUMNS
diff --git a/erpnext/regional/report/datev/test_datev.py b/erpnext/regional/report/datev/test_datev.py
new file mode 100644
index 0000000..3cc65fe
--- /dev/null
+++ b/erpnext/regional/report/datev/test_datev.py
@@ -0,0 +1,244 @@
+# coding=utf-8
+from __future__ import unicode_literals
+
+import os
+import json
+import zipfile
+from six import BytesIO
+from unittest import TestCase
+
+import frappe
+from frappe.utils import getdate, today, now_datetime, cstr
+from frappe.test_runner import make_test_objects
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
+
+from erpnext.regional.report.datev.datev import validate
+from erpnext.regional.report.datev.datev import get_transactions
+from erpnext.regional.report.datev.datev import get_customers
+from erpnext.regional.report.datev.datev import get_suppliers
+from erpnext.regional.report.datev.datev import get_account_names
+from erpnext.regional.report.datev.datev import get_datev_csv
+from erpnext.regional.report.datev.datev import get_header
+from erpnext.regional.report.datev.datev import download_datev_csv
+
+from erpnext.regional.report.datev.datev_constants import DataCategory
+from erpnext.regional.report.datev.datev_constants import Transactions
+from erpnext.regional.report.datev.datev_constants import DebtorsCreditors
+from erpnext.regional.report.datev.datev_constants import AccountNames
+from erpnext.regional.report.datev.datev_constants import QUERY_REPORT_COLUMNS
+
+def make_company(company_name, abbr):
+	if not frappe.db.exists("Company", company_name):
+		company = frappe.get_doc({
+			"doctype": "Company",
+			"company_name": company_name,
+			"abbr": abbr,
+			"default_currency": "EUR",
+			"country": "Germany",
+			"create_chart_of_accounts_based_on": "Standard Template",
+			"chart_of_accounts": "SKR04 mit Kontonummern"
+		})
+		company.insert()
+	else:
+		company = frappe.get_doc("Company", company_name)
+
+	# indempotent
+	company.create_default_warehouses()
+
+	if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": company.name}):
+		company.create_default_cost_center()
+
+	company.save()
+	return company
+
+def setup_fiscal_year():
+	fiscal_year = None
+	year = cstr(now_datetime().year)
+	if not frappe.db.get_value("Fiscal Year", {"year": year}, "name"):
+		try:
+			fiscal_year = frappe.get_doc({
+				"doctype": "Fiscal Year",
+				"year": year,
+				"year_start_date": "{0}-01-01".format(year),
+				"year_end_date": "{0}-12-31".format(year)
+			})
+			fiscal_year.insert()
+		except frappe.NameError:
+			pass
+
+	if fiscal_year:
+		fiscal_year.set_as_default()
+
+def make_customer_with_account(customer_name, company):
+	acc_name = frappe.db.get_value("Account", {
+			"account_name": customer_name,
+			"company": company.name
+		}, "name")
+
+	if not acc_name:
+		acc = frappe.get_doc({
+			"doctype": "Account",
+			"parent_account": "1 - Forderungen aus Lieferungen und Leistungen - _TG",
+			"account_name": customer_name,
+			"company": company.name,
+			"account_type": "Receivable",
+			"account_number": "10001"
+		})
+		acc.insert()
+		acc_name = acc.name
+
+	if not frappe.db.exists("Customer", customer_name):
+		customer = frappe.get_doc({
+			"doctype": "Customer",		
+			"customer_name": customer_name,
+			"customer_type": "Company",
+			"accounts": [{
+				"company": company.name,
+				"account": acc_name
+			}]
+		})
+		customer.insert()
+	else:
+		customer = frappe.get_doc("Customer", customer_name)
+
+	return customer
+
+def make_item(item_code, company):
+	warehouse_name = frappe.db.get_value("Warehouse", {
+			"warehouse_name": "Stores",
+			"company": company.name
+		}, "name")
+
+	if not frappe.db.exists("Item", item_code):
+		item = frappe.get_doc({
+			"doctype": "Item",
+			"item_code": item_code,
+			"item_name": item_code,
+			"description": item_code,
+			"item_group": "All Item Groups",
+			"is_stock_item": 0,
+			"is_purchase_item": 0,
+			"is_customer_provided_item": 0,
+			"item_defaults": [{
+				"default_warehouse": warehouse_name,
+				"company": company.name
+			}]
+		})
+		item.insert()
+	else:
+		item = frappe.get_doc("Item", item_code)
+	return item
+
+def make_datev_settings(company):
+	if not frappe.db.exists("DATEV Settings", company.name):
+		frappe.get_doc({
+			"doctype": "DATEV Settings",
+			"client": company.name,
+			"client_number": "12345",
+			"consultant_number": "67890"
+		}).insert()
+
+
+class TestDatev(TestCase):
+	def setUp(self):
+		self.company = make_company("_Test GmbH", "_TG")
+		self.customer = make_customer_with_account("_Test Kunde GmbH", self.company)
+		self.filters = {
+			"company": self.company.name,
+			"from_date": today(),
+			"to_date": today()
+		}
+
+		make_datev_settings(self.company)
+		item = make_item("_Test Item", self.company)
+		setup_fiscal_year()
+
+		warehouse = frappe.db.get_value("Item Default", {
+				"parent": item.name, 
+				"company": self.company.name
+			}, "default_warehouse")
+
+		income_account = frappe.db.get_value("Account", {
+				"account_number": "4200", 
+				"company": self.company.name
+			}, "name")
+
+		tax_account = frappe.db.get_value("Account", {
+				"account_number": "3806", 
+				"company": self.company.name
+			}, "name")
+
+		si = create_sales_invoice(
+			company=self.company.name,
+			customer=self.customer.name,
+			currency=self.company.default_currency,
+			debit_to=self.customer.accounts[0].account,
+			income_account="4200 - Erlöse - _TG",
+			expense_account="6990 - Herstellungskosten - _TG",
+			cost_center=self.company.cost_center,
+			warehouse=warehouse,
+			item=item.name,
+			do_not_save=1
+		)
+
+		si.append("taxes", {
+			"charge_type": "On Net Total",
+			"account_head": tax_account,
+			"description": "Umsatzsteuer 19 %",
+			"rate": 19
+		})
+
+		si.save()
+		si.submit()
+
+	def test_columns(self):
+		def is_subset(get_data, allowed_keys):
+			"""
+			Validate that the dict contains only allowed keys.
+			
+			Params:
+			get_data -- Function that returns a list of dicts.
+			allowed_keys -- List of allowed keys
+			"""
+			data = get_data(self.filters)
+			if data == []:
+				# No data and, therefore, no columns is okay
+				return True
+			actual_set = set(data[0].keys())
+			# allowed set must be interpreted as unicode to match the actual set
+			allowed_set = set({frappe.as_unicode(key) for key in allowed_keys})
+			return actual_set.issubset(allowed_set)
+
+		self.assertTrue(is_subset(get_transactions, Transactions.COLUMNS))
+		self.assertTrue(is_subset(get_customers, DebtorsCreditors.COLUMNS))
+		self.assertTrue(is_subset(get_suppliers, DebtorsCreditors.COLUMNS))
+		self.assertTrue(is_subset(get_account_names, AccountNames.COLUMNS))
+
+	def test_header(self):
+		self.assertTrue(Transactions.DATA_CATEGORY in get_header(self.filters, Transactions))
+		self.assertTrue(AccountNames.DATA_CATEGORY in get_header(self.filters, AccountNames))
+		self.assertTrue(DebtorsCreditors.DATA_CATEGORY in get_header(self.filters, DebtorsCreditors))
+
+	def test_csv(self):
+		test_data = [{
+			"Umsatz (ohne Soll/Haben-Kz)": 100,
+			"Soll/Haben-Kennzeichen": "H",
+			"Kontonummer": "4200",
+			"Gegenkonto (ohne BU-Schlüssel)": "10000",
+			"Belegdatum": today(),
+			"Buchungstext": "No remark",
+			"Beleginfo - Art 1": "Sales Invoice",
+			"Beleginfo - Inhalt 1": "SINV-0001"
+		}]
+		get_datev_csv(data=test_data, filters=self.filters, csv_class=Transactions)
+
+	def test_download(self):
+		"""Assert that the returned file is a ZIP file."""
+		download_datev_csv(self.filters)
+
+		# zipfile.is_zipfile() expects a file-like object
+		zip_buffer = BytesIO()
+		zip_buffer.write(frappe.response['filecontent'])
+
+		self.assertTrue(zipfile.is_zipfile(zip_buffer))
diff --git a/erpnext/regional/report/gstr_1/gstr_1.js b/erpnext/regional/report/gstr_1/gstr_1.js
index 9682768..ce55921 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.js
+++ b/erpnext/regional/report/gstr_1/gstr_1.js
@@ -52,7 +52,7 @@
 	],
 	onload: function (report) {
 
-		report.page.add_inner_button(__("Download as Json"), function () {
+		report.page.add_inner_button(__("Download as JSON"), function () {
 			var filters = report.get_values();
 
 			const args = {
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index e12b359..e97a4ee 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -834,6 +834,10 @@
 		for item in sales_order.items:
 			if item.supplier and item.supplier not in suppliers:
 				suppliers.append(item.supplier)
+
+	if not suppliers:
+		frappe.throw(_("Please set a Supplier against the Items to be considered in the Purchase Order."))
+
 	for supplier in suppliers:
 		po =frappe.get_list("Purchase Order", filters={"sales_order":source_name, "supplier":supplier, "docstatus": ("<", "2")})
 		if len(po) == 0:
diff --git a/erpnext/setup/setup_wizard/test_setup_wizard.py b/erpnext/setup/setup_wizard/test_setup_wizard.py
deleted file mode 100644
index a489133..0000000
--- a/erpnext/setup/setup_wizard/test_setup_wizard.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe, time
-from frappe.utils.selenium_testdriver import TestDriver
-
-def run_setup_wizard_test():
-	driver = TestDriver()
-	frappe.db.set_default('in_selenium', '1')
-	frappe.db.commit()
-
-	driver.login('#page-setup-wizard')
-	print('Running Setup Wizard Test...')
-
-	# Language slide
-	driver.wait_for_ajax(True)
-	time.sleep(1)
-
-	driver.set_select("language", "English (United States)")
-	driver.wait_for_ajax(True)
-	time.sleep(1)
-	driver.click(".next-btn")
-
-	# Region slide
-	driver.wait_for_ajax(True)
-	driver.set_select("country", "India")
-	driver.wait_for_ajax(True)
-	time.sleep(1)
-	driver.click(".next-btn")
-
-	# Profile slide
-	driver.set_field("full_name", "Great Tester")
-	driver.set_field("email", "great@example.com")
-	driver.set_field("password", "test")
-	driver.wait_for_ajax(True)
-	time.sleep(1)
-	driver.click(".next-btn")
-	time.sleep(1)
-
-	# domain slide
-	driver.set_multicheck("domains", ["Manufacturing"])
-	time.sleep(1)
-	driver.click(".next-btn")
-
-	# Org slide
-	driver.set_field("company_name", "For Testing")
-	time.sleep(1)
-	driver.print_console()
-	driver.click(".next-btn")
-
-	driver.set_field("company_tagline", "Just for GST")
-	driver.set_field("bank_account", "HDFC")
-	time.sleep(3)
-	driver.click(".complete-btn")
-
-	# Wait for desktop
-	driver.wait_for('#page-desktop', timeout=600)
-
-	driver.print_console()
-	time.sleep(3)
-
-	frappe.db.set_default('in_selenium', None)
-	frappe.db.set_value("Company", "For Testing", "write_off_account", "Write Off - FT")
-	frappe.db.set_value("Company", "For Testing", "exchange_gain_loss_account", "Exchange Gain/Loss - FT")
-	frappe.db.commit()
-
-	driver.close()
-
-	return True
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index 1236ade..813d0dd 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -66,6 +66,7 @@
 
 	from erpnext.selling.doctype.quotation.quotation import _make_sales_order
 	sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
+	sales_order.payment_schedule = []
 
 	if not cint(cart_settings.allow_items_not_in_stock):
 		for item in sales_order.get("items"):
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 410d9f1..e3d356f 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -136,6 +136,20 @@
 		frm.toggle_reqd('customer', frm.doc.is_customer_provided_item ? 1:0);
 	},
 
+	gst_hsn_code: function(frm){
+		if(!frm.doc.taxes){
+			frappe.db.get_doc("GST HSN Code", frm.doc.gst_hsn_code).then(hsn_doc=>{
+				frm.doc.taxes = [];
+				$.each(hsn_doc.taxes || [], function(i, tax) {
+					let a = frappe.model.add_child(cur_frm.doc, 'Item Tax', 'taxes');
+					a.item_tax_template = tax.item_tax_template;
+					a.tax_category = tax.tax_category;
+					frm.refresh_field('taxes');
+				});
+			});
+		}
+	},
+
 	is_fixed_asset: function(frm) {
 		// set serial no to false & toggles its visibility
 		frm.set_value('has_serial_no', 0);
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index d5914f9..6b5e40e 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -34,6 +34,12 @@
 				filters: {'company': frm.doc.company }
 			}
 		});
+
+		frm.set_query("taxes_and_charges", function() {
+			return {
+				filters: {'company': frm.doc.company }
+			}
+		});
 		
 	},
 	onload: function(frm) {
@@ -296,4 +302,4 @@
 			}
 		});
 	}
-};
\ No newline at end of file
+};
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
index 947f948..c9eba71 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
@@ -1,874 +1,299 @@
 {
  "allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
  "autoname": "MAT-SLE-.YYYY.-.#####",
- "beta": 0,
  "creation": "2013-01-29 19:25:42",
- "custom": 0,
- "docstatus": 0,
  "doctype": "DocType",
  "document_type": "Other",
- "editable_grid": 0,
  "engine": "InnoDB",
+ "field_order": [
+  "item_code",
+  "serial_no",
+  "batch_no",
+  "warehouse",
+  "posting_date",
+  "posting_time",
+  "voucher_type",
+  "voucher_no",
+  "voucher_detail_no",
+  "actual_qty",
+  "incoming_rate",
+  "outgoing_rate",
+  "stock_uom",
+  "qty_after_transaction",
+  "valuation_rate",
+  "stock_value",
+  "stock_value_difference",
+  "stock_queue",
+  "project",
+  "company",
+  "fiscal_year",
+  "is_cancelled",
+  "to_rename"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "item_code",
    "fieldtype": "Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
    "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Item Code",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "item_code",
    "oldfieldtype": "Link",
    "options": "Item",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "100px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
    "search_index": 1,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "100px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "serial_no",
-   "fieldtype": "Text",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
+   "fieldtype": "Long Text",
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Serial No",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "100px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "100px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "batch_no",
    "fieldtype": "Data",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Batch No",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "batch_no",
    "oldfieldtype": "Data",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "warehouse",
    "fieldtype": "Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
    "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Warehouse",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "warehouse",
    "oldfieldtype": "Link",
    "options": "Warehouse",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "100px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
    "search_index": 1,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "100px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "posting_date",
    "fieldtype": "Date",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Posting Date",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "posting_date",
    "oldfieldtype": "Date",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "100px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
    "search_index": 1,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "100px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "posting_time",
    "fieldtype": "Time",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Posting Time",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "posting_time",
    "oldfieldtype": "Time",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "100px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "100px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "voucher_type",
    "fieldtype": "Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Voucher Type",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "voucher_type",
    "oldfieldtype": "Data",
    "options": "DocType",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "voucher_no",
    "fieldtype": "Dynamic Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
-   "in_list_view": 0,
    "in_standard_filter": 1,
    "label": "Voucher No",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "voucher_no",
    "oldfieldtype": "Data",
    "options": "voucher_type",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "voucher_detail_no",
    "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": "Voucher Detail No",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "voucher_detail_no",
    "oldfieldtype": "Data",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "actual_qty",
    "fieldtype": "Float",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Actual Quantity",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "actual_qty",
    "oldfieldtype": "Currency",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "incoming_rate",
    "fieldtype": "Currency",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Incoming Rate",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "incoming_rate",
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "outgoing_rate",
    "fieldtype": "Currency",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Outgoing Rate",
-   "length": 0,
-   "no_copy": 0,
    "options": "Company:company:default_currency",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "stock_uom",
    "fieldtype": "Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Stock UOM",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "stock_uom",
    "oldfieldtype": "Data",
    "options": "UOM",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "qty_after_transaction",
    "fieldtype": "Float",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Actual Qty After Transaction",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "bin_aqat",
    "oldfieldtype": "Currency",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "valuation_rate",
    "fieldtype": "Currency",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Valuation Rate",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "valuation_rate",
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "stock_value",
    "fieldtype": "Currency",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Stock Value",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "stock_value",
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "stock_value_difference",
    "fieldtype": "Currency",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Stock Value Difference",
-   "length": 0,
-   "no_copy": 0,
    "options": "Company:company:default_currency",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "stock_queue",
    "fieldtype": "Text",
    "hidden": 1,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Stock Queue (FIFO)",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "fcfs_stack",
    "oldfieldtype": "Text",
-   "permlevel": 0,
    "print_hide": 1,
-   "print_hide_if_no_value": 0,
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 1,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "report_hide": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "project",
    "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": "Project",
-   "length": 0,
-   "no_copy": 0,
-   "options": "Project",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "options": "Project"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "company",
    "fieldtype": "Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Company",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "company",
    "oldfieldtype": "Data",
    "options": "Company",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "fiscal_year",
    "fieldtype": "Data",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
    "in_filter": 1,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Fiscal Year",
-   "length": 0,
-   "no_copy": 0,
    "oldfieldname": "fiscal_year",
    "oldfieldtype": "Data",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
    "print_width": "150px",
    "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0,
    "width": "150px"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "is_cancelled",
    "fieldtype": "Select",
    "hidden": 1,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Is Cancelled",
-   "length": 0,
-   "no_copy": 0,
    "options": "\nNo\nYes",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 1,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "report_hide": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "default": "1",
    "fieldname": "to_rename",
    "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": "To Rename",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 1,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "search_index": 1
   }
  ],
- "has_web_view": 0,
- "hide_heading": 0,
  "hide_toolbar": 1,
  "icon": "fa fa-list",
  "idx": 1,
- "image_view": 0,
  "in_create": 1,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-01-07 07:04:37.523024",
+ "modified": "2019-11-27 12:17:31.522675",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Ledger Entry",
  "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0,
-   "cancel": 0,
-   "create": 0,
-   "delete": 0,
-   "email": 0,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
-   "role": "Stock User",
-   "set_user_permissions": 0,
-   "share": 0,
-   "submit": 0,
-   "write": 0
+   "role": "Stock User"
   },
   {
-   "amend": 0,
-   "cancel": 0,
-   "create": 0,
-   "delete": 0,
-   "email": 0,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
-   "print": 0,
    "read": 1,
    "report": 1,
-   "role": "Accounts Manager",
-   "set_user_permissions": 0,
-   "share": 0,
-   "submit": 0,
-   "write": 0
+   "role": "Accounts Manager"
   }
  ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
  "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 9f47edc..55f4be1 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -254,6 +254,12 @@
 		args['material_request_type'] = frappe.db.get_value('Material Request',
 			args.get('name'), 'material_request_type', cache=True)
 
+	expense_account = None
+
+	if args.get('doctype') == 'Purchase Invoice' and item.is_fixed_asset:
+		from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
+		expense_account = get_asset_category_account(fieldname = "fixed_asset_account", item = args.item_code, company= args.company)
+
 	#Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master
 	if not args.uom:
 		if args.get('doctype') in sales_doctypes:
@@ -271,7 +277,7 @@
 		"image": cstr(item.image).strip(),
 		"warehouse": warehouse,
 		"income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults),
-		"expense_account": get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults),
+		"expense_account": expense_account or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults) ,
 		"cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults),
 		'has_serial_no': item.has_serial_no,
 		'has_batch_no': item.has_batch_no,
diff --git a/erpnext/stock/report/purchase_order_items_to_be_received_or_billed/purchase_order_items_to_be_received_or_billed.json b/erpnext/stock/report/purchase_order_items_to_be_received_or_billed/purchase_order_items_to_be_received_or_billed.json
index caf7eb8..48c0f42 100644
--- a/erpnext/stock/report/purchase_order_items_to_be_received_or_billed/purchase_order_items_to_be_received_or_billed.json
+++ b/erpnext/stock/report/purchase_order_items_to_be_received_or_billed/purchase_order_items_to_be_received_or_billed.json
@@ -15,7 +15,7 @@
  "prepared_report": 0,
  "query": "SELECT\n\t`poi_pri`.`purchase_order` as \"Purchase Order:Link/Purchase Order:120\",\n\t`poi_pri`.`status` as \"Status:Data:120\",\n\t`poi_pri`.`transaction_date` as \"Date:Date:100\",\n\t`poi_pri`.`schedule_date` as \"Reqd by Date:Date:110\",\n\t`poi_pri`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`poi_pri`.`supplier_name` as \"Supplier Name::150\",\n\t`poi_pri`.`item_code` as \"Item Code:Link/Item:120\",\n\t`poi_pri`.`qty` as \"Qty:Float:100\",\n\t`poi_pri`.`base_amount` as  \"Base Amount:Currency:100\",\n\t`poi_pri`.`received_qty` as \"Received Qty:Float:100\",\n\t`poi_pri`.`received_amount` as \"Received Qty Amount:Currency:100\",\n\t`poi_pri`.`qty_to_receive` as \"Qty to Receive:Float:100\",\n\t`poi_pri`.`amount_to_be_received` as \"Amount to Receive:Currency:100\",\n\t`poi_pri`.`billed_amount` as  \"Billed Amount:Currency:100\",\n\t`poi_pri`.`amount_to_be_billed` as  \"Amount To Be Billed:Currency:100\",\n\tSUM(`pii`.`qty`) AS \"Billed Qty:Float:100\",\n\t`poi_pri`.qty - SUM(`pii`.`qty`) AS \"Qty To Be Billed:Float:100\",\n\t`poi_pri`.`warehouse` as \"Warehouse:Link/Warehouse:150\",\n\t`poi_pri`.`item_name` as \"Item Name::150\",\n\t`poi_pri`.`description` as \"Description::200\",\n\t`poi_pri`.`brand` as \"Brand::100\",\n\t`poi_pri`.`project` as \"Project\",\n\t`poi_pri`.`company` as \"Company:Link/Company:\"\nFROM\n\t(SELECT\n\t\t`po`.`name` AS 'purchase_order',\n\t\t`po`.`status`,\n\t\t`po`.`company`,\n\t\t`poi`.`warehouse`,\n\t\t`poi`.`brand`,\n\t\t`poi`.`description`,\n\t\t`po`.`transaction_date`,\n\t\t`poi`.`schedule_date`,\n\t\t`po`.`supplier`,\n\t\t`po`.`supplier_name`,\n\t\t`poi`.`project`,\n\t\t`poi`.`item_code`,\n\t\t`poi`.`item_name`,\n\t\t`poi`.`qty`,\n\t\t`poi`.`base_amount`,\n\t\t`poi`.`received_qty`,\n\t\t(`poi`.billed_amt * ifnull(`po`.conversion_rate, 1)) as billed_amount,\n\t\t(`poi`.base_amount - (`poi`.billed_amt * ifnull(`po`.conversion_rate, 1))) as amount_to_be_billed,\n\t\t`poi`.`qty` - IFNULL(`poi`.`received_qty`, 0) AS 'qty_to_receive',\n\t\t(`poi`.`qty` - IFNULL(`poi`.`received_qty`, 0)) * `poi`.`rate` AS 'amount_to_be_received',\n\t\tSUM(`pri`.`amount`) AS 'received_amount',\n\t\t`poi`.`name` AS 'poi_name',\n\t\t`pri`.`name` AS 'pri_name'\n\tFROM\n\t\t`tabPurchase Order` po\n\t\tLEFT JOIN `tabPurchase Order Item` poi\n\t\tON `poi`.`parent` = `po`.`name`\n\t\tLEFT JOIN `tabPurchase Receipt Item` pri\n\t\tON `pri`.`purchase_order_item` = `poi`.`name`\n\t\t\tAND `pri`.`docstatus`=1\n\tWHERE\n\t\t`po`.`status` not in ('Stopped', 'Closed')\n\t\tAND `po`.`docstatus` = 1\n\t\tAND IFNULL(`poi`.`received_qty`, 0) < IFNULL(`poi`.`qty`, 0)\n\tGROUP BY `poi`.`name`\n\tORDER BY `po`.`transaction_date` ASC\n\t) poi_pri\n\tLEFT JOIN `tabPurchase Invoice Item` pii\n\tON `pii`.`po_detail` = `poi_pri`.`poi_name`\n\t\tAND `pii`.`docstatus`=1\nGROUP BY `poi_pri`.`poi_name`",
  "ref_doctype": "Purchase Order",
- "report_name": "Purchase Order Items To Be Received or Billed1",
+ "report_name": "Purchase Order Items To Be Received or Billed",
  "report_type": "Query Report",
  "roles": [
   {
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index db7f6ad..d757ecb 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -122,8 +122,8 @@
 	cf_field = cf_join = ""
 	if include_uom:
 		cf_field = ", ucd.conversion_factor"
-		cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \
-			% (include_uom)
+		cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom=%s" \
+			% frappe.db.escape(include_uom)
 
 	res = frappe.db.sql("""
 		select
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 2e25a12..cdff3ff 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -1329,7 +1329,7 @@
 apps/erpnext/erpnext/utilities/transaction_base.py,Invalid Posting Time,Ungültige Buchungszeit
 DocType: Salary Component,Condition and Formula,Zustand und Formel
 DocType: Lead,Campaign Name,Kampagnenname
-apps/erpnext/erpnext/setup/default_energy_point_rules.py,On Task Completion,Bei Abschluss der Aufgabe
+apps/erpnext/erpnext/setup/default_energy_point_rules.py,On Task Completion,Bei Abschluss des Vorgangs
 apps/erpnext/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py,There is no leave period in between {0} and {1},Es gibt keinen Urlaub zwischen {0} und {1}
 DocType: Fee Validity,Healthcare Practitioner,praktischer Arzt
 DocType: Hotel Room,Capacity,Kapazität
@@ -1353,7 +1353,7 @@
 apps/erpnext/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py,Payment Cancelled. Please check your GoCardless Account for more details,Zahlung abgebrochen. Bitte überprüfen Sie Ihr GoCardless Konto für weitere Details
 DocType: Work Order,Skip Material Transfer to WIP Warehouse,Überspringen Sie die Materialübertragung in das WIP-Lager
 DocType: Contract,N/A,nicht verfügbar
-DocType: Task Type,Task Type,Aufgabentyp
+DocType: Task Type,Task Type,Vorgangstyp
 DocType: Topic,Topic Content,Themeninhalt
 DocType: Delivery Settings,Send with Attachment,Senden mit Anhang
 DocType: Service Level,Priorities,Prioritäten
@@ -2449,7 +2449,7 @@
 DocType: Asset,Depreciation Schedules,Abschreibungen Termine
 apps/erpnext/erpnext/projects/doctype/timesheet/timesheet.js,Create Sales Invoice,Verkaufsrechnung erstellen
 apps/erpnext/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html,Ineligible ITC,Nicht förderfähiges ITC
-DocType: Task,Dependent Tasks,Abhängige Aufgaben
+DocType: Task,Dependent Tasks,Abhängige Vorgänge
 apps/erpnext/erpnext/regional/report/gstr_1/gstr_1.py,Following accounts might be selected in GST Settings:,In den GST-Einstellungen können folgende Konten ausgewählt werden:
 apps/erpnext/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js,Quantity to Produce,Menge zu produzieren
 apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py,Application period cannot be outside leave allocation period,Beantragter Zeitraum kann nicht außerhalb der beantragten Urlaubszeit liegen
@@ -2846,7 +2846,7 @@
 DocType: Purchase Invoice,03-Deficiency in services,03-Mangel an Dienstleistungen
 DocType: Healthcare Settings,Default Medical Code Standard,Default Medical Code Standard
 DocType: Purchase Invoice Item,HSN/SAC,HSN / SAC
-DocType: Project Template Task,Project Template Task,Projektvorlagenaufgabe
+DocType: Project Template Task,Project Template Task,Projektvorgangsvorlage
 DocType: Accounts Settings,Over Billing Allowance (%),Mehr als Abrechnungsbetrag (%)
 apps/erpnext/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py,Purchase Receipt {0} is not submitted,Kaufbeleg {0} wurde nicht übertragen
 DocType: Company,Default Payable Account,Standard-Verbindlichkeitenkonto
@@ -3323,7 +3323,7 @@
 ,Qty to Order,Zu bestellende Menge
 DocType: Period Closing Voucher,"The account head under Liability or Equity, in which Profit/Loss will be booked","Der Kontenkopf unter Eigen- oder Fremdkapital, in dem Gewinn / Verlust verbucht wird"
 apps/erpnext/erpnext/accounts/doctype/budget/budget.py,Another Budget record '{0}' already exists against {1} '{2}' and account '{3}' for fiscal year {4},Ein weiterer Budgeteintrag &#39;{0}&#39; existiert bereits für {1} &#39;{2}&#39; und für &#39;{3}&#39; für das Geschäftsjahr {4}
-apps/erpnext/erpnext/config/projects.py,Gantt chart of all tasks.,Gantt-Diagramm aller Aufgaben
+apps/erpnext/erpnext/config/projects.py,Gantt chart of all tasks.,Gantt-Diagramm aller Vorgänge
 DocType: Opportunity,Mins to First Response,Minuten zum First Response
 DocType: Pricing Rule,Margin Type,Margenart
 apps/erpnext/erpnext/projects/doctype/project/project_dashboard.html,{0} hours,{0} Stunden
@@ -3961,7 +3961,7 @@
 apps/erpnext/erpnext/education/doctype/student/student_dashboard.py,Student LMS Activity,Student LMS Aktivität
 DocType: POS Profile,Applicable for Users,Anwendbar für Benutzer
 DocType: Supplier Quotation,PUR-SQTN-.YYYY.-,PUR-SQTN-.JJJJ.-
-apps/erpnext/erpnext/projects/doctype/project/project.js,Set Project and all Tasks to status {0}?,Projekt und alle Aufgaben auf Status {0} setzen?
+apps/erpnext/erpnext/projects/doctype/project/project.js,Set Project and all Tasks to status {0}?,Projekt und alle Vorgänge auf Status {0} setzen?
 DocType: Purchase Invoice,Set Advances and Allocate (FIFO),Vorschüsse setzen und zuordnen (FIFO)
 apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.py,No Work Orders created,Keine Arbeitsaufträge erstellt
 apps/erpnext/erpnext/hr/doctype/salary_slip/salary_slip.py,Salary Slip of employee {0} already created for this period,Gehaltsabrechnung der Mitarbeiter {0} für diesen Zeitraum bereits erstellt
@@ -4418,7 +4418,7 @@
 DocType: Hotel Room,Hotels,Hotels
 apps/erpnext/erpnext/accounts/doctype/cost_center/cost_center_tree.js,New Cost Center Name,Neuer Kostenstellenname
 DocType: Leave Control Panel,Leave Control Panel,Urlaubsverwaltung
-DocType: Project,Task Completion,Aufgabenerledigung
+DocType: Project,Task Completion,Vorgangserfüllung
 apps/erpnext/erpnext/templates/generators/item/item_add_to_cart.html,Not in Stock,Nicht lagernd
 DocType: Volunteer,Volunteer Skills,Freiwillige Fähigkeiten
 DocType: Additional Salary,HR User,Nutzer Personalabteilung
@@ -5197,7 +5197,7 @@
 apps/erpnext/erpnext/accounts/report/general_ledger/general_ledger.py,Account {0} does not exists,Konto {0} existiert nicht
 apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.js,Select Loyalty Program,Wählen Sie Treueprogramm
 DocType: Project,Project Type,Projekttyp
-apps/erpnext/erpnext/projects/doctype/task/task.py,Child Task exists for this Task. You can not delete this Task.,Für diese Aufgabe existiert eine untergeordnete Aufgabe. Sie können diese Aufgabe daher nicht löschen.
+apps/erpnext/erpnext/projects/doctype/task/task.py,Child Task exists for this Task. You can not delete this Task.,Für diesen Vorgang existiert ein untergeordneter Vorgang. Sie können diese Aufgabe daher nicht löschen.
 apps/erpnext/erpnext/setup/doctype/sales_person/sales_person.py,Either target qty or target amount is mandatory.,Entweder Zielstückzahl oder Zielmenge ist zwingend erforderlich.
 apps/erpnext/erpnext/config/projects.py,Cost of various activities,Aufwendungen für verschiedene Tätigkeiten
 apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py,"Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}","Einstellen Events auf {0}, da die Mitarbeiter auf die beigefügten unter Verkaufs Personen keine Benutzer-ID {1}"
@@ -5597,7 +5597,7 @@
 apps/erpnext/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py,{0} is not a valid Batch Number for Item {1},{0} ist keine gültige Chargennummer für Artikel {1}
 apps/erpnext/erpnext/shopping_cart/cart.py,Please enter valid coupon code !!,Bitte geben Sie einen gültigen Gutscheincode ein !!
 apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py,Note: There is not enough leave balance for Leave Type {0},Hinweis: Es gibt nicht genügend Urlaubsguthaben für Abwesenheitstyp {0}
-DocType: Task,Task Description,Aufgabenbeschreibung
+DocType: Task,Task Description,Vorgangsbeschreibung
 DocType: Training Event,Seminar,Seminar
 DocType: Program Enrollment Fee,Program Enrollment Fee,Programm Einschreibegebühr
 DocType: Item,Supplier Items,Lieferantenartikel
@@ -5754,7 +5754,7 @@
 DocType: Lost Reason Detail,Lost Reason Detail,Verlorene Begründung Detail
 apps/erpnext/erpnext/hr/utils.py,Please set leave policy for employee {0} in Employee / Grade record,Legen Sie die Abwesenheitsrichtlinie für den Mitarbeiter {0} im Mitarbeiter- / Notensatz fest
 apps/erpnext/erpnext/public/js/controllers/transaction.js,Invalid Blanket Order for the selected Customer and Item,Ungültiger Blankoauftrag für den ausgewählten Kunden und Artikel
-apps/erpnext/erpnext/projects/doctype/task/task_tree.js,Add Multiple Tasks,Mehrere Aufgaben hinzufügen
+apps/erpnext/erpnext/projects/doctype/task/task_tree.js,Add Multiple Tasks,Mehrere Vorgänge hinzufügen
 DocType: Purchase Invoice,Items,Artikel
 apps/erpnext/erpnext/crm/doctype/contract/contract.py,End Date cannot be before Start Date.,Das Enddatum darf nicht vor dem Startdatum liegen.
 apps/erpnext/erpnext/education/doctype/course_enrollment/course_enrollment.py,Student is already enrolled.,Student ist bereits eingetragen sind.