diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py index 8338a5b153..db6de44f09 100644 --- a/accounts/doctype/gl_entry/gl_entry.py +++ b/accounts/doctype/gl_entry/gl_entry.py @@ -117,7 +117,7 @@ def check_negative_balance(account, adv_adj=False): flt(balance[0][0]) or -1*flt(balance[0][0]) if flt(balance) < 0: - webnotes.throw(_("Negative balance is not allowed for account ") + self.doc.account) + webnotes.throw(_("Negative balance is not allowed for account ") + account) def check_freezing_date(posting_date, adv_adj=False): """ diff --git a/buying/doctype/purchase_order/test_purchase_order.py b/buying/doctype/purchase_order/test_purchase_order.py index e160babc59..cef5e4a207 100644 --- a/buying/doctype/purchase_order/test_purchase_order.py +++ b/buying/doctype/purchase_order/test_purchase_order.py @@ -6,9 +6,10 @@ from __future__ import unicode_literals import unittest import webnotes import webnotes.defaults +from webnotes.utils import flt class TestPurchaseOrder(unittest.TestCase): - def test_make_purchase_receipt(self): + def test_make_purchase_receipt(self): from buying.doctype.purchase_order.purchase_order import make_purchase_receipt po = webnotes.bean(copy=test_records[0]).insert() @@ -18,6 +19,7 @@ class TestPurchaseOrder(unittest.TestCase): po = webnotes.bean("Purchase Order", po.doc.name) po.submit() + pr = make_purchase_receipt(po.doc.name) pr[0]["supplier_warehouse"] = "_Test Warehouse 1 - _TC" @@ -25,7 +27,52 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(len(pr), len(test_records[0])) pr[0].naming_series = "_T-Purchase Receipt-" - webnotes.bean(pr).insert() + pr_bean = webnotes.bean(pr) + pr_bean.insert() + + def test_ordered_qty(self): + webnotes.conn.sql("delete from tabBin") + + from buying.doctype.purchase_order.purchase_order import make_purchase_receipt + + po = webnotes.bean(copy=test_records[0]).insert() + + self.assertRaises(webnotes.ValidationError, make_purchase_receipt, + po.doc.name) + + po = webnotes.bean("Purchase Order", po.doc.name) + po.doc.is_subcontracted = "No" + po.doclist[1].item_code = "_Test Item" + po.submit() + + self.assertEquals(webnotes.conn.get_value("Bin", {"item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC"}, "ordered_qty"), 10) + + pr = make_purchase_receipt(po.doc.name) + + self.assertEquals(pr[0]["doctype"], "Purchase Receipt") + self.assertEquals(len(pr), len(test_records[0])) + + pr[0].naming_series = "_T-Purchase Receipt-" + pr[1].qty = 4.0 + pr_bean = webnotes.bean(pr) + pr_bean.insert() + pr_bean.submit() + + self.assertEquals(flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC"}, "ordered_qty")), 6.0) + + webnotes.conn.set_value('Item', '_Test Item', 'tolerance', 50) + + pr1 = make_purchase_receipt(po.doc.name) + pr1[0].naming_series = "_T-Purchase Receipt-" + pr1[1].qty = 8 + pr1_bean = webnotes.bean(pr1) + pr1_bean.insert() + pr1_bean.submit() + + self.assertEquals(flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC"}, "ordered_qty")), 0.0) def test_make_purchase_invocie(self): from buying.doctype.purchase_order.purchase_order import make_purchase_invoice diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 278becd7e1..7d663b8778 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -117,8 +117,7 @@ class DocType(BuyingController): }, "Purchase Order Item": { "ref_dn_field": "prevdoc_detail_docname", - "compare_fields": [["project_name", "="], ["warehouse", "="], - ["uom", "="], ["item_code", "="]], + "compare_fields": [["project_name", "="], ["uom", "="], ["item_code", "="]], "is_child_table": True } }) @@ -165,34 +164,43 @@ class DocType(BuyingController): self.bk_flush_supp_wh(sl_entries) self.make_sl_entries(sl_entries) - - def update_ordered_qty(self, is_cancelled="No"): - pc_obj = get_obj('Purchase Common') + + def update_ordered_qty(self): stock_items = self.get_stock_items() - for d in getlist(self.doclist, 'purchase_receipt_details'): + for d in self.doclist.get({"parentfield": "purchase_receipt_details"}): if d.item_code in stock_items and d.warehouse \ and cstr(d.prevdoc_doctype) == 'Purchase Order': - pr_qty = flt(d.qty) * flt(d.conversion_factor) - - # get qty and pending_qty of prevdoc - curr_ref_qty = pc_obj.get_qty(d.doctype, 'prevdoc_detail_docname', - d.prevdoc_detail_docname, 'Purchase Order Item', - 'Purchase Order - Purchase Receipt', self.doc.name) - max_qty, qty, curr_qty = flt(curr_ref_qty.split('~~~')[1]), \ - flt(curr_ref_qty.split('~~~')[0]), 0 - - if flt(qty) + flt(pr_qty) > flt(max_qty): - curr_qty = (flt(max_qty) - flt(qty)) * flt(d.conversion_factor) + + already_received_qty = self.get_already_received_qty(d.prevdoc_docname, + d.prevdoc_detail_docname) + po_qty, ordered_warehouse = self.get_po_qty_and_warehouse(d.prevdoc_detail_docname) + + if not ordered_warehouse: + webnotes.throw(_("Warehouse is missing in Purchase Order")) + + if already_received_qty + d.qty > po_qty: + ordered_qty = - (po_qty - already_received_qty) * flt(d.conversion_factor) else: - curr_qty = flt(pr_qty) - - args = { + ordered_qty = - flt(d.qty) * flt(d.conversion_factor) + + update_bin({ "item_code": d.item_code, - "warehouse": d.warehouse, + "warehouse": ordered_warehouse, "posting_date": self.doc.posting_date, - "ordered_qty": (is_cancelled=="Yes" and -1 or 1)*flt(curr_qty) - } - update_bin(args) + "ordered_qty": flt(ordered_qty) if self.doc.docstatus==1 else -flt(ordered_qty) + }) + + def get_already_received_qty(self, po, po_detail): + qty = webnotes.conn.sql("""select sum(qty) from `tabPurchase Receipt Item` + where prevdoc_detail_docname = %s and docstatus = 1 + and prevdoc_doctype='Purchase Order' and prevdoc_docname=%s + and parent != %s""", (po_detail, po, self.doc.name)) + return qty and flt(qty[0][0]) or 0.0 + + def get_po_qty_and_warehouse(self, po_detail): + po_qty, po_warehouse = webnotes.conn.get_value("Purchase Order Item", po_detail, + ["qty", "warehouse"]) + return po_qty, po_warehouse def bk_flush_supp_wh(self, sl_entries): for d in getlist(self.doclist, 'pr_raw_material_details'): @@ -201,7 +209,7 @@ class DocType(BuyingController): sl_entries.append(self.get_sl_entries(d, { "item_code": d.rm_item_code, "warehouse": self.doc.supplier_warehouse, - "actual_qty": -1*flt(consumed_qty), + "actual_qty": -1*flt(d.consumed_qty), "incoming_rate": 0 })) @@ -281,7 +289,7 @@ class DocType(BuyingController): webnotes.conn.set(self.doc,'status','Cancelled') - self.update_ordered_qty(is_cancelled="Yes") + self.update_ordered_qty() self.update_stock() self.update_serial_nos(cancel=True) diff --git a/stock/doctype/warehouse/warehouse.py b/stock/doctype/warehouse/warehouse.py index c2b3284608..58cf11bfdf 100644 --- a/stock/doctype/warehouse/warehouse.py +++ b/stock/doctype/warehouse/warehouse.py @@ -59,10 +59,7 @@ class DocType: else: webnotes.throw(_("Please enter account group under which account \ for warehouse ") + self.doc.name +_(" will be created")) - - def on_rename(self, new, old): - webnotes.conn.set_value("Account", {"account_type": "Warehouse", "master_name": old}, - "master_name", new) + def merge_warehouses(self): webnotes.conn.auto_commit_on_many_writes = 1 @@ -207,6 +204,9 @@ class DocType: sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name) def on_rename(self, newdn, olddn, merge=False): + webnotes.conn.set_value("Account", {"account_type": "Warehouse", "master_name": olddn}, + "master_name", newdn) + if merge: from stock.stock_ledger import update_entries_after for item_code in webnotes.conn.sql("""select item_code from `tabBin` diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index 2535db7ab5..0655567c24 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -143,7 +143,8 @@ class TransactionBase(StatusUpdater): self.doc.fields.update(self.get_lead_defaults()) def get_customer_address(self, args): - args = load_json(args) + args = load_json(args) + webnotes.errprint(args) ret = { 'customer_address' : args["address"], 'address_display' : get_address_display(args["address"]),