Merge branch 'version-15-hotfix' into mergify/bp/version-15-hotfix/pr-45987

This commit is contained in:
Mihir Kandoi
2025-03-05 13:59:59 +05:30
committed by GitHub
13 changed files with 168 additions and 74 deletions

View File

@@ -50,6 +50,7 @@ def get_group_by_asset_category_data(filters):
flt(row.accumulated_depreciation_as_on_from_date)
+ flt(row.depreciation_amount_during_the_period)
- flt(row.depreciation_eliminated_during_the_period)
- flt(row.depreciation_eliminated_via_reversal)
)
row.net_asset_value_as_on_from_date = flt(row.value_as_on_from_date) - flt(
@@ -247,6 +248,7 @@ def get_group_by_asset_data(filters):
flt(row.accumulated_depreciation_as_on_from_date)
+ flt(row.depreciation_amount_during_the_period)
- flt(row.depreciation_eliminated_during_the_period)
- flt(row.depreciation_eliminated_via_reversal)
)
row.net_asset_value_as_on_from_date = flt(row.value_as_on_from_date) - flt(
@@ -276,6 +278,7 @@ def get_assets_for_grouped_by_category(filters):
f"""
SELECT results.asset_category,
sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
sum(results.depreciation_eliminated_via_reversal) as depreciation_eliminated_via_reversal,
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
from (SELECT a.asset_category,
@@ -284,6 +287,11 @@ def get_assets_for_grouped_by_category(filters):
else
0
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when gle.posting_date <= %(to_date)s and ifnull(a.disposal_date, 0) = 0 then
gle.credit
else
0
end), 0) as depreciation_eliminated_via_reversal,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s and gle.posting_date <= a.disposal_date then
gle.debit
@@ -307,7 +315,6 @@ def get_assets_for_grouped_by_category(filters):
a.docstatus=1
and a.company=%(company)s
and a.purchase_date <= %(to_date)s
and gle.debit != 0
and gle.is_cancelled = 0
and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account)
{condition} {finance_book_filter}
@@ -319,6 +326,7 @@ def get_assets_for_grouped_by_category(filters):
else
a.opening_accumulated_depreciation
end), 0) as accumulated_depreciation_as_on_from_date,
0 as depreciation_eliminated_via_reversal,
ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
a.opening_accumulated_depreciation
else
@@ -354,6 +362,7 @@ def get_assets_for_grouped_by_asset(filters):
f"""
SELECT results.name as asset,
sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
sum(results.depreciation_eliminated_via_reversal) as depreciation_eliminated_via_reversal,
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
from (SELECT a.name as name,
@@ -362,6 +371,11 @@ def get_assets_for_grouped_by_asset(filters):
else
0
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when gle.posting_date <= %(to_date)s and ifnull(a.disposal_date, 0) = 0 then
gle.credit
else
0
end), 0) as depreciation_eliminated_via_reversal,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s and gle.posting_date <= a.disposal_date then
gle.debit
@@ -385,7 +399,6 @@ def get_assets_for_grouped_by_asset(filters):
a.docstatus=1
and a.company=%(company)s
and a.purchase_date <= %(to_date)s
and gle.debit != 0
and gle.is_cancelled = 0
and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account)
{finance_book_filter} {condition}
@@ -397,6 +410,7 @@ def get_assets_for_grouped_by_asset(filters):
else
a.opening_accumulated_depreciation
end), 0) as accumulated_depreciation_as_on_from_date,
0 as depreciation_as_on_from_date_credit,
ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
a.opening_accumulated_depreciation
else
@@ -503,6 +517,12 @@ def get_columns(filters):
"fieldtype": "Currency",
"width": 270,
},
{
"label": _("Depreciation eliminated via reversal"),
"fieldname": "depreciation_eliminated_via_reversal",
"fieldtype": "Currency",
"width": 270,
},
{
"label": _("Net Asset value as on") + " " + formatdate(filters.day_before_from_date),
"fieldname": "net_asset_value_as_on_from_date",

View File

@@ -307,6 +307,7 @@ class Deferred_Revenue_and_Expense_Report:
.where(
(inv.docstatus == 1)
& (deferred_flag_field == 1)
& (inv.company == self.filters.company)
& (
(
(self.period_list[0].from_date >= inv_item.service_start_date)

View File

@@ -2,5 +2,27 @@
// For license information, please see license.txt
frappe.query_reports["Delivered Items To Be Billed"] = {
filters: [],
filters: [
{
label: __("Company"),
fieldname: "company",
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_default("Company"),
},
{
label: __("As on Date"),
fieldname: "posting_date",
fieldtype: "Date",
reqd: 1,
default: frappe.datetime.get_today(),
},
{
label: __("Delivery Note"),
fieldname: "delivery_note",
fieldtype: "Link",
options: "Delivery Note",
},
],
};

View File

@@ -3,6 +3,7 @@
from frappe import _
from pypika import Order
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
@@ -10,7 +11,7 @@ from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_d
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
data = get_ordered_to_be_billed_data(args, filters)
return columns, data
@@ -76,13 +77,6 @@ def get_column():
"options": "Project",
"width": 120,
},
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
]
@@ -92,5 +86,6 @@ def get_args():
"party": "customer",
"date": "posting_date",
"order": "name",
"order_by": "desc",
"order_by": Order.desc,
"reference_field": "delivery_note",
}

View File

@@ -4,11 +4,12 @@
import frappe
from frappe.model.meta import get_field_precision
from frappe.query_builder.functions import IfNull, Round
from erpnext import get_default_currency
def get_ordered_to_be_billed_data(args):
def get_ordered_to_be_billed_data(args, filters=None):
doctype, party = args.get("doctype"), args.get("party")
child_tab = doctype + " Item"
precision = (
@@ -18,47 +19,57 @@ def get_ordered_to_be_billed_data(args):
or 2
)
project_field = get_project_field(doctype, party)
doctype = frappe.qb.DocType(doctype)
child_doctype = frappe.qb.DocType(child_tab)
return frappe.db.sql(
"""
Select
`{parent_tab}`.name, `{parent_tab}`.{date_field},
`{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
`{child_tab}`.item_code,
`{child_tab}`.base_amount,
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0)),
(`{child_tab}`.base_amount -
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)) -
(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0))),
`{child_tab}`.item_name, `{child_tab}`.description,
{project_field}, `{parent_tab}`.company
from
`{parent_tab}`, `{child_tab}`
where
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1
and `{parent_tab}`.status not in ('Closed', 'Completed')
and `{child_tab}`.amount > 0
and (`{child_tab}`.base_amount -
round(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) -
(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0))) > 0
order by
`{parent_tab}`.{order} {order_by}
""".format(
parent_tab="tab" + doctype,
child_tab="tab" + child_tab,
precision=precision,
party=party,
date_field=args.get("date"),
project_field=project_field,
order=args.get("order"),
order_by=args.get("order_by"),
docname = filters.get(args.get("reference_field"), None)
project_field = get_project_field(doctype, child_doctype, party)
query = (
frappe.qb.from_(doctype)
.inner_join(child_doctype)
.on(doctype.name == child_doctype.parent)
.select(
doctype.name,
doctype[args.get("date")].as_("date"),
doctype[party],
doctype[party + "_name"],
child_doctype.item_code,
child_doctype.base_amount.as_("amount"),
(child_doctype.billed_amt * IfNull(doctype.conversion_rate, 1)).as_("billed_amount"),
(child_doctype.base_rate * IfNull(child_doctype.returned_qty, 0)).as_("returned_amount"),
(
child_doctype.base_amount
- (child_doctype.billed_amt * IfNull(doctype.conversion_rate, 1))
- (child_doctype.base_rate * IfNull(child_doctype.returned_qty, 0))
).as_("pending_amount"),
child_doctype.item_name,
child_doctype.description,
project_field,
)
.where(
(doctype.docstatus == 1)
& (doctype.status.notin(["Closed", "Completed"]))
& (doctype.company == filters.get("company"))
& (doctype.posting_date <= filters.get("posting_date"))
& (child_doctype.amount > 0)
& (
child_doctype.base_amount
- Round(child_doctype.billed_amt * IfNull(doctype.conversion_rate, 1), precision)
- (child_doctype.base_rate * IfNull(child_doctype.returned_qty, 0))
)
> 0
)
.orderby(doctype[args.get("order")], order=args.get("order_by"))
)
if docname:
query = query.where(doctype.name == docname)
def get_project_field(doctype, party):
return query.run(as_dict=True)
def get_project_field(doctype, child_doctype, party):
if party == "supplier":
doctype = doctype + " Item"
return "`tab%s`.project" % (doctype)
return child_doctype.project
return doctype.project

View File

@@ -2,5 +2,27 @@
// For license information, please see license.txt
frappe.query_reports["Received Items To Be Billed"] = {
filters: [],
filters: [
{
label: __("Company"),
fieldname: "company",
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_default("Company"),
},
{
label: __("As on Date"),
fieldname: "posting_date",
fieldtype: "Date",
reqd: 1,
default: frappe.datetime.get_today(),
},
{
label: __("Purchase Receipt"),
fieldname: "purchase_receipt",
fieldtype: "Link",
options: "Purchase Receipt",
},
],
};

View File

@@ -3,6 +3,7 @@
from frappe import _
from pypika import Order
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
@@ -10,7 +11,7 @@ from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_d
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
data = get_ordered_to_be_billed_data(args, filters)
return columns, data
@@ -76,13 +77,6 @@ def get_column():
"options": "Project",
"width": 120,
},
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
]
@@ -92,5 +86,6 @@ def get_args():
"party": "supplier",
"date": "posting_date",
"order": "name",
"order_by": "desc",
"order_by": Order.desc,
"reference_field": "purchase_receipt",
}

