Landed cost voucher: fixes for serialized item

This commit is contained in:
Nabin Hait 2015-03-27 15:38:31 +05:30
parent 712440c045
commit 54c865e77c
7 changed files with 37 additions and 18 deletions

View File

@ -197,9 +197,10 @@ class StockController(AccountsController):
sl_dict.update(args) sl_dict.update(args)
return sl_dict return sl_dict
def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False): def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False,
via_landed_cost_voucher=False):
from erpnext.stock.stock_ledger import make_sl_entries from erpnext.stock.stock_ledger import make_sl_entries
make_sl_entries(sl_entries, is_amended, allow_negative_stock) make_sl_entries(sl_entries, is_amended, allow_negative_stock, via_landed_cost_voucher)
def make_gl_entries_on_cancel(self): def make_gl_entries_on_cancel(self):
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s

View File

@ -23,7 +23,7 @@ class Bin(Document):
if (not getattr(self, f, None)) or (not self.get(f)): if (not getattr(self, f, None)) or (not self.get(f)):
self.set(f, 0.0) self.set(f, 0.0)
def update_stock(self, args, allow_negative_stock=False): def update_stock(self, args, allow_negative_stock=False, via_landed_cost_voucher=False):
self.update_qty(args) self.update_qty(args)
if args.get("actual_qty") or args.get("voucher_type") == "Stock Reconciliation": if args.get("actual_qty") or args.get("voucher_type") == "Stock Reconciliation":
@ -38,7 +38,7 @@ class Bin(Document):
"warehouse": self.warehouse, "warehouse": self.warehouse,
"posting_date": args.get("posting_date"), "posting_date": args.get("posting_date"),
"posting_time": args.get("posting_time") "posting_time": args.get("posting_time")
}, allow_negative_stock=allow_negative_stock) }, allow_negative_stock=allow_negative_stock, via_landed_cost_voucher=via_landed_cost_voucher)
def update_qty(self, args): def update_qty(self, args):
# update the stock values (for current quantities) # update the stock values (for current quantities)

View File

@ -6,6 +6,7 @@ import frappe
from frappe import _ from frappe import _
from frappe.utils import flt from frappe.utils import flt
from frappe.model.document import Document from frappe.model.document import Document
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
class LandedCostVoucher(Document): class LandedCostVoucher(Document):
def get_items_from_purchase_receipts(self): def get_items_from_purchase_receipts(self):
@ -92,13 +93,25 @@ class LandedCostVoucher(Document):
# save will update landed_cost_voucher_amount and voucher_amount in PR, # save will update landed_cost_voucher_amount and voucher_amount in PR,
# as those fields are allowed to edit after submit # as those fields are allowed to edit after submit
pr.save() pr.save()
# update latest valuation rate in serial no
self.update_rate_in_serial_no(pr)
# update stock & gl entries for cancelled state of PR # update stock & gl entries for cancelled state of PR
pr.docstatus = 2 pr.docstatus = 2
pr.update_stock_ledger(allow_negative_stock=True) pr.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
pr.make_gl_entries_on_cancel() pr.make_gl_entries_on_cancel()
# update stock & gl entries for submit state of PR # update stock & gl entries for submit state of PR
pr.docstatus = 1 pr.docstatus = 1
pr.update_stock_ledger() pr.update_stock_ledger(via_landed_cost_voucher=True)
pr.make_gl_entries() pr.make_gl_entries()
def update_rate_in_serial_no(self, purchase_receipt):
for item in purchase_receipt.get("purchase_receipt_details"):
if item.serial_no:
serial_nos = get_serial_nos(item.serial_no)
if serial_nos:
frappe.db.sql("update `tabSerial No` set purchase_rate=%s where name in ({0})"
.format(", ".join(["%s"]*len(serial_nos))), tuple([item.valuation_rate] + serial_nos))

View File

@ -129,7 +129,7 @@ class PurchaseReceipt(BuyingController):
if not d.prevdoc_docname: if not d.prevdoc_docname:
frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code)) frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
def update_stock_ledger(self, allow_negative_stock=False): def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
sl_entries = [] sl_entries = []
stock_items = self.get_stock_items() stock_items = self.get_stock_items()
@ -154,7 +154,8 @@ class PurchaseReceipt(BuyingController):
})) }))
self.bk_flush_supp_wh(sl_entries) self.bk_flush_supp_wh(sl_entries)
self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock) self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock,
via_landed_cost_voucher=via_landed_cost_voucher)
def update_ordered_qty(self): def update_ordered_qty(self):
po_map = {} po_map = {}

View File

@ -27,8 +27,9 @@ class StockLedgerEntry(Document):
self.check_stock_frozen_date() self.check_stock_frozen_date()
self.actual_amt_check() self.actual_amt_check()
from erpnext.stock.doctype.serial_no.serial_no import process_serial_no if not self.get("via_landed_cost_voucher"):
process_serial_no(self) from erpnext.stock.doctype.serial_no.serial_no import process_serial_no
process_serial_no(self)
#check for item quantity available in stock #check for item quantity available in stock
def actual_amt_check(self): def actual_amt_check(self):

