1 # -*- encoding: utf-8 -*-
\r
2 ##############################################################################
\r
4 # OpenERP, Open Source Management Solution
\r
6 # Copyright (c) 2011 Noviat nv/sa (www.noviat.be). All rights reserved.
\r
8 # This program is free software: you can redistribute it and/or modify
\r
9 # it under the terms of the GNU Affero General Public License as
\r
10 # published by the Free Software Foundation, either version 3 of the
\r
11 # License, or (at your option) any later version.
\r
13 # This program is distributed in the hope that it will be useful,
\r
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 # GNU Affero General Public License for more details.
\r
18 # You should have received a copy of the GNU Affero General Public License
\r
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
21 ##############################################################################
\r
23 import re, time, random
\r
24 from openerp import api
\r
25 from openerp.osv import fields, osv
\r
26 from openerp.tools.translate import _
\r
28 _logger = logging.getLogger(__name__)
\r
31 account.invoice object:
\r
32 - Add support for Belgian structured communication
\r
33 - Rename 'reference' field labels to 'Communication'
\r
36 class account_invoice(osv.osv):
\r
37 _inherit = 'account.invoice'
\r
40 def _get_reference_type(self, cursor, user, context=None):
\r
41 """Add BBA Structured Communication Type and change labels from 'reference' into 'communication' """
\r
42 res = super(account_invoice, self)._get_reference_type(cursor, user,
\r
44 res[[i for i,x in enumerate(res) if x[0] == 'none'][0]] = ('none', 'Free Communication')
\r
45 res.append(('bba', 'BBA Structured Communication'))
\r
46 #l_logger.warning('reference_type = %s' %res )
\r
49 def check_bbacomm(self, val):
\r
50 supported_chars = '0-9+*/ '
\r
51 pattern = re.compile('[^' + supported_chars + ']')
\r
52 if pattern.findall(val or ''):
\r
54 bbacomm = re.sub('\D', '', val or '')
\r
55 if len(bbacomm) == 12:
\r
56 base = int(bbacomm[:10])
\r
57 mod = base % 97 or 97
\r
58 if mod == int(bbacomm[-2:]):
\r
62 def _check_communication(self, cr, uid, ids):
\r
63 for inv in self.browse(cr, uid, ids):
\r
64 if inv.reference_type == 'bba':
\r
65 return self.check_bbacomm(inv.reference)
\r
68 def onchange_partner_id(self, cr, uid, ids, type, partner_id,
\r
69 date_invoice=False, payment_term=False,
\r
70 partner_bank_id=False, company_id=False,
\r
72 result = super(account_invoice, self).onchange_partner_id(cr, uid, ids, type, partner_id,
\r
73 date_invoice, payment_term, partner_bank_id, company_id, context)
\r
74 # reference_type = self.default_get(cr, uid, ['reference_type'])['reference_type']
\r
75 # _logger.warning('partner_id %s' % partner_id)
\r
77 reference_type = 'none'
\r
79 if (type == 'out_invoice'):
\r
80 reference_type = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context).out_inv_comm_type
\r
82 reference = self.generate_bbacomm(cr, uid, ids, type, reference_type, partner_id, '', context=context)['value']['reference']
\r
84 'reference_type': reference_type or 'none',
\r
85 'reference': reference,
\r
87 result['value'].update(res_update)
\r
90 def generate_bbacomm(self, cr, uid, ids, type, reference_type, partner_id, reference, context=None):
\r
91 partner_obj = self.pool.get('res.partner')
\r
92 reference = reference or ''
\r
95 algorithm = partner_obj.browse(cr, uid, partner_id, context=context).out_inv_comm_algorithm
\r
96 algorithm = algorithm or 'random'
\r
97 if (type == 'out_invoice'):
\r
98 if reference_type == 'bba':
\r
99 if algorithm == 'date':
\r
100 if not self.check_bbacomm(reference):
\r
101 doy = time.strftime('%j')
\r
102 year = time.strftime('%Y')
\r
104 seq_ids = self.search(cr, uid,
\r
105 [('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'),
\r
106 ('reference', 'like', '+++%s/%s/%%' % (doy, year))], order='reference')
\r
108 prev_seq = int(self.browse(cr, uid, seq_ids[-1]).reference[12:15])
\r
110 seq = '%03d' % (prev_seq + 1)
\r
112 raise osv.except_osv(_('Warning!'),
\r
113 _('The daily maximum of outgoing invoices with an automatically generated BBA Structured Communications has been exceeded!' \
\r
114 '\nPlease create manually a unique BBA Structured Communication.'))
\r
115 bbacomm = doy + year + seq
\r
116 base = int(bbacomm)
\r
117 mod = base % 97 or 97
\r
118 reference = '+++%s/%s/%s%02d+++' % (doy, year, seq, mod)
\r
119 elif algorithm == 'partner_ref':
\r
120 if not self.check_bbacomm(reference):
\r
121 partner_ref = self.pool.get('res.partner').browse(cr, uid, partner_id).ref
\r
122 partner_ref_nr = re.sub('\D', '', partner_ref or '')
\r
123 if (len(partner_ref_nr) < 3) or (len(partner_ref_nr) > 7):
\r
124 raise osv.except_osv(_('Warning!'),
\r
125 _('The Partner should have a 3-7 digit Reference Number for the generation of BBA Structured Communications!' \
\r
126 '\nPlease correct the Partner record.'))
\r
128 partner_ref_nr = partner_ref_nr.ljust(7, '0')
\r
130 seq_ids = self.search(cr, uid,
\r
131 [('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'),
\r
132 ('reference', 'like', '+++%s/%s/%%' % (partner_ref_nr[:3], partner_ref_nr[3:]))], order='reference')
\r
134 prev_seq = int(self.browse(cr, uid, seq_ids[-1]).reference[12:15])
\r
136 seq = '%03d' % (prev_seq + 1)
\r
138 raise osv.except_osv(_('Warning!'),
\r
139 _('The daily maximum of outgoing invoices with an automatically generated BBA Structured Communications has been exceeded!' \
\r
140 '\nPlease create manually a unique BBA Structured Communication.'))
\r
141 bbacomm = partner_ref_nr + seq
\r
142 base = int(bbacomm)
\r
143 mod = base % 97 or 97
\r
144 reference = '+++%s/%s/%s%02d+++' % (partner_ref_nr[:3], partner_ref_nr[3:], seq, mod)
\r
145 elif algorithm == 'random':
\r
146 if not self.check_bbacomm(reference):
\r
147 base = random.randint(1, 9999999999)
\r
148 bbacomm = str(base).rjust(10, '0')
\r
149 base = int(bbacomm)
\r
150 mod = base % 97 or 97
\r
151 mod = str(mod).rjust(2, '0')
\r
152 reference = '+++%s/%s/%s%s+++' % (bbacomm[:3], bbacomm[3:7], bbacomm[7:], mod)
\r
154 raise osv.except_osv(_('Error!'),
\r
155 _("Unsupported Structured Communication Type Algorithm '%s' !" \
\r
156 "\nPlease contact your Odoo support channel.") % algorithm)
\r
157 return {'value': {'reference': reference}}
\r
159 def create(self, cr, uid, vals, context=None):
\r
160 reference = vals.get('reference', False)
\r
161 reference_type = vals.get('reference_type', False)
\r
162 if vals.get('type') == 'out_invoice' and not reference_type:
\r
163 # fallback on default communication type for partner
\r
164 reference_type = self.pool.get('res.partner').browse(cr, uid, vals['partner_id']).out_inv_comm_type
\r
165 if reference_type == 'bba':
\r
166 reference = self.generate_bbacomm(cr, uid, [], vals['type'], reference_type, vals['partner_id'], '', context={})['value']['reference']
\r
168 'reference_type': reference_type or 'none',
\r
169 'reference': reference,
\r
172 if reference_type == 'bba':
\r
174 raise osv.except_osv(_('Warning!'),
\r
175 _('Empty BBA Structured Communication!' \
\r
176 '\nPlease fill in a unique BBA Structured Communication.'))
\r
177 if self.check_bbacomm(reference):
\r
178 reference = re.sub('\D', '', reference)
\r
179 vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++'
\r
180 same_ids = self.search(cr, uid,
\r
181 [('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'),
\r
182 ('reference', '=', vals['reference'])])
\r
184 raise osv.except_osv(_('Warning!'),
\r
185 _('The BBA Structured Communication has already been used!' \
\r
186 '\nPlease create manually a unique BBA Structured Communication.'))
\r
187 return super(account_invoice, self).create(cr, uid, vals, context=context)
\r
189 def write(self, cr, uid, ids, vals, context=None):
\r
190 if isinstance(ids, (int, long)):
\r
192 for inv in self.browse(cr, uid, ids, context):
\r
193 if vals.has_key('reference_type'):
\r
194 reference_type = vals['reference_type']
\r
196 reference_type = inv.reference_type or ''
\r
197 if reference_type == 'bba':
\r
198 if vals.has_key('reference'):
\r
199 bbacomm = vals['reference']
\r
201 bbacomm = inv.reference or ''
\r
202 if self.check_bbacomm(bbacomm):
\r
203 reference = re.sub('\D', '', bbacomm)
\r
204 vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++'
\r
205 same_ids = self.search(cr, uid,
\r
206 [('id', '!=', inv.id), ('type', '=', 'out_invoice'),
\r
207 ('reference_type', '=', 'bba'), ('reference', '=', vals['reference'])])
\r
209 raise osv.except_osv(_('Warning!'),
\r
210 _('The BBA Structured Communication has already been used!' \
\r
211 '\nPlease create manually a unique BBA Structured Communication.'))
\r
212 return super(account_invoice, self).write(cr, uid, ids, vals, context)
\r
214 def copy(self, cr, uid, id, default=None, context=None):
\r
215 default = default or {}
\r
216 invoice = self.browse(cr, uid, id, context=context)
\r
217 if invoice.type in ['out_invoice']:
\r
218 reference_type = invoice.reference_type or 'none'
\r
219 default['reference_type'] = reference_type
\r
220 if reference_type == 'bba':
\r
221 partner = invoice.partner_id
\r
222 default['reference'] = self.generate_bbacomm(cr, uid, id,
\r
223 invoice.type, reference_type,
\r
224 partner.id, '', context=context)['value']['reference']
\r
225 return super(account_invoice, self).copy(cr, uid, id, default, context=context)
\r
228 'reference': fields.char('Communication', help="The partner reference of this invoice."),
\r
229 'reference_type': fields.selection(_get_reference_type, 'Communication Type',
\r
233 (_check_communication, 'Invalid BBA Structured Communication !', ['Communication']),
\r
238 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\r