Merge branch 'master' of github.com:webnotes/erpnext

This commit is contained in:
Anand Doshi
2013-03-12 11:06:06 +05:30
20 changed files with 655 additions and 230 deletions

View File

@@ -225,7 +225,12 @@ class DocType(SellingController):
bin = sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
def on_update(self):
self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details')
sl = get_obj('Stock Ledger')
sl.scrub_serial_nos(self)
sl.scrub_serial_nos(self, 'packing_details')
def on_submit(self):
self.validate_packed_qty()
@@ -252,6 +257,7 @@ class DocType(SellingController):
self.credit_limit()
self.set_buying_amount()
self.make_gl_entries()
# set DN status
@@ -387,13 +393,19 @@ class DocType(SellingController):
if amount != 0:
total = (amount/self.doc.net_total)*self.doc.grand_total
get_obj('Sales Common').check_credit(self, total)
def on_update(self):
self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details')
sl = get_obj('Stock Ledger')
sl.scrub_serial_nos(self)
sl.scrub_serial_nos(self, 'packing_details')
def set_buying_amount(self):
from stock.utils import get_buying_amount, get_sales_bom
stock_ledger_entries = self.get_stock_ledger_entries()
item_sales_bom = get_sales_bom()
if stock_ledger_entries:
for item in self.doclist.get({"parentfield": "delivery_note_details"}):
item.buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty,
self.doc.doctype, self.doc.name, item.name, stock_ledger_entries,
item_sales_bom)
webnotes.conn.set_value("Delivery Note Item", item.name, "buying_amount",
item.buying_amount)
self.validate_warehouse()
@@ -435,38 +447,6 @@ class DocType(SellingController):
make_gl_entries(gl_entries, cancel=self.doc.docstatus == 2)
def get_total_buying_amount(self):
from stock.utils import get_buying_amount, get_sales_bom
stock_ledger_entries = self.get_stock_ledger_entries()
item_sales_bom = get_sales_bom()
total_buying_amount = 0
if stock_ledger_entries:
for item in self.doclist.get({"parentfield": "delivery_note_details"}):
buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty,
self.doc.name, item.name, stock_ledger_entries, item_sales_bom)
total_buying_amount += buying_amount
total_buying_amount = sum([item.buying_amount for item in
self.doclist.get({"parentfield": "delivery_note_details"})])
return total_buying_amount
def get_stock_ledger_entries(self):
item_list, warehouse_list = self.get_distinct_item_warehouse()
if item_list and warehouse_list:
return webnotes.conn.sql("""select item_code, voucher_type, voucher_no,
voucher_detail_no, posting_date, posting_time, stock_value,
warehouse, actual_qty as qty from `tabStock Ledger Entry`
where ifnull(`is_cancelled`, "No") = "No" and company = %s
and item_code in (%s) and warehouse in (%s)
order by item_code desc, warehouse desc, posting_date desc,
posting_time desc, name desc""" %
('%s', ', '.join(['%s']*len(item_list)), ', '.join(['%s']*len(warehouse_list))),
tuple([self.doc.company] + item_list + warehouse_list), as_dict=1)
def get_distinct_item_warehouse(self):
item_list = []
warehouse_list = []
for item in self.doclist.get({"parentfield": "delivery_note_details"}) \
+ self.doclist.get({"parentfield": "packing_details"}):
item_list.append(item.item_code)
warehouse_list.append(item.warehouse)
return list(set(item_list)), list(set(warehouse_list))

View File

