Merge branch 'develop' into fix-clear-depr-schedule
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index c0c437f..351556c 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -185,84 +185,85 @@
 		if not self.available_for_use_date:
 			return
 
-		for d in self.get('finance_books'):
-			self.validate_asset_finance_books(d)
+		start = self.clear_depreciation_schedule()
 
-			start = self.clear_depreciation_schedule()
+		for finance_book in self.get('finance_books'):
+			self.validate_asset_finance_books(finance_book)
 
 			# value_after_depreciation - current Asset value
-			if self.docstatus == 1 and d.value_after_depreciation:
-				value_after_depreciation = (flt(d.value_after_depreciation) -
+			if self.docstatus == 1 and finance_book.value_after_depreciation:
+				value_after_depreciation = (flt(finance_book.value_after_depreciation) -
 					flt(self.opening_accumulated_depreciation))
 			else:
 				value_after_depreciation = (flt(self.gross_purchase_amount) -
 					flt(self.opening_accumulated_depreciation))
 
-			d.value_after_depreciation = value_after_depreciation
+			finance_book.value_after_depreciation = value_after_depreciation
 
-			number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
+			number_of_pending_depreciations = cint(finance_book.total_number_of_depreciations) - \
 				cint(self.number_of_depreciations_booked)
 
-			has_pro_rata = self.check_is_pro_rata(d)
+			has_pro_rata = self.check_is_pro_rata(finance_book)
 
 			if has_pro_rata:
 				number_of_pending_depreciations += 1
 
 			skip_row = False
-			for n in range(start, number_of_pending_depreciations):
+
+			for n in range(start[finance_book.idx-1], number_of_pending_depreciations):
 				# If depreciation is already completed (for double declining balance)
 				if skip_row: continue
 
-				depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d)
+				depreciation_amount = get_depreciation_amount(self, value_after_depreciation, finance_book)
 
 				if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
-					schedule_date = add_months(d.depreciation_start_date,
-						n * cint(d.frequency_of_depreciation))
+					schedule_date = add_months(finance_book.depreciation_start_date,
+						n * cint(finance_book.frequency_of_depreciation))
 
 					# schedule date will be a year later from start date
 					# so monthly schedule date is calculated by removing 11 months from it
-					monthly_schedule_date = add_months(schedule_date, - d.frequency_of_depreciation + 1)
+					monthly_schedule_date = add_months(schedule_date, - finance_book.frequency_of_depreciation + 1)
 
 				# if asset is being sold
 				if date_of_sale:
-					from_date = self.get_from_date(d.finance_book)
-					depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
+					from_date = self.get_from_date(finance_book.finance_book)
+					depreciation_amount, days, months = self.get_pro_rata_amt(finance_book, depreciation_amount,
 						from_date, date_of_sale)
 
 					if depreciation_amount > 0:
 						self.append("schedules", {
 							"schedule_date": date_of_sale,
 							"depreciation_amount": depreciation_amount,
-							"depreciation_method": d.depreciation_method,
-							"finance_book": d.finance_book,
-							"finance_book_id": d.idx
+							"depreciation_method": finance_book.depreciation_method,
+							"finance_book": finance_book.finance_book,
+							"finance_book_id": finance_book.idx
 						})
 
 					break
 
 				# For first row
 				if has_pro_rata and n==0:
-					depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
-						self.available_for_use_date, d.depreciation_start_date)
+					depreciation_amount, days, months = self.get_pro_rata_amt(finance_book, depreciation_amount,
+						self.available_for_use_date, finance_book.depreciation_start_date)
 
 					# For first depr schedule date will be the start date
 					# so monthly schedule date is calculated by removing month difference between use date and start date
-					monthly_schedule_date = add_months(d.depreciation_start_date, - months + 1)
+					monthly_schedule_date = add_months(finance_book.depreciation_start_date, - months + 1)
 
 				# For last row
 				elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
 					if not self.flags.increase_in_asset_life:
 						# In case of increase_in_asset_life, the self.to_date is already set on asset_repair submission
 						self.to_date = add_months(self.available_for_use_date,
-							n * cint(d.frequency_of_depreciation))
+							n * cint(finance_book.frequency_of_depreciation))
 
 					depreciation_amount_without_pro_rata = depreciation_amount
 
-					depreciation_amount, days, months = self.get_pro_rata_amt(d,
+					depreciation_amount, days, months = self.get_pro_rata_amt(finance_book,
 						depreciation_amount, schedule_date, self.to_date)
 
 					depreciation_amount = self.get_adjusted_depreciation_amount(depreciation_amount_without_pro_rata,
-						depreciation_amount, d.finance_book)
+						depreciation_amount, finance_book.finance_book)
 
 					monthly_schedule_date = add_months(schedule_date, 1)
 					schedule_date = add_days(schedule_date, days)
@@ -273,10 +274,10 @@
 					self.precision("gross_purchase_amount"))
 
 				# Adjust depreciation amount in the last period based on the expected value after useful life
-				if d.expected_value_after_useful_life and ((n == cint(number_of_pending_depreciations) - 1
-					and value_after_depreciation != d.expected_value_after_useful_life)
-					or value_after_depreciation < d.expected_value_after_useful_life):
-					depreciation_amount += (value_after_depreciation - d.expected_value_after_useful_life)
+				if finance_book.expected_value_after_useful_life and ((n == cint(number_of_pending_depreciations) - 1
+					and value_after_depreciation != finance_book.expected_value_after_useful_life)
+					or value_after_depreciation < finance_book.expected_value_after_useful_life):
+					depreciation_amount += (value_after_depreciation - finance_book.expected_value_after_useful_life)
 					skip_row = True
 
 				if depreciation_amount > 0:
@@ -286,7 +287,7 @@
 						# In pro rata case, for first and last depreciation, month range would be different
 						month_range = months \
 							if (has_pro_rata and n==0) or (has_pro_rata and n == cint(number_of_pending_depreciations) - 1) \
-							else d.frequency_of_depreciation
+							else finance_book.frequency_of_depreciation
 
 						for r in range(month_range):
 							if (has_pro_rata and n == 0):
@@ -312,27 +313,52 @@
 							self.append("schedules", {
 								"schedule_date": date,
 								"depreciation_amount": amount,
-								"depreciation_method": d.depreciation_method,
-								"finance_book": d.finance_book,
-								"finance_book_id": d.idx
+								"depreciation_method": finance_book.depreciation_method,
+								"finance_book": finance_book.finance_book,
+								"finance_book_id": finance_book.idx
 							})
 					else:
 						self.append("schedules", {
 							"schedule_date": schedule_date,
 							"depreciation_amount": depreciation_amount,
-							"depreciation_method": d.depreciation_method,
-							"finance_book": d.finance_book,
-							"finance_book_id": d.idx
+							"depreciation_method": finance_book.depreciation_method,
+							"finance_book": finance_book.finance_book,
+							"finance_book_id": finance_book.idx
 						})
 
-	# used when depreciation schedule needs to be modified due to increase in asset life
+	# depreciation schedules need to be cleared before modification due to increase in asset life/asset sales
+	# JE: Journal Entry, FB: Finance Book
 	def clear_depreciation_schedule(self):
-		start = 0
-		for n in range(len(self.schedules)):
-			if not self.schedules[n].journal_entry:
-				del self.schedules[n:]
-				start = n
-				break
+		start = []
+		num_of_depreciations_completed = 0
+		depr_schedule = []
+
+		for schedule in self.get('schedules'):
+
+			# to update start when there are JEs linked with all the schedule rows corresponding to an FB
+			if len(start) == (int(schedule.finance_book_id) - 2):
+				start.append(num_of_depreciations_completed)
+				num_of_depreciations_completed = 0
+
+			# to ensure that start will only be updated once for each FB
+			if len(start) == (int(schedule.finance_book_id) - 1):
+				if schedule.journal_entry:
+					num_of_depreciations_completed += 1
+					depr_schedule.append(schedule)
+				else:
+					start.append(num_of_depreciations_completed)
+					num_of_depreciations_completed = 0
+
+		# to update start when all the schedule rows corresponding to the last FB are linked with JEs
+		if len(start) == (len(self.finance_books) - 1):
+			start.append(num_of_depreciations_completed)
+
+		# when the Depreciation Schedule is being created for the first time
+		if start == []:
+			start = [0] * len(self.finance_books)
+		else:
+			self.schedules = depr_schedule
+
 		return start
 
 	def get_from_date(self, finance_book):
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index d1d4527..a297a5a 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -890,6 +890,82 @@
 
 		self.assertEqual(len(asset.schedules), 1)
 
+	def test_clear_depreciation_schedule_for_multiple_finance_books(self):
+		asset = create_asset(
+			item_code = "Macbook Pro",
+			available_for_use_date = "2019-12-31",
+			do_not_save = 1
+		)
+
+		asset.calculate_depreciation = 1
+		asset.append("finance_books", {
+			"depreciation_method": "Straight Line",
+			"frequency_of_depreciation": 1,
+			"total_number_of_depreciations": 3,
+			"expected_value_after_useful_life": 10000,
+			"depreciation_start_date": "2020-01-31"
+		})
+		asset.append("finance_books", {
+			"depreciation_method": "Straight Line",
+			"frequency_of_depreciation": 1,
+			"total_number_of_depreciations": 6,
+			"expected_value_after_useful_life": 10000,
+			"depreciation_start_date": "2020-01-31"
+		})
+		asset.append("finance_books", {
+			"depreciation_method": "Straight Line",
+			"frequency_of_depreciation": 12,
+			"total_number_of_depreciations": 3,
+			"expected_value_after_useful_life": 10000,
+			"depreciation_start_date": "2020-12-31"
+		})
+		asset.submit()
+
+		post_depreciation_entries(date="2020-04-01")
+		asset.load_from_db()
+
+		asset.clear_depreciation_schedule()
+
+		self.assertEqual(len(asset.schedules), 6)
+
+		for schedule in asset.schedules:
+			if schedule.idx <= 3:
+				self.assertEqual(schedule.finance_book_id, "1")
+			else:
+				self.assertEqual(schedule.finance_book_id, "2")
+
+	def test_depreciation_schedules_are_set_up_for_multiple_finance_books(self):
+		asset = create_asset(
+			item_code = "Macbook Pro",
+			available_for_use_date = "2019-12-31",
+			do_not_save = 1
+		)
+
+		asset.calculate_depreciation = 1
+		asset.append("finance_books", {
+			"depreciation_method": "Straight Line",
+			"frequency_of_depreciation": 12,
+			"total_number_of_depreciations": 3,
+			"expected_value_after_useful_life": 10000,
+			"depreciation_start_date": "2020-12-31"
+		})
+		asset.append("finance_books", {
+			"depreciation_method": "Straight Line",
+			"frequency_of_depreciation": 12,
+			"total_number_of_depreciations": 6,
+			"expected_value_after_useful_life": 10000,
+			"depreciation_start_date": "2020-12-31"
+		})
+		asset.save()
+
+		self.assertEqual(len(asset.schedules), 9)
+
+		for schedule in asset.schedules:
+			if schedule.idx <= 3:
+				self.assertEqual(schedule.finance_book_id, 1)
+			else:
+				self.assertEqual(schedule.finance_book_id, 2)
+
 	def test_depreciation_entry_cancellation(self):
 		asset = create_asset(
 			item_code = "Macbook Pro",