mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-06 21:59:13 +00:00
fix: Add group by functionality to purchase register
This commit is contained in:
@@ -34,6 +34,20 @@ frappe.query_reports["Item-wise Purchase Register"] = {
|
|||||||
"label": __("Mode of Payment"),
|
"label": __("Mode of Payment"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Mode of Payment"
|
"options": "Mode of Payment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": __("Group By"),
|
||||||
|
"fieldname": "group_by",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": ["Supplier", "Item Group", "Item", "Invoice"]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (data && data.bold) {
|
||||||
|
value = value.bold();
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ from __future__ import unicode_literals
|
|||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import get_tax_accounts
|
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts,
|
||||||
|
get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, update_total_row,
|
||||||
|
get_group_by_conditions)
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
return _execute(filters)
|
return _execute(filters)
|
||||||
@@ -13,7 +15,7 @@ def execute(filters=None):
|
|||||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||||
if not filters: filters = {}
|
if not filters: filters = {}
|
||||||
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
|
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
|
||||||
columns = get_columns(additional_table_columns)
|
columns = get_columns(additional_table_columns, filters)
|
||||||
|
|
||||||
company_currency = erpnext.get_company_currency(filters.company)
|
company_currency = erpnext.get_company_currency(filters.company)
|
||||||
|
|
||||||
@@ -23,16 +25,15 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
|
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
|
||||||
doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges")
|
doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges")
|
||||||
|
|
||||||
columns.append({
|
|
||||||
"fieldname": "currency",
|
|
||||||
"label": _("Currency"),
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"width": 80
|
|
||||||
})
|
|
||||||
|
|
||||||
po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
|
po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
|
total_row_map = {}
|
||||||
|
prev_group_by_value = ''
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
grand_total = get_grand_total(filters, 'Purchase Invoice')
|
||||||
|
|
||||||
for d in item_list:
|
for d in item_list:
|
||||||
if not d.stock_qty:
|
if not d.stock_qty:
|
||||||
continue
|
continue
|
||||||
@@ -44,51 +45,240 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
|
purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
|
||||||
|
|
||||||
expense_account = d.expense_account or aii_account_map.get(d.company)
|
expense_account = d.expense_account or aii_account_map.get(d.company)
|
||||||
row = [d.item_code, d.item_name, d.item_group, d.description, d.parent, d.posting_date, d.supplier,
|
|
||||||
d.supplier_name]
|
row = {
|
||||||
|
'item_code': d.item_code,
|
||||||
|
'item_name': d.item_name,
|
||||||
|
'item_group': d.item_group,
|
||||||
|
'description': d.description,
|
||||||
|
'invoice': d.parent,
|
||||||
|
'posting_date': d.posting_date,
|
||||||
|
'customer': d.supplier,
|
||||||
|
'customer_name': d.supplier_name
|
||||||
|
}
|
||||||
|
|
||||||
if additional_query_columns:
|
if additional_query_columns:
|
||||||
for col in additional_query_columns:
|
for col in additional_query_columns:
|
||||||
row.append(d.get(col))
|
row.update({
|
||||||
|
col: d.get(col)
|
||||||
|
})
|
||||||
|
|
||||||
row += [
|
row.update({
|
||||||
d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
|
'credit_to': d.credit_to,
|
||||||
purchase_receipt, expense_account, d.stock_qty, d.stock_uom, d.base_net_amount / d.stock_qty, d.base_net_amount
|
'mode_of_payment': d.mode_of_payment,
|
||||||
]
|
'project': d.project,
|
||||||
|
'company': d.company,
|
||||||
|
'purchase_order': d.purchase_order,
|
||||||
|
'purchase_receipt': d.purchase_receipt,
|
||||||
|
'expense_account': expense_account,
|
||||||
|
'stock_qty': d.stock_qty,
|
||||||
|
'stock_uom': d.stock_uom,
|
||||||
|
'rate': d.base_net_amount / d.stock_qty,
|
||||||
|
'amount': d.base_net_amount
|
||||||
|
})
|
||||||
|
|
||||||
total_tax = 0
|
total_tax = 0
|
||||||
for tax in tax_columns:
|
for tax in tax_columns:
|
||||||
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
|
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
|
||||||
row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)]
|
row.update({
|
||||||
|
frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
|
||||||
|
frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
|
||||||
|
})
|
||||||
total_tax += flt(item_tax.get("tax_amount"))
|
total_tax += flt(item_tax.get("tax_amount"))
|
||||||
|
|
||||||
row += [total_tax, d.base_net_amount + total_tax, company_currency]
|
row.update({
|
||||||
|
'total_tax': total_tax,
|
||||||
|
'total': d.base_net_amount + total_tax,
|
||||||
|
'currency': company_currency
|
||||||
|
})
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
row.update({'percent_gt': flt(row['total']/grand_total) * 100})
|
||||||
|
group_by_field, subtotal_display_field = get_group_by_and_display_fields(filters)
|
||||||
|
data, prev_group_by_value = add_total_row(data, filters, prev_group_by_value, d, total_row_map,
|
||||||
|
group_by_field, subtotal_display_field, grand_total)
|
||||||
|
update_total_row(row, total_row_map, d.get(group_by_field, ''), tax_columns)
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
|
||||||
|
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
|
||||||
|
data.append(total_row)
|
||||||
|
data.append({})
|
||||||
|
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
|
|
||||||
def get_columns(additional_table_columns):
|
def get_columns(additional_table_columns, filters):
|
||||||
columns = [
|
|
||||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
columns = []
|
||||||
_("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Purchase Invoice:120",
|
|
||||||
_("Posting Date") + ":Date:80", _("Supplier") + ":Link/Supplier:120",
|
if filters.get('group_by') != ('Item'):
|
||||||
"Supplier Name::120"
|
columns.extend(
|
||||||
]
|
[
|
||||||
|
{
|
||||||
|
'label': _('Item Code'),
|
||||||
|
'fieldname': 'item_code',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Item',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Item Name'),
|
||||||
|
'fieldname': 'item_name',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if filters.get('group_by') not in ('Item', 'Item Group'):
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Item Group'),
|
||||||
|
'fieldname': 'item_group',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Item Group',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Description'),
|
||||||
|
'fieldname': 'description',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Invoice'),
|
||||||
|
'fieldname': 'invoice',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Purchase Invoice',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Posting Date'),
|
||||||
|
'fieldname': 'posting_date',
|
||||||
|
'fieldtype': 'Date',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
if filters.get('group_by') != 'Supplier':
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Supplier'),
|
||||||
|
'fieldname': 'supplier',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Supplier',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Supplier Name'),
|
||||||
|
'fieldname': 'supplier_name',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
if additional_table_columns:
|
if additional_table_columns:
|
||||||
columns += additional_table_columns
|
columns += additional_table_columns
|
||||||
|
|
||||||
columns += [
|
columns += [
|
||||||
"Payable Account:Link/Account:120",
|
{
|
||||||
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
|
'label': _('Payable Account'),
|
||||||
_("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100",
|
'fieldname': 'credit_to',
|
||||||
_("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140",
|
'fieldtype': 'Link',
|
||||||
_("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
|
'options': 'Account',
|
||||||
_("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120"
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Mode Of Payment'),
|
||||||
|
'fieldname': 'mode_of_payment',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Project'),
|
||||||
|
'fieldname': 'project',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Project',
|
||||||
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Company'),
|
||||||
|
'fieldname': 'company',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Company',
|
||||||
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Purchase Order'),
|
||||||
|
'fieldname': 'purchase_order',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Purchase Order',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _("Purchase Receipt"),
|
||||||
|
'fieldname': 'Purchase Receipt',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Purchase Receipt',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Expense Account'),
|
||||||
|
'fieldname': 'expense_account',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Account',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Stock Qty'),
|
||||||
|
'fieldname': 'stock_qty',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Stock UOM'),
|
||||||
|
'fieldname': 'stock_uom',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'UOM',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Rate'),
|
||||||
|
'fieldname': 'rate',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Amount'),
|
||||||
|
'fieldname': 'amount',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'fieldname': 'currency',
|
||||||
|
'label': _('Currency'),
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'width': 80,
|
||||||
|
'hidden': 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
columns.append({
|
||||||
|
'label': _('% Of Grand Total'),
|
||||||
|
'fieldname': 'percent_gt',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'width': 80
|
||||||
|
})
|
||||||
|
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
def get_conditions(filters):
|
def get_conditions(filters):
|
||||||
@@ -103,6 +293,11 @@ def get_conditions(filters):
|
|||||||
if filters.get(opts[0]):
|
if filters.get(opts[0]):
|
||||||
conditions += opts[1]
|
conditions += opts[1]
|
||||||
|
|
||||||
|
if not filters.get("group_by"):
|
||||||
|
conditions += "ORDER BY `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc"
|
||||||
|
else:
|
||||||
|
conditions += get_group_by_conditions(filters, 'Purchase Invoice')
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
def get_items(filters, additional_query_columns):
|
def get_items(filters, additional_query_columns):
|
||||||
@@ -129,7 +324,6 @@ def get_items(filters, additional_query_columns):
|
|||||||
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
|
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
|
||||||
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
||||||
`tabPurchase Invoice`.docstatus = 1 %s %s
|
`tabPurchase Invoice`.docstatus = 1 %s %s
|
||||||
order by `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc
|
|
||||||
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
|
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
|
||||||
|
|
||||||
def get_aii_accounts():
|
def get_aii_accounts():
|
||||||
|
|||||||
Reference in New Issue
Block a user