@@ -48,6 +48,8 @@ class TestDeliveryNote(unittest.TestCase):
def test_delivery_note_gl_entry(self):
webnotes.conn.sql("""delete from `tabBin`""")
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 1)

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-02-22 01:28:00",
"creation": "2013-03-07 11:42:59",
"docstatus": 0,
"modified": "2013-03-07 07:03:20",
"modified": "2013-03-07 15:46:43",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -30,7 +30,8 @@
"fieldname": "barcode",
"fieldtype": "Data",
"label": "Barcode",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -42,6 +43,7 @@
"oldfieldtype": "Link",
"options": "Item",
"print_width": "150px",
"read_only": 0,
"reqd": 1,
"search_index": 1,
"width": "150px"
@@ -64,6 +66,7 @@
"oldfieldtype": "Data",
"print_hide": 1,
"print_width": "150px",
"read_only": 0,
"reqd": 1,
"width": "150px"
},
@@ -75,6 +78,7 @@
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"print_width": "300px",
"read_only": 0,
"reqd": 1,
"width": "300px"
},
@@ -87,6 +91,7 @@
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"print_width": "100px",
"read_only": 0,
"reqd": 1,
"width": "100px"
},
@@ -115,6 +120,7 @@
"options": "currency",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"reqd": 0,
"width": "100px"
},
@@ -128,6 +134,7 @@
"oldfieldtype": "Float",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"width": "100px"
},
{
@@ -140,6 +147,7 @@
"options": "currency",
"print_hide": 0,
"print_width": "150px",
"read_only": 0,
"reqd": 0,
"width": "150px"
},
@@ -181,6 +189,7 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"print_width": "150px",
"read_only": 0,
"reqd": 0,
"width": "150px"
},
@@ -208,6 +217,7 @@
"options": "Warehouse",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"width": "100px"
},
{
@@ -219,7 +229,8 @@
"no_copy": 1,
"oldfieldname": "serial_no",
"oldfieldtype": "Text",
"print_hide": 0
"print_hide": 0,
"read_only": 0
},
{
"doctype": "DocField",
@@ -229,7 +240,8 @@
"oldfieldname": "batch_no",
"oldfieldtype": "Link",
"options": "Batch",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -375,6 +387,17 @@
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "buying_amount",
"fieldtype": "Currency",
"hidden": 1,
"label": "Buying Amount",
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"allow_on_submit": 1,
"doctype": "DocField",
@@ -383,6 +406,7 @@
"label": "Page Break",
"oldfieldname": "page_break",
"oldfieldtype": "Check",
"print_hide": 1
"print_hide": 1,
"read_only": 0
}
]

View File

@@ -127,4 +127,23 @@ test_records = [
"is_sub_contracted_item": "Yes",
"stock_uom": "_Test UOM"
}],
[{
"doctype": "Item",
"item_code": "_Test Non Stock Item",
"item_name": "_Test Non Stock Item",
"description": "_Test Non Stock Item",
"item_group": "_Test Item Group Desktops",
"is_stock_item": "No",
"is_asset_item": "No",
"has_batch_no": "No",
"has_serial_no": "No",
"is_purchase_item": "Yes",
"is_sales_item": "Yes",
"is_service_item": "No",
"is_sample_item": "No",
"inspection_required": "No",
"is_pro_applicable": "No",
"is_sub_contracted_item": "No",
"stock_uom": "_Test UOM"
}],
]

View File

