mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-04 04:39:11 +00:00
Merge branch 'develop' into develop-customer-item-price-report
This commit is contained in:
@@ -11,8 +11,7 @@ def execute(filters=None):
|
||||
columns = get_columns()
|
||||
iwq_map = get_item_warehouse_quantity_map()
|
||||
item_map = get_item_details()
|
||||
|
||||
data = []
|
||||
data = []
|
||||
for sbom, warehouse in iwq_map.items():
|
||||
total = 0
|
||||
total_qty = 0
|
||||
@@ -20,8 +19,8 @@ def execute(filters=None):
|
||||
for wh, item_qty in warehouse.items():
|
||||
total += 1
|
||||
row = [sbom, item_map.get(sbom).item_name, item_map.get(sbom).description,
|
||||
item_map.get(sbom).stock_uom, wh]
|
||||
available_qty = min(item_qty.values())
|
||||
item_map.get(sbom).stock_uom, wh]
|
||||
available_qty = item_qty
|
||||
total_qty += flt(available_qty)
|
||||
row += [available_qty]
|
||||
|
||||
@@ -30,51 +29,50 @@ def execute(filters=None):
|
||||
if (total == len(warehouse)):
|
||||
row = ["", "", "Total", "", "", total_qty]
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns():
|
||||
columns = ["Item Code:Link/Item:100", "Item Name::100", "Description::120", \
|
||||
"UOM:Link/UOM:80", "Warehouse:Link/Warehouse:100", "Quantity::100"]
|
||||
"UOM:Link/UOM:80", "Warehouse:Link/Warehouse:100", "Quantity::100"]
|
||||
|
||||
return columns
|
||||
|
||||
def get_product_bundle_items():
|
||||
sbom_item_map = {}
|
||||
for sbom in frappe.db.sql("""select pb.new_item_code as parent, pbi.item_code, pbi.qty
|
||||
from `tabProduct Bundle Item` as pbi, `tabProduct Bundle` as pb
|
||||
where pb.docstatus < 2 and pb.name = pbi.parent""", as_dict=1):
|
||||
sbom_item_map.setdefault(sbom.parent, {}).setdefault(sbom.item_code, sbom.qty)
|
||||
|
||||
return sbom_item_map
|
||||
|
||||
def get_item_details():
|
||||
item_map = {}
|
||||
for item in frappe.db.sql("""select name, item_name, description, stock_uom
|
||||
from `tabItem`""", as_dict=1):
|
||||
item_map.setdefault(item.name, item)
|
||||
|
||||
for item in frappe.db.sql("""SELECT name, item_name, description, stock_uom
|
||||
from `tabItem`""", as_dict=1):
|
||||
item_map.setdefault(item.name, item)
|
||||
return item_map
|
||||
|
||||
def get_item_warehouse_quantity():
|
||||
iwq_map = {}
|
||||
bin = frappe.db.sql("""select item_code, warehouse, actual_qty from `tabBin`
|
||||
where actual_qty > 0""")
|
||||
for item, wh, qty in bin:
|
||||
iwq_map.setdefault(item, {}).setdefault(wh, qty)
|
||||
|
||||
return iwq_map
|
||||
|
||||
def get_item_warehouse_quantity_map():
|
||||
query = """SELECT parent, warehouse, MIN(qty) AS qty
|
||||
FROM (SELECT b.parent, bi.item_code, bi.warehouse,
|
||||
sum(bi.projected_qty) / b.qty AS qty
|
||||
FROM tabBin AS bi, (SELECT pb.new_item_code as parent, b.item_code, b.qty, w.name
|
||||
FROM `tabProduct Bundle Item` b, `tabWarehouse` w,
|
||||
`tabProduct Bundle` pb
|
||||
where b.parent = pb.name) AS b
|
||||
WHERE bi.item_code = b.item_code
|
||||
AND bi.warehouse = b.name
|
||||
GROUP BY b.parent, b.item_code, bi.warehouse
|
||||
UNION ALL
|
||||
SELECT b.parent, b.item_code, b.name, 0 AS qty
|
||||
FROM (SELECT pb.new_item_code as parent, b.item_code, b.qty, w.name
|
||||
FROM `tabProduct Bundle Item` b, `tabWarehouse` w,
|
||||
`tabProduct Bundle` pb
|
||||
where b.parent = pb.name) AS b
|
||||
WHERE NOT EXISTS(SELECT *
|
||||
FROM `tabBin` AS bi
|
||||
WHERE bi.item_code = b.item_code
|
||||
AND bi.warehouse = b.name)) AS r
|
||||
GROUP BY parent, warehouse
|
||||
HAVING MIN(qty) != 0"""
|
||||
result = frappe.db.sql(query, as_dict=1)
|
||||
last_sbom = ""
|
||||
sbom_map = {}
|
||||
iwq_map = get_item_warehouse_quantity()
|
||||
sbom_item_map = get_product_bundle_items()
|
||||
|
||||
for sbom, sbom_items in sbom_item_map.items():
|
||||
for item, child_qty in sbom_items.items():
|
||||
for wh, qty in iwq_map.get(item, {}).items():
|
||||
avail_qty = flt(qty) / flt(child_qty)
|
||||
sbom_map.setdefault(sbom, {}).setdefault(wh, {}) \
|
||||
.setdefault(item, avail_qty)
|
||||
|
||||
for line in result:
|
||||
if line.get("parent") != last_sbom:
|
||||
last_sbom = line.get("parent")
|
||||
actual_dict = sbom_map.setdefault(last_sbom, {})
|
||||
actual_dict.setdefault(line.get("warehouse"), line.get("qty"))
|
||||
return sbom_map
|
||||
@@ -16,20 +16,6 @@ frappe.query_reports["Customer Credit Balance"] = {
|
||||
"label": __("Customer"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Customer"
|
||||
},
|
||||
{
|
||||
"fieldname":"cost_center",
|
||||
"label": __("Cost Center"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Cost Center",
|
||||
get_query: () => {
|
||||
var company = frappe.query_report.get_filter_value('company');
|
||||
return {
|
||||
filters: {
|
||||
'company': company
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ def execute(filters=None):
|
||||
row = []
|
||||
|
||||
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"),
|
||||
ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order,
|
||||
cost_center=filters.get("cost_center"))
|
||||
ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order)
|
||||
|
||||
credit_limit = get_credit_limit(d.name, filters.get("company"))
|
||||
|
||||
@@ -66,3 +65,4 @@ def get_details(filters):
|
||||
return frappe.db.sql("""select name, customer_name,
|
||||
bypass_credit_limit_check_at_sales_order, is_frozen, disabled from `tabCustomer` %s
|
||||
""" % conditions, filters, as_dict=1)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ frappe.query_reports["Sales Analytics"] = {
|
||||
fieldname: "tree_type",
|
||||
label: __("Tree Type"),
|
||||
fieldtype: "Select",
|
||||
options: ["Customer Group","Customer","Item Group","Item","Territory"],
|
||||
options: ["Customer Group","Customer","Item Group","Item","Territory","Order Type"],
|
||||
default: "Customer",
|
||||
reqd: 1
|
||||
},
|
||||
|
||||
@@ -23,15 +23,15 @@ class Analytics(object):
|
||||
self.get_columns()
|
||||
self.get_data()
|
||||
self.get_chart_data()
|
||||
return self.columns, self.data , None, self.chart
|
||||
return self.columns, self.data, None, self.chart
|
||||
|
||||
def get_columns(self):
|
||||
self.columns =[{
|
||||
self.columns = [{
|
||||
"label": _(self.filters.tree_type + " ID"),
|
||||
"options": self.filters.tree_type,
|
||||
"options": self.filters.tree_type if self.filters.tree_type != "Order Type" else "",
|
||||
"fieldname": "entity",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
"fieldtype": "Link" if self.filters.tree_type != "Order Type" else "Data",
|
||||
"width": 140 if self.filters.tree_type != "Order Type" else 200
|
||||
}]
|
||||
if self.filters.tree_type in ["Customer", "Supplier", "Item"]:
|
||||
self.columns.append({
|
||||
@@ -73,6 +73,28 @@ class Analytics(object):
|
||||
self.get_sales_transactions_based_on_item_group()
|
||||
self.get_rows_by_group()
|
||||
|
||||
elif self.filters.tree_type == "Order Type":
|
||||
if self.filters.doc_type != "Sales Order":
|
||||
self.data = []
|
||||
return
|
||||
self.get_sales_transactions_based_on_order_type()
|
||||
self.get_rows_by_group()
|
||||
|
||||
def get_sales_transactions_based_on_order_type(self):
|
||||
if self.filters["value_quantity"] == 'Value':
|
||||
value_field = "base_net_total"
|
||||
else:
|
||||
value_field = "total_qty"
|
||||
|
||||
self.entries = frappe.db.sql(""" select s.order_type as entity, s.{value_field} as value_field, s.{date_field}
|
||||
from `tab{doctype}` s where s.docstatus = 1 and s.company = %s and s.{date_field} between %s and %s
|
||||
and ifnull(s.order_type, '') != '' order by s.order_type
|
||||
"""
|
||||
.format(date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type),
|
||||
(self.filters.company, self.filters.from_date, self.filters.to_date), as_dict=1)
|
||||
|
||||
self.get_teams()
|
||||
|
||||
def get_sales_transactions_based_on_customers_or_suppliers(self):
|
||||
if self.filters["value_quantity"] == 'Value':
|
||||
value_field = "base_net_total as value_field"
|
||||
@@ -88,7 +110,7 @@ class Analytics(object):
|
||||
|
||||
self.entries = frappe.get_all(self.filters.doc_type,
|
||||
fields=[entity, entity_name, value_field, self.date_field],
|
||||
filters = {
|
||||
filters={
|
||||
"docstatus": 1,
|
||||
"company": self.filters.company,
|
||||
self.date_field: ('between', [self.filters.from_date, self.filters.to_date])
|
||||
@@ -112,7 +134,7 @@ class Analytics(object):
|
||||
where s.name = i.parent and i.docstatus = 1 and s.company = %s
|
||||
and s.{date_field} between %s and %s
|
||||
"""
|
||||
.format(date_field=self.date_field, value_field = value_field, doctype=self.filters.doc_type),
|
||||
.format(date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type),
|
||||
(self.filters.company, self.filters.from_date, self.filters.to_date), as_dict=1)
|
||||
|
||||
self.entity_names = {}
|
||||
@@ -135,7 +157,7 @@ class Analytics(object):
|
||||
|
||||
self.entries = frappe.get_all(self.filters.doc_type,
|
||||
fields=[entity_field, value_field, self.date_field],
|
||||
filters = {
|
||||
filters={
|
||||
"docstatus": 1,
|
||||
"company": self.filters.company,
|
||||
self.date_field: ('between', [self.filters.from_date, self.filters.to_date])
|
||||
@@ -154,13 +176,13 @@ class Analytics(object):
|
||||
from `tab{doctype} Item` i , `tab{doctype}` s
|
||||
where s.name = i.parent and i.docstatus = 1 and s.company = %s
|
||||
and s.{date_field} between %s and %s
|
||||
""".format(date_field=self.date_field, value_field = value_field, doctype=self.filters.doc_type),
|
||||
""".format(date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type),
|
||||
(self.filters.company, self.filters.from_date, self.filters.to_date), as_dict=1)
|
||||
|
||||
self.get_groups()
|
||||
|
||||
def get_rows(self):
|
||||
self.data=[]
|
||||
self.data = []
|
||||
self.get_periodic_data()
|
||||
|
||||
for entity, period_data in iteritems(self.entity_periodic_data):
|
||||
@@ -192,7 +214,7 @@ class Analytics(object):
|
||||
period = self.get_period(end_date)
|
||||
amount = flt(self.entity_periodic_data.get(d.name, {}).get(period, 0.0))
|
||||
row[scrub(period)] = amount
|
||||
if d.parent:
|
||||
if d.parent and (self.filters.tree_type != "Order Type" or d.parent == "Order Types"):
|
||||
self.entity_periodic_data.setdefault(d.parent, frappe._dict()).setdefault(period, 0.0)
|
||||
self.entity_periodic_data[d.parent][period] += amount
|
||||
total += amount
|
||||
@@ -216,7 +238,7 @@ class Analytics(object):
|
||||
elif self.filters.range == 'Monthly':
|
||||
period = str(self.months[posting_date.month - 1]) + " " + str(posting_date.year)
|
||||
elif self.filters.range == 'Quarterly':
|
||||
period = "Quarter " + str(((posting_date.month-1)//3)+1) +" " + str(posting_date.year)
|
||||
period = "Quarter " + str(((posting_date.month - 1) // 3) + 1) + " " + str(posting_date.year)
|
||||
else:
|
||||
year = get_fiscal_year(posting_date, company=self.filters.company)
|
||||
period = str(year[0])
|
||||
@@ -234,7 +256,7 @@ class Analytics(object):
|
||||
}.get(self.filters.range, 1)
|
||||
|
||||
if self.filters.range in ['Monthly', 'Quarterly']:
|
||||
from_date = from_date.replace(day = 1)
|
||||
from_date = from_date.replace(day=1)
|
||||
elif self.filters.range == "Yearly":
|
||||
from_date = get_fiscal_year(from_date)[1]
|
||||
else:
|
||||
@@ -270,7 +292,22 @@ class Analytics(object):
|
||||
|
||||
self.group_entries = frappe.db.sql("""select name, lft, rgt , {parent} as parent
|
||||
from `tab{tree}` order by lft"""
|
||||
.format(tree=self.filters.tree_type, parent=parent), as_dict=1)
|
||||
.format(tree=self.filters.tree_type, parent=parent), as_dict=1)
|
||||
|
||||
for d in self.group_entries:
|
||||
if d.parent:
|
||||
self.depth_map.setdefault(d.name, self.depth_map.get(d.parent) + 1)
|
||||
else:
|
||||
self.depth_map.setdefault(d.name, 0)
|
||||
|
||||
def get_teams(self):
|
||||
self.depth_map = frappe._dict()
|
||||
|
||||
self.group_entries = frappe.db.sql(""" select * from (select "Order Types" as name, 0 as lft,
|
||||
2 as rgt, '' as parent union select distinct order_type as name, 1 as lft, 1 as rgt, "Order Types" as parent
|
||||
from `tab{doctype}` where ifnull(order_type, '') != '') as b order by lft, name
|
||||
"""
|
||||
.format(doctype=self.filters.doc_type), as_dict=1)
|
||||
|
||||
for d in self.group_entries:
|
||||
if d.parent:
|
||||
@@ -285,13 +322,13 @@ class Analytics(object):
|
||||
length = len(self.columns)
|
||||
|
||||
if self.filters.tree_type in ["Customer", "Supplier", "Item"]:
|
||||
labels = [d.get("label") for d in self.columns[2:length-1]]
|
||||
labels = [d.get("label") for d in self.columns[2:length - 1]]
|
||||
else:
|
||||
labels = [d.get("label") for d in self.columns[1:length-1]]
|
||||
labels = [d.get("label") for d in self.columns[1:length - 1]]
|
||||
self.chart = {
|
||||
"data": {
|
||||
'labels': labels,
|
||||
'datasets':[]
|
||||
'datasets': []
|
||||
},
|
||||
"type": "line"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user