fix: time out error while submitting the purchase receipt which has more than 100 serial nos

This commit is contained in:
Rohit Waghchaure 2020-02-07 14:38:25 +05:30
parent d64135b2d2
commit f0d27528e3
2 changed files with 58 additions and 32 deletions

View File

@ -262,6 +262,30 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertEqual(pr2.per_billed, 80)
self.assertEqual(pr2.status, "To Bill")
def test_serial_no_against_purchase_receipt(self):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
item_code = "Test Manual Created Serial No"
if not frappe.db.exists("Item", item_code):
item = make_item(item_code, dict(has_serial_no=1))
serial_no = random_string(5)
pr_doc = make_purchase_receipt(item_code=item_code,
qty=1, serial_no = serial_no)
self.assertEqual(serial_no, frappe.db.get_value("Serial No",
{"purchase_document_type": "Purchase Receipt", "purchase_document_no": pr_doc.name}, "name"))
item_code = "Test Auto Created Serial No"
if not frappe.db.exists("Item", item_code):
item = make_item(item_code, dict(has_serial_no=1, serial_no_series="KLJL.###"))
new_pr_doc = make_purchase_receipt(item_code=item_code, qty=1)
serial_no = get_serial_nos(new_pr_doc[0].serial_no)[0]
self.assertEqual(serial_no, frappe.db.get_value("Serial No",
{"purchase_document_type": "Purchase Receipt", "purchase_document_no": new_pr_doc.name}, "name"))
def test_not_accept_duplicate_serial_no(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note

View File

@ -29,13 +29,12 @@ class SerialNo(StockController):
self.via_stock_ledger = False
def validate(self):
if self.get("__islocal") and self.warehouse:
if self.get("__islocal") and self.warehouse and not self.via_stock_ledger:
frappe.throw(_("New Serial No cannot have Warehouse. Warehouse must be set by Stock Entry or Purchase Receipt"), SerialNoCannotCreateDirectError)
self.set_maintenance_status()
self.validate_warehouse()
self.validate_item()
self.on_stock_ledger_entry()
def set_maintenance_status(self):
if not self.warranty_expiry_date and not self.amc_expiry_date:
@ -68,7 +67,7 @@ class SerialNo(StockController):
"""
Validate whether serial no is required for this item
"""
item = frappe.get_doc("Item", self.item_code)
item = frappe.get_cached_doc("Item", self.item_code)
if item.has_serial_no!=1:
frappe.throw(_("Item {0} is not setup for Serial Nos. Check Item master").format(self.item_code))
@ -117,9 +116,9 @@ class SerialNo(StockController):
"warranty_expiry_date"):
self.set(fieldname, None)
def get_last_sle(self):
def get_last_sle(self, serial_no=None):
entries = {}
sle_dict = self.get_stock_ledger_entries()
sle_dict = self.get_stock_ledger_entries(serial_no)
if sle_dict:
if sle_dict.get("incoming", []):
entries["purchase_sle"] = sle_dict["incoming"][0]
@ -132,13 +131,28 @@ class SerialNo(StockController):
return entries
def get_stock_ledger_entries(self):
def get_stock_ledger_entries(self, serial_no=None):
sle_dict = {}
for sle in frappe.db.sql("""select * from `tabStock Ledger Entry`
where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No'
order by posting_date desc, posting_time desc, creation desc""",
("%%%s%%" % self.name, self.item_code), as_dict=1):
if self.name.upper() in get_serial_nos(sle.serial_no):
if not serial_no:
serial_no = self.name
for sle in frappe.db.sql("""
SELECT voucher_type, voucher_no,
posting_date, posting_time, incoming_rate, actual_qty, serial_no
FROM
`tabStock Ledger Entry`
WHERE
item_code=%s AND company = %s AND ifnull(is_cancelled, 'No')='No'
AND (serial_no = %s
OR serial_no like %s
OR serial_no like %s
OR serial_no like %s
)
ORDER BY
posting_date desc, posting_time desc, creation desc""",
(self.item_code, self.company,
serial_no, serial_no+'\n%', '%\n'+serial_no, '%\n'+serial_no+'\n%'), as_dict=1):
if serial_no.upper() in get_serial_nos(sle.serial_no):
if cint(sle.actual_qty) > 0:
sle_dict.setdefault("incoming", []).append(sle)
else:
@ -178,12 +192,11 @@ class SerialNo(StockController):
where name=%s""" % (dt[0], '%s', '%s'),
('\n'.join(list(serial_nos)), item[0]))
def on_stock_ledger_entry(self):
if self.via_stock_ledger and not self.get("__islocal"):
last_sle = self.get_last_sle()
self.set_purchase_details(last_sle.get("purchase_sle"))
self.set_sales_details(last_sle.get("delivery_sle"))
self.set_maintenance_status()
def update_serial_no_reference(self, serial_no=None):
last_sle = self.get_last_sle(serial_no)
self.set_purchase_details(last_sle.get("purchase_sle"))
self.set_sales_details(last_sle.get("delivery_sle"))
self.set_maintenance_status()
def process_serial_no(sle):
item_det = get_item_details(sle.item_code)
@ -407,27 +420,16 @@ def get_serial_nos(serial_no):
def make_serial_no(serial_no, args):
sr = frappe.new_doc("Serial No")
sr.warehouse = None
sr.dont_update_if_missing.append("warehouse")
sr.flags.ignore_permissions = True
sr.serial_no = serial_no
sr.item_code = args.get('item_code')
sr.company = args.get('company')
sr.batch_no = args.get('batch_no')
sr.via_stock_ledger = args.get('via_stock_ledger') or True
sr.asset = args.get('asset')
sr.location = args.get('location')
sr.warehouse = args.get('warehouse')
if args.get('purchase_document_type'):
sr.purchase_document_type = args.get('purchase_document_type')
sr.purchase_document_no = args.get('purchase_document_no')
sr.supplier = args.get('supplier')
sr.insert()
if args.get('warehouse'):
sr.warehouse = args.get('warehouse')
sr.save()
sr.validate_item()
sr.update_serial_no_reference(serial_no)
sr.db_insert()
return sr.name