@@ -21,6 +21,77 @@ class TestStockEntry(unittest.TestCase):
where item_code='_Test Item'""")
self.assertTrue(mr_name)
def test_material_receipt_gl_entry(self):
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
mr = webnotes.bean(copy=test_records[0])
mr.insert()
mr.submit()
stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
"stock_in_hand_account")
self.check_stock_ledger_entries("Stock Entry", mr.doc.name,
[["_Test Item", "_Test Warehouse", 50.0]])
self.check_gl_entries("Stock Entry", mr.doc.name,
sorted([
[stock_in_hand_account, 5000.0, 0.0],
["Stock Adjustment - _TC", 0.0, 5000.0]
])
)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
def test_material_issue_gl_entry(self):
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
mr = webnotes.bean(copy=test_records[0])
mr.insert()
mr.submit()
stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
"stock_in_hand_account")
self.check_stock_ledger_entries("Stock Entry", mr.doc.name,
[["_Test Item", "_Test Warehouse", 50.0]])
self.check_gl_entries("Stock Entry", mr.doc.name,
sorted([
[stock_in_hand_account, 5000.0, 0.0],
["Stock Adjustment - _TC", 0.0, 5000.0]
])
)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle):
# check stock ledger entries
sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where voucher_type = %s and voucher_no = %s order by item_code, warehouse""",
(voucher_type, voucher_no), as_dict=1)
self.assertTrue(sle)
for i, sle in enumerate(sle):
self.assertEquals(expected_sle[i][0], sle.item_code)
self.assertEquals(expected_sle[i][1], sle.warehouse)
self.assertEquals(expected_sle[i][2], sle.actual_qty)
def check_gl_entries(self, voucher_type, voucher_no, expected_gl_entries):
# check gl entries
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account asc, debit asc""", (voucher_type, voucher_no), as_dict=1)
self.assertTrue(gl_entries)
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_gl_entries[i][0], gle.account)
self.assertEquals(expected_gl_entries[i][1], gle.debit)
self.assertEquals(expected_gl_entries[i][2], gle.credit)
test_records = [
[

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-01-10 16:34:30",
"creation": "2013-03-07 18:50:32",
"docstatus": 0,
"modified": "2013-02-04 11:35:53",
"modified": "2013-03-11 17:58:45",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -21,7 +21,8 @@
"name": "__common__",
"parent": "Warehouse",
"parentfield": "fields",
"parenttype": "DocType"
"parenttype": "DocType",
"read_only": 0
},
{
"doctype": "DocPerm",
@@ -190,7 +191,7 @@
"permlevel": 0
},
{
"description": "This feature is for merging duplicate warehouses. It will replace all the links of this warehouse by \"Merge With\" warehouse. After merging you can delete this warehouse, as stock level for this warehouse will be zero.",
"description": "This feature is for merging duplicate warehouses. It will replace all the links of this warehouse by \"Merge Into\" warehouse. After merging you can delete this warehouse, as stock level for this warehouse will be zero.",
"doctype": "DocField",
"fieldname": "merge_warehouses_section",
"fieldtype": "Section Break",
@@ -201,7 +202,7 @@
"doctype": "DocField",
"fieldname": "merge_with",
"fieldtype": "Link",
"label": "Merge With",
"label": "Merge Into",
"options": "Warehouse",
"permlevel": 2
},
@@ -221,24 +222,6 @@
"role": "Material Master Manager",
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Material User",
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 2,
"role": "Material User",
"write": 0
},
{
"cancel": 1,
"create": 1,
@@ -248,6 +231,26 @@
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Material Manager",
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Material User",
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 2,

View File

@@ -36,7 +36,6 @@ def update_entries_after(args, verbose=1):
}
"""
previous_sle = get_sle_before_datetime(args)
qty_after_transaction = flt(previous_sle.get("qty_after_transaction"))
valuation_rate = flt(previous_sle.get("valuation_rate"))
stock_queue = json.loads(previous_sle.get("stock_queue") or "[]")
@@ -214,7 +213,6 @@ def get_moving_average_values(qty_after_transaction, sle, valuation_rate):
def get_fifo_values(qty_after_transaction, sle, stock_queue):
incoming_rate = flt(sle.incoming_rate)
actual_qty = flt(sle.actual_qty)
if not stock_queue:
stock_queue.append([0, 0])

View File

@@ -164,23 +164,24 @@ def get_warehouse_list(doctype, txt, searchfield, start, page_len, filters):
wlist.append([w])
return wlist
def get_buying_amount(item_code, warehouse, qty, voucher_no, voucher_detail_no,
def get_buying_amount(item_code, warehouse, qty, voucher_type, voucher_no, voucher_detail_no,
stock_ledger_entries, item_sales_bom):
if item_sales_bom.get(item_code):
# sales bom item
buying_amount = 0.0
for bom_item in item_sales_bom[item_code]:
buying_amount += _get_buying_amount(voucher_no, "[** No Item Row **]",
buying_amount += _get_buying_amount(voucher_type, voucher_no, "[** No Item Row **]",
item_code, warehouse, bom_item.qty * qty, stock_ledger_entries)
return buying_amount
else:
# doesn't have sales bom
return _get_buying_amount(voucher_no, voucher_detail_no, item_code, warehouse, qty,
stock_ledger_entries)
return _get_buying_amount(voucher_type, voucher_no, voucher_detail_no,
item_code, warehouse, qty, stock_ledger_entries)
def _get_buying_amount(voucher_no, item_row, item_code, warehouse, qty, stock_ledger_entries):
def _get_buying_amount(voucher_type, voucher_no, item_row, item_code, warehouse, qty,
stock_ledger_entries):
for i, sle in enumerate(stock_ledger_entries):
if sle.voucher_type == "Delivery Note" and sle.voucher_no == voucher_no:
if sle.voucher_type == voucher_type and sle.voucher_no == voucher_no:
if (sle.voucher_detail_no == item_row) or \
(sle.item_code == item_code and sle.warehouse == warehouse and \
abs(flt(sle.qty)) == qty):