Merge pull request #25696 from rohitwaghchaure/incorrect-serial-no-qty-valuation-report

feat: Incorrect valuation rate report for serialized items
This commit is contained in:
rohitwaghchaure 2021-06-23 16:52:51 +05:30 committed by GitHub
commit b4863bfa50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 426 additions and 1 deletions

View File

@ -0,0 +1,27 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports["Incorrect Balance Qty After Transaction"] = {
"filters": [
{
label: __("Company"),
fieldtype: "Link",
fieldname: "company",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
reqd: 1
},
{
label: __('Item Code'),
fieldtype: 'Link',
fieldname: 'item_code',
options: 'Item'
},
{
label: __('Warehouse'),
fieldtype: 'Link',
fieldname: 'warehouse'
}
]
};

View File

@ -0,0 +1,32 @@
{
"add_total_row": 0,
"columns": [],
"creation": "2021-05-12 16:47:58.717853",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"modified": "2021-05-12 16:48:28.347575",
"modified_by": "Administrator",
"module": "Stock",
"name": "Incorrect Balance Qty After Transaction",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Stock Ledger Entry",
"report_name": "Incorrect Balance Qty After Transaction",
"report_type": "Script Report",
"roles": [
{
"role": "Stock User"
},
{
"role": "Stock Manager"
},
{
"role": "Purchase User"
}
]
}

View File

@ -0,0 +1,111 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import frappe
from frappe import _
from six import iteritems
from frappe.utils import flt
def execute(filters=None):
columns, data = [], []
columns = get_columns()
data = get_data(filters)
return columns, data
def get_data(filters):
data = get_stock_ledger_entries(filters)
itewise_balance_qty = {}
for row in data:
key = (row.item_code, row.warehouse)
itewise_balance_qty.setdefault(key, []).append(row)
res = validate_data(itewise_balance_qty)
return res
def validate_data(itewise_balance_qty):
res = []
for key, data in iteritems(itewise_balance_qty):
row = get_incorrect_data(data)
if row:
res.append(row)
res.append({})
return res
def get_incorrect_data(data):
balance_qty = 0.0
for row in data:
balance_qty += row.actual_qty
if row.voucher_type == "Stock Reconciliation" and not row.batch_no:
balance_qty = flt(row.qty_after_transaction)
row.expected_balance_qty = balance_qty
if abs(flt(row.expected_balance_qty) - flt(row.qty_after_transaction)) > 0.5:
row.differnce = abs(flt(row.expected_balance_qty) - flt(row.qty_after_transaction))
return row
def get_stock_ledger_entries(report_filters):
filters = {}
fields = ['name', 'voucher_type', 'voucher_no', 'item_code', 'actual_qty',
'posting_date', 'posting_time', 'company', 'warehouse', 'qty_after_transaction', 'batch_no']
for field in ['warehouse', 'item_code', 'company']:
if report_filters.get(field):
filters[field] = report_filters.get(field)
return frappe.get_all('Stock Ledger Entry', fields = fields, filters = filters,
order_by = 'timestamp(posting_date, posting_time) asc, creation asc')
def get_columns():
return [{
'label': _('Id'),
'fieldtype': 'Link',
'fieldname': 'name',
'options': 'Stock Ledger Entry',
'width': 120
}, {
'label': _('Posting Date'),
'fieldtype': 'Date',
'fieldname': 'posting_date',
'width': 110
}, {
'label': _('Voucher Type'),
'fieldtype': 'Link',
'fieldname': 'voucher_type',
'options': 'DocType',
'width': 120
}, {
'label': _('Voucher No'),
'fieldtype': 'Dynamic Link',
'fieldname': 'voucher_no',
'options': 'voucher_type',
'width': 120
}, {
'label': _('Item Code'),
'fieldtype': 'Link',
'fieldname': 'item_code',
'options': 'Item',
'width': 120
}, {
'label': _('Warehouse'),
'fieldtype': 'Link',
'fieldname': 'warehouse',
'options': 'Warehouse',
'width': 120
}, {
'label': _('Expected Balance Qty'),
'fieldtype': 'Float',
'fieldname': 'expected_balance_qty',
'width': 170
}, {
'label': _('Actual Balance Qty'),
'fieldtype': 'Float',
'fieldname': 'qty_after_transaction',
'width': 150
}, {
'label': _('Difference'),
'fieldtype': 'Float',
'fieldname': 'differnce',
'width': 110
}]

View File

@ -0,0 +1,35 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports["Incorrect Serial No Valuation"] = {
"filters": [
{
label: __('Item Code'),
fieldtype: 'Link',
fieldname: 'item_code',
options: 'Item',
get_query: function() {
return {
filters: {
'has_serial_no': 1
}
}
}
},
{
label: __('From Date'),
fieldtype: 'Date',
fieldname: 'from_date',
reqd: 1,
default: frappe.defaults.get_user_default("year_start_date")
},
{
label: __('To Date'),
fieldtype: 'Date',
fieldname: 'to_date',
reqd: 1,
default: frappe.defaults.get_user_default("year_end_date")
}
]
};

View File

@ -0,0 +1,36 @@
{
"add_total_row": 0,
"columns": [],
"creation": "2021-05-13 13:07:00.767845",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"json": "{}",
"modified": "2021-05-13 13:07:00.767845",
"modified_by": "Administrator",
"module": "Stock",
"name": "Incorrect Serial No Valuation",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Stock Ledger Entry",
"report_name": "Incorrect Serial No Valuation",
"report_type": "Script Report",
"roles": [
{
"role": "Stock User"
},
{
"role": "Accounts Manager"
},
{
"role": "Accounts User"
},
{
"role": "Stock Manager"
}
]
}

