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

This commit is contained in:
Akhilesh Darjee
2013-12-26 18:15:14 +05:30
39 changed files with 310 additions and 164 deletions

View File

@@ -58,11 +58,6 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(stock_value, 0)
self.assertEqual(stock_value_difference, -375)
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Delivery Note' and voucher_no=%s
order by account desc""", dn.doc.name, as_dict=1)
self.assertFalse(get_gl_entries("Delivery Note", dn.doc.name))
def test_delivery_note_gl_entry(self):
@@ -111,8 +106,8 @@ class TestDeliveryNote(unittest.TestCase):
gl_entries = get_gl_entries("Delivery Note", dn.doc.name)
self.assertTrue(gl_entries)
expected_values = {
stock_in_hand_account: [0.0, 666.65],
"Cost of Goods Sold - _TC": [666.65, 0.0]
stock_in_hand_account: [0.0, 666.67],
"Cost of Goods Sold - _TC": [666.67, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))

View File

@@ -49,6 +49,7 @@ class DocType(DocListController, WebsiteGenerator):
def on_update(self):
self.validate_name_with_item_group()
self.update_website()
self.update_item_price()
def check_warehouse_is_set_for_stock_item(self):
if self.doc.is_stock_item=="Yes" and not self.doc.default_warehouse:
@@ -123,14 +124,14 @@ class DocType(DocListController, WebsiteGenerator):
msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1)
def check_for_active_boms(self):
if self.doc.is_active != "Yes" or self.doc.is_purchase_item != "Yes":
if self.doc.is_purchase_item != "Yes":
bom_mat = webnotes.conn.sql("""select distinct t1.parent
from `tabBOM Item` t1, `tabBOM` t2 where t2.name = t1.parent
and t1.item_code =%s and ifnull(t1.bom_no, '') = '' and t2.is_active = 1
and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name)
if bom_mat and bom_mat[0][0]:
webnotes.throw(_("Item must be active and purchase item, \
webnotes.throw(_("Item must be a purchase item, \
as it is present in one or many Active BOMs"))
if self.doc.is_manufactured_item != "Yes":
@@ -210,6 +211,11 @@ class DocType(DocListController, WebsiteGenerator):
WebsiteGenerator.on_update(self)
def update_item_price(self):
webnotes.conn.sql("""update `tabItem Price` set item_name=%s,
item_description=%s, modified=NOW() where item_code=%s""",
(self.doc.item_name, self.doc.description, self.doc.name))
def get_page_title(self):
if self.doc.name==self.doc.item_name:
page_name_from = self.doc.name
@@ -246,6 +252,9 @@ class DocType(DocListController, WebsiteGenerator):
def before_rename(self, olddn, newdn, merge=False):
if merge:
# Validate properties before merging
if not webnotes.conn.exists("Item", newdn):
webnotes.throw(_("Item ") + newdn +_(" does not exists"))
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"]
new_properties = [cstr(d) for d in webnotes.conn.get_value("Item", newdn, field_list)]
if new_properties != [cstr(self.doc.fields[fld]) for fld in field_list]:

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-02-22 01:28:02",
"docstatus": 0,
"modified": "2013-11-03 20:36:45",
"modified": "2013-12-18 14:52:02",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -219,7 +219,7 @@
"fieldname": "sales_order_no",
"fieldtype": "Link",
"label": "Sales Order No",
"no_copy": 1,
"no_copy": 0,
"options": "Sales Order",
"print_hide": 1,
"read_only": 1

View File

@@ -44,5 +44,5 @@ class DocType(DocListController):
def update_item_price(self):
webnotes.conn.sql("""update `tabItem Price` set currency=%s,
buying_or_selling=%s where price_list=%s""",
buying_or_selling=%s, modified=NOW() where price_list=%s""",
(self.doc.currency, self.doc.buying_or_selling, self.doc.name))

View File

@@ -287,9 +287,15 @@ class DocType(StockController):
# 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)
if not returnable_qty:
webnotes.throw("{item}: {item_code} {returned}".format(
item=_("Item"), item_code=item.item_code,
returned=_("already returned though some other documents")))
elif item.transfer_qty > returnable_qty:
webnotes.throw("{item}: {item_code}, {returned}: {qty}".format(
item=_("Item"), item_code=item.item_code,
returned=_("Max Returnable Qty"), qty=returnable_qty))
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 (

View File

@@ -20,6 +20,19 @@ class DocType:
if self.doc.email_id and not validate_email_add(self.doc.email_id):
msgprint("Please enter valid Email Id", raise_exception=1)
self.update_parent_account()
def update_parent_account(self):
if not self.doc.__islocal and (self.doc.create_account_under !=
webnotes.conn.get_value("Warehouse", self.doc.name, "create_account_under")):
warehouse_account = webnotes.conn.get_value("Account",
{"account_type": "Warehouse", "company": self.doc.company,
"master_name": self.doc.name}, ["name", "parent_account"])
if warehouse_account and warehouse_account[1] != self.doc.create_account_under:
acc_bean = webnotes.bean("Account", warehouse_account[0])
acc_bean.doc.parent_account = self.doc.create_account_under
acc_bean.save()
def on_update(self):
self.create_account_head()
@@ -84,6 +97,9 @@ class DocType:
new_warehouse = get_name_with_abbr(newdn, self.doc.company)
if merge:
if not webnotes.conn.exists("Warehouse", newdn):
webnotes.throw(_("Warehouse ") + newdn +_(" does not exists"))
if self.doc.company != webnotes.conn.get_value("Warehouse", new_warehouse, "company"):
webnotes.throw(_("Both Warehouse must belong to same Company"))

View File

@@ -15,8 +15,8 @@ def execute(filters=None):
bom_rate = get_item_bom_rate()
val_rate_map = get_valuation_rate()
precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2
precision = get_currency_precision or 2
data = []
for item in sorted(item_map):
data.append([item, item_map[item]["item_name"],
@@ -30,6 +30,14 @@ def execute(filters=None):
])
return columns, data
def get_currency_precision():
company_currency = webnotes.conn.get_value("Company",
webnotes.conn.get_default("company"), "default_currency")
currency_format = webnotes.conn.get_value("Currency", company_currency, "number_format")
from webnotes.utils import get_number_format_info
return get_number_format_info(currency_format)[2]
def get_columns(filters):
"""return columns based on filters"""

View File

@@ -67,7 +67,7 @@ def get_stock_ledger_entries(filters):
item.name, item.item_name, item_group, brand, description, item.stock_uom,
actual_qty, posting_date
from `tabStock Ledger Entry` sle,
(select name, item_name, description, stock_uom, brand
(select name, item_name, description, stock_uom, brand, item_group
from `tabItem` {item_conditions}) item
where item_code = item.name and
company = %(company)s and

View File

@@ -3,7 +3,6 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _
def execute(filters=None):
columns = get_columns()
@@ -13,10 +12,14 @@ def execute(filters=None):
data = []
for sle in sl_entries:
item_detail = item_details[sle.item_code]
voucher_link_icon = """<a href="%s"><i class="icon icon-share"
style="cursor: pointer;"></i></a>""" \
% ("/".join(["#Form", sle.voucher_type, sle.voucher_no]),)
data.append([sle.date, sle.item_code, item_detail.item_name, item_detail.item_group,
item_detail.brand, item_detail.description, sle.warehouse, item_detail.stock_uom,
sle.actual_qty, sle.qty_after_transaction, sle.stock_value, sle.voucher_type,
sle.voucher_no, sle.batch_no, sle.serial_no, sle.company])
sle.voucher_no, voucher_link_icon, sle.batch_no, sle.serial_no, sle.company])
return columns, data
@@ -25,17 +28,10 @@ def get_columns():
"Item Group:Link/Item Group:100", "Brand:Link/Brand:100",
"Description::200", "Warehouse:Link/Warehouse:100",
"Stock UOM:Link/UOM:100", "Qty:Float:50", "Balance Qty:Float:80",
"Balance Value:Currency:100", "Voucher Type::100", "Voucher #::100",
"Balance Value:Currency:100", "Voucher Type::100", "Voucher #::100", "Link::30",
"Batch:Link/Batch:100", "Serial #:Link/Serial No:100", "Company:Link/Company:100"]
def get_stock_ledger_entries(filters):
if not filters.get("company"):
webnotes.throw(_("Company is mandatory"))
if not filters.get("from_date"):
webnotes.throw(_("From Date is mandatory"))
if not filters.get("to_date"):
webnotes.throw(_("To Date is mandatory"))
return webnotes.conn.sql("""select concat_ws(" ", posting_date, posting_time) as date,
item_code, warehouse, actual_qty, qty_after_transaction,
stock_value, voucher_type, voucher_no, batch_no, serial_no, company
@@ -66,6 +62,10 @@ def get_item_conditions(filters):
def get_sle_conditions(filters):
conditions = []
item_conditions=get_item_conditions(filters)
if item_conditions:
conditions.append("""item_code in (select name from tabItem
{item_conditions})""".format(item_conditions=item_conditions))
if filters.get("warehouse"):
conditions.append("warehouse=%(warehouse)s")
if filters.get("voucher_no"):

View File

@@ -7,9 +7,7 @@ wn.query_reports["Stock Projected Qty"] = {
"fieldname":"company",
"label": wn._("Company"),
"fieldtype": "Link",
"options": "Company",
"default": wn.defaults.get_user_default("company"),
"reqd": 1
"options": "Company"
},
{
"fieldname":"warehouse",

View File

@@ -13,23 +13,23 @@ def execute(filters=None):
projected_qty, item.re_order_level, item.re_order_qty
from `tabBin` bin,
(select name, company from tabWarehouse
where company=%(company)s {warehouse_conditions}) wh,
{warehouse_conditions}) wh,
(select name, item_name, description, stock_uom, item_group,
brand, re_order_level, re_order_qty
from `tabItem` {item_conditions}) item
where item_code = item.name and warehouse = wh.name
order by item.name, wh.name"""\
.format(item_conditions=get_item_conditions(filters),
warehouse_conditions=get_warehouse_conditions(filters)), filters, debug=1)
warehouse_conditions=get_warehouse_conditions(filters)), filters)
return columns, data
def get_columns():
return ["Item Code:Link/Item:140", "Item Name::100", "Description::200",
"Brand:Link/Brand:100", "Warehouse:Link/Warehouse:120", "UOM:Link/UOM:100",
"Actual Qty:Float:100", "Planned Qty:Float:100", "Requested Qty:Float:110",
"Ordered Qty:Float:100", "Reserved Qty:Float:100", "Projected Qty:Float:100",
"Reorder Level:Float:100", "Reorder Qty:Float:100"]
"Item Group:Link/Item Group:100", "Brand:Link/Brand:100", "Warehouse:Link/Warehouse:120",
"UOM:Link/UOM:100", "Actual Qty:Float:100", "Planned Qty:Float:100",
"Requested Qty:Float:110", "Ordered Qty:Float:100", "Reserved Qty:Float:100",
"Projected Qty:Float:100", "Reorder Level:Float:100", "Reorder Qty:Float:100"]
def get_item_conditions(filters):
conditions = []
@@ -41,4 +41,10 @@ def get_item_conditions(filters):
return "where {}".format(" and ".join(conditions)) if conditions else ""
def get_warehouse_conditions(filters):
return " and name=%(warehouse)s" if filters.get("warehouse") else ""
conditions = []
if filters.get("company"):
conditions.append("company=%(company)s")
if filters.get("warehouse"):
conditions.append("name=%(warehouse)s")
return "where {}".format(" and ".join(conditions)) if conditions else ""

View File

@@ -113,7 +113,14 @@ def update_entries_after(args, verbose=1):
(qty_after_transaction * valuation_rate) or 0
else:
stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue))
# rounding as per precision
from webnotes.model.meta import get_field_precision
meta = webnotes.get_doctype("Stock Ledger Entry")
stock_value = flt(stock_value, get_field_precision(meta.get_field("stock_value"),
webnotes._dict({"fields": sle})))
stock_value_difference = stock_value - prev_stock_value
prev_stock_value = stock_value