From a12e691825f6d17a9f7d6f23582b861dececcce6 Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Thu, 21 Aug 2008 02:04:33 +0530 Subject: [PATCH 01/20] * remove comment from the bin/addons/base/ir/ir_actions.py bzr revid: mga@tinyerp.com-20080820203433-xz58p9cn4xcru811 --- bin/addons/base/ir/ir_actions.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 806f129994f..e0b34a7932a 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -356,11 +356,8 @@ class actions_server(osv.osv): 'model_id': fields.many2one('ir.model', 'Model', required=True), 'trigger_name': fields.char('Trigger Name', size=128), 'trigger_obj_id': fields.reference('Trigger On', selection=model_get, size=128), - #'trigger_object': fields.char('Trigger Object', size=128), - #'trigger_object_id': fields.char('Trigger Object ID', size=128), 'message': fields.text('Message', translate=True), 'address': fields.many2one('ir.model.fields', 'Email From / SMS'), - #selection(_get_fields ,'Email / SMS', size=128), 'child_ids': fields.one2many('ir.actions.actions', 'parent_id', 'Others Actions'), 'usage': fields.char('Action Usage', size=32), 'type': fields.char('Report Type', size=32, required=True), From 92e1cd64c4b616a147624c6a64565a9f2772f9a4 Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Thu, 21 Aug 2008 14:34:40 +0530 Subject: [PATCH 02/20] * make globle method to fetch address and merging message bzr revid: mga@tinyerp.com-20080821090440-cgrfrm9cwdwemvrj --- bin/addons/base/ir/ir_actions.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index e0b34a7932a..768c6beeeff 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -376,7 +376,21 @@ class actions_server(osv.osv): # If you plan to return an action, assign: action = {...} """ } + + def get_address(self, cr, uid, action): + obj_pool = self.pool.get(action.model_id.model) + id = context.get('active_id') + obj = obj_pool.browse(cr, uid, id) + + fields = action.address.complete_name.split('/') + for field in fields: + obj = getattr(obj, field) + + return obj + def merge_message(self, cr, uid, action): + return action.message + # # Context should contains: # ids : original ids @@ -404,17 +418,8 @@ class actions_server(osv.osv): user = config['email_from'] subject = action.name - obj_pool = self.pool.get(action.model_id.model) - id = context.get('active_id') - obj = obj_pool.browse(cr, uid, id) - - fields = action.address.complete_name.split('/') - for field in fields: - obj = getattr(obj, field) - - address = obj - - body = action.message + address = self.get_address(cr, uid, action) + body = self.merge_message(cr, uid, action) #TODO : Apply Mail merge in to the Content of the Email if tools.email_send_attach(user, address, subject, body, debug=False) == True: From c1d400209fcf43986e63552adc8bc6c226603db3 Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Thu, 21 Aug 2008 16:06:17 +0530 Subject: [PATCH 03/20] * change content type in to the email send method * Implement the mail marge method * change in to the view to have tiny_mce editor in e-tiny bzr revid: mga@tinyerp.com-20080821103617-wrct24u6imwv9cnb --- bin/addons/base/ir/ir.xml | 4 +-- bin/addons/base/ir/ir_actions.py | 47 +++++++++++++++++++++++++++----- bin/tools/misc.py | 2 +- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index 542daa77e75..8135406e02f 100755 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1055,12 +1055,12 @@ - + - diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 768c6beeeff..b646564c897 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -33,6 +33,7 @@ import tools import time from tools.config import config import netsvc +import re class actions(osv.osv): _name = 'ir.actions.actions' @@ -377,19 +378,51 @@ class actions_server(osv.osv): """ } - def get_address(self, cr, uid, action): + def get_field_value(self, cr, uid, action, context): obj_pool = self.pool.get(action.model_id.model) id = context.get('active_id') obj = obj_pool.browse(cr, uid, id) - fields = action.address.complete_name.split('/') + fields = None + + if '/' in action.address.complete_name: + fields = action.address.complete_name.split('/') + elif '.' in action.address.complete_name: + fields = action.address.complete_name.split('.') + for field in fields: - obj = getattr(obj, field) + try: + obj = getattr(obj, field) + except Exception,e : + logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (match.group())) return obj - def merge_message(self, cr, uid, action): - return action.message + def merge_message(self, cr, uid, action, context): + logger = netsvc.Logger() + def merge(match): + + obj_pool = self.pool.get(action.model_id.model) + id = context.get('active_id') + obj = obj_pool.browse(cr, uid, id) + + field = match.group() + field = field.replace('[','') + field = field.replace(']','') + field = field.strip() + + fields = field.split('.') + for field in fields: + try: + obj = getattr(obj, field) + except Exception,e : + logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (match.group())) + + return str(obj) + + com = re.compile('\[\[(.+?)\]\]') + message = com.sub(merge, str(action.message)) + return message # # Context should contains: @@ -418,8 +451,8 @@ class actions_server(osv.osv): user = config['email_from'] subject = action.name - address = self.get_address(cr, uid, action) - body = self.merge_message(cr, uid, action) + address = self.get_field_value(cr, uid, action, context) + body = self.merge_message(cr, uid, action, context) #TODO : Apply Mail merge in to the Content of the Email if tools.email_send_attach(user, address, subject, body, debug=False) == True: diff --git a/bin/tools/misc.py b/bin/tools/misc.py index e02785efa18..d1a90a35ac5 100644 --- a/bin/tools/misc.py +++ b/bin/tools/misc.py @@ -394,7 +394,7 @@ def email_send_attach(email_from, email_to, subject, body, email_cc=None, email_ if tinycrm: msg['Message-Id'] = '<'+str(time.time())+'-tinycrm-'+str(tinycrm)+'@'+socket.gethostname()+'>' msg['Date'] = formatdate(localtime=True) - msg.attach( MIMEText(body or '', _charset='utf-8') ) + msg.attach( MIMEText(body or '', _charset='utf-8', _subtype="html")) for (fname,fcontent) in attach: part = MIMEBase('application', "octet-stream") part.set_payload( fcontent ) From bb31f33da6b344413c38842a6a07998be8536555 Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Thu, 21 Aug 2008 16:54:25 +0530 Subject: [PATCH 04/20] * Bug-Fix for the Dashboard - changein write method of the ir.ui.view bzr revid: mga@tinyerp.com-20080821112425-hbkppvql30kmum9t --- bin/addons/base/ir/ir_ui_view.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/addons/base/ir/ir_ui_view.py b/bin/addons/base/ir/ir_ui_view.py index 6bf326bd33e..97387b3b6dd 100644 --- a/bin/addons/base/ir/ir_ui_view.py +++ b/bin/addons/base/ir/ir_ui_view.py @@ -80,12 +80,13 @@ class view(osv.osv): (_check_xml, 'Invalid XML for View Architecture!', ['arch']) ] - def read(self,cr, uid, ids, fields=None, context={}, load='_classic_read'): + def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'): if not isinstance(ids, (list, tuple)): ids = [ids] result = super(view, self).read(cr, uid, ids, fields, context, load) + print '************************** : ',result for rs in result: if rs.get('model') == 'board.board': @@ -94,6 +95,7 @@ class view(osv.osv): if oview: rs['arch'] = oview[0]['arch'] + return result def write(self, cr, uid, ids, vals, context={}): @@ -107,7 +109,7 @@ class view(osv.osv): vals2 = {'user_id': uid, 'ref_id': ids[0], 'arch': vals.pop('arch')} # write fields except arch to the `ir.ui.view` - result = super(view, self).write(cr, uid, vids, vals, context) + result = super(view, self).write(cr, uid, ids, vals, context) if not vids: self.pool.get('ir.ui.view.custom').create(cr, uid, vals2) From f89f8c3c2df7460bc58a18a9b23709c2d9742472 Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Thu, 21 Aug 2008 17:48:10 +0530 Subject: [PATCH 05/20] committee un commited changes bzr revid: mga@tinyerp.com-20080821121810-c1xr1j5i74sez609 --- bin/addons/base/ir/ir_actions.py | 1 + bin/addons/base/ir/ir_ui_view.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index b646564c897..724f546bc3d 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -279,6 +279,7 @@ class ir_model_fields(osv.osv): } def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80): + def get_fields(cr, uid, field, rel): result = [] mobj = self.pool.get('ir.model') diff --git a/bin/addons/base/ir/ir_ui_view.py b/bin/addons/base/ir/ir_ui_view.py index 97387b3b6dd..fd43bac2900 100644 --- a/bin/addons/base/ir/ir_ui_view.py +++ b/bin/addons/base/ir/ir_ui_view.py @@ -86,7 +86,6 @@ class view(osv.osv): ids = [ids] result = super(view, self).read(cr, uid, ids, fields, context, load) - print '************************** : ',result for rs in result: if rs.get('model') == 'board.board': From a2acce64f64b45126c592545baaa51af15036f4f Mon Sep 17 00:00:00 2001 From: Mustufa Rangwala Date: Fri, 22 Aug 2008 14:27:08 +0530 Subject: [PATCH 06/20] added boolean field on journal and modify move object bzr revid: mra@tinyerp.com-20080822085708-ijrakip4amwlgoy1 --- addons/account/account.py | 32 ++++++++++++++++++-------------- addons/account/account_view.xml | 1 + 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/addons/account/account.py b/addons/account/account.py index 99e3bb9ee68..8b37e6431fd 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -139,7 +139,7 @@ class account_account(osv.osv): context=None, count=False): if context is None: context = {} - pos = 0 + pos = 0 while pos + From 3f649972d9c045c53b5aecf0ed488216864a560d Mon Sep 17 00:00:00 2001 From: Mustufa Rangwala Date: Fri, 22 Aug 2008 17:23:40 +0530 Subject: [PATCH 07/20] modify button confirmation action bzr revid: mra@tinyerp.com-20080822115340-9qi06s066v7igmhr --- addons/account/account_bank_statement.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 4b860a520c5..79c96359dcf 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -138,7 +138,7 @@ class account_bank_statement(osv.osv): 'currency': fields.function(_currency, method=True, string='Currency', type='many2one', relation='res.currency'), } - + _defaults = { 'name': lambda self, cr, uid, context=None: \ self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement'), @@ -289,6 +289,8 @@ class account_bank_statement(osv.osv): except: raise osv.except_osv(_('Error !'), _('Unable to reconcile entry "%s": %.2f') % (move.name, move.amount)) + if st.journal_id.entry_posted: + account_move_obj.write(cr, uid, [move_id], {'state':'posted'}) done.append(st.id) self.write(cr, uid, done, {'state':'confirm'}, context=context) return True From 8eaa179e9a2e868b1209217c959037a5cb13a6f3 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 22 Aug 2008 15:33:44 +0200 Subject: [PATCH 08/20] add base_vat_check module bzr revid: christophe@tinyerp.com-20080822133344-3h8dt2qsk9jvieki --- addons/base_vat_check/__init__.py | 34 + addons/base_vat_check/__terp__.py | 42 ++ addons/base_vat_check/partner.py | 1027 +++++++++++++++++++++++++++++ 3 files changed, 1103 insertions(+) create mode 100644 addons/base_vat_check/__init__.py create mode 100644 addons/base_vat_check/__terp__.py create mode 100644 addons/base_vat_check/partner.py diff --git a/addons/base_vat_check/__init__.py b/addons/base_vat_check/__init__.py new file mode 100644 index 00000000000..af7847dfb9d --- /dev/null +++ b/addons/base_vat_check/__init__.py @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved. +# +# $Id$ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import partner + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/base_vat_check/__terp__.py b/addons/base_vat_check/__terp__.py new file mode 100644 index 00000000000..48200c92fc9 --- /dev/null +++ b/addons/base_vat_check/__terp__.py @@ -0,0 +1,42 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004-2008 Tiny SPRL (http://tiny.be) All Rights Reserved. +# +# $Id$ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +############################################################################### +{ + "name": "VAT Check", + "description": "Add a check of the VAT Number. Idea and code from Tryton (c2bk)", + "version": "1.0", + "author": "Tiny", + "category": "Generic Modules/Base", + "depends": ["base", "base_vat"], + "update_xml": [], + "active": False, + "installable": True, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/base_vat_check/partner.py b/addons/base_vat_check/partner.py new file mode 100644 index 00000000000..c5f9010cf91 --- /dev/null +++ b/addons/base_vat_check/partner.py @@ -0,0 +1,1027 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004-2008 Tiny SPRL (http://tiny.be) All Rights Reserved. +# +# $Id$ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +############################################################################### + +from osv import osv + + +class res_partner(osv.osv): + _inherit = 'res.partner' + + def check_vat(self, cr, uid, ids): + ''' + Check the VAT number depending of the country. + http://sima-pc.com/nif.php + ''' + for partner in self.browse(cr, uid, ids): + if not partner.vat_subject: + continue + if not partner.vat: + continue #FIXME return False? empty vat numbre is invalid? + + vat_country, vat_number = partner.vat[:2].lower(), partner.vat[2:] + if not getattr(self, 'check_vat_' + vat_country)(vat_number): + return False + + return True + + _constraints = [(check_vat, "The VAT doesn't seem to be correct.", ["vat"])] + + # code from the following methods come from Tryton (c2bk) + # http://www.tryton.org/hgwebdir.cgi/modules/relationship/file/544d1de586d9/party.py + def check_vat_at(self, vat): + ''' + Check Austria VAT number. + ''' + if len(vat) != 9: + return False + if vat[0] != 'U': + return False + num = vat[1:] + try: + int(num) + except: + return False + sum = int(num[0]) + mult_add(2, int(num[1])) + \ + int(num[2]) + mult_add(2, int(num[3])) + \ + int(num[4]) + mult_add(2, int(num[5])) + \ + int(num[6]) + check = 10 - ((sum + 4) % 10) + if check == 10: + check = 0 + if int(vat[-1:]) != check: + return False + return True + + def check_vat_be(self, vat): + ''' + Check Belgium VAT number. + ''' + if len(vat) != 10: + return False + try: + int(vat) + except: + return False + if int(vat[-2:]) != \ + 97 - (int(vat[:8]) % 97): + return False + return True + + def check_vat_bg(self, vat): + ''' + Check Bulgaria VAT number. + ''' + if len(vat) != 10: + return False + try: + int(vat) + except: + return False + if int(vat[0]) in (2, 3) and \ + int(vat[1:2]) != 22: + return False + sum = 4 * int(vat[0]) + 3 * int(vat[1]) + 2 * int(vat[2]) + \ + 7 * int(vat[3]) + 6 * int(vat[4]) + 5 * int(vat[5]) + \ + 4 * int(vat[6]) + 3 * int(vat[7]) + 2 * int(vat[8]) + check = 11 - (sum % 11) + if check == 11: + check = 0 + if check == 10: + return False + if check != int(vat[9]): + return False + return True + + def check_vat_cy(self, vat): + ''' + Check Cyprus VAT number. + ''' + if len(vat) != 9: + return False + try: + int(vat[:8]) + except: + return False + n0 = int(vat[0]) + n1 = int(vat[1]) + n2 = int(vat[2]) + n3 = int(vat[3]) + n4 = int(vat[4]) + n5 = int(vat[5]) + n6 = int(vat[6]) + n7 = int(vat[7]) + + def conv(x): + if x == 0: + return 1 + elif x == 1: + return 0 + elif x == 2: + return 5 + elif x == 3: + return 7 + elif x == 4: + return 9 + elif x == 5: + return 13 + elif x == 6: + return 15 + elif x == 7: + return 17 + elif x == 8: + return 19 + elif x == 9: + return 21 + return x + n0 = conv(n0) + n2 = conv(n2) + n4 = conv(n4) + n6 = conv(n6) + + sum = n0 + n1 + n2 + n3 + n4 + n5 + n6 + n7 + check = chr(sum % 26 + 65) + if check != vat[8]: + return False + return True + + def check_vat_cz(self, vat): + ''' + Check Czech Republic VAT number. + ''' + if len(vat) not in (8, 9, 10): + return False + try: + int(vat) + except: + return False + + if len(vat) == 8: + if int(vat[0]) not in (0, 1, 2, 3, 4, 5, 6, 7, 8): + return False + sum = 8 * int(vat[0]) + 7 * int(vat[1]) + 6 * int(vat[2]) + \ + 5 * int(vat[3]) + 4 * int(vat[4]) + 3 * int(vat[5]) + \ + 2 * int(vat[6]) + check = 11 - (sum % 11) + if check == 10: + check = 0 + if check == 11: + check = 1 + if check != int(vat[7]): + return False + elif len(vat) == 9 and int(vat[0]) == 6: + sum = 8 * int(vat[1]) + 7 * int(vat[2]) + 6 * int(vat[3]) + \ + 5 * int(vat[4]) + 4 * int(vat[5]) + 3 * int(vat[6]) + \ + 2 * int(vat[7]) + check = 9 - ((11 - (sum % 11)) % 10) + if check != int(vat[8]): + return False + elif len(vat) == 9: + if int(vat[0:2]) > 53 and int(vat[0:2]) < 80: + return False + if int(vat[2:4]) < 1: + return False + if int(vat[2:4]) > 12 and int(vat[2:4]) < 51: + return False + if int(vat[2:4]) > 62: + return False + if int(vat[2:4]) in (2, 52) and int(vat[0:2]) % 4 > 0: + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 28: + return False + if int(vat[2:4]) in (2, 52) and int(vat[0:2]) % 4 == 0: + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 29: + return False + if int(vat[2:4]) in (4, 6, 9, 11, 54, 56, 59, 61): + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 30: + return False + if int(vat[2:4]) in (1, 3, 5, 7, 8, 10, 12, 51, + 53, 55, 57, 58, 60, 62): + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 31: + return False + elif len(vat) == 10: + if int(vat[0:2]) < 54: + return False + if int(vat[2:4]) < 1: + return False + if int(vat[2:4]) > 12 and int(vat[2:4]) < 51: + return False + if int(vat[2:4]) > 62: + return False + if int(vat[2:4]) in (2, 52) and int(vat[0:2]) % 4 > 0: + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 28: + return False + if int(vat[2:4]) in (2, 52) and int(vat[0:2]) % 4 == 0: + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 29: + return False + if int(vat[2:4]) in (4, 6, 9, 11, 54, 56, 59, 61): + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 30: + return False + if int(vat[2:4]) in (1, 3, 5, 7, 8, 10, 12, 51, + 53, 55, 57, 58, 60, 62): + if int(vat[4:6]) < 1: + return False + if int(vat[4:6]) > 31: + return False + if (int(vat[0:2]) + int(vat[2:4]) + int(vat[4:6]) + int(vat[6:8]) + + int(vat[8:10])) % 11 != 0: + return False + if int(vat[0:10]) % 11 != 0: + return False + return True + + def check_vat_de(self, vat): + ''' + Check Germany VAT number. + ''' + if len(vat) != 9: + return False + try: + int(vat) + except: + return False + if int(vat[0:7]) <= 0: + return False + sum = 0 + for i in range(8): + sum = (2 * ((int(vat[i]) + sum + 9) % 10 + 1)) % 11 + check = 11 - sum + if check == 10: + check = 0 + if int(vat[8]) != check: + return False + return True + + def check_vat_dk(self, vat): + ''' + Check Denmark VAT number. + ''' + if len(vat) != 8: + return False + try: + int(vat) + except: + return False + if int(vat[0]) <= 0: + return False + sum = 2 * int(vat[0]) + 7 * int(vat[1]) + 6 * int(vat[2]) + \ + 5 * int(vat[3]) + 4 * int(vat[4]) + 3 * int(vat[5]) + \ + 2 * int(vat[6]) + int(vat[7]) + if sum % 11 != 0: + return False + return True + + def check_vat_ee(self, vat): + ''' + Check Estonia VAT number. + ''' + if len(vat) != 9: + return False + try: + int(vat) + except: + return False + sum = 3 * int(vat[0]) + 7 * int(vat[1]) + 1 * int(vat[2]) + \ + 3 * int(vat[3]) + 7 * int(vat[4]) + 1 * int(vat[5]) + \ + 3 * int(vat[6]) + 7 * int(vat[7]) + check = 10 - (sum % 10) + if check == 10: + check = 0 + if check != int(vat[8]): + return False + return True + + def check_vat_es(self, vat): + ''' + Check Spain VAT number. + ''' + if len(vat) != 9: + return False + + conv = { + 1: 'T', + 2: 'R', + 3: 'W', + 4: 'A', + 5: 'G', + 6: 'M', + 7: 'Y', + 8: 'F', + 9: 'P', + 10: 'D', + 11: 'X', + 12: 'B', + 13: 'N', + 14: 'J', + 15: 'Z', + 16: 'S', + 17: 'Q', + 18: 'V', + 19: 'H', + 20: 'L', + 21: 'C', + 22: 'K', + 23: 'E', + } + + if vat[0] in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'): + try: + int(vat[1:]) + except: + return False + sum = mult_add(2, int(vat[1])) + int(vat[2]) + \ + mult_add(2, int(vat[3])) + int(vat[4]) + \ + mult_add(2, int(vat[5])) + int(vat[6]) + \ + mult_add(2, int(vat[7])) + check = 10 - (sum % 10) + if check == 10: + check = 0 + if check != int(vat[8]): + return False + return True + elif vat[0] in ('N', 'P', 'Q', 'S'): + try: + int(vat[1:8]) + except: + return False + sum = mult_add(2, int(vat[1])) + int(vat[2]) + \ + mult_add(2, int(vat[3])) + int(vat[4]) + \ + mult_add(2, int(vat[5])) + int(vat[6]) + \ + mult_add(2, int(vat[7])) + check = 10 - (sum % 10) + check = chr(check + 64) + if check != vat[8]: + return False + return True + elif vat[0] in ('K', 'L', 'M', 'X'): + try: + int(vat[1:8]) + except: + return False + check = 1 + (int(vat[1:8]) % 23) + + check = conv[check] + if check != vat[8]: + return False + return True + else: + try: + int(vat[:8]) + except: + return False + check = 1 + (int(vat[:8]) % 23) + + check = conv[check] + if check != vat[8]: + return False + return True + + def check_vat_fi(self, vat): + ''' + Check Finland VAT number. + ''' + if len(vat) != 8: + return False + try: + int(vat) + except: + return False + sum = 7 * int(vat[0]) + 9 * int(vat[1]) + 10 * int(vat[2]) + \ + 5 * int(vat[3]) + 8 * int(vat[4]) + 4 * int(vat[5]) + \ + 2 * int(vat[6]) + check = 11 - (sum % 11) + if check == 11: + check = 0 + if check == 10: + return False + if check != int(vat[7]): + return False + return True + + def check_vat_fr(self, vat): + ''' + Check France VAT number. + ''' + if len(vat) != 11: + return False + + try: + int(vat[2:11]) + except: + return False + + system = None + try: + int(vat[0:2]) + system = 'old' + except: + system = 'new' + + if system == 'old': + check = ((int(vat[2:11]) * 100) + 12) % 97 + if check != int(vat[0:2]): + return False + return True + else: + conv = ['0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z'] + if vat[0] not in conv \ + or vat[1] not in conv: + return False + c1 = conv.index(vat[0]) + c2 = conv.index(vat[1]) + + if c1 < 10: + sum = c1 * 24 + c2 - 10 + else: + sum = c1 * 34 + c2 - 100 + + x = sum % 11 + sum = (int(sum) / 11) + 1 + y = (int(vat[2:11]) + sum) % 11 + if x != y: + return False + return True + + def check_vat_gb(self, vat): + ''' + Check United Kingdom VAT number. + ''' + + if len(vat) == 5: + try: + int(vat[2:5]) + except: + return False + + if vat[0:2] == 'GD': + if int(vat[2:5]) >= 500: + return False + return True + if vat[0:2] == 'HA': + if int(vat[2:5]) < 500: + return False + return True + return False + elif len(vat) in (9, 10): + try: + int(vat) + except: + return False + + if int(vat[0:7]) < 1: + return False + if int(vat[0:7]) > 19999 and int(vat[0:7]) < 1000000: + return False + if int(vat[7:9]) > 97: + return False + if len(vat) == 10 and int(vat[9]) != 3: + return False + + sum = 8 * int(vat[0]) + 7 * int(vat[1]) + 6 * int(vat[2]) + \ + 5 * int(vat[3]) + 4 * int(vat[4]) + 3 * int(vat[5]) + \ + 2 * int(vat[6]) + 10 * int(vat[7]) + int(vat[8]) + if sum % 97 != 0: + return False + return True + elif len(vat) in (12, 13): + try: + int(vat) + except: + return False + + if int(vat[0:3]) not in (0, 1): + return False + + if int(vat[3:10]) < 1: + return False + if int(vat[3:10]) > 19999 and int(vat[3:10]) < 1000000: + return False + if int(vat[10:12]) > 97: + return False + if len(vat) == 13 and int(vat[12]) != 3: + return False + + sum = 8 * int(vat[3]) + 7 * int(vat[4]) + 6 * int(vat[5]) + \ + 5 * int(vat[6]) + 4 * int(vat[7]) + 3 * int(vat[8]) + \ + 2 * int(vat[9]) + 10 * int(vat[10]) + int(vat[11]) + if sum % 97 != 0: + return False + return True + return False + + def check_vat_gr(self, vat): + ''' + Check Greece VAT number. + ''' + try: + int(vat) + except: + return False + if len(vat) == 8: + sum = 128 * int(vat[0]) + 64 * int(vat[1]) + 32 * int(vat[2]) + \ + 16 * int(vat[3]) + 8 * int(vat[4]) + 4 * int(vat[5]) + \ + 2 * int(vat[6]) + check = sum % 11 + if check == 10: + check = 0 + if check != int(vat[7]): + return False + return True + elif len(vat) == 9: + sum = 256 * int(vat[0]) + 128 * int(vat[1]) + 64 * int(vat[2]) + \ + 32 * int(vat[3]) + 16 * int(vat[4]) + 8 * int(vat[5]) + \ + 4 * int(vat[6]) + 2 * int(vat[7]) + check = sum % 11 + if check == 10: + check = 0 + if check != int(vat[8]): + return False + return True + return False + + def check_vat_el(self, vat): + return self.check_vat_gr(vat) + + def check_vat_hu(self, vat): + ''' + Check Hungary VAT number. + ''' + if len(vat) != 8: + return False + try: + int(vat) + except: + return False + if int(vat[0]) <= 0: + return False + sum = 9 * int(vat[0]) + 7 * int(vat[1]) + 3 * int(vat[2]) + \ + 1 * int(vat[3]) + 9 * int(vat[4]) + 7 * int(vat[5]) + \ + 3 * int(vat[6]) + check = 10 - (sum % 10) + if check == 10: + check = 0 + if check != int(vat[7]): + return False + return True + + def check_vat_ie(self, vat): + ''' + Check Ireland VAT number. + ''' + if len(vat) != 8: + return False + if (ord(vat[1]) >= 65 and ord(vat[1]) <= 90) \ + or vat[1] in ('+', '*'): + try: + int(vat[0]) + int(vat[2:7]) + except: + return False + + if int(vat[0]) <= 6: + return False + + sum = 7 * int(vat[2]) + 6 * int(vat[3]) + 5 * int(vat[4]) + \ + 4 * int(vat[5]) + 3 * int(vat[6]) + 2 * int(vat[0]) + check = sum % 23 + if check == 0: + check = 'W' + else: + check = chr(check + 64) + if check != vat[7]: + return False + return True + else: + try: + int(vat[0:7]) + except: + return False + + sum = 8 * int(vat[0]) + 7 * int(vat[1]) + 6 * int(vat[2]) + \ + 5 * int(vat[3]) + 4 * int(vat[4]) + 3 * int(vat[5]) + \ + 2 * int(vat[6]) + check = sum % 23 + if check == 0: + check = 'W' + else: + check = chr(check + 64) + if check != vat[7]: + return False + return True + + def check_vat_it(self, vat): + ''' + Check Italy VAT number. + ''' + if len(vat) != 11: + return False + try: + int(vat) + except: + return False + if int(vat[0:7]) <= 0: + return False + if int(vat[7:10]) <= 0: + return False + if int(vat[7:10]) > 100 and int(vat[7:10]) < 120: + return False + if int(vat[7:10]) > 121: + return False + + sum = int(vat[0]) + mult_add(2, int(vat[1])) + int(vat[2]) + \ + mult_add(2, int(vat[3])) + int(vat[4]) + \ + mult_add(2, int(vat[5])) + int(vat[6]) + \ + mult_add(2, int(vat[7])) + int(vat[8]) + \ + mult_add(2, int(vat[9])) + check = 10 - (sum % 10) + if check == 10: + check = 0 + if check != int(vat[10]): + return False + return True + + def check_vat_lt(self, vat): + ''' + Check Lithuania VAT number. + ''' + try: + int(vat) + except: + return False + + if len(vat) == 9: + if int(vat[7]) != 1: + return False + sum = 1 * int(vat[0]) + 2 * int(vat[1]) + 3 * int(vat[2]) + \ + 4 * int(vat[3]) + 5 * int(vat[4]) + 6 * int(vat[5]) + \ + 7 * int(vat[6]) + 8 * int(vat[7]) + if sum % 11 == 10: + sum = 3 * int(vat[0]) + 4 * int(vat[1]) + 5 * int(vat[2]) + \ + 6 * int(vat[3]) + 7 * int(vat[4]) + 8 * int(vat[5]) + \ + 9 * int(vat[6]) + 1 * int(vat[7]) + check = sum % 11 + if check == 10: + check = 0 + if check != int(vat[8]): + return False + return True + elif len(vat) == 12: + if int(vat[10]) != 1: + return False + sum = 1 * int(vat[0]) + 2 * int(vat[1]) + 3 * int(vat[2]) + \ + 4 * int(vat[3]) + 5 * int(vat[4]) + 6 * int(vat[5]) + \ + 7 * int(vat[6]) + 8 * int(vat[7]) + 9 * int(vat[8]) + \ + 1 * int(vat[9]) + 2 * int(vat[10]) + if sum % 11 == 10: + sum = 3 * int(vat[0]) + 4 * int(vat[1]) + 5 * int(vat[2]) + \ + 6 * int(vat[3]) + 7 * int(vat[4]) + 8 * int(vat[5]) + \ + 9 * int(vat[6]) + 1 * int(vat[7]) + 2 * int(vat[8]) + \ + 3 * int(vat[9]) + 4 * int(vat[10]) + check = sum % 11 + if check == 10: + check = 0 + if check != int(vat[11]): + return False + return True + return False + + def check_vat_lu(self, vat): + ''' + Check Luxembourg VAT number. + ''' + if len(vat) != 8: + return False + try: + int(vat) + except: + return False + if int(vat[0:6]) <= 0: + return False + check = int(vat[0:6]) % 89 + if check != int(vat[6:8]): + return False + return True + + def check_vat_lv(self, vat): + ''' + Check Latvia VAT number. + ''' + if len(vat) != 11: + return False + try: + int(vat) + except: + return False + if int(vat[0]) >= 4: + sum = 9 * int(vat[0]) + 1 * int(vat[1]) + 4 * int(vat[2]) + \ + 8 * int(vat[3]) + 3 * int(vat[4]) + 10 * int(vat[5]) + \ + 2 * int(vat[6]) + 5 * int(vat[7]) + 7 * int(vat[8]) + \ + 6 * int(vat[9]) + if sum % 11 == 4 and int(vat[0]) == 9: + sum = sum - 45 + if sum % 11 == 4: + check = 4 - (sum % 11) + elif sum % 11 > 4: + check = 14 - (sum % 11) + elif sum % 11 < 4: + check = 3 - (sum % 11) + if check != int(vat[10]): + return False + return True + else: + if int(vat[2:4]) == 2 and int(vat[4:6]) % 4 > 0: + if int(vat[0:2]) < 1 or int(vat[0:2]) > 28: + return False + if int(vat[2:4]) == 2 and int(vat[4:6]) % 4 == 0: + if int(vat[0:2]) < 1 or int(vat[0:2]) > 29: + return False + if int(vat[2:4]) in (4, 6, 9, 11): + if int(vat[0:2]) < 1 or int(vat[0:2]) > 30: + return False + if int(vat[2:4]) in (1, 3, 5, 7, 8, 10, 12): + if int(vat[0:2]) < 1 or int(vat[0:2]) > 31: + return False + if int(vat[2:4]) < 1 or int(vat[2:4]) > 12: + return False + return True + + def check_vat_mt(self, vat): + ''' + Check Malta VAT number. + ''' + if len(vat) != 8: + return False + try: + int(vat) + except: + return False + + if int(vat[0:6]) < 100000: + return False + + sum = 3 * int(vat[0]) + 4 * int(vat[1]) + 6 * int(vat[2]) + \ + 7 * int(vat[3]) + 8 * int(vat[4]) + 9 * int(vat[5]) + check = 37 - (sum % 37) + if check != int(vat[6:8]): + return False + return True + + def check_vat_nl(self, vat): + ''' + Check Netherlands VAT number. + ''' + if len(vat) != 12: + return False + try: + int(vat[0:9]) + int(vat[10:12]) + except: + return False + if int(vat[0:8]) <= 0: + return False + if vat[9] != 'B': + return False + + sum = 9 * int(vat[0]) + 8 * int(vat[1]) + 7 * int(vat[2]) + \ + 6 * int(vat[3]) + 5 * int(vat[4]) + 4 * int(vat[5]) + \ + 3 * int(vat[6]) + 2 * int(vat[7]) + + check = sum % 11 + if check == 10: + return False + if check != int(vat[8]): + return False + return True + + def check_vat_pl(self, vat): + ''' + Check Poland VAT number. + ''' + if len(vat) != 10: + return False + try: + int(vat) + except: + return False + + sum = 6 * int(vat[0]) + 5 * int(vat[1]) + 7 * int(vat[2]) + \ + 2 * int(vat[3]) + 3 * int(vat[4]) + 4 * int(vat[5]) + \ + 5 * int(vat[6]) + 6 * int(vat[7]) + 7 * int(vat[8]) + check = sum % 11 + if check == 10: + return False + if check != int(vat[9]): + return False + return True + + def check_vat_pt(self, vat): + ''' + Check Portugal VAT number. + ''' + if len(vat) != 9: + return False + try: + int(vat) + except: + return False + + if int(vat[0]) <= 0: + return False + + sum = 9 * int(vat[0]) + 8 * int(vat[1]) + 7 * int(vat[2]) + \ + 6 * int(vat[3]) + 5 * int(vat[4]) + 4 * int(vat[5]) + \ + 3 * int(vat[6]) + 2 * int(vat[7]) + check = 11 - (sum % 11) + if check == 10: + check = 0 + if check != int(vat[8]): + return False + return True + + def check_vat_ro(self, vat): + ''' + Check Romania VAT number. + ''' + try: + int(vat) + except: + return False + + if len(vat) == 10: + sum = 7 * int(vat[0]) + 5 * int(vat[1]) + 3 * int(vat[2]) + \ + 2 * int(vat[3]) + 1 * int(vat[4]) + 7 * int(vat[5]) + \ + 5 * int(vat[6]) + 3 * int(vat[7]) + 2 * int(vat[8]) + check = (sum * 10) % 11 + if check == 10: + check = 0 + if check != int(vat[9]): + return False + return True + elif len(vat) == 13: + if int(vat[0]) not in (1, 2, 3, 4, 6): + return False + if int(vat[3:5]) < 1 or int(vat[3:5]) > 12: + return False + if int(vat[3:5]) == 2 and int(vat[1:3]) % 4 > 0: + if int(vat[5:7]) < 1 or int(vat[5:7]) > 28: + return False + if int(vat[3:5]) == 2 and int(vat[1:3]) % 4 == 0: + if int(vat[5:7]) < 1 or int(vat[5:7]) > 29: + return False + if int(vat[3:5]) in (4, 6, 9, 11): + if int(vat[5:7]) < 1 or int(vat[5:7]) > 30: + return False + if int(vat[3:5]) in (1, 3, 5, 7, 8, 10, 12): + if int(vat[5:7]) < 1 or int(vat[5:7]) > 31: + return False + + sum = 2 * int(vat[0]) + 7 * int(vat[1]) + 9 * int(vat[2]) + \ + 1 * int(vat[3]) + 4 * int(vat[4]) + 6 * int(vat[5]) + \ + 3 * int(vat[6]) + 5 * int(vat[7]) + 8 * int(vat[8]) + \ + 2 * int(vat[9]) + 7 * int(vat[10]) + 9 * int(vat[11]) + check = sum % 11 + if check == 10: + check = 1 + if check != int(vat[12]): + return False + return True + return False + + def check_vat_se(self, vat): + ''' + Check Sweden VAT number. + ''' + if len(vat) != 12: + return False + try: + int(vat) + except: + return False + if int(vat[9:11]) <= 0: + return False + + sum = mult_add(2, int(vat[0])) + int(vat[1]) + \ + mult_add(2, int(vat[2])) + int(vat[3]) + \ + mult_add(2, int(vat[4])) + int(vat[5]) + \ + mult_add(2, int(vat[6])) + int(vat[7]) + \ + mult_add(2, int(vat[8])) + check = 10 - (sum % 10) + if check == 10: + check = 0 + if check != int(vat[9]): + return False + return True + + def check_vat_si(self, vat): + ''' + Check Slovenia VAT number. + ''' + if len(vat) != 8: + return False + try: + int(vat) + except: + return False + if int(vat[0:7]) <= 999999: + return False + + sum = 8 * int(vat[0]) + 7 * int(vat[1]) + 6 * int(vat[2]) + \ + 5 * int(vat[3]) + 4 * int(vat[4]) + 3 * int(vat[5]) + \ + 2 * int(vat[6]) + check = 11 - (sum % 11) + if check == 10: + check = 0 + if check == 11: + check = 1 + if check != int(vat[7]): + return False + return True + + def check_vat_sk(self, vat): + ''' + Check Slovakia VAT number. + ''' + try: + int(vat) + except: + return False + if len(vat) not in(9, 10): + return False + + if int(vat[0:2]) == 0 and len(vat) == 10: + return True + + if len(vat) == 10: + if int(vat[0:2]) < 54 or int(vat[0:2]) > 99: + return False + + if len(vat) == 9: + if int(vat[0:2]) > 53 : + return False + + if int(vat[2:4]) < 1: + return False + if int(vat[2:4]) > 12 and int(vat[2:4]) < 51: + return False + if int(vat[2:4]) > 62: + return False + if int(vat[2:4]) in (2, 52) and int(vat[0:2]) % 4 > 0: + if int(vat[4:6]) < 1 or int(vat[4:6]) > 28: + return False + if int(vat[2:4]) in (2, 52) and int(vat[0:2]) % 4 == 0: + if int(vat[4:6]) < 1 or int(vat[4:6]) > 29: + return False + if int(vat[2:4]) in (4, 6, 9, 11, 54, 56, 59, 61): + if int(vat[4:6]) < 1 or int(vat[4:6]) > 30: + return False + if int(vat[2:4]) in (1, 3, 5, 7, 8, 10, 12, + 51, 53, 55, 57, 58, 60, 62): + if int(vat[4:6]) < 1 or int(vat[4:6]) > 31: + return False + return True + +res_partner() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + From 421603085ae82caee4a9d5e348a58a80f11f1b9b Mon Sep 17 00:00:00 2001 From: dharmesh rathod Date: Mon, 25 Aug 2008 12:42:26 +0530 Subject: [PATCH 09/20] add 'unit' key calculation bzr revid: dharmesh247@gmail.com-20080825071226-5eovqe6kc8altmul --- bin/report/render/rml2pdf/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/report/render/rml2pdf/utils.py b/bin/report/render/rml2pdf/utils.py index f7eaa0e3531..35460a2faeb 100644 --- a/bin/report/render/rml2pdf/utils.py +++ b/bin/report/render/rml2pdf/utils.py @@ -92,6 +92,8 @@ def attr_get(node, attrs, dict={}): res[key] = bool_get(node.getAttribute(key)) elif dict[key]=='int': res[key] = int(node.getAttribute(key)) + elif dict[key]=='unit': + res[key] = unit_get(node.getAttribute(name)) return res # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 476f91a11679b856c1fbabae1944c5d9e5aefb3f Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Mon, 25 Aug 2008 14:33:22 +0530 Subject: [PATCH 10/20] * Changes in to the python code remove comment bzr revid: mga@tinyerp.com-20080825090322-w7qe36114gltz7iv --- bin/addons/base/ir/ir.xml | 2 +- bin/addons/base/ir/ir_actions.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index 8135406e02f..26303e01829 100755 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1058,7 +1058,7 @@ - + diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 724f546bc3d..03f3bde4bcb 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -454,7 +454,6 @@ class actions_server(osv.osv): address = self.get_field_value(cr, uid, action, context) body = self.merge_message(cr, uid, action, context) - #TODO : Apply Mail merge in to the Content of the Email if tools.email_send_attach(user, address, subject, body, debug=False) == True: logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address)) From 785a372fbc322f897be2ad7f62179c722cc3aa82 Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Mon, 25 Aug 2008 16:25:15 +0530 Subject: [PATCH 11/20] Implement Objects for the Server Write / Create Option Implement View for the new Objects bzr revid: mga@tinyerp.com-20080825105515-htkpw9kab5sh4wjb --- bin/addons/base/ir/ir.xml | 17 +++++++++++++++++ bin/addons/base/ir/ir_actions.py | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index 26303e01829..3a44b8c55e3 100755 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1063,6 +1063,23 @@ + + + + + + + + + +
+ + + + + +
+ diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 03f3bde4bcb..9cba2ceeffe 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -333,6 +333,23 @@ class ir_model_fields(osv.osv): ir_model_fields() +class server_object_lines(osv.osv): + _name = 'ir.server.object.lines' + _sequence = 'ir_actions_id_seq' + _columns = { + 'server_id': fields.many2one('ir.actions.server', 'Object Mapping'), + 'col1': fields.many2one('ir.model.fields', 'Destination', required=True), + 'value': fields.text('Value', required=True), + 'type': fields.selection([ + ('value','Value'), + ('equation','Formula') + ], 'Type', required=True, size=32, change_default=True), + } + _defaults = { + 'type': lambda *a: 'equation', + } +server_object_lines() + ## # Actions that are run on the server side # @@ -363,6 +380,8 @@ class actions_server(osv.osv): 'child_ids': fields.one2many('ir.actions.actions', 'parent_id', 'Others Actions'), 'usage': fields.char('Action Usage', size=32), 'type': fields.char('Report Type', size=32, required=True), + 'srcmodel_id': fields.many2one('ir.model', 'Model', required=True), + 'fields_lines': fields.one2many('ir.server.object.lines', 'server_id', 'Fields Mapping'), } _defaults = { 'state': lambda *a: 'dummy', From 78f828620bb7aaf283e825258d08ac9f32a0f69c Mon Sep 17 00:00:00 2001 From: Harshad Modi Date: Mon, 25 Aug 2008 17:24:56 +0530 Subject: [PATCH 12/20] Put Payment Term in the sale order. When we change the partner, it sets the right payment term according to what have been defined in the res.partner. When creating invoices from sale order or from picking, uses the payment term of the sale order instead of the one of the partner. bzr revid: hmo@tinyerp.com-20080825115456-hwftk6ehj69392bp --- addons/sale/sale.py | 10 ++++++---- addons/sale/sale_view.xml | 1 + addons/stock/stock.py | 7 +++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index ada1ef51a94..ddd56a3b300 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -239,6 +239,7 @@ class sale_order(osv.osv): 'amount_tax': fields.function(_amount_tax, method=True, string='Taxes'), 'amount_total': fields.function(_amount_total, method=True, string='Total'), 'invoice_quantity': fields.selection([('order','Ordered Quantities'),('procurement','Shipped Quantities')], 'Invoice on', help="The sale order will automatically create the invoice proposition (draft invoice). Ordered and delivered quantities may not be the same. You have to choose if you invoice based on ordered or shipped quantities. If the product is a service, shipped quantities means hours spent on the associated tasks."), + 'payment_term' : fields.many2one('account.payment.term', 'Payment Term'), } _defaults = { 'picking_policy': lambda *a: 'direct', @@ -281,10 +282,11 @@ class sale_order(osv.osv): def onchange_partner_id(self, cr, uid, ids, part): if not part: - return {'value':{'partner_invoice_id': False, 'partner_shipping_id':False, 'partner_order_id':False}} + return {'value':{'partner_invoice_id': False, 'partner_shipping_id':False, 'partner_order_id':False, 'payment_term' : False}} addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['delivery','invoice','contact']) pricelist = self.pool.get('res.partner').browse(cr, uid, part).property_product_pricelist.id - return {'value':{'partner_invoice_id': addr['invoice'], 'partner_order_id':addr['contact'], 'partner_shipping_id':addr['delivery'], 'pricelist_id': pricelist}} + payment_term = self.pool.get('res.partner').browse(cr, uid, part).property_payment_term.id + return {'value':{'partner_invoice_id': addr['invoice'], 'partner_order_id':addr['contact'], 'partner_shipping_id':addr['delivery'], 'pricelist_id': pricelist, 'payment_term' : payment_term}} def button_dummy(self, cr, uid, ids, context={}): return True @@ -298,8 +300,8 @@ class sale_order(osv.osv): def _make_invoice(self, cr, uid, order, lines): a = order.partner_id.property_account_receivable.id - if order.partner_id and order.partner_id.property_payment_term.id: - pay_term = order.partner_id.property_payment_term.id + if order.payment_term: + pay_term = order.payment_term.id else: pay_term = False for preinv in order.invoice_ids: diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 2b4156366d0..ec39d306f9f 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -167,6 +167,7 @@ + diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 224420d2e8d..7b3c1bd0c77 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -606,15 +606,14 @@ class stock_picking(osv.osv): for picking in self.browse(cursor, user, ids, context=context): if picking.invoice_state != '2binvoiced': continue - + payment_term_id = False partner = picking.address_id.partner_id if type in ('out_invoice', 'out_refund'): account_id = partner.property_account_receivable.id + payment_term_id= picking.sale_id.payment_term.id else: account_id = partner.property_account_payable.id - payment_term_id = False - if partner.property_payment_term: - payment_term_id = partner.property_payment_term.id +# payment_term_id = picking.purchase_id.payment_term.id address_contact_id, address_invoice_id = \ self._get_address_invoice(cursor, user, picking).values() From d9b9b08a210eeb089ba041743b59cb0ceed3eb4d Mon Sep 17 00:00:00 2001 From: Harshad Modi Date: Mon, 25 Aug 2008 17:55:04 +0530 Subject: [PATCH 13/20] In invoices, if we do not specify the period (force period) it must take the period relative to the date of the invoice, not the current period. bzr revid: hmo@tinyerp.com-20080825122504-9g3lxashtn3100zx --- addons/account/invoice.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/addons/account/invoice.py b/addons/account/invoice.py index 9a49a871f42..7dabe6fe88d 100644 --- a/addons/account/invoice.py +++ b/addons/account/invoice.py @@ -499,14 +499,18 @@ class account_invoice(osv.osv): _('Can not create invoice move on centralized journal')) move = {'name': name, 'line_id': line, 'journal_id': journal_id} - if inv.period_id: - move['period_id'] = inv.period_id.id + period_id=inv.period_id and inv.period_id.id or False + if not period_id: + period_ids= self.pool.get('account.period').search(cr,uid,[('date_start','<=',inv.date_invoice),('date_stop','>=',inv.date_invoice)]) + if len(period_ids): + period_id=period_ids[0] + if period_id: + move['period_id'] = period_id for i in line: - i[2]['period_id'] = inv.period_id.id - + i[2]['period_id'] = period_id move_id = self.pool.get('account.move').create(cr, uid, move) # make the invoice point to that move - self.write(cr, uid, [inv.id], {'move_id': move_id}) + self.write(cr, uid, [inv.id], {'move_id': move_id,'period_id':period_id}) self.pool.get('account.move').post(cr, uid, [move_id]) self._log_event(cr, uid, ids) return True From 1df81cdaa191947b103154d889eb0ad0ddba27e6 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 25 Aug 2008 14:29:37 +0200 Subject: [PATCH 14/20] * add a step in the install wizard to propose to install the base_vat_check module * change the "Install" icon in the install button bzr revid: christophe@tinyerp.com-20080825122937-9gyph7d1yj6vy7o5 --- addons/base_setup/wizard/wizard_base_setup.py | 50 ++++++++++++++++--- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/addons/base_setup/wizard/wizard_base_setup.py b/addons/base_setup/wizard/wizard_base_setup.py index b37efde2a20..67a13f0f976 100644 --- a/addons/base_setup/wizard/wizard_base_setup.py +++ b/addons/base_setup/wizard/wizard_base_setup.py @@ -62,6 +62,20 @@ view_form_charts = """ """ +view_form_vatcheck = """ +
+ + + + + + + +
""" + view_form_company = """
@@ -97,6 +111,8 @@ view_form_update = """ + + @@ -185,12 +201,16 @@ class wizard_base_setup(wizard.interface): def _update(self, cr, uid, data, context): pool=pooler.get_pool(cr.dbname) form=data['form'] - if 'profile' in data['form'] and data['form']['profile'] > 0: - module_obj=pool.get('ir.module.module') - module_obj.state_update(cr, uid, [data['form']['profile']], 'to install', ['uninstalled'], context) - if 'charts' in data['form'] and data['form']['charts'] > 0: - module_obj=pool.get('ir.module.module') - module_obj.state_update(cr, uid, [data['form']['charts']], 'to install', ['uninstalled'], context) + module_obj=pool.get('ir.module.module') + + if 'profile' in form and form['profile'] > 0: + module_obj.state_update(cr, uid, [form['profile']], 'to install', ['uninstalled'], context) + if 'charts' in form and form['charts'] > 0: + module_obj.state_update(cr, uid, [form['charts']], 'to install', ['uninstalled'], context) + if 'vatcheck' in form and form['vatcheck']: + mid = module_obj.search(cr, uid, [('name', '=', 'base_vat_check')], context=context) + if mid: + module_obj.state_update(cr, uid, mid, 'to install', ['uninstalled'], context) company_obj=pool.get('res.company') partner_obj=pool.get('res.partner') @@ -271,7 +291,7 @@ class wizard_base_setup(wizard.interface): def _previous(self, cr, uid, data, context): if 'profile' not in data['form'] or data['form']['profile'] <= 0: return 'init' - return 'charts' + return 'vatcheck' def _config(self, cr, uid, data, context=None): users_obj=pooler.get_pool(cr.dbname).get('res.users') @@ -307,6 +327,11 @@ class wizard_base_setup(wizard.interface): 'default': -1, 'required': True, }, + 'vatcheck':{ + 'string': "Install 'base_vat_check' module", + 'type': 'boolean', + 'default': False, + }, 'name':{ 'string': 'Company Name', 'type': 'char', @@ -402,6 +427,15 @@ IBAN: BE74 1262 0121 6907 - SWIFT: CPDF BE71 - VAT: BE0477.472.701""", 'result': {'type': 'form', 'arch': view_form_charts, 'fields': fields, 'state':[ ('init', 'Previous', 'gtk-go-back'), + ('vatcheck', 'Next', 'gtk-go-forward', True) + ] + } + }, + 'vatcheck':{ + 'actions':[], + 'result': {'type': 'form', 'arch': view_form_vatcheck, 'fields': fields, + 'state': [ + ('charts', 'Previous', 'gtk-go-back'), ('company', 'Next', 'gtk-go-forward', True) ] } @@ -424,7 +458,7 @@ IBAN: BE74 1262 0121 6907 - SWIFT: CPDF BE71 - VAT: BE0477.472.701""", 'result': {'type': 'form', 'arch': view_form_update, 'fields': fields, 'state': [ ('company', 'Previous', 'gtk-go-back'), - ('finish', 'Install', 'gtk-ok', True) + ('finish', 'Install', 'gtk-save', True) ] } }, From a33736084ab2e452d7cf1e7226e74503f2608907 Mon Sep 17 00:00:00 2001 From: "mga@tinyerp.com" <> Date: Mon, 25 Aug 2008 18:41:10 +0530 Subject: [PATCH 15/20] Implement normal operations using eval() method bzr revid: mga@tinyerp.com-20080825131110-kket17k3zdcx2rb5 --- bin/addons/base/ir/ir_actions.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 9cba2ceeffe..ac15909c014 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -418,7 +418,7 @@ class actions_server(osv.osv): return obj - def merge_message(self, cr, uid, action, context): + def merge_message(self, cr, uid, keystr, action, context): logger = netsvc.Logger() def merge(match): @@ -441,7 +441,7 @@ class actions_server(osv.osv): return str(obj) com = re.compile('\[\[(.+?)\]\]') - message = com.sub(merge, str(action.message)) + message = com.sub(merge, keystr) return message # @@ -471,7 +471,7 @@ class actions_server(osv.osv): user = config['email_from'] subject = action.name - address = self.get_field_value(cr, uid, action, context) + address = self.get_field_value(cr, uid, str(action.message), action, context) body = self.merge_message(cr, uid, action, context) if tools.email_send_attach(user, address, subject, body, debug=False) == True: @@ -508,7 +508,22 @@ class actions_server(osv.osv): exec code in localdict if 'action' in localdict: return localdict['action'] - + if action.state == 'object_write': + res = {} + for exp in action.fields_lines: + euq = exp.value + if exp.type == 'equation': + expr = self.merge_message(cr, uid, euq, action, context) + expr = eval(expr) + else: + expr = exp.value + res[exp.col1.name] = expr + obj_pool = self.pool.get(action.model_id.model) + obj_pool.write(cr, uid, [context.get('active_id')], res) + + if action.state == 'object_create': + pass + return False actions_server() From 7c78a74aeab51bbce6268d996a71f035d585b080 Mon Sep 17 00:00:00 2001 From: qdp Date: Mon, 25 Aug 2008 17:41:01 +0200 Subject: [PATCH 16/20] *commited patch of c2c to bugfix multi currencies glitch on wizard_pay_invoice. It now takes in consideration the date and is improved thanks to a comment and a better name for writtes-off. bzr revid: qdp@tinyerp.com-20080825154101-vxnkipmf3nlooxto --- addons/account/account.py | 2 +- addons/account/account_move_line.py | 16 +++++++++--- addons/account/invoice.py | 27 +++++++++++++++------ addons/account/wizard/wizard_pay_invoice.py | 11 ++++++++- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/addons/account/account.py b/addons/account/account.py index 04c5c92d98c..34b421c7e6f 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -423,7 +423,7 @@ class account_journal(osv.osv): 'user_id': fields.many2one('res.users', 'User', help="The responsible user of this journal"), 'groups_id': fields.many2many('res.groups', 'account_journal_group_rel', 'journal_id', 'group_id', 'Groups'), 'currency': fields.many2one('res.currency', 'Currency', help='The currency used to enter statement'), - 'entry_posted': fields.boolean('Skip \'Draft\' State of Created Entries', help='Check this box if you don\'t want that new account moves pass through the draft state'), + 'entry_posted': fields.boolean('Skip \'Draft\' State for Created Entries', help='Check this box if you don\'t want that new account moves pass through the \'draft\' state and goes direclty to the \'posted state\' without any manual validation.'), } _defaults = { 'active': lambda *a: 1, diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 125e3a7d5f0..09e8bccec12 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -404,7 +404,11 @@ class account_move_line(osv.osv): account_id = line['account_id']['id'] partner_id = (line['partner_id'] and line['partner_id']['id']) or False writeoff = debit - credit - date = time.strftime('%Y-%m-%d') + # Ifdate_p in context => take this date + if context.has_key('date_p') and context['date_p']: + date=context['date_p'] + else: + date = time.strftime('%Y-%m-%d') cr.execute('SELECT account_id, reconcile_id \ FROM account_move_line \ @@ -435,9 +439,15 @@ class account_move_line(osv.osv): self_credit = 0.0 self_debit = -writeoff + # If comment exist in context, take it + if context['comment']: + libelle=context['comment'] + else: + libelle='Write-Off' + writeoff_lines = [ (0, 0, { - 'name':'Write-Off', + 'name':libelle, 'debit':self_debit, 'credit':self_credit, 'account_id':account_id, @@ -447,7 +457,7 @@ class account_move_line(osv.osv): 'amount_currency': account.currency_id.id and -currency or 0.0 }), (0, 0, { - 'name':'Write-Off', + 'name':libelle, 'debit':debit, 'credit':credit, 'account_id':writeoff_acc_id, diff --git a/addons/account/invoice.py b/addons/account/invoice.py index 7dabe6fe88d..89e47a1ac43 100644 --- a/addons/account/invoice.py +++ b/addons/account/invoice.py @@ -685,20 +685,30 @@ class account_invoice(osv.osv): invoice = self.browse(cr, uid, ids[0]) src_account_id = invoice.account_id.id journal = self.pool.get('account.journal').browse(cr, uid, pay_journal_id) - if not name: - if journal.sequence_id: - name = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id) - else: - raise osv.except_osv(_('No piece number !'), _('Can not create an automatic sequence for this piece !\n\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.')) + if journal.sequence_id: + name = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id) + else: + raise osv.except_osv(_('No piece number !'), _('Can not create an automatic sequence for this piece !\n\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.')) + # Take the seq as name for move + if journal.sequence_id: + seq = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id) + else: + raise osv.except_osv('No piece number !', 'Can not create an automatic sequence for this piece !\n\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.') types = {'out_invoice': -1, 'in_invoice': 1, 'out_refund': 1, 'in_refund': -1} direction = types[invoice.type] + #take the choosen date + if context.has_key('date_p') and context['date_p']: + date=context['date_p'] + else: + date=time.strftime('%Y-%m-%d') l1 = { 'name': name, 'debit': direction * pay_amount>0 and direction * pay_amount, 'credit': direction * pay_amount<0 and - direction * pay_amount, 'account_id': src_account_id, 'partner_id': invoice.partner_id.id, - 'date': time.strftime('%Y-%m-%d'), + 'date': date, + 'ref':invoice.number, } l2 = { 'name':name, @@ -706,11 +716,12 @@ class account_invoice(osv.osv): 'credit': direction * pay_amount>0 and direction * pay_amount, 'account_id': pay_account_id, 'partner_id': invoice.partner_id.id, - 'date': time.strftime('%Y-%m-%d'), + 'date': date, + 'ref':invoice.number, } lines = [(0, 0, l1), (0, 0, l2)] - move = {'name': name, 'line_id': lines, 'journal_id': pay_journal_id, 'period_id': period_id} + move = {'name': seq, 'line_id': lines, 'journal_id': pay_journal_id, 'period_id': period_id} move_id = self.pool.get('account.move').create(cr, uid, move) line_ids = [] diff --git a/addons/account/wizard/wizard_pay_invoice.py b/addons/account/wizard/wizard_pay_invoice.py index c8f1197571e..3503070ee21 100644 --- a/addons/account/wizard/wizard_pay_invoice.py +++ b/addons/account/wizard/wizard_pay_invoice.py @@ -68,6 +68,13 @@ def _pay_and_reconcile(self, cr, uid, data, context): ctx = {'date':data['form']['date']} amount = cur_obj.compute(cr, uid, journal.currency.id, invoice.company_id.currency_id.id, amount, context=ctx) + + # Take the choosen date + if form.has_key('comment'): + context={'date_p':form['date'],'comment':form['comment']} + else: + context={'date_p':form['date'],'comment':False} + acc_id = journal.default_credit_account_id and journal.default_credit_account_id.id if not acc_id: raise wizard.except_wizard(_('Error !'), _('Your journal must have a default credit and debit account.')) @@ -80,7 +87,7 @@ def _wo_check(self, cr, uid, data, context): pool = pooler.get_pool(cr.dbname) invoice = pool.get('account.invoice').browse(cr, uid, data['id'], context) journal = pool.get('account.journal').browse(cr, uid, data['form']['journal_id'], context) - if invoice.company_id.currency_id.id<>journal.currency.id: + if invoice.company_id.currency_id.id<>journal.currency.id or journal.currency.id <> invoice.currency_id.id: return 'addendum' if pool.get('res.currency').is_zero(cr, uid, invoice.currency_id, (data['form']['amount'] - invoice.amount_total)): @@ -92,11 +99,13 @@ _transaction_add_form = ''' + ''' _transaction_add_fields = { 'writeoff_acc_id': {'string':'Write-Off account', 'type':'many2one', 'relation':'account.account', 'required':True}, 'writeoff_journal_id': {'string': 'Write-Off journal', 'type': 'many2one', 'relation':'account.journal', 'required':True}, + 'comment': {'string': 'Entry Name', 'type':'char', 'size': 64, 'required':True}, } def _get_value_addendum(self, cr, uid, data, context={}): From 88129d790933f7f61c5d39fc1ee000d8bc26cf17 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Mon, 25 Aug 2008 21:36:47 +0200 Subject: [PATCH 17/20] Bugfixes bzr revid: fp@tinyerp.com-20080825193647-k928o039lhsrgspq --- bin/addons/base/res/partner/partner.py | 7 +- bin/addons/base/res/partner/partner_view.xml | 152 +++++++++---------- bin/addons/module_graph.py | 0 bin/osv/expression.py | 6 +- bin/osv/orm.py | 2 +- 5 files changed, 85 insertions(+), 82 deletions(-) mode change 100644 => 100755 bin/addons/module_graph.py diff --git a/bin/addons/base/res/partner/partner.py b/bin/addons/base/res/partner/partner.py index 0d3ff0bf3d9..1b7b833fe9c 100644 --- a/bin/addons/base/res/partner/partner.py +++ b/bin/addons/base/res/partner/partner.py @@ -138,7 +138,7 @@ class res_partner(osv.osv): 'parent_id': fields.many2one('res.partner','Main Company', select=2), 'child_ids': fields.one2many('res.partner', 'parent_id', 'Partner Ref.'), 'ref': fields.char('Code', size=64), - 'lang': fields.selection(_lang_get, 'Language', size=5), + 'lang': fields.selection(_lang_get, 'Language', size=5, help="If the selected language is loaded in the system, all documents related to this partner will be printed in this language. If not, it will be english."), 'user_id': fields.many2one('res.users', 'Dedicated Salesman', help='The internal user that is in charge of communicating with this partner if any.'), 'responsible': fields.many2one('res.users', 'Users'), 'vat': fields.char('VAT',size=32 ,help="Value Added Tax number"), @@ -152,9 +152,12 @@ class res_partner(osv.osv): 'credit_limit': fields.float(string='Credit Limit'), 'ean13': fields.char('EAN13', size=13), 'active': fields.boolean('Active'), + 'customer': fields.boolean('Customer'), + 'supplier': fields.boolean('Supplier'), } _defaults = { 'active': lambda *a: 1, + 'customer': lambda *a: 1, } _sql_constraints = [ ('name_uniq', 'unique (name)', 'The name of the partner must be unique !') @@ -262,7 +265,7 @@ class res_partner(osv.osv): res_partner() class res_partner_address(osv.osv): - _description ='Partner Contact' + _description ='Partner Addresses' _name = 'res.partner.address' _order = 'id' _columns = { diff --git a/bin/addons/base/res/partner/partner_view.xml b/bin/addons/base/res/partner/partner_view.xml index 84cdb89b97c..8a1533aaf28 100644 --- a/bin/addons/base/res/partner/partner_view.xml +++ b/bin/addons/base/res/partner/partner_view.xml @@ -6,10 +6,10 @@ + ================================ + Function + ================================ + --> res.partner.function.form res.partner.function @@ -41,16 +41,16 @@ + ===================== + Partner Address + ===================== + --> res.partner.address.tree res.partner.address tree - + @@ -73,7 +73,7 @@ form -
+ @@ -98,7 +98,7 @@ - Partner Contacts + Partner Addresses ir.actions.act_window res.partner.address form @@ -118,10 +118,10 @@ + ========================================= + the short form used in the partner form + ========================================= + --> res.partner.address.form2 res.partner.address @@ -151,10 +151,10 @@ + ======================= + Partner Titles + ======================= + --> res.partner.title.form res.partner.title @@ -176,10 +176,10 @@ + ======================= + Partner + ======================= + --> res.partner.tree res.partner @@ -201,13 +201,16 @@ form - + + + + + + + + + - - - - - @@ -239,47 +242,19 @@ - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + @@ -305,7 +280,32 @@ - + + + Customers Partners + ir.actions.act_window + res.partner + form + [('customer','=',1)] + + + + Suppliers Partners + ir.actions.act_window + res.partner + form + [('supplier','=',1)] + + + + Others Partners + ir.actions.act_window + res.partner + form + [('supplier','<>',1),('customer','<>',1)] + + + res.payterm res.payterm @@ -389,10 +389,10 @@ + ====================== + Company Architecture + ====================== + --> res.partner.tree res.partner @@ -423,16 +423,16 @@ + ====================== + Categories + ====================== + --> res.partner.category.form res.partner.category form -
+ @@ -445,7 +445,7 @@ tree - + @@ -462,7 +462,7 @@ - Partner categories + Partners by Categories ir.actions.act_window res.partner.category tree diff --git a/bin/addons/module_graph.py b/bin/addons/module_graph.py old mode 100644 new mode 100755 diff --git a/bin/osv/expression.py b/bin/osv/expression.py index 9855a4a5d91..d95852d4f35 100644 --- a/bin/osv/expression.py +++ b/bin/osv/expression.py @@ -70,7 +70,7 @@ class expression(object): return [] ids2 = table.search(cr, uid, [(parent, 'in', ids)], context=context) return ids+rg(ids2, table, parent) - return [(prefix+left, 'in', rg(ids2, table, parent))] + return [(left, 'in', rg(ids2, table, parent))] self.__main_table = table @@ -148,7 +148,7 @@ class expression(object): return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids) dom = _rec_get(ids2, field_obj, working_table._parent_name) - ids2 = field_obj.search(cr, uid, doms, context=context) + ids2 = field_obj.search(cr, uid, dom, context=context) self.__exp[i] = ('id', 'in', _rec_convert(ids2)) else: if isinstance(right, basestring): @@ -165,7 +165,7 @@ class expression(object): self.__operator = 'in' if field._obj != working_table._name: - dom = _rec_get(ids2, field_obj, working_table._parent_name, left=left) + dom = _rec_get(ids2, field_obj, working_table._parent_name, left=left, prefix=field._obj) else: dom = _rec_get(ids2, working_table, left) self.__exp = self.__exp[:i] + dom + self.__exp[i+1:] diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 8eabab0ada8..48adc8f9a99 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -767,7 +767,7 @@ class orm_template(object): fields[node.getAttribute('name')] = attrs elif node.nodeType==node.ELEMENT_NODE and node.localName in ('form', 'tree'): - result = self.view_header_get(cr, user, False, node.localName, context) + result = self.pool.get(self._name).view_header_get(cr, user, False, node.localName, context) if result: node.setAttribute('string', result.decode('utf-8')) if node.nodeType == node.ELEMENT_NODE and node.hasAttribute('groups'): From 7f51b4001487ec71e941b3f5dbd6cbdd7921e122 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Mon, 25 Aug 2008 22:15:55 +0200 Subject: [PATCH 18/20] Better View Titles bzr revid: fp@tinyerp.com-20080825201555-howb8p6zdjmnarp1 --- bin/addons/base/res/partner/partner.py | 8 ++++++++ bin/addons/base/res/partner/partner_view.xml | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bin/addons/base/res/partner/partner.py b/bin/addons/base/res/partner/partner.py index 1b7b833fe9c..80434c30da6 100644 --- a/bin/addons/base/res/partner/partner.py +++ b/bin/addons/base/res/partner/partner.py @@ -262,6 +262,14 @@ class res_partner(osv.osv): # update the current partner cr.execute("update res_partner set ref=%d where id=%d", (nextref, ids[0])) return True + + def view_header_get(self, cr, uid, view_id, view_type, context): + res = super(res_partner, self).view_header_get(cr, uid, view_id, view_type, context) + if res: return res + if (not context.get('category_id', False)): + return False + return _('Partners: ')+self.pool.get('res.partner.category').browse(cr, uid, context['category_id'], context).name + res_partner() class res_partner_address(osv.osv): diff --git a/bin/addons/base/res/partner/partner_view.xml b/bin/addons/base/res/partner/partner_view.xml index 8a1533aaf28..9f625f1c2f4 100644 --- a/bin/addons/base/res/partner/partner_view.xml +++ b/bin/addons/base/res/partner/partner_view.xml @@ -472,11 +472,12 @@ - Partners By Category + res.partner form tree,form [('category_id','child_of', [active_id])] + {'category_id':active_id} From 97dd8d1a250bb57ddcc21d8d8df211d1f8f94761 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Tue, 26 Aug 2008 00:20:48 +0200 Subject: [PATCH 19/20] Merge bzr revid: fp@tinyerp.com-20080825222048-dfz0h2fx1ooofavq --- addons/account/account_move_line.py | 11 +- addons/account/account_view.xml | 19 +-- addons/account/partner_view.xml | 74 +++++++--- addons/account/product_view.xml | 11 +- addons/account/project/project_view.xml | 2 +- .../account/wizard/wizard_move_line_select.py | 5 +- addons/delivery/delivery_view.xml | 7 +- addons/membership/membership_view.xml | 4 +- addons/product/partner_view.xml | 9 +- addons/product/product.py | 7 + addons/product/product_view.xml | 100 ++++++------- addons/purchase/partner_view.xml | 8 +- addons/purchase/purchase.py | 6 +- addons/purchase/purchase_view.xml | 27 ++-- addons/sale/sale_view.xml | 22 +-- addons/stock/__terp__.py | 3 +- addons/stock/partner_view.xml | 10 +- addons/stock/product_view.xml | 42 +++--- addons/stock/stock.py | 2 + addons/stock/stock_view.xml | 139 +++++++++--------- 20 files changed, 275 insertions(+), 233 deletions(-) diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 1ee414e6b74..ca37e254d7b 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -488,6 +488,11 @@ class account_move_line(osv.osv): return r_id def view_header_get(self, cr, user, view_id, view_type, context): + if context.get('account_id', False): + cr.execute('select code from account_account where id=%d', (context['account_id'],)) + res = cr.fetchone() + res = _('Entries: ')+ (res[0] or '') + return res if (not context.get('journal_id', False)) or (not context.get('period_id', False)): return False cr.execute('select code from account_journal where id=%d', (context['journal_id'],)) @@ -495,8 +500,8 @@ class account_move_line(osv.osv): cr.execute('select code from account_period where id=%d', (context['period_id'],)) p = cr.fetchone()[0] or '' if j or p: - return j+':'+p - return 'Journal' + return j+(p and (':'+p) or '') + return False def fields_view_get(self, cr, uid, view_id=None, view_type='form', context={}, toolbar=False): result = super(osv.osv, self).fields_view_get(cr, uid, view_id,view_type,context) @@ -709,7 +714,6 @@ class account_move_line(osv.osv): tax_id=tax_obj.browse(cr,uid,vals['account_tax_id']) total = vals['credit'] or (-vals['debit']) for tax in tax_obj.compute(cr,uid,[tax_id],total,1.00): - print 'Processing Tax', tax self.write(cr, uid,[result], { 'tax_code_id': tax['base_code_id'], 'tax_amount': tax['base_sign'] * total @@ -729,7 +733,6 @@ class account_move_line(osv.osv): 'credit': tax['amount']>0 and tax['amount'] or 0.0, 'debit': tax['amount']<0 and -tax['amount'] or 0.0, } - print data self.create(cr, uid, data, context) if check: self.pool.get('account.move').validate(cr, uid, [vals['move_id']], context) diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 8b66b7b62b8..b3e5b24960e 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -887,7 +887,7 @@ - + @@ -1318,17 +1318,18 @@ - Move line select + Entries account.move.line form tree,form [('account_id','child_of', [active_id]),('state','<>','draft')] + {'account_id':active_id} - Open all entries lines + Account Entries @@ -1513,14 +1514,14 @@ - + account.chart.template.form account.chart.template form - + @@ -1537,7 +1538,7 @@ account.chart.template tree - + @@ -1545,7 +1546,7 @@ - Account Chart Templates + Chart of Accounts Templates account.chart.template form tree,form @@ -1597,7 +1598,7 @@ wizard.account.chart.duplicate form - + @@ -1610,7 +1611,7 @@ - Duplicate Account Chart + Duplicate Chart of Accounts ir.actions.act_window wizard.account.chart.duplicate form diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml index ccc93735a59..8e523c5bc4d 100644 --- a/addons/account/partner_view.xml +++ b/addons/account/partner_view.xml @@ -5,20 +5,6 @@ Partners Extension --> - - res.partner.form.inherit - res.partner - form - - - - - - - - - - res.partner.property.form.inherit res.partner @@ -26,16 +12,56 @@ 2 - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/account/product_view.xml b/addons/account/product_view.xml index 1512b202f2f..3ca95e625b8 100644 --- a/addons/account/product_view.xml +++ b/addons/account/product_view.xml @@ -50,10 +50,13 @@ form - - - - +
+ + + + + +
diff --git a/addons/account/project/project_view.xml b/addons/account/project/project_view.xml index 27ba38f3f88..d8f6d8af516 100644 --- a/addons/account/project/project_view.xml +++ b/addons/account/project/project_view.xml @@ -78,7 +78,7 @@ - Analytic Charts of Accounts + Analytic Chart of Accounts ir.actions.act_window account.analytic.account [('parent_id','=',False)] diff --git a/addons/account/wizard/wizard_move_line_select.py b/addons/account/wizard/wizard_move_line_select.py index 86c677ffb6a..10c69f81468 100644 --- a/addons/account/wizard/wizard_move_line_select.py +++ b/addons/account/wizard/wizard_move_line_select.py @@ -52,7 +52,10 @@ class wizard_move_line_select(wizard.interface): result = mod_obj._get_id(cr, uid, 'account', 'action_move_line_tree1') id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id'] result = act_obj.read(cr, uid, [id])[0] - result['context'] = str({'fiscalyear': context.get('fiscalyear', False)}) + result['context'] = { + 'fiscalyear': context.get('fiscalyear', False), + 'account_id': data['id'] + } result['domain']=result['domain'][0:-1]+','+domain+result['domain'][-1] return result diff --git a/addons/delivery/delivery_view.xml b/addons/delivery/delivery_view.xml index 4aaced6c4f6..d643f44feb7 100644 --- a/addons/delivery/delivery_view.xml +++ b/addons/delivery/delivery_view.xml @@ -124,10 +124,9 @@ sale.order - + - - + @@ -195,4 +194,4 @@ - \ No newline at end of file + diff --git a/addons/membership/membership_view.xml b/addons/membership/membership_view.xml index fdfe3ba3e4e..16ac3e910cc 100644 --- a/addons/membership/membership_view.xml +++ b/addons/membership/membership_view.xml @@ -318,7 +318,7 @@ res.partner - + @@ -341,7 +341,7 @@ - +
diff --git a/addons/product/partner_view.xml b/addons/product/partner_view.xml index 68fc31d3640..c13194c47e6 100644 --- a/addons/product/partner_view.xml +++ b/addons/product/partner_view.xml @@ -7,9 +7,12 @@ form - - - + + + + + +
diff --git a/addons/product/product.py b/addons/product/product.py index 529936bec0b..a9bf05ad65c 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -328,6 +328,13 @@ class product_template(osv.osv): product_template() class product_product(osv.osv): + def view_header_get(self, cr, uid, view_id, view_type, context): + res = super(product_product, self).view_header_get(cr, uid, view_id, view_type, context) + if res: return res + if (not context.get('categ_id', False)): + return False + return _('Products: ')+self.pool.get('product.category').browse(cr, uid, context['categ_id'], context).name + def _product_price(self, cr, uid, ids, name, arg, context={}): res = {} quantity = context.get('quantity', 1) diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml index 61e00f64916..aed5604555e 100644 --- a/addons/product/product_view.xml +++ b/addons/product/product_view.xml @@ -46,64 +46,64 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - + @@ -162,8 +162,7 @@ - - +
@@ -199,12 +198,13 @@ - product.normal.action.tree + ir.actions.act_window product.product form tree,form [('categ_id','child_of',[active_id])] + {'categ_id':active_id} diff --git a/addons/purchase/partner_view.xml b/addons/purchase/partner_view.xml index 188ac119d79..cdab52d471f 100644 --- a/addons/purchase/partner_view.xml +++ b/addons/purchase/partner_view.xml @@ -7,9 +7,11 @@ form - - - + + + + + diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 35c46825008..688892ee02f 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -99,10 +99,10 @@ class purchase_order(osv.osv): 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', states={'posted':[('readonly',True)]}), 'location_id': fields.many2one('stock.location', 'Delivery destination', required=True), - 'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}), + 'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}, help="The pricelist sets the currency used for this purchase order. It also computes the supplier price for the selected products/quantities."), 'state': fields.selection([('draft', 'Request for Quotation'), ('wait', 'Waiting'), ('confirmed', 'Confirmed'), ('approved', 'Approved'),('except_picking', 'Shipping Exception'), ('except_invoice', 'Invoice Exception'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Order State', readonly=True, help="The state of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' state. Then the order has to be confirmed by the user, the state switch to 'Confirmed'. Then the supplier must confirm the order to change the state to 'Approved'. When the purchase order is paid and received, the state becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the state becomes in exception.", select=True), - 'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order State', states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}), + 'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}), 'validator' : fields.many2one('res.users', 'Validated by', readonly=True), 'notes': fields.text('Notes'), 'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True), @@ -331,7 +331,7 @@ class purchase_order_line(osv.osv): } _table = 'purchase_order_line' _name = 'purchase.order.line' - _description = 'Purchase Order line' + _description = 'Purchase Order lines' def copy(self, cr, uid, id, default=None,context={}): if not default: default = {} diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml index 57bdae954ec..5484b22ea8b 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -1,10 +1,6 @@ - - Suppliers - - @@ -13,23 +9,23 @@ form
- + + + + + + + + + + - - - - - - - - - + - @@ -53,7 +49,6 @@ - diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 2b4156366d0..32c1d571df8 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -51,7 +51,7 @@ - + @@ -68,16 +68,17 @@ form - + + + + + + + + + - - - - - - - - + @@ -166,7 +167,6 @@ - diff --git a/addons/stock/__terp__.py b/addons/stock/__terp__.py index 0a498ac0ef9..92c553a71da 100644 --- a/addons/stock/__terp__.py +++ b/addons/stock/__terp__.py @@ -43,7 +43,8 @@ "stock_report.xml", "stock_sequence.xml", "product_data.xml", - "product_view.xml" + "product_view.xml", + "partner_view.xml" ], "active": False, "installable": True diff --git a/addons/stock/partner_view.xml b/addons/stock/partner_view.xml index 2cfc6cc3a4a..0fce0ccf7e0 100644 --- a/addons/stock/partner_view.xml +++ b/addons/stock/partner_view.xml @@ -11,10 +11,12 @@ form - - - - + + + + + + diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml index e060ab15ca0..1eb0b03f75a 100644 --- a/addons/stock/product_view.xml +++ b/addons/stock/product_view.xml @@ -8,12 +8,14 @@ form - - - - - - + + + + + + + +
@@ -48,8 +50,8 @@ - -
+
+
product.normal.stock.form.inherit @@ -58,13 +60,13 @@ - + - - - - - + + + + + @@ -76,12 +78,12 @@ - - - - - - + + + + + +
diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 224420d2e8d..dcf66f4a14a 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1136,6 +1136,8 @@ class product_product(osv.osv): # Utiliser browse pour limiter les queries ! # def view_header_get(self, cr, user, view_id, view_type, context): + res = super(product_product, self).view_header_get(cr, user, view_id, view_type, context) + if res: return res if (not context.get('location', False)): return False cr.execute('select name from stock_location where id=%d', (context['location'],)) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index f1d8550cd1d..256ee36b4e4 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -55,20 +55,19 @@ form
- - - - - - - -