Fixed asset: status, restore, testcase and much more
diff --git a/erpnext/accounts/doctype/asset/asset.js b/erpnext/accounts/doctype/asset/asset.js
index 91d41e5..0b28a36 100644
--- a/erpnext/accounts/doctype/asset/asset.js
+++ b/erpnext/accounts/doctype/asset/asset.js
@@ -17,10 +17,16 @@
 	},
 	
 	refresh: function(frm) {
-		if(frm.doc.docstatus==1 && frm.doc.status=='Available') {
-			cur_frm.add_custom_button("Scrap", function() {
-				erpnext.asset.scrap_asset(frm);
-			});
+		if (frm.doc.docstatus==1) {
+			if (in_list(["Submittted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) {
+				cur_frm.add_custom_button("Scrap Asset", function() {
+					erpnext.asset.scrap_asset(frm);
+				});
+			} else if (frm.doc.status=='Scrapped') {
+				cur_frm.add_custom_button("Restore Asset", function() {
+					erpnext.asset.restore_asset(frm);
+				});
+			}
 		}
 	}
 });
@@ -37,4 +43,18 @@
 			}
 		})
 	})
+}
+
+erpnext.asset.restore_asset = function(frm) {
+	frappe.confirm(__("Do you really want to restore this scrapped asset?"), function () {
+		frappe.call({
+			args: {
+				"asset_name": frm.doc.name
+			},
+			method: "erpnext.accounts.doctype.asset.depreciation.restore_asset",
+			callback: function(r) {
+				cur_frm.reload_doc();
+			}
+		})
+	})
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset/asset.json b/erpnext/accounts/doctype/asset/asset.json
index 8c29c44..6dfef0f 100644
--- a/erpnext/accounts/doctype/asset/asset.json
+++ b/erpnext/accounts/doctype/asset/asset.json
@@ -90,7 +90,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "default": "Available", 
+   "default": "Draft", 
    "fieldname": "status", 
    "fieldtype": "Select", 
    "hidden": 0, 
@@ -101,7 +101,7 @@
    "label": "Status", 
    "length": 0, 
    "no_copy": 1, 
-   "options": "Available\nSold\nScrapped", 
+   "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -244,6 +244,32 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "journal_entry_for_scrap", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Journal Entry for Scrap", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "Journal Entry", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "section_break_5", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -356,7 +382,7 @@
    "in_list_view": 0, 
    "label": "Next Depreciation Date", 
    "length": 0, 
-   "no_copy": 0, 
+   "no_copy": 1, 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -458,7 +484,7 @@
    "in_list_view": 0, 
    "label": "Current Value (After Depreciation)", 
    "length": 0, 
-   "no_copy": 0, 
+   "no_copy": 1, 
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
@@ -557,7 +583,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2016-03-09 12:22:05.223886", 
+ "modified": "2016-03-11 12:23:37.114298", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Asset", 
diff --git a/erpnext/accounts/doctype/asset/asset.py b/erpnext/accounts/doctype/asset/asset.py
index 488ba6a..05c3bc3 100644
--- a/erpnext/accounts/doctype/asset/asset.py
+++ b/erpnext/accounts/doctype/asset/asset.py
@@ -10,14 +10,20 @@
 
 class Asset(Document):
 	def validate(self):
+		self.set_status()
 		self.validate_fixed_asset_item()
 		self.validate_asset_values()
 		self.set_depreciation_settings()
 		self.make_depreciation_schedule()
+		self.validate_depreciation_settings_in_company()
+		
+	def on_submit(self):
+		self.set_status()
 		
 	def on_cancel(self):
 		self.validate_cancellation()
 		self.delete_depreciation_entries()
+		self.set_status()
 		
 	def validate_fixed_asset_item(self):
 		item = frappe.get_doc("Item", self.item_code)
@@ -49,7 +55,7 @@
 				
 	def make_depreciation_schedule(self):
 		self.schedules = []
-		if not self.get("schedules") and self.status == "Available":
+		if not self.get("schedules"):
 			accumulated_depreciation = 0
 			value_after_depreciation = flt(self.current_value)
 			for n in xrange(self.number_of_depreciations):
@@ -71,8 +77,8 @@
 			depreciation_amount = (flt(self.current_value) - 
 				flt(self.expected_value_after_useful_life)) / cint(self.number_of_depreciations)
 		else:
-			factor = 200 /  cint(self.number_of_depreciations)
-			depreciation_amount = depreciable_value * factor / 100
+			factor = 200.0 /  cint(self.number_of_depreciations)
+			depreciation_amount = flt(depreciable_value * factor / 100, 0)
 
 			value_after_depreciation = flt(depreciable_value) - depreciation_amount
 			if value_after_depreciation < flt(self.expected_value_after_useful_life):
@@ -81,9 +87,11 @@
 		return depreciation_amount
 		
 	def validate_cancellation(self):
-		if self.status != "Available":
-			frappe.throw(_("Asset {0} cannot be cancelled, as it is already {1}")
-				.format(self.name, self.status))
+		if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
+			frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))
+				
+		if self.purchase_invoice:
+			frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
 		
 	def delete_depreciation_entries(self):
 		total_depreciation_amount = 0
