Skip to content

Commit

Permalink
Merge pull request #441 from 8848digital/assets_remove_from_buying_co…
Browse files Browse the repository at this point in the history
…ntrolley

feat: removing assets dependency for buying controller and purchase receipt
  • Loading branch information
aasif-patel authored Oct 25, 2024
2 parents 193ee0c + f3e17ba commit f7ce9e8
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 332 deletions.
221 changes: 11 additions & 210 deletions erpnext/controllers/buying_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ def validate(self):
self.validate_warehouse()
self.validate_from_warehouse()
self.set_supplier_address()
self.validate_asset_return()
self.validate_auto_repeat_subscription_dates()
self.create_package_for_transfer()

Expand Down Expand Up @@ -166,7 +165,7 @@ def set_supplier_from_item_default(self):
break

def validate_stock_or_nonstock_items(self):
if self.meta.get_field("taxes") and not self.get_stock_items() and not self.get_asset_items():
if self.meta.get_field("taxes") and not self.get_stock_items():
msg = _('Tax Category has been changed to "Total" because all the Items are non-stock items')
self.update_tax_category(msg)

Expand All @@ -181,32 +180,6 @@ def update_tax_category(self, msg):

msgprint(msg)

def validate_asset_return(self):
if self.doctype not in ["Purchase Receipt", "Purchase Invoice"] or not self.is_return:
return

purchase_doc_field = "purchase_receipt" if self.doctype == "Purchase Receipt" else "purchase_invoice"
not_cancelled_asset = []
if self.return_against:
not_cancelled_asset = [
d.name
for d in frappe.db.get_all("Asset", {purchase_doc_field: self.return_against, "docstatus": 1})
]

if self.is_return and len(not_cancelled_asset):
frappe.throw(
_(
"{} has submitted assets linked to it. You need to cancel the assets to create purchase return."
).format(self.return_against),
title=_("Not Allowed"),
)

def get_asset_items(self):
if self.doctype not in ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]:
return []

return [d.item_code for d in self.items if d.is_fixed_asset]

