diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 132840e38c2..e7af9bd5bc2 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -1425,6 +1425,16 @@ def create_asset_category(): "depreciation_expense_account": "_Test Depreciations - _TC", }, ) + asset_category.append( + "accounts", + { + "company_name": "_Test Company with perpetual inventory", + "fixed_asset_account": "_Test Fixed Asset - TCP1", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - TCP1", + "depreciation_expense_account": "_Test Depreciations - TCP1", + }, + ) + asset_category.insert() diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js index d135e60ae7f..9c7f70b0e57 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js @@ -27,7 +27,11 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s me.setup_warehouse_query(); me.frm.set_query("target_item_code", function() { - return erpnext.queries.item(); + if (me.frm.doc.entry_type == "Capitalization") { + return erpnext.queries.item({"is_stock_item": 0, "is_fixed_asset": 1}); + } else { + return erpnext.queries.item({"is_stock_item": 1, "is_fixed_asset": 0}); + } }); me.frm.set_query("target_asset", function() { @@ -410,5 +414,4 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s } }; -//$.extend(cur_frm.cscript, new erpnext.assets.AssetCapitalization({frm: cur_frm})); cur_frm.cscript = new erpnext.assets.AssetCapitalization({frm: cur_frm}); diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json index d7e6b547162..d1be5752d61 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json @@ -8,29 +8,28 @@ "engine": "InnoDB", "field_order": [ "title", + "naming_series", + "entry_type", "target_item_code", "target_item_name", "target_is_fixed_asset", "target_has_batch_no", "target_has_serial_no", - "entry_type", - "finance_book", - "naming_series", "column_break_9", + "target_asset", + "target_asset_name", + "target_warehouse", + "target_qty", + "target_stock_uom", + "target_batch_no", + "target_serial_no", + "column_break_5", "company", + "finance_book", "posting_date", "posting_time", "set_posting_time", "amended_from", - "target_item_details_section", - "target_asset", - "target_asset_name", - "target_warehouse", - "target_batch_no", - "target_serial_no", - "column_break_5", - "target_qty", - "target_stock_uom", "section_break_16", "stock_items", "stock_items_total", @@ -86,16 +85,17 @@ "fieldtype": "Column Break" }, { - "depends_on": "eval:!doc.target_item_code || doc.target_is_fixed_asset", + "depends_on": "eval:doc.entry_type=='Capitalization'", "fieldname": "target_asset", "fieldtype": "Link", "in_standard_filter": 1, "label": "Target Asset", + "mandatory_depends_on": "eval:doc.entry_type=='Capitalization'", "no_copy": 1, "options": "Asset" }, { - "depends_on": "target_asset", + "depends_on": "eval:doc.entry_type=='Capitalization'", "fetch_from": "target_asset.asset_name", "fieldname": "target_asset_name", "fieldtype": "Data", @@ -170,15 +170,11 @@ "options": "Asset Capitalization Stock Item" }, { - "fieldname": "target_item_details_section", - "fieldtype": "Section Break", - "label": "Target Item Details" - }, - { - "depends_on": "eval:!doc.target_is_fixed_asset", + "depends_on": "eval:doc.entry_type=='Decapitalization'", "fieldname": "target_warehouse", "fieldtype": "Link", "label": "Target Warehouse", + "mandatory_depends_on": "eval:doc.entry_type=='Decapitalization'", "options": "Warehouse" }, { @@ -240,13 +236,14 @@ "options": "Asset Capitalization Asset Item" }, { + "default": "Capitalization", "fieldname": "entry_type", "fieldtype": "Select", "in_list_view": 1, "in_standard_filter": 1, "label": "Entry Type", - "options": "\nCapitalization\nDecapitalization", - "read_only": 1 + "options": "Capitalization\nDecapitalization", + "reqd": 1 }, { "fieldname": "stock_items_total", @@ -337,7 +334,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-09-15 15:41:27.917458", + "modified": "2022-09-12 15:09:40.771332", "modified_by": "Administrator", "module": "Assets", "name": "Asset Capitalization", @@ -377,6 +374,7 @@ ], "sort_field": "modified", "sort_order": "DESC", + "states": [], "title_field": "title", "track_changes": 1, "track_seen": 1 diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index a8f2d79c270..2e6f0ad7b02 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -10,9 +10,9 @@ from frappe import _ from frappe.utils import cint, flt from six import string_types +import erpnext from erpnext.assets.doctype.asset.depreciation import ( get_gl_entries_on_asset_disposal, - get_gl_entries_on_asset_regain, get_value_after_depreciation_on_disposal_date, ) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account @@ -32,16 +32,26 @@ from erpnext.stock.get_item_details import ( from erpnext.stock.stock_ledger import get_previous_sle from erpnext.stock.utils import get_incoming_rate -force_fields = ['target_item_name', 'target_asset_name', 'item_name', 'asset_name', - 'target_is_fixed_asset', 'target_has_serial_no', 'target_has_batch_no', - 'target_stock_uom', 'stock_uom', 'target_fixed_asset_account', 'fixed_asset_account'] +force_fields = [ + "target_item_name", + "target_asset_name", + "item_name", + "asset_name", + "target_is_fixed_asset", + "target_has_serial_no", + "target_has_batch_no", + "target_stock_uom", + "stock_uom", + "target_fixed_asset_account", + "fixed_asset_account", + "valuation_rate", +] class AssetCapitalization(StockController): def validate(self): self.validate_posting_time() self.set_missing_values(for_validate=True) - self.set_entry_type() self.validate_target_item() self.validate_target_asset() self.validate_consumed_stock_item() @@ -58,14 +68,13 @@ class AssetCapitalization(StockController): def on_submit(self): self.update_stock_ledger() self.make_gl_entries() + self.update_target_asset() def on_cancel(self): - self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry', 'Repost Item Valuation') + self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Repost Item Valuation") self.update_stock_ledger() self.make_gl_entries() - - def set_entry_type(self): - self.entry_type = "Capitalization" if self.target_is_fixed_asset else "Decapitalization" + self.update_target_asset() def set_title(self): self.title = self.target_asset_name or self.target_item_name or self.target_item_code @@ -90,7 +99,7 @@ class AssetCapitalization(StockController): args.update(d.as_dict()) args.doctype = self.doctype args.name = self.name - consumed_stock_item_details = get_consumed_stock_item_details(args, get_valuation_rate=False) + consumed_stock_item_details = get_consumed_stock_item_details(args) for k, v in consumed_stock_item_details.items(): if d.meta.has_field(k) and (not d.get(k) or k in force_fields): d.set(k, v) @@ -100,8 +109,8 @@ class AssetCapitalization(StockController): args.update(d.as_dict()) args.doctype = self.doctype args.name = self.name - args.finance_book = d.get('finance_book') or self.get('finance_book') - consumed_asset_details = get_consumed_asset_details(args, get_asset_value=False) + args.finance_book = d.get("finance_book") or self.get("finance_book") + consumed_asset_details = get_consumed_asset_details(args) for k, v in consumed_asset_details.items(): if d.meta.has_field(k) and (not d.get(k) or k in force_fields): d.set(k, v) @@ -120,8 +129,14 @@ class AssetCapitalization(StockController): target_item = frappe.get_cached_doc("Item", self.target_item_code) if not target_item.is_fixed_asset and not target_item.is_stock_item: - frappe.throw(_("Target Item {0} is neither a Fixed Asset nor a Stock Item") - .format(target_item.name)) + frappe.throw( + _("Target Item {0} is neither a Fixed Asset nor a Stock Item").format(target_item.name) + ) + + if self.entry_type == "Capitalization" and not target_item.is_fixed_asset: + frappe.throw(_("Target Item {0} must be a Fixed Asset item").format(target_item.name)) + elif self.entry_type == "Decapitalization" and not target_item.is_stock_item: + frappe.throw(_("Target Item {0} must be a Stock Item").format(target_item.name)) if target_item.is_fixed_asset: self.target_qty = 1 @@ -144,14 +159,13 @@ class AssetCapitalization(StockController): self.validate_item(target_item) def validate_target_asset(self): - if self.target_is_fixed_asset and not self.target_asset: - frappe.throw(_("Target Asset is mandatory for Capitalization")) - if self.target_asset: target_asset = self.get_asset_for_validation(self.target_asset) if target_asset.item_code != self.target_item_code: - frappe.throw(_("Asset {0} does not belong to Item {1}").format(self.target_asset, self.target_item_code)) + frappe.throw( + _("Asset {0} does not belong to Item {1}").format(self.target_asset, self.target_item_code) + ) self.validate_asset(target_asset) @@ -172,8 +186,11 @@ class AssetCapitalization(StockController): for d in self.asset_items: if d.asset: if d.asset == self.target_asset: - frappe.throw(_("Row #{0}: Consumed Asset {1} cannot be the same as the Target Asset") - .format(d.idx, d.asset)) + frappe.throw( + _("Row #{0}: Consumed Asset {1} cannot be the same as the Target Asset").format( + d.idx, d.asset + ) + ) asset = self.get_asset_for_validation(d.asset) self.validate_asset(asset) @@ -198,18 +215,21 @@ class AssetCapitalization(StockController): d.cost_center = frappe.get_cached_value("Company", self.company, "cost_center") def validate_source_mandatory(self): - if not self.target_is_fixed_asset and not self.get('asset_items'): + if not self.target_is_fixed_asset and not self.get("asset_items"): frappe.throw(_("Consumed Asset Items is mandatory for Decapitalization")) - if not self.get('stock_items') and not self.get('asset_items'): + if not self.get("stock_items") and not self.get("asset_items"): frappe.throw(_("Consumed Stock Items or Consumed Asset Items is mandatory for Capitalization")) def validate_item(self, item): from erpnext.stock.doctype.item.item import validate_end_of_life + validate_end_of_life(item.name, item.end_of_life, item.disabled) def get_asset_for_validation(self, asset): - return frappe.db.get_value("Asset", asset, ["name", "item_code", "company", "status", "docstatus"], as_dict=1) + return frappe.db.get_value( + "Asset", asset, ["name", "item_code", "company", "status", "docstatus"], as_dict=1 + ) def validate_asset(self, asset): if asset.status in ("Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"): @@ -225,7 +245,7 @@ class AssetCapitalization(StockController): @frappe.whitelist() def set_warehouse_details(self): - for d in self.get('stock_items'): + for d in self.get("stock_items"): if d.item_code and d.warehouse: args = self.get_args_for_incoming_rate(d) warehouse_details = get_warehouse_details(args) @@ -233,27 +253,30 @@ class AssetCapitalization(StockController): @frappe.whitelist() def set_asset_values(self): - for d in self.get('asset_items'): + for d in self.get("asset_items"): if d.asset: - finance_book = d.get('finance_book') or self.get('finance_book') + finance_book = d.get("finance_book") or self.get("finance_book") d.current_asset_value = flt(get_current_asset_value(d.asset, finance_book=finance_book)) - d.asset_value = get_value_after_depreciation_on_disposal_date(d.asset, self.posting_date, - finance_book=finance_book) + d.asset_value = get_value_after_depreciation_on_disposal_date( + d.asset, self.posting_date, finance_book=finance_book + ) def get_args_for_incoming_rate(self, item): - return frappe._dict({ - "item_code": item.item_code, - "warehouse": item.warehouse, - "posting_date": self.posting_date, - "posting_time": self.posting_time, - "qty": -1 * flt(item.stock_qty), - "serial_no": item.serial_no, - "batch_no": item.batch_no, - "voucher_type": self.doctype, - "voucher_no": self.name, - "company": self.company, - "allow_zero_valuation": cint(item.get('allow_zero_valuation_rate')), - }) + return frappe._dict( + { + "item_code": item.item_code, + "warehouse": item.warehouse, + "posting_date": self.posting_date, + "posting_time": self.posting_time, + "qty": -1 * flt(item.stock_qty), + "serial_no": item.serial_no, + "batch_no": item.batch_no, + "voucher_type": self.doctype, + "voucher_no": self.name, + "company": self.company, + "allow_zero_valuation": cint(item.get("allow_zero_valuation_rate")), + } + ) def calculate_totals(self): self.stock_items_total = 0 @@ -261,45 +284,51 @@ class AssetCapitalization(StockController): self.service_items_total = 0 for d in self.stock_items: - d.amount = flt(flt(d.stock_qty) * flt(d.valuation_rate), d.precision('amount')) + d.amount = flt(flt(d.stock_qty) * flt(d.valuation_rate), d.precision("amount")) self.stock_items_total += d.amount for d in self.asset_items: - d.asset_value = flt(flt(d.asset_value), d.precision('asset_value')) + d.asset_value = flt(flt(d.asset_value), d.precision("asset_value")) self.asset_items_total += d.asset_value for d in self.service_items: - d.amount = flt(flt(d.qty) * flt(d.rate), d.precision('amount')) + d.amount = flt(flt(d.qty) * flt(d.rate), d.precision("amount")) self.service_items_total += d.amount - self.stock_items_total = flt(self.stock_items_total, self.precision('stock_items_total')) - self.asset_items_total = flt(self.asset_items_total, self.precision('asset_items_total')) - self.service_items_total = flt(self.service_items_total, self.precision('service_items_total')) + self.stock_items_total = flt(self.stock_items_total, self.precision("stock_items_total")) + self.asset_items_total = flt(self.asset_items_total, self.precision("asset_items_total")) + self.service_items_total = flt(self.service_items_total, self.precision("service_items_total")) self.total_value = self.stock_items_total + self.asset_items_total + self.service_items_total - self.total_value = flt(self.total_value, self.precision('total_value')) + self.total_value = flt(self.total_value, self.precision("total_value")) - self.target_qty = flt(self.target_qty, self.precision('target_qty')) + self.target_qty = flt(self.target_qty, self.precision("target_qty")) self.target_incoming_rate = self.total_value / self.target_qty def update_stock_ledger(self): sl_entries = [] for d in self.stock_items: - sle = self.get_sl_entries(d, { - "actual_qty": -flt(d.stock_qty), - }) + sle = self.get_sl_entries( + d, + { + "actual_qty": -flt(d.stock_qty), + }, + ) sl_entries.append(sle) - if not frappe.db.get_value("Item", self.target_item_code, "is_fixed_asset", cache=1): - sle = self.get_sl_entries(self, { - "item_code": self.target_item_code, - "warehouse": self.target_warehouse, - "batch_no": self.target_batch_no, - "serial_no": self.target_serial_no, - "actual_qty": flt(self.target_qty), - "incoming_rate": flt(self.target_incoming_rate) - }) + if self.entry_type == "Decapitalization" and not self.target_is_fixed_asset: + sle = self.get_sl_entries( + self, + { + "item_code": self.target_item_code, + "warehouse": self.target_warehouse, + "batch_no": self.target_batch_no, + "serial_no": self.target_serial_no, + "actual_qty": flt(self.target_qty), + "incoming_rate": flt(self.target_incoming_rate), + }, + ) sl_entries.append(sle) # reverse sl entries if cancel @@ -312,139 +341,183 @@ class AssetCapitalization(StockController): def make_gl_entries(self, gl_entries=None, from_repost=False): from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries - if not gl_entries: - gl_entries = self.get_gl_entries() - if self.docstatus == 1: + if not gl_entries: + gl_entries = self.get_gl_entries() + if gl_entries: make_gl_entries(gl_entries, from_repost=from_repost) elif self.docstatus == 2: make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name) - def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): + def get_gl_entries( + self, warehouse_account=None, default_expense_account=None, default_cost_center=None + ): # Stock GL Entries gl_entries = [] - if not warehouse_account: - warehouse_account = get_warehouse_account_map(self.company) + self.warehouse_account = warehouse_account + if not self.warehouse_account: + self.warehouse_account = get_warehouse_account_map(self.company) precision = self.get_debit_field_precision() - sle_map = self.get_stock_ledger_details() - - if self.target_is_fixed_asset: - target_account = self.target_fixed_asset_account - else: - target_account = warehouse_account[self.target_warehouse]["account"] + self.sle_map = self.get_stock_ledger_details() + target_account = self.get_target_account() target_against = set() + self.get_gl_entries_for_consumed_stock_items( + gl_entries, target_account, target_against, precision + ) + self.get_gl_entries_for_consumed_asset_items( + gl_entries, target_account, target_against, precision + ) + self.get_gl_entries_for_consumed_service_items( + gl_entries, target_account, target_against, precision + ) + + self.get_gl_entries_for_target_item(gl_entries, target_against, precision) + return gl_entries + + def get_target_account(self): + if self.target_is_fixed_asset: + return self.target_fixed_asset_account + else: + return self.warehouse_account[self.target_warehouse]["account"] + + def get_gl_entries_for_consumed_stock_items( + self, gl_entries, target_account, target_against, precision + ): # Consumed Stock Items - total_consumed_stock_value = 0 for item_row in self.stock_items: - sle_list = sle_map.get(item_row.name) + sle_list = self.sle_map.get(item_row.name) if sle_list: for sle in sle_list: stock_value_difference = flt(sle.stock_value_difference, precision) - total_consumed_stock_value += -1 * sle.stock_value_difference - account = warehouse_account[sle.warehouse]["account"] + if erpnext.is_perpetual_inventory_enabled(self.company): + account = self.warehouse_account[sle.warehouse]["account"] + else: + account = self.get_company_default("default_expense_account") + target_against.add(account) + gl_entries.append( + self.get_gl_dict( + { + "account": account, + "against": target_account, + "cost_center": item_row.cost_center, + "project": item_row.get("project") or self.get("project"), + "remarks": self.get("remarks") or "Accounting Entry for Stock", + "credit": -1 * stock_value_difference, + }, + self.warehouse_account[sle.warehouse]["account_currency"], + item=item_row, + ) + ) - gl_entries.append(self.get_gl_dict({ - "account": account, - "against": target_account, - "cost_center": item_row.cost_center, - "project": item_row.get('project') or self.get('project'), - "remarks": self.get("remarks") or "Accounting Entry for Stock", - "credit": -1 * stock_value_difference, - }, warehouse_account[sle.warehouse]["account_currency"], item=item_row)) - + def get_gl_entries_for_consumed_asset_items( + self, gl_entries, target_account, target_against, precision + ): # Consumed Assets for item in self.asset_items: asset = self.get_asset(item) - if self.docstatus == 2: - fixed_asset_gl_entries = get_gl_entries_on_asset_regain(asset, - item.asset_value, item.get('finance_book') or self.get('finance_book')) - asset.db_set("disposal_date", None) + if asset.calculate_depreciation: + self.depreciate_asset(asset) + asset.reload() + fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( + asset, item.asset_value, item.get("finance_book") or self.get("finance_book") + ) + + asset.db_set("disposal_date", self.posting_date) + + self.set_consumed_asset_status(asset) + + for gle in fixed_asset_gl_entries: + gle["against"] = target_account + gl_entries.append(self.get_gl_dict(gle, item=item)) + target_against.add(gle["account"]) + + def get_gl_entries_for_consumed_service_items( + self, gl_entries, target_account, target_against, precision + ): + # Service Expenses + for item_row in self.service_items: + expense_amount = flt(item_row.amount, precision) + target_against.add(item_row.expense_account) + + gl_entries.append( + self.get_gl_dict( + { + "account": item_row.expense_account, + "against": target_account, + "cost_center": item_row.cost_center, + "project": item_row.get("project") or self.get("project"), + "remarks": self.get("remarks") or "Accounting Entry for Stock", + "credit": expense_amount, + }, + item=item_row, + ) + ) + + def get_gl_entries_for_target_item(self, gl_entries, target_against, precision): + if self.target_is_fixed_asset: + # Capitalization + gl_entries.append( + self.get_gl_dict( + { + "account": self.target_fixed_asset_account, + "against": ", ".join(target_against), + "remarks": self.get("remarks") or _("Accounting Entry for Asset"), + "debit": flt(self.total_value, precision), + "cost_center": self.get("cost_center"), + }, + item=self, + ) + ) + else: + # Target Stock Item + sle_list = self.sle_map.get(self.name) + for sle in sle_list: + stock_value_difference = flt(sle.stock_value_difference, precision) + account = self.warehouse_account[sle.warehouse]["account"] + + gl_entries.append( + self.get_gl_dict( + { + "account": account, + "against": ", ".join(target_against), + "cost_center": self.cost_center, + "project": self.get("project"), + "remarks": self.get("remarks") or "Accounting Entry for Stock", + "debit": stock_value_difference, + }, + self.warehouse_account[sle.warehouse]["account_currency"], + item=self, + ) + ) + + def update_target_asset(self): + total_target_asset_value = flt(self.total_value, self.precision("total_value")) + if self.docstatus == 1 and self.entry_type == "Capitalization": + asset_doc = frappe.get_doc("Asset", self.target_asset) + asset_doc.purchase_date = self.posting_date + asset_doc.gross_purchase_amount = total_target_asset_value + asset_doc.purchase_receipt_amount = total_target_asset_value + asset_doc.prepare_depreciation_data() + asset_doc.flags.ignore_validate_update_after_submit = True + asset_doc.save() + elif self.docstatus == 2: + for item in self.asset_items: + asset = self.get_asset(item) + asset.db_set("disposal_date", None) self.set_consumed_asset_status(asset) if asset.calculate_depreciation: self.reverse_depreciation_entry_made_after_disposal(asset) self.reset_depreciation_schedule(asset) - else: - if asset.calculate_depreciation: - self.depreciate_asset(asset) - asset.reload() - - fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, - item.asset_value, item.get('finance_book') or self.get('finance_book')) - asset.db_set("disposal_date", self.posting_date) - - self.set_consumed_asset_status(asset) - - for gle in fixed_asset_gl_entries: - gle["against"] = target_account - gl_entries.append(self.get_gl_dict(gle, item=item)) - - # Service Expenses - total_service_expenses = 0 - for item_row in self.service_items: - expense_amount = flt(item_row.amount, precision) - total_service_expenses += expense_amount - target_against.add(item_row.expense_account) - - gl_entries.append(self.get_gl_dict({ - "account": item_row.expense_account, - "against": target_account, - "cost_center": item_row.cost_center, - "project": item_row.get('project') or self.get('project'), - "remarks": self.get("remarks") or "Accounting Entry for Stock", - "credit": expense_amount, - }, item=item_row)) - - target_against = ", ".join(target_against) - total_target_stock_value = 0 - total_target_asset_value = 0 - - if self.target_is_fixed_asset: - # Target Asset Item - total_target_asset_value = flt(self.total_value, precision) - gl_entries.append(self.get_gl_dict({ - "account": self.target_fixed_asset_account, - "against": target_against, - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "debit": total_target_asset_value, - "cost_center": self.get('cost_center') - }, item=self)) - - if self.docstatus == 1: - asset_doc = frappe.get_doc("Asset", self.target_asset) - asset_doc.purchase_date = self.posting_date - asset_doc.gross_purchase_amount = total_target_asset_value - asset_doc.purchase_receipt_amount = total_target_asset_value - asset_doc.prepare_depreciation_data() - asset_doc.flags.ignore_validate_update_after_submit = True - asset_doc.save() - else: - # Target Stock Item - sle_list = sle_map.get(self.name) - for sle in sle_list: - stock_value_difference = flt(sle.stock_value_difference, precision) - total_target_stock_value += sle.stock_value_difference - account = warehouse_account[sle.warehouse]["account"] - - gl_entries.append(self.get_gl_dict({ - "account": account, - "against": target_against, - "cost_center": self.cost_center, - "project": self.get('project'), - "remarks": self.get("remarks") or "Accounting Entry for Stock", - "debit": stock_value_difference, - }, warehouse_account[sle.warehouse]["account_currency"], item=self)) - - return gl_entries def get_asset(self, item): asset = frappe.get_doc("Asset", item.asset) @@ -489,16 +562,12 @@ def get_target_item_details(item_code=None, company=None): item_defaults = get_item_defaults(item.name, company) item_group_defaults = get_item_group_defaults(item.name, company) brand_defaults = get_brand_defaults(item.name, company) - out.cost_center = get_default_cost_center(frappe._dict({'item_code': item.name, 'company': company}), - item_defaults, item_group_defaults, brand_defaults) - - # Set Entry Type - if not item_code: - out.entry_type = "" - elif out.target_is_fixed_asset: - out.entry_type = "Capitalization" - else: - out.entry_type = "Decapitalization" + out.cost_center = get_default_cost_center( + frappe._dict({"item_code": item.name, "company": company}), + item_defaults, + item_group_defaults, + brand_defaults, + ) return out @@ -510,7 +579,7 @@ def get_target_asset_details(asset=None, company=None): # Get Asset Details asset_details = frappe._dict() if asset: - asset_details = frappe.db.get_value("Asset", asset, ['asset_name', 'item_code'], as_dict=1) + asset_details = frappe.db.get_value("Asset", asset, ["asset_name", "item_code"], as_dict=1) if not asset_details: frappe.throw(_("Asset {0} does not exist").format(asset)) @@ -521,8 +590,9 @@ def get_target_asset_details(asset=None, company=None): out.asset_name = asset_details.asset_name if asset_details.item_code: - out.target_fixed_asset_account = get_asset_category_account('fixed_asset_account', item=asset_details.item_code, - company=company) + out.target_fixed_asset_account = get_asset_category_account( + "fixed_asset_account", item=asset_details.item_code, company=company + ) else: out.target_fixed_asset_account = None @@ -530,7 +600,7 @@ def get_target_asset_details(asset=None, company=None): @frappe.whitelist() -def get_consumed_stock_item_details(args, get_valuation_rate=True): +def get_consumed_stock_item_details(args): if isinstance(args, string_types): args = json.loads(args) @@ -554,24 +624,29 @@ def get_consumed_stock_item_details(args, get_valuation_rate=True): item_defaults = get_item_defaults(item.name, args.company) item_group_defaults = get_item_group_defaults(item.name, args.company) brand_defaults = get_brand_defaults(item.name, args.company) - out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults) + out.cost_center = get_default_cost_center( + args, item_defaults, item_group_defaults, brand_defaults + ) - if get_valuation_rate: - if args.item_code and out.warehouse: - incoming_rate_args = frappe._dict({ - 'item_code': args.item_code, - 'warehouse': out.warehouse, - 'posting_date': args.posting_date, - 'posting_time': args.posting_time, - 'qty': -1 * flt(out.stock_qty), + if args.item_code and out.warehouse: + incoming_rate_args = frappe._dict( + { + "item_code": args.item_code, + "warehouse": out.warehouse, + "posting_date": args.posting_date, + "posting_time": args.posting_time, + "qty": -1 * flt(out.stock_qty), "voucher_type": args.doctype, "voucher_no": args.name, "company": args.company, - }) - out.update(get_warehouse_details(incoming_rate_args)) - else: - out.valuation_rate = 0 - out.actual_qty = 0 + "serial_no": args.serial_no, + "batch_no": args.batch_no, + } + ) + out.update(get_warehouse_details(incoming_rate_args)) + else: + out.valuation_rate = 0 + out.actual_qty = 0 return out @@ -587,13 +662,13 @@ def get_warehouse_details(args): if args.warehouse and args.item_code: out = { "actual_qty": get_previous_sle(args).get("qty_after_transaction") or 0, - "valuation_rate": get_incoming_rate(args, raise_error_if_no_rate=False) + "valuation_rate": get_incoming_rate(args, raise_error_if_no_rate=False), } return out @frappe.whitelist() -def get_consumed_asset_details(args, get_asset_value=True): +def get_consumed_asset_details(args): if isinstance(args, string_types): args = json.loads(args) @@ -602,7 +677,9 @@ def get_consumed_asset_details(args, get_asset_value=True): asset_details = frappe._dict() if args.asset: - asset_details = frappe.db.get_value("Asset", args.asset, ['asset_name', 'item_code', 'item_name'], as_dict=1) + asset_details = frappe.db.get_value( + "Asset", args.asset, ["asset_name", "item_code", "item_name"], as_dict=1 + ) if not asset_details: frappe.throw(_("Asset {0} does not exist").format(args.asset)) @@ -610,19 +687,22 @@ def get_consumed_asset_details(args, get_asset_value=True): out.asset_name = asset_details.asset_name out.item_name = asset_details.item_name - if get_asset_value: - if args.asset: - out.current_asset_value = flt(get_current_asset_value(args.asset, finance_book=args.finance_book)) - out.asset_value = get_value_after_depreciation_on_disposal_date(args.asset, args.posting_date, - finance_book=args.finance_book) - else: - out.current_asset_value = 0 - out.asset_value = 0 + if args.asset: + out.current_asset_value = flt( + get_current_asset_value(args.asset, finance_book=args.finance_book) + ) + out.asset_value = get_value_after_depreciation_on_disposal_date( + args.asset, args.posting_date, finance_book=args.finance_book + ) + else: + out.current_asset_value = 0 + out.asset_value = 0 # Account if asset_details.item_code: - out.fixed_asset_account = get_asset_category_account('fixed_asset_account', item=asset_details.item_code, - company=args.company) + out.fixed_asset_account = get_asset_category_account( + "fixed_asset_account", item=asset_details.item_code, company=args.company + ) else: out.fixed_asset_account = None @@ -632,7 +712,9 @@ def get_consumed_asset_details(args, get_asset_value=True): item_defaults = get_item_defaults(item.name, args.company) item_group_defaults = get_item_group_defaults(item.name, args.company) brand_defaults = get_brand_defaults(item.name, args.company) - out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults) + out.cost_center = get_default_cost_center( + args, item_defaults, item_group_defaults, brand_defaults + ) return out @@ -657,7 +739,11 @@ def get_service_item_details(args): item_group_defaults = get_item_group_defaults(item.name, args.company) brand_defaults = get_brand_defaults(item.name, args.company) - out.expense_account = get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults) - out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults) + out.expense_account = get_default_expense_account( + args, item_defaults, item_group_defaults, brand_defaults + ) + out.cost_center = get_default_cost_center( + args, item_defaults, item_group_defaults, brand_defaults + ) return out diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index 7046de6f837..86861f0b165 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -22,9 +22,12 @@ class TestAssetCapitalization(unittest.TestCase): create_asset_capitalization_data() frappe.db.sql("delete from `tabTax Rule`") - def test_capitalization(self): + def test_capitalization_with_perpetual_inventory(self): + company = "_Test Company with perpetual inventory" + set_depreciation_settings_in_company(company=company) + # Variables - consumed_asset_value = 100_000 + consumed_asset_value = 100000 stock_rate = 1000 stock_qty = 2 @@ -34,23 +37,39 @@ class TestAssetCapitalization(unittest.TestCase): service_qty = 2 service_amount = 1000 - total_amount = 103_000 + total_amount = 103000 # Create assets - target_asset = create_asset(asset_name='Asset Capitalization Target Asset', submit=1) - consumed_asset = create_asset(asset_name='Asset Capitalization Consumable Asset', asset_value=consumed_asset_value, - submit=1) + target_asset = create_asset( + asset_name="Asset Capitalization Target Asset", + submit=1, + warehouse="Stores - TCP1", + company=company, + ) + consumed_asset = create_asset( + asset_name="Asset Capitalization Consumable Asset", + asset_value=consumed_asset_value, + submit=1, + warehouse="Stores - TCP1", + company=company, + ) # Create and submit Asset Captitalization - asset_capitalization = create_asset_capitalization(target_asset=target_asset.name, - stock_qty=stock_qty, stock_rate=stock_rate, + asset_capitalization = create_asset_capitalization( + entry_type="Capitalization", + target_asset=target_asset.name, + stock_qty=stock_qty, + stock_rate=stock_rate, consumed_asset=consumed_asset.name, - service_qty=service_qty, service_rate=service_rate, - service_expense_account='Expenses Included In Asset Valuation - _TC', - submit=1) + service_qty=service_qty, + service_rate=service_rate, + service_expense_account="Expenses Included In Asset Valuation - TCP1", + company=company, + submit=1, + ) # Test Asset Capitalization values - self.assertEqual(asset_capitalization.entry_type, 'Capitalization') + self.assertEqual(asset_capitalization.entry_type, "Capitalization") self.assertEqual(asset_capitalization.target_qty, 1) self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate) @@ -72,13 +91,13 @@ class TestAssetCapitalization(unittest.TestCase): self.assertEqual(target_asset.purchase_receipt_amount, total_amount) # Test Consumed Asset values - self.assertEqual(consumed_asset.db_get('status'), 'Capitalized') + self.assertEqual(consumed_asset.db_get("status"), "Capitalized") # Test General Ledger Entries expected_gle = { - '_Test Fixed Asset - _TC': 3000, - 'Expenses Included In Asset Valuation - _TC': -1000, - 'Stock In Hand - _TC' : -2000 + "_Test Fixed Asset - TCP1": 3000, + "Expenses Included In Asset Valuation - TCP1": -1000, + "_Test Warehouse - TCP1": -2000, } actual_gle = get_actual_gle_dict(asset_capitalization.name) @@ -86,25 +105,121 @@ class TestAssetCapitalization(unittest.TestCase): # Test Stock Ledger Entries expected_sle = { - ('Capitalization Source Stock Item', '_Test Warehouse - _TC'): { - 'actual_qty': -stock_qty, 'stock_value_difference': -stock_amount + ("Capitalization Source Stock Item", "_Test Warehouse - TCP1"): { + "actual_qty": -stock_qty, + "stock_value_difference": -stock_amount, } } actual_sle = get_actual_sle_dict(asset_capitalization.name) - self.assertEqual(actual_sle, expected_sle) # Cancel Asset Capitalization and make test entries and status are reversed asset_capitalization.cancel() - self.assertEqual(consumed_asset.db_get('status'), 'Submitted') + self.assertEqual(consumed_asset.db_get("status"), "Submitted") + self.assertFalse(get_actual_gle_dict(asset_capitalization.name)) + self.assertFalse(get_actual_sle_dict(asset_capitalization.name)) + + def test_capitalization_with_periodical_inventory(self): + company = "_Test Company" + # Variables + consumed_asset_value = 100000 + + stock_rate = 1000 + stock_qty = 2 + stock_amount = 2000 + + service_rate = 500 + service_qty = 2 + service_amount = 1000 + + total_amount = 103000 + + # Create assets + target_asset = create_asset( + asset_name="Asset Capitalization Target Asset", + submit=1, + warehouse="Stores - _TC", + company=company, + ) + consumed_asset = create_asset( + asset_name="Asset Capitalization Consumable Asset", + asset_value=consumed_asset_value, + submit=1, + warehouse="Stores - _TC", + company=company, + ) + + # Create and submit Asset Captitalization + asset_capitalization = create_asset_capitalization( + entry_type="Capitalization", + target_asset=target_asset.name, + stock_qty=stock_qty, + stock_rate=stock_rate, + consumed_asset=consumed_asset.name, + service_qty=service_qty, + service_rate=service_rate, + service_expense_account="Expenses Included In Asset Valuation - _TC", + company=company, + submit=1, + ) + + # Test Asset Capitalization values + self.assertEqual(asset_capitalization.entry_type, "Capitalization") + self.assertEqual(asset_capitalization.target_qty, 1) + + self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate) + self.assertEqual(asset_capitalization.stock_items[0].amount, stock_amount) + self.assertEqual(asset_capitalization.stock_items_total, stock_amount) + + self.assertEqual(asset_capitalization.asset_items[0].asset_value, consumed_asset_value) + self.assertEqual(asset_capitalization.asset_items_total, consumed_asset_value) + + self.assertEqual(asset_capitalization.service_items[0].amount, service_amount) + self.assertEqual(asset_capitalization.service_items_total, service_amount) + + self.assertEqual(asset_capitalization.total_value, total_amount) + self.assertEqual(asset_capitalization.target_incoming_rate, total_amount) + + # Test Target Asset values + target_asset.reload() + self.assertEqual(target_asset.gross_purchase_amount, total_amount) + self.assertEqual(target_asset.purchase_receipt_amount, total_amount) + + # Test Consumed Asset values + self.assertEqual(consumed_asset.db_get("status"), "Capitalized") + + # Test General Ledger Entries + default_expense_account = frappe.db.get_value("Company", company, "default_expense_account") + expected_gle = { + "_Test Fixed Asset - _TC": 3000, + "Expenses Included In Asset Valuation - _TC": -1000, + default_expense_account: -2000, + } + actual_gle = get_actual_gle_dict(asset_capitalization.name) + + self.assertEqual(actual_gle, expected_gle) + + # Test Stock Ledger Entries + expected_sle = { + ("Capitalization Source Stock Item", "_Test Warehouse - _TC"): { + "actual_qty": -stock_qty, + "stock_value_difference": -stock_amount, + } + } + actual_sle = get_actual_sle_dict(asset_capitalization.name) + self.assertEqual(actual_sle, expected_sle) + + # Cancel Asset Capitalization and make test entries and status are reversed + asset_capitalization.cancel() + self.assertEqual(consumed_asset.db_get("status"), "Submitted") self.assertFalse(get_actual_gle_dict(asset_capitalization.name)) self.assertFalse(get_actual_sle_dict(asset_capitalization.name)) def test_decapitalization_with_depreciation(self): # Variables - purchase_date = '2020-01-01' - depreciation_start_date = '2020-12-31' - capitalization_date = '2021-06-30' + purchase_date = "2020-01-01" + depreciation_start_date = "2020-12-31" + capitalization_date = "2021-06-30" total_number_of_depreciations = 3 expected_value_after_useful_life = 10_000 @@ -126,29 +241,38 @@ class TestAssetCapitalization(unittest.TestCase): # Create assets consumed_asset = create_depreciation_asset( - asset_name='Asset Capitalization Consumable Asset', + asset_name="Asset Capitalization Consumable Asset", asset_value=consumed_asset_purchase_value, purchase_date=purchase_date, depreciation_start_date=depreciation_start_date, - depreciation_method='Straight Line', + depreciation_method="Straight Line", total_number_of_depreciations=total_number_of_depreciations, frequency_of_depreciation=12, expected_value_after_useful_life=expected_value_after_useful_life, - submit=1) + company="_Test Company with perpetual inventory", + submit=1, + ) # Create and submit Asset Captitalization asset_capitalization = create_asset_capitalization( + entry_type="Decapitalization", posting_date=capitalization_date, # half a year target_item_code="Capitalization Target Stock Item", target_qty=target_qty, consumed_asset=consumed_asset.name, - submit=1) + company="_Test Company with perpetual inventory", + submit=1, + ) # Test Asset Capitalization values - self.assertEqual(asset_capitalization.entry_type, 'Decapitalization') + self.assertEqual(asset_capitalization.entry_type, "Decapitalization") - self.assertEqual(asset_capitalization.asset_items[0].current_asset_value, consumed_asset_current_value) - self.assertEqual(asset_capitalization.asset_items[0].asset_value, consumed_asset_value_before_disposal) + self.assertEqual( + asset_capitalization.asset_items[0].current_asset_value, consumed_asset_current_value + ) + self.assertEqual( + asset_capitalization.asset_items[0].asset_value, consumed_asset_value_before_disposal + ) self.assertEqual(asset_capitalization.asset_items_total, consumed_asset_value_before_disposal) self.assertEqual(asset_capitalization.total_value, consumed_asset_value_before_disposal) @@ -156,38 +280,45 @@ class TestAssetCapitalization(unittest.TestCase): # Test Consumed Asset values consumed_asset.reload() - self.assertEqual(consumed_asset.status, 'Decapitalized') + self.assertEqual(consumed_asset.status, "Decapitalized") - consumed_depreciation_schedule = [d for d in consumed_asset.schedules - if getdate(d.schedule_date) == getdate(capitalization_date)] - self.assertTrue(consumed_depreciation_schedule and consumed_depreciation_schedule[0].journal_entry) - self.assertEqual(consumed_depreciation_schedule[0].depreciation_amount, depreciation_before_disposal_amount) + consumed_depreciation_schedule = [ + d for d in consumed_asset.schedules if getdate(d.schedule_date) == getdate(capitalization_date) + ] + self.assertTrue( + consumed_depreciation_schedule and consumed_depreciation_schedule[0].journal_entry + ) + self.assertEqual( + consumed_depreciation_schedule[0].depreciation_amount, depreciation_before_disposal_amount + ) # Test General Ledger Entries expected_gle = { - 'Stock In Hand - _TC': consumed_asset_value_before_disposal, - '_Test Accumulated Depreciations - _TC': accumulated_depreciation, - '_Test Fixed Asset - _TC': -consumed_asset_purchase_value, + "_Test Warehouse - TCP1": consumed_asset_value_before_disposal, + "_Test Accumulated Depreciations - TCP1": accumulated_depreciation, + "_Test Fixed Asset - TCP1": -consumed_asset_purchase_value, } actual_gle = get_actual_gle_dict(asset_capitalization.name) - self.assertEqual(actual_gle, expected_gle) # Cancel Asset Capitalization and make test entries and status are reversed asset_capitalization.reload() asset_capitalization.cancel() - self.assertEqual(consumed_asset.db_get('status'), 'Partially Depreciated') + self.assertEqual(consumed_asset.db_get("status"), "Partially Depreciated") self.assertFalse(get_actual_gle_dict(asset_capitalization.name)) self.assertFalse(get_actual_sle_dict(asset_capitalization.name)) def create_asset_capitalization_data(): - create_item("Capitalization Target Stock Item", - is_stock_item=1, is_fixed_asset=0, is_purchase_item=0) - create_item("Capitalization Source Stock Item", - is_stock_item=1, is_fixed_asset=0, is_purchase_item=0) - create_item("Capitalization Source Service Item", - is_stock_item=0, is_fixed_asset=0, is_purchase_item=0) + create_item( + "Capitalization Target Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0 + ) + create_item( + "Capitalization Source Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0 + ) + create_item( + "Capitalization Source Service Item", is_stock_item=0, is_fixed_asset=0, is_purchase_item=0 + ) def create_asset_capitalization(**args): @@ -204,43 +335,55 @@ def create_asset_capitalization(**args): source_warehouse = args.source_warehouse or warehouse asset_capitalization = frappe.new_doc("Asset Capitalization") - asset_capitalization.update({ - "company": company, - "posting_date": args.posting_date or now.strftime('%Y-%m-%d'), - "posting_time": args.posting_time or now.strftime('%H:%M:%S.%f'), - "target_item_code": target_item_code, - "target_asset": target_asset.name, - "target_warehouse": target_warehouse, - "target_qty": flt(args.target_qty) or 1, - "target_batch_no": args.target_batch_no, - "target_serial_no": args.target_serial_no, - "finance_book": args.finance_book - }) + asset_capitalization.update( + { + "entry_type": args.entry_type or "Capitalization", + "company": company, + "posting_date": args.posting_date or now.strftime("%Y-%m-%d"), + "posting_time": args.posting_time or now.strftime("%H:%M:%S.%f"), + "target_item_code": target_item_code, + "target_asset": target_asset.name, + "target_warehouse": target_warehouse, + "target_qty": flt(args.target_qty) or 1, + "target_batch_no": args.target_batch_no, + "target_serial_no": args.target_serial_no, + "finance_book": args.finance_book, + } + ) if args.posting_date or args.posting_time: asset_capitalization.set_posting_time = 1 if flt(args.stock_rate): - asset_capitalization.append("stock_items", { - "item_code": args.stock_item or "Capitalization Source Stock Item", - "warehouse": source_warehouse, - "stock_qty": flt(args.stock_qty) or 1, - "batch_no": args.stock_batch_no, - "serial_no": args.stock_serial_no, - }) + asset_capitalization.append( + "stock_items", + { + "item_code": args.stock_item or "Capitalization Source Stock Item", + "warehouse": source_warehouse, + "stock_qty": flt(args.stock_qty) or 1, + "batch_no": args.stock_batch_no, + "serial_no": args.stock_serial_no, + }, + ) if args.consumed_asset: - asset_capitalization.append("asset_items", { - "asset": args.consumed_asset, - }) + asset_capitalization.append( + "asset_items", + { + "asset": args.consumed_asset, + }, + ) if flt(args.service_rate): - asset_capitalization.append("service_items", { - "item_code": args.service_item or "Capitalization Source Service Item", - "expense_account": args.service_expense_account, - "qty": flt(args.service_qty) or 1, - "rate": flt(args.service_rate) - }) + asset_capitalization.append( + "service_items", + { + "item_code": args.service_item or "Capitalization Source Service Item", + "expense_account": args.service_expense_account, + "qty": flt(args.service_qty) or 1, + "rate": flt(args.service_rate), + }, + ) if args.submit: create_stock_reconciliation(asset_capitalization, stock_rate=args.stock_rate) @@ -255,17 +398,23 @@ def create_asset_capitalization(**args): def create_stock_reconciliation(asset_capitalization, stock_rate=0): from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + EmptyStockReconciliationItemsError, create_stock_reconciliation, ) - if not asset_capitalization.get('stock_items'): + + if not asset_capitalization.get("stock_items"): return - return create_stock_reconciliation( - item_code=asset_capitalization.stock_items[0].item_code, - warehouse=asset_capitalization.stock_items[0].warehouse, - qty=flt(asset_capitalization.stock_items[0].stock_qty), - rate=flt(stock_rate), - company=asset_capitalization.company) + try: + create_stock_reconciliation( + item_code=asset_capitalization.stock_items[0].item_code, + warehouse=asset_capitalization.stock_items[0].warehouse, + qty=flt(asset_capitalization.stock_items[0].stock_qty), + rate=flt(stock_rate), + company=asset_capitalization.company, + ) + except EmptyStockReconciliationItemsError: + pass def create_depreciation_asset(**args): @@ -281,15 +430,15 @@ def create_depreciation_asset(**args): asset.asset_name = args.asset_name or asset.item_code asset.location = args.location or "Test Location" - asset.purchase_date = args.purchase_date or '2020-01-01' + asset.purchase_date = args.purchase_date or "2020-01-01" asset.available_for_use_date = args.available_for_use_date or asset.purchase_date asset.gross_purchase_amount = args.asset_value or 100000 asset.purchase_receipt_amount = asset.gross_purchase_amount - finance_book = asset.append('finance_books') - finance_book.depreciation_start_date = args.depreciation_start_date or '2020-12-31' - finance_book.depreciation_method = args.depreciation_method or 'Straight Line' + finance_book = asset.append("finance_books") + finance_book.depreciation_start_date = args.depreciation_start_date or "2020-12-31" + finance_book.depreciation_method = args.depreciation_method or "Straight Line" finance_book.total_number_of_depreciations = cint(args.total_number_of_depreciations) or 3 finance_book.frequency_of_depreciation = cint(args.frequency_of_depreciation) or 12 finance_book.expected_value_after_useful_life = flt(args.expected_value_after_useful_life) @@ -305,17 +454,23 @@ def create_depreciation_asset(**args): def get_actual_gle_dict(name): - return dict(frappe.db.sql(""" + return dict( + frappe.db.sql( + """ select account, sum(debit-credit) as diff from `tabGL Entry` where voucher_type = 'Asset Capitalization' and voucher_no = %s group by account having diff != 0 - """, name)) + """, + name, + ) + ) def get_actual_sle_dict(name): - sles = frappe.db.sql(""" + sles = frappe.db.sql( + """ select item_code, warehouse, sum(actual_qty) as actual_qty, @@ -324,12 +479,16 @@ def get_actual_sle_dict(name): where voucher_type = 'Asset Capitalization' and voucher_no = %s group by item_code, warehouse having actual_qty != 0 - """, name, as_dict=1) + """, + name, + as_dict=1, + ) sle_dict = {} for d in sles: sle_dict[(d.item_code, d.warehouse)] = { - 'actual_qty': d.actual_qty, 'stock_value_difference': d.stock_value_difference + "actual_qty": d.actual_qty, + "stock_value_difference": d.stock_value_difference, } return sle_dict diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 6e06f52ac65..2786349f7b6 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -129,18 +129,6 @@ class TestAssetRepair(unittest.TestCase): def test_gl_entries_with_perpetual_inventory(self): set_depreciation_settings_in_company(company="_Test Company with perpetual inventory") - asset_category = frappe.get_doc("Asset Category", "Computers") - asset_category.append( - "accounts", - { - "company_name": "_Test Company with perpetual inventory", - "fixed_asset_account": "_Test Fixed Asset - TCP1", - "accumulated_depreciation_account": "_Test Accumulated Depreciations - TCP1", - "depreciation_expense_account": "_Test Depreciations - TCP1", - }, - ) - asset_category.save() - asset_repair = create_asset_repair( capitalize_repair_cost=1, stock_consumption=1, diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 191c03f5f1c..4e76ae781f9 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -727,7 +727,12 @@ def create_stock_reconciliation(**args): sr.set_posting_time = 1 sr.company = args.company or "_Test Company" sr.expense_account = args.expense_account or ( - "Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC" + ( + frappe.get_cached_value("Company", sr.company, "stock_adjustment_account") + or "Stock Adjustment - _TC" + ) + if frappe.get_all("Stock Ledger Entry", {"company": sr.company}) + else "Temporary Opening - _TC" ) sr.cost_center = ( args.cost_center