mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-24 13:57:05 +00:00
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
This commit is contained in:
@@ -89,6 +89,30 @@ frappe.query_reports["Sales Order Analysis"] = {
|
||||
label: __("Group by Sales Order"),
|
||||
fieldtype: "Check",
|
||||
default: 0,
|
||||
on_change: (report) => {
|
||||
if (report.get_filter_value("group_by_so") && report.get_filter_value("group_by_item")) {
|
||||
report.set_filter_value("group_by_item", 0);
|
||||
return;
|
||||
}
|
||||
if (!report._no_refresh) {
|
||||
report.refresh(true);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldname: "group_by_item",
|
||||
label: __("Group by Item"),
|
||||
fieldtype: "Check",
|
||||
default: 0,
|
||||
on_change: (report) => {
|
||||
if (report.get_filter_value("group_by_so") && report.get_filter_value("group_by_item")) {
|
||||
report.set_filter_value("group_by_so", 0);
|
||||
return;
|
||||
}
|
||||
if (!report._no_refresh) {
|
||||
report.refresh(true);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
|
||||
@@ -8,19 +8,24 @@ import frappe
|
||||
from frappe import _, qb
|
||||
from frappe.query_builder import CustomFunction
|
||||
from frappe.query_builder.functions import Max
|
||||
from frappe.utils import date_diff, flt, getdate
|
||||
from frappe.utils import date_diff, flt
|
||||
|
||||
import erpnext
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters:
|
||||
return [], [], None, []
|
||||
|
||||
filters = frappe._dict(filters)
|
||||
filters.company = filters.get("company") or erpnext.get_default_company()
|
||||
|
||||
validate_filters(filters)
|
||||
|
||||
columns = get_columns(filters)
|
||||
conditions = get_conditions(filters)
|
||||
data = get_data(conditions, filters)
|
||||
so_elapsed_time = get_so_elapsed_time(data)
|
||||
so_elapsed_time = {} if filters.get("group_by_item") else get_so_elapsed_time(data)
|
||||
|
||||
if not data:
|
||||
return [], [], None, []
|
||||
@@ -31,6 +36,9 @@ def execute(filters=None):
|
||||
|
||||
|
||||
def validate_filters(filters):
|
||||
if not filters.get("company"):
|
||||
frappe.throw(_("{0} is mandatory").format(_("Company")))
|
||||
|
||||
from_date, to_date = filters.get("from_date"), filters.get("to_date")
|
||||
|
||||
if not from_date and to_date:
|
||||
@@ -38,14 +46,16 @@ def validate_filters(filters):
|
||||
elif date_diff(to_date, from_date) < 0:
|
||||
frappe.throw(_("To Date cannot be before From Date."))
|
||||
|
||||
if filters.get("group_by_so") and filters.get("group_by_item"):
|
||||
frappe.throw(_("Group the report by Sales Order or by Item, not both."))
|
||||
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ""
|
||||
if filters.get("from_date") and filters.get("to_date"):
|
||||
conditions += " and so.transaction_date between %(from_date)s and %(to_date)s"
|
||||
|
||||
if filters.get("company"):
|
||||
conditions += " and so.company = %(company)s"
|
||||
conditions += " and so.company = %(company)s"
|
||||
|
||||
if filters.get("sales_order"):
|
||||
conditions += " and so.name in %(sales_order)s"
|
||||
@@ -66,7 +76,7 @@ def get_data(conditions, filters):
|
||||
so.transaction_date as date,
|
||||
soi.delivery_date as delivery_date,
|
||||
so.name as sales_order,
|
||||
so.status, so.customer, soi.item_code,
|
||||
so.status, so.customer, soi.item_code, soi.uom,
|
||||
DATEDIFF(CURRENT_DATE, soi.delivery_date) as delay_days,
|
||||
IF(so.status in ('Completed','To Bill'), 0, (SELECT delay_days)) as delay,
|
||||
soi.qty, soi.delivered_qty,
|
||||
@@ -140,71 +150,86 @@ def get_so_elapsed_time(data):
|
||||
return so_elapsed_time
|
||||
|
||||
|
||||
AGGREGATED_FIELDS = (
|
||||
"qty",
|
||||
"delivered_qty",
|
||||
"pending_qty",
|
||||
"billed_qty",
|
||||
"qty_to_bill",
|
||||
"amount",
|
||||
"delivered_qty_amount",
|
||||
"billed_amount",
|
||||
"pending_amount",
|
||||
)
|
||||
|
||||
|
||||
def prepare_data(data, so_elapsed_time, filters):
|
||||
completed, pending = 0, 0
|
||||
|
||||
if filters.get("group_by_so"):
|
||||
sales_order_map = {}
|
||||
|
||||
for row in data:
|
||||
# sum data for chart
|
||||
completed += row["billed_amount"]
|
||||
pending += row["pending_amount"]
|
||||
|
||||
# prepare data for report view
|
||||
row["qty_to_bill"] = flt(row["qty"]) - flt(row["billed_qty"])
|
||||
|
||||
row["delay"] = 0 if row["delay"] and row["delay"] < 0 else row["delay"]
|
||||
|
||||
row["time_taken_to_deliver"] = (
|
||||
so_elapsed_time.get((row.sales_order, row.item_code))
|
||||
if row["status"] in ("To Bill", "Completed")
|
||||
else 0
|
||||
)
|
||||
|
||||
if filters.get("group_by_so"):
|
||||
so_name = row["sales_order"]
|
||||
|
||||
if so_name not in sales_order_map:
|
||||
# create an entry
|
||||
row_copy = copy.deepcopy(row)
|
||||
sales_order_map[so_name] = row_copy
|
||||
else:
|
||||
# update existing entry
|
||||
so_row = sales_order_map[so_name]
|
||||
so_row["required_date"] = max(getdate(so_row["delivery_date"]), getdate(row["delivery_date"]))
|
||||
so_row["delay"] = (
|
||||
min(so_row["delay"], row["delay"])
|
||||
if row["delay"] and so_row["delay"]
|
||||
else so_row["delay"]
|
||||
)
|
||||
|
||||
# sum numeric columns
|
||||
fields = [
|
||||
"qty",
|
||||
"delivered_qty",
|
||||
"pending_qty",
|
||||
"billed_qty",
|
||||
"qty_to_bill",
|
||||
"amount",
|
||||
"delivered_qty_amount",
|
||||
"billed_amount",
|
||||
"pending_amount",
|
||||
]
|
||||
for field in fields:
|
||||
so_row[field] = flt(row[field]) + flt(so_row[field])
|
||||
|
||||
chart_data = prepare_chart_data(pending, completed)
|
||||
|
||||
if filters.get("group_by_so"):
|
||||
data = []
|
||||
for so in sales_order_map:
|
||||
data.append(sales_order_map[so])
|
||||
return data, chart_data
|
||||
data = group_by_sales_order(data)
|
||||
elif filters.get("group_by_item"):
|
||||
data = group_by_item(data)
|
||||
|
||||
return data, chart_data
|
||||
|
||||
|
||||
def group_by_sales_order(data):
|
||||
sales_order_map = {}
|
||||
|
||||
for row in data:
|
||||
group = sales_order_map.get(row["sales_order"])
|
||||
if not group:
|
||||
sales_order_map[row["sales_order"]] = copy.deepcopy(row)
|
||||
continue
|
||||
|
||||
group["delay"] = (
|
||||
min(group["delay"], row["delay"]) if row["delay"] and group["delay"] else group["delay"]
|
||||
)
|
||||
add_aggregated_fields(group, row)
|
||||
|
||||
return list(sales_order_map.values())
|
||||
|
||||
|
||||
def group_by_item(data):
|
||||
"""Group on company and UOM as well as the item.
|
||||
|
||||
Quantities are in the line UOM and amounts are in the company currency, so neither sums
|
||||
across a second UOM of the same item or a second company.
|
||||
"""
|
||||
item_map = {}
|
||||
|
||||
for row in data:
|
||||
key = (row["company"], row["item_code"], row["uom"])
|
||||
group = item_map.get(key)
|
||||
if not group:
|
||||
item_map[key] = copy.deepcopy(row)
|
||||
continue
|
||||
|
||||
add_aggregated_fields(group, row)
|
||||
|
||||
return sorted(item_map.values(), key=lambda row: (row["company"], row["item_code"], row["uom"]))
|
||||
|
||||
|
||||
def add_aggregated_fields(group, row):
|
||||
for field in AGGREGATED_FIELDS:
|
||||
group[field] = flt(group[field]) + flt(row[field])
|
||||
|
||||
|
||||
def prepare_chart_data(pending, completed):
|
||||
labels = [_("Amount to Bill"), _("Billed Amount")]
|
||||
|
||||
@@ -216,7 +241,34 @@ def prepare_chart_data(pending, completed):
|
||||
|
||||
|
||||
def get_columns(filters):
|
||||
columns = [
|
||||
if filters.get("group_by_item"):
|
||||
return get_grouped_by_item_columns()
|
||||
|
||||
columns = get_sales_order_columns()
|
||||
|
||||
if not filters.get("group_by_so"):
|
||||
columns += get_item_columns()
|
||||
|
||||
columns += get_quantity_columns() + get_amount_columns() + get_delivery_columns()
|
||||
|
||||
if not filters.get("group_by_so"):
|
||||
columns.append(get_warehouse_column())
|
||||
|
||||
columns.append(get_company_column())
|
||||
|
||||
return columns
|
||||
|
||||
|
||||
def get_grouped_by_item_columns():
|
||||
columns = [get_item_code_column(), get_uom_column()]
|
||||
columns += get_quantity_columns() + get_amount_columns()
|
||||
columns.append(get_company_column())
|
||||
|
||||
return columns
|
||||
|
||||
|
||||
def get_sales_order_columns():
|
||||
return [
|
||||
{"label": _("Date"), "fieldname": "date", "fieldtype": "Date", "width": 90},
|
||||
{
|
||||
"label": _("Sales Order"),
|
||||
@@ -235,117 +287,139 @@ def get_columns(filters):
|
||||
},
|
||||
]
|
||||
|
||||
if not filters.get("group_by_so"):
|
||||
columns.append(
|
||||
{
|
||||
"label": _("Item Code"),
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 100,
|
||||
}
|
||||
)
|
||||
columns.append(
|
||||
{"label": _("Description"), "fieldname": "description", "fieldtype": "Small Text", "width": 100}
|
||||
)
|
||||
|
||||
columns.extend(
|
||||
[
|
||||
{
|
||||
"label": _("Qty"),
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Delivered Qty"),
|
||||
"fieldname": "delivered_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Qty to Deliver"),
|
||||
"fieldname": "pending_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Billed Qty"),
|
||||
"fieldname": "billed_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 80,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Qty to Bill"),
|
||||
"fieldname": "qty_to_bill",
|
||||
"fieldtype": "Float",
|
||||
"width": 80,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Amount"),
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 110,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
{
|
||||
"label": _("Billed Amount"),
|
||||
"fieldname": "billed_amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 110,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
{
|
||||
"label": _("Pending Amount"),
|
||||
"fieldname": "pending_amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 130,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
{
|
||||
"label": _("Amount Delivered"),
|
||||
"fieldname": "delivered_qty_amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 100,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
{"label": _("Delivery Date"), "fieldname": "delivery_date", "fieldtype": "Date", "width": 120},
|
||||
{"label": _("Delay (in Days)"), "fieldname": "delay", "fieldtype": "Data", "width": 100},
|
||||
{
|
||||
"label": _("Time Taken to Deliver"),
|
||||
"fieldname": "time_taken_to_deliver",
|
||||
"fieldtype": "Duration",
|
||||
"width": 100,
|
||||
},
|
||||
]
|
||||
)
|
||||
if not filters.get("group_by_so"):
|
||||
columns.append(
|
||||
{
|
||||
"label": _("Warehouse"),
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"width": 100,
|
||||
}
|
||||
)
|
||||
columns.append(
|
||||
def get_item_columns():
|
||||
return [
|
||||
get_item_code_column(),
|
||||
{"label": _("Description"), "fieldname": "description", "fieldtype": "Small Text", "width": 100},
|
||||
]
|
||||
|
||||
|
||||
def get_item_code_column():
|
||||
return {
|
||||
"label": _("Item Code"),
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 100,
|
||||
}
|
||||
|
||||
|
||||
def get_uom_column():
|
||||
return {
|
||||
"label": _("UOM"),
|
||||
"fieldname": "uom",
|
||||
"fieldtype": "Link",
|
||||
"options": "UOM",
|
||||
"width": 100,
|
||||
}
|
||||
|
||||
|
||||
def get_quantity_columns():
|
||||
return [
|
||||
{
|
||||
"label": _("Company"),
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"width": 100,
|
||||
}
|
||||
)
|
||||
"label": _("Qty"),
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Delivered Qty"),
|
||||
"fieldname": "delivered_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Qty to Deliver"),
|
||||
"fieldname": "pending_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Billed Qty"),
|
||||
"fieldname": "billed_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 80,
|
||||
"convertible": "qty",
|
||||
},
|
||||
{
|
||||
"label": _("Qty to Bill"),
|
||||
"fieldname": "qty_to_bill",
|
||||
"fieldtype": "Float",
|
||||
"width": 80,
|
||||
"convertible": "qty",
|
||||
},
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
def get_amount_columns():
|
||||
return [
|
||||
{
|
||||
"label": _("Amount"),
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 110,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
{
|
||||
"label": _("Billed Amount"),
|
||||
"fieldname": "billed_amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 110,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
{
|
||||
"label": _("Pending Amount"),
|
||||
"fieldname": "pending_amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 130,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
{
|
||||
"label": _("Amount Delivered"),
|
||||
"fieldname": "delivered_qty_amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 100,
|
||||
"options": "Company:company:default_currency",
|
||||
"convertible": "rate",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def get_delivery_columns():
|
||||
return [
|
||||
{"label": _("Delivery Date"), "fieldname": "delivery_date", "fieldtype": "Date", "width": 120},
|
||||
{"label": _("Delay (in Days)"), "fieldname": "delay", "fieldtype": "Data", "width": 100},
|
||||
{
|
||||
"label": _("Time Taken to Deliver"),
|
||||
"fieldname": "time_taken_to_deliver",
|
||||
"fieldtype": "Duration",
|
||||
"width": 100,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def get_warehouse_column():
|
||||
return {
|
||||
"label": _("Warehouse"),
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"width": 100,
|
||||
}
|
||||
|
||||
|
||||
def get_company_column():
|
||||
return {
|
||||
"label": _("Company"),
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"width": 100,
|
||||
}
|
||||
|
||||
@@ -1,20 +1,27 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
import frappe
|
||||
from frappe.utils import add_days
|
||||
|
||||
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||
from erpnext.selling.report.sales_order_analysis.sales_order_analysis import execute
|
||||
from erpnext.selling.report.sales_order_analysis.sales_order_analysis import (
|
||||
AGGREGATED_FIELDS,
|
||||
execute,
|
||||
group_by_item,
|
||||
)
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
|
||||
class TestSalesOrderAnalysis(ERPNextTestSuite):
|
||||
def create_sales_order(self, transaction_date, do_not_save=False, do_not_submit=False):
|
||||
def create_sales_order(self, transaction_date, do_not_save=False, do_not_submit=False, qty=10, uom=None):
|
||||
item = create_item(item_code="_Test Excavator", is_stock_item=0)
|
||||
so = make_sales_order(
|
||||
transaction_date=transaction_date,
|
||||
item=item.item_code,
|
||||
qty=10,
|
||||
qty=qty,
|
||||
uom=uom,
|
||||
rate=100000,
|
||||
do_not_save=True,
|
||||
)
|
||||
@@ -28,6 +35,17 @@ class TestSalesOrderAnalysis(ERPNextTestSuite):
|
||||
so.submit()
|
||||
return item, so
|
||||
|
||||
def make_item_row(self, company, qty):
|
||||
row = frappe._dict(dict.fromkeys(AGGREGATED_FIELDS, 0))
|
||||
row.update({"company": company, "item_code": "_Test Excavator", "uom": "Nos", "qty": qty})
|
||||
return row
|
||||
|
||||
def add_uom(self, item_code, uom, conversion_factor):
|
||||
item = frappe.get_doc("Item", item_code)
|
||||
if not any(row.uom == uom for row in item.uoms):
|
||||
item.append("uoms", {"uom": uom, "conversion_factor": conversion_factor})
|
||||
item.save()
|
||||
|
||||
def create_sales_invoice(self, so, do_not_save=False, do_not_submit=False):
|
||||
sinv = make_sales_invoice(so.name)
|
||||
sinv.posting_date = so.transaction_date
|
||||
@@ -255,3 +273,104 @@ class TestSalesOrderAnalysis(ERPNextTestSuite):
|
||||
for key, val in expected_value.items():
|
||||
with self.subTest(key=key, val=val):
|
||||
self.assertEqual(data[0][key], val)
|
||||
|
||||
def test_08_group_by_item_across_sales_orders(self):
|
||||
transaction_date = "2021-06-01"
|
||||
item, so1 = self.create_sales_order(transaction_date)
|
||||
self.create_sales_order(transaction_date, qty=4)
|
||||
|
||||
dn = self.create_delivery_note(so1, do_not_save=True)
|
||||
dn.items[0].qty = 3
|
||||
dn.save().submit()
|
||||
|
||||
columns, data, message, chart = execute(
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"from_date": "2021-06-01",
|
||||
"to_date": "2021-06-30",
|
||||
"group_by_item": 1,
|
||||
}
|
||||
)
|
||||
expected_value = {
|
||||
"item_code": item.item_code,
|
||||
"uom": "Nos",
|
||||
"qty": 14,
|
||||
"delivered_qty": 3,
|
||||
"pending_qty": 11,
|
||||
}
|
||||
self.assertEqual(len(data), 1)
|
||||
for key, val in expected_value.items():
|
||||
with self.subTest(key=key, val=val):
|
||||
self.assertEqual(data[0][key], val)
|
||||
|
||||
fieldnames = [column["fieldname"] for column in columns]
|
||||
self.assertIn("uom", fieldnames)
|
||||
self.assertNotIn("sales_order", fieldnames)
|
||||
|
||||
def test_09_group_by_item_keeps_each_uom_apart(self):
|
||||
transaction_date = "2021-06-01"
|
||||
item, so = self.create_sales_order(transaction_date)
|
||||
self.add_uom(item.item_code, "Box", 10)
|
||||
self.create_sales_order(transaction_date, qty=2, uom="Box")
|
||||
|
||||
columns, data, message, chart = execute(
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"from_date": "2021-06-01",
|
||||
"to_date": "2021-06-30",
|
||||
"group_by_item": 1,
|
||||
}
|
||||
)
|
||||
self.assertEqual(len(data), 2)
|
||||
self.assertEqual([(row["uom"], row["qty"]) for row in data], [("Box", 2), ("Nos", 10)])
|
||||
|
||||
def test_10_group_by_filters_cannot_be_combined(self):
|
||||
self.assertRaises(
|
||||
frappe.ValidationError,
|
||||
execute,
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"from_date": "2021-06-01",
|
||||
"to_date": "2021-06-30",
|
||||
"group_by_so": 1,
|
||||
"group_by_item": 1,
|
||||
},
|
||||
)
|
||||
|
||||
def test_11_group_by_item_keeps_each_company_apart(self):
|
||||
rows = [
|
||||
self.make_item_row("_Test Company", 10),
|
||||
self.make_item_row("_Test Company 1", 4),
|
||||
self.make_item_row("_Test Company", 6),
|
||||
]
|
||||
|
||||
grouped = group_by_item(rows)
|
||||
|
||||
self.assertEqual(
|
||||
[(row["company"], row["qty"]) for row in grouped],
|
||||
[("_Test Company", 16), ("_Test Company 1", 4)],
|
||||
)
|
||||
|
||||
def test_12_company_falls_back_to_the_default(self):
|
||||
transaction_date = "2021-06-01"
|
||||
item, so = self.create_sales_order(transaction_date)
|
||||
filters = {"from_date": "2021-06-01", "to_date": "2021-06-30"}
|
||||
|
||||
with patch("erpnext.get_default_company", return_value="_Test Company"):
|
||||
columns, data, message, chart = execute(filters)
|
||||
|
||||
self.assertEqual(len(data), 1)
|
||||
self.assertEqual(data[0]["sales_order"], so.name)
|
||||
|
||||
with patch("erpnext.get_default_company", return_value="_Test Company 1"):
|
||||
columns, data, message, chart = execute(filters)
|
||||
|
||||
self.assertNotIn(so.name, [row["sales_order"] for row in data])
|
||||
|
||||
def test_13_company_is_mandatory_without_a_default(self):
|
||||
with patch("erpnext.get_default_company", return_value=None):
|
||||
self.assertRaises(
|
||||
frappe.ValidationError,
|
||||
execute,
|
||||
{"from_date": "2021-06-01", "to_date": "2021-06-30"},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user