Merged master into wsgi

This commit is contained in:
Anand Doshi
2013-10-10 16:04:40 +05:30
parent b604eddbfd
commit 373680bbae
33 changed files with 520 additions and 418 deletions

View File

@@ -186,7 +186,6 @@ class DocType(SellingController):
# create stock ledger entry
self.update_stock_ledger()
self.update_serial_nos()
self.credit_limit()
@@ -204,42 +203,12 @@ class DocType(SellingController):
self.update_prevdoc_status()
self.update_stock_ledger()
self.update_serial_nos(cancel=True)
webnotes.conn.set(self.doc, 'status', 'Cancelled')
self.cancel_packing_slips()
self.make_cancel_gl_entries()
def update_serial_nos(self, cancel=False):
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
update_serial_nos_after_submit(self, "Delivery Note", "delivery_note_details")
update_serial_nos_after_submit(self, "Delivery Note", "packing_details")
for table_fieldname in ("delivery_note_details", "packing_details"):
for d in self.doclist.get({"parentfield": table_fieldname}):
for serial_no in get_serial_nos(d.serial_no):
sr = webnotes.bean("Serial No", serial_no)
if cancel:
sr.doc.status = "Available"
for fieldname in ("warranty_expiry_date", "delivery_document_type",
"delivery_document_no", "delivery_date", "delivery_time", "customer",
"customer_name"):
sr.doc.fields[fieldname] = None
else:
sr.doc.delivery_document_type = "Delivery Note"
sr.doc.delivery_document_no = self.doc.name
sr.doc.delivery_date = self.doc.posting_date
sr.doc.delivery_time = self.doc.posting_time
sr.doc.customer = self.doc.customer
sr.doc.customer_name = self.doc.customer_name
if sr.doc.warranty_period:
sr.doc.warranty_expiry_date = add_days(cstr(self.doc.posting_date),
cint(sr.doc.warranty_period))
sr.doc.status = 'Delivered'
sr.save()
def validate_packed_qty(self):
"""
Validate that if packed qty exists, it should be equal to qty

View File

@@ -85,7 +85,6 @@ class DocType:
pr_bean = webnotes.bean("Purchase Receipt", pr)
pr_bean.run_method("update_ordered_qty", is_cancelled="Yes")
pr_bean.run_method("update_serial_nos", cancel=True)
webnotes.conn.sql("""delete from `tabStock Ledger Entry`
where voucher_type='Purchase Receipt' and voucher_no=%s""", pr)
@@ -97,5 +96,4 @@ class DocType:
pr_bean = webnotes.bean("Purchase Receipt", pr)
pr_bean.run_method("update_ordered_qty")
pr_bean.run_method("update_stock")
pr_bean.run_method("update_serial_nos")
pr_bean.run_method("make_gl_entries")
pr_bean.run_method("make_gl_entries")

View File

@@ -68,22 +68,14 @@ class DocType(BuyingController):
self.doc.status = "Draft"
import utilities
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
"Cancelled"])
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", "Cancelled"])
# restrict material request type
self.validate_value("material_request_type", "in", ["Purchase", "Transfer"])
# Get Purchase Common Obj
pc_obj = get_obj(dt='Purchase Common')
# Validate for items
pc_obj.validate_for_items(self)
# Validate qty against SO
self.validate_qty_against_so()
self.validate_qty_against_so()
def update_bin(self, is_submit, is_stopped):
""" Update Quantity Requested for Purchase in Bin for Material Request of type 'Purchase'"""

View File

@@ -246,26 +246,12 @@ class DocType(BuyingController):
self.update_stock()
self.update_serial_nos()
from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
update_serial_nos_after_submit(self, "Purchase Receipt", "purchase_receipt_details")
purchase_controller.update_last_purchase_rate(self, 1)
self.make_gl_entries()
def update_serial_nos(self, cancel=False):
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
update_serial_nos_after_submit(self, "Purchase Receipt", "purchase_receipt_details")
for d in self.doclist.get({"parentfield": "purchase_receipt_details"}):
for serial_no in get_serial_nos(d.serial_no):
sr = webnotes.bean("Serial No", serial_no)
if cancel:
sr.doc.supplier = None
sr.doc.supplier_name = None
else:
sr.doc.supplier = self.doc.supplier
sr.doc.supplier_name = self.doc.supplier_name
sr.save()
def check_next_docstatus(self):
submit_rv = webnotes.conn.sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % (self.doc.name))
@@ -292,7 +278,6 @@ class DocType(BuyingController):
self.update_ordered_qty()
self.update_stock()
self.update_serial_nos(cancel=True)
self.update_prevdoc_status()
pc_obj.update_last_purchase_rate(self, 0)
@@ -308,7 +293,7 @@ class DocType(BuyingController):
def get_rate(self,arg):
return get_obj('Purchase Common').get_rate(arg,self)
def get_gl_entries_for_stock(self, warehouse_account=None):
against_stock_account = self.get_company_default("stock_received_but_not_billed")

View File

@@ -4,14 +4,22 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, getdate, nowdate
from webnotes.utils import cint, getdate, nowdate, cstr, flt, add_days
import datetime
from webnotes import msgprint, _
from webnotes import msgprint, _, ValidationError
from controllers.stock_controller import StockController
class SerialNoCannotCreateDirectError(webnotes.ValidationError): pass
class SerialNoCannotCannotChangeError(webnotes.ValidationError): pass
class SerialNoCannotCreateDirectError(ValidationError): pass
class SerialNoCannotCannotChangeError(ValidationError): pass
class SerialNoNotRequiredError(ValidationError): pass
class SerialNoRequiredError(ValidationError): pass
class SerialNoQtyError(ValidationError): pass
class SerialNoItemError(ValidationError): pass
class SerialNoWarehouseError(ValidationError): pass
class SerialNoStatusError(ValidationError): pass
class SerialNoNotExistsError(ValidationError): pass
class SerialNoDuplicateError(ValidationError): pass
class DocType(StockController):
def __init__(self, doc, doclist=None):
@@ -21,13 +29,18 @@ class DocType(StockController):
def validate(self):
if self.doc.fields.get("__islocal") and self.doc.warehouse:
webnotes.throw(_("New Serial No cannot have Warehouse. Warehouse must be set by Stock Entry or Purchase Receipt"),
SerialNoCannotCreateDirectError)
webnotes.throw(_("New Serial No cannot have Warehouse. Warehouse must be \
set by Stock Entry or Purchase Receipt"), SerialNoCannotCreateDirectError)
self.validate_warranty_status()
self.validate_amc_status()
self.validate_warehouse()
self.validate_item()
if self.via_stock_ledger:
self.set_status()
self.set_purchase_details()
self.set_sales_details()
def validate_amc_status(self):
"""
@@ -41,7 +54,8 @@ class DocType(StockController):
validate warranty status
"""
if (self.doc.maintenance_status == 'Out of Warranty' and self.doc.warranty_expiry_date and getdate(self.doc.warranty_expiry_date) >= datetime.date.today()) or (self.doc.maintenance_status == 'Under Warranty' and (not self.doc.warranty_expiry_date or getdate(self.doc.warranty_expiry_date) < datetime.date.today())):
msgprint("Warranty expiry date and maintenance status mismatch. Please verify", raise_exception=1)
msgprint("Warranty expiry date and maintenance status mismatch. Please verify",
raise_exception=1)
def validate_warehouse(self):
@@ -49,10 +63,11 @@ class DocType(StockController):
item_code, warehouse = webnotes.conn.get_value("Serial No",
self.doc.name, ["item_code", "warehouse"])
if item_code != self.doc.item_code:
webnotes.throw(_("Item Code cannot be changed for Serial No."), SerialNoCannotCannotChangeError)
webnotes.throw(_("Item Code cannot be changed for Serial No."),
SerialNoCannotCannotChangeError)
if not self.via_stock_ledger and warehouse != self.doc.warehouse:
webnotes.throw(_("Warehouse cannot be changed for Serial No."), SerialNoCannotCannotChangeError)
webnotes.throw(_("Warehouse cannot be changed for Serial No."),
SerialNoCannotCannotChangeError)
def validate_item(self):
"""
@@ -67,16 +82,89 @@ class DocType(StockController):
self.doc.item_name = item.item_name
self.doc.brand = item.brand
self.doc.warranty_period = item.warranty_period
def set_status(self):
last_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where (serial_no like %s or serial_no like %s or serial_no=%s)
and item_code=%s and ifnull(is_cancelled, 'No')='No'
order by name desc limit 1""",
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
self.doc.item_code), as_dict=1)
if last_sle:
if last_sle[0].voucher_type == "Stock Entry":
document_type = webnotes.conn.get_value("Stock Entry", last_sle[0].voucher_no,
"purpose")
else:
document_type = last_sle[0].voucher_type
if last_sle[0].actual_qty > 0:
if document_type == "Sales Return":
self.doc.status = "Sales Returned"
else:
self.doc.status = "Available"
else:
if document_type == "Purchase Return":
self.doc.status = "Purchase Returned"
elif last_sle[0].voucher_type in ("Delivery Note", "Sales Invoice"):
self.doc.status = "Delivered"
else:
self.doc.status = "Not Available"
def set_purchase_details(self):
purchase_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where (serial_no like %s or serial_no like %s or serial_no=%s)
and item_code=%s and actual_qty > 0
and ifnull(is_cancelled, 'No')='No' order by name asc limit 1""",
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
self.doc.item_code), as_dict=1)
if purchase_sle:
self.doc.purchase_document_type = purchase_sle[0].voucher_type
self.doc.purchase_document_no = purchase_sle[0].voucher_no
self.doc.purchase_date = purchase_sle[0].posting_date
self.doc.purchase_time = purchase_sle[0].posting_time
self.doc.purchase_rate = purchase_sle[0].incoming_rate
if purchase_sle[0].voucher_type == "Purchase Receipt":
self.doc.supplier, self.doc.supplier_name = \
webnotes.conn.get_value("Purchase Receipt", purchase_sle[0].voucher_no,
["supplier", "supplier_name"])
else:
for fieldname in ("purchase_document_type", "purchase_document_no",
"purchase_date", "purchase_time", "purchase_rate", "supplier", "supplier_name"):
self.doc.fields[fieldname] = None
def set_sales_details(self):
delivery_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where (serial_no like %s or serial_no like %s or serial_no=%s)
and item_code=%s and actual_qty<0
and voucher_type in ('Delivery Note', 'Sales Invoice')
and ifnull(is_cancelled, 'No')='No' order by name desc limit 1""",
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
self.doc.item_code), as_dict=1)
if delivery_sle:
self.doc.delivery_document_type = delivery_sle[0].voucher_type
self.doc.delivery_document_no = delivery_sle[0].voucher_no
self.doc.delivery_date = delivery_sle[0].posting_date
self.doc.delivery_time = delivery_sle[0].posting_time
self.doc.customer, self.doc.customer_name = \
webnotes.conn.get_value(delivery_sle[0].voucher_type, delivery_sle[0].voucher_no,
["customer", "customer_name"])
if self.doc.warranty_period:
self.doc.warranty_expiry_date = add_days(cstr(delivery_sle[0].posting_date),
cint(self.doc.warranty_period))
else:
for fieldname in ("delivery_document_type", "delivery_document_no",
"delivery_date", "delivery_time", "customer", "customer_name",
"warranty_expiry_date"):
self.doc.fields[fieldname] = None
def on_trash(self):
if self.doc.status == 'Delivered':
msgprint("Cannot trash Serial No : %s as it is already Delivered" % (self.doc.name), raise_exception = 1)
webnotes.throw(_("Delivered Serial No ") + self.doc.name + _(" can not be deleted"))
if self.doc.warehouse:
webnotes.throw(_("Cannot delete Serial No in warehouse. First remove from warehouse, then delete.") + \
": " + self.doc.name)
def on_cancel(self):
self.on_trash()
webnotes.throw(_("Cannot delete Serial No in warehouse. \
First remove from warehouse, then delete.") + ": " + self.doc.name)
def on_rename(self, new, old, merge=False):
"""rename serial_no text fields"""
@@ -93,3 +181,106 @@ class DocType(StockController):
webnotes.conn.sql("""update `tab%s` set serial_no = %s
where name=%s""" % (dt[0], '%s', '%s'),
('\n'.join(serial_nos), item[0]))
def process_serial_no(sle):
item_det = get_item_details(sle.item_code)
validate_serial_no(sle, item_det)
update_serial_nos(sle, item_det)
def validate_serial_no(sle, item_det):
if item_det.has_serial_no=="No":
if sle.serial_no:
webnotes.throw(_("Serial Number should be blank for Non Serialized Item" + ": "
+ sle.item_code), SerialNoNotRequiredError)
else:
if sle.serial_no:
serial_nos = get_serial_nos(sle.serial_no)
if cint(sle.actual_qty) != flt(sle.actual_qty):
webnotes.throw(_("Serial No qty cannot be a fraction") + \
(": %s (%s)" % (sle.item_code, sle.actual_qty)))
if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)):
webnotes.throw(_("Serial Nos do not match with qty") + \
(": %s (%s)" % (sle.item_code, sle.actual_qty)), SerialNoQtyError)
for serial_no in serial_nos:
if webnotes.conn.exists("Serial No", serial_no):
sr = webnotes.bean("Serial No", serial_no)
if sr.doc.item_code!=sle.item_code:
webnotes.throw(_("Serial No does not belong to Item") +
(": %s (%s)" % (sle.item_code, serial_no)), SerialNoItemError)
if sr.doc.warehouse and sle.actual_qty > 0:
webnotes.throw(_("Same Serial No") + ": " + sr.doc.name +
_(" can not be received twice"), SerialNoDuplicateError)
if sle.actual_qty < 0:
if sr.doc.warehouse!=sle.warehouse:
webnotes.throw(_("Serial No") + ": " + serial_no +
_(" does not belong to Warehouse") + ": " + sle.warehouse,
SerialNoWarehouseError)
if sle.voucher_type in ("Delivery Note", "Sales Invoice") \
and sr.doc.status != "Available":
webnotes.throw(_("Serial No status must be 'Available' to Deliver")
+ ": " + serial_no, SerialNoStatusError)
elif sle.actual_qty < 0:
# transfer out
webnotes.throw(_("Serial No must exist to transfer out.") + \
": " + serial_no, SerialNoNotExistsError)
elif not item_det.serial_no_series:
webnotes.throw(_("Serial Number Required for Serialized Item" + ": "
+ sle.item_code), SerialNoRequiredError)
def update_serial_nos(sle, item_det):
if sle.serial_no:
serial_nos = get_serial_nos(sle.serial_no)
for serial_no in serial_nos:
if webnotes.conn.exists("Serial No", serial_no):
sr = webnotes.bean("Serial No", serial_no)
sr.make_controller().via_stock_ledger = True
sr.doc.warehouse = sle.warehouse if sle.actual_qty > 0 else None
sr.save()
elif sle.actual_qty > 0:
make_serial_no(serial_no, sle)
elif sle.actual_qty > 0 and item_det.serial_no_series:
from webnotes.model.doc import make_autoname
serial_nos = []
for i in xrange(cint(sle.actual_qty)):
serial_nos.append(make_serial_no(make_autoname(item_det.serial_no_series), sle))
sle.serial_no = "\n".join(serial_nos)
def get_item_details(item_code):
return webnotes.conn.sql("""select name, has_batch_no, docstatus,
is_stock_item, has_serial_no, serial_no_series
from tabItem where name=%s""", item_code, as_dict=True)[0]
def get_serial_nos(serial_no):
return [s.strip() for s in cstr(serial_no).strip().replace(',', '\n').split('\n') if s.strip()]
def make_serial_no(serial_no, sle):
sr = webnotes.new_bean("Serial No")
sr.doc.serial_no = serial_no
sr.doc.item_code = sle.item_code
sr.make_controller().via_stock_ledger = True
sr.insert()
sr.doc.warehouse = sle.warehouse
sr.doc.status = "Available"
sr.save()
webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name)
return sr.doc.name
def update_serial_nos_after_submit(controller, parenttype, parentfield):
if not hasattr(webnotes, "new_stock_ledger_entries"):
return
for d in controller.doclist.get({"parentfield": parentfield}):
serial_no = None
for sle in webnotes.new_stock_ledger_entries:
if sle.voucher_detail_no==d.name:
serial_no = sle.serial_no
break
if d.serial_no != serial_no:
d.serial_no = serial_no
webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no)

View File

@@ -51,13 +51,15 @@ class DocType(StockController):
def on_submit(self):
self.update_stock_ledger()
self.update_serial_no(1)
from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
update_serial_nos_after_submit(self, "Stock Entry", "mtn_details")
self.update_production_order(1)
self.make_gl_entries()
def on_cancel(self):
self.update_stock_ledger()
self.update_serial_no(0)
self.update_production_order(0)
self.make_cancel_gl_entries()
@@ -293,24 +295,6 @@ class DocType(StockController):
from `tabStock Entry Detail` where parent in (
select name from `tabStock Entry` where `%s`=%s and docstatus=1)
group by item_code""" % (ref_fieldname, "%s"), (self.doc.fields.get(ref_fieldname),)))
def update_serial_no(self, is_submit):
"""Create / Update Serial No"""
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
update_serial_nos_after_submit(self, "Stock Entry", "mtn_details")
for d in getlist(self.doclist, 'mtn_details'):
for serial_no in get_serial_nos(d.serial_no):
if self.doc.purpose == 'Purchase Return':
sr = webnotes.bean("Serial No", serial_no)
sr.doc.status = "Purchase Returned" if is_submit else "Available"
sr.save()
if self.doc.purpose == "Sales Return":
sr = webnotes.bean("Serial No", serial_no)
sr.doc.status = "Sales Returned" if is_submit else "Delivered"
sr.save()
def update_stock_ledger(self):
sl_entries = []