View File

@@ -93,7 +93,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Accounts Payable",
"link_count": 0,
"link_to": "Accounts Payable",
@@ -103,7 +103,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Accounts Payable Summary",
"link_count": 0,
"link_to": "Accounts Payable Summary",
@@ -113,7 +113,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Purchase Register",
"link_count": 0,
"link_to": "Purchase Register",
@@ -123,7 +123,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Item-wise Purchase Register",
"link_count": 0,
"link_to": "Item-wise Purchase Register",
@@ -133,7 +133,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Purchase Order Analysis",
"link_count": 0,
"link_to": "Purchase Order Analysis",
@@ -143,7 +143,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Received Items To Be Billed",
"link_count": 0,
"link_to": "Received Items To Be Billed",
@@ -153,7 +153,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Supplier Ledger Summary",
"link_count": 0,
"link_to": "Supplier Ledger Summary",

View File

@@ -1234,7 +1234,7 @@ class StockController(AccountsController):
child_tab.item_code,
child_tab.qty,
)
.where(parent_tab.docstatus < 2)
.where(parent_tab.docstatus == 1)
)
if self.doctype == "Purchase Invoice":

View File

@@ -396,3 +396,4 @@ erpnext.patches.v15_0.set_difference_amount_in_asset_value_adjustment
erpnext.patches.v14_0.update_posting_datetime
erpnext.stock.doctype.stock_ledger_entry.patches.ensure_sle_indexes
erpnext.patches.v15_0.rename_sla_fields
erpnext.patches.v15_0.update_query_report

