[FIX] added domain=[('type','<>','view')] on accounts of fiscal_position and fiscal_p...
[odoo/odoo.git] / addons / account / partner.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution   
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22
23 from osv import fields, osv
24 import ir
25
26 class account_fiscal_position(osv.osv):
27     _name = 'account.fiscal.position'
28     _description = 'Fiscal Position'
29     _columns = {
30         'name': fields.char('Fiscal Position', size=64, translate=True, required=True),
31         'company_id': fields.many2one('res.company', 'Company'),
32         'account_ids': fields.one2many('account.fiscal.position.account', 'position_id', 'Accounts Mapping'),
33         'tax_ids': fields.one2many('account.fiscal.position.tax', 'position_id', 'Taxes Mapping')
34     }
35     def map_tax(self, cr, uid, partner, taxes, context={}):
36         if (not partner) or (not partner.property_account_position) :
37             return map(lambda x: x.id, taxes)
38         result = []
39         for t in taxes:
40             ok = False
41             for tax in partner.property_account_position.tax_ids:
42                 if tax.tax_src_id.id==t.id:
43                     if tax.tax_dest_id:
44                         result.append(tax.tax_dest_id.id)
45                     ok=True
46             if not ok:
47                 result.append(t.id)
48         return result
49
50     def map_account(self, cr, uid, partner, account_id, context={}):
51         if (not partner) or (not partner.property_account_position) :
52             return account_id
53         for pos in partner.property_account_position.account_ids:
54             if pos.account_src_id.id==account_id:
55                 account_id = pos.account_dest_id.id
56                 break
57         return account_id
58 account_fiscal_position()
59
60
61 class account_fiscal_position_tax(osv.osv):
62     _name = 'account.fiscal.position.tax'
63     _description = 'Fiscal Position Taxes Mapping'
64     _rec_name = 'position_id'
65     _columns = {
66         'position_id': fields.many2one('account.fiscal.position', 'Fiscal Position', required=True, ondelete='cascade'),
67         'tax_src_id': fields.many2one('account.tax', 'Tax Source', required=True),
68         'tax_dest_id': fields.many2one('account.tax', 'Replacement Tax')
69     }
70 account_fiscal_position_tax()
71
72
73 class account_fiscal_position_account(osv.osv):
74     _name = 'account.fiscal.position.account'
75     _description = 'Fiscal Position Accounts Mapping'
76     _rec_name = 'position_id'
77     _columns = {
78         'position_id': fields.many2one('account.fiscal.position', 'Fiscal Position', required=True, ondelete='cascade'),
79         'account_src_id': fields.many2one('account.account', 'Account Source', domain=[('type','<>','view')], required=True),
80         'account_dest_id': fields.many2one('account.account', 'Account Destination', domain=[('type','<>','view')], required=True)
81     }
82 account_fiscal_position_account()
83
84 class res_partner(osv.osv):
85     _name = 'res.partner'
86     _inherit = 'res.partner'
87     _description = 'Partner'
88     def _credit_debit_get(self, cr, uid, ids, field_names, arg, context):
89         query = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
90         cr.execute(("""select
91                 l.partner_id, a.type, sum(l.debit-l.credit)
92             from
93                 account_move_line l
94             left join
95                 account_account a on (l.account_id=a.id)
96             where
97                 a.type in ('receivable','payable') and
98                 l.partner_id in (%s) and
99                 l.reconcile_id is null and
100                 """ % (','.join(map(str, ids)),))+query+"""
101             group by
102                 l.partner_id, a.type
103             """)
104         tinvert = {
105             'credit': 'receivable',
106             'debit': 'payable'
107         }
108         maps = {'receivable':'credit', 'payable':'debit' }
109         res = {}
110         for id in ids:
111             res[id] = {}.fromkeys(field_names, 0)
112         for pid,type,val in cr.fetchall():
113             res[pid][maps[type]] = val
114         return res
115
116     def _credit_search(self, cr, uid, obj, name, args):
117         if not len(args):
118             return []
119         where = ' and '.join(map(lambda x: '(sum(debit-credit)'+x[1]+str(x[2])+')',args))
120         query = self.pool.get('account.move.line')._query_get(cr, uid, context={})
121         cr.execute(('select partner_id from account_move_line l where account_id in (select id from account_account where type=%s and active) and reconcile_id is null and '+query+' and partner_id is not null group by partner_id having '+where), ('receivable',) )
122         res = cr.fetchall()
123         if not len(res):
124             return [('id','=','0')]
125         return [('id','in',map(lambda x:x[0], res))]
126
127     def _debit_search(self, cr, uid, obj, name, args):
128         if not len(args):
129             return []
130         query = self.pool.get('account.move.line')._query_get(cr, uid, context={})
131         where = ' and '.join(map(lambda x: '(sum(debit-credit)'+x[1]+str(x[2])+')',args))
132         cr.execute(('select partner_id from account_move_line l where account_id in (select id from account_account where type=%s and active) and reconcile_id is null and '+query+' and partner_id is not null group by partner_id having '+where), ('payable',) )
133         res = cr.fetchall()
134         if not len(res):
135             return [('id','=','0')]
136         return [('id','in',map(lambda x:x[0], res))]
137
138     _columns = {
139         'credit': fields.function(_credit_debit_get, fnct_search=_credit_search, method=True, string='Total Receivable', multi='dc', help="Total amount this customer owns you."),
140         'debit': fields.function(_credit_debit_get, fnct_search=_debit_search, method=True, string='Total Payable', multi='dc', help="Total amount you have to pay to this supplier."),
141         'debit_limit': fields.float('Payable Limit'),
142         'property_account_payable': fields.property(
143             'account.account',
144             type='many2one',
145             relation='account.account',
146             string="Account Payable",
147             method=True,
148             view_load=True,
149             domain="[('type', '=', 'payable')]",
150             help="This account will be used, instead of the default one, as the payable account for the current partner",
151             required=True),
152         'property_account_receivable': fields.property(
153             'account.account',
154             type='many2one',
155             relation='account.account',
156             string="Account Receivable",
157             method=True,
158             view_load=True,
159             domain="[('type', '=', 'receivable')]",
160             help="This account will be used, instead of the default one, as the receivable account for the current partner",
161             required=True),
162         'property_account_position': fields.property(
163             'account.fiscal.position',
164             type='many2one',
165             relation='account.fiscal.position',
166             string="Fiscal Position",
167             method=True,
168             view_load=True,
169             help="The fiscal position will determine taxes and the accounts used for the the partner.",
170         ),
171         'property_payment_term': fields.property(
172             'account.payment.term',
173             type='many2one',
174             relation='account.payment.term',
175             string ='Payment Term',
176             method=True,
177             view_load=True,
178             help="This payment term will be used, instead of the default one, for the current partner"),
179         'ref_companies': fields.one2many('res.company', 'partner_id',
180             'Companies that refers to partner'),
181     }
182 res_partner()
183
184
185
186 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
187