@@ -94,4 +102,28 @@
 				d.db_set("journal_entry", None)
 				total_depreciation_amount += flt(d.depreciation_amount)
 		self.db_set("current_value", (self.current_value - total_depreciation_amount))
-	
\ No newline at end of file
+		
+	def validate_depreciation_settings_in_company(self):
+		company = frappe.get_doc("Company", self.company)
+		for field in ("accumulated_depreciation_account", "depreciation_expense_account", 
+			"disposal_account", "depreciation_cost_center"):
+				if not company.get(field):
+					frappe.throw(_("Please set {0} in Company {1}")
+						.format(company.meta.get_label(field), self.company))
+	
+	def set_status(self, status=None):
+		if not status:
+			if self.docstatus == 0:
+				status = "Draft"
+			elif self.docstatus == 1:
+				status = "Submitted"
+				if self.journal_entry_for_scrap:
+					status = "Scrapped"
+				elif flt(self.current_value) <= flt(self.expected_value_after_useful_life):
+					status = "Fully Depreciated"
+				elif flt(self.current_value) < flt(self.gross_purchase_amount):
+					status = 'Partially Depreciated'
+			elif self.docstatus == 2:
+				status = "Cancelled"
+
+		frappe.db.set_value(self.doctype, self.name, "status", status)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset/depreciation.py b/erpnext/accounts/doctype/asset/depreciation.py
index bd2c74f..8889c81 100644
--- a/erpnext/accounts/doctype/asset/depreciation.py
+++ b/erpnext/accounts/doctype/asset/depreciation.py
@@ -17,7 +17,8 @@
 	return frappe.db.sql_list("""select a.name
 		from tabAsset a, `tabDepreciation Schedule` ds
 		where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s 
-			and a.status = 'Available' and ifnull(ds.journal_entry, '')=''""", date)
+			and a.status in ('Submitted', 'Partially Depreciated') 
+			and ifnull(ds.journal_entry, '')=''""", date)
 
 def make_depreciation_entry(asset_name, date=None):
 	if not date:
@@ -26,6 +27,8 @@
 	asset = frappe.get_doc("Asset", asset_name)
 	fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
 		get_depreciation_accounts(asset)
+		
+	depreciation_cost_center = frappe.db.get_value("Company", asset.company, "depreciation_cost_center")
 	
 	for d in asset.get("schedules"):
 		if not d.journal_entry and getdate(d.schedule_date) <= getdate(date):
@@ -34,7 +37,7 @@
 			je.posting_date = d.schedule_date
 			je.company = asset.company
 			je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount)
-	
+			
 			je.append("accounts", {
 				"account": accumulated_depreciation_account,
 				"credit_in_account_currency": d.depreciation_amount,
@@ -46,15 +49,18 @@
 				"account": depreciation_expense_account,
 				"debit_in_account_currency": d.depreciation_amount,
 				"reference_type": "Asset",
-				"reference_name": asset.name
+				"reference_name": asset.name,
+				"cost_center": depreciation_cost_center
 			})
-	
+			
 			je.flags.ignore_permissions = True
 			je.submit()
 	
 			d.db_set("journal_entry", je.name)
 			asset.current_value -= d.depreciation_amount
-			frappe.db.set_value("Asset", asset_name, "current_value", asset.current_value)			
+			
+		asset.db_set("current_value", asset.current_value)
+		asset.set_status()
 	
 def get_depreciation_accounts(asset):
 	accounts = frappe.db.sql("""select fixed_asset_account, accumulated_depreciation_account, 
