Compare commits

...

43 Commits

Author SHA1 Message Date
Deepesh Garg
c2dec3389b Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2022-04-13 14:11:23 +05:30
Deepesh Garg
bffd7feadb fix: Remove docstatus check during budget validate 2022-03-11 16:59:28 +05:30
Deepesh Garg
1fe608ea23 Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2022-03-11 16:55:03 +05:30
Deepesh Garg
9464b3c3e6 fix: Make abbreviation limit to 10 2022-02-23 20:43:48 +05:30
Deepesh Garg
8da929635f fix: Handle stringified jsons 2022-02-09 12:29:09 +05:30
Deepesh Garg
1f6e0b871b fix: Incorrect tax template in Sales Invocie via data import 2022-02-09 11:59:10 +05:30
Deepesh Garg
18ac08413b feat: API method to created consolidated purchase invoice from receipts 2022-02-09 11:58:01 +05:30
Deepesh Garg
0f83ba221f fix: first depreciation amount in asset 2022-01-21 12:43:09 +05:30
Deepesh Garg
e5898a37dc chore: Add test case 2022-01-19 16:43:38 +05:30
Deepesh Garg
f4b3e208b7 feat: Splitting group assets 2022-01-19 16:43:36 +05:30
Deepesh Garg
eeb3d72dc0 Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2022-01-14 11:43:58 +05:30
Deepesh Garg
29ca1950a2 Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-12-29 18:25:52 +05:30
Deepesh Garg
8a4de134ac Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-12-14 11:38:46 +05:30
Deepesh Garg
69c9856bee Merge branch 'enterprise-hotfix' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-12-14 11:37:21 +05:30
Saqib
4343bdd8db fix: cannot load company form (#28536) 2021-11-24 11:04:15 +05:30
Saqib
2bf30db3d1 fix: Add indexes in stock queries (#27888) 2021-10-11 10:27:23 +05:30
Deepesh Garg
8b1be1db4c fix: Incorrect actual qty updation 2021-10-11 09:54:35 +05:30
Deepesh Garg
13d501c0b9 fix: Remove print statements 2021-10-11 09:54:33 +05:30
Deepesh Garg
59ae7e09cb fix: Remove unwanted comments 2021-10-11 09:54:14 +05:30
Deepesh Garg
4425442bbb fix: Optimization on Bin updation 2021-10-11 09:53:55 +05:30
Deepesh Garg
ed98125807 fix: Add indexes in stock queries 2021-10-11 09:53:44 +05:30
Deepesh Garg
5aae91e6cb Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-10-11 09:49:47 +05:30
mergify[bot]
c6725d43cb fix: cannot set custom label for 'total' field in print format (#27666) 2021-09-27 14:29:54 +05:30
Subin Tom
f36ed34907 fix: Tax Breakup table headers fix 2021-09-20 16:16:35 +05:30
Deepesh Garg
ccf1472c56 fix: Update modified timestamp in selling settings 2021-09-20 14:14:59 +05:30
Subin Tom
bb95287357 fix: tax breakup test fix, eway bill hsn fix 2021-09-20 13:01:50 +05:30
Subin Tom
35d6c6ade4 fix: added gst fields,warehouse validation to pos inv,patch 2021-09-20 13:01:49 +05:30
Subin Tom
f9c46e766b fix: Tax breakup based on items 2021-09-20 13:00:33 +05:30
Deepesh Garg
1c183c16d4 Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-09-20 12:57:46 +05:30
Saqib
a4140a1487 fix: fieldname 2021-09-14 13:50:51 +05:30
Deepesh Garg
3c20553104 fix: Linting Issues 2021-09-14 13:18:42 +05:30
Deepesh Garg
b169558885 feat: Merge POS invoices based on customer group 2021-09-14 13:18:24 +05:30
Deepesh Garg
21d2efbbdc fix: Add missing imports 2021-09-09 11:52:30 +05:30
Deepesh Garg
591b57a02a fix: Add missing imports 2021-09-09 11:22:04 +05:30
Deepesh Garg
be55fb31e4 fix: Autoname for customer and supplier 2021-09-09 10:27:06 +05:30
Deepesh Garg
0419ba1d78 Merge branch 'enterprise-hotfix' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-09-07 18:15:01 +05:30
Deepesh Garg
945214771a Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-09-07 18:14:01 +05:30
Deepesh Garg
0e10f69c6e Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-08-23 23:00:54 +05:30
Deepesh Garg
3d039d0fac fix: Store records to delete in a separate list 2021-08-12 18:19:21 +05:30
Deepesh Garg
b74db6f2b8 fix: Cascade deletion for Company 2021-08-12 17:53:27 +05:30
Deepesh Garg
efc76f4245 Merge branch 'version-13' of https://github.com/frappe/erpnext into enterprise-hotfix 2021-08-12 17:46:44 +05:30
Deepesh Garg
653e1455ed fix: Use update flag for company dependant fixtures 2021-07-13 20:02:38 +05:30
Deepesh Garg
ac5e7f2b74 fix: Error on creation of company for India 2021-07-13 20:01:36 +05:30
6 changed files with 427 additions and 166 deletions

View File

@@ -108,6 +108,10 @@ frappe.ui.form.on('Asset', {
frm.trigger("create_asset_repair");
}, __("Manage"));
frm.add_custom_button(__("Split Asset"), function() {
frm.trigger("split_asset");
}, __("Manage"));
if (frm.doc.status != 'Fully Depreciated') {
frm.add_custom_button(__("Adjust Asset Value"), function() {
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) {
frappe.call({
args: {

View File

@@ -3,7 +3,7 @@
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2016-03-01 17:01:27.920130",
"creation": "2022-01-18 02:26:55.975005",
"doctype": "DocType",
"document_type": "Document",
"engine": "InnoDB",
@@ -23,6 +23,7 @@
"asset_name",
"asset_category",
"location",
"split_from",
"custodian",
"department",
"disposal_date",
@@ -35,6 +36,7 @@
"available_for_use_date",
"column_break_23",
"gross_purchase_amount",
"asset_quantity",
"purchase_date",
"section_break_23",
"calculate_depreciation",
@@ -481,6 +483,18 @@
"fieldname": "section_break_36",
"fieldtype": "Section Break",
"label": "Finance Books"
},
{
"fieldname": "split_from",
"fieldtype": "Link",
"label": "Split From",
"options": "Asset",
"read_only": 1
},
{
"fieldname": "asset_quantity",
"fieldtype": "Int",
"label": "Asset Quantity"
}
],
"idx": 72,
@@ -507,6 +521,7 @@
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
"naming_rule": "By \"Naming Series\" field",
"owner": "Administrator",
"permissions": [
{
@@ -543,6 +558,7 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "asset_name",
"track_changes": 1
}

View File

@@ -39,7 +39,8 @@ class Asset(AccountsController):
self.validate_item()
self.validate_cost_center()
self.set_missing_values()
self.prepare_depreciation_data()
if not self.split_from:
self.prepare_depreciation_data()
self.validate_gross_and_purchase_amount()
if self.get("schedules"):
self.validate_expected_value_after_useful_life()
@@ -235,175 +236,180 @@ class Asset(AccountsController):
start = self.clear_depreciation_schedule()
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
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
def _make_depreciation_schedule(self, finance_book, start, date_of_sale):
self.validate_asset_finance_books(finance_book)
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) - cint(
self.number_of_depreciations_booked
)
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[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, 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)
)
finance_book.value_after_depreciation = value_after_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, -finance_book.frequency_of_depreciation + 1)
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(finance_book)
if has_pro_rata:
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
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)
)
# 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, -finance_book.frequency_of_depreciation + 1)
# if asset is being sold
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:
from_date = add_days(
self.available_for_use_date, -1
) # needed to calc depr amount for available_for_use_date too
depreciation_amount, days, months = self.get_pro_rata_amt(
finance_book, depreciation_amount, from_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 asset is being sold
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:
# 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
)
self._add_depreciation_row(
date_of_sale,
depreciation_amount,
finance_book.depreciation_method,
finance_book.finance_book,
finance_book.idx,
)
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:
date = add_months(monthly_schedule_date, r)
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
break
# For first row
if has_pro_rata and not self.opening_accumulated_depreciation and n == 0:
from_date = add_days(
self.available_for_use_date, -1
) # needed to calc depr amount for available_for_use_date too
depreciation_amount, days, months = self.get_pro_rata_amt(
finance_book, depreciation_amount, from_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:
# 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:
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",
{
"schedule_date": date,
"depreciation_amount": amount,
"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": finance_book.depreciation_method,
"finance_book": finance_book.finance_book,
"finance_book_id": finance_book.idx,
},
self._add_depreciation_row(
date, amount, finance_book.depreciation_method, finance_book.finance_book, finance_book.idx
)
else:
self._add_depreciation_row(
schedule_date,
depreciation_amount,
finance_book.depreciation_method,
finance_book.finance_book,
finance_book.idx,
)
def _add_depreciation_row(
self, schedule_date, depreciation_amount, depreciation_method, finance_book, finance_book_id
):
self.append(
"schedules",
{
"schedule_date": schedule_date,
"depreciation_amount": depreciation_amount,
"depreciation_method": depreciation_method,
"finance_book": finance_book,
"finance_book_id": finance_book_id,
},
)
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
# JE: Journal Entry, FB: Finance Book
@@ -413,7 +419,6 @@ class Asset(AccountsController):
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)
@@ -1124,3 +1129,150 @@ def get_depreciation_amount(asset, depreciable_value, row):
depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100))
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.asset_quantity:
frappe.throw(_("Split qty cannot be grater than or equal to asset qty"))
remaining_qty = asset.asset_quantity - split_qty
new_asset = create_new_asset_after_split(asset, split_qty)
update_existing_asset(asset, remaining_qty)
return new_asset
def update_existing_asset(asset, remaining_qty):
remaining_gross_purchase_amount = flt(
(asset.gross_purchase_amount * remaining_qty) / asset.asset_quantity
)
opening_accumulated_depreciation = flt(
(asset.opening_accumulated_depreciation * remaining_qty) / asset.asset_quantity
)
frappe.db.set_value(
"Asset",
asset.name,
{
"opening_accumulated_depreciation": opening_accumulated_depreciation,
"gross_purchase_amount": remaining_gross_purchase_amount,
"asset_quantity": remaining_qty,
},
)
for finance_book in asset.get("finance_books"):
value_after_depreciation = flt(
(finance_book.value_after_depreciation * remaining_qty) / asset.asset_quantity
)
expected_value_after_useful_life = flt(
(finance_book.expected_value_after_useful_life * remaining_qty) / asset.asset_quantity
)
frappe.db.set_value(
"Asset Finance Book", finance_book.name, "value_after_depreciation", value_after_depreciation
)
frappe.db.set_value(
"Asset Finance Book",
finance_book.name,
"expected_value_after_useful_life",
expected_value_after_useful_life,
)
accumulated_depreciation = 0
for term in asset.get("schedules"):
depreciation_amount = flt((term.depreciation_amount * remaining_qty) / asset.asset_quantity)
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", accumulated_depreciation
)
def create_new_asset_after_split(asset, split_qty):
new_asset = frappe.copy_doc(asset)
new_gross_purchase_amount = flt((asset.gross_purchase_amount * split_qty) / asset.asset_quantity)
opening_accumulated_depreciation = flt(
(asset.opening_accumulated_depreciation * split_qty) / asset.asset_quantity
)
new_asset.gross_purchase_amount = new_gross_purchase_amount
new_asset.opening_accumulated_depreciation = opening_accumulated_depreciation
new_asset.asset_quantity = 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.asset_quantity
)
finance_book.expected_value_after_useful_life = flt(
(finance_book.expected_value_after_useful_life * split_qty) / asset.asset_quantity
)
for term in new_asset.get("schedules"):
depreciation_amount = flt((term.depreciation_amount * split_qty) / asset.asset_quantity)
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 = []
idx = len(journal_entry.get("accounts")) + 1
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
entry.idx = idx
idx += 1
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()

