[MERGE] trunk-mako_to_jinja-rco: use Jinja2 instead of mako to render email templates...
[odoo/odoo.git] / addons / l10n_ch / invoice.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    Author: Nicolas Bessi. Copyright Camptocamp SA
5 #    Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 from datetime import datetime
23 from osv import fields, osv
24 from tools import mod10r
25
26 class account_invoice(osv.osv):
27     """Inherit account.invoice in order to add bvr
28     printing functionnalites. BVR is a Swiss payment vector"""
29     _inherit = "account.invoice"
30
31     ## @param self The object pointer.
32     ## @param cursor a psycopg cursor
33     ## @param user res.user.id that is currently loged
34     ## @parma context a standard dict
35     ## @return a list of tuple (name,value)
36     def _get_reference_type(self, cursor, user, context=None):
37         """Function use by the function field reference_type in order to initalise available
38         BVR Reference Types"""
39         res = super(account_invoice, self)._get_reference_type(cursor, user,
40                 context=context)
41         res.append(('bvr', 'BVR'))
42         return res
43
44     ## @param self The object pointer.
45     ## @param cursor a psycopg cursor
46     ## @param user res.user.id that is currently loged
47     ## @parma context a standard dict
48     ## @param name of the files
49     ## @param args a list of diverse argument
50     ## @parma context a standard dict
51     ## @return a  dict (invoice id,amount to pay)
52     def _amount_to_pay(self, cursor, user, ids, name, args, context=None):
53         '''Return the amount still to pay regarding all the payment orders'''
54         if not ids:
55             return {}
56         res = {}
57         for invoice in self.browse(cursor, user, ids, context=context):
58             res[invoice.id] = 0.0
59             if invoice.move_id:
60                 for line in invoice.move_id.line_id:
61                     if not line.date_maturity or \
62                             datetime.strptime(line.date_maturity, '%Y-%m-%d') \
63                             < datetime.now():
64                         res[invoice.id] += line.amount_to_pay
65         return res
66
67     _columns = {
68         ### BVR reference type BVR or FREE
69         'reference_type': fields.selection(_get_reference_type,
70             'Payment Reference', required=True),
71         ### Partner bank link between bank and partner id
72         'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account',
73             help='The partner bank account to pay\nKeep empty to use the default'
74             ),
75         ### Amount to pay
76         'amount_to_pay': fields.function(_amount_to_pay,
77             type='float', 
78             string='Amount to be paid',
79             help='The amount which should be paid at the current date\n' \
80                     'minus the amount which is already in payment order'),
81     }
82
83     ## @param self The object pointer.
84     ## @param cursor a psycopg cursor
85     ## @param user res.user.id that is currently loged
86     ## @parma ids invoices id
87     ## @return a boolean True if valid False if invalid
88     def _check_bvr(self, cr, uid, ids, context=None):
89         """
90         Function to validate a bvr reference like :
91         0100054150009>132000000000000000000000014+ 1300132412>
92         The validation is based on l10n_ch
93         """
94         invoices = self.browse(cr,uid,ids)
95         for invoice in invoices:
96             if invoice.reference_type == 'bvr':
97                 if not invoice.reference:
98                     return False
99                 ## I need help for this bug because in this case
100                 # <010001000060190> 052550152684006+ 43435>
101                 # the reference 052550152684006 do not match modulo 10
102                 #
103                 if mod10r(invoice.reference[:-1]) != invoice.reference and \
104                     len(invoice.reference) == 15:
105                     return True
106                 #
107                 if mod10r(invoice.reference[:-1]) != invoice.reference:
108                     return False
109         return True
110     ## @param self The object pointer.
111     ## @param cursor a psycopg cursor
112     ## @param user res.user.id that is currently loged
113     ## @parma ids invoices id
114     ## @return a boolean True if valid False if invalid
115     def _check_reference_type(self, cursor, user, ids, context=None):
116         """Check the customer invoice reference type depending
117         on the BVR reference type and the invoice partner bank type"""
118         for invoice in self.browse(cursor, user, ids):
119             if invoice.type in 'in_invoice':
120                 if invoice.partner_bank_id and \
121                         invoice.partner_bank_id.state in \
122                         ('bvrbank', 'bvrpost') and \
123                         invoice.reference_type != 'bvr':
124                     return False
125         return True
126
127     _constraints = [
128         (_check_bvr, 'Error: Invalid Bvr Number (wrong checksum).',
129             ['reference']),
130         (_check_reference_type, 'Error: BVR reference is required.',
131             ['reference_type']),
132     ]
133
134     ## @param self The object pointer.
135     ## @param cr a psycopg cursor
136     ## @param uid res.user.id that is currently loged
137     ## @parma ids invoices id
138     ## @parma type the invoice type
139     ## @param partner_id the partner linked to the invoice
140     ## @parma date_invoice date of the invoice
141     ## @parma payment_term inoice payment term
142     ## @param partner_bank_id the partner linked invoice bank
143     ## @return the dict of values with the partner_bank value updated
144     def onchange_partner_id(self, cr, uid, ids, type, partner_id,
145             date_invoice=False, payment_term=False, partner_bank_id=False, company_id=False):
146         """ Function that is call when the partner of the invoice is changed
147         it will retrieve and set the good bank partner bank"""
148         #context not define in signature of function in account module
149         context = {}
150         res = super(account_invoice, self).onchange_partner_id(cr,
151                                                                uid,
152                                                                ids,
153                                                                type,
154                                                                partner_id,
155                                                                date_invoice,
156                                                                payment_term,
157                                                                partner_bank_id,
158                                                                company_id)
159         bank_id = False
160         if partner_id:
161             if type in ('in_invoice', 'in_refund'):
162                 p = self.pool.get('res.partner').browse(cr, uid, partner_id, context)
163                 if p.bank_ids:
164                     bank_id = p.bank_ids[0].id
165                 res['value']['partner_bank_id'] = bank_id
166             else:
167                 user = self.pool.get('res.users').browse(cr, uid, uid, context)
168                 bank_ids = user.company_id.partner_id.bank_ids
169                 if bank_ids:
170                     #How to order bank ?
171                     for bank in bank_ids:
172                         if bank.my_bank:
173                             bank_id = bank.id
174                 res['value']['partner_bank_id'] = bank_id
175
176         if partner_bank_id != bank_id:
177             to_update = self.onchange_partner_bank(cr, uid, ids, bank_id)
178             res['value'].update(to_update['value'])
179         return res
180
181     ## @param self The object pointer.
182     ## @param cursor a psycopg cursor
183     ## @param user res.user.id that is currently loged
184     ## @parma ids invoices id
185     ## @param partner_bank_id the partner linked invoice bank
186     ## @return the dict of values with the reference type  value updated
187     def onchange_partner_bank(self, cursor, user, ids, partner_bank_id):
188         """update the reference type depending of the partner bank"""
189         res = {'value': {}}
190         partner_bank_obj = self.pool.get('res.partner.bank')
191         if partner_bank_id:
192             partner_bank = partner_bank_obj.browse(cursor, user, partner_bank_id)
193             if partner_bank.state in ('bvrbank', 'bvrpost'):
194                 res['value']['reference_type'] = 'bvr'
195         return res
196
197 account_invoice()
198
199 class account_tax_code(osv.osv):
200     """Inherit account tax code in order
201     to add a Case code"""
202     _name = 'account.tax.code'
203     _inherit = "account.tax.code"
204     _columns = {
205         'code': fields.char('Case Code', size=512),
206     }
207
208 account_tax_code()
209
210 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: