X-Git-Url: http://git.inspyration.org/?a=blobdiff_plain;f=bin%2Faddons%2Fbase%2Fres%2Fpartner%2Fpartner.py;h=82acd80d6ce7c7dd44c9bd7ff16d7f87aa8c5429;hb=8c64e3c18b4614043aea37c2bbefb633b467809b;hp=3cac309de1187369ec3d8f9409f840e3f48b3541;hpb=2eb6b8265b0030121046b258793368e16211744a;p=odoo%2Fodoo.git diff --git a/bin/addons/base/res/partner/partner.py b/bin/addons/base/res/partner/partner.py index 3cac309..82acd80 100644 --- a/bin/addons/base/res/partner/partner.py +++ b/bin/addons/base/res/partner/partner.py @@ -1,30 +1,21 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). # -# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. # -# $Id$ +# 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 Affero General Public License for more details. # -# 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. +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . # ############################################################################## @@ -34,15 +25,20 @@ from osv import fields,osv import tools import ir import pooler +from tools.translate import _ class res_partner_function(osv.osv): _name = 'res.partner.function' _description = 'Function of the contact' _columns = { - 'name': fields.char('Function name', size=64, required=True), - 'code': fields.char('Code', size=8), + 'name': fields.char('Function Name', size=64, required=True), + 'code': fields.char('Code', size=8, required=True), + 'ref':fields.char('Notes', size=32,), } _order = 'name' + _sql_constraints = [ + ('code_uniq', 'unique (code)', 'The Code of the Partner Function must be unique !') + ] res_partner_function() @@ -50,15 +46,15 @@ class res_payterm(osv.osv): _description = 'Payment term' _name = 'res.payterm' _columns = { - 'name': fields.char('Payment term (short name)', size=64), + 'name': fields.char('Payment Term (short name)', size=64), } res_payterm() class res_partner_category(osv.osv): - def name_get(self, cr, uid, ids, context={}): + def name_get(self, cr, uid, ids, context=None): if not len(ids): return [] - reads = self.read(cr, uid, ids, ['name','parent_id'], context) + reads = self.read(cr, uid, ids, ['name','parent_id'], context=context) res = [] for record in reads: name = record['name'] @@ -67,13 +63,14 @@ class res_partner_category(osv.osv): res.append((record['id'], name)) return res - def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, unknow_dict): - res = self.name_get(cr, uid, ids) + def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): + res = self.name_get(cr, uid, ids, context=context) return dict(res) + def _check_recursion(self, cr, uid, ids): level = 100 while len(ids): - cr.execute('select distinct parent_id from res_partner_category where id in ('+','.join(map(str,ids))+')') + cr.execute('select distinct parent_id from res_partner_category where id in ('+','.join(map(str, ids))+')') ids = filter(None, map(lambda x:x[0], cr.fetchall())) if not level: return False @@ -83,11 +80,11 @@ class res_partner_category(osv.osv): _description='Partner Categories' _name = 'res.partner.category' _columns = { - 'name': fields.char('Category Name', required=True, size=64), + 'name': fields.char('Category Name', required=True, size=64, translate=True), 'parent_id': fields.many2one('res.partner.category', 'Parent Category', select=True), - 'complete_name': fields.function(_name_get_fnc, method=True, type="char", string='Name'), - 'child_ids': fields.one2many('res.partner.category', 'parent_id', 'Childs Category'), - 'active' : fields.boolean('Active', help="The active field allows you to hide the category, without removing it."), + 'complete_name': fields.function(_name_get_fnc, method=True, type="char", string='Full Name'), + 'child_ids': fields.one2many('res.partner.category', 'parent_id', 'Child Categories'), + 'active' : fields.boolean('Active', help="The active field allows you to hide the category without removing it."), } _constraints = [ (_check_recursion, 'Error ! You can not create recursive categories.', ['parent_id']) @@ -112,7 +109,7 @@ def _contact_title_get(self, cr, uid, context={}): obj = self.pool.get('res.partner.title') ids = obj.search(cr, uid, [('domain', '=', 'contact')]) res = obj.read(cr, uid, ids, ['shortcut','name'], context) - return [(r['shortcut'], r['name']) for r in res] + return [(r['shortcut'], r['name']) for r in res] + [('','')] def _partner_title_get(self, cr, uid, context={}): obj = self.pool.get('res.partner.title') @@ -122,10 +119,12 @@ def _partner_title_get(self, cr, uid, context={}): def _lang_get(self, cr, uid, context={}): obj = self.pool.get('res.lang') - ids = obj.search(cr, uid, []) + ids = obj.search(cr, uid, [], context=context) res = obj.read(cr, uid, ids, ['code', 'name'], context) - res = [(r['code'], r['name']) for r in res] - return res + [(False, '')] + return [(r['code'], r['name']) for r in res] + [('','')] + + + class res_partner(osv.osv): _description='Partner' @@ -138,10 +137,9 @@ 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"), + 'vat': fields.char('VAT',size=32 ,help="Value Added Tax number. Check the box if the partner is subjected to the VAT. Used by the VAT legal statement."), 'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'), 'website': fields.char('Website',size=64), 'comment': fields.text('Notes'), @@ -151,19 +149,27 @@ 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', help="Check this box if the partner is a customer."), + 'supplier': fields.boolean('Supplier', help="Check this box if the partner is a supplier. If it's not checked, purchase people will not see it when encoding a purchase order."), + 'city':fields.related('address','city',type='char', string='City'), + 'country':fields.related('address','country_id',type='many2one', relation='res.country', string='Country'), } + + def _default_category(self, cr, uid, context={}): + if 'category_id' in context and context['category_id']: + return [context['category_id']] + return [] + _defaults = { 'active': lambda *a: 1, + 'customer': lambda *a: 1, + 'category_id': _default_category, } - _sql_constraints = [ - ('name_uniq', 'unique (name)', 'The name of the partner must be unique !') - ] - def copy(self, cr, uid, id, default=None, context={}): name = self.read(cr, uid, [id], ['name'])[0]['name'] - default.update({'name': name+' (copy)'}) + default.update({'name': name+' (copy)', 'events':[]}) return super(res_partner, self).copy(cr, uid, id, default, context) - + def _check_ean_key(self, cr, uid, ids): for partner_o in pooler.get_pool(cr.dbname).get('res.partner').read(cr, uid, ids, ['ean13',]): thisean=partner_o['ean13'] @@ -189,10 +195,10 @@ class res_partner(osv.osv): rec_name = 'ref' else: rec_name = 'name' - + res = [(r['id'], r[rec_name]) for r in self.read(cr, uid, ids, [rec_name], context)] return res - + def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80): if not args: args=[] @@ -226,12 +232,12 @@ class res_partner(osv.osv): }) ids = ids[16:] return True - + def address_get(self, cr, uid, ids, adr_pref=['default']): - cr.execute('select type,id from res_partner_address where partner_id in ('+','.join(map(str,ids))+')') + cr.execute('select type,id from res_partner_address where partner_id in ('+','.join(map(str,map(int, ids)))+')') res = cr.fetchall() adr = dict(res) - # get the id of the (first) default address if there is one, + # get the id of the (first) default address if there is one, # otherwise get the id of the first address in the list if res: default_address = adr.get('default', res[0][1]) @@ -241,32 +247,40 @@ class res_partner(osv.osv): for a in adr_pref: result[a] = adr.get(a, default_address) return result - + def gen_next_ref(self, cr, uid, ids): if len(ids) != 1: return True - + # compute the next number ref cr.execute("select ref from res_partner where ref is not null order by char_length(ref) desc, ref desc limit 1") res = cr.dictfetchall() ref = res and res[0]['ref'] or '0' try: nextref = int(ref)+1 - except e: + except: raise osv.except_osv(_('Warning'), _("Couldn't generate the next id because some partners have an alphabetic id !")) # update the current partner - cr.execute("update res_partner set ref=%d where id=%d", (nextref, ids[0])) + cr.execute("update res_partner set ref=%s where id=%s", (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): - _description ='Partner Contact' + _description ='Partner Addresses' _name = 'res.partner.address' _order = 'id' _columns = { - 'partner_id': fields.many2one('res.partner', 'Partner', required=True, ondelete='cascade', select=True), - 'type': fields.selection( [ ('default','Default'),('invoice','Invoice'), ('delivery','Delivery'), ('contact','Contact'), ('other','Other') ],'Address Type'), + 'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null', select=True, help="Keep empty for a private address, not related to partner."), + 'type': fields.selection( [ ('default','Default'),('invoice','Invoice'), ('delivery','Delivery'), ('contact','Contact'), ('other','Other') ],'Address Type', help="Used to select automatically the right address according to the context in sales and purchases documents."), 'function': fields.many2one('res.partner.function', 'Function'), 'title': fields.selection(_contact_title_get, 'Title', size=32), 'name': fields.char('Contact Name', size=64), @@ -274,14 +288,14 @@ class res_partner_address(osv.osv): 'street2': fields.char('Street2', size=128), 'zip': fields.char('Zip', change_default=True, size=24), 'city': fields.char('City', size=128), - 'state_id': fields.many2one("res.country.state", 'State', change_default=True, domain="[('country_id','=',country_id)]"), - 'country_id': fields.many2one('res.country', 'Country', change_default=True), + 'state_id': fields.many2one("res.country.state", 'Fed. State', domain="[('country_id','=',country_id)]"), + 'country_id': fields.many2one('res.country', 'Country'), 'email': fields.char('E-Mail', size=240), 'phone': fields.char('Phone', size=64), 'fax': fields.char('Fax', size=64), 'mobile': fields.char('Mobile', size=64), 'birthdate': fields.char('Birthdate', size=64), - 'active': fields.boolean('Active'), + 'active': fields.boolean('Active', help="Uncheck the active field to hide the contact."), } _defaults = { 'active': lambda *a: 1, @@ -292,13 +306,13 @@ class res_partner_address(osv.osv): return [] res = [] for r in self.read(cr, user, ids, ['name','zip','city','partner_id', 'street']): - if context.get('contact_display', 'contact')=='partner': + if context.get('contact_display', 'contact')=='partner' and r['partner_id']: res.append((r['id'], r['partner_id'][1])) else: - addr = str(r['name'] or '') + addr = r['name'] or '' if r['name'] and (r['zip'] or r['city']): addr += ', ' - addr += str(r['street'] or '') + ' ' + str(r['zip'] or '') + ' ' + str(r['city'] or '') + addr += (r['street'] or '') + ' ' + (r['zip'] or '') + ' ' + (r['city'] or '') res.append((r['id'], addr.strip() or '/')) return res @@ -310,20 +324,27 @@ class res_partner_address(osv.osv): if context.get('contact_display', 'contact')=='partner': ids = self.search(cr, user, [('partner_id',operator,name)], limit=limit, context=context) else: - ids = self.search(cr, user, [('zip','=',name)] + args, limit=limit, context=context) - if not ids: + if not name: + ids = self.search(cr, user, args, limit=limit, context=context) + else: + ids = self.search(cr, user, [('zip','=',name)] + args, limit=limit, context=context) + if not ids: ids = self.search(cr, user, [('city',operator,name)] + args, limit=limit, context=context) if name: ids += self.search(cr, user, [('name',operator,name)] + args, limit=limit, context=context) ids += self.search(cr, user, [('partner_id',operator,name)] + args, limit=limit, context=context) return self.name_get(cr, user, ids, context=context) + + def get_city(self, cr, uid, id): + return self.browse(cr, uid, id).city + res_partner_address() class res_partner_bank_type(osv.osv): _description='Bank Account Type' _name = 'res.partner.bank.type' _columns = { - 'name': fields.char('Name', size=64, required=True), + 'name': fields.char('Name', size=64, required=True, translate=True), 'code': fields.char('Code', size=64, required=True), 'field_ids': fields.one2many('res.partner.bank.type.field', 'bank_type_id', 'Type fields'), } @@ -333,8 +354,8 @@ class res_partner_bank_type_fields(osv.osv): _description='Bank type fields' _name = 'res.partner.bank.type.field' _columns = { - 'name': fields.char('Field name', size=64, required=True), - 'bank_type_id': fields.many2one('res.partner.bank.type', 'Bank type', required=True, ondelete='cascade'), + 'name': fields.char('Field Name', size=64, required=True, translate=True), + 'bank_type_id': fields.many2one('res.partner.bank.type', 'Bank Type', required=True, ondelete='cascade'), 'required': fields.boolean('Required'), 'readonly': fields.boolean('Readonly'), 'size': fields.integer('Max. Size'), @@ -345,7 +366,7 @@ res_partner_bank_type_fields() class res_partner_bank(osv.osv): '''Bank Accounts''' _name = "res.partner.bank" - _rec_name = "state" + _rec_name = "acc_number" _description = __doc__ _order = 'sequence' @@ -354,7 +375,7 @@ class res_partner_bank(osv.osv): result = [] type_ids = bank_type_obj.search(cr, uid, []) - bank_types = bank_type_obj.browse(cr, uid, type_ids) + bank_types = bank_type_obj.browse(cr, uid, type_ids, context=context) for bank_type in bank_types: result.append((bank_type.code, bank_type.name)) return result @@ -375,9 +396,9 @@ class res_partner_bank(osv.osv): _columns = { 'name': fields.char('Description', size=128), - 'acc_number': fields.char('Account number', size=64, required=False), + 'acc_number': fields.char('Account Number', size=64, required=False), 'bank': fields.many2one('res.bank', 'Bank'), - 'owner_name': fields.char('Account owner', size=64), + 'owner_name': fields.char('Account Owner', size=64), 'street': fields.char('Street', size=128), 'zip': fields.char('Zip', change_default=True, size=24), 'city': fields.char('City', size=128), @@ -387,11 +408,9 @@ class res_partner_bank(osv.osv): change_default=True, domain="[('country_id','=',country_id)]"), 'partner_id': fields.many2one('res.partner', 'Partner', required=True, ondelete='cascade', select=True), - 'state': fields.selection(_bank_type_get, 'Bank type', required=True, + 'state': fields.selection(_bank_type_get, 'Bank Type', required=True, change_default=True), 'sequence': fields.integer('Sequence'), - 'state_id': fields.many2one('res.country.state', 'State', - domain="[('country_id', '=', country_id)]"), } _defaults = { 'owner_name': lambda obj, cursor, user, context: obj._default_value(