From edc5f2edd007ed6318829d0fb97d385aec3baed4 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 26 Apr 2013 17:21:49 +0530 Subject: [PATCH] [sales invoice] [fetching] fetch pos values and customer address contact values --- .../doctype/sales_invoice/sales_invoice.py | 154 ++++++++---------- .../sales_invoice/test_sales_invoice.py | 2 +- utilities/doctype/address/test_address.py | 14 ++ utilities/transaction_base.py | 19 ++- 4 files changed, 104 insertions(+), 85 deletions(-) create mode 100644 utilities/doctype/address/test_address.py diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index f44a787de9..f0222a0ac7 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -46,6 +46,14 @@ class DocType(SellingController): def validate(self): super(DocType, self).validate() + 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 + + if cint(self.doc.is_pos): + self.set_pos_fields(for_validate=True) + self.validate_posting_time() self.so_dn_required() self.validate_proj_cust() @@ -153,60 +161,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 +289,58 @@ 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): diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index fd8dc648d2..31bf024e7f 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -395,7 +395,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 = [ [ diff --git a/utilities/doctype/address/test_address.py b/utilities/doctype/address/test_address.py new file mode 100644 index 0000000000..eddd9c754d --- /dev/null +++ b/utilities/doctype/address/test_address.py @@ -0,0 +1,14 @@ +test_records = [ + [{ + "doctype": "Address", + "customer": "_Test Customer", + "customer_name": "_Test Customer", + "address_type": "Office", + "address_title": "_Test Address", + "address_line1": "_Test Address Line 1", + "city": "_Test City", + "country": "India", + "phone": "+91 0000000000", + "is_primary_address": 1 + }], +] \ No newline at end of file diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index 4b34ba1286..5d7d1a84b1 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -22,6 +22,23 @@ from webnotes.model.doc import addchild from webnotes.model.controller import DocListController class TransactionBase(DocListController): + def get_default_address_and_contact(self, party_type): + """get a dict of default field values of address and contact for a given party type + party_type can be one of: customer, supplier""" + ret = {} + + # {customer: self.doc.fields.get("customer")} + args = {party_type: self.doc.fields.get(party_type)} + + address_text, address_name = self.get_address_text(**args) + ret.update({ + # customer_address + (party_type + "_address"): address_name, + "address_display": address_text + }) + ret.update(self.get_contact_text(**args)) + return ret + # Get Customer Default Primary Address - first load def get_default_customer_address(self, args=''): address_text, address_name = self.get_address_text(customer=self.doc.customer) @@ -73,7 +90,7 @@ class TransactionBase(DocListController): details = webnotes.conn.sql("select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_shipping_address desc, is_primary_address desc limit 1" % cond, as_dict = 1) else: details = webnotes.conn.sql("select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_primary_address desc limit 1" % cond, as_dict = 1) - + extract = lambda x: details and details[0] and details[0].get(x,'') or '' address_fields = [('','address_line1'),('\n','address_line2'),('\n','city'),('\n','state'),(' ','pincode'),('\n','country'),('\nPhone: ','phone'),('\nFax: ', 'fax')] address_display = ''.join([a[0]+extract(a[1]) for a in address_fields if extract(a[1])])