mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 03:09:09 +00:00
refactor: age range in one field (#42736)
* fix: age range in one field
* fix: patch for custom reports
* refactor: stock ageing and account payable report
* fix: fixing the test cases
* fix: common patch for reports with ageing
* refactor: rename variable and minor refactor
* fix: fixing the test case
(cherry picked from commit 05de8994b0)
This commit is contained in:
@@ -54,25 +54,10 @@ frappe.query_reports["Stock Ageing"] = {
|
||||
options: "Brand",
|
||||
},
|
||||
{
|
||||
fieldname: "range1",
|
||||
label: __("Ageing Range 1"),
|
||||
fieldtype: "Int",
|
||||
default: "30",
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "range2",
|
||||
label: __("Ageing Range 2"),
|
||||
fieldtype: "Int",
|
||||
default: "60",
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "range3",
|
||||
label: __("Ageing Range 3"),
|
||||
fieldtype: "Int",
|
||||
default: "90",
|
||||
reqd: 1,
|
||||
fieldname: "range",
|
||||
label: __("Ageing Range"),
|
||||
fieldtype: "Data",
|
||||
default: "30, 60, 90",
|
||||
},
|
||||
{
|
||||
fieldname: "show_warehouse_wise_stock",
|
||||
|
||||
@@ -16,6 +16,7 @@ Filters = frappe._dict
|
||||
|
||||
def execute(filters: Filters = None) -> tuple:
|
||||
to_date = filters["to_date"]
|
||||
filters.ranges = [num.strip() for num in filters.range.split(",") if num.strip().isdigit()]
|
||||
columns = get_columns(filters)
|
||||
|
||||
item_details = FIFOSlots(filters).generate()
|
||||
@@ -48,7 +49,7 @@ def format_report_data(filters: Filters, item_details: dict, to_date: str) -> li
|
||||
average_age = get_average_age(fifo_queue, to_date)
|
||||
earliest_age = date_diff(to_date, fifo_queue[0][1])
|
||||
latest_age = date_diff(to_date, fifo_queue[-1][1])
|
||||
range1, range2, range3, above_range3 = get_range_age(filters, fifo_queue, to_date, item_dict)
|
||||
range_values = get_range_age(filters, fifo_queue, to_date, item_dict)
|
||||
|
||||
row = [details.name, details.item_name, details.description, details.item_group, details.brand]
|
||||
|
||||
@@ -59,10 +60,7 @@ def format_report_data(filters: Filters, item_details: dict, to_date: str) -> li
|
||||
[
|
||||
flt(item_dict.get("total_qty"), precision),
|
||||
average_age,
|
||||
range1,
|
||||
range2,
|
||||
range3,
|
||||
above_range3,
|
||||
*range_values,
|
||||
earliest_age,
|
||||
latest_age,
|
||||
details.stock_uom,
|
||||
@@ -89,25 +87,22 @@ def get_average_age(fifo_queue: list, to_date: str) -> float:
|
||||
return flt(age_qty / total_qty, 2) if total_qty else 0.0
|
||||
|
||||
|
||||
def get_range_age(filters: Filters, fifo_queue: list, to_date: str, item_dict: dict) -> tuple:
|
||||
def get_range_age(filters: Filters, fifo_queue: list, to_date: str, item_dict: dict) -> list:
|
||||
precision = cint(frappe.db.get_single_value("System Settings", "float_precision", cache=True))
|
||||
|
||||
range1 = range2 = range3 = above_range3 = 0.0
|
||||
range_values = [0.0] * (len(filters.ranges) + 1)
|
||||
|
||||
for item in fifo_queue:
|
||||
age = flt(date_diff(to_date, item[1]))
|
||||
qty = flt(item[0]) if not item_dict["has_serial_no"] else 1.0
|
||||
|
||||
if age <= flt(filters.range1):
|
||||
range1 = flt(range1 + qty, precision)
|
||||
elif age <= flt(filters.range2):
|
||||
range2 = flt(range2 + qty, precision)
|
||||
elif age <= flt(filters.range3):
|
||||
range3 = flt(range3 + qty, precision)
|
||||
for i, age_limit in enumerate(filters.ranges):
|
||||
if age <= flt(age_limit):
|
||||
range_values[i] = flt(range_values[i] + qty, precision)
|
||||
break
|
||||
else:
|
||||
above_range3 = flt(above_range3 + qty, precision)
|
||||
range_values[-1] = flt(range_values[-1] + qty, precision)
|
||||
|
||||
return range1, range2, range3, above_range3
|
||||
return range_values
|
||||
|
||||
|
||||
def get_columns(filters: Filters) -> list[dict]:
|
||||
@@ -193,12 +188,14 @@ def get_chart_data(data: list, filters: Filters) -> dict:
|
||||
|
||||
|
||||
def setup_ageing_columns(filters: Filters, range_columns: list):
|
||||
ranges = [
|
||||
f"0 - {filters['range1']}",
|
||||
f"{cint(filters['range1']) + 1} - {cint(filters['range2'])}",
|
||||
f"{cint(filters['range2']) + 1} - {cint(filters['range3'])}",
|
||||
_("{0} - Above").format(cint(filters["range3"]) + 1),
|
||||
]
|
||||
prev_range_value = 0
|
||||
ranges = []
|
||||
for range in filters.ranges:
|
||||
ranges.append(f"{prev_range_value} - {range}")
|
||||
prev_range_value = cint(range) + 1
|
||||
|
||||
ranges.append(f"{prev_range_value} - Above")
|
||||
|
||||
for i, label in enumerate(ranges):
|
||||
fieldname = "range" + str(i + 1)
|
||||
add_column(range_columns, label=_("Age ({0})").format(label), fieldname=fieldname)
|
||||
|
||||
@@ -9,9 +9,7 @@ from erpnext.stock.report.stock_ageing.stock_ageing import FIFOSlots, format_rep
|
||||
|
||||
class TestStockAgeing(FrappeTestCase):
|
||||
def setUp(self) -> None:
|
||||
self.filters = frappe._dict(
|
||||
company="_Test Company", to_date="2021-12-10", range1=30, range2=60, range3=90
|
||||
)
|
||||
self.filters = frappe._dict(company="_Test Company", to_date="2021-12-10", ranges=["30", "60", "90"])
|
||||
|
||||
def test_normal_inward_outward_queue(self):
|
||||
"Reference: Case 1 in stock_ageing_fifo_logic.md (same wh)"
|
||||
|
||||
@@ -62,7 +62,7 @@ REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [
|
||||
("Item Prices", {"items": "Enabled Items only"}),
|
||||
("Delayed Item Report", {"based_on": "Sales Invoice"}),
|
||||
("Delayed Item Report", {"based_on": "Delivery Note"}),
|
||||
("Stock Ageing", {"range1": 30, "range2": 60, "range3": 90, "_optional": True}),
|
||||
("Stock Ageing", {"range": "30, 60, 90", "_optional": True}),
|
||||
("Stock Ledger Invariant Check", {"warehouse": "_Test Warehouse - _TC", "item": "_Test Item"}),
|
||||
("FIFO Queue vs Qty After Transaction Comparison", {"warehouse": "_Test Warehouse - _TC"}),
|
||||
("FIFO Queue vs Qty After Transaction Comparison", {"item_group": "All Item Groups"}),
|
||||
|
||||
Reference in New Issue
Block a user