[TYPO] Set the right category for the Point Of Sale
[odoo/odoo.git] / addons / l10n_be_invoice_bba / invoice.py
1 # -*- encoding: utf-8 -*-\r
2 ##############################################################################\r
3 #\r
4 #    OpenERP, Open Source Management Solution\r
5 #    \r
6 #    Copyright (c) 2011 Noviat nv/sa (www.noviat.be). All rights reserved.\r
7\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
12 #\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
17 #\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
20 #\r
21 ##############################################################################\r
22 \r
23 import re, time, random\r
24 from osv import fields, osv\r
25 from tools.translate import _\r
26 import logging\r
27 _logger = logging.getLogger(__name__)\r
28 \r
29 """\r
30 account.invoice object:\r
31     - Add support for Belgian structured communication\r
32     - Rename 'reference' field labels to 'Communication'\r
33 """\r
34 \r
35 class account_invoice(osv.osv):\r
36     _inherit = 'account.invoice'\r
37 \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
41                 context=context)\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
45         return res\r
46 \r
47     def check_bbacomm(self, val):
48         supported_chars = '0-9+*/ '\r
49         pattern = re.compile('[^' + supported_chars + ']')\r
50         if pattern.findall(val or ''):\r
51             return False                \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
57                 return True\r
58         return False\r
59 \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
64         return True\r
65 \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
72         reference = False\r
73         reference_type = 'none'\r
74         if partner_id:        \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
77                 if reference_type:\r
78                     reference = self.generate_bbacomm(cr, uid, ids, type, reference_type, partner_id, '', context={})['value']['reference']\r
79         res_update = {       \r
80             'reference_type': reference_type or 'none',\r
81             'reference': reference,\r
82         }\r
83         result['value'].update(res_update)\r
84         return result                    \r
85 \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 ''
89         algorithm = False
90         if partner_id:\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
99                         seq = '001'\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
103                         if seq_ids:\r
104                             prev_seq = int(self.browse(cr, uid, seq_ids[-1]).reference[12:15])\r
105                             if prev_seq < 999:\r
106                                 seq = '%03d' % (prev_seq + 1)\r
107                             else:\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
123                         else:\r
124                             partner_ref_nr = partner_ref_nr.ljust(7, '0')\r
125                             seq = '001'\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
129                             if seq_ids:\r
130                                 prev_seq = int(self.browse(cr, uid, seq_ids[-1]).reference[12:15])\r
131                                 if prev_seq < 999:\r
132                                     seq = '%03d' % (prev_seq + 1)\r
133                                 else:\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
149                 else:\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
154     \r
155     def create(self, cr, uid, vals, context=None):\r
156         if vals.has_key('reference_type'):\r
157             reference_type = vals['reference_type']\r
158             if reference_type == 'bba':               \r
159                 if vals.has_key('reference'):\r
160                     bbacomm = vals['reference']\r
161                 else:\r
162                     raise osv.except_osv(_('Warning!'),\r
163                         _('Empty BBA Structured Communication!' \\r
164                           '\nPlease fill in a unique BBA Structured Communication.'))       \r
165                 if self.check_bbacomm(bbacomm):\r
166                     reference = re.sub('\D', '', bbacomm)\r
167                     vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++'     \r
168                     same_ids = self.search(cr, uid, \r
169                         [('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'),\r
170                          ('reference', '=', vals['reference'])])\r
171                     if same_ids:\r
172                         raise osv.except_osv(_('Warning!'),\r
173                             _('The BBA Structured Communication has already been used!' \\r
174                               '\nPlease create manually a unique BBA Structured Communication.'))                 \r
175         return super(account_invoice, self).create(cr, uid, vals, context=context)     \r
176 \r
177     def write(self, cr, uid, ids, vals, context={}):\r
178         if isinstance(ids, (int, long)):\r
179             ids = [ids]\r
180         for inv in self.browse(cr, uid, ids, context):    \r
181             if vals.has_key('reference_type'):\r
182                 reference_type = vals['reference_type']\r
183             else:    \r
184                 reference_type = inv.reference_type or ''\r
185             if reference_type == 'bba':               \r
186                 if vals.has_key('reference'):\r
187                     bbacomm = vals['reference']\r
188                 else:\r
189                     bbacomm = inv.reference or ''\r
190                 if self.check_bbacomm(bbacomm):\r
191                     reference = re.sub('\D', '', bbacomm)\r
192                     vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++'     \r
193                     same_ids = self.search(cr, uid, \r
194                         [('id', '!=', inv.id), ('type', '=', 'out_invoice'), \r
195                          ('reference_type', '=', 'bba'), ('reference', '=', vals['reference'])])\r
196                     if same_ids:\r
197                         raise osv.except_osv(_('Warning!'),\r
198                             _('The BBA Structured Communication has already been used!' \\r
199                               '\nPlease create manually a unique BBA Structured Communication.'))                 \r
200         return super(account_invoice, self).write(cr, uid, ids, vals, context)    \r
201 \r
202     _columns = {\r
203         'reference': fields.char('Communication', size=64, help="The partner reference of this invoice."),\r
204         'reference_type': fields.selection(_get_reference_type, 'Communication Type',\r
205             required=True),\r
206     }\r
207     \r
208     _constraints = [\r
209         (_check_communication, 'Invalid BBA Structured Communication !', ['Communication']),\r
210         ]\r
211 \r
212 account_invoice()\r
213 \r
214 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:\r