Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/accounts/doctype/journal_voucher/journal_voucher.py b/accounts/doctype/journal_voucher/journal_voucher.py
index 8b54f0f..9b1ca7a 100644
--- a/accounts/doctype/journal_voucher/journal_voucher.py
+++ b/accounts/doctype/journal_voucher/journal_voucher.py
@@ -375,9 +375,9 @@
(filters["account"], "%%%s%%" % txt, start, page_len))
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
- return webnotes.conn.sql("""select name, posting_date, user_remark
+ return webnotes.conn.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail
- where jv_detail.parent = jv.name and jv_detail.account = %s and docstatus = 1
+ where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
and jv.%s like %s order by jv.name desc limit %s, %s""" %
("%s", searchfield, "%s", "%s", "%s"),
(filters["account"], "%%%s%%" % txt, start, page_len))
\ No newline at end of file
diff --git a/selling/doctype/lead/lead.txt b/selling/doctype/lead/lead.txt
index ae8c6c4..e162551 100644
--- a/selling/doctype/lead/lead.txt
+++ b/selling/doctype/lead/lead.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-01-28 17:07:01",
"docstatus": 0,
- "modified": "2013-03-26 13:07:11",
+ "modified": "2013-03-26 14:05:01",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -118,6 +118,18 @@
"search_index": 0
},
{
+ "depends_on": "eval:doc.source == 'Customer'",
+ "description": "Source of th",
+ "doctype": "DocField",
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "label": "From Customer",
+ "oldfieldname": "customer",
+ "oldfieldtype": "Link",
+ "options": "Customer"
+ },
+ {
"depends_on": "eval:doc.source == 'Campaign'",
"description": "Enter campaign name if the source of lead is campaign.",
"doctype": "DocField",
@@ -145,37 +157,10 @@
},
{
"doctype": "DocField",
- "fieldname": "sb8",
+ "fieldname": "contact_info",
"fieldtype": "Section Break",
- "label": "Lead Details"
- },
- {
- "depends_on": "eval:doc.source == 'Existing Customer'",
- "description": "Source of th",
- "doctype": "DocField",
- "fieldname": "customer",
- "fieldtype": "Link",
- "hidden": 0,
- "label": "From Customer",
- "oldfieldname": "customer",
- "oldfieldtype": "Link",
- "options": "Customer"
- },
- {
- "doctype": "DocField",
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "width": "50%"
- },
- {
- "doctype": "DocField",
- "fieldname": "type",
- "fieldtype": "Select",
- "in_filter": 1,
- "label": "Lead Type",
- "oldfieldname": "type",
- "oldfieldtype": "Select",
- "options": "\nClient\nChannel Partner\nConsultant"
+ "label": "Contact Info",
+ "oldfieldtype": "Column Break"
},
{
"doctype": "DocField",
@@ -187,13 +172,6 @@
},
{
"doctype": "DocField",
- "fieldname": "contact_info",
- "fieldtype": "Section Break",
- "label": "Contact Info",
- "oldfieldtype": "Column Break"
- },
- {
- "doctype": "DocField",
"fieldname": "phone",
"fieldtype": "Data",
"label": "Phone",
@@ -308,6 +286,16 @@
"oldfieldtype": "Section Break"
},
{
+ "doctype": "DocField",
+ "fieldname": "type",
+ "fieldtype": "Select",
+ "in_filter": 1,
+ "label": "Lead Type",
+ "oldfieldname": "type",
+ "oldfieldtype": "Select",
+ "options": "\nClient\nChannel Partner\nConsultant"
+ },
+ {
"default": "__user",
"doctype": "DocField",
"fieldname": "lead_owner",
diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py
index f31f245..dbbeecc 100644
--- a/stock/doctype/item/test_item.py
+++ b/stock/doctype/item/test_item.py
@@ -146,4 +146,23 @@
"is_sub_contracted_item": "No",
"stock_uom": "_Test UOM"
}],
+ [{
+ "doctype": "Item",
+ "item_code": "_Test Serialized Item",
+ "item_name": "_Test Serialized Item",
+ "description": "_Test Serialized Item",
+ "item_group": "_Test Item Group Desktops",
+ "is_stock_item": "Yes",
+ "is_asset_item": "No",
+ "has_batch_no": "No",
+ "has_serial_no": "Yes",
+ "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"
+ }],
]
\ No newline at end of file
diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py
index 00f2de7..5b15977 100644
--- a/stock/doctype/serial_no/serial_no.py
+++ b/stock/doctype/serial_no/serial_no.py
@@ -19,14 +19,11 @@
from webnotes.utils import cint, getdate, nowdate
import datetime
-
-sql = webnotes.conn.sql
-msgprint = webnotes.msgprint
+from webnotes import msgprint, _
+from controllers.stock_controller import StockController
-from utilities.transaction_base import TransactionBase
-
-class DocType(TransactionBase):
+class DocType(StockController):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
@@ -54,21 +51,14 @@
"""
Validate whether serial no is required for this item
"""
- item = sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code)
+ item = webnotes.conn.sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code)
if not item:
msgprint("Item is not exists in the system", raise_exception=1)
elif item[0][1] == 'No':
msgprint("To proceed please select 'Yes' in 'Has Serial No' in Item master: '%s'" % self.doc.item_code, raise_exception=1)
- # ---------
- # validate
- # ---------
def validate(self):
- # import utilities
- # utilities.validate_status(self.doc.status, ["In Store", "Delivered",
- # "Not in Use", "Purchase Returned"])
-
self.validate_warranty_status()
self.validate_amc_status()
self.validate_warehouse()
@@ -77,10 +67,12 @@
def on_update(self):
if self.doc.warehouse and self.doc.status == 'In Store' \
and cint(self.doc.sle_exists) == 0 and \
- not sql("""select name from `tabStock Ledger Entry` where serial_no = %s and
- ifnull(is_cancelled, 'No') = 'No'""", self.doc.name):
+ not webnotes.conn.sql("""select name from `tabStock Ledger Entry`
+ where serial_no = %s and ifnull(is_cancelled, 'No') = 'No'""", self.doc.name):
self.make_stock_ledger_entry(1)
webnotes.conn.set(self.doc, 'sle_exists', 1)
+
+ self.make_gl_entries()
def make_stock_ledger_entry(self, qty):
from webnotes.model.code import get_obj
@@ -105,15 +97,13 @@
get_obj('Stock Ledger').update_stock(values)
- # ---------
- # on trash
- # ---------
def on_trash(self):
if self.doc.status == 'Delivered':
msgprint("Cannot trash Serial No : %s as it is already Delivered" % (self.doc.name), raise_exception = 1)
elif self.doc.status == 'In Store':
webnotes.conn.set(self.doc, 'status', 'Not in Use')
self.make_stock_ledger_entry(-1)
+ self.make_gl_entries(cancel=True)
def on_cancel(self):
@@ -121,6 +111,7 @@
def on_restore(self):
self.make_stock_ledger_entry(1)
+ self.make_gl_entries()
def on_rename(self, new, old):
"""rename serial_no text fields"""
@@ -135,7 +126,16 @@
where name=%s""" % (dt[0], '%s', '%s'),
('\n'.join(serial_nos), item[0]))
+ def make_gl_entries(self, cancel=False):
+ if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
+ return
-
+ from accounts.general_ledger import make_gl_entries
+ against_stock_account = self.get_company_default("stock_adjustment_account")
+ gl_entries = self.get_gl_entries_for_stock(against_stock_account, self.doc.purchase_rate)
+
+ for entry in gl_entries:
+ entry["posting_date"] = self.doc.purchase_date
-
\ No newline at end of file
+ if gl_entries:
+ make_gl_entries(gl_entries, cancel)
\ No newline at end of file
diff --git a/stock/doctype/serial_no/test_serial_no.py b/stock/doctype/serial_no/test_serial_no.py
index ef20de8..fb27aa9 100644
--- a/stock/doctype/serial_no/test_serial_no.py
+++ b/stock/doctype/serial_no/test_serial_no.py
@@ -1,93 +1,102 @@
# ERPNext - web based ERP (http://erpnext.com)
-# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
+# For license information, please see license.txt
from __future__ import unicode_literals
-import unittest
-import webnotes
-from webnotes.tests import insert_test_data
-
-company = webnotes.conn.get_default("company")
+import webnotes, unittest
class TestSerialNo(unittest.TestCase):
- def setUp(self):
- webnotes.conn.begin()
- self.insert_test_data()
-
- def tearDown(self):
- # print "Message Log:", "\n--\n".join(webnotes.message_log)
- # print "Debug Log:", "\n--\n".join(webnotes.debug_log)
- webnotes.conn.rollback()
+ def test_aii_gl_entries_for_serial_no_in_store(self):
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
- def test_serialized_stock_entry(self):
- data = [["2012-01-01", "01:00", "10001", 400, 400],
- ["2012-01-01", "03:00", "10002", 500, 700],
- ["2012-01-01", "04:00", "10003", 700, 700],
- ["2012-01-01", "05:00", "10004", 1200, 800],
- ["2012-01-01", "05:00", "10005", 800, 800],
- ["2012-01-01", "02:00", "10006", 1200, 800],
- ["2012-01-01", "06:00", "10007", 1500, 900]]
- for d in data:
- webnotes.bean([{
- "doctype": "Serial No",
- "item_code": "Nebula 8",
- "warehouse": "Default Warehouse",
- "status": "In Store",
- "sle_exists": 0,
- "purchase_date": d[0],
- "purchase_time": d[1],
- "serial_no": d[2],
- "purchase_rate": d[3],
- "company": company,
- }]).insert()
+ sr = webnotes.bean(copy=test_records[0])
+ sr.doc.serial_no = "_Test Serial No 1"
+ sr.insert()
+
+ stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
+ "stock_in_hand_account")
+ against_stock_account = webnotes.conn.get_value("Company", "_Test Company",
+ "stock_adjustment_account")
+
+ # check stock ledger entries
+ sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
+ where voucher_type = 'Serial No' and voucher_no = %s""", sr.doc.name, as_dict=1)[0]
+ self.assertTrue(sle)
+ self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty],
+ ["_Test Serialized Item", "_Test Warehouse", 1.0])
- for d in data:
- res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry`
- where posting_date=%s and posting_time=%s and actual_qty=1 and serial_no=%s""",
- (d[0], d[1], d[2]))
- self.assertEquals(res[0][0], d[4])
+ # check gl entries
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
+ order by account desc""", sr.doc.name, as_dict=1)
+ self.assertTrue(gl_entries)
- print "deleted"
- webnotes.delete_doc("Serial No", "10002")
+ expected_values = [
+ [stock_in_hand_account, 1000.0, 0.0],
+ [against_stock_account, 0.0, 1000.0]
+ ]
- test_data = [["10001", 400, 400],
- ["10003", 700, 766.666667],
- ["10004", 1200, 875],
- ["10005", 800, 860],
- ["10006", 1200, 800],
- ["10007", 1500, 966.666667]]
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_values[i][0], gle.account)
+ self.assertEquals(expected_values[i][1], gle.debit)
+ self.assertEquals(expected_values[i][2], gle.credit)
- for d in test_data:
- res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry`
- where actual_qty=1 and serial_no=%s""", (d[0],))
- self.assertEquals(res[0][0], d[2])
+ sr.load_from_db()
+ self.assertEquals(sr.doc.sle_exists, 1)
+
+ # save again
+ sr.save()
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
+ order by account desc""", sr.doc.name, as_dict=1)
+
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_values[i][0], gle.account)
+ self.assertEquals(expected_values[i][1], gle.debit)
+ self.assertEquals(expected_values[i][2], gle.credit)
+
+ # trash/cancel
+ sr.submit()
+ sr.cancel()
+
+ gl_count = webnotes.conn.sql("""select count(name) from `tabGL Entry`
+ where voucher_type='Serial No' and voucher_no=%s and ifnull(is_cancelled, 'No') = 'Yes'
+ order by account asc, name asc""", sr.doc.name)
+
+ self.assertEquals(gl_count[0][0], 4)
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+
+ def test_aii_gl_entries_for_serial_no_delivered(self):
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ sr = webnotes.bean(copy=test_records[0])
+ sr.doc.serial_no = "_Test Serial No 2"
+ sr.doc.status = "Delivered"
+ sr.insert()
+
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
+ order by account desc""", sr.doc.name, as_dict=1)
+ self.assertFalse(gl_entries)
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
- def insert_test_data(self):
- # create default warehouse
- if not webnotes.conn.exists("Warehouse", "Default Warehouse"):
- webnotes.insert({"doctype": "Warehouse",
- "warehouse_name": "Default Warehouse",
- "warehouse_type": "Stores"})
-
- # create UOM: Nos.
- if not webnotes.conn.exists("UOM", "Nos"):
- webnotes.insert({"doctype": "UOM", "uom_name": "Nos"})
-
- # create item groups and items
- insert_test_data("Item Group",
- sort_fn=lambda ig: (ig[0].get('parent_item_group'), ig[0].get('name')))
-
- insert_test_data("Item")
\ No newline at end of file
+
+test_records = [
+ [
+ {
+ "company": "_Test Company",
+ "doctype": "Serial No",
+ "serial_no": "_Test Serial No",
+ "status": "In Store",
+ "item_code": "_Test Serialized Item",
+ "item_group": "_Test Item Group",
+ "warehouse": "_Test Warehouse",
+ "purchase_rate": 1000.0,
+ "purchase_time": "11:37:39",
+ "purchase_date": "2013-02-26",
+ 'fiscal_year': "_Test Fiscal Year 2013"
+ }
+ ]
+]
\ No newline at end of file