View File

@ -14,7 +14,7 @@ class NegativeStockError(frappe.ValidationError): pass
_exceptions = frappe.local('stockledger_exceptions') _exceptions = frappe.local('stockledger_exceptions')
# _exceptions = [] # _exceptions = []
def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False): def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False, via_landed_cost_voucher=False):
if sl_entries: if sl_entries:
from erpnext.stock.utils import update_bin from erpnext.stock.utils import update_bin
@ -28,14 +28,14 @@ def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False):
sle['actual_qty'] = -flt(sle['actual_qty']) sle['actual_qty'] = -flt(sle['actual_qty'])
if sle.get("actual_qty") or sle.get("voucher_type")=="Stock Reconciliation": if sle.get("actual_qty") or sle.get("voucher_type")=="Stock Reconciliation":
sle_id = make_entry(sle, allow_negative_stock) sle_id = make_entry(sle, allow_negative_stock, via_landed_cost_voucher)
args = sle.copy() args = sle.copy()
args.update({ args.update({
"sle_id": sle_id, "sle_id": sle_id,
"is_amended": is_amended "is_amended": is_amended
}) })
update_bin(args, allow_negative_stock) update_bin(args, allow_negative_stock, via_landed_cost_voucher)
if cancel: if cancel:
delete_cancelled_entry(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no')) delete_cancelled_entry(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no'))
@ -46,11 +46,12 @@ def set_as_cancel(voucher_type, voucher_no):
where voucher_no=%s and voucher_type=%s""", where voucher_no=%s and voucher_type=%s""",
(now(), frappe.session.user, voucher_type, voucher_no)) (now(), frappe.session.user, voucher_type, voucher_no))
def make_entry(args, allow_negative_stock=False): def make_entry(args, allow_negative_stock=False, via_landed_cost_voucher=False):
args.update({"doctype": "Stock Ledger Entry"}) args.update({"doctype": "Stock Ledger Entry"})
sle = frappe.get_doc(args) sle = frappe.get_doc(args)
sle.ignore_permissions = 1 sle.ignore_permissions = 1
sle.allow_negative_stock=allow_negative_stock sle.allow_negative_stock=allow_negative_stock
sle.via_landed_cost_voucher = via_landed_cost_voucher
sle.insert() sle.insert()
sle.submit() sle.submit()
return sle.name return sle.name
@ -59,7 +60,9 @@ def delete_cancelled_entry(voucher_type, voucher_no):
frappe.db.sql("""delete from `tabStock Ledger Entry` frappe.db.sql("""delete from `tabStock Ledger Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no)) where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
def update_entries_after(args, allow_zero_rate=False, allow_negative_stock=False, verbose=1): def update_entries_after(args, allow_zero_rate=False, allow_negative_stock=False,
via_landed_cost_voucher=False, verbose=1):
""" """
update valution rate and qty after transaction update valution rate and qty after transaction
from the current time-bucket onwards from the current time-bucket onwards
@ -91,7 +94,7 @@ def update_entries_after(args, allow_zero_rate=False, allow_negative_stock=False
stock_value_difference = 0.0 stock_value_difference = 0.0
for sle in entries_to_fix: for sle in entries_to_fix:
if sle.serial_no or not allow_negative_stock: if (sle.serial_no and not via_landed_cost_voucher) or not allow_negative_stock:
# validate negative stock for serialized items, fifo valuation # validate negative stock for serialized items, fifo valuation
# or when negative stock is not allowed for moving average # or when negative stock is not allowed for moving average
if not validate_negative_stock(qty_after_transaction, sle): if not validate_negative_stock(qty_after_transaction, sle):

View File

@ -53,11 +53,11 @@ def get_bin(item_code, warehouse):
bin_obj.ignore_permissions = True bin_obj.ignore_permissions = True
return bin_obj return bin_obj
def update_bin(args, allow_negative_stock=False): def update_bin(args, allow_negative_stock=False, via_landed_cost_voucher=False):
is_stock_item = frappe.db.get_value('Item', args.get("item_code"), 'is_stock_item') is_stock_item = frappe.db.get_value('Item', args.get("item_code"), 'is_stock_item')
if is_stock_item == 'Yes': if is_stock_item == 'Yes':
bin = get_bin(args.get("item_code"), args.get("warehouse")) bin = get_bin(args.get("item_code"), args.get("warehouse"))
bin.update_stock(args, allow_negative_stock) bin.update_stock(args, allow_negative_stock, via_landed_cost_voucher)
return bin return bin
else: else:
frappe.msgprint(_("Item {0} ignored since it is not a stock item").format(args.get("item_code"))) frappe.msgprint(_("Item {0} ignored since it is not a stock item").format(args.get("item_code")))