validate over-return of stock for sales purchase return
This commit is contained in:
parent
0a1ac4090c
commit
87052b366b
@ -66,6 +66,17 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
if (this.frm.doc.docstatus==1) {
|
||||
this.show_stock_ledger();
|
||||
}
|
||||
|
||||
if(this.frm.doc.docstatus === 1 && wn.boot.profile.can_create("Journal Voucher")) {
|
||||
if(this.frm.doc.purpose === "Sales Return") {
|
||||
this.frm.add_custom_button("Make Credit Note", this.make_return_jv);
|
||||
this.add_excise_button();
|
||||
} else if(this.frm.doc.purpose === "Purchase Return") {
|
||||
this.frm.add_custom_button("Make Debit Note", this.make_return_jv);
|
||||
this.add_excise_button();
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
on_submit: function() {
|
||||
@ -143,6 +154,29 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add_excise_button: function() {
|
||||
if(wn.boot.control_panel.country === "India")
|
||||
this.frm.add_custom_button("Make Excise Invoice", function() {
|
||||
var excise = wn.model.make_new_doc_and_get_name('Journal Voucher');
|
||||
excise = locals['Journal Voucher'][excise];
|
||||
excise.voucher_type = 'Excise Voucher';
|
||||
loaddoc('Journal Voucher', excise.name);
|
||||
});
|
||||
},
|
||||
|
||||
make_return_jv: function() {
|
||||
this.frm.call({
|
||||
method: "make_return_jv",
|
||||
args: {
|
||||
stock_entry: this.frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
console.log(r);
|
||||
loaddoc("Journal Voucher", r.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
@ -29,6 +29,7 @@ import json
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
class NotUpdateStockError(webnotes.ValidationError): pass
|
||||
class StockOverReturnError(webnotes.ValidationError): pass
|
||||
|
||||
from controllers.accounts_controller import AccountsController
|
||||
|
||||
@ -278,32 +279,24 @@ class DocType(AccountsController):
|
||||
|
||||
def validate_return_reference_doc(self):
|
||||
"""validate item with reference doc"""
|
||||
ref_doclist = parentfields = None
|
||||
ref = get_return_reference_details(self.doc.fields)
|
||||
|
||||
# get ref_doclist
|
||||
if self.doc.purpose in return_map:
|
||||
for fieldname, val in return_map[self.doc.purpose].items():
|
||||
if self.doc.fields.get(fieldname):
|
||||
ref_doclist = webnotes.get_doclist(val[0], self.doc.fields[fieldname])
|
||||
parentfields = val[1]
|
||||
|
||||
if ref_doclist:
|
||||
if ref.doclist:
|
||||
# validate docstatus
|
||||
if ref_doclist[0].docstatus != 1:
|
||||
webnotes.msgprint(_(ref_doclist[0].doctype) + ' "' + ref_doclist[0].name + '": '
|
||||
if ref.doclist[0].docstatus != 1:
|
||||
webnotes.msgprint(_(ref.doclist[0].doctype) + ' "' + ref.doclist[0].name + '": '
|
||||
+ _("Status should be Submitted"), raise_exception=webnotes.InvalidStatusError)
|
||||
|
||||
|
||||
# update stock check
|
||||
if ref_doclist[0].doctype == "Sales Invoice" and (cint(ref_doclist[0].is_pos) != 1 \
|
||||
or cint(ref_doclist[0].update_stock) != 1):
|
||||
webnotes.msgprint(_(ref_doclist[0].doctype) + ' "' + ref_doclist[0].name + '": '
|
||||
if ref.doclist[0].doctype == "Sales Invoice" and (cint(ref.doclist[0].is_pos) != 1 \
|
||||
or cint(ref.doclist[0].update_stock) != 1):
|
||||
webnotes.msgprint(_(ref.doclist[0].doctype) + ' "' + ref.doclist[0].name + '": '
|
||||
+ _("Is POS and Update Stock should be checked."),
|
||||
raise_exception=NotUpdateStockError)
|
||||
|
||||
# posting date check
|
||||
ref_posting_datetime = "%s %s" % (cstr(ref_doclist[0].posting_date),
|
||||
cstr(ref_doclist[0].posting_time))
|
||||
ref_posting_datetime = "%s %s" % (cstr(ref.doclist[0].posting_date),
|
||||
cstr(ref.doclist[0].posting_time))
|
||||
this_posting_datetime = "%s %s" % (cstr(self.doc.posting_date),
|
||||
cstr(self.doc.posting_time))
|
||||
if this_posting_datetime < ref_posting_datetime:
|
||||
@ -312,18 +305,27 @@ class DocType(AccountsController):
|
||||
+ ": " + datetime_in_user_format(ref_posting_datetime),
|
||||
raise_exception=True)
|
||||
|
||||
stock_items = get_stock_items_for_return(ref_doclist, parentfields)
|
||||
stock_items = get_stock_items_for_return(ref.doclist, ref.parentfields)
|
||||
already_returned_item_qty = self.get_already_returned_item_qty(ref.fieldname)
|
||||
|
||||
for item in self.doclist.get({"parentfield": "mtn_details"}):
|
||||
# validate if item exists in the ref doclist and that it is a stock item
|
||||
if item.item_code not in stock_items:
|
||||
msgprint(_("Item") + ': "' + item.item_code + _("\" does not exist in ") +
|
||||
ref_doclist[0].doctype + ": " + ref_doclist[0].name,
|
||||
ref.doclist[0].doctype + ": " + ref.doclist[0].name,
|
||||
raise_exception=webnotes.DoesNotExistError)
|
||||
|
||||
# validate quantity <= ref item's qty
|
||||
ref_item = ref_doclist.getone({"item_code": item.item_code})
|
||||
self.validate_value("transfer_qty", "<=", ref_item.qty, item)
|
||||
# validate quantity <= ref item's qty - qty already returned
|
||||
ref_item = ref.doclist.getone({"item_code": item.item_code})
|
||||
returnable_qty = ref_item.qty - flt(already_returned_item_qty.get(item.item_code))
|
||||
self.validate_value("transfer_qty", "<=", returnable_qty, item,
|
||||
raise_exception=StockOverReturnError)
|
||||
|
||||
def get_already_returned_item_qty(self, ref_fieldname):
|
||||
return dict(webnotes.conn.sql("""select item_code, sum(transfer_qty) as qty
|
||||
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"""
|
||||
@ -670,7 +672,7 @@ class DocType(AccountsController):
|
||||
+ " " + _("Row #") + (" %d %s " % (mreq_item.idx, _("of")))
|
||||
+ _("Material Request") + (" - %s" % item.material_request),
|
||||
raise_exception=webnotes.MappingMismatchError)
|
||||
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_production_order_details(production_order):
|
||||
result = webnotes.conn.sql("""select bom_no,
|
||||
@ -700,16 +702,13 @@ def query_purchase_return_doc(doctype, txt, searchfield, start, page_len, filter
|
||||
|
||||
def query_return_item(doctype, txt, searchfield, start, page_len, filters):
|
||||
txt = txt.replace("%", "")
|
||||
|
||||
for fieldname, val in return_map[filters["purpose"]].items():
|
||||
if filters.get(fieldname):
|
||||
ref_doclist = webnotes.get_doclist(val[0], filters[fieldname])
|
||||
parentfields = val[1]
|
||||
|
||||
ref = get_return_reference_details(filters)
|
||||
|
||||
stock_items = get_stock_items_for_return(ref_doclist, parentfields)
|
||||
stock_items = get_stock_items_for_return(ref.doclist, ref.parentfields)
|
||||
|
||||
result = []
|
||||
for item in ref_doclist.get({"parentfield": ["in", parentfields]}):
|
||||
for item in ref.doclist.get({"parentfield": ["in", ref.parentfields]}):
|
||||
if item.item_code in stock_items:
|
||||
item.item_name = cstr(item.item_name)
|
||||
item.description = cstr(item.description)
|
||||
@ -738,6 +737,20 @@ def get_stock_items_for_return(ref_doclist, parentfields):
|
||||
|
||||
return stock_items
|
||||
|
||||
def get_return_reference_details(args):
|
||||
ref = webnotes._dict()
|
||||
|
||||
# get ref_doclist
|
||||
if args["purpose"] in return_map:
|
||||
for fieldname, val in return_map[args["purpose"]].items():
|
||||
if args.get(fieldname):
|
||||
ref.fieldname = fieldname
|
||||
ref.doclist = webnotes.get_doclist(val[0], args[fieldname])
|
||||
ref.parentfields = val[1]
|
||||
break
|
||||
|
||||
return ref
|
||||
|
||||
return_map = {
|
||||
"Sales Return": {
|
||||
# [Ref DocType, [Item tables' parentfields]]
|
||||
@ -748,3 +761,18 @@ return_map = {
|
||||
"purchase_receipt_no": ["Purchase Receipt", ["purchase_receipt_details"]]
|
||||
}
|
||||
}
|
||||
|
||||
def make_return_jv(stock_entry):
|
||||
jv = webnotes.bean({
|
||||
"doctype": "Journal Voucher",
|
||||
"__islocal": 1
|
||||
})
|
||||
|
||||
se = webnotes.bean("Stock Entry", stock_entry)
|
||||
|
||||
if not webnotes.response.get("docs"):
|
||||
webnotes.response["docs"] = []
|
||||
|
||||
webnotes.response["docs"] = jv.doclist
|
||||
|
||||
return jv.doc.name
|
@ -312,6 +312,23 @@ class TestStockEntry(unittest.TestCase):
|
||||
|
||||
self.assertEquals(actual_qty_1 - 5, actual_qty_2)
|
||||
|
||||
return pr.doc.name
|
||||
|
||||
def test_over_stock_return(self):
|
||||
from stock.doctype.stock_entry.stock_entry import StockOverReturnError
|
||||
|
||||
# out of 10, 5 gets returned
|
||||
pr_docname = self.test_purchase_receipt_return()
|
||||
|
||||
# submit purchase return - return another 6 qtys so that exception is raised
|
||||
se = webnotes.bean(copy=test_records[0])
|
||||
se.doc.purpose = "Purchase Return"
|
||||
se.doc.purchase_receipt_no = pr_docname
|
||||
se.doc.posting_date = "2013-03-01"
|
||||
se.doclist[1].qty = se.doclist[1].transfer_qty = 6
|
||||
se.doclist[1].s_warehouse = "_Test Warehouse"
|
||||
|
||||
self.assertRaises(StockOverReturnError, se.insert)
|
||||
|
||||
test_records = [
|
||||
[
|
||||
|
Loading…
x
Reference in New Issue
Block a user