View File

@@ -7,7 +7,7 @@ import frappe
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.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 (
post_depreciation_entries,
restore_asset,
@@ -232,6 +232,57 @@ class TestAsset(AssetSetup):
si.cancel()
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
def test_asset_splitting(self):
asset = create_asset(
calculate_depreciation=1,
asset_quantity=10,
available_for_use_date="2020-01-01",
purchase_date="2020-01-01",
expected_value_after_useful_life=0,
total_number_of_depreciations=6,
number_of_depreciations_booked=1,
frequency_of_depreciation=10,
depreciation_start_date="2021-01-01",
opening_accumulated_depreciation=20000,
gross_purchase_amount=120000,
submit=1,
)
post_depreciation_entries(date="2021-01-01")
self.assertEqual(asset.asset_quantity, 10)
self.assertEqual(asset.gross_purchase_amount, 120000)
self.assertEqual(asset.opening_accumulated_depreciation, 20000)
new_asset = split_asset(asset.name, 2)
asset.load_from_db()
self.assertEqual(new_asset.asset_quantity, 2)
self.assertEqual(new_asset.gross_purchase_amount, 24000)
self.assertEqual(new_asset.opening_accumulated_depreciation, 4000)
self.assertEqual(new_asset.split_from, asset.name)
self.assertEqual(new_asset.schedules[0].depreciation_amount, 4000)
self.assertEqual(new_asset.schedules[1].depreciation_amount, 4000)
self.assertEqual(asset.asset_quantity, 8)
self.assertEqual(asset.gross_purchase_amount, 96000)
self.assertEqual(asset.opening_accumulated_depreciation, 16000)
self.assertEqual(asset.schedules[0].depreciation_amount, 16000)
self.assertEqual(asset.schedules[1].depreciation_amount, 16000)
journal_entry = asset.schedules[0].journal_entry
jv = frappe.get_doc("Journal Entry", journal_entry)
self.assertEqual(jv.accounts[0].credit_in_account_currency, 16000)
self.assertEqual(jv.accounts[1].debit_in_account_currency, 16000)
self.assertEqual(jv.accounts[2].credit_in_account_currency, 4000)
self.assertEqual(jv.accounts[3].debit_in_account_currency, 4000)
self.assertEqual(jv.accounts[0].reference_name, asset.name)
self.assertEqual(jv.accounts[1].reference_name, asset.name)
self.assertEqual(jv.accounts[2].reference_name, new_asset.name)
self.assertEqual(jv.accounts[3].reference_name, new_asset.name)
def test_expense_head(self):
pr = make_purchase_receipt(
item_code="Macbook Pro", qty=2, rate=200000.0, location="Test Location"
@@ -1291,6 +1342,7 @@ def create_asset(**args):
"location": args.location or "Test Location",
"asset_owner": args.asset_owner or "Company",
"is_existing_asset": args.is_existing_asset or 1,
"asset_quantity": args.get("asset_quantity") or 1,
}
)