View File

@@ -0,0 +1,25 @@
import frappe
def execute():
reports = [
"Accounts Payable",
"Accounts Payable Summary",
"Purchase Register",
"Item-wise Purchase Register",
"Purchase Order Analysis",
"Received Items To Be Billed",
"Supplier Ledger Summary",
]
frappe.db.set_value(
"Workspace Link",
{
"parent": "Payables",
"link_type": "Report",
"type": "Link",
"link_to": ["in", reports],
"is_query_report": 0,
},
"is_query_report",
1,
)

View File

@@ -1044,7 +1044,7 @@ def make_delivery_note(source_name, target_doc=None, kwargs=None):
ignore_permissions=True,
)
dn_item.qty = flt(sre.reserved_qty) * flt(dn_item.get("conversion_factor", 1))
dn_item.qty = flt(sre.reserved_qty) / flt(dn_item.get("conversion_factor", 1))
if sre.reservation_based_on == "Serial and Batch" and (sre.has_serial_no or sre.has_batch_no):
dn_item.serial_and_batch_bundle = get_ssb_bundle_for_voucher(sre)

View File

@@ -221,7 +221,7 @@ def update_stock(ctx, out, doc=None):
else:
qty -= batch_qty
out.update({"batch_no": batch_no, "actual_batch_qty": qty})
out.update({"batch_no": batch_no, "actual_batch_qty": batch_qty})
if rate:
out.update({"rate": rate, "price_list_rate": rate})
@@ -1051,9 +1051,11 @@ def get_batch_based_item_price(params, item_code) -> float:
if not item_price:
item_price = get_item_price(params, item_code, ignore_party=True, force_batch_no=True)
is_free_item = params.get("items", [{}])[0].get("is_free_item")
if item_price and item_price[0][2] == params.get("uom") and not is_free_item:
if (
item_price
and item_price[0][2] == params.get("uom")
and not params.get("items", [{}])[0].get("is_free_item", 0)
):
return item_price[0][1]
return 0.0