provision to add batch number in the stock reconciliation

This commit is contained in:
Rohit Waghchaure 2019-05-24 16:53:51 +05:30
parent 05d3bcb63d
commit 66aa37f1e2
5 changed files with 230 additions and 816 deletions

View File

@ -257,10 +257,10 @@ def get_batches(item_code, warehouse, qty=1, throw=False):
'on (`tabBatch`.batch_id = `tabStock Ledger Entry`.batch_no )' 'on (`tabBatch`.batch_id = `tabStock Ledger Entry`.batch_no )'
'where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s ' 'where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s '
'and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL)' 'and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL)'
'group by batch_id ' 'group by batch_id having qty > 0'
'order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC', 'order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC',
(item_code, warehouse), (item_code, warehouse),
as_dict=True as_dict=True, debug=1
) )
return batches return batches

View File

@ -76,6 +76,7 @@ frappe.ui.form.on("Stock Reconciliation", {
set_valuation_rate_and_qty: function(frm, cdt, cdn) { set_valuation_rate_and_qty: function(frm, cdt, cdn) {
var d = frappe.model.get_doc(cdt, cdn); var d = frappe.model.get_doc(cdt, cdn);
if(d.item_code && d.warehouse) { if(d.item_code && d.warehouse) {
frappe.call({ frappe.call({
method: "erpnext.stock.doctype.stock_reconciliation.stock_reconciliation.get_stock_balance_for", method: "erpnext.stock.doctype.stock_reconciliation.stock_reconciliation.get_stock_balance_for",
@ -83,7 +84,8 @@ frappe.ui.form.on("Stock Reconciliation", {
item_code: d.item_code, item_code: d.item_code,
warehouse: d.warehouse, warehouse: d.warehouse,
posting_date: frm.doc.posting_date, posting_date: frm.doc.posting_date,
posting_time: frm.doc.posting_time posting_time: frm.doc.posting_time,
batch_no: d.batch_no
}, },
callback: function(r) { callback: function(r) {
frappe.model.set_value(cdt, cdn, "qty", r.message.qty); frappe.model.set_value(cdt, cdn, "qty", r.message.qty);
@ -152,9 +154,22 @@ frappe.ui.form.on("Stock Reconciliation Item", {
frm.events.set_item_code(frm, cdt, cdn); frm.events.set_item_code(frm, cdt, cdn);
}, },
warehouse: function(frm, cdt, cdn) { warehouse: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
if (child.batch_no) {
frappe.model.set_value(child.cdt, child.cdn, "batch_no", "");
}
frm.events.set_valuation_rate_and_qty(frm, cdt, cdn); frm.events.set_valuation_rate_and_qty(frm, cdt, cdn);
}, },
item_code: function(frm, cdt, cdn) { item_code: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
if (child.batch_no) {
frappe.model.set_value(child.cdt, child.cdn, "batch_no", "");
}
frm.events.set_valuation_rate_and_qty(frm, cdt, cdn);
},
batch_no: function(frm, cdt, cdn) {
frm.events.set_valuation_rate_and_qty(frm, cdt, cdn); frm.events.set_valuation_rate_and_qty(frm, cdt, cdn);
}, },
qty: function(frm, cdt, cdn) { qty: function(frm, cdt, cdn) {

View File

@ -11,6 +11,7 @@ from erpnext.controllers.stock_controller import StockController
from erpnext.accounts.utils import get_company_default from erpnext.accounts.utils import get_company_default
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from erpnext.stock.utils import get_stock_balance, get_incoming_rate, get_available_serial_nos from erpnext.stock.utils import get_stock_balance, get_incoming_rate, get_available_serial_nos
from erpnext.stock.doctype.batch.batch import get_batch_qty
class OpeningEntryAccountError(frappe.ValidationError): pass class OpeningEntryAccountError(frappe.ValidationError): pass
class EmptyStockReconciliationItemsError(frappe.ValidationError): pass class EmptyStockReconciliationItemsError(frappe.ValidationError): pass
@ -44,7 +45,7 @@ class StockReconciliation(StockController):
self.difference_amount = 0.0 self.difference_amount = 0.0
def _changed(item): def _changed(item):
item_dict = get_stock_balance_for(item.item_code, item.warehouse, item_dict = get_stock_balance_for(item.item_code, item.warehouse,
self.posting_date, self.posting_time) self.posting_date, self.posting_time, batch_no=item.batch_no)
if ((item.qty==None or item.qty==item_dict.get("qty")) if ((item.qty==None or item.qty==item_dict.get("qty"))
and (item.valuation_rate==None or item.valuation_rate==item_dict.get("rate"))): and (item.valuation_rate==None or item.valuation_rate==item_dict.get("rate"))):
@ -90,10 +91,15 @@ class StockReconciliation(StockController):
for row_num, row in enumerate(self.items): for row_num, row in enumerate(self.items):
# find duplicates # find duplicates
if [row.item_code, row.warehouse] in item_warehouse_combinations: key = [row.item_code, row.warehouse]
for field in ['serial_no', 'batch_no']:
if row.get(field):
key.append(row.get(field))
if key in item_warehouse_combinations:
self.validation_messages.append(_get_msg(row_num, _("Duplicate entry"))) self.validation_messages.append(_get_msg(row_num, _("Duplicate entry")))
else: else:
item_warehouse_combinations.append([row.item_code, row.warehouse]) item_warehouse_combinations.append(key)
self.validate_item(row.item_code, row) self.validate_item(row.item_code, row)
@ -155,9 +161,12 @@ class StockReconciliation(StockController):
raise frappe.ValidationError(_("Serial nos are required for serialized item {0}").format(item_code)) raise frappe.ValidationError(_("Serial nos are required for serialized item {0}").format(item_code))
# item managed batch-wise not allowed # item managed batch-wise not allowed
if item.has_batch_no and not row.batch: if item.has_batch_no and not row.batch_no and not item.create_new_batch:
raise frappe.ValidationError(_("Batch no is required for batched item {0}").format(item_code)) raise frappe.ValidationError(_("Batch no is required for batched item {0}").format(item_code))
if self._action=="submit" and item.create_new_batch:
self.make_batches('warehouse')
# docstatus should be < 2 # docstatus should be < 2
validate_cancelled_item(item_code, item.docstatus, verbose=0) validate_cancelled_item(item_code, item.docstatus, verbose=0)
@ -171,7 +180,7 @@ class StockReconciliation(StockController):
sl_entries = [] sl_entries = []
for row in self.items: for row in self.items:
if row.serial_no: if row.serial_no or row.batch_no:
self.get_sle_for_serialized_items(row, sl_entries) self.get_sle_for_serialized_items(row, sl_entries)
else: else:
previous_sle = get_previous_sle({ previous_sle = get_previous_sle({
@ -205,15 +214,20 @@ class StockReconciliation(StockController):
from erpnext.stock.stock_ledger import get_previous_sle from erpnext.stock.stock_ledger import get_previous_sle
# To issue existing serial nos # To issue existing serial nos
if row.current_serial_no: if row.current_qty and (row.current_serial_no or row.batch_no):
args = self.get_sle_for_items(row) args = self.get_sle_for_items(row)
args.update({ args.update({
'actual_qty': -1 * row.current_qty, 'actual_qty': -1 * row.current_qty,
'serial_no': row.current_serial_no, 'serial_no': row.current_serial_no,
'qty_after_transaction': 0, 'batch_no': row.batch_no,
'valuation_rate': row.current_valuation_rate 'valuation_rate': row.current_valuation_rate
}) })
if row.current_serial_no:
args.update({
'qty_after_transaction': 0,
})
sl_entries.append(args) sl_entries.append(args)
for serial_no in get_serial_nos(row.serial_no): for serial_no in get_serial_nos(row.serial_no):
@ -265,7 +279,7 @@ class StockReconciliation(StockController):
if not serial_nos and row.serial_no: if not serial_nos and row.serial_no:
serial_nos = get_serial_nos(row.serial_no) serial_nos = get_serial_nos(row.serial_no)
return frappe._dict({ data = frappe._dict({
"doctype": "Stock Ledger Entry", "doctype": "Stock Ledger Entry",
"item_code": row.item_code, "item_code": row.item_code,
"warehouse": row.warehouse, "warehouse": row.warehouse,
@ -276,11 +290,16 @@ class StockReconciliation(StockController):
"company": self.company, "company": self.company,
"stock_uom": frappe.db.get_value("Item", row.item_code, "stock_uom"), "stock_uom": frappe.db.get_value("Item", row.item_code, "stock_uom"),
"is_cancelled": "No" if self.docstatus != 2 else "Yes", "is_cancelled": "No" if self.docstatus != 2 else "Yes",
"qty_after_transaction": flt(row.qty, row.precision("qty")),
"serial_no": '\n'.join(serial_nos) if serial_nos else '', "serial_no": '\n'.join(serial_nos) if serial_nos else '',
"batch_no": row.batch_no,
"valuation_rate": flt(row.valuation_rate, row.precision("valuation_rate")) "valuation_rate": flt(row.valuation_rate, row.precision("valuation_rate"))
}) })
if not row.batch_no:
data.qty_after_transaction = flt(row.qty, row.precision("qty"))
return data
def delete_and_repost_sle(self): def delete_and_repost_sle(self):
""" Delete Stock Ledger Entries related to this voucher """ Delete Stock Ledger Entries related to this voucher
and repost future Stock Ledger Entries""" and repost future Stock Ledger Entries"""
@ -295,7 +314,7 @@ class StockReconciliation(StockController):
sl_entries = [] sl_entries = []
for row in self.items: for row in self.items:
if row.serial_no: if row.serial_no or row.batch_no:
self.get_sle_for_serialized_items(row, sl_entries) self.get_sle_for_serialized_items(row, sl_entries)
if sl_entries: if sl_entries:
@ -395,41 +414,51 @@ def get_items(warehouse, posting_date, posting_time, company):
return res return res
@frappe.whitelist() @frappe.whitelist()
def get_stock_balance_for(item_code, warehouse, posting_date, posting_time, with_valuation_rate= True): def get_stock_balance_for(item_code, warehouse,
posting_date, posting_time, batch_no=None, with_valuation_rate= True):
frappe.has_permission("Stock Reconciliation", "write", throw = True) frappe.has_permission("Stock Reconciliation", "write", throw = True)
has_serial_no = frappe.get_cached_value("Item", item_code, "has_serial_no") item_dict = frappe.db.get_value("Item", item_code,
["has_serial_no", "has_batch_no"], as_dict=1)
serial_nos = "" serial_nos = ""
if has_serial_no: if item_dict.get("has_serial_no"):
qty, rate, serial_nos = get_qty_rate_for_serial_nos(item_code, qty, rate, serial_nos = get_qty_rate_for_serial_nos(item_code,
warehouse, posting_date, posting_time) warehouse, posting_date, posting_time, item_dict)
else: else:
qty, rate = get_stock_balance(item_code, warehouse, qty, rate = get_stock_balance(item_code, warehouse,
posting_date, posting_time, with_valuation_rate=with_valuation_rate) posting_date, posting_time, with_valuation_rate=with_valuation_rate)
if item_dict.get("has_batch_no"):
qty = get_batch_qty(batch_no, warehouse) or 0
print(qty, rate, batch_no, warehouse)
return { return {
'qty': qty, 'qty': qty,
'rate': rate, 'rate': rate,
'serial_nos': serial_nos 'serial_nos': serial_nos
} }
def get_qty_rate_for_serial_nos(item_code, warehouse, posting_date, posting_time): def get_qty_rate_for_serial_nos(item_code, warehouse, posting_date, posting_time, item_dict):
args = {
"item_code": item_code,
"warehouse": warehouse,
"posting_date": posting_date,
"posting_time": posting_time,
}
serial_nos_list = [serial_no.get("name") serial_nos_list = [serial_no.get("name")
for serial_no in get_available_serial_nos(item_code, warehouse)] for serial_no in get_available_serial_nos(item_code, warehouse)]
qty = len(serial_nos_list) qty = len(serial_nos_list)
serial_nos = '\n'.join(serial_nos_list) serial_nos = '\n'.join(serial_nos_list)
args.update({
rate = get_incoming_rate({ 'qty': qty,
"item_code": item_code, "serial_nos": serial_nos
"warehouse": warehouse,
"posting_date": posting_date,
"posting_time": posting_time,
"qty": qty,
"serial_no":serial_nos,
}) })
rate = get_incoming_rate(args)
return qty, rate, serial_nos return qty, rate, serial_nos
@frappe.whitelist() @frappe.whitelist()

View File

@ -1,810 +1,181 @@
{ {
"allow_copy": 0, "creation": "2015-02-17 01:06:05.072764",
"allow_events_in_timeline": 0, "doctype": "DocType",
"allow_guest_to_view": 0, "document_type": "Other",
"allow_import": 0, "editable_grid": 1,
"allow_rename": 0, "engine": "InnoDB",
"beta": 0, "field_order": [
"creation": "2015-02-17 01:06:05.072764", "barcode",
"custom": 0, "item_code",
"docstatus": 0, "item_name",
"doctype": "DocType", "warehouse",
"document_type": "Other", "column_break_6",
"editable_grid": 1, "qty",
"engine": "InnoDB", "valuation_rate",
"amount",
"serial_no_and_batch_section",
"serial_no",
"column_break_11",
"batch_no",
"section_break_3",
"current_qty",
"current_serial_no",
"column_break_9",
"current_valuation_rate",
"current_amount",
"section_break_14",
"quantity_difference",
"column_break_16",
"amount_difference"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "fieldname": "barcode",
"allow_in_quick_entry": 0, "fieldtype": "Data",
"allow_on_submit": 0, "label": "Barcode",
"bold": 0, "print_hide": 1
"collapsible": 0, },
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "barcode",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Barcode",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 3,
"allow_in_quick_entry": 0, "fieldname": "item_code",
"allow_on_submit": 0, "fieldtype": "Link",
"bold": 0, "in_global_search": 1,
"collapsible": 0, "in_list_view": 1,
"columns": 3, "label": "Item Code",
"fetch_if_empty": 0, "options": "Item",
"fieldname": "item_code", "reqd": 1
"fieldtype": "Link", },
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Code",
"length": 0,
"no_copy": 0,
"options": "Item",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "item_name",
"allow_in_quick_entry": 0, "fieldtype": "Data",
"allow_on_submit": 0, "in_global_search": 1,
"bold": 0, "label": "Item Name",
"collapsible": 0, "no_copy": 1,
"columns": 0, "print_hide": 1,
"fetch_if_empty": 0, "read_only": 1
"fieldname": "item_name", },
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Name",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 3,
"allow_in_quick_entry": 0, "fieldname": "warehouse",
"allow_on_submit": 0, "fieldtype": "Link",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "Warehouse",
"columns": 3, "options": "Warehouse",
"fetch_if_empty": 0, "reqd": 1
"fieldname": "warehouse", },
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Warehouse",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "column_break_6",
"allow_in_quick_entry": 0, "fieldtype": "Column Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 2,
"allow_in_quick_entry": 0, "fieldname": "qty",
"allow_on_submit": 0, "fieldtype": "Float",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "Quantity"
"columns": 2, },
"description": "",
"fetch_if_empty": 0,
"fieldname": "qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Quantity",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 2,
"allow_in_quick_entry": 0, "fieldname": "valuation_rate",
"allow_on_submit": 0, "fieldtype": "Currency",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "Valuation Rate",
"columns": 2, "options": "Company:company:default_currency"
"description": "", },
"fetch_if_empty": 0,
"fieldname": "valuation_rate",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Valuation Rate",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "amount",
"allow_in_quick_entry": 0, "fieldtype": "Currency",
"allow_on_submit": 0, "label": "Amount",
"bold": 0, "options": "Company:company:default_currency",
"collapsible": 0, "read_only": 1
"columns": 0, },
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amount",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "serial_no_and_batch_section",
"allow_in_quick_entry": 0, "fieldtype": "Section Break",
"allow_on_submit": 0, "label": "Serial No and Batch"
"bold": 0, },
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "serial_no_and_batch_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Serial No and Batch",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "serial_no",
"allow_in_quick_entry": 0, "fieldtype": "Small Text",
"allow_on_submit": 0, "label": "Serial No"
"bold": 0, },
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "serial_no",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Serial No",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "column_break_11",
"allow_in_quick_entry": 0, "fieldtype": "Column Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "section_break_3",
"allow_in_quick_entry": 0, "fieldtype": "Section Break",
"allow_on_submit": 0, "label": "Before reconciliation"
"bold": 0, },
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "batch",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Batch",
"length": 0,
"no_copy": 0,
"options": "Batch",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "current_qty",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "label": "Current Qty",
"bold": 0, "read_only": 1
"collapsible": 0, },
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_3",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Before reconciliation",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "current_serial_no",
"allow_in_quick_entry": 0, "fieldtype": "Small Text",
"allow_on_submit": 0, "label": "Current Serial No",
"bold": 0, "no_copy": 1,
"collapsible": 0, "print_hide": 1,
"columns": 0, "read_only": 1
"description": "", },
"fetch_if_empty": 0,
"fieldname": "current_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Current Qty",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "column_break_9",
"allow_in_quick_entry": 0, "fieldtype": "Column Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "current_batch",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Current Batch No",
"length": 0,
"no_copy": 1,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "current_valuation_rate",
"allow_in_quick_entry": 0, "fieldtype": "Currency",
"allow_on_submit": 0, "label": "Current Valuation Rate",
"bold": 0, "options": "Company:company:default_currency",
"collapsible": 0, "read_only": 1
"columns": 0, },
"fetch_if_empty": 0,
"fieldname": "current_serial_no",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Current Serial No",
"length": 0,
"no_copy": 1,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "current_amount",
"allow_in_quick_entry": 0, "fieldtype": "Currency",
"allow_on_submit": 0, "label": "Current Amount",
"bold": 0, "options": "Company:company:default_currency",
"collapsible": 0, "read_only": 1
"columns": 0, },
"fetch_if_empty": 0,
"fieldname": "column_break_9",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "section_break_14",
"allow_in_quick_entry": 0, "fieldtype": "Section Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "current_valuation_rate",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Current Valuation Rate",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "quantity_difference",
"allow_in_quick_entry": 0, "fieldtype": "Read Only",
"allow_on_submit": 0, "label": "Quantity Difference"
"bold": 0, },
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "current_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Current Amount",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "column_break_16",
"allow_in_quick_entry": 0, "fieldtype": "Column Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_14",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "amount_difference",
"allow_in_quick_entry": 0, "fieldtype": "Currency",
"allow_on_submit": 0, "label": "Amount Difference",
"bold": 0, "options": "Company:company:default_currency",
"collapsible": 0, "read_only": 1
"columns": 0, },
"fetch_if_empty": 0,
"fieldname": "quantity_difference",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Quantity Difference",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "batch_no",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "label": "Batch No",
"bold": 0, "options": "Batch"
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_16",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amount_difference",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amount Difference",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "istable": 1,
"hide_toolbar": 0, "modified": "2019-05-24 12:34:50.018491",
"idx": 0, "modified_by": "Administrator",
"in_create": 0, "module": "Stock",
"is_submittable": 0, "name": "Stock Reconciliation Item",
"issingle": 0, "owner": "Administrator",
"istable": 1, "permissions": [],
"max_attachments": 0, "quick_entry": 1,
"menu_index": 0, "sort_field": "modified",
"modified": "2019-04-24 19:07:59.113660", "sort_order": "DESC",
"modified_by": "Administrator", "track_changes": 1
"module": "Stock",
"name": "Stock Reconciliation Item",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
} }

View File

@ -161,9 +161,8 @@ class update_entries_after(object):
self.qty_after_transaction = sle.qty_after_transaction self.qty_after_transaction = sle.qty_after_transaction
self.stock_value = flt(self.qty_after_transaction) * flt(self.valuation_rate) self.stock_value = flt(self.qty_after_transaction) * flt(self.valuation_rate)
frappe.errprint([self.stock_value, self.qty_after_transaction, self.valuation_rate])
else: else:
if sle.voucher_type=="Stock Reconciliation": if sle.voucher_type=="Stock Reconciliation" and not sle.batch_no:
# assert # assert
self.valuation_rate = sle.valuation_rate self.valuation_rate = sle.valuation_rate
self.qty_after_transaction = sle.qty_after_transaction self.qty_after_transaction = sle.qty_after_transaction
@ -181,7 +180,6 @@ class update_entries_after(object):
# rounding as per precision # rounding as per precision
self.stock_value = flt(self.stock_value, self.precision) self.stock_value = flt(self.stock_value, self.precision)
frappe.errprint([self.stock_value, self.qty_after_transaction, self.valuation_rate, "wefjlk"])
if self.prev_stock_value < 0 and self.stock_value >= 0 and sle.voucher_type != 'Stock Reconciliation': if self.prev_stock_value < 0 and self.stock_value >= 0 and sle.voucher_type != 'Stock Reconciliation':
stock_value_difference = sle.actual_qty * self.valuation_rate stock_value_difference = sle.actual_qty * self.valuation_rate
@ -376,7 +374,7 @@ class update_entries_after(object):
"""get Stock Ledger Entries after a particular datetime, for reposting""" """get Stock Ledger Entries after a particular datetime, for reposting"""
return get_stock_ledger_entries(self.previous_sle or frappe._dict({ return get_stock_ledger_entries(self.previous_sle or frappe._dict({
"item_code": self.args.get("item_code"), "warehouse": self.args.get("warehouse") }), "item_code": self.args.get("item_code"), "warehouse": self.args.get("warehouse") }),
">", "asc", for_update=True) ">", "asc", for_update=True, check_serial_no=False)
def raise_exceptions(self): def raise_exceptions(self):
deficiency = min(e["diff"] for e in self.exceptions) deficiency = min(e["diff"] for e in self.exceptions)
@ -417,7 +415,8 @@ def get_previous_sle(args, for_update=False):
sle = get_stock_ledger_entries(args, "<=", "desc", "limit 1", for_update=for_update) sle = get_stock_ledger_entries(args, "<=", "desc", "limit 1", for_update=for_update)
return sle and sle[0] or {} return sle and sle[0] or {}
def get_stock_ledger_entries(previous_sle, operator=None, order="desc", limit=None, for_update=False, debug=False): def get_stock_ledger_entries(previous_sle, operator=None,
order="desc", limit=None, for_update=False, debug=False, check_serial_no=True):
"""get stock ledger entries filtered by specific posting datetime conditions""" """get stock ledger entries filtered by specific posting datetime conditions"""
conditions = " and timestamp(posting_date, posting_time) {0} timestamp(%(posting_date)s, %(posting_time)s)".format(operator) conditions = " and timestamp(posting_date, posting_time) {0} timestamp(%(posting_date)s, %(posting_time)s)".format(operator)
if previous_sle.get("warehouse"): if previous_sle.get("warehouse"):
@ -425,7 +424,7 @@ def get_stock_ledger_entries(previous_sle, operator=None, order="desc", limit=No
elif previous_sle.get("warehouse_condition"): elif previous_sle.get("warehouse_condition"):
conditions += " and " + previous_sle.get("warehouse_condition") conditions += " and " + previous_sle.get("warehouse_condition")
if previous_sle.get("serial_no"): if check_serial_no and previous_sle.get("serial_no"):
conditions += " and serial_no like {}".format(frappe.db.escape('%{0}%'.format(previous_sle.get("serial_no")))) conditions += " and serial_no like {}".format(frappe.db.escape('%{0}%'.format(previous_sle.get("serial_no"))))
if not previous_sle.get("posting_date"): if not previous_sle.get("posting_date"):