@@ -84,8 +90,10 @@
 def scrap_asset(asset_name):
 	asset = frappe.get_doc("Asset", asset_name)
 	
-	if asset.docstatus != 1 or asset.status != 'Available':
-		frappe.throw(_("Asset {0} must be submitted and available").format(asset.name))
+	if asset.docstatus != 1:
+		frappe.throw(_("Asset {0} must be submitted").format(asset.name))
+	elif asset.status in ("Cancelled", "Sold", "Scrapped"):
+		frappe.throw(_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status))
 
 	je = frappe.new_doc("Journal Entry")
 	je.voucher_type = "Journal Entry"
@@ -103,12 +111,23 @@
 	je.flags.ignore_permissions = True
 	je.submit()
 	
-	frappe.db.set_value("Asset", asset_name, "status", "Scrapped")
+	frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
+	asset.set_status("Scrapped")
 	
 @frappe.whitelist()
+def restore_asset(asset_name):
+	asset = frappe.get_doc("Asset", asset_name)
+	
+	je = asset.journal_entry_for_scrap
+	asset.db_set("journal_entry_for_scrap", None)
+	frappe.get_doc("Journal Entry", je).cancel()
+	
+	asset.set_status()
+		
+@frappe.whitelist()
 def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
 	fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset)
-	disposal_account, disposal_cost_center = get_disposal_account_and_cost_center(asset.company)
+	disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
 	accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(asset.current_value)
 	
 	gl_entries = [
@@ -129,7 +148,7 @@
 		debit_or_credit = "debit" if profit_amount < 0 else "credit"
 		gl_entries.append({
 			"account": disposal_account,
-			"cost_center": disposal_cost_center,
+			"cost_center": depreciation_cost_center,
 			debit_or_credit: abs(profit_amount),
 			debit_or_credit + "_in_account_currency": abs(profit_amount)
 		})
@@ -137,8 +156,12 @@
 	return gl_entries
 	
 def get_disposal_account_and_cost_center(company):
-	disposal_account, disposal_cost_center = frappe.db.get_value("Company", company, 
-		["disposal_account", "disposal_cost_center"])
-	if not disposal_account or not disposal_cost_center:
-		frappe.throw(_("Please set 'Asset Disposal Account' and 'Asset Disposal Cost Center' in Company {0}").format(company))
-	return disposal_account, disposal_cost_center
\ No newline at end of file
+	disposal_account, depreciation_cost_center = frappe.db.get_value("Company", company, 
+		["disposal_account", "depreciation_cost_center"])
+		
+	if not disposal_account:
+		frappe.throw(_("Please set 'Asset Disposal Account' in Company {0}").format(company))
+	if not depreciation_cost_center:
+		frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company))
+		
+	return disposal_account, depreciation_cost_center
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset/test_asset.py b/erpnext/accounts/doctype/asset/test_asset.py
index 031fcc2..9902034 100644
--- a/erpnext/accounts/doctype/asset/test_asset.py
+++ b/erpnext/accounts/doctype/asset/test_asset.py
@@ -5,9 +5,13 @@
 
 import frappe
 import unittest
+from frappe.utils import cstr
+from erpnext.accounts.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
 
 class TestAsset(unittest.TestCase):
 	def setUp(self):
+		set_depreciation_settings_in_company()
 		create_asset()
 		
 	def test_fixed_asset_must_be_non_stock_item(self):
@@ -15,11 +19,128 @@
 		item.is_stock_item = 1
 		self.assertRaises(frappe.ValidationError, item.save)
 	
-	def test_asset_purchase(self):
-		asset = create_asset()
+	def test_schedule_for_straight_line_method(self):
+		asset = frappe.get_doc("Asset", "Macbook Pro 1")
 		
