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.osv import fields, osv
\r
25 from openerp.tools.translate import _
\r
27 _logger = logging.getLogger(__name__)
\r
30 account.invoice object:
\r
31 - Add support for Belgian structured communication
\r
32 - Rename 'reference' field labels to 'Communication'
\r
35 class account_invoice(osv.osv):
\r
36 _inherit = 'account.invoice'
\r
38 def _get_reference_type(self, cursor, user, context=None):
\r
39 """Add BBA Structured Communication Type and change labels from 'reference' into 'communication' """
\r
40 res = super(account_invoice, self)._get_reference_type(cursor, user,
\r
42 res[[i for i,x in enumerate(res) if x[0] == 'none'][0]] = ('none', 'Free Communication')
\r
43 res.append(('bba', 'BBA Structured Communication'))
\r
44 #l_logger.warning('reference_type = %s' %res )
\r
47 def check_bbacomm(self, val):
\r
48 supported_chars = '0-9+*/ '
\r
49 pattern = re.compile('[^' + supported_chars + ']')
\r
50 if pattern.findall(val or ''):
\r
52 bbacomm = re.sub('\D', '', val or '')
\r
53 if len(bbacomm) == 12:
\r
54 base = int(bbacomm[:10])
\r
55 mod = base % 97 or 97
\r
56 if mod == int(bbacomm[-2:]):
\r
60 def _check_communication(self, cr, uid, ids):
\r
61 for inv in self.browse(cr, uid, ids):
\r
62 if inv.reference_type == 'bba':
\r
63 return self.check_bbacomm(inv.reference)
\r
66 def onchange_partner_id(self, cr, uid, ids, type, partner_id,
\r
67 date_invoice=False, payment_term=False, partner_bank_id=False, company_id=False):
\r
68 result = super(account_invoice, self).onchange_partner_id(cr, uid, ids, type, partner_id,
\r
69 date_invoice, payment_term, partner_bank_id, company_id)
\r
70 # reference_type = self.default_get(cr, uid, ['reference_type'])['reference_type']
\r
71 # _logger.warning('partner_id %s' % partner_id)
\r
73 reference_type = 'none'
\r
75 if (type == 'out_invoice'):
\r
76 reference_type = self.pool.get('res.partner').browse(cr, uid, partner_id).out_inv_comm_type
\r
78 reference = self.generate_bbacomm(cr, uid, ids, type, reference_type, partner_id, '', context={})['value']['reference']
\r
80 'reference_type': reference_type or 'none',
\r
81 'reference': reference,
\r
83 result['value'].update(res_update)
\r
86 def generate_bbacomm(self, cr, uid, ids, type, reference_type, partner_id, reference, context=None):
\r
87 partner_obj = self.pool.get('res.partner')
\r
88 reference = reference or ''
\r
91 algorithm = partner_obj.browse(cr, uid, partner_id, context=context).out_inv_comm_algorithm
\r
92 algorithm = algorithm or 'random'
\r
93 if (type == 'out_invoice'):
\r
94 if reference_type == 'bba':
\r
95 if algorithm == 'date':
\r
96 if not self.check_bbacomm(reference):
\r
97 doy = time.strftime('%j')
\r
98 year = time.strftime('%Y')
\r
100 seq_ids = self.search(cr, uid,
\r
101 [('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'),
\r
102 ('reference', 'like', '+++%s/%s/%%' % (doy, year))], order='reference')
\r
104 prev_seq = int(self.browse(cr, uid, seq_ids[-1]).reference[12:15])
\r
106 seq = '%03d' % (prev_seq + 1)
\r
108 raise osv.except_osv(_('Warning!'),
\r
109 _('The daily maximum of outgoing invoices with an automatically generated BBA Structured Communications has been exceeded!' \
\r
110 '\nPlease create manually a unique BBA Structured Communication.'))
\r
111 bbacomm = doy + year + seq
\r
112 base = int(bbacomm)
\r
113 mod = base % 97 or 97
\r
114 reference = '+++%s/%s/%s%02d+++' % (doy, year, seq, mod)
\r
115 elif algorithm == 'partner_ref':
\r
116 if not self.check_bbacomm(reference):
\r
117 partner_ref = self.pool.get('res.partner').browse(cr, uid, partner_id).ref
\r
118 partner_ref_nr = re.sub('\D', '', partner_ref or '')
\r
119 if (len(partner_ref_nr) < 3) or (len(partner_ref_nr) > 7):
\r
120 raise osv.except_osv(_('Warning!'),
\r
121 _('The Partner should have a 3-7 digit Reference Number for the generation of BBA Structured Communications!' \
\r
122 '\nPlease correct the Partner record.'))
\r
124 partner_ref_nr = partner_ref_nr.ljust(7, '0')
\r
126 seq_ids = self.search(cr, uid,
\r
127 [('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'),
\r
128 ('reference', 'like', '+++%s/%s/%%' % (partner_ref_nr[:3], partner_ref_nr[3:]))], order='reference')
\r
130 prev_seq = int(self.browse(cr, uid, seq_ids[-1]).reference[12:15])
\r
132 seq = '%03d' % (prev_seq + 1)
\r
134 raise osv.except_osv(_('Warning!'),
\r
135 _('The daily maximum of outgoing invoices with an automatically generated BBA Structured Communications has been exceeded!' \
\r
136 '\nPlease create manually a unique BBA Structured Communication.'))
\r
137 bbacomm = partner_ref_nr + seq
\r
138 base = int(bbacomm)
\r
139 mod = base % 97 or 97
\r
140 reference = '+++%s/%s/%s%02d+++' % (partner_ref_nr[:3], partner_ref_nr[3:], seq, mod)
\r
141 elif algorithm == 'random':
\r
142 if not self.check_bbacomm(reference):
\r
143 base = random.randint(1, 9999999999)
\r
144 bbacomm = str(base).rjust(7, '0')
\r
145 base = int(bbacomm)
\r
146 mod = base % 97 or 97
\r
147 mod = str(mod).rjust(2, '0')
\r
148 reference = '+++%s/%s/%s%s+++' % (bbacomm[:3], bbacomm[3:7], bbacomm[7:], mod)
\r
150 raise osv.except_osv(_('Error!'),
\r
151 _("Unsupported Structured Communication Type Algorithm '%s' !" \
\r
152 "\nPlease contact your OpenERP support channel.") % algorithm)
\r
153 return {'value': {'reference': reference}}
\r
155 def create(self, cr, uid, vals, context=None):
\r
156 reference = vals.get('reference', False)
\r
157 reference_type = vals.get('reference_type', False)
\r
158 if vals.get('type') == 'out_invoice' and not reference_type:
\r
159 # fallback on default communication type for partner
\r
160 reference_type = self.pool.get('res.partner').browse(cr, uid, vals['partner_id']).out_inv_comm_type
\r
161 if reference_type == 'bba':
\r
162 reference = self.generate_bbacomm(cr, uid, [], vals['type'], reference_type, vals['partner_id'], '', context={})['value']['reference']
\r
164 'reference_type': reference_type or 'none',
\r
165 'reference': reference,
\r
168 if reference_type == 'bba':
\r
170 raise osv.except_osv(_('Warning!'),
\r
171 _('Empty BBA Structured Communication!' \
\r
172 '\nPlease fill in a unique BBA Structured Communication.'))
\r
173 if self.check_bbacomm(reference):
\r
174 reference = re.sub('\D', '', reference)
\r
175 vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++'
\r
176 same_ids = self.search(cr, uid,
\r
177 [('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'),
\r
178 ('reference', '=', vals['reference'])])
\r
180 raise osv.except_osv(_('Warning!'),
\r
181 _('The BBA Structured Communication has already been used!' \
\r
182 '\nPlease create manually a unique BBA Structured Communication.'))
\r
183 return super(account_invoice, self).create(cr, uid, vals, context=context)
\r
185 def write(self, cr, uid, ids, vals, context=None):
\r
186 if isinstance(ids, (int, long)):
\r
188 for inv in self.browse(cr, uid, ids, context):
\r
189 if vals.has_key('reference_type'):
\r
190 reference_type = vals['reference_type']
\r
192 reference_type = inv.reference_type or ''
\r
193 if reference_type == 'bba':
\r
194 if vals.has_key('reference'):
\r
195 bbacomm = vals['reference']
\r
197 bbacomm = inv.reference or ''
\r
198 if self.check_bbacomm(bbacomm):
\r
199 reference = re.sub('\D', '', bbacomm)
\r
200 vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++'
\r
201 same_ids = self.search(cr, uid,
\r
202 [('id', '!=', inv.id), ('type', '=', 'out_invoice'),
\r
203 ('reference_type', '=', 'bba'), ('reference', '=', vals['reference'])])
\r
205 raise osv.except_osv(_('Warning!'),
\r
206 _('The BBA Structured Communication has already been used!' \
\r
207 '\nPlease create manually a unique BBA Structured Communication.'))
\r
208 return super(account_invoice, self).write(cr, uid, ids, vals, context)
\r
210 def copy(self, cr, uid, id, default=None, context=None):
\r
211 default = default or {}
\r
212 invoice = self.browse(cr, uid, id, context=context)
\r
213 if invoice.type in ['out_invoice']:
\r
214 reference_type = invoice.reference_type or 'none'
\r
215 default['reference_type'] = reference_type
\r
216 if reference_type == 'bba':
\r
217 partner = invoice.partner_id
\r
218 default['reference'] = self.generate_bbacomm(cr, uid, id,
\r
219 invoice.type, reference_type,
\r
220 partner.id, '', context=context)['value']['reference']
\r
221 return super(account_invoice, self).copy(cr, uid, id, default, context=context)
\r
224 'reference': fields.char('Communication', size=64, help="The partner reference of this invoice."),
\r
225 'reference_type': fields.selection(_get_reference_type, 'Communication Type',
\r
229 (_check_communication, 'Invalid BBA Structured Communication !', ['Communication']),
\r
234 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\r