feat: Splitting group assets
This commit is contained in:
parent
388293dbea
commit
d37feb8208
@ -108,6 +108,10 @@ frappe.ui.form.on('Asset', {
|
|||||||
frm.trigger("create_asset_repair");
|
frm.trigger("create_asset_repair");
|
||||||
}, __("Manage"));
|
}, __("Manage"));
|
||||||
|
|
||||||
|
frm.add_custom_button(__("Split Asset"), function() {
|
||||||
|
frm.trigger("split_asset");
|
||||||
|
}, __("Manage"));
|
||||||
|
|
||||||
if (frm.doc.status != 'Fully Depreciated') {
|
if (frm.doc.status != 'Fully Depreciated') {
|
||||||
frm.add_custom_button(__("Adjust Asset Value"), function() {
|
frm.add_custom_button(__("Adjust Asset Value"), function() {
|
||||||
frm.trigger("create_asset_value_adjustment");
|
frm.trigger("create_asset_value_adjustment");
|
||||||
@ -322,6 +326,43 @@ frappe.ui.form.on('Asset', {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
split_asset: function(frm) {
|
||||||
|
const title = __('Split Asset');
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
{
|
||||||
|
fieldname: 'split_qty',
|
||||||
|
fieldtype:'Int',
|
||||||
|
label: __('Split Qty'),
|
||||||
|
reqd: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let dialog = new frappe.ui.Dialog({
|
||||||
|
title: title,
|
||||||
|
fields: fields
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.set_primary_action(__('Split'), function() {
|
||||||
|
const dialog_data = dialog.get_values();
|
||||||
|
frappe.call({
|
||||||
|
args: {
|
||||||
|
"asset_name": frm.doc.name,
|
||||||
|
"split_qty": cint(dialog_data.split_qty)
|
||||||
|
},
|
||||||
|
method: "erpnext.assets.doctype.asset.asset.split_asset",
|
||||||
|
callback: function(r) {
|
||||||
|
let doclist = frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
},
|
||||||
|
|
||||||
create_asset_value_adjustment: function(frm) {
|
create_asset_value_adjustment: function(frm) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
args: {
|
args: {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"creation": "2016-03-01 17:01:27.920130",
|
"creation": "2022-01-18 02:26:55.975005",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Document",
|
"document_type": "Document",
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
@ -23,6 +23,8 @@
|
|||||||
"asset_name",
|
"asset_name",
|
||||||
"asset_category",
|
"asset_category",
|
||||||
"location",
|
"location",
|
||||||
|
"split_from",
|
||||||
|
"qty",
|
||||||
"custodian",
|
"custodian",
|
||||||
"department",
|
"department",
|
||||||
"disposal_date",
|
"disposal_date",
|
||||||
@ -480,6 +482,18 @@
|
|||||||
"fieldname": "section_break_36",
|
"fieldname": "section_break_36",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Finance Books"
|
"label": "Finance Books"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "qty",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Qty"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "split_from",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Split From",
|
||||||
|
"options": "Asset",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 72,
|
"idx": 72,
|
||||||
@ -502,10 +516,11 @@
|
|||||||
"link_fieldname": "asset"
|
"link_fieldname": "asset"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2021-06-24 14:58:51.097908",
|
"modified": "2022-01-18 09:15:34.238601",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Asset",
|
"name": "Asset",
|
||||||
|
"naming_rule": "By \"Naming Series\" field",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@ -542,6 +557,7 @@
|
|||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"title_field": "asset_name",
|
"title_field": "asset_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -37,7 +37,8 @@ class Asset(AccountsController):
|
|||||||
self.validate_asset_and_reference()
|
self.validate_asset_and_reference()
|
||||||
self.validate_item()
|
self.validate_item()
|
||||||
self.set_missing_values()
|
self.set_missing_values()
|
||||||
self.prepare_depreciation_data()
|
if not self.split_from:
|
||||||
|
self.prepare_depreciation_data()
|
||||||
self.validate_gross_and_purchase_amount()
|
self.validate_gross_and_purchase_amount()
|
||||||
if self.get("schedules"):
|
if self.get("schedules"):
|
||||||
self.validate_expected_value_after_useful_life()
|
self.validate_expected_value_after_useful_life()
|
||||||
@ -188,142 +189,142 @@ class Asset(AccountsController):
|
|||||||
start = self.clear_depreciation_schedule()
|
start = self.clear_depreciation_schedule()
|
||||||
|
|
||||||
for finance_book in self.get('finance_books'):
|
for finance_book in self.get('finance_books'):
|
||||||
self.validate_asset_finance_books(finance_book)
|
self._make_depreciation_schedule(finance_book, start, date_of_sale)
|
||||||
|
|
||||||
# value_after_depreciation - current Asset value
|
def _make_depreciation_schedule(self, finance_book, start, date_of_sale):
|
||||||
if self.docstatus == 1 and finance_book.value_after_depreciation:
|
self.validate_asset_finance_books(finance_book)
|
||||||
value_after_depreciation = flt(finance_book.value_after_depreciation)
|
|
||||||
else:
|
|
||||||
value_after_depreciation = (flt(self.gross_purchase_amount) -
|
|
||||||
flt(self.opening_accumulated_depreciation))
|
|
||||||
|
|
||||||
finance_book.value_after_depreciation = value_after_depreciation
|
value_after_depreciation = self._get_value_after_depreciation(finance_book)
|
||||||
|
finance_book.value_after_depreciation = value_after_depreciation
|
||||||
|
|
||||||
number_of_pending_depreciations = cint(finance_book.total_number_of_depreciations) - \
|
number_of_pending_depreciations = cint(finance_book.total_number_of_depreciations) - \
|
||||||
cint(self.number_of_depreciations_booked)
|
cint(self.number_of_depreciations_booked)
|
||||||
|
|
||||||
has_pro_rata = self.check_is_pro_rata(finance_book)
|
has_pro_rata = self.check_is_pro_rata(finance_book)
|
||||||
|
if has_pro_rata:
|
||||||
|
number_of_pending_depreciations += 1
|
||||||
|
|
||||||
if has_pro_rata:
|
skip_row = False
|
||||||
number_of_pending_depreciations += 1
|
|
||||||
|
|
||||||
skip_row = False
|
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
|
||||||
|
|
||||||
for n in range(start[finance_book.idx-1], number_of_pending_depreciations):
|
depreciation_amount = get_depreciation_amount(self, value_after_depreciation, finance_book)
|
||||||
# If depreciation is already completed (for double declining balance)
|
|
||||||
if skip_row: continue
|
|
||||||
|
|
||||||
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(finance_book.depreciation_start_date,
|
||||||
|
n * cint(finance_book.frequency_of_depreciation))
|
||||||
|
|
||||||
if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
|
# schedule date will be a year later from start date
|
||||||
schedule_date = add_months(finance_book.depreciation_start_date,
|
# so monthly schedule date is calculated by removing 11 months from it
|
||||||
n * cint(finance_book.frequency_of_depreciation))
|
monthly_schedule_date = add_months(schedule_date, - finance_book.frequency_of_depreciation + 1)
|
||||||
|
|
||||||
# schedule date will be a year later from start date
|
# if asset is being sold
|
||||||
# so monthly schedule date is calculated by removing 11 months from it
|
if date_of_sale:
|
||||||
monthly_schedule_date = add_months(schedule_date, - finance_book.frequency_of_depreciation + 1)
|
from_date = self.get_from_date(finance_book.finance_book)
|
||||||
|
depreciation_amount, days, months = self.get_pro_rata_amt(finance_book, depreciation_amount,
|
||||||
# if asset is being sold
|
from_date, date_of_sale)
|
||||||
if date_of_sale:
|
|
||||||
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": 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 not self.opening_accumulated_depreciation and n==0:
|
|
||||||
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(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 + self.number_of_depreciations_booked) * cint(finance_book.frequency_of_depreciation))
|
|
||||||
|
|
||||||
depreciation_amount_without_pro_rata = depreciation_amount
|
|
||||||
|
|
||||||
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, finance_book.finance_book)
|
|
||||||
|
|
||||||
monthly_schedule_date = add_months(schedule_date, 1)
|
|
||||||
schedule_date = add_days(schedule_date, days)
|
|
||||||
last_schedule_date = schedule_date
|
|
||||||
|
|
||||||
if not depreciation_amount: continue
|
|
||||||
value_after_depreciation -= flt(depreciation_amount,
|
|
||||||
self.precision("gross_purchase_amount"))
|
|
||||||
|
|
||||||
# Adjust depreciation amount in the last period based on the 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:
|
if depreciation_amount > 0:
|
||||||
# With monthly depreciation, each depreciation is divided by months remaining until next date
|
self._add_depreciation_row(date_of_sale, depreciation_amount, finance_book.depreciation_method,
|
||||||
if self.allow_monthly_depreciation:
|
finance_book.finance_book, finance_book.idx)
|
||||||
# month range is 1 to 12
|
|
||||||
# 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 finance_book.frequency_of_depreciation
|
|
||||||
|
|
||||||
for r in range(month_range):
|
break
|
||||||
if (has_pro_rata and n == 0):
|
|
||||||
# For first entry of monthly depr
|
# For first row
|
||||||
if r == 0:
|
if has_pro_rata and not self.opening_accumulated_depreciation and n==0:
|
||||||
days_until_first_depr = date_diff(monthly_schedule_date, self.available_for_use_date)
|
depreciation_amount, days, months = self.get_pro_rata_amt(finance_book, depreciation_amount,
|
||||||
per_day_amt = depreciation_amount / days
|
self.available_for_use_date, finance_book.depreciation_start_date)
|
||||||
depreciation_amount_for_current_month = per_day_amt * days_until_first_depr
|
|
||||||
depreciation_amount -= depreciation_amount_for_current_month
|
# For first depr schedule date will be the start date
|
||||||
date = monthly_schedule_date
|
# so monthly schedule date is calculated by removing month difference between use date and start date
|
||||||
amount = depreciation_amount_for_current_month
|
monthly_schedule_date = add_months(finance_book.depreciation_start_date, - months + 1)
|
||||||
else:
|
|
||||||
date = add_months(monthly_schedule_date, r)
|
# For last row
|
||||||
amount = depreciation_amount / (month_range - 1)
|
elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
|
||||||
elif (has_pro_rata and n == cint(number_of_pending_depreciations) - 1) and r == cint(month_range) - 1:
|
if not self.flags.increase_in_asset_life:
|
||||||
# For last entry of monthly depr
|
# In case of increase_in_asset_life, the self.to_date is already set on asset_repair submission
|
||||||
date = last_schedule_date
|
self.to_date = add_months(self.available_for_use_date,
|
||||||
amount = depreciation_amount / month_range
|
(n + self.number_of_depreciations_booked) * cint(finance_book.frequency_of_depreciation))
|
||||||
|
|
||||||
|
depreciation_amount_without_pro_rata = depreciation_amount
|
||||||
|
|
||||||
|
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, finance_book.finance_book)
|
||||||
|
|
||||||
|
monthly_schedule_date = add_months(schedule_date, 1)
|
||||||
|
schedule_date = add_days(schedule_date, days)
|
||||||
|
last_schedule_date = schedule_date
|
||||||
|
|
||||||
|
if not depreciation_amount: continue
|
||||||
|
value_after_depreciation -= flt(depreciation_amount,
|
||||||
|
self.precision("gross_purchase_amount"))
|
||||||
|
|
||||||
|
# Adjust depreciation amount in the last period based on the 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:
|
||||||
|
# With monthly depreciation, each depreciation is divided by months remaining until next date
|
||||||
|
if self.allow_monthly_depreciation:
|
||||||
|
# month range is 1 to 12
|
||||||
|
# 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 finance_book.frequency_of_depreciation
|
||||||
|
|
||||||
|
for r in range(month_range):
|
||||||
|
if (has_pro_rata and n == 0):
|
||||||
|
# For first entry of monthly depr
|
||||||
|
if r == 0:
|
||||||
|
days_until_first_depr = date_diff(monthly_schedule_date, self.available_for_use_date)
|
||||||
|
per_day_amt = depreciation_amount / days
|
||||||
|
depreciation_amount_for_current_month = per_day_amt * days_until_first_depr
|
||||||
|
depreciation_amount -= depreciation_amount_for_current_month
|
||||||
|
date = monthly_schedule_date
|
||||||
|
amount = depreciation_amount_for_current_month
|
||||||
else:
|
else:
|
||||||
date = add_months(monthly_schedule_date, r)
|
date = add_months(monthly_schedule_date, r)
|
||||||
amount = depreciation_amount / month_range
|
amount = depreciation_amount / (month_range - 1)
|
||||||
|
elif (has_pro_rata and n == cint(number_of_pending_depreciations) - 1) and r == cint(month_range) - 1:
|
||||||
|
# For last entry of monthly depr
|
||||||
|
date = last_schedule_date
|
||||||
|
amount = depreciation_amount / month_range
|
||||||
|
else:
|
||||||
|
date = add_months(monthly_schedule_date, r)
|
||||||
|
amount = depreciation_amount / month_range
|
||||||
|
|
||||||
self.append("schedules", {
|
self._add_depreciation_row(date, amount, finance_book.depreciation_method,
|
||||||
"schedule_date": date,
|
finance_book.finance_book, finance_book.idx)
|
||||||
"depreciation_amount": amount,
|
else:
|
||||||
"depreciation_method": finance_book.depreciation_method,
|
self._add_depreciation_row(schedule_date, depreciation_amount, finance_book.depreciation_method,
|
||||||
"finance_book": finance_book.finance_book,
|
finance_book.finance_book, finance_book.idx)
|
||||||
"finance_book_id": finance_book.idx
|
|
||||||
})
|
def _add_depreciation_row(self, schedule_date, depreciation_amount, depreciation_method, finance_book, finance_book_id):
|
||||||
else:
|
self.append("schedules", {
|
||||||
self.append("schedules", {
|
"schedule_date": schedule_date,
|
||||||
"schedule_date": schedule_date,
|
"depreciation_amount": depreciation_amount,
|
||||||
"depreciation_amount": depreciation_amount,
|
"depreciation_method": depreciation_method,
|
||||||
"depreciation_method": finance_book.depreciation_method,
|
"finance_book": finance_book,
|
||||||
"finance_book": finance_book.finance_book,
|
"finance_book_id": finance_book_id
|
||||||
"finance_book_id": finance_book.idx
|
})
|
||||||
})
|
|
||||||
|
def _get_value_after_depreciation(self, finance_book):
|
||||||
|
# value_after_depreciation - current Asset value
|
||||||
|
if self.docstatus == 1 and finance_book.value_after_depreciation:
|
||||||
|
value_after_depreciation = flt(finance_book.value_after_depreciation)
|
||||||
|
else:
|
||||||
|
value_after_depreciation = (flt(self.gross_purchase_amount) -
|
||||||
|
flt(self.opening_accumulated_depreciation))
|
||||||
|
|
||||||
|
return value_after_depreciation
|
||||||
|
|
||||||
# depreciation schedules need to be cleared before modification due to increase in asset life/asset sales
|
# depreciation schedules need to be cleared before modification due to increase in asset life/asset sales
|
||||||
# JE: Journal Entry, FB: Finance Book
|
# JE: Journal Entry, FB: Finance Book
|
||||||
@ -333,7 +334,6 @@ class Asset(AccountsController):
|
|||||||
depr_schedule = []
|
depr_schedule = []
|
||||||
|
|
||||||
for schedule in self.get('schedules'):
|
for schedule in self.get('schedules'):
|
||||||
|
|
||||||
# to update start when there are JEs linked with all the schedule rows corresponding to an FB
|
# 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):
|
if len(start) == (int(schedule.finance_book_id) - 2):
|
||||||
start.append(num_of_depreciations_completed)
|
start.append(num_of_depreciations_completed)
|
||||||
@ -907,3 +907,103 @@ def get_depreciation_amount(asset, depreciable_value, row):
|
|||||||
depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100))
|
depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100))
|
||||||
|
|
||||||
return depreciation_amount
|
return depreciation_amount
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def split_asset(asset_name, split_qty):
|
||||||
|
asset = frappe.get_doc("Asset", asset_name)
|
||||||
|
split_qty = cint(split_qty)
|
||||||
|
|
||||||
|
if split_qty >= asset.qty:
|
||||||
|
frappe.throw(_("Split qty cannot be grater than or equal to asset qty"))
|
||||||
|
|
||||||
|
remaining_qty = asset.qty - split_qty
|
||||||
|
|
||||||
|
# Update gross purchase amount
|
||||||
|
new_gross_purchase_amount = flt((asset.gross_purchase_amount * split_qty) / asset.qty)
|
||||||
|
remaining_gross_purchase_amount = flt((asset.gross_purchase_amount * split_qty) / asset.qty)
|
||||||
|
|
||||||
|
new_asset = create_new_asset_after_split(asset, new_gross_purchase_amount, split_qty)
|
||||||
|
update_existing_asset(asset, remaining_gross_purchase_amount, remaining_qty)
|
||||||
|
|
||||||
|
return new_asset
|
||||||
|
|
||||||
|
def update_existing_asset(asset, remaingin_gross_purchase_amount, remaining_qty):
|
||||||
|
frappe.db.set_value("Asset", asset.name, {
|
||||||
|
'gross_purchase_amount': remaingin_gross_purchase_amount,
|
||||||
|
'qty': remaining_qty
|
||||||
|
})
|
||||||
|
|
||||||
|
for finance_book in asset.get('finance_books'):
|
||||||
|
value_after_depreciation = flt((finance_book.value_after_depreciation * remaining_qty)/asset.qty)
|
||||||
|
frappe.db.set_value('Asset Finance Book', finance_book.name, 'value_after_depreciation', value_after_depreciation)
|
||||||
|
|
||||||
|
accumulated_depreciation = 0
|
||||||
|
|
||||||
|
for term in asset.get('schedules'):
|
||||||
|
depreciation_amount = flt((term.depreciation_amount * remaining_qty)/asset.qty)
|
||||||
|
frappe.db.set_value('Depreciation Schedule', term.name, 'depreciation_amount', depreciation_amount)
|
||||||
|
accumulated_depreciation += depreciation_amount
|
||||||
|
frappe.db.set_value('Depreciation Schedule', term.name, 'accumulated_depreciation_amount', depreciation_amount)
|
||||||
|
|
||||||
|
def create_new_asset_after_split(asset, new_gross_purchase_amount, split_qty):
|
||||||
|
new_asset = frappe.copy_doc(asset)
|
||||||
|
|
||||||
|
new_asset.gross_purchase_amount = new_gross_purchase_amount
|
||||||
|
new_asset.qty = split_qty
|
||||||
|
new_asset.split_from = asset.name
|
||||||
|
accumulated_depreciation = 0
|
||||||
|
|
||||||
|
for finance_book in new_asset.get('finance_books'):
|
||||||
|
finance_book.value_after_depreciation = flt((finance_book.value_after_depreciation * split_qty)/asset.qty)
|
||||||
|
|
||||||
|
for term in new_asset.get('schedules'):
|
||||||
|
depreciation_amount = flt((term.depreciation_amount * split_qty)/asset.qty)
|
||||||
|
term.depreciation_amount = depreciation_amount
|
||||||
|
accumulated_depreciation += depreciation_amount
|
||||||
|
term.accumulated_depreciation_amount = accumulated_depreciation
|
||||||
|
|
||||||
|
new_asset.submit()
|
||||||
|
new_asset.set_status()
|
||||||
|
|
||||||
|
for term in new_asset.get('schedules'):
|
||||||
|
# Update references in JV
|
||||||
|
if term.journal_entry:
|
||||||
|
add_reference_in_jv_on_split(term.journal_entry, new_asset.name, asset.name, term.depreciation_amount)
|
||||||
|
|
||||||
|
return new_asset
|
||||||
|
|
||||||
|
def add_reference_in_jv_on_split(entry_name, new_asset_name, old_asset_name, depreciation_amount):
|
||||||
|
journal_entry = frappe.get_doc('Journal Entry', entry_name)
|
||||||
|
entries_to_add = []
|
||||||
|
|
||||||
|
for account in journal_entry.get('accounts'):
|
||||||
|
if account.reference_name == old_asset_name:
|
||||||
|
entries_to_add.append(frappe.copy_doc(account).as_dict())
|
||||||
|
if account.credit:
|
||||||
|
account.credit = account.credit - depreciation_amount
|
||||||
|
account.credit_in_account_currency = account.credit_in_account_currency - \
|
||||||
|
account.exchange_rate * depreciation_amount
|
||||||
|
elif account.debit:
|
||||||
|
account.debit = account.debit - depreciation_amount
|
||||||
|
account.debit_in_account_currency = account.debit_in_account_currency - \
|
||||||
|
account.exchange_rate * depreciation_amount
|
||||||
|
|
||||||
|
for entry in entries_to_add:
|
||||||
|
entry.reference_name = new_asset_name
|
||||||
|
if entry.credit:
|
||||||
|
entry.credit = depreciation_amount
|
||||||
|
entry.credit_in_account_currency = entry.exchange_rate * depreciation_amount
|
||||||
|
elif entry.debit:
|
||||||
|
entry.debit = depreciation_amount
|
||||||
|
entry.debit_in_account_currency = entry.exchange_rate * depreciation_amount
|
||||||
|
|
||||||
|
journal_entry.append('accounts', entry)
|
||||||
|
|
||||||
|
journal_entry.flags.ignore_validate_update_after_submit = True
|
||||||
|
journal_entry.save()
|
||||||
|
|
||||||
|
# Repost GL Entries
|
||||||
|
journal_entry.docstatus = 2
|
||||||
|
journal_entry.make_gl_entries(1)
|
||||||
|
journal_entry.docstatus = 1
|
||||||
|
journal_entry.make_gl_entries()
|
@ -7,7 +7,7 @@ import frappe
|
|||||||
from frappe.utils import add_days, add_months, cstr, flt, get_last_day, getdate, nowdate
|
from frappe.utils import add_days, add_months, cstr, flt, get_last_day, getdate, nowdate
|
||||||
|
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
from erpnext.assets.doctype.asset.asset import make_sales_invoice
|
from erpnext.assets.doctype.asset.asset import make_sales_invoice, split_asset
|
||||||
from erpnext.assets.doctype.asset.depreciation import (
|
from erpnext.assets.doctype.asset.depreciation import (
|
||||||
post_depreciation_entries,
|
post_depreciation_entries,
|
||||||
restore_asset,
|
restore_asset,
|
||||||
@ -28,9 +28,9 @@ class AssetSetup(unittest.TestCase):
|
|||||||
make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location")
|
make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location")
|
||||||
frappe.db.sql("delete from `tabTax Rule`")
|
frappe.db.sql("delete from `tabTax Rule`")
|
||||||
|
|
||||||
@classmethod
|
# @classmethod
|
||||||
def tearDownClass(cls):
|
# def tearDownClass(cls):
|
||||||
frappe.db.rollback()
|
# frappe.db.rollback()
|
||||||
|
|
||||||
class TestAsset(AssetSetup):
|
class TestAsset(AssetSetup):
|
||||||
def test_asset_category_is_fetched(self):
|
def test_asset_category_is_fetched(self):
|
||||||
@ -222,6 +222,22 @@ class TestAsset(AssetSetup):
|
|||||||
si.cancel()
|
si.cancel()
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
|
||||||
|
|
||||||
|
def test_asset_splitting(self):
|
||||||
|
asset = create_asset(
|
||||||
|
calculate_depreciation = 1,
|
||||||
|
qty=10,
|
||||||
|
available_for_use_date = '2020-01-01',
|
||||||
|
purchase_date = '2020-01-01',
|
||||||
|
expected_value_after_useful_life = 0,
|
||||||
|
total_number_of_depreciations = 5,
|
||||||
|
frequency_of_depreciation = 10,
|
||||||
|
depreciation_start_date = '2021-01-01',
|
||||||
|
submit = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
post_depreciation_entries(date="2021-01-01")
|
||||||
|
split_asset(asset.name, 5)
|
||||||
|
|
||||||
def test_expense_head(self):
|
def test_expense_head(self):
|
||||||
pr = make_purchase_receipt(item_code="Macbook Pro",
|
pr = make_purchase_receipt(item_code="Macbook Pro",
|
||||||
qty=2, rate=200000.0, location="Test Location")
|
qty=2, rate=200000.0, location="Test Location")
|
||||||
@ -1164,7 +1180,8 @@ def create_asset(**args):
|
|||||||
"available_for_use_date": args.available_for_use_date or "2020-06-06",
|
"available_for_use_date": args.available_for_use_date or "2020-06-06",
|
||||||
"location": args.location or "Test Location",
|
"location": args.location or "Test Location",
|
||||||
"asset_owner": args.asset_owner or "Company",
|
"asset_owner": args.asset_owner or "Company",
|
||||||
"is_existing_asset": args.is_existing_asset or 1
|
"is_existing_asset": args.is_existing_asset or 1,
|
||||||
|
"qty": args.get("qty") or 1
|
||||||
})
|
})
|
||||||
|
|
||||||
if asset.calculate_depreciation:
|
if asset.calculate_depreciation:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user