View File

@ -0,0 +1,148 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import frappe
import copy
from frappe import _
from six import iteritems
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
def execute(filters=None):
columns, data = [], []
columns = get_columns()
data = get_data(filters)
return columns, data
def get_data(filters):
data = get_stock_ledger_entries(filters)
serial_nos_data = prepare_serial_nos(data)
data = get_incorrect_serial_nos(serial_nos_data)
return data
def prepare_serial_nos(data):
serial_no_wise_data = {}
for row in data:
if not row.serial_nos:
continue
for serial_no in get_serial_nos(row.serial_nos):
sle = copy.deepcopy(row)
sle.serial_no = serial_no
sle.qty = 1 if sle.actual_qty > 0 else -1
sle.valuation_rate = sle.valuation_rate if sle.actual_qty > 0 else sle.valuation_rate * -1
serial_no_wise_data.setdefault(serial_no, []).append(sle)
return serial_no_wise_data
def get_incorrect_serial_nos(serial_nos_data):
result = []
total_value = frappe._dict({'qty': 0, 'valuation_rate': 0, 'serial_no': frappe.bold(_('Balance'))})
for serial_no, data in iteritems(serial_nos_data):
total_dict = frappe._dict({'qty': 0, 'valuation_rate': 0, 'serial_no': frappe.bold(_('Total'))})
if check_incorrect_serial_data(data, total_dict):
result.extend(data)
total_value.qty += total_dict.qty
total_value.valuation_rate += total_dict.valuation_rate
result.append(total_dict)
result.append({})
result.append(total_value)
return result
def check_incorrect_serial_data(data, total_dict):
incorrect_data = False
for row in data:
total_dict.qty += row.qty
total_dict.valuation_rate += row.valuation_rate
if ((total_dict.qty == 0 and abs(total_dict.valuation_rate) > 0) or total_dict.qty < 0):
incorrect_data = True
return incorrect_data
def get_stock_ledger_entries(report_filters):
fields = ['name', 'voucher_type', 'voucher_no', 'item_code', 'serial_no as serial_nos', 'actual_qty',
'posting_date', 'posting_time', 'company', 'warehouse', '(stock_value_difference / actual_qty) as valuation_rate']
filters = {'serial_no': ("is", "set")}
if report_filters.get('item_code'):
filters['item_code'] = report_filters.get('item_code')
if report_filters.get('from_date') and report_filters.get('to_date'):
filters['posting_date'] = ('between', [report_filters.get('from_date'), report_filters.get('to_date')])
return frappe.get_all('Stock Ledger Entry', fields = fields, filters = filters,
order_by = 'timestamp(posting_date, posting_time) asc, creation asc')
def get_columns():
return [{
'label': _('Company'),
'fieldtype': 'Link',
'fieldname': 'company',
'options': 'Company',
'width': 120
}, {
'label': _('Id'),
'fieldtype': 'Link',
'fieldname': 'name',
'options': 'Stock Ledger Entry',
'width': 120
}, {
'label': _('Posting Date'),
'fieldtype': 'Date',
'fieldname': 'posting_date',
'width': 90
}, {
'label': _('Posting Time'),
'fieldtype': 'Time',
'fieldname': 'posting_time',
'width': 90
}, {
'label': _('Voucher Type'),
'fieldtype': 'Link',
'fieldname': 'voucher_type',
'options': 'DocType',
'width': 100
}, {
'label': _('Voucher No'),
'fieldtype': 'Dynamic Link',
'fieldname': 'voucher_no',
'options': 'voucher_type',
'width': 110
}, {
'label': _('Item Code'),
'fieldtype': 'Link',
'fieldname': 'item_code',
'options': 'Item',
'width': 120
}, {
'label': _('Warehouse'),
'fieldtype': 'Link',
'fieldname': 'warehouse',
'options': 'Warehouse',
'width': 120
}, {
'label': _('Serial No'),
'fieldtype': 'Link',
'fieldname': 'serial_no',
'options': 'Serial No',
'width': 100
}, {
'label': _('Qty'),
'fieldtype': 'Float',
'fieldname': 'qty',
'width': 80
}, {
'label': _('Valuation Rate (In / Out)'),
'fieldtype': 'Currency',
'fieldname': 'valuation_rate',
'width': 110
}]

View File

@ -15,6 +15,7 @@
"hide_custom": 0,
"icon": "stock",
"idx": 0,
"is_default": 0,
"is_standard": 1,
"label": "Stock",
"links": [
@ -653,9 +654,44 @@
"link_type": "Report",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Incorrect Data Report",
"link_type": "DocType",
"onboard": 0,
"type": "Card Break"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Incorrect Serial No Qty and Valuation",
"link_to": "Incorrect Serial No Valuation",
"link_type": "Report",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Incorrect Balance Qty After Transaction",
"link_to": "Incorrect Balance Qty After Transaction",
"link_type": "Report",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Stock and Account Value Comparison",
"link_to": "Stock and Account Value Comparison",
"link_type": "Report",
"onboard": 0,
"type": "Link"
}
],
"modified": "2020-12-01 13:38:36.282890",
"modified": "2021-05-13 13:10:24.914983",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",