View File

@@ -627,7 +627,7 @@ class BuyingController(StockController, Subcontracting):
}
)
validate_expense_against_budget(args)
validate_expense_against_budget(args)
def process_fixed_asset(self):
if self.doctype == "Purchase Invoice" and not self.update_stock:

View File

@@ -79,11 +79,11 @@ erpnext.setup.slides_settings = [
slide.get_input("company_name").on("change", function () {
var parts = slide.get_input("company_name").val().split(" ");
var abbr = $.map(parts, function (p) { return p ? p.substr(0, 1) : null }).join("");
slide.get_field("company_abbr").set_value(abbr.slice(0, 5).toUpperCase());
slide.get_field("company_abbr").set_value(abbr.slice(0, 10).toUpperCase());
}).val(frappe.boot.sysdefaults.company_name || "").trigger("change");
slide.get_input("company_abbr").on("change", function () {
if (slide.get_input("company_abbr").val().length > 5) {
if (slide.get_input("company_abbr").val().length > 10) {
frappe.msgprint(__("Company Abbreviation cannot have more than 5 characters"));
slide.get_field("company_abbr").set_value("");
}
@@ -97,7 +97,7 @@ erpnext.setup.slides_settings = [
if (!this.values.company_abbr) {
return false;
}
if (this.values.company_abbr.length > 5) {
if (this.values.company_abbr.length > 10) {
return false;
}
return true;