feat: Asset Capitalization
- manual selection of entry type - GLE cleanup with smaller functions - GLE considering periodical inventory - test cases
This commit is contained in:
parent
fefe95052d
commit
58d430fe3e
@ -1425,6 +1425,16 @@ def create_asset_category():
|
|||||||
"depreciation_expense_account": "_Test Depreciations - _TC",
|
"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()
|
asset_category.insert()
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,11 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
|
|||||||
me.setup_warehouse_query();
|
me.setup_warehouse_query();
|
||||||
|
|
||||||
me.frm.set_query("target_item_code", function() {
|
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() {
|
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});
|
cur_frm.cscript = new erpnext.assets.AssetCapitalization({frm: cur_frm});
|
||||||
|
@ -8,29 +8,28 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"title",
|
"title",
|
||||||
|
"naming_series",
|
||||||
|
"entry_type",
|
||||||
"target_item_code",
|
"target_item_code",
|
||||||
"target_item_name",
|
"target_item_name",
|
||||||
"target_is_fixed_asset",
|
"target_is_fixed_asset",
|
||||||
"target_has_batch_no",
|
"target_has_batch_no",
|
||||||
"target_has_serial_no",
|
"target_has_serial_no",
|
||||||
"entry_type",
|
|
||||||
"finance_book",
|
|
||||||
"naming_series",
|
|
||||||
"column_break_9",
|
"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",
|
"company",
|
||||||
|
"finance_book",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
"posting_time",
|
"posting_time",
|
||||||
"set_posting_time",
|
"set_posting_time",
|
||||||
"amended_from",
|
"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",
|
"section_break_16",
|
||||||
"stock_items",
|
"stock_items",
|
||||||
"stock_items_total",
|
"stock_items_total",
|
||||||
@ -86,16 +85,17 @@
|
|||||||
"fieldtype": "Column Break"
|
"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",
|
"fieldname": "target_asset",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Target Asset",
|
"label": "Target Asset",
|
||||||
|
"mandatory_depends_on": "eval:doc.entry_type=='Capitalization'",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Asset"
|
"options": "Asset"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "target_asset",
|
"depends_on": "eval:doc.entry_type=='Capitalization'",
|
||||||
"fetch_from": "target_asset.asset_name",
|
"fetch_from": "target_asset.asset_name",
|
||||||
"fieldname": "target_asset_name",
|
"fieldname": "target_asset_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
@ -170,15 +170,11 @@
|
|||||||
"options": "Asset Capitalization Stock Item"
|
"options": "Asset Capitalization Stock Item"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "target_item_details_section",
|
"depends_on": "eval:doc.entry_type=='Decapitalization'",
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Target Item Details"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:!doc.target_is_fixed_asset",
|
|
||||||
"fieldname": "target_warehouse",
|
"fieldname": "target_warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Target Warehouse",
|
"label": "Target Warehouse",
|
||||||
|
"mandatory_depends_on": "eval:doc.entry_type=='Decapitalization'",
|
||||||
"options": "Warehouse"
|
"options": "Warehouse"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -240,13 +236,14 @@
|
|||||||
"options": "Asset Capitalization Asset Item"
|
"options": "Asset Capitalization Asset Item"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"default": "Capitalization",
|
||||||
"fieldname": "entry_type",
|
"fieldname": "entry_type",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Entry Type",
|
"label": "Entry Type",
|
||||||
"options": "\nCapitalization\nDecapitalization",
|
"options": "Capitalization\nDecapitalization",
|
||||||
"read_only": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "stock_items_total",
|
"fieldname": "stock_items_total",
|
||||||
@ -337,7 +334,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-15 15:41:27.917458",
|
"modified": "2022-09-12 15:09:40.771332",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Asset Capitalization",
|
"name": "Asset Capitalization",
|
||||||
@ -377,6 +374,7 @@
|
|||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"title_field": "title",
|
"title_field": "title",
|
||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 1
|
"track_seen": 1
|
||||||
|
@ -10,9 +10,9 @@ from frappe import _
|
|||||||
from frappe.utils import cint, flt
|
from frappe.utils import cint, flt
|
||||||
from six import string_types
|
from six import string_types
|
||||||
|
|
||||||
|
import erpnext
|
||||||
from erpnext.assets.doctype.asset.depreciation import (
|
from erpnext.assets.doctype.asset.depreciation import (
|
||||||
get_gl_entries_on_asset_disposal,
|
get_gl_entries_on_asset_disposal,
|
||||||
get_gl_entries_on_asset_regain,
|
|
||||||
get_value_after_depreciation_on_disposal_date,
|
get_value_after_depreciation_on_disposal_date,
|
||||||
)
|
)
|
||||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
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.stock_ledger import get_previous_sle
|
||||||
from erpnext.stock.utils import get_incoming_rate
|
from erpnext.stock.utils import get_incoming_rate
|
||||||
|
|
||||||
force_fields = ['target_item_name', 'target_asset_name', 'item_name', 'asset_name',
|
force_fields = [
|
||||||
'target_is_fixed_asset', 'target_has_serial_no', 'target_has_batch_no',
|
"target_item_name",
|
||||||
'target_stock_uom', 'stock_uom', 'target_fixed_asset_account', 'fixed_asset_account']
|
"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):
|
class AssetCapitalization(StockController):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_posting_time()
|
self.validate_posting_time()
|
||||||
self.set_missing_values(for_validate=True)
|
self.set_missing_values(for_validate=True)
|
||||||
self.set_entry_type()
|
|
||||||
self.validate_target_item()
|
self.validate_target_item()
|
||||||
self.validate_target_asset()
|
self.validate_target_asset()
|
||||||
self.validate_consumed_stock_item()
|
self.validate_consumed_stock_item()
|
||||||
@ -58,14 +68,13 @@ class AssetCapitalization(StockController):
|
|||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
self.update_target_asset()
|
||||||
|
|
||||||
def on_cancel(self):
|
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.update_stock_ledger()
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
self.update_target_asset()
|
||||||
def set_entry_type(self):
|
|
||||||
self.entry_type = "Capitalization" if self.target_is_fixed_asset else "Decapitalization"
|
|
||||||
|
|
||||||
def set_title(self):
|
def set_title(self):
|
||||||
self.title = self.target_asset_name or self.target_item_name or self.target_item_code
|
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.update(d.as_dict())
|
||||||
args.doctype = self.doctype
|
args.doctype = self.doctype
|
||||||
args.name = self.name
|
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():
|
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):
|
if d.meta.has_field(k) and (not d.get(k) or k in force_fields):
|
||||||
d.set(k, v)
|
d.set(k, v)
|
||||||
@ -100,8 +109,8 @@ class AssetCapitalization(StockController):
|
|||||||
args.update(d.as_dict())
|
args.update(d.as_dict())
|
||||||
args.doctype = self.doctype
|
args.doctype = self.doctype
|
||||||
args.name = self.name
|
args.name = self.name
|
||||||
args.finance_book = d.get('finance_book') or self.get('finance_book')
|
args.finance_book = d.get("finance_book") or self.get("finance_book")
|
||||||
consumed_asset_details = get_consumed_asset_details(args, get_asset_value=False)
|
consumed_asset_details = get_consumed_asset_details(args)
|
||||||
for k, v in consumed_asset_details.items():
|
for k, v in consumed_asset_details.items():
|
||||||
if d.meta.has_field(k) and (not d.get(k) or k in force_fields):
|
if d.meta.has_field(k) and (not d.get(k) or k in force_fields):
|
||||||
d.set(k, v)
|
d.set(k, v)
|
||||||
@ -120,8 +129,14 @@ class AssetCapitalization(StockController):
|
|||||||
target_item = frappe.get_cached_doc("Item", self.target_item_code)
|
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:
|
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")
|
frappe.throw(
|
||||||
.format(target_item.name))
|
_("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:
|
if target_item.is_fixed_asset:
|
||||||
self.target_qty = 1
|
self.target_qty = 1
|
||||||
@ -144,14 +159,13 @@ class AssetCapitalization(StockController):
|
|||||||
self.validate_item(target_item)
|
self.validate_item(target_item)
|
||||||
|
|
||||||
def validate_target_asset(self):
|
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:
|
if self.target_asset:
|
||||||
target_asset = self.get_asset_for_validation(self.target_asset)
|
target_asset = self.get_asset_for_validation(self.target_asset)
|
||||||
|
|
||||||
if target_asset.item_code != self.target_item_code:
|
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)
|
self.validate_asset(target_asset)
|
||||||
|
|
||||||
@ -172,8 +186,11 @@ class AssetCapitalization(StockController):
|
|||||||
for d in self.asset_items:
|
for d in self.asset_items:
|
||||||
if d.asset:
|
if d.asset:
|
||||||
if d.asset == self.target_asset:
|
if d.asset == self.target_asset:
|
||||||
frappe.throw(_("Row #{0}: Consumed Asset {1} cannot be the same as the Target Asset")
|
frappe.throw(
|
||||||
.format(d.idx, d.asset))
|
_("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)
|
asset = self.get_asset_for_validation(d.asset)
|
||||||
self.validate_asset(asset)
|
self.validate_asset(asset)
|
||||||
@ -198,18 +215,21 @@ class AssetCapitalization(StockController):
|
|||||||
d.cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
d.cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
||||||
|
|
||||||
def validate_source_mandatory(self):
|
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"))
|
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"))
|
frappe.throw(_("Consumed Stock Items or Consumed Asset Items is mandatory for Capitalization"))
|
||||||
|
|
||||||
def validate_item(self, item):
|
def validate_item(self, item):
|
||||||
from erpnext.stock.doctype.item.item import validate_end_of_life
|
from erpnext.stock.doctype.item.item import validate_end_of_life
|
||||||
|
|
||||||
validate_end_of_life(item.name, item.end_of_life, item.disabled)
|
validate_end_of_life(item.name, item.end_of_life, item.disabled)
|
||||||
|
|
||||||
def get_asset_for_validation(self, asset):
|
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):
|
def validate_asset(self, asset):
|
||||||
if asset.status in ("Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"):
|
if asset.status in ("Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"):
|
||||||
@ -225,7 +245,7 @@ class AssetCapitalization(StockController):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def set_warehouse_details(self):
|
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:
|
if d.item_code and d.warehouse:
|
||||||
args = self.get_args_for_incoming_rate(d)
|
args = self.get_args_for_incoming_rate(d)
|
||||||
warehouse_details = get_warehouse_details(args)
|
warehouse_details = get_warehouse_details(args)
|
||||||
@ -233,15 +253,17 @@ class AssetCapitalization(StockController):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def set_asset_values(self):
|
def set_asset_values(self):
|
||||||
for d in self.get('asset_items'):
|
for d in self.get("asset_items"):
|
||||||
if d.asset:
|
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.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,
|
d.asset_value = get_value_after_depreciation_on_disposal_date(
|
||||||
finance_book=finance_book)
|
d.asset, self.posting_date, finance_book=finance_book
|
||||||
|
)
|
||||||
|
|
||||||
def get_args_for_incoming_rate(self, item):
|
def get_args_for_incoming_rate(self, item):
|
||||||
return frappe._dict({
|
return frappe._dict(
|
||||||
|
{
|
||||||
"item_code": item.item_code,
|
"item_code": item.item_code,
|
||||||
"warehouse": item.warehouse,
|
"warehouse": item.warehouse,
|
||||||
"posting_date": self.posting_date,
|
"posting_date": self.posting_date,
|
||||||
@ -252,8 +274,9 @@ class AssetCapitalization(StockController):
|
|||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": self.name,
|
"voucher_no": self.name,
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"allow_zero_valuation": cint(item.get('allow_zero_valuation_rate')),
|
"allow_zero_valuation": cint(item.get("allow_zero_valuation_rate")),
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def calculate_totals(self):
|
def calculate_totals(self):
|
||||||
self.stock_items_total = 0
|
self.stock_items_total = 0
|
||||||
@ -261,45 +284,51 @@ class AssetCapitalization(StockController):
|
|||||||
self.service_items_total = 0
|
self.service_items_total = 0
|
||||||
|
|
||||||
for d in self.stock_items:
|
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
|
self.stock_items_total += d.amount
|
||||||
|
|
||||||
for d in self.asset_items:
|
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
|
self.asset_items_total += d.asset_value
|
||||||
|
|
||||||
for d in self.service_items:
|
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.service_items_total += d.amount
|
||||||
|
|
||||||
self.stock_items_total = flt(self.stock_items_total, self.precision('stock_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.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.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 = 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
|
self.target_incoming_rate = self.total_value / self.target_qty
|
||||||
|
|
||||||
def update_stock_ledger(self):
|
def update_stock_ledger(self):
|
||||||
sl_entries = []
|
sl_entries = []
|
||||||
|
|
||||||
for d in self.stock_items:
|
for d in self.stock_items:
|
||||||
sle = self.get_sl_entries(d, {
|
sle = self.get_sl_entries(
|
||||||
|
d,
|
||||||
|
{
|
||||||
"actual_qty": -flt(d.stock_qty),
|
"actual_qty": -flt(d.stock_qty),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
sl_entries.append(sle)
|
sl_entries.append(sle)
|
||||||
|
|
||||||
if not frappe.db.get_value("Item", self.target_item_code, "is_fixed_asset", cache=1):
|
if self.entry_type == "Decapitalization" and not self.target_is_fixed_asset:
|
||||||
sle = self.get_sl_entries(self, {
|
sle = self.get_sl_entries(
|
||||||
|
self,
|
||||||
|
{
|
||||||
"item_code": self.target_item_code,
|
"item_code": self.target_item_code,
|
||||||
"warehouse": self.target_warehouse,
|
"warehouse": self.target_warehouse,
|
||||||
"batch_no": self.target_batch_no,
|
"batch_no": self.target_batch_no,
|
||||||
"serial_no": self.target_serial_no,
|
"serial_no": self.target_serial_no,
|
||||||
"actual_qty": flt(self.target_qty),
|
"actual_qty": flt(self.target_qty),
|
||||||
"incoming_rate": flt(self.target_incoming_rate)
|
"incoming_rate": flt(self.target_incoming_rate),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
sl_entries.append(sle)
|
sl_entries.append(sle)
|
||||||
|
|
||||||
# reverse sl entries if cancel
|
# reverse sl entries if cancel
|
||||||
@ -312,74 +341,96 @@ class AssetCapitalization(StockController):
|
|||||||
def make_gl_entries(self, gl_entries=None, from_repost=False):
|
def make_gl_entries(self, gl_entries=None, from_repost=False):
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
|
||||||
|
|
||||||
|
if self.docstatus == 1:
|
||||||
if not gl_entries:
|
if not gl_entries:
|
||||||
gl_entries = self.get_gl_entries()
|
gl_entries = self.get_gl_entries()
|
||||||
|
|
||||||
if self.docstatus == 1:
|
|
||||||
if gl_entries:
|
if gl_entries:
|
||||||
make_gl_entries(gl_entries, from_repost=from_repost)
|
make_gl_entries(gl_entries, from_repost=from_repost)
|
||||||
elif self.docstatus == 2:
|
elif self.docstatus == 2:
|
||||||
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
|
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
|
# Stock GL Entries
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
|
|
||||||
if not warehouse_account:
|
self.warehouse_account = warehouse_account
|
||||||
warehouse_account = get_warehouse_account_map(self.company)
|
if not self.warehouse_account:
|
||||||
|
self.warehouse_account = get_warehouse_account_map(self.company)
|
||||||
|
|
||||||
precision = self.get_debit_field_precision()
|
precision = self.get_debit_field_precision()
|
||||||
sle_map = self.get_stock_ledger_details()
|
self.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"]
|
|
||||||
|
|
||||||
|
target_account = self.get_target_account()
|
||||||
target_against = set()
|
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
|
# Consumed Stock Items
|
||||||
total_consumed_stock_value = 0
|
|
||||||
for item_row in self.stock_items:
|
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:
|
if sle_list:
|
||||||
for sle in sle_list:
|
for sle in sle_list:
|
||||||
stock_value_difference = flt(sle.stock_value_difference, precision)
|
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)
|
target_against.add(account)
|
||||||
|
gl_entries.append(
|
||||||
gl_entries.append(self.get_gl_dict({
|
self.get_gl_dict(
|
||||||
|
{
|
||||||
"account": account,
|
"account": account,
|
||||||
"against": target_account,
|
"against": target_account,
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"project": item_row.get('project') or self.get('project'),
|
"project": item_row.get("project") or self.get("project"),
|
||||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||||
"credit": -1 * stock_value_difference,
|
"credit": -1 * stock_value_difference,
|
||||||
}, warehouse_account[sle.warehouse]["account_currency"], item=item_row))
|
},
|
||||||
|
self.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
|
# Consumed Assets
|
||||||
for item in self.asset_items:
|
for item in self.asset_items:
|
||||||
asset = self.get_asset(item)
|
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)
|
|
||||||
|
|
||||||
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:
|
if asset.calculate_depreciation:
|
||||||
self.depreciate_asset(asset)
|
self.depreciate_asset(asset)
|
||||||
asset.reload()
|
asset.reload()
|
||||||
|
|
||||||
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset,
|
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
|
||||||
item.asset_value, item.get('finance_book') or self.get('finance_book'))
|
asset, item.asset_value, item.get("finance_book") or self.get("finance_book")
|
||||||
|
)
|
||||||
|
|
||||||
asset.db_set("disposal_date", self.posting_date)
|
asset.db_set("disposal_date", self.posting_date)
|
||||||
|
|
||||||
self.set_consumed_asset_status(asset)
|
self.set_consumed_asset_status(asset)
|
||||||
@ -387,39 +438,70 @@ class AssetCapitalization(StockController):
|
|||||||
for gle in fixed_asset_gl_entries:
|
for gle in fixed_asset_gl_entries:
|
||||||
gle["against"] = target_account
|
gle["against"] = target_account
|
||||||
gl_entries.append(self.get_gl_dict(gle, item=item))
|
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
|
# Service Expenses
|
||||||
total_service_expenses = 0
|
|
||||||
for item_row in self.service_items:
|
for item_row in self.service_items:
|
||||||
expense_amount = flt(item_row.amount, precision)
|
expense_amount = flt(item_row.amount, precision)
|
||||||
total_service_expenses += expense_amount
|
|
||||||
target_against.add(item_row.expense_account)
|
target_against.add(item_row.expense_account)
|
||||||
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
gl_entries.append(
|
||||||
|
self.get_gl_dict(
|
||||||
|
{
|
||||||
"account": item_row.expense_account,
|
"account": item_row.expense_account,
|
||||||
"against": target_account,
|
"against": target_account,
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"project": item_row.get('project') or self.get('project'),
|
"project": item_row.get("project") or self.get("project"),
|
||||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||||
"credit": expense_amount,
|
"credit": expense_amount,
|
||||||
}, item=item_row))
|
},
|
||||||
|
item=item_row,
|
||||||
target_against = ", ".join(target_against)
|
)
|
||||||
total_target_stock_value = 0
|
)
|
||||||
total_target_asset_value = 0
|
|
||||||
|
|
||||||
|
def get_gl_entries_for_target_item(self, gl_entries, target_against, precision):
|
||||||
if self.target_is_fixed_asset:
|
if self.target_is_fixed_asset:
|
||||||
# Target Asset Item
|
# Capitalization
|
||||||
total_target_asset_value = flt(self.total_value, precision)
|
gl_entries.append(
|
||||||
gl_entries.append(self.get_gl_dict({
|
self.get_gl_dict(
|
||||||
|
{
|
||||||
"account": self.target_fixed_asset_account,
|
"account": self.target_fixed_asset_account,
|
||||||
"against": target_against,
|
"against": ", ".join(target_against),
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||||
"debit": total_target_asset_value,
|
"debit": flt(self.total_value, precision),
|
||||||
"cost_center": self.get('cost_center')
|
"cost_center": self.get("cost_center"),
|
||||||
}, item=self))
|
},
|
||||||
|
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"]
|
||||||
|
|
||||||
if self.docstatus == 1:
|
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 = frappe.get_doc("Asset", self.target_asset)
|
||||||
asset_doc.purchase_date = self.posting_date
|
asset_doc.purchase_date = self.posting_date
|
||||||
asset_doc.gross_purchase_amount = total_target_asset_value
|
asset_doc.gross_purchase_amount = total_target_asset_value
|
||||||
@ -427,24 +509,15 @@ class AssetCapitalization(StockController):
|
|||||||
asset_doc.prepare_depreciation_data()
|
asset_doc.prepare_depreciation_data()
|
||||||
asset_doc.flags.ignore_validate_update_after_submit = True
|
asset_doc.flags.ignore_validate_update_after_submit = True
|
||||||
asset_doc.save()
|
asset_doc.save()
|
||||||
else:
|
elif self.docstatus == 2:
|
||||||
# Target Stock Item
|
for item in self.asset_items:
|
||||||
sle_list = sle_map.get(self.name)
|
asset = self.get_asset(item)
|
||||||
for sle in sle_list:
|
asset.db_set("disposal_date", None)
|
||||||
stock_value_difference = flt(sle.stock_value_difference, precision)
|
self.set_consumed_asset_status(asset)
|
||||||
total_target_stock_value += sle.stock_value_difference
|
|
||||||
account = warehouse_account[sle.warehouse]["account"]
|
|
||||||
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
if asset.calculate_depreciation:
|
||||||
"account": account,
|
self.reverse_depreciation_entry_made_after_disposal(asset)
|
||||||
"against": target_against,
|
self.reset_depreciation_schedule(asset)
|
||||||
"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):
|
def get_asset(self, item):
|
||||||
asset = frappe.get_doc("Asset", item.asset)
|
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_defaults = get_item_defaults(item.name, company)
|
||||||
item_group_defaults = get_item_group_defaults(item.name, company)
|
item_group_defaults = get_item_group_defaults(item.name, company)
|
||||||
brand_defaults = get_brand_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}),
|
out.cost_center = get_default_cost_center(
|
||||||
item_defaults, item_group_defaults, brand_defaults)
|
frappe._dict({"item_code": item.name, "company": company}),
|
||||||
|
item_defaults,
|
||||||
# Set Entry Type
|
item_group_defaults,
|
||||||
if not item_code:
|
brand_defaults,
|
||||||
out.entry_type = ""
|
)
|
||||||
elif out.target_is_fixed_asset:
|
|
||||||
out.entry_type = "Capitalization"
|
|
||||||
else:
|
|
||||||
out.entry_type = "Decapitalization"
|
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@ -510,7 +579,7 @@ def get_target_asset_details(asset=None, company=None):
|
|||||||
# Get Asset Details
|
# Get Asset Details
|
||||||
asset_details = frappe._dict()
|
asset_details = frappe._dict()
|
||||||
if asset:
|
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:
|
if not asset_details:
|
||||||
frappe.throw(_("Asset {0} does not exist").format(asset))
|
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
|
out.asset_name = asset_details.asset_name
|
||||||
|
|
||||||
if asset_details.item_code:
|
if asset_details.item_code:
|
||||||
out.target_fixed_asset_account = get_asset_category_account('fixed_asset_account', item=asset_details.item_code,
|
out.target_fixed_asset_account = get_asset_category_account(
|
||||||
company=company)
|
"fixed_asset_account", item=asset_details.item_code, company=company
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
out.target_fixed_asset_account = None
|
out.target_fixed_asset_account = None
|
||||||
|
|
||||||
@ -530,7 +600,7 @@ def get_target_asset_details(asset=None, company=None):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@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):
|
if isinstance(args, string_types):
|
||||||
args = json.loads(args)
|
args = json.loads(args)
|
||||||
|
|
||||||
@ -554,20 +624,25 @@ def get_consumed_stock_item_details(args, get_valuation_rate=True):
|
|||||||
item_defaults = get_item_defaults(item.name, args.company)
|
item_defaults = get_item_defaults(item.name, args.company)
|
||||||
item_group_defaults = get_item_group_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)
|
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:
|
if args.item_code and out.warehouse:
|
||||||
incoming_rate_args = frappe._dict({
|
incoming_rate_args = frappe._dict(
|
||||||
'item_code': args.item_code,
|
{
|
||||||
'warehouse': out.warehouse,
|
"item_code": args.item_code,
|
||||||
'posting_date': args.posting_date,
|
"warehouse": out.warehouse,
|
||||||
'posting_time': args.posting_time,
|
"posting_date": args.posting_date,
|
||||||
'qty': -1 * flt(out.stock_qty),
|
"posting_time": args.posting_time,
|
||||||
|
"qty": -1 * flt(out.stock_qty),
|
||||||
"voucher_type": args.doctype,
|
"voucher_type": args.doctype,
|
||||||
"voucher_no": args.name,
|
"voucher_no": args.name,
|
||||||
"company": args.company,
|
"company": args.company,
|
||||||
})
|
"serial_no": args.serial_no,
|
||||||
|
"batch_no": args.batch_no,
|
||||||
|
}
|
||||||
|
)
|
||||||
out.update(get_warehouse_details(incoming_rate_args))
|
out.update(get_warehouse_details(incoming_rate_args))
|
||||||
else:
|
else:
|
||||||
out.valuation_rate = 0
|
out.valuation_rate = 0
|
||||||
@ -587,13 +662,13 @@ def get_warehouse_details(args):
|
|||||||
if args.warehouse and args.item_code:
|
if args.warehouse and args.item_code:
|
||||||
out = {
|
out = {
|
||||||
"actual_qty": get_previous_sle(args).get("qty_after_transaction") or 0,
|
"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
|
return out
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_consumed_asset_details(args, get_asset_value=True):
|
def get_consumed_asset_details(args):
|
||||||
if isinstance(args, string_types):
|
if isinstance(args, string_types):
|
||||||
args = json.loads(args)
|
args = json.loads(args)
|
||||||
|
|
||||||
@ -602,7 +677,9 @@ def get_consumed_asset_details(args, get_asset_value=True):
|
|||||||
|
|
||||||
asset_details = frappe._dict()
|
asset_details = frappe._dict()
|
||||||
if args.asset:
|
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:
|
if not asset_details:
|
||||||
frappe.throw(_("Asset {0} does not exist").format(args.asset))
|
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.asset_name = asset_details.asset_name
|
||||||
out.item_name = asset_details.item_name
|
out.item_name = asset_details.item_name
|
||||||
|
|
||||||
if get_asset_value:
|
|
||||||
if args.asset:
|
if args.asset:
|
||||||
out.current_asset_value = flt(get_current_asset_value(args.asset, finance_book=args.finance_book))
|
out.current_asset_value = flt(
|
||||||
out.asset_value = get_value_after_depreciation_on_disposal_date(args.asset, args.posting_date,
|
get_current_asset_value(args.asset, finance_book=args.finance_book)
|
||||||
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:
|
else:
|
||||||
out.current_asset_value = 0
|
out.current_asset_value = 0
|
||||||
out.asset_value = 0
|
out.asset_value = 0
|
||||||
|
|
||||||
# Account
|
# Account
|
||||||
if asset_details.item_code:
|
if asset_details.item_code:
|
||||||
out.fixed_asset_account = get_asset_category_account('fixed_asset_account', item=asset_details.item_code,
|
out.fixed_asset_account = get_asset_category_account(
|
||||||
company=args.company)
|
"fixed_asset_account", item=asset_details.item_code, company=args.company
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
out.fixed_asset_account = None
|
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_defaults = get_item_defaults(item.name, args.company)
|
||||||
item_group_defaults = get_item_group_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)
|
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
|
return out
|
||||||
|
|
||||||
@ -657,7 +739,11 @@ def get_service_item_details(args):
|
|||||||
item_group_defaults = get_item_group_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)
|
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.expense_account = get_default_expense_account(
|
||||||
out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults)
|
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
|
return out
|
||||||
|
@ -22,9 +22,12 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
create_asset_capitalization_data()
|
create_asset_capitalization_data()
|
||||||
frappe.db.sql("delete from `tabTax Rule`")
|
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
|
# Variables
|
||||||
consumed_asset_value = 100_000
|
consumed_asset_value = 100000
|
||||||
|
|
||||||
stock_rate = 1000
|
stock_rate = 1000
|
||||||
stock_qty = 2
|
stock_qty = 2
|
||||||
@ -34,23 +37,39 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
service_qty = 2
|
service_qty = 2
|
||||||
service_amount = 1000
|
service_amount = 1000
|
||||||
|
|
||||||
total_amount = 103_000
|
total_amount = 103000
|
||||||
|
|
||||||
# Create assets
|
# Create assets
|
||||||
target_asset = create_asset(asset_name='Asset Capitalization Target Asset', submit=1)
|
target_asset = create_asset(
|
||||||
consumed_asset = create_asset(asset_name='Asset Capitalization Consumable Asset', asset_value=consumed_asset_value,
|
asset_name="Asset Capitalization Target Asset",
|
||||||
submit=1)
|
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
|
# Create and submit Asset Captitalization
|
||||||
asset_capitalization = create_asset_capitalization(target_asset=target_asset.name,
|
asset_capitalization = create_asset_capitalization(
|
||||||
stock_qty=stock_qty, stock_rate=stock_rate,
|
entry_type="Capitalization",
|
||||||
|
target_asset=target_asset.name,
|
||||||
|
stock_qty=stock_qty,
|
||||||
|
stock_rate=stock_rate,
|
||||||
consumed_asset=consumed_asset.name,
|
consumed_asset=consumed_asset.name,
|
||||||
service_qty=service_qty, service_rate=service_rate,
|
service_qty=service_qty,
|
||||||
service_expense_account='Expenses Included In Asset Valuation - _TC',
|
service_rate=service_rate,
|
||||||
submit=1)
|
service_expense_account="Expenses Included In Asset Valuation - TCP1",
|
||||||
|
company=company,
|
||||||
|
submit=1,
|
||||||
|
)
|
||||||
|
|
||||||
# Test Asset Capitalization values
|
# 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.target_qty, 1)
|
||||||
|
|
||||||
self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate)
|
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)
|
self.assertEqual(target_asset.purchase_receipt_amount, total_amount)
|
||||||
|
|
||||||
# Test Consumed Asset values
|
# Test Consumed Asset values
|
||||||
self.assertEqual(consumed_asset.db_get('status'), 'Capitalized')
|
self.assertEqual(consumed_asset.db_get("status"), "Capitalized")
|
||||||
|
|
||||||
# Test General Ledger Entries
|
# Test General Ledger Entries
|
||||||
expected_gle = {
|
expected_gle = {
|
||||||
'_Test Fixed Asset - _TC': 3000,
|
"_Test Fixed Asset - TCP1": 3000,
|
||||||
'Expenses Included In Asset Valuation - _TC': -1000,
|
"Expenses Included In Asset Valuation - TCP1": -1000,
|
||||||
'Stock In Hand - _TC' : -2000
|
"_Test Warehouse - TCP1": -2000,
|
||||||
}
|
}
|
||||||
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
||||||
|
|
||||||
@ -86,25 +105,121 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
|
|
||||||
# Test Stock Ledger Entries
|
# Test Stock Ledger Entries
|
||||||
expected_sle = {
|
expected_sle = {
|
||||||
('Capitalization Source Stock Item', '_Test Warehouse - _TC'): {
|
("Capitalization Source Stock Item", "_Test Warehouse - TCP1"): {
|
||||||
'actual_qty': -stock_qty, 'stock_value_difference': -stock_amount
|
"actual_qty": -stock_qty,
|
||||||
|
"stock_value_difference": -stock_amount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actual_sle = get_actual_sle_dict(asset_capitalization.name)
|
actual_sle = get_actual_sle_dict(asset_capitalization.name)
|
||||||
|
|
||||||
self.assertEqual(actual_sle, expected_sle)
|
self.assertEqual(actual_sle, expected_sle)
|
||||||
|
|
||||||
# Cancel Asset Capitalization and make test entries and status are reversed
|
# Cancel Asset Capitalization and make test entries and status are reversed
|
||||||
asset_capitalization.cancel()
|
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_gle_dict(asset_capitalization.name))
|
||||||
self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
|
self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
|
||||||
|
|
||||||
def test_decapitalization_with_depreciation(self):
|
def test_decapitalization_with_depreciation(self):
|
||||||
# Variables
|
# Variables
|
||||||
purchase_date = '2020-01-01'
|
purchase_date = "2020-01-01"
|
||||||
depreciation_start_date = '2020-12-31'
|
depreciation_start_date = "2020-12-31"
|
||||||
capitalization_date = '2021-06-30'
|
capitalization_date = "2021-06-30"
|
||||||
|
|
||||||
total_number_of_depreciations = 3
|
total_number_of_depreciations = 3
|
||||||
expected_value_after_useful_life = 10_000
|
expected_value_after_useful_life = 10_000
|
||||||
@ -126,29 +241,38 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
|
|
||||||
# Create assets
|
# Create assets
|
||||||
consumed_asset = create_depreciation_asset(
|
consumed_asset = create_depreciation_asset(
|
||||||
asset_name='Asset Capitalization Consumable Asset',
|
asset_name="Asset Capitalization Consumable Asset",
|
||||||
asset_value=consumed_asset_purchase_value,
|
asset_value=consumed_asset_purchase_value,
|
||||||
purchase_date=purchase_date,
|
purchase_date=purchase_date,
|
||||||
depreciation_start_date=depreciation_start_date,
|
depreciation_start_date=depreciation_start_date,
|
||||||
depreciation_method='Straight Line',
|
depreciation_method="Straight Line",
|
||||||
total_number_of_depreciations=total_number_of_depreciations,
|
total_number_of_depreciations=total_number_of_depreciations,
|
||||||
frequency_of_depreciation=12,
|
frequency_of_depreciation=12,
|
||||||
expected_value_after_useful_life=expected_value_after_useful_life,
|
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
|
# Create and submit Asset Captitalization
|
||||||
asset_capitalization = create_asset_capitalization(
|
asset_capitalization = create_asset_capitalization(
|
||||||
|
entry_type="Decapitalization",
|
||||||
posting_date=capitalization_date, # half a year
|
posting_date=capitalization_date, # half a year
|
||||||
target_item_code="Capitalization Target Stock Item",
|
target_item_code="Capitalization Target Stock Item",
|
||||||
target_qty=target_qty,
|
target_qty=target_qty,
|
||||||
consumed_asset=consumed_asset.name,
|
consumed_asset=consumed_asset.name,
|
||||||
submit=1)
|
company="_Test Company with perpetual inventory",
|
||||||
|
submit=1,
|
||||||
|
)
|
||||||
|
|
||||||
# Test Asset Capitalization values
|
# 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(
|
||||||
self.assertEqual(asset_capitalization.asset_items[0].asset_value, consumed_asset_value_before_disposal)
|
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.asset_items_total, consumed_asset_value_before_disposal)
|
||||||
|
|
||||||
self.assertEqual(asset_capitalization.total_value, 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
|
# Test Consumed Asset values
|
||||||
consumed_asset.reload()
|
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
|
consumed_depreciation_schedule = [
|
||||||
if getdate(d.schedule_date) == getdate(capitalization_date)]
|
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)
|
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
|
# Test General Ledger Entries
|
||||||
expected_gle = {
|
expected_gle = {
|
||||||
'Stock In Hand - _TC': consumed_asset_value_before_disposal,
|
"_Test Warehouse - TCP1": consumed_asset_value_before_disposal,
|
||||||
'_Test Accumulated Depreciations - _TC': accumulated_depreciation,
|
"_Test Accumulated Depreciations - TCP1": accumulated_depreciation,
|
||||||
'_Test Fixed Asset - _TC': -consumed_asset_purchase_value,
|
"_Test Fixed Asset - TCP1": -consumed_asset_purchase_value,
|
||||||
}
|
}
|
||||||
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
||||||
|
|
||||||
self.assertEqual(actual_gle, expected_gle)
|
self.assertEqual(actual_gle, expected_gle)
|
||||||
|
|
||||||
# Cancel Asset Capitalization and make test entries and status are reversed
|
# Cancel Asset Capitalization and make test entries and status are reversed
|
||||||
asset_capitalization.reload()
|
asset_capitalization.reload()
|
||||||
asset_capitalization.cancel()
|
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_gle_dict(asset_capitalization.name))
|
||||||
self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
|
self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
|
||||||
|
|
||||||
|
|
||||||
def create_asset_capitalization_data():
|
def create_asset_capitalization_data():
|
||||||
create_item("Capitalization Target Stock Item",
|
create_item(
|
||||||
is_stock_item=1, is_fixed_asset=0, is_purchase_item=0)
|
"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(
|
||||||
create_item("Capitalization Source Service Item",
|
"Capitalization Source Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0
|
||||||
is_stock_item=0, 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):
|
def create_asset_capitalization(**args):
|
||||||
@ -204,43 +335,55 @@ def create_asset_capitalization(**args):
|
|||||||
source_warehouse = args.source_warehouse or warehouse
|
source_warehouse = args.source_warehouse or warehouse
|
||||||
|
|
||||||
asset_capitalization = frappe.new_doc("Asset Capitalization")
|
asset_capitalization = frappe.new_doc("Asset Capitalization")
|
||||||
asset_capitalization.update({
|
asset_capitalization.update(
|
||||||
|
{
|
||||||
|
"entry_type": args.entry_type or "Capitalization",
|
||||||
"company": company,
|
"company": company,
|
||||||
"posting_date": args.posting_date or now.strftime('%Y-%m-%d'),
|
"posting_date": args.posting_date or now.strftime("%Y-%m-%d"),
|
||||||
"posting_time": args.posting_time or now.strftime('%H:%M:%S.%f'),
|
"posting_time": args.posting_time or now.strftime("%H:%M:%S.%f"),
|
||||||
"target_item_code": target_item_code,
|
"target_item_code": target_item_code,
|
||||||
"target_asset": target_asset.name,
|
"target_asset": target_asset.name,
|
||||||
"target_warehouse": target_warehouse,
|
"target_warehouse": target_warehouse,
|
||||||
"target_qty": flt(args.target_qty) or 1,
|
"target_qty": flt(args.target_qty) or 1,
|
||||||
"target_batch_no": args.target_batch_no,
|
"target_batch_no": args.target_batch_no,
|
||||||
"target_serial_no": args.target_serial_no,
|
"target_serial_no": args.target_serial_no,
|
||||||
"finance_book": args.finance_book
|
"finance_book": args.finance_book,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if args.posting_date or args.posting_time:
|
if args.posting_date or args.posting_time:
|
||||||
asset_capitalization.set_posting_time = 1
|
asset_capitalization.set_posting_time = 1
|
||||||
|
|
||||||
if flt(args.stock_rate):
|
if flt(args.stock_rate):
|
||||||
asset_capitalization.append("stock_items", {
|
asset_capitalization.append(
|
||||||
|
"stock_items",
|
||||||
|
{
|
||||||
"item_code": args.stock_item or "Capitalization Source Stock Item",
|
"item_code": args.stock_item or "Capitalization Source Stock Item",
|
||||||
"warehouse": source_warehouse,
|
"warehouse": source_warehouse,
|
||||||
"stock_qty": flt(args.stock_qty) or 1,
|
"stock_qty": flt(args.stock_qty) or 1,
|
||||||
"batch_no": args.stock_batch_no,
|
"batch_no": args.stock_batch_no,
|
||||||
"serial_no": args.stock_serial_no,
|
"serial_no": args.stock_serial_no,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
if args.consumed_asset:
|
if args.consumed_asset:
|
||||||
asset_capitalization.append("asset_items", {
|
asset_capitalization.append(
|
||||||
|
"asset_items",
|
||||||
|
{
|
||||||
"asset": args.consumed_asset,
|
"asset": args.consumed_asset,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
if flt(args.service_rate):
|
if flt(args.service_rate):
|
||||||
asset_capitalization.append("service_items", {
|
asset_capitalization.append(
|
||||||
|
"service_items",
|
||||||
|
{
|
||||||
"item_code": args.service_item or "Capitalization Source Service Item",
|
"item_code": args.service_item or "Capitalization Source Service Item",
|
||||||
"expense_account": args.service_expense_account,
|
"expense_account": args.service_expense_account,
|
||||||
"qty": flt(args.service_qty) or 1,
|
"qty": flt(args.service_qty) or 1,
|
||||||
"rate": flt(args.service_rate)
|
"rate": flt(args.service_rate),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
if args.submit:
|
if args.submit:
|
||||||
create_stock_reconciliation(asset_capitalization, stock_rate=args.stock_rate)
|
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):
|
def create_stock_reconciliation(asset_capitalization, stock_rate=0):
|
||||||
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
||||||
|
EmptyStockReconciliationItemsError,
|
||||||
create_stock_reconciliation,
|
create_stock_reconciliation,
|
||||||
)
|
)
|
||||||
if not asset_capitalization.get('stock_items'):
|
|
||||||
|
if not asset_capitalization.get("stock_items"):
|
||||||
return
|
return
|
||||||
|
|
||||||
return create_stock_reconciliation(
|
try:
|
||||||
|
create_stock_reconciliation(
|
||||||
item_code=asset_capitalization.stock_items[0].item_code,
|
item_code=asset_capitalization.stock_items[0].item_code,
|
||||||
warehouse=asset_capitalization.stock_items[0].warehouse,
|
warehouse=asset_capitalization.stock_items[0].warehouse,
|
||||||
qty=flt(asset_capitalization.stock_items[0].stock_qty),
|
qty=flt(asset_capitalization.stock_items[0].stock_qty),
|
||||||
rate=flt(stock_rate),
|
rate=flt(stock_rate),
|
||||||
company=asset_capitalization.company)
|
company=asset_capitalization.company,
|
||||||
|
)
|
||||||
|
except EmptyStockReconciliationItemsError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def create_depreciation_asset(**args):
|
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.asset_name = args.asset_name or asset.item_code
|
||||||
asset.location = args.location or "Test Location"
|
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.available_for_use_date = args.available_for_use_date or asset.purchase_date
|
||||||
|
|
||||||
asset.gross_purchase_amount = args.asset_value or 100000
|
asset.gross_purchase_amount = args.asset_value or 100000
|
||||||
asset.purchase_receipt_amount = asset.gross_purchase_amount
|
asset.purchase_receipt_amount = asset.gross_purchase_amount
|
||||||
|
|
||||||
finance_book = asset.append('finance_books')
|
finance_book = asset.append("finance_books")
|
||||||
finance_book.depreciation_start_date = args.depreciation_start_date or '2020-12-31'
|
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.depreciation_method = args.depreciation_method or "Straight Line"
|
||||||
finance_book.total_number_of_depreciations = cint(args.total_number_of_depreciations) or 3
|
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.frequency_of_depreciation = cint(args.frequency_of_depreciation) or 12
|
||||||
finance_book.expected_value_after_useful_life = flt(args.expected_value_after_useful_life)
|
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):
|
def get_actual_gle_dict(name):
|
||||||
return dict(frappe.db.sql("""
|
return dict(
|
||||||
|
frappe.db.sql(
|
||||||
|
"""
|
||||||
select account, sum(debit-credit) as diff
|
select account, sum(debit-credit) as diff
|
||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where voucher_type = 'Asset Capitalization' and voucher_no = %s
|
where voucher_type = 'Asset Capitalization' and voucher_no = %s
|
||||||
group by account
|
group by account
|
||||||
having diff != 0
|
having diff != 0
|
||||||
""", name))
|
""",
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_actual_sle_dict(name):
|
def get_actual_sle_dict(name):
|
||||||
sles = frappe.db.sql("""
|
sles = frappe.db.sql(
|
||||||
|
"""
|
||||||
select
|
select
|
||||||
item_code, warehouse,
|
item_code, warehouse,
|
||||||
sum(actual_qty) as actual_qty,
|
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
|
where voucher_type = 'Asset Capitalization' and voucher_no = %s
|
||||||
group by item_code, warehouse
|
group by item_code, warehouse
|
||||||
having actual_qty != 0
|
having actual_qty != 0
|
||||||
""", name, as_dict=1)
|
""",
|
||||||
|
name,
|
||||||
|
as_dict=1,
|
||||||
|
)
|
||||||
|
|
||||||
sle_dict = {}
|
sle_dict = {}
|
||||||
for d in sles:
|
for d in sles:
|
||||||
sle_dict[(d.item_code, d.warehouse)] = {
|
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
|
return sle_dict
|
||||||
|
@ -129,18 +129,6 @@ class TestAssetRepair(unittest.TestCase):
|
|||||||
def test_gl_entries_with_perpetual_inventory(self):
|
def test_gl_entries_with_perpetual_inventory(self):
|
||||||
set_depreciation_settings_in_company(company="_Test Company with perpetual inventory")
|
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(
|
asset_repair = create_asset_repair(
|
||||||
capitalize_repair_cost=1,
|
capitalize_repair_cost=1,
|
||||||
stock_consumption=1,
|
stock_consumption=1,
|
||||||
|
@ -727,7 +727,12 @@ def create_stock_reconciliation(**args):
|
|||||||
sr.set_posting_time = 1
|
sr.set_posting_time = 1
|
||||||
sr.company = args.company or "_Test Company"
|
sr.company = args.company or "_Test Company"
|
||||||
sr.expense_account = args.expense_account or (
|
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 = (
|
sr.cost_center = (
|
||||||
args.cost_center
|
args.cost_center
|
||||||
|
Loading…
x
Reference in New Issue
Block a user