def set_landed_cost_voucher_amount(self):
for d in self.get("items"):
lc_voucher_data = frappe.db.sql(
Expand Down Expand Up @@ -277,15 +250,15 @@ def update_valuation_rate(self, reset_outgoing_rate=True):
TODO: rename item_tax_amount to valuation_tax_amount
"""
stock_and_asset_items = []
stock_and_asset_items = self.get_stock_items() + self.get_asset_items()
stock_items = []
stock_items = self.get_stock_items()

stock_and_asset_items_qty, stock_and_asset_items_amount = 0, 0
stock_items_qty, stock_items_amount = 0, 0
last_item_idx = 1
for d in self.get("items"):
if d.item_code and d.item_code in stock_and_asset_items:
stock_and_asset_items_qty += flt(d.qty)
stock_and_asset_items_amount += flt(d.base_net_amount)
if d.item_code and d.item_code in stock_items:
stock_items_qty += flt(d.qty)
stock_items_amount += flt(d.base_net_amount)
last_item_idx = d.idx

total_valuation_amount = sum(
Expand All @@ -296,11 +269,11 @@ def update_valuation_rate(self, reset_outgoing_rate=True):

valuation_amount_adjustment = total_valuation_amount
for i, item in enumerate(self.get("items")):
if item.item_code and item.qty and item.item_code in stock_and_asset_items:
if item.item_code and item.qty and item.item_code in stock_items:
item_proportion = (
flt(item.base_net_amount) / stock_and_asset_items_amount
if stock_and_asset_items_amount
else flt(item.qty) / stock_and_asset_items_qty
flt(item.base_net_amount) / stock_items_amount
if stock_items_amount
else flt(item.qty) / stock_items_qty
)

if i == (last_item_idx - 1):
Expand Down Expand Up @@ -691,9 +664,6 @@ def on_submit(self):
if self.get("is_return"):
return

if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
self.process_fixed_asset()

if self.doctype in [
"Purchase Order",
"Purchase Receipt",
Expand All @@ -712,12 +682,6 @@ def on_cancel(self):
):
update_last_purchase_rate(self, is_submit=0)

if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
field = "purchase_invoice" if self.doctype == "Purchase Invoice" else "purchase_receipt"

self.delete_linked_asset()
self.update_fixed_asset(field, delete_asset=True)

def validate_budget(self):
if self.docstatus == 1:
for data in self.get("items"):
Expand All @@ -736,156 +700,6 @@ def validate_budget(self):

validate_expense_against_budget(args)

def process_fixed_asset(self):
if self.doctype == "Purchase Invoice" and not self.update_stock:
return

asset_items = self.get_asset_items()
if asset_items:
self.auto_make_assets(asset_items)

def auto_make_assets(self, asset_items):
items_data = get_asset_item_details(asset_items)
messages = []

for d in self.items:
if d.is_fixed_asset:
item_data = items_data.get(d.item_code)

if item_data.get("auto_create_assets"):
# If asset has to be auto created
# Check for asset naming series
if item_data.get("asset_naming_series"):
created_assets = []
if item_data.get("is_grouped_asset"):
asset = self.make_asset(d, is_grouped_asset=True)
created_assets.append(asset)
else:
for _qty in range(cint(d.qty)):
asset = self.make_asset(d)
created_assets.append(asset)

if len(created_assets) > 5:
# dont show asset form links if more than 5 assets are created
messages.append(
_("{} Assets created for {}").format(
len(created_assets), frappe.bold(d.item_code)
)
)
else:
assets_link = list(
map(lambda d: frappe.utils.get_link_to_form("Asset", d), created_assets)
)
assets_link = frappe.bold(",".join(assets_link))

is_plural = "s" if len(created_assets) != 1 else ""
messages.append(
_("Asset{} {assets_link} created for {}").format(
is_plural, frappe.bold(d.item_code), assets_link=assets_link
)
)
else:
frappe.throw(
_(
"Row {}: Asset Naming Series is mandatory for the auto creation for item {}"
).format(d.idx, frappe.bold(d.item_code))
)
else:
messages.append(
_("Assets not created for {0}. You will have to create asset manually.").format(
frappe.bold(d.item_code)
)
)

for message in messages:
frappe.msgprint(message, title="Success", indicator="green")

def make_asset(self, row, is_grouped_asset=False):
if not row.asset_location:
frappe.throw(_("Row {0}: Enter location for the asset item {1}").format(row.idx, row.item_code))

item_data = frappe.get_cached_value(
"Item", row.item_code, ["asset_naming_series", "asset_category"], as_dict=1
)
asset_quantity = row.qty if is_grouped_asset else 1
purchase_amount = flt(row.valuation_rate) * asset_quantity

asset = frappe.get_doc(
{
"doctype": "Asset",
"item_code": row.item_code,
"asset_name": row.item_name,
"naming_series": item_data.get("asset_naming_series") or "AST",
"asset_category": item_data.get("asset_category"),
"location": row.asset_location,
"company": self.company,
"supplier": self.supplier,
"purchase_date": self.posting_date,
"calculate_depreciation": 0,
"purchase_amount": purchase_amount,
"gross_purchase_amount": purchase_amount,
"asset_quantity": asset_quantity,
"purchase_receipt": self.name if self.doctype == "Purchase Receipt" else None,
"purchase_invoice": self.name if self.doctype == "Purchase Invoice" else None,
}
)

asset.flags.ignore_validate = True
asset.flags.ignore_mandatory = True
asset.set_missing_values()
asset.db_insert()

return asset.name

def update_fixed_asset(self, field, delete_asset=False):
for d in self.get("items"):
if d.is_fixed_asset:
is_auto_create_enabled = frappe.db.get_value("Item", d.item_code, "auto_create_assets")
assets = frappe.db.get_all("Asset", filters={field: self.name, "item_code": d.item_code})

for asset in assets:
asset = frappe.get_doc("Asset", asset.name)
if delete_asset and is_auto_create_enabled:
# need to delete movements to delete assets otherwise throws link exists error
movements = frappe.db.sql(
"""SELECT asm.name
FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
WHERE asm_item.parent=asm.name and asm_item.asset=%s""",
asset.name,
as_dict=1,
)
for movement in movements:
frappe.delete_doc("Asset Movement", movement.name, force=1)
frappe.delete_doc("Asset", asset.name, force=1)
continue

if self.docstatus == 2:
if asset.docstatus == 2:
continue
if asset.docstatus == 0:
asset.set(field, None)
asset.supplier = None
if asset.docstatus == 1 and delete_asset:
frappe.throw(
_(
"Cannot cancel this document as it is linked with submitted asset {0}. Please cancel it to continue."
).format(frappe.utils.get_link_to_form("Asset", asset.name))
)

asset.flags.ignore_validate_update_after_submit = True
asset.flags.ignore_mandatory = True
if asset.docstatus == 0:
asset.flags.ignore_validate = True

asset.save()

def delete_linked_asset(self):
if self.doctype == "Purchase Invoice" and not self.get("update_stock"):
return

asset_movement = frappe.db.get_value("Asset Movement", {"reference_name": self.name}, "name")
frappe.delete_doc("Asset Movement", asset_movement, force=1)

def validate_schedule_date(self):
if not self.get("items"):
return
Expand Down Expand Up @@ -920,19 +734,6 @@ def validate_items(self):
else:
validate_item_type(self, "is_purchase_item", "purchase")


def get_asset_item_details(asset_items):
asset_items_data = {}
for d in frappe.get_all(
"Item",
fields=["name", "auto_create_assets", "asset_naming_series", "is_grouped_asset"],
filters={"name": ("in", asset_items)},
):
asset_items_data.setdefault(d.name, d)

return asset_items_data


def validate_item_type(doc, fieldname, message):
# iterate through items and check if they are valid sales or purchase items
items = [d.item_code for d in doc.items if d.item_code]
Expand Down
28 changes: 0 additions & 28 deletions erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ frappe.ui.form.on("Purchase Receipt", {
};
});

frm.set_query("wip_composite_asset", "items", function () {
return {
filters: { is_composite_asset: 1, docstatus: 0 },
};
});

frm.set_query("taxes_and_charges", function () {
return {
filters: { company: frm.doc.company },
Expand Down Expand Up @@ -195,28 +189,6 @@ erpnext.stock.PurchaseReceiptController = class PurchaseReceiptController extend
this.show_stock_ledger();
//removed for temporary
this.show_general_ledger();

this.frm.add_custom_button(
__("Asset"),
function () {
frappe.route_options = {
purchase_receipt: me.frm.doc.name,
};
frappe.set_route("List", "Asset");
},
__("View")
);

this.frm.add_custom_button(
__("Asset Movement"),
function () {
frappe.route_options = {
reference_name: me.frm.doc.name,
};
frappe.set_route("List", "Asset Movement");
},
__("View")
);
}

if (!this.frm.doc.is_return && this.frm.doc.status != "Closed") {
Expand Down
Loading

0 comments on commit f7ce9e8

Please sign in to comment.