feat(received items to be billed): add company and date filters (backport #46271) (#46302)

feat(received items to be billed): add company and date filters (#46271)

* feat(received items to be billed): add company and date filters

* feat(delivered to be billed): add company and date filters

* feat: add company and date conditions

* chore: remove debugger

(cherry picked from commit 6117706ab5)

Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
This commit is contained in:
mergify[bot]
2025-03-05 13:12:09 +05:30
committed by GitHub
parent 363129bcd4
commit 400f4f32ad
5 changed files with 104 additions and 59 deletions

View File

@@ -2,5 +2,27 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.query_reports["Delivered Items To Be Billed"] = { 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 frappe import _
from pypika import Order
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data 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): def execute(filters=None):
columns = get_column() columns = get_column()
args = get_args() args = get_args()
data = get_ordered_to_be_billed_data(args) data = get_ordered_to_be_billed_data(args, filters)
return columns, data return columns, data
@@ -76,13 +77,6 @@ def get_column():
"options": "Project", "options": "Project",
"width": 120, "width": 120,
}, },
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
] ]
@@ -92,5 +86,6 @@ def get_args():
"party": "customer", "party": "customer",
"date": "posting_date", "date": "posting_date",
"order": "name", "order": "name",
"order_by": "desc", "order_by": Order.desc,
"reference_field": "delivery_note",
} }

View File

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

View File

@@ -2,5 +2,27 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.query_reports["Received Items To Be Billed"] = { 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 frappe import _
from pypika import Order
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data 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): def execute(filters=None):
columns = get_column() columns = get_column()
args = get_args() args = get_args()
data = get_ordered_to_be_billed_data(args) data = get_ordered_to_be_billed_data(args, filters)
return columns, data return columns, data
@@ -76,13 +77,6 @@ def get_column():
"options": "Project", "options": "Project",
"width": 120, "width": 120,
}, },
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
] ]
@@ -92,5 +86,6 @@ def get_args():
"party": "supplier", "party": "supplier",
"date": "posting_date", "date": "posting_date",
"order": "name", "order": "name",
"order_by": "desc", "order_by": Order.desc,
"reference_field": "purchase_receipt",
} }