-		self.assertEqual(asset.current_value, 100000)
-
+		self.assertEqual(asset.status, "Draft")
+		
+		expected_schedules = [
+			["2015-12-31", 30000, 30000],
+			["2016-03-31", 30000, 60000],
+			["2016-06-30", 30000, 90000]
+		]
+		
+		schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] 
+			for d in asset.get("schedules")]
+		
+		self.assertEqual(schedules, expected_schedules)
+		
+		
+	def test_schedule_for_double_declining_method(self):
+		asset = frappe.get_doc("Asset", "Macbook Pro 1")
+		asset.depreciation_method = "Double Declining Balance"
+		asset.save()
+		
+		expected_schedules = [
+			["2015-12-31", 66667, 66667],
+			["2016-03-31", 22222, 88889],
+			["2016-06-30", 1111, 90000]
+		]
+		
+		schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] 
+			for d in asset.get("schedules")]
+		
+		self.assertEqual(schedules, expected_schedules)
+		
+	def test_depreciation(self):
+		asset = frappe.get_doc("Asset", "Macbook Pro 1")
+		asset.submit()
+		asset.load_from_db()
+		self.assertEqual(asset.status, "Submitted")
+		
+		post_depreciation_entries(date="2016-01-01")
+		asset.load_from_db()
+		
+		self.assertEqual(asset.status, "Partially Depreciated")
+		
+		expected_gle = (
+			("_Test Accumulated Depreciations - _TC", 0.0, 30000.0),
+			("_Test Depreciations - _TC", 30000.0, 0.0)
+		)
+		
+		gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` 
+			where against_voucher_type='Asset' and against_voucher = %s
+			order by account""", asset.name)
+			
+		self.assertEqual(gle, expected_gle)
+		self.assertEqual(asset.get("current_value"), 70000)
+		
+		
+	def test_scrap_asset(self):
+		asset = frappe.get_doc("Asset", "Macbook Pro 1")
+		asset.submit()
+		post_depreciation_entries(date="2016-01-01")
+		
+		scrap_asset("Macbook Pro 1")
+		
+		asset.load_from_db()
+		self.assertEqual(asset.status, "Scrapped")
+		self.assertTrue(asset.journal_entry_for_scrap)
+		
+		expected_gle = (
+			("_Test Accumulated Depreciations - _TC", 30000.0, 0.0),
+			("_Test Fixed Asset - _TC", 0.0, 100000.0),
+			("_Test Gain/Loss on Asset Disposal - _TC", 70000.0, 0.0)
+		)
+		
+		gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` 
+			where voucher_type='Journal Entry' and voucher_no = %s
+			order by account""", asset.journal_entry_for_scrap)
+		
+		self.assertEqual(gle, expected_gle)
+		
+		restore_asset("Macbook Pro 1")
+		
+		asset.load_from_db()
+		self.assertFalse(asset.journal_entry_for_scrap)
+		self.assertEqual(asset.status, "Partially Depreciated")
+		
+	def test_asset_sale(self):
+		frappe.get_doc("Asset", "Macbook Pro 1").submit()
+		post_depreciation_entries(date="2016-01-01")
+		
+		si = create_sales_invoice(item_code="Macbook Pro", rate=25000, do_not_save=True)
+		si.get("items")[0].asset = "Macbook Pro 1"
+		si.submit()
+		
+		self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Sold")
+		
+		expected_gle = (
+			("_Test Accumulated Depreciations - _TC", 30000.0, 0.0),
+			("_Test Fixed Asset - _TC", 0.0, 100000.0),
+			("_Test Gain/Loss on Asset Disposal - _TC", 45000.0, 0.0),
+			("Debtors - _TC", 25000.0, 0.0)
+		)
+		
+		gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` 
+			where voucher_type='Sales Invoice' and voucher_no = %s
+			order by account""", si.name)
+		
+		self.assertEqual(gle, expected_gle)
+		
+		si.cancel()
+		
+		self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Partially Depreciated")
+		
+	def tearDown(self):
+		asset = frappe.get_doc("Asset", "Macbook Pro 1")
+		
+		if asset.docstatus == 1 and asset.status not in ("Scrapped", "Sold", "Draft", "Cancelled"):
+			asset.cancel()
+			
+			self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Cancelled")
+		
+		frappe.delete_doc("Asset", "Macbook Pro 1")
 
 def create_asset():
 	if not frappe.db.exists("Asset Category", "Computers"):
