mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-31 10:49:09 +00:00
Merge pull request #36295 from frappe/version-13-hotfix
chore: release v13
This commit is contained in:
@@ -63,20 +63,21 @@ class AssetMovement(Document):
|
|||||||
frappe.throw(_("Source and Target Location cannot be same"))
|
frappe.throw(_("Source and Target Location cannot be same"))
|
||||||
|
|
||||||
if self.purpose == "Receipt":
|
if self.purpose == "Receipt":
|
||||||
if not (d.source_location or d.from_employee) and not (d.target_location or d.to_employee):
|
if not (d.source_location) and not (d.target_location or d.to_employee):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Target Location or To Employee is required while receiving Asset {0}").format(d.asset)
|
_("Target Location or To Employee is required while receiving Asset {0}").format(d.asset)
|
||||||
)
|
)
|
||||||
elif d.from_employee and not d.target_location:
|
elif d.source_location:
|
||||||
frappe.throw(
|
if d.from_employee and not d.target_location:
|
||||||
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
|
frappe.throw(
|
||||||
)
|
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
|
||||||
elif d.to_employee and d.target_location:
|
)
|
||||||
frappe.throw(
|
elif d.to_employee and d.target_location:
|
||||||
_(
|
frappe.throw(
|
||||||
"Asset {0} cannot be received at a location and given to an employee in a single movement"
|
_(
|
||||||
).format(d.asset)
|
"Asset {0} cannot be received at a location and given to an employee in a single movement"
|
||||||
)
|
).format(d.asset)
|
||||||
|
)
|
||||||
|
|
||||||
def validate_employee(self):
|
def validate_employee(self):
|
||||||
for d in self.assets:
|
for d in self.assets:
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ def get_conditions(filters):
|
|||||||
conditions["cost_center"] = filters.get("cost_center")
|
conditions["cost_center"] = filters.get("cost_center")
|
||||||
|
|
||||||
if status:
|
if status:
|
||||||
# In Store assets are those that are not sold or scrapped
|
# In Store assets are those that are not sold or scrapped or capitalized or decapitalized
|
||||||
operand = "not in"
|
operand = "not in"
|
||||||
if status not in "In Location":
|
if status not in "In Location":
|
||||||
operand = "in"
|
operand = "in"
|
||||||
|
|
||||||
conditions["status"] = (operand, ["Sold", "Scrapped"])
|
conditions["status"] = (operand, ["Sold", "Scrapped", "Capitalized", "Decapitalized"])
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
@@ -71,36 +71,6 @@ def get_data(filters):
|
|||||||
pr_supplier_map = get_purchase_receipt_supplier_map()
|
pr_supplier_map = get_purchase_receipt_supplier_map()
|
||||||
pi_supplier_map = get_purchase_invoice_supplier_map()
|
pi_supplier_map = get_purchase_invoice_supplier_map()
|
||||||
|
|
||||||
group_by = frappe.scrub(filters.get("group_by"))
|
|
||||||
|
|
||||||
if group_by == "asset_category":
|
|
||||||
fields = ["asset_category", "gross_purchase_amount", "opening_accumulated_depreciation"]
|
|
||||||
assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields, group_by=group_by)
|
|
||||||
|
|
||||||
elif group_by == "location":
|
|
||||||
fields = ["location", "gross_purchase_amount", "opening_accumulated_depreciation"]
|
|
||||||
assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields, group_by=group_by)
|
|
||||||
|
|
||||||
else:
|
|
||||||
fields = [
|
|
||||||
"name as asset_id",
|
|
||||||
"asset_name",
|
|
||||||
"status",
|
|
||||||
"department",
|
|
||||||
"company",
|
|
||||||
"cost_center",
|
|
||||||
"calculate_depreciation",
|
|
||||||
"purchase_receipt",
|
|
||||||
"asset_category",
|
|
||||||
"purchase_date",
|
|
||||||
"gross_purchase_amount",
|
|
||||||
"location",
|
|
||||||
"available_for_use_date",
|
|
||||||
"purchase_invoice",
|
|
||||||
"opening_accumulated_depreciation",
|
|
||||||
]
|
|
||||||
assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields)
|
|
||||||
|
|
||||||
assets_linked_to_fb = get_assets_linked_to_fb(filters)
|
assets_linked_to_fb = get_assets_linked_to_fb(filters)
|
||||||
|
|
||||||
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
|
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
|
||||||
@@ -114,6 +84,31 @@ def get_data(filters):
|
|||||||
|
|
||||||
depreciation_amount_map = get_asset_depreciation_amount_map(filters, finance_book)
|
depreciation_amount_map = get_asset_depreciation_amount_map(filters, finance_book)
|
||||||
|
|
||||||
|
group_by = frappe.scrub(filters.get("group_by"))
|
||||||
|
|
||||||
|
if group_by in ("asset_category", "location"):
|
||||||
|
data = get_group_by_data(group_by, conditions, assets_linked_to_fb, depreciation_amount_map)
|
||||||
|
return data
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
"name as asset_id",
|
||||||
|
"asset_name",
|
||||||
|
"status",
|
||||||
|
"department",
|
||||||
|
"company",
|
||||||
|
"cost_center",
|
||||||
|
"calculate_depreciation",
|
||||||
|
"purchase_receipt",
|
||||||
|
"asset_category",
|
||||||
|
"purchase_date",
|
||||||
|
"gross_purchase_amount",
|
||||||
|
"location",
|
||||||
|
"available_for_use_date",
|
||||||
|
"purchase_invoice",
|
||||||
|
"opening_accumulated_depreciation",
|
||||||
|
]
|
||||||
|
assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields)
|
||||||
|
|
||||||
for asset in assets_record:
|
for asset in assets_record:
|
||||||
if (
|
if (
|
||||||
assets_linked_to_fb
|
assets_linked_to_fb
|
||||||
@@ -136,7 +131,7 @@ def get_data(filters):
|
|||||||
or pi_supplier_map.get(asset.purchase_invoice),
|
or pi_supplier_map.get(asset.purchase_invoice),
|
||||||
"gross_purchase_amount": asset.gross_purchase_amount,
|
"gross_purchase_amount": asset.gross_purchase_amount,
|
||||||
"opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
|
"opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
|
||||||
"depreciated_amount": get_depreciation_amount_of_asset(asset, depreciation_amount_map),
|
"depreciated_amount": depreciation_amount_map.get(asset.asset_id) or 0.0,
|
||||||
"available_for_use_date": asset.available_for_use_date,
|
"available_for_use_date": asset.available_for_use_date,
|
||||||
"location": asset.location,
|
"location": asset.location,
|
||||||
"asset_category": asset.asset_category,
|
"asset_category": asset.asset_category,
|
||||||
@@ -230,12 +225,11 @@ def get_assets_linked_to_fb(filters):
|
|||||||
return assets_linked_to_fb
|
return assets_linked_to_fb
|
||||||
|
|
||||||
|
|
||||||
def get_depreciation_amount_of_asset(asset, depreciation_amount_map):
|
|
||||||
return depreciation_amount_map.get(asset.asset_id) or 0.0
|
|
||||||
|
|
||||||
|
|
||||||
def get_asset_depreciation_amount_map(filters, finance_book):
|
def get_asset_depreciation_amount_map(filters, finance_book):
|
||||||
date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date
|
start_date = (
|
||||||
|
filters.from_date if filters.filter_based_on == "Date Range" else filters.year_start_date
|
||||||
|
)
|
||||||
|
end_date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date
|
||||||
|
|
||||||
asset = frappe.qb.DocType("Asset")
|
asset = frappe.qb.DocType("Asset")
|
||||||
gle = frappe.qb.DocType("GL Entry")
|
gle = frappe.qb.DocType("GL Entry")
|
||||||
@@ -256,25 +250,77 @@ def get_asset_depreciation_amount_map(filters, finance_book):
|
|||||||
)
|
)
|
||||||
.where(gle.debit != 0)
|
.where(gle.debit != 0)
|
||||||
.where(gle.is_cancelled == 0)
|
.where(gle.is_cancelled == 0)
|
||||||
|
.where(company.name == filters.company)
|
||||||
.where(asset.docstatus == 1)
|
.where(asset.docstatus == 1)
|
||||||
.groupby(asset.name)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if filters.only_existing_assets:
|
||||||
|
query = query.where(asset.is_existing_asset == 1)
|
||||||
|
if filters.asset_category:
|
||||||
|
query = query.where(asset.asset_category == filters.asset_category)
|
||||||
|
if filters.cost_center:
|
||||||
|
query = query.where(asset.cost_center == filters.cost_center)
|
||||||
|
if filters.status:
|
||||||
|
if filters.status == "In Location":
|
||||||
|
query = query.where(asset.status.notin(["Sold", "Scrapped", "Capitalized", "Decapitalized"]))
|
||||||
|
else:
|
||||||
|
query = query.where(asset.status.isin(["Sold", "Scrapped", "Capitalized", "Decapitalized"]))
|
||||||
if finance_book:
|
if finance_book:
|
||||||
query = query.where(
|
query = query.where(
|
||||||
(gle.finance_book.isin([cstr(finance_book), ""])) | (gle.finance_book.isnull())
|
(gle.finance_book.isin([cstr(finance_book), ""])) | (gle.finance_book.isnull())
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
query = query.where((gle.finance_book.isin([""])) | (gle.finance_book.isnull()))
|
query = query.where((gle.finance_book.isin([""])) | (gle.finance_book.isnull()))
|
||||||
|
|
||||||
if filters.filter_based_on in ("Date Range", "Fiscal Year"):
|
if filters.filter_based_on in ("Date Range", "Fiscal Year"):
|
||||||
query = query.where(gle.posting_date <= date)
|
query = query.where(gle.posting_date >= start_date)
|
||||||
|
query = query.where(gle.posting_date <= end_date)
|
||||||
|
|
||||||
|
query = query.groupby(asset.name)
|
||||||
|
|
||||||
asset_depr_amount_map = query.run()
|
asset_depr_amount_map = query.run()
|
||||||
|
|
||||||
return dict(asset_depr_amount_map)
|
return dict(asset_depr_amount_map)
|
||||||
|
|
||||||
|
|
||||||
|
def get_group_by_data(group_by, conditions, assets_linked_to_fb, depreciation_amount_map):
|
||||||
|
fields = [
|
||||||
|
group_by,
|
||||||
|
"name",
|
||||||
|
"gross_purchase_amount",
|
||||||
|
"opening_accumulated_depreciation",
|
||||||
|
"calculate_depreciation",
|
||||||
|
]
|
||||||
|
assets = frappe.db.get_all("Asset", filters=conditions, fields=fields)
|
||||||
|
|
||||||
|
data = []
|
||||||
|
|
||||||
|
for a in assets:
|
||||||
|
if assets_linked_to_fb and a.calculate_depreciation and a.name not in assets_linked_to_fb:
|
||||||
|
continue
|
||||||
|
|
||||||
|
a["depreciated_amount"] = depreciation_amount_map.get(a["name"], 0.0)
|
||||||
|
a["asset_value"] = (
|
||||||
|
a["gross_purchase_amount"] - a["opening_accumulated_depreciation"] - a["depreciated_amount"]
|
||||||
|
)
|
||||||
|
|
||||||
|
del a["name"]
|
||||||
|
del a["calculate_depreciation"]
|
||||||
|
|
||||||
|
idx = ([i for i, d in enumerate(data) if a[group_by] == d[group_by]] or [None])[0]
|
||||||
|
if idx is None:
|
||||||
|
data.append(a)
|
||||||
|
else:
|
||||||
|
for field in (
|
||||||
|
"gross_purchase_amount",
|
||||||
|
"opening_accumulated_depreciation",
|
||||||
|
"depreciated_amount",
|
||||||
|
"asset_value",
|
||||||
|
):
|
||||||
|
data[idx][field] = data[idx][field] + a[field]
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def get_purchase_receipt_supplier_map():
|
def get_purchase_receipt_supplier_map():
|
||||||
return frappe._dict(
|
return frappe._dict(
|
||||||
frappe.db.sql(
|
frappe.db.sql(
|
||||||
@@ -313,35 +359,35 @@ def get_columns(filters):
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"fieldname": frappe.scrub(filters.get("group_by")),
|
"fieldname": frappe.scrub(filters.get("group_by")),
|
||||||
"options": filters.get("group_by"),
|
"options": filters.get("group_by"),
|
||||||
"width": 120,
|
"width": 216,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Gross Purchase Amount"),
|
"label": _("Gross Purchase Amount"),
|
||||||
"fieldname": "gross_purchase_amount",
|
"fieldname": "gross_purchase_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": "company:currency",
|
"options": "company:currency",
|
||||||
"width": 100,
|
"width": 250,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Opening Accumulated Depreciation"),
|
"label": _("Opening Accumulated Depreciation"),
|
||||||
"fieldname": "opening_accumulated_depreciation",
|
"fieldname": "opening_accumulated_depreciation",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": "company:currency",
|
"options": "company:currency",
|
||||||
"width": 90,
|
"width": 250,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Depreciated Amount"),
|
"label": _("Depreciated Amount"),
|
||||||
"fieldname": "depreciated_amount",
|
"fieldname": "depreciated_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": "company:currency",
|
"options": "company:currency",
|
||||||
"width": 100,
|
"width": 250,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Asset Value"),
|
"label": _("Asset Value"),
|
||||||
"fieldname": "asset_value",
|
"fieldname": "asset_value",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": "company:currency",
|
"options": "company:currency",
|
||||||
"width": 100,
|
"width": 250,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1068,6 +1068,16 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
this.frm.set_df_property("conversion_rate", "read_only", erpnext.stale_rate_allowed() ? 0 : 1);
|
this.frm.set_df_property("conversion_rate", "read_only", erpnext.stale_rate_allowed() ? 0 : 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
apply_discount_on_item: function(doc, cdt, cdn, field) {
|
||||||
|
var item = frappe.get_doc(cdt, cdn);
|
||||||
|
if(!item.price_list_rate) {
|
||||||
|
item[field] = 0.0;
|
||||||
|
} else {
|
||||||
|
this.price_list_rate(doc, cdt, cdn);
|
||||||
|
}
|
||||||
|
this.set_gross_profit(item);
|
||||||
|
},
|
||||||
|
|
||||||
shipping_rule: function() {
|
shipping_rule: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
if(this.frm.doc.shipping_rule) {
|
if(this.frm.doc.shipping_rule) {
|
||||||
@@ -1720,6 +1730,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
() => {
|
() => {
|
||||||
if(args.items.length) {
|
if(args.items.length) {
|
||||||
me._set_values_for_item_list(r.message.children);
|
me._set_values_for_item_list(r.message.children);
|
||||||
|
$.each(r.message.children || [], function(i, d) {
|
||||||
|
me.apply_discount_on_item(d, d.doctype, d.name, 'discount_percentage');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() => { me.in_apply_price_list = false; }
|
() => { me.in_apply_price_list = false; }
|
||||||
|
|||||||
@@ -145,16 +145,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
this.apply_discount_on_item(doc, cdt, cdn, 'discount_amount');
|
this.apply_discount_on_item(doc, cdt, cdn, 'discount_amount');
|
||||||
},
|
},
|
||||||
|
|
||||||
apply_discount_on_item: function(doc, cdt, cdn, field) {
|
|
||||||
var item = frappe.get_doc(cdt, cdn);
|
|
||||||
if(!item.price_list_rate) {
|
|
||||||
item[field] = 0.0;
|
|
||||||
} else {
|
|
||||||
this.price_list_rate(doc, cdt, cdn);
|
|
||||||
}
|
|
||||||
this.set_gross_profit(item);
|
|
||||||
},
|
|
||||||
|
|
||||||
commission_rate: function() {
|
commission_rate: function() {
|
||||||
this.calculate_commission();
|
this.calculate_commission();
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user