def test_returned_serial_no_case(self): from erpnext.accounts.doctype.pos_invoice_merge_log.test_pos_invoice_merge_log import ( init_user_and_profile, ) from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos from erpnext.stock.doctype.serial_no.test_serial_no import get_serial_nos from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item frappe.db.savepoint("before_test_returned_serial_no_case") try: se = make_serialized_item() serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] init_user_and_profile() pos_inv = create_pos_invoice( item_code="_Test Serialized Item With Series", serial_no=serial_no, qty=1, rate=100, ) pos_return = make_sales_return(pos_inv.name) pos_return.flags.ignore_validate = True pos_return.insert() pos_return.submit() pos_reserved_serial_nos = get_pos_reserved_serial_nos( {"item_code": "_Test Serialized Item With Series", "warehouse": "_Test Warehouse - _TC"} ) self.assertTrue(serial_no not in pos_reserved_serial_nos) finally: frappe.db.rollback(save_point="before_test_returned_serial_no_case") frappe.set_user("Administrator")
def validate_stock_availablility(self): if self.is_return: return allow_negative_stock = frappe.db.get_value('Stock Settings', None, 'allow_negative_stock') error_msg = [] for d in self.get('items'): msg = "" if d.serial_no: filters = {"item_code": d.item_code, "warehouse": d.warehouse} if d.batch_no: filters["batch_no"] = d.batch_no reserved_serial_nos = get_pos_reserved_serial_nos(filters) serial_nos = get_serial_nos(d.serial_no) invalid_serial_nos = [ s for s in serial_nos if s in reserved_serial_nos ] bold_invalid_serial_nos = frappe.bold( ', '.join(invalid_serial_nos)) if len(invalid_serial_nos) == 1: msg = (_( "Row #{}: Serial No. {} has already been transacted into another POS Invoice. Please select valid serial no." ).format(d.idx, bold_invalid_serial_nos)) elif invalid_serial_nos: msg = (_( "Row #{}: Serial Nos. {} has already been transacted into another POS Invoice. Please select valid serial no." ).format(d.idx, bold_invalid_serial_nos)) else: if allow_negative_stock: return available_stock = get_stock_availability( d.item_code, d.warehouse) item_code, warehouse, qty = frappe.bold( d.item_code), frappe.bold(d.warehouse), frappe.bold(d.qty) if flt(available_stock) <= 0: msg = (_( 'Row #{}: Item Code: {} is not available under warehouse {}.' ).format(d.idx, item_code, warehouse)) elif flt(available_stock) < flt(d.qty): msg = (_( 'Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.' ).format(d.idx, item_code, warehouse, qty)) if msg: error_msg.append(msg) if error_msg: frappe.throw(error_msg, title=_("Item Unavailable"), as_list=True)
def validate_stock_availablility(self): allow_negative_stock = frappe.db.get_value('Stock Settings', None, 'allow_negative_stock') for d in self.get('items'): if d.serial_no: filters = { "item_code": d.item_code, "warehouse": d.warehouse, "delivery_document_no": "", "sales_invoice": "" } if d.batch_no: filters["batch_no"] = d.batch_no reserved_serial_nos, unreserved_serial_nos = get_pos_reserved_serial_nos( filters) serial_nos = d.serial_no.split("\n") serial_nos = ' '.join(serial_nos).split() # remove whitespaces invalid_serial_nos = [] for s in serial_nos: if s in reserved_serial_nos: invalid_serial_nos.append(s) if len(invalid_serial_nos): multiple_nos = 's' if len(invalid_serial_nos) > 1 else '' frappe.throw(_( "Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. \ Please select valid serial no.".format( d.idx, multiple_nos, frappe.bold(', '.join(invalid_serial_nos)))), title=_("Not Available")) else: if allow_negative_stock: return available_stock = get_stock_availability( d.item_code, d.warehouse) if not (flt(available_stock) > 0): frappe.throw(_( 'Row #{}: Item Code: {} is not available under warehouse {}.' .format(d.idx, frappe.bold(d.item_code), frappe.bold(d.warehouse))), title=_("Not Available")) elif flt(available_stock) < flt(d.qty): frappe.msgprint(_( 'Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. \ Available quantity {}.'.format(d.idx, frappe.bold(d.item_code), frappe.bold(d.warehouse), frappe.bold(d.qty))), title=_("Not Available"))
def validate_pos_reserved_serial_nos(self, item): serial_nos = get_serial_nos(item.serial_no) filters = {"item_code": item.item_code, "warehouse": item.warehouse} if item.batch_no: filters["batch_no"] = item.batch_no reserved_serial_nos = get_pos_reserved_serial_nos(filters) invalid_serial_nos = [ s for s in serial_nos if s in reserved_serial_nos ] bold_invalid_serial_nos = frappe.bold(', '.join(invalid_serial_nos)) if len(invalid_serial_nos) == 1: frappe.throw(_( "Row #{}: Serial No. {} has already been transacted into another POS Invoice. Please select valid serial no." ).format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable")) elif invalid_serial_nos: frappe.throw(_( "Row #{}: Serial Nos. {} has already been transacted into another POS Invoice. Please select valid serial no." ).format(item.idx, bold_invalid_serial_nos), title=_("Item Unavailable"))