Merge branch 'edge' of github.com:webnotes/erpnext into webshop

Conflicts:
	stock/doctype/item/item.txt
This commit is contained in:
Anand Doshi
2013-05-06 12:07:30 +05:30
77 changed files with 1376 additions and 370 deletions

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-03-26 11:03:07",
"creation": "2013-04-30 12:58:25",
"docstatus": 0,
"modified": "2013-03-26 12:48:18",
"modified": "2013-05-03 14:36:24",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -40,6 +40,7 @@
"doctype": "DocField",
"fieldname": "user",
"fieldtype": "Link",
"in_list_view": 1,
"label": "User",
"oldfieldname": "user",
"oldfieldtype": "Link",
@@ -99,6 +100,7 @@
"doctype": "DocField",
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Link",
@@ -210,12 +212,6 @@
"oldfieldtype": "Select",
"options": "link:Print Heading"
},
{
"create": 1,
"doctype": "DocPerm",
"role": "System Manager",
"write": 1
},
{
"create": 1,
"doctype": "DocPerm",

View File

@@ -45,7 +45,7 @@ class DocType(SellingController):
def validate(self):
super(DocType, self).validate()
self.fetch_missing_values()
self.validate_posting_time()
self.so_dn_required()
self.validate_proj_cust()
@@ -137,7 +137,27 @@ class DocType(SellingController):
def on_update_after_submit(self):
self.validate_recurring_invoice()
self.convert_to_recurring()
def fetch_missing_values(self):
# fetch contact and address details for customer, if they are not mentioned
if not (self.doc.contact_person and self.doc.customer_address):
for fieldname, val in self.get_default_address_and_contact("customer").items():
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
self.doc.fields[fieldname] = val
# fetch missing item values
for item in self.doclist.get({"parentfield": "entries"}):
if item.fields.get("item_code"):
ret = get_obj('Sales Common').get_item_details(item.fields, self)
for fieldname, value in ret.items():
if self.meta.get_field(fieldname, parentfield="entries") and \
not item.fields.get(fieldname):
item.fields[fieldname] = value
# fetch pos details, if they are not fetched
if cint(self.doc.is_pos):
self.set_pos_fields(for_validate=True)
def update_time_log_batch(self, sales_invoice):
for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
if d.time_log_batch:
@@ -153,60 +173,42 @@ class DocType(SellingController):
webnotes.msgprint(_("Time Log Batch status must be 'Submitted'") + ":" + d.time_log_batch,
raise_exception=True)
def set_pos_fields(self):
def set_pos_fields(self, for_validate=False):
"""Set retail related fields from pos settings"""
pos = self.pos_details
if pos:
val = webnotes.conn.sql("""select name from `tabAccount`
where name = %s and docstatus != 2""",
(cstr(self.doc.customer) + " - " + self.get_company_abbr()))
val = val and val[0][0] or ''
if not val: val = pos[0]['customer_account'] or ''
if cint(self.doc.is_pos) != 1:
return
if self.pos_settings:
pos = self.pos_settings[0]
self.doc.conversion_rate = flt(pos.conversion_rate)
if not self.doc.debit_to:
webnotes.conn.set(self.doc,'debit_to',val)
lst = ['territory', 'naming_series', 'currency', 'charge', 'letter_head', 'tc_name',
'price_list_name', 'company', 'select_print_heading', 'cash_bank_account']
self.doc.debit_to = self.doc.customer and webnotes.conn.get_value("Account", {
"name": self.doc.customer + " - " + self.get_company_abbr(),
"docstatus": ["!=", 2]
}) or pos.customer_account
for i in lst:
self.doc.fields[i] = pos[0][i] or ''
for fieldname in ('territory', 'naming_series', 'currency', 'charge', 'letter_head', 'tc_name',
'price_list_name', 'company', 'select_print_heading', 'cash_bank_account'):
if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
self.doc.fields[fieldname] = pos.get(fieldname)
self.set_pos_item_values()
self.doc.conversion_rate = flt(pos[0]['conversion_rate']) or 0
# set pos values in items
for doc in self.doclist.get({"parentfield": "entries"}):
if doc.fields.get('item_code'):
for fieldname, val in self.apply_pos_settings(doc.fields).items():
if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
doc.fields[fieldname] = val
#fetch terms
if self.doc.tc_name:
# fetch terms
if self.doc.tc_name and not self.doc.terms:
self.get_tc_details()
#fetch charges
if self.doc.charge:
# fetch charges
if self.doc.charge and not len(self.doclist.get({"parentfield": "other_charges"})):
self.get_other_charges()
def set_pos_item_values(self):
"""Set default values related to pos for previously created sales invoice."""
if cint(self.doc.is_pos) == 1:
dtl = self.pos_details
for d in getlist(self.doclist,'entries'):
# overwrite if mentioned in item
item = webnotes.conn.sql("""select default_income_account,
default_sales_cost_center, default_warehouse, purchase_account
from tabItem where name = %s""", (d.item_code,), as_dict=1)
d.income_account = (item and item[0]['default_income_account']) \
or (dtl and dtl[0]['income_account']) or d.income_account
d.cost_center = (item and item[0]['default_sales_cost_center']) \
or (dtl and dtl[0]['cost_center']) or d.cost_center
d.warehouse = (item and item[0]['default_warehouse']) \
or (dtl and dtl[0]['warehouse']) or d.warehouse
d.expense_account = (item and item[0].purchase_account) \
or (dtl and dtl[0].expense_account) or d.expense_account
def get_customer_account(self):
"""Get Account Head to which amount needs to be Debited based on Customer"""
if not self.doc.company:
@@ -299,60 +301,59 @@ class DocType(SellingController):
args = args and json.loads(args) or {}
if args.get('item_code'):
ret = get_obj('Sales Common').get_item_details(args, self)
return self.get_pos_details(args, ret)
else:
for doc in self.doclist:
if cint(self.doc.is_pos) == 1 and self.pos_settings:
ret = self.apply_pos_settings(args, ret)
return ret
elif cint(self.doc.is_pos) == 1 and self.pos_settings:
for doc in self.doclist.get({"parentfield": "entries"}):
if doc.fields.get('item_code'):
arg = {
'item_code':doc.fields.get('item_code'),
'income_account':doc.fields.get('income_account'),
'cost_center': doc.fields.get('cost_center'),
'warehouse': doc.fields.get('warehouse'),
'expense_account': doc.fields.get('expense_account'),
}
ret = self.get_pos_details(arg)
ret = self.apply_pos_settings(doc.fields)
for r in ret:
if not doc.fields.get(r):
doc.fields[r] = ret[r]
@property
def pos_details(self):
if not hasattr(self, "_pos_details"):
def pos_settings(self):
if not hasattr(self, "_pos_settings"):
dtl = webnotes.conn.sql("""select * from `tabPOS Setting` where user = %s
and company = %s""", (webnotes.session['user'], self.doc.company), as_dict=1)
if not dtl:
dtl = webnotes.conn.sql("""select * from `tabPOS Setting`
where ifnull(user,'') = '' and company = %s""", self.doc.company, as_dict=1)
self._pos_details = dtl
self._pos_settings = dtl
return self._pos_details
return self._pos_settings
def get_pos_details(self, args, ret = {}):
if args['item_code'] and cint(self.doc.is_pos) == 1:
dtl = self.pos_details
item = webnotes.conn.sql("""select default_income_account, default_sales_cost_center,
default_warehouse, purchase_account from tabItem where name = %s""",
args['item_code'], as_dict=1)
ret['income_account'] = item and item[0].get('default_income_account') \
or (dtl and dtl[0].get('income_account') or args.get('income_account'))
ret['cost_center'] = item and item[0].get('default_sales_cost_center') \
or (dtl and dtl[0].get('cost_center') or args.get('cost_center'))
def apply_pos_settings(self, args, ret=None):
if not ret: ret = {}
pos = self.pos_settings[0]
item = webnotes.conn.sql("""select default_income_account, default_sales_cost_center,
default_warehouse, purchase_account from tabItem where name = %s""",
args.get('item_code'), as_dict=1)
if item:
item = item[0]
ret['warehouse'] = item and item[0].get('default_warehouse') \
or (dtl and dtl[0].get('warehouse') or args.get('warehouse'))
ret.update({
"income_account": item.get("default_income_account") \
or pos.get("income_account") or args.get("income_account"),
"cost_center": item.get("default_sales_cost_center") \
or pos.get("cost_center") or args.get("cost_center"),
"warehouse": item.get("default_warehouse") \
or pos.get("warehouse") or args.get("warehouse"),
"expense_account": item.get("purchase_account") \
or pos.get("expense_account") or args.get("expense_account")
})
ret['expense_account'] = item and item[0].get('purchase_account') \
or (dtl and dtl[0].get('expense_account') or args.get('expense_account'))
if ret['warehouse']:
actual_qty = webnotes.conn.sql("""select actual_qty from `tabBin`
where item_code = %s and warehouse = %s""",
(args['item_code'], ret['warehouse']))
ret['actual_qty']= actual_qty and flt(actual_qty[0][0]) or 0
if ret.get("warehouse"):
ret["actual_qty"] = flt(webnotes.conn.get_value("Bin",
{"item_code": args.get("item_code"), "warehouse": args.get("warehouse")},
"actual_qty"))
return ret
def get_barcode_details(self, barcode):

View File

@@ -90,6 +90,9 @@ class TestSalesInvoice(unittest.TestCase):
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
old_default_company = webnotes.conn.get_default("company")
webnotes.conn.set_default("company", "_Test Company")
self._insert_purchase_receipt()
self._insert_pos_settings()
@@ -106,7 +109,8 @@ class TestSalesInvoice(unittest.TestCase):
# check stock ledger entries
sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where voucher_type = 'Sales Invoice' and voucher_no = %s""", si.doc.name, as_dict=1)[0]
where voucher_type = 'Sales Invoice' and voucher_no = %s""",
si.doc.name, as_dict=1)[0]
self.assertTrue(sle)
self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty],
["_Test Item", "_Test Warehouse", -5.0])
@@ -145,6 +149,7 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(gl_count[0][0], 16)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
webnotes.conn.set_default("company", old_default_company)
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
@@ -337,7 +342,7 @@ class TestSalesInvoice(unittest.TestCase):
# change posting date but keep recuring day to be today
si7 = webnotes.bean(copy=base_si.doclist)
si7.doc.fields.update({
"posting_date": add_to_date(today, days=-3)
"posting_date": add_to_date(today, days=-1)
})
si7.insert()
si7.submit()
@@ -345,7 +350,7 @@ class TestSalesInvoice(unittest.TestCase):
# setting so that _test function works
si7.doc.posting_date = today
self._test_recurring_invoice(si7, True)
def _test_recurring_invoice(self, base_si, first_and_last_day):
from webnotes.utils import add_months, get_last_day, getdate
from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices
@@ -361,7 +366,8 @@ class TestSalesInvoice(unittest.TestCase):
manage_recurring_invoices(next_date=next_date, commit=False)
recurred_invoices = webnotes.conn.sql("""select name from `tabSales Invoice`
where recurring_id=%s and docstatus=1 order by name desc""", base_si.doc.recurring_id)
where recurring_id=%s and docstatus=1 order by name desc""",
base_si.doc.recurring_id)
self.assertEquals(i+2, len(recurred_invoices))
@@ -395,7 +401,7 @@ class TestSalesInvoice(unittest.TestCase):
for i in xrange(count):
base_si = _test(i)
test_dependencies = ["Journal Voucher", "POS Setting"]
test_dependencies = ["Journal Voucher", "POS Setting", "Contact", "Address"]
test_records = [
[