Reschedule for future depreciations and booked difference amount in accumulated depreciation account
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 51308e50..9bbd137 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe, erpnext, json
-from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, nowdate
+from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, nowdate, cint
from frappe import msgprint, _, scrub
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on, get_account_currency
@@ -92,6 +92,7 @@
self.unlink_advance_entry_reference()
self.unlink_asset_reference()
self.unlink_inter_company_jv()
+ self.unlink_asset_adjustment_entry()
def unlink_advance_entry_reference(self):
for d in self.get("accounts"):
@@ -109,9 +110,12 @@
for s in asset.get("schedules"):
if s.journal_entry == self.name:
s.db_set("journal_entry", None)
- asset.value_after_depreciation += s.depreciation_amount
- asset.db_set("value_after_depreciation", asset.value_after_depreciation)
+ idx = cint(s.finance_book_id) or 1
+ finance_books = asset.get('finance_books')[idx - 1]
+ finance_books.value_after_depreciation += s.depreciation_amount
+ finance_books.db_update()
+
asset.set_status()
def unlink_inter_company_jv(self):
@@ -121,6 +125,10 @@
frappe.db.set_value("Journal Entry", self.name,\
"inter_company_journal_entry_reference", "")
+ def unlink_asset_adjustment_entry(self):
+ frappe.db.sql(""" update `tabAsset Adjustment`
+ set journal_entry = null where journal_entry = %s""", self.name)
+
def validate_party(self):
for d in self.get("accounts"):
account_type = frappe.db.get_value("Account", d.account, "account_type")
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 4daeae2..c05667a 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -80,6 +80,12 @@
frm.trigger("create_asset_maintenance");
}, __("Make"));
}
+ if (frm.doc.status != 'Fully Depreciated') {
+ frm.add_custom_button(__("Asset Adjustment"), function() {
+ frm.trigger("create_asset_maintenance");
+ }, __("Make"));
+ }
+
frm.page.set_inner_btn_group_as_primary(__("Make"));
frm.trigger("setup_chart");
}
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index 9a05cad..49a010d 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -1606,6 +1606,36 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "purchase_receipt_amount",
+ "fieldtype": "Currency",
+ "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": "Purchase Receipt Amount",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "purchase_invoice",
"fieldtype": "Link",
"hidden": 0,
@@ -1673,7 +1703,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-05-11 01:48:18.711485",
+ "modified": "2018-05-11 10:41:45.972686",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index bf70fbc..748849e 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -63,9 +63,6 @@
if not self.calculate_depreciation:
return
- self.value_after_depreciation = (flt(self.gross_purchase_amount) -
- flt(self.opening_accumulated_depreciation))
-
if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(nowdate()):
frappe.throw(_("Available-for-use Date is entered as past date"))
@@ -79,7 +76,9 @@
for d in self.get('finance_books'):
self.validate_asset_finance_books(d)
- value_after_depreciation = flt(self.value_after_depreciation)
+ value_after_depreciation = (flt(self.gross_purchase_amount) -
+ flt(self.opening_accumulated_depreciation))
+
d.value_after_depreciation = value_after_depreciation
no_of_depreciations = cint(d.total_number_of_depreciations - 1) - cint(self.number_of_depreciations_booked)
@@ -139,7 +138,8 @@
depreciation_amount = days * rate_per_day
from_date = schedule_date
else:
- depreciation_amount = self.get_depreciation_amount(value_after_depreciation,d)
+ depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
+ d.total_number_of_depreciations, d)
if depreciation_amount:
value_after_depreciation -= flt(depreciation_amount)
@@ -187,21 +187,24 @@
frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date")
.format(row.idx))
- def set_accumulated_depreciation(self):
- value_after_depreciation = flt(self.value_after_depreciation)
+ def set_accumulated_depreciation(self, ignore_booked_entry = False):
straight_line_idx = [d.idx for d in self.get("schedules") if d.depreciation_method == 'Straight Line']
finance_books = []
for i, d in enumerate(self.get("schedules")):
+ if ignore_booked_entry and d.journal_entry:
+ continue
+
if d.finance_book_id not in finance_books:
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
+ value_after_depreciation = flt(self.get_value_after_depreciation(d.finance_book_id))
finance_books.append(d.finance_book_id)
depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
value_after_depreciation -= flt(depreciation_amount)
if straight_line_idx and i == max(straight_line_idx) - 1:
- book = self.get('finance_books')[d.finance_book_id - 1]
+ book = self.get('finance_books')[cint(d.finance_book_id) - 1]
depreciation_amount += flt(value_after_depreciation -
flt(book.expected_value_after_useful_life), d.precision("depreciation_amount"))
@@ -210,10 +213,13 @@
d.accumulated_depreciation_amount = flt(accumulated_depreciation,
d.precision("accumulated_depreciation_amount"))
- def get_depreciation_amount(self, depreciable_value, row):
+ def get_value_after_depreciation(self, idx):
+ return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)
+
+ def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
- factor = percentage_value / row.total_number_of_depreciations
+ factor = percentage_value / total_number_of_depreciations
depreciation_amount = flt(depreciable_value * factor / 100, 0)
value_after_depreciation = flt(depreciable_value) - depreciation_amount
@@ -229,7 +235,7 @@
prorata_temporis = 1
if row.depreciation_method in ("Straight Line", "Manual"):
- depreciation_amount = (flt(self.value_after_depreciation) -
+ depreciation_amount = (flt(row.value_after_depreciation) -
flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked)) * prorata_temporis
else:
@@ -306,7 +312,7 @@
doc.submit()
def make_gl_entries(self):
- if self.purchase_receipt:
+ if self.purchase_receipt and self.purchase_receipt_amount:
from erpnext.accounts.general_ledger import make_gl_entries
gl_entries = []
@@ -320,8 +326,8 @@
"against": fixed_aseet_account,
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
"posting_date": self.available_for_use_date,
- "credit": self.gross_purchase_amount,
- "credit_in_account_currency": self.gross_purchase_amount
+ "credit": self.purchase_receipt_amount,
+ "credit_in_account_currency": self.purchase_receipt_amount
}))
gl_entries.append(self.get_gl_dict({
@@ -329,8 +335,8 @@
"against": cwip_account,
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
"posting_date": self.available_for_use_date,
- "debit": self.gross_purchase_amount,
- "debit_in_account_currency": self.gross_purchase_amount
+ "debit": self.purchase_receipt_amount,
+ "debit_in_account_currency": self.purchase_receipt_amount
}))
make_gl_entries(gl_entries)
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 92a251e..aacaef5 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import flt, today, getdate
+from frappe.utils import flt, today, getdate, cint
def post_depreciation_entries(date=None):
# Return if automatic booking of asset depreciation is disabled
@@ -47,6 +47,7 @@
je.naming_series = depreciation_series
je.posting_date = d.schedule_date
je.company = asset.company
+ je.finance_book = d.finance_book
je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount)
je.append("accounts", {
@@ -68,9 +69,12 @@
je.submit()
d.db_set("journal_entry", je.name)
- asset.value_after_depreciation -= d.depreciation_amount
+
+ idx = cint(d.finance_book_id)
+ finance_books = asset.get('finance_books')[idx - 1]
+ finance_books.value_after_depreciation -= d.depreciation_amount
+ finance_books.db_update()
- asset.db_set("value_after_depreciation", asset.value_after_depreciation)
asset.set_status()
return asset
diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js
index 0535743..11c02e1 100644
--- a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js
+++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js
@@ -2,7 +2,29 @@
// For license information, please see license.txt
frappe.ui.form.on('Asset Adjustment', {
- refresh: function(frm) {
+ asset: function(frm) {
+ frm.trigger("set_current_asset_value");
+ },
+ finance_book: function(frm) {
+ frm.trigger("set_current_asset_value");
+ },
+
+ set_current_asset_value: function(frm) {
+ debugger
+ if (frm.doc.finance_book && frm.doc.asset) {
+ frm.call({
+ method: "erpnext.assets.doctype.asset_adjustment.asset_adjustment.get_current_asset_value",
+ args: {
+ asset: frm.doc.asset,
+ finance_book: frm.doc.finance_book
+ },
+ callback: function(r) {
+ if (r.message) {
+ frm.set_value('current_asset_value', r.message);
+ }
+ }
+ });
+ }
}
});
diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json
index 8a0e957..faa36ef 100644
--- a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json
+++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json
@@ -18,6 +18,37 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "company",
+ "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": "Company",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "asset",
"fieldtype": "Link",
"hidden": 0,
@@ -38,7 +69,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -100,37 +131,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "current_asset_value",
- "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": "Current Asset Value",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -231,27 +232,26 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
+ "fieldname": "current_asset_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_list_view": 1,
"in_standard_filter": 0,
- "label": "Company",
+ "label": "Current Asset Value",
"length": 0,
"no_copy": 0,
- "options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -281,7 +281,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -292,8 +292,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "accumulated_depreciation_account",
- "fieldtype": "Link",
+ "fieldname": "difference_amount",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -301,15 +301,14 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Accumulated Depreciation Account",
+ "label": "Difference Amount",
"length": 0,
- "no_copy": 0,
- "options": "Account",
+ "no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -358,7 +357,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-05-11 00:25:07.222408",
+ "modified": "2018-05-11 21:45:03.459696",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Adjustment",
diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py
index 437f9bd..6b4b752 100644
--- a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py
+++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py
@@ -4,7 +4,100 @@
from __future__ import unicode_literals
import frappe
+from frappe import _
+from frappe.utils import flt, getdate, cint, date_diff
+from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
from frappe.model.document import Document
class AssetAdjustment(Document):
- pass
+ def validate(self):
+ self.set_difference_amount()
+ self.set_current_asset_value()
+
+ def on_submit(self):
+ self.make_depreciation_entry()
+ self.reschedule_depreciations()
+
+ def on_cancel(self):
+ if self.journal_entry:
+ frappe.throw(_("Cancel the journal entry {0} first").format(self.journal_entry))
+
+ def set_difference_amount(self):
+ self.difference_amount = flt(self.current_asset_value - self.new_asset_value)
+
+ def set_current_asset_value(self):
+ if not self.current_asset_value and self.asset and self.finance_book:
+ self.current_asset_value = get_current_asset_value(self.asset, self.finance_book)
+
+ def make_depreciation_entry(self):
+ asset = frappe.get_doc("Asset", self.asset)
+ fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
+ get_depreciation_accounts(asset)
+
+ depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company,
+ ["depreciation_cost_center", "series_for_depreciation_entry"])
+
+ je = frappe.new_doc("Journal Entry")
+ je.voucher_type = "Depreciation Entry"
+ je.naming_series = depreciation_series
+ je.posting_date = self.date
+ je.company = self.company
+ je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount)
+
+ je.append("accounts", {
+ "account": accumulated_depreciation_account,
+ "credit_in_account_currency": self.difference_amount,
+ })
+
+ je.append("accounts", {
+ "account": depreciation_expense_account,
+ "debit_in_account_currency": self.difference_amount,
+ "cost_center": depreciation_cost_center
+ })
+
+ je.flags.ignore_permissions = True
+ je.submit()
+
+ self.db_set("journal_entry", je.name)
+
+ def reschedule_depreciations(self):
+ asset = frappe.get_doc('Asset', self.asset)
+
+ for d in asset.finance_books:
+ d.value_after_depreciation = self.new_asset_value
+
+ if d.depreciation_method in ("Straight Line", "Manual"):
+ end_date = max([s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx])
+ total_days = date_diff(end_date, self.date)
+ rate_per_day = flt(d.value_after_depreciation) / flt(total_days)
+ from_date = self.date
+ else:
+ no_of_depreciations = len([e.name for e in asset.schedules
+ if (cint(s.finance_book_id) == d.idx and not e.journal_entry)])
+
+ value_after_depreciation = d.value_after_depreciation
+ for data in asset.schedules:
+ if cint(data.finance_book_id) == d.idx and not data.journal_entry:
+ if d.depreciation_method in ("Straight Line", "Manual"):
+ days = date_diff(data.schedule_date, from_date)
+ depreciation_amount = days * rate_per_day
+ from_date = data.schedule_date
+ else:
+ depreciation_amount = asset.get_depreciation_amount(value_after_depreciation,
+ no_of_depreciations, d)
+
+ if depreciation_amount:
+ value_after_depreciation -= flt(depreciation_amount)
+ data.depreciation_amount = depreciation_amount
+
+ d.db_update()
+
+ asset.set_accumulated_depreciation(ignore_booked_entry=True)
+ for asset_data in asset.schedules:
+ if not asset_data.journal_entry:
+ asset_data.db_update()
+
+@frappe.whitelist()
+def get_current_asset_value(asset, finance_book):
+ return frappe.db.get_value('Asset Finance Book',
+ {'parent': asset, 'parenttype': 'Asset', 'finance_book': finance_book}, 'value_after_depreciation', debug=1)
diff --git a/erpnext/config/assets.py b/erpnext/config/assets.py
index 99a7a5c..d52f142 100644
--- a/erpnext/config/assets.py
+++ b/erpnext/config/assets.py
@@ -45,6 +45,10 @@
},
{
"type": "doctype",
+ "name": "Asset Adjustment",
+ },
+ {
+ "type": "doctype",
"name": "Asset Repair",
},
]
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index f33ed25..c4e9fdd 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -511,6 +511,7 @@
item_data = frappe.db.get_value('Item',
row.item_code, ['asset_naming_series', 'asset_category'], as_dict=1)
+ purchase_amount = flt(row.base_net_amount + row.item_tax_amount)
asset = frappe.get_doc({
'doctype': 'Asset',
'item_code': row.item_code,
@@ -522,7 +523,8 @@
'company': self.company,
'purchase_date': self.posting_date,
'calculate_depreciation': 1,
- 'gross_purchase_amount': flt(row.base_net_amount + row.item_tax_amount),
+ 'purchase_receipt_amount': purchase_amount,
+ 'gross_purchase_amount': purchase_amount,
'purchase_receipt': self.name if self.doctype == 'Purchase Receipt' else None,
'purchase_invoice': self.name if self.doctype == 'Purchase Invoice' else None
})