@@ -33,6 +154,7 @@
 		"asset_name": "Macbook Pro 1",
 		"asset_category": "Computers",
 		"item_code": "Macbook Pro",
+		"company": "_Test Company",
 		"purchase_date": "2015-01-01",
 		"next_depreciation_date": "2015-12-31",
 		"gross_purchase_amount": 100000,
@@ -48,8 +170,8 @@
 def create_asset_category():
 	asset_category = frappe.new_doc("Asset Category")
 	asset_category.asset_category_name = "Computers"
-	asset_category.number_of_depreciations = 5
-	asset_category.number_of_months_in_a_period = 12
+	asset_category.number_of_depreciations = 3
+	asset_category.number_of_months_in_a_period = 3
 	asset_category.append("accounts", {
 		"company": "_Test Company",
 		"fixed_asset_account": "_Test Fixed Asset - _TC",
@@ -73,4 +195,10 @@
 	except frappe.DuplicateEntryError:
 		pass
 	
-	
\ No newline at end of file
+def set_depreciation_settings_in_company():
+	company = frappe.get_doc("Company", "_Test Company")
+	company.accumulated_depreciation_account = "_Test Accumulated Depreciations - _TC"
+	company.depreciation_expense_account = "_Test Depreciations - _TC"
+	company.disposal_account = "_Test Gain/Loss on Asset Disposal - _TC"
+	company.depreciation_cost_center = "_Test Cost Center - _TC"
+	company.save()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_category/test_asset_category.py b/erpnext/accounts/doctype/asset_category/test_asset_category.py
index 1fe4aae..d119066 100644
--- a/erpnext/accounts/doctype/asset_category/test_asset_category.py
+++ b/erpnext/accounts/doctype/asset_category/test_asset_category.py
@@ -18,7 +18,7 @@
 		asset_category.append("accounts", {
 			"company": "_Test Company",
 			"fixed_asset_account": "_Test Fixed Asset - _TC",
-			"accumulated_depreciation_account": "_Test Accoumulated Depreciations - _TC",
+			"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
 			"depreciation_expense_account": "_Test Depreciations - _TC"
 		})
 		
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 9505528..dd8d51e 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -88,8 +88,8 @@
 					"Cost Center", self.cost_center, "company")
 
 			return self.cost_center_company[self.cost_center]
-
-		if self.cost_center and _get_cost_center_company() != self.company:
+		
+		if self.cost_center and _get_cost_center_company() != self.company:	
 			frappe.throw(_("Cost Center {0} does not belong to Company {1}").format(self.cost_center, self.company))
 
 	def validate_party(self):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 0143a4f..bcb0503 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -217,7 +217,7 @@
 			'item_code': d.item_code,
 			'docstatus': 1,
 			'company': doc.company,
-			'status': 'Available'
+			'status': 'Submitted'
 		}
 	}
 });
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 06b2ece..7d9745b 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -237,7 +237,7 @@
 
 	def on_submit(self):
 		self.check_prev_docstatus()
-		self.post_asset_depreciation()
+		self.validate_asset()
 
 		frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
 			self.company, self.base_grand_total)
@@ -252,29 +252,30 @@
 
 		self.update_project()
 		
-	def post_asset_depreciation(self):
+	def validate_asset(self):
 		for d in self.get("items"):
 			if frappe.db.get_value("Item", d.item_code, "is_fixed_asset"):
 				if not d.asset:
 					frappe.throw(_("Row #{0}: Asset is mandatory against a Fixed Asset Item").format(d.idx))
 				else:
 					asset = frappe.get_doc("Asset", d.asset)