View File

@@ -7,7 +7,7 @@
from __future__ import unicode_literals
import webnotes, unittest
from webnotes.utils import flt
from stock.doctype.stock_ledger_entry.stock_ledger_entry import *
from stock.doctype.serial_no.serial_no import *
from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
@@ -48,7 +48,7 @@ class TestStockEntry(unittest.TestCase):
webnotes.bean("Profile", "test2@example.com").get_controller()\
.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
from stock.doctype.stock_ledger_entry.stock_ledger_entry import InvalidWarehouseCompany
from stock.utils import InvalidWarehouseCompany
st1 = webnotes.bean(copy=test_records[0])
st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1"
st1.insert()
@@ -721,6 +721,18 @@ class TestStockEntry(unittest.TestCase):
se.insert()
self.assertRaises(SerialNoNotExistsError, se.submit)
def test_serial_duplicate(self):
self._clear_stock_account_balance()
self.test_serial_by_series()
se = webnotes.bean(copy=test_records[0])
se.doclist[1].item_code = "_Test Serialized Item With Series"
se.doclist[1].qty = 1
se.doclist[1].serial_no = "ABCD00001"
se.doclist[1].transfer_qty = 1
se.insert()
self.assertRaises(SerialNoDuplicateError, se.submit)
def test_serial_by_series(self):
self._clear_stock_account_balance()
se = make_serialized_item()

