completed sales purchase return as part of stock entry
This commit is contained in:
parent
6230aa9292
commit
ab7b7c2974
@ -133,7 +133,7 @@ class DocType(SellingController):
|
|||||||
super(DocType, self).validate()
|
super(DocType, self).validate()
|
||||||
|
|
||||||
import utilities
|
import utilities
|
||||||
utilities.validate_status(self.doc.status, ["Draft", "submitted", "Cancelled"])
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Cancelled"])
|
||||||
|
|
||||||
self.so_required()
|
self.so_required()
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
|
@ -60,6 +60,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
|
var me = this;
|
||||||
erpnext.hide_naming_series();
|
erpnext.hide_naming_series();
|
||||||
this.toggle_related_fields(this.frm.doc);
|
this.toggle_related_fields(this.frm.doc);
|
||||||
this.toggle_enable_bom();
|
this.toggle_enable_bom();
|
||||||
@ -67,12 +68,13 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
this.show_stock_ledger();
|
this.show_stock_ledger();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.frm.doc.docstatus === 1 && wn.boot.profile.can_create("Journal Voucher")) {
|
if(this.frm.doc.docstatus === 1 &&
|
||||||
|
wn.boot.profile.can_create.indexOf("Journal Voucher")!==-1) {
|
||||||
if(this.frm.doc.purpose === "Sales Return") {
|
if(this.frm.doc.purpose === "Sales Return") {
|
||||||
this.frm.add_custom_button("Make Credit Note", this.make_return_jv);
|
this.frm.add_custom_button("Make Credit Note", function() { me.make_return_jv(); });
|
||||||
this.add_excise_button();
|
this.add_excise_button();
|
||||||
} else if(this.frm.doc.purpose === "Purchase Return") {
|
} else if(this.frm.doc.purpose === "Purchase Return") {
|
||||||
this.frm.add_custom_button("Make Debit Note", this.make_return_jv);
|
this.frm.add_custom_button("Make Debit Note", function() { me.make_return_jv(); });
|
||||||
this.add_excise_button();
|
this.add_excise_button();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,8 +174,17 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
stock_entry: this.frm.doc.name
|
stock_entry: this.frm.doc.name
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
console.log(r);
|
if(!r.exc) {
|
||||||
loaddoc("Journal Voucher", r.message);
|
var jv_name = wn.model.make_new_doc_and_get_name('Journal Voucher');
|
||||||
|
var jv = locals["Journal Voucher"][jv_name];
|
||||||
|
$.extend(jv, r.message[0]);
|
||||||
|
$.each(r.message.slice(1), function(i, jvd) {
|
||||||
|
var child = wn.model.add_child(jv, "Journal Voucher Detail", "entries");
|
||||||
|
$.extend(child, jvd);
|
||||||
|
});
|
||||||
|
loaddoc("Journal Voucher", jv_name);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -25,7 +25,6 @@ from webnotes import msgprint, _
|
|||||||
from stock.utils import get_incoming_rate
|
from stock.utils import get_incoming_rate
|
||||||
from stock.stock_ledger import get_previous_sle
|
from stock.stock_ledger import get_previous_sle
|
||||||
import json
|
import json
|
||||||
from accounts.utils import get_balance_on
|
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
sql = webnotes.conn.sql
|
||||||
|
|
||||||
@ -297,7 +296,7 @@ class DocType(AccountsController):
|
|||||||
|
|
||||||
# posting date check
|
# posting date check
|
||||||
ref_posting_datetime = "%s %s" % (cstr(ref.doclist[0].posting_date),
|
ref_posting_datetime = "%s %s" % (cstr(ref.doclist[0].posting_date),
|
||||||
cstr(ref.doclist[0].posting_time))
|
cstr(ref.doclist[0].posting_time) or "00:00:00")
|
||||||
this_posting_datetime = "%s %s" % (cstr(self.doc.posting_date),
|
this_posting_datetime = "%s %s" % (cstr(self.doc.posting_date),
|
||||||
cstr(self.doc.posting_time))
|
cstr(self.doc.posting_time))
|
||||||
if this_posting_datetime < ref_posting_datetime:
|
if this_posting_datetime < ref_posting_datetime:
|
||||||
@ -779,13 +778,30 @@ def make_return_jv(stock_entry):
|
|||||||
result = make_return_jv_from_purchase_receipt(se, ref)
|
result = make_return_jv_from_purchase_receipt(se, ref)
|
||||||
|
|
||||||
# create jv doclist and fetch balance for each unique row item
|
# create jv doclist and fetch balance for each unique row item
|
||||||
|
jv_list = [{
|
||||||
|
"__islocal": 1,
|
||||||
|
"doctype": "Journal Voucher",
|
||||||
|
"posting_date": se.doc.posting_date,
|
||||||
|
"voucher_type": se.doc.purpose == "Sales Return" and "Credit Note" or "Debit Note",
|
||||||
|
"fiscal_year": se.doc.fiscal_year,
|
||||||
|
"company": se.doc.company
|
||||||
|
}]
|
||||||
|
|
||||||
if not webnotes.response.get("docs"):
|
from accounts.utils import get_balance_on
|
||||||
webnotes.response["docs"] = []
|
for r in result:
|
||||||
|
jv_list.append({
|
||||||
|
"__islocal": 1,
|
||||||
|
"doctype": "Journal Voucher Detail",
|
||||||
|
"parentfield": "entries",
|
||||||
|
"account": r.get("account"),
|
||||||
|
"debit": r.get("debit"),
|
||||||
|
"credit": r.get("credit"),
|
||||||
|
"against_invoice": r.get("against_invoice"),
|
||||||
|
"against_voucher": r.get("against_voucher"),
|
||||||
|
"balance": get_balance_on(r.get("account"), se.doc.posting_date)
|
||||||
|
})
|
||||||
|
|
||||||
webnotes.response["docs"] = jv.doclist
|
return jv_list
|
||||||
|
|
||||||
return jv.doc.name
|
|
||||||
|
|
||||||
def make_return_jv_from_sales_invoice(se, ref):
|
def make_return_jv_from_sales_invoice(se, ref):
|
||||||
# customer account entry
|
# customer account entry
|
||||||
@ -833,12 +849,10 @@ def make_return_jv_from_delivery_note(se, ref):
|
|||||||
ref.doclist[0].name)
|
ref.doclist[0].name)
|
||||||
|
|
||||||
if not invoices_against_delivery:
|
if not invoices_against_delivery:
|
||||||
item_codes = [item.item_code for item in se.doclist.get({"parentfield": "mtn_details"})]
|
sales_orders_against_delivery = [d.prevdoc_docname for d in
|
||||||
sales_orders_against_delivery = [d.prev_docname for d in
|
ref.doclist.get({"prevdoc_doctype": "Sales Order"}) if d.prevdoc_docname]
|
||||||
ref.doclist.get({"prev_doctype": "Sales Order"})
|
|
||||||
if d.prev_docname and d.item_code in item_codes]
|
|
||||||
|
|
||||||
invoices_against_delivery = get_invoice_list("Sales Order Item", "sales_order",
|
invoices_against_delivery = get_invoice_list("Sales Invoice Item", "sales_order",
|
||||||
sales_orders_against_delivery)
|
sales_orders_against_delivery)
|
||||||
|
|
||||||
against_invoice = {}
|
against_invoice = {}
|
||||||
@ -846,8 +860,10 @@ def make_return_jv_from_delivery_note(se, ref):
|
|||||||
for se_item in se.doclist.get({"parentfield": "mtn_details"}):
|
for se_item in se.doclist.get({"parentfield": "mtn_details"}):
|
||||||
pending = se_item.transfer_qty
|
pending = se_item.transfer_qty
|
||||||
for sales_invoice in invoices_against_delivery:
|
for sales_invoice in invoices_against_delivery:
|
||||||
si_doclist = webnotes.get_doclist("Sales Invoice", sales_invoice)
|
si = webnotes.bean("Sales Invoice", sales_invoice)
|
||||||
ref_item = si_doclist.get({"item_code": se_item.item_code})
|
si.run_method("make_packing_list")
|
||||||
|
ref_item = si.doclist.get({"item_code": se_item.item_code})
|
||||||
|
|
||||||
if not ref_item:
|
if not ref_item:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -860,12 +876,12 @@ def make_return_jv_from_delivery_note(se, ref):
|
|||||||
transfer_qty = pending
|
transfer_qty = pending
|
||||||
pending = 0
|
pending = 0
|
||||||
|
|
||||||
account, debit = get_sales_account_and_amount_from_item(si_doclist, ref_item,
|
account, debit = get_sales_account_and_amount_from_item(si.doclist, ref_item,
|
||||||
transfer_qty)
|
transfer_qty)
|
||||||
|
|
||||||
if si_doclist[0].name not in against_invoice:
|
if si.doclist[0].name not in against_invoice:
|
||||||
against_invoice[sales_invoice] = {
|
against_invoice[sales_invoice] = {
|
||||||
"parent": {"account": si_doclist[0].debit_to, "credit": 0},
|
"parent": {"account": si.doclist[0].debit_to, "credit": 0},
|
||||||
"children": {}
|
"children": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,8 +899,11 @@ def make_return_jv_from_delivery_note(se, ref):
|
|||||||
|
|
||||||
result = []
|
result = []
|
||||||
for sales_invoice, opts in against_invoice.items():
|
for sales_invoice, opts in against_invoice.items():
|
||||||
result += [opts["parent"]] + [{"account": account, "debit": debit}
|
parent = opts["parent"]
|
||||||
|
parent.update({"against_invoice": sales_invoice})
|
||||||
|
children = [{"account": account, "debit": debit}
|
||||||
for account, debit in opts["children"].items()]
|
for account, debit in opts["children"].items()]
|
||||||
|
result += [parent] + children
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_invoice_list(doctype, link_field, value):
|
def get_invoice_list(doctype, link_field, value):
|
||||||
@ -896,4 +915,63 @@ def get_invoice_list(doctype, link_field, value):
|
|||||||
", ".join(["%s"]*len(value))), tuple(value))
|
", ".join(["%s"]*len(value))), tuple(value))
|
||||||
|
|
||||||
def make_return_jv_from_purchase_receipt(se, ref):
|
def make_return_jv_from_purchase_receipt(se, ref):
|
||||||
pass
|
invoice_against_receipt = get_invoice_list("Purchase Invoice Item", "purchase_receipt",
|
||||||
|
ref.doclist[0].name)
|
||||||
|
|
||||||
|
if not invoice_against_receipt:
|
||||||
|
purchase_orders_against_receipt = [d.prevdoc_docname for d in
|
||||||
|
ref.doclist.get({"prevdoc_doctype": "Purchase Order"}) if d.prevdoc_docname]
|
||||||
|
|
||||||
|
invoice_against_receipt = get_invoice_list("Purchase Invoice Item", "purchase_order",
|
||||||
|
purchase_orders_against_receipt)
|
||||||
|
|
||||||
|
against_voucher = {}
|
||||||
|
|
||||||
|
for se_item in se.doclist.get({"parentfield": "mtn_details"}):
|
||||||
|
pending = se_item.transfer_qty
|
||||||
|
for purchase_invoice in invoice_against_receipt:
|
||||||
|
pi = webnotes.bean("Purchase Invoice", purchase_invoice)
|
||||||
|
ref_item = pi.doclist.get({"item_code": se_item.item_code})
|
||||||
|
|
||||||
|
if not ref_item:
|
||||||
|
continue
|
||||||
|
|
||||||
|
ref_item = ref_item[0]
|
||||||
|
|
||||||
|
if ref_item.qty < pending:
|
||||||
|
transfer_qty = ref_item.qty
|
||||||
|
pending -= ref_item.qty
|
||||||
|
else:
|
||||||
|
transfer_qty = pending
|
||||||
|
pending = 0
|
||||||
|
|
||||||
|
credit = ref_item.rate * transfer_qty
|
||||||
|
account = ref_item.expense_head
|
||||||
|
|
||||||
|
if pi.doclist[0].name not in against_voucher:
|
||||||
|
against_voucher[purchase_invoice] = {
|
||||||
|
"parent": {"account": pi.doclist[0].credit_to, "debit": 0},
|
||||||
|
"children": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
against_voucher[purchase_invoice]["parent"]["debit"] += credit
|
||||||
|
|
||||||
|
if account not in against_voucher[purchase_invoice]["children"]:
|
||||||
|
against_voucher[purchase_invoice]["children"][account] = 0
|
||||||
|
|
||||||
|
against_voucher[purchase_invoice]["children"][account] += credit
|
||||||
|
|
||||||
|
# find tax account and value and add corresponding rows
|
||||||
|
|
||||||
|
if pending <= 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for purchase_invoice, opts in against_voucher.items():
|
||||||
|
parent = opts["parent"]
|
||||||
|
parent.update({"against_voucher": purchase_invoice})
|
||||||
|
children = [{"account": account, "credit": credit}
|
||||||
|
for account, credit in opts["children"].items()]
|
||||||
|
result += [parent] + children
|
||||||
|
return result
|
||||||
|
|
@ -9,6 +9,9 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
def test_auto_material_request(self):
|
def test_auto_material_request(self):
|
||||||
webnotes.conn.sql("""delete from `tabMaterial Request Item`""")
|
webnotes.conn.sql("""delete from `tabMaterial Request Item`""")
|
||||||
webnotes.conn.sql("""delete from `tabMaterial Request`""")
|
webnotes.conn.sql("""delete from `tabMaterial Request`""")
|
||||||
|
self._clear_stock()
|
||||||
|
|
||||||
|
webnotes.conn.set_value("Global Defaults", None, "auto_indent", True)
|
||||||
|
|
||||||
st1 = webnotes.bean(copy=test_records[0])
|
st1 = webnotes.bean(copy=test_records[0])
|
||||||
st1.insert()
|
st1.insert()
|
||||||
@ -166,9 +169,14 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
|
|
||||||
def _insert_material_receipt(self):
|
def _insert_material_receipt(self):
|
||||||
self._clear_stock()
|
self._clear_stock()
|
||||||
material_receipt = webnotes.bean(copy=test_records[0])
|
se1 = webnotes.bean(copy=test_records[0])
|
||||||
material_receipt.insert()
|
se1.insert()
|
||||||
material_receipt.submit()
|
se1.submit()
|
||||||
|
|
||||||
|
se2 = webnotes.bean(copy=test_records[0])
|
||||||
|
se2.doclist[1].item_code = "_Test Item Home Desktop 100"
|
||||||
|
se2.insert()
|
||||||
|
se2.submit()
|
||||||
|
|
||||||
def _get_actual_qty(self):
|
def _get_actual_qty(self):
|
||||||
return flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item",
|
return flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item",
|
||||||
@ -239,6 +247,8 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
|
self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
|
||||||
|
|
||||||
|
return se
|
||||||
|
|
||||||
def test_sales_invoice_return_of_non_packing_item(self):
|
def test_sales_invoice_return_of_non_packing_item(self):
|
||||||
self._test_sales_invoice_return("_Test Item", 5, 2)
|
self._test_sales_invoice_return("_Test Item", 5, 2)
|
||||||
|
|
||||||
@ -248,11 +258,12 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty):
|
def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty):
|
||||||
self._insert_material_receipt()
|
self._insert_material_receipt()
|
||||||
|
|
||||||
actual_qty_0 = self._get_actual_qty()
|
|
||||||
|
|
||||||
# insert and submit delivery note
|
|
||||||
from stock.doctype.delivery_note.test_delivery_note \
|
from stock.doctype.delivery_note.test_delivery_note \
|
||||||
import test_records as delivery_note_test_records
|
import test_records as delivery_note_test_records
|
||||||
|
|
||||||
|
actual_qty_0 = self._get_actual_qty()
|
||||||
|
|
||||||
|
# make a delivery note based on this invoice
|
||||||
dn = webnotes.bean(copy=delivery_note_test_records[0])
|
dn = webnotes.bean(copy=delivery_note_test_records[0])
|
||||||
dn.doclist[1].item_code = item_code
|
dn.doclist[1].item_code = item_code
|
||||||
dn.insert()
|
dn.insert()
|
||||||
@ -262,11 +273,26 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
|
self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
|
||||||
|
|
||||||
|
si_doclist = webnotes.map_doclist([
|
||||||
|
["Delivery Note", "Sales Invoice"],
|
||||||
|
["Delivery Note Item", "Sales Invoice Item"],
|
||||||
|
["Sales Taxes and Charges", "Sales Taxes and Charges"],
|
||||||
|
["Sales Team", "Sales Team"]], dn.doc.name)
|
||||||
|
|
||||||
|
si = webnotes.bean(si_doclist)
|
||||||
|
si.doc.posting_date = dn.doc.posting_date
|
||||||
|
si.doc.debit_to = "_Test Customer - _TC"
|
||||||
|
for d in si.doclist.get({"parentfield": "entries"}):
|
||||||
|
d.income_account = "Sales - _TC"
|
||||||
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
si.insert()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
# insert and submit stock entry for sales return
|
# insert and submit stock entry for sales return
|
||||||
se = webnotes.bean(copy=test_records[0])
|
se = webnotes.bean(copy=test_records[0])
|
||||||
se.doc.purpose = "Sales Return"
|
se.doc.purpose = "Sales Return"
|
||||||
se.doc.delivery_note_no = dn.doc.name
|
se.doc.delivery_note_no = dn.doc.name
|
||||||
se.doc.posting_date = "2013-03-01"
|
se.doc.posting_date = "2013-03-10"
|
||||||
se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty
|
se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty
|
||||||
|
|
||||||
se.insert()
|
se.insert()
|
||||||
@ -275,12 +301,115 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
actual_qty_2 = self._get_actual_qty()
|
actual_qty_2 = self._get_actual_qty()
|
||||||
self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
|
self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
|
||||||
|
|
||||||
|
return se
|
||||||
|
|
||||||
def test_delivery_note_return_of_non_packing_item(self):
|
def test_delivery_note_return_of_non_packing_item(self):
|
||||||
self._test_delivery_note_return("_Test Item", 5, 2)
|
self._test_delivery_note_return("_Test Item", 5, 2)
|
||||||
|
|
||||||
def test_delivery_note_return_of_packing_item(self):
|
def test_delivery_note_return_of_packing_item(self):
|
||||||
self._test_delivery_note_return("_Test Sales BOM Item", 25, 20)
|
self._test_delivery_note_return("_Test Sales BOM Item", 25, 20)
|
||||||
|
|
||||||
|
def _test_sales_return_jv(self, se, returned_value):
|
||||||
|
from stock.doctype.stock_entry.stock_entry import make_return_jv
|
||||||
|
jv_list = make_return_jv(se.doc.name)
|
||||||
|
|
||||||
|
self.assertEqual(len(jv_list), 3)
|
||||||
|
self.assertEqual(jv_list[0].get("voucher_type"), "Credit Note")
|
||||||
|
self.assertEqual(jv_list[0].get("posting_date"), se.doc.posting_date)
|
||||||
|
self.assertEqual(jv_list[1].get("account"), "_Test Customer - _TC")
|
||||||
|
self.assertEqual(jv_list[2].get("account"), "Sales - _TC")
|
||||||
|
self.assertTrue(jv_list[1].get("against_invoice"))
|
||||||
|
|
||||||
|
# debit == credit
|
||||||
|
debit = sum([flt(d.get("debit")) for d in jv_list])
|
||||||
|
credit = sum([flt(d.get("credit")) for d in jv_list])
|
||||||
|
self.assertEqual(debit, credit)
|
||||||
|
|
||||||
|
# validate value of debit
|
||||||
|
self.assertEqual(debit, returned_value)
|
||||||
|
|
||||||
|
def test_make_return_jv_for_sales_invoice_non_packing_item(self):
|
||||||
|
se = self._test_sales_invoice_return("_Test Item", 5, 2)
|
||||||
|
self._test_sales_return_jv(se, 1000)
|
||||||
|
|
||||||
|
def test_make_return_jv_for_sales_invoice_packing_item(self):
|
||||||
|
se = self._test_sales_invoice_return("_Test Sales BOM Item", 25, 20)
|
||||||
|
self._test_sales_return_jv(se, 2000)
|
||||||
|
|
||||||
|
def test_make_return_jv_for_delivery_note_non_packing_item(self):
|
||||||
|
se = self._test_delivery_note_return("_Test Item", 5, 2)
|
||||||
|
self._test_sales_return_jv(se, 200)
|
||||||
|
|
||||||
|
se = self._test_delivery_note_return_against_sales_order("_Test Item", 5, 2)
|
||||||
|
self._test_sales_return_jv(se, 200)
|
||||||
|
|
||||||
|
def test_make_return_jv_for_delivery_note_packing_item(self):
|
||||||
|
se = self._test_delivery_note_return("_Test Sales BOM Item", 25, 20)
|
||||||
|
self._test_sales_return_jv(se, 400)
|
||||||
|
|
||||||
|
se = self._test_delivery_note_return_against_sales_order("_Test Sales BOM Item", 25, 20)
|
||||||
|
self._test_sales_return_jv(se, 400)
|
||||||
|
|
||||||
|
def _test_delivery_note_return_against_sales_order(self, item_code, delivered_qty, returned_qty):
|
||||||
|
self._insert_material_receipt()
|
||||||
|
|
||||||
|
from selling.doctype.sales_order.test_sales_order \
|
||||||
|
import test_records as sales_order_test_records
|
||||||
|
|
||||||
|
actual_qty_0 = self._get_actual_qty()
|
||||||
|
|
||||||
|
so = webnotes.bean(copy=sales_order_test_records[0])
|
||||||
|
so.doclist[1].item_code = item_code
|
||||||
|
so.doclist[1].qty = 5.0
|
||||||
|
so.insert()
|
||||||
|
so.submit()
|
||||||
|
|
||||||
|
dn_doclist = webnotes.map_doclist([
|
||||||
|
["Sales Order", "Delivery Note"],
|
||||||
|
["Sales Order Item", "Delivery Note Item"],
|
||||||
|
["Sales Taxes and Charges", "Sales Taxes and Charges"],
|
||||||
|
["Sales Team", "Sales Team"]], so.doc.name)
|
||||||
|
|
||||||
|
dn = webnotes.bean(dn_doclist)
|
||||||
|
dn.doc.status = "Draft"
|
||||||
|
dn.doc.posting_date = so.doc.delivery_date
|
||||||
|
dn.insert()
|
||||||
|
dn.submit()
|
||||||
|
|
||||||
|
actual_qty_1 = self._get_actual_qty()
|
||||||
|
|
||||||
|
self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
|
||||||
|
|
||||||
|
si_doclist = webnotes.map_doclist([
|
||||||
|
["Sales Order", "Sales Invoice"],
|
||||||
|
["Sales Order Item", "Sales Invoice Item"],
|
||||||
|
["Sales Taxes and Charges", "Sales Taxes and Charges"],
|
||||||
|
["Sales Team", "Sales Team"]], so.doc.name)
|
||||||
|
|
||||||
|
si = webnotes.bean(si_doclist)
|
||||||
|
si.doc.posting_date = dn.doc.posting_date
|
||||||
|
si.doc.debit_to = "_Test Customer - _TC"
|
||||||
|
for d in si.doclist.get({"parentfield": "entries"}):
|
||||||
|
d.income_account = "Sales - _TC"
|
||||||
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
si.insert()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
# insert and submit stock entry for sales return
|
||||||
|
se = webnotes.bean(copy=test_records[0])
|
||||||
|
se.doc.purpose = "Sales Return"
|
||||||
|
se.doc.delivery_note_no = dn.doc.name
|
||||||
|
se.doc.posting_date = "2013-03-10"
|
||||||
|
se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty
|
||||||
|
|
||||||
|
se.insert()
|
||||||
|
se.submit()
|
||||||
|
|
||||||
|
actual_qty_2 = self._get_actual_qty()
|
||||||
|
self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
|
||||||
|
|
||||||
|
return se
|
||||||
|
|
||||||
def test_purchase_receipt_return(self):
|
def test_purchase_receipt_return(self):
|
||||||
self._clear_stock()
|
self._clear_stock()
|
||||||
|
|
||||||
@ -298,6 +427,24 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEquals(actual_qty_0 + 10, actual_qty_1)
|
self.assertEquals(actual_qty_0 + 10, actual_qty_1)
|
||||||
|
|
||||||
|
pi_doclist = webnotes.map_doclist([
|
||||||
|
["Purchase Receipt", "Purchase Invoice"],
|
||||||
|
["Purchase Receipt Item", "Purchase Invoice Item"],
|
||||||
|
["Purchase Taxes and Charges", "Purchase Taxes and Charges"]], pr.doc.name)
|
||||||
|
|
||||||
|
pi = webnotes.bean(pi_doclist)
|
||||||
|
pi.doc.posting_date = pr.doc.posting_date
|
||||||
|
pi.doc.credit_to = "_Test Supplier - _TC"
|
||||||
|
for d in pi.doclist.get({"parentfield": "entries"}):
|
||||||
|
d.expense_head = "_Test Account Cost for Goods Sold - _TC"
|
||||||
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
for d in pi.doclist.get({"parentfield": "purchase_tax_details"}):
|
||||||
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
|
||||||
|
pi.run_method("calculate_taxes_and_totals")
|
||||||
|
pi.insert()
|
||||||
|
pi.submit()
|
||||||
|
|
||||||
# submit purchase return
|
# submit purchase return
|
||||||
se = webnotes.bean(copy=test_records[0])
|
se = webnotes.bean(copy=test_records[0])
|
||||||
se.doc.purpose = "Purchase Return"
|
se.doc.purpose = "Purchase Return"
|
||||||
@ -312,13 +459,13 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEquals(actual_qty_1 - 5, actual_qty_2)
|
self.assertEquals(actual_qty_1 - 5, actual_qty_2)
|
||||||
|
|
||||||
return pr.doc.name
|
return se, pr.doc.name
|
||||||
|
|
||||||
def test_over_stock_return(self):
|
def test_over_stock_return(self):
|
||||||
from stock.doctype.stock_entry.stock_entry import StockOverReturnError
|
from stock.doctype.stock_entry.stock_entry import StockOverReturnError
|
||||||
|
|
||||||
# out of 10, 5 gets returned
|
# out of 10, 5 gets returned
|
||||||
pr_docname = self.test_purchase_receipt_return()
|
prev_se, pr_docname = self.test_purchase_receipt_return()
|
||||||
|
|
||||||
# submit purchase return - return another 6 qtys so that exception is raised
|
# submit purchase return - return another 6 qtys so that exception is raised
|
||||||
se = webnotes.bean(copy=test_records[0])
|
se = webnotes.bean(copy=test_records[0])
|
||||||
@ -330,6 +477,96 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(StockOverReturnError, se.insert)
|
self.assertRaises(StockOverReturnError, se.insert)
|
||||||
|
|
||||||
|
def _test_purchase_return_jv(self, se, returned_value):
|
||||||
|
from stock.doctype.stock_entry.stock_entry import make_return_jv
|
||||||
|
jv_list = make_return_jv(se.doc.name)
|
||||||
|
|
||||||
|
self.assertEqual(len(jv_list), 3)
|
||||||
|
self.assertEqual(jv_list[0].get("voucher_type"), "Debit Note")
|
||||||
|
self.assertEqual(jv_list[0].get("posting_date"), se.doc.posting_date)
|
||||||
|
self.assertEqual(jv_list[1].get("account"), "_Test Supplier - _TC")
|
||||||
|
self.assertEqual(jv_list[2].get("account"), "_Test Account Cost for Goods Sold - _TC")
|
||||||
|
self.assertTrue(jv_list[1].get("against_voucher"))
|
||||||
|
|
||||||
|
# debit == credit
|
||||||
|
debit = sum([flt(d.get("debit")) for d in jv_list])
|
||||||
|
credit = sum([flt(d.get("credit")) for d in jv_list])
|
||||||
|
self.assertEqual(debit, credit)
|
||||||
|
|
||||||
|
# validate value of credit
|
||||||
|
self.assertEqual(credit, returned_value)
|
||||||
|
|
||||||
|
def test_make_return_jv_for_purchase_receipt(self):
|
||||||
|
se, pr_name = self.test_purchase_receipt_return()
|
||||||
|
self._test_purchase_return_jv(se, 250)
|
||||||
|
|
||||||
|
se, pr_name = self._test_purchase_return_return_against_purchase_order()
|
||||||
|
self._test_purchase_return_jv(se, 250)
|
||||||
|
|
||||||
|
def _test_purchase_return_return_against_purchase_order(self):
|
||||||
|
self._clear_stock()
|
||||||
|
|
||||||
|
actual_qty_0 = self._get_actual_qty()
|
||||||
|
|
||||||
|
from buying.doctype.purchase_order.test_purchase_order \
|
||||||
|
import test_records as purchase_order_test_records
|
||||||
|
|
||||||
|
# submit purchase receipt
|
||||||
|
po = webnotes.bean(copy=purchase_order_test_records[0])
|
||||||
|
po.doc.is_subcontracted = None
|
||||||
|
po.doclist[1].item_code = "_Test Item"
|
||||||
|
po.doclist[1].import_rate = 50
|
||||||
|
po.insert()
|
||||||
|
po.submit()
|
||||||
|
|
||||||
|
pr_doclist = webnotes.map_doclist([
|
||||||
|
["Purchase Order", "Purchase Receipt"],
|
||||||
|
["Purchase Order Item", "Purchase Receipt Item"],
|
||||||
|
["Purchase Taxes and Charges", "Purchase Taxes and Charges"]], po.doc.name)
|
||||||
|
|
||||||
|
pr = webnotes.bean(pr_doclist)
|
||||||
|
pr.doc.posting_date = po.doc.transaction_date
|
||||||
|
pr.insert()
|
||||||
|
pr.submit()
|
||||||
|
|
||||||
|
actual_qty_1 = self._get_actual_qty()
|
||||||
|
|
||||||
|
self.assertEquals(actual_qty_0 + 10, actual_qty_1)
|
||||||
|
|
||||||
|
pi_doclist = webnotes.map_doclist([
|
||||||
|
["Purchase Order", "Purchase Invoice"],
|
||||||
|
["Purchase Order Item", "Purchase Invoice Item"],
|
||||||
|
["Purchase Taxes and Charges", "Purchase Taxes and Charges"]], po.doc.name)
|
||||||
|
|
||||||
|
pi = webnotes.bean(pi_doclist)
|
||||||
|
pi.doc.posting_date = pr.doc.posting_date
|
||||||
|
pi.doc.credit_to = "_Test Supplier - _TC"
|
||||||
|
for d in pi.doclist.get({"parentfield": "entries"}):
|
||||||
|
d.expense_head = "_Test Account Cost for Goods Sold - _TC"
|
||||||
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
for d in pi.doclist.get({"parentfield": "purchase_tax_details"}):
|
||||||
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
|
||||||
|
pi.run_method("calculate_taxes_and_totals")
|
||||||
|
pi.insert()
|
||||||
|
pi.submit()
|
||||||
|
|
||||||
|
# submit purchase return
|
||||||
|
se = webnotes.bean(copy=test_records[0])
|
||||||
|
se.doc.purpose = "Purchase Return"
|
||||||
|
se.doc.purchase_receipt_no = pr.doc.name
|
||||||
|
se.doc.posting_date = "2013-03-01"
|
||||||
|
se.doclist[1].qty = se.doclist[1].transfer_qty = 5
|
||||||
|
se.doclist[1].s_warehouse = "_Test Warehouse"
|
||||||
|
se.insert()
|
||||||
|
se.submit()
|
||||||
|
|
||||||
|
actual_qty_2 = self._get_actual_qty()
|
||||||
|
|
||||||
|
self.assertEquals(actual_qty_1 - 5, actual_qty_2)
|
||||||
|
|
||||||
|
return se, pr.doc.name
|
||||||
|
|
||||||
test_records = [
|
test_records = [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user