-					self.validate_asset(asset, d)
+					
+					super(PurchaseInvoice, self).validate_asset(asset, d)
+		
+					if getdate(asset.purchase_date) != getdate(self.posting_date):
+						frappe.throw(_("Purchase Date of asset {0} does not match with Purchase Invoice date")
+							.format(d.asset))
+					
+					if asset.supplier != self.supplier:
+						frappe.throw(_("Supplier of asset {0} does not match with the supplier in the Purchase Invoice").format(d.asset))
+				
+					if asset.status != "Available":
+						frappe.throw(_("Row #{0}: Asset {1} is already {2}")
+							.format(d.idx, d.asset, asset.status))
 					
 					frappe.db.set_value("Asset", asset.name, "purchase_invoice", 
 						(self.name if self.docstatus==1 else None))
-							
-	def validate_asset(self, asset, item_row):
-		super(PurchaseInvoice, self).validate_asset(asset, item_row)
-		
-		if getdate(asset.purchase_date) != getdate(self.posting_date):
-			frappe.throw(_("Purchase Date of asset {0} does not match with Purchase Invoice date")
-				.format(item_row.asset))
-				
-		if asset.supplier != self.supplier:
-			frappe.throw(_("Supplier of asset {0} does not match with the supplier in the Purchase Invoice")
-				.format(item_row.asset))
-		
+					
 	def make_gl_entries(self):
 		auto_accounting_for_stock = \
 			cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
@@ -441,7 +442,7 @@
 
 		self.make_gl_entries_on_cancel()
 		self.update_project()
-		self.post_asset_depreciation()
+		self.validate_asset()
 
 	def update_project(self):
 		project_list = []
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 265e697..f6f746a 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -475,11 +475,11 @@
 cur_frm.set_query("asset", "items", function(doc, cdt, cdn) {
 	var d = locals[cdt][cdn];
 	return {
-		filters: {
-			'item_code': d.item_code,
-			'docstatus': 1,
-			'company': doc.company,
-			'status': 'Available'
-		}
+		filters: [
+			["Asset", "item_code", "=", d.item_code],
+			["Asset", "docstatus", "=", 1],
+			["Asset", "status", "in", ["Submitted", "Partially Depreciated", "Fully Depreciated"]],
+			["Asset", "company", "=", doc.company]
+		]
 	}
 });
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 9758067..9ffe8a9 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -484,6 +484,13 @@
 
 			if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
 				throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
+				
+	def validate_asset(self, asset, item_row):
+		super(SalesInvoice, self).validate_asset(asset, item_row)
+		
+		if self.docstatus == 1 and asset.status in ("Scrapped", "Cancelled", "Sold"):
+			frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}")
+				.format(item_row.idx, asset.name, asset.status))
 
 	def make_gl_entries(self, repost_future_gle=True):
 		gl_entries = self.get_gl_entries()
@@ -582,7 +589,7 @@
 						for gle in fixed_asset_gl_entries:
 							gl_entries.append(self.get_gl_dict(gle))
 						
-						frappe.db.set_value("Asset", asset.name, "status", "Sold")
+						asset.set_status("Sold" if self.docstatus==1 else None)
 				else:
 					account_currency = get_account_currency(item.income_account)
 					gl_entries.append(
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 777fe1e..dfa6c0a 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -141,7 +141,7 @@
 		["disposal_account", {"report_type": "Profit and Loss"}],
 		["cost_center", {}],
 		["round_off_cost_center", {}],
-		["disposal_cost_center", {}]
+		["depreciation_cost_center", {}]
 	], function(i, v) {
 		erpnext.company.set_custom_query(frm, v);
 	});
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index be63aac..9d6785d 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -1091,14 +1091,14 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "disposal_cost_center", 
+   "fieldname": "depreciation_cost_center", 
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Asset Disposal Cost Center", 
+   "label": "Asset Depreciation Cost Center", 
    "length": 0, 
    "no_copy": 1, 
    "options": "Cost Center", 
@@ -1387,7 +1387,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2016-03-09 12:06:12.189968", 
+ "modified": "2016-03-10 04:34:43.440914", 
  "modified_by": "Administrator", 
  "module": "Setup", 
  "name": "Company", 
@@ -1536,6 +1536,5 @@
  ], 
  "read_only": 0, 
  "read_only_onload": 0, 
- "sort_order": "ASC", 
- "version": 0
+ "sort_order": "ASC"
 }
\ No newline at end of file