View File

@@ -3,29 +3,17 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint, ValidationError
from webnotes import _, msgprint
from webnotes.utils import cint, flt, getdate, cstr
from webnotes.model.controller import DocListController
class InvalidWarehouseCompany(ValidationError): pass
class SerialNoNotRequiredError(ValidationError): pass
class SerialNoRequiredError(ValidationError): pass
class SerialNoQtyError(ValidationError): pass
class SerialNoItemError(ValidationError): pass
class SerialNoWarehouseError(ValidationError): pass
class SerialNoStatusError(ValidationError): pass
class SerialNoNotExistsError(ValidationError): pass
def get_serial_nos(serial_no):
return [s.strip() for s in cstr(serial_no).strip().replace(',', '\n').split('\n') if s.strip()]
class DocType(DocListController):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
def validate(self):
from stock.utils import validate_warehouse_user
from stock.utils import validate_warehouse_user, validate_warehouse_company
if not hasattr(webnotes, "new_stock_ledger_entries"):
webnotes.new_stock_ledger_entries = []
@@ -33,7 +21,7 @@ class DocType(DocListController):
self.validate_mandatory()
self.validate_item()
validate_warehouse_user(self.doc.warehouse)
self.validate_warehouse_company()
validate_warehouse_company(self.doc.warehouse, self.doc.company)
self.scrub_posting_time()
from accounts.utils import validate_fiscal_year
@@ -42,7 +30,9 @@ class DocType(DocListController):
def on_submit(self):
self.check_stock_frozen_date()
self.actual_amt_check()
self.validate_serial_no()
from stock.doctype.serial_no.serial_no import process_serial_no
process_serial_no(self.doc)
#check for item quantity available in stock
def actual_amt_check(self):
@@ -63,13 +53,6 @@ class DocType(DocListController):
as on %(posting_date)s %(posting_time)s""" % self.doc.fields)
sself.doc.fields.pop('batch_bal')
def validate_warehouse_company(self):
warehouse_company = webnotes.conn.get_value("Warehouse", self.doc.warehouse, "company")
if warehouse_company and warehouse_company != self.doc.company:
webnotes.msgprint(_("Warehouse does not belong to company.") + " (" + \
self.doc.warehouse + ", " + self.doc.company +")",
raise_exception=InvalidWarehouseCompany)
def validate_mandatory(self):
mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company']
@@ -81,7 +64,10 @@ class DocType(DocListController):
msgprint("Warehouse: '%s' does not exist in the system. Please check." % self.doc.fields.get(k), raise_exception = 1)
def validate_item(self):
item_det = self.get_item_details()
item_det = webnotes.conn.sql("""select name, has_batch_no, docstatus,
is_stock_item, has_serial_no, serial_no_series
from tabItem where name=%s""",
self.doc.item_code, as_dict=True)[0]
if item_det.is_stock_item != 'Yes':
webnotes.throw("""Item: "%s" is not a Stock Item.""" % self.doc.item_code)
@@ -99,95 +85,6 @@ class DocType(DocListController):
if not self.doc.stock_uom:
self.doc.stock_uom = item_det.stock_uom
def get_item_details(self):
return webnotes.conn.sql("""select name, has_batch_no, docstatus,
is_stock_item, has_serial_no, serial_no_series
from tabItem where name=%s""",
self.doc.item_code, as_dict=True)[0]
def validate_serial_no(self):
item_det = self.get_item_details()
if item_det.has_serial_no=="No":
if self.doc.serial_no:
webnotes.throw(_("Serial Number should be blank for Non Serialized Item" + ": " + self.doc.item),
SerialNoNotRequiredError)
else:
if self.doc.serial_no:
serial_nos = get_serial_nos(self.doc.serial_no)
if cint(self.doc.actual_qty) != flt(self.doc.actual_qty):
webnotes.throw(_("Serial No qty cannot be a fraction") + \
(": %s (%s)" % (self.doc.item_code, self.doc.actual_qty)))
if len(serial_nos) and len(serial_nos) != abs(cint(self.doc.actual_qty)):
webnotes.throw(_("Serial Nos do not match with qty") + \
(": %s (%s)" % (self.doc.item_code, self.doc.actual_qty)), SerialNoQtyError)
# check serial no exists, if yes then source
for serial_no in serial_nos:
if webnotes.conn.exists("Serial No", serial_no):
sr = webnotes.bean("Serial No", serial_no)
if sr.doc.item_code!=self.doc.item_code:
webnotes.throw(_("Serial No does not belong to Item") + \
(": %s (%s)" % (self.doc.item_code, serial_no)), SerialNoItemError)
sr.make_controller().via_stock_ledger = True
if self.doc.actual_qty < 0:
if sr.doc.warehouse!=self.doc.warehouse:
webnotes.throw(_("Serial No") + ": " + serial_no +
_(" does not belong to Warehouse") + ": " + self.doc.warehouse,
SerialNoWarehouseError)
if self.doc.voucher_type in ("Delivery Note", "Sales Invoice") \
and sr.doc.status != "Available":
webnotes.throw(_("Serial No status must be 'Available' to Deliver")
+ ": " + serial_no, SerialNoStatusError)
sr.doc.warehouse = None
sr.save()
else:
sr.doc.warehouse = self.doc.warehouse
sr.save()
else:
if self.doc.actual_qty < 0:
# transfer out
webnotes.throw(_("Serial No must exist to transfer out.") + \
": " + serial_no, SerialNoNotExistsError)
else:
# transfer in
self.make_serial_no(serial_no)
else:
if item_det.serial_no_series:
from webnotes.model.doc import make_autoname
serial_nos = []
for i in xrange(cint(self.doc.actual_qty)):
serial_nos.append(self.make_serial_no(make_autoname(item_det.serial_no_series)))
self.doc.serial_no = "\n".join(serial_nos)
else:
webnotes.throw(_("Serial Number Required for Serialized Item" + ": " + self.doc.item),
SerialNoRequiredError)
def make_serial_no(self, serial_no):
sr = webnotes.new_bean("Serial No")
sr.doc.serial_no = serial_no
sr.doc.item_code = self.doc.item_code
sr.doc.purchase_rate = self.doc.incoming_rate
sr.doc.purchase_document_type = self.doc.voucher_type
sr.doc.purchase_document_no = self.doc.voucher_no
sr.doc.purchase_date = self.doc.posting_date
sr.doc.purchase_time = self.doc.posting_time
sr.make_controller().via_stock_ledger = True
sr.insert()
# set warehouse
sr.doc.warehouse = self.doc.warehouse
sr.doc.status = "Available"
sr.save()
webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name)
return sr.doc.name
def check_stock_frozen_date(self):
stock_frozen_upto = webnotes.conn.get_value('Stock Settings', None, 'stock_frozen_upto') or ''
if stock_frozen_upto:
@@ -199,21 +96,6 @@ class DocType(DocListController):
if not self.doc.posting_time or self.doc.posting_time == '00:0':
self.doc.posting_time = '00:00'
def update_serial_nos_after_submit(controller, parenttype, parentfield):
if not hasattr(webnotes, "new_stock_ledger_entries"):
return
for d in controller.doclist.get({"parentfield": parentfield}):
serial_no = None
for sle in webnotes.new_stock_ledger_entries:
if sle.voucher_detail_no==d.name:
serial_no = sle.serial_no
break
if d.serial_no != serial_no:
d.serial_no = serial_no
webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no)
def on_doctype_update():
if not webnotes.conn.sql("""show index from `tabStock Ledger Entry`
where Key_name="posting_sort_index" """):

View File

@@ -9,6 +9,7 @@ from webnotes.defaults import get_global_default
from webnotes.utils.email_lib import sendmail
class UserNotAllowedForWarehouse(webnotes.ValidationError): pass
class InvalidWarehouseCompany(webnotes.ValidationError): pass
def get_stock_balance_on(warehouse, posting_date=None):
if not posting_date: posting_date = nowdate()
@@ -216,6 +217,12 @@ def validate_warehouse_user(warehouse):
if warehouse_users and not (webnotes.session.user in warehouse_users):
webnotes.throw(_("Not allowed entry in Warehouse") \
+ ": " + warehouse, UserNotAllowedForWarehouse)
def validate_warehouse_company(warehouse, company):
warehouse_company = webnotes.conn.get_value("Warehouse", warehouse, "company")
if warehouse_company and warehouse_company != company:
webnotes.msgprint(_("Warehouse does not belong to company.") + " (" + \
warehouse + ", " + company +")", raise_exception=InvalidWarehouseCompany)
def get_sales_bom_buying_amount(item_code, warehouse, voucher_type, voucher_no, voucher_detail_no,
stock_ledger_entries, item_sales_bom):