[FIX] account.invoice.line: move context to last position in onchange methods
[odoo/odoo.git] / addons / account_analytic_default / account_analytic_default.py
1 # -*- coding: utf-8 -*-
2 ###############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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 import time
23
24 from openerp.osv import fields, osv
25
26 class account_analytic_default(osv.osv):
27     _name = "account.analytic.default"
28     _description = "Analytic Distribution"
29     _rec_name = "analytic_id"
30     _order = "sequence"
31     _columns = {
32         'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of analytic distribution"),
33         'analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
34         'product_id': fields.many2one('product.product', 'Product', ondelete='cascade', help="Select a product which will use analytic account specified in analytic default (e.g. create new customer invoice or Sales order if we select this product, it will automatically take this as an analytic account)"),
35         'partner_id': fields.many2one('res.partner', 'Partner', ondelete='cascade', help="Select a partner which will use analytic account specified in analytic default (e.g. create new customer invoice or Sales order if we select this partner, it will automatically take this as an analytic account)"),
36         'user_id': fields.many2one('res.users', 'User', ondelete='cascade', help="Select a user which will use analytic account specified in analytic default."),
37         'company_id': fields.many2one('res.company', 'Company', ondelete='cascade', help="Select a company which will use analytic account specified in analytic default (e.g. create new customer invoice or Sales order if we select this company, it will automatically take this as an analytic account)"),
38         'date_start': fields.date('Start Date', help="Default start date for this Analytic Account."),
39         'date_stop': fields.date('End Date', help="Default end date for this Analytic Account."),
40     }
41
42     def account_get(self, cr, uid, product_id=None, partner_id=None, user_id=None, date=None, company_id=None, context=None):
43         domain = []
44         if product_id:
45             domain += ['|', ('product_id', '=', product_id)]
46         domain += [('product_id','=', False)]
47         if partner_id:
48             domain += ['|', ('partner_id', '=', partner_id)]
49         domain += [('partner_id', '=', False)]
50         if company_id:
51             domain += ['|', ('company_id', '=', company_id)]
52         domain += [('company_id', '=', False)]
53         if user_id:
54             domain += ['|',('user_id', '=', user_id)]
55         domain += [('user_id','=', False)]
56         if date:
57             domain += ['|', ('date_start', '<=', date), ('date_start', '=', False)]
58             domain += ['|', ('date_stop', '>=', date), ('date_stop', '=', False)]
59         best_index = -1
60         res = False
61         for rec in self.browse(cr, uid, self.search(cr, uid, domain, context=context), context=context):
62             index = 0
63             if rec.product_id: index += 1
64             if rec.partner_id: index += 1
65             if rec.company_id: index += 1
66             if rec.user_id: index += 1
67             if rec.date_start: index += 1
68             if rec.date_stop: index += 1
69             if index > best_index:
70                 res = rec
71                 best_index = index
72         return res
73
74
75 class account_invoice_line(osv.osv):
76     _inherit = "account.invoice.line"
77     _description = "Invoice Line"
78
79     def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, company_id=None, context=None):
80         res_prod = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit, currency_id=currency_id, company_id=company_id, context=context)
81         rec = self.pool.get('account.analytic.default').account_get(cr, uid, product, partner_id, uid, time.strftime('%Y-%m-%d'), company_id=company_id, context=context)
82         if rec:
83             res_prod['value'].update({'account_analytic_id': rec.analytic_id.id})
84         else:
85             res_prod['value'].update({'account_analytic_id': False})
86         return res_prod
87
88
89
90 class stock_picking(osv.osv):
91     _inherit = "stock.picking"
92
93     def _get_account_analytic_invoice(self, cursor, user, picking, move_line):
94         partner_id = picking.partner_id and picking.partner_id.id or False
95         rec = self.pool.get('account.analytic.default').account_get(cursor, user, move_line.product_id.id, partner_id, user, time.strftime('%Y-%m-%d'))
96
97         if rec:
98             return rec.analytic_id.id
99
100         return super(stock_picking, self)._get_account_analytic_invoice(cursor, user, picking, move_line)
101
102
103 class sale_order_line(osv.osv):
104     _inherit = "sale.order.line"
105
106     # Method overridden to set the analytic account by default on criterion match
107     def invoice_line_create(self, cr, uid, ids, context=None):
108         create_ids = super(sale_order_line, self).invoice_line_create(cr, uid, ids, context=context)
109         if not ids:
110             return create_ids
111         sale_line = self.browse(cr, uid, ids[0], context=context)
112         inv_line_obj = self.pool.get('account.invoice.line')
113         anal_def_obj = self.pool.get('account.analytic.default')
114
115         for line in inv_line_obj.browse(cr, uid, create_ids, context=context):
116             rec = anal_def_obj.account_get(cr, uid, line.product_id.id, sale_line.order_id.partner_id.id, sale_line.order_id.user_id.id, time.strftime('%Y-%m-%d'), context=context)
117
118             if rec:
119                 inv_line_obj.write(cr, uid, [line.id], {'account_analytic_id': rec.analytic_id.id}, context=context)
120         return create_ids
121 class product_product(osv.Model):
122     _inherit = 'product.product'
123     def _rules_count(self, cr, uid, ids, field_name, arg, context=None):
124         Analytic = self.pool['account.analytic.default']
125         return {
126             product_id: Analytic.search_count(cr, uid, [('product_id', '=', product_id)], context=context)
127             for product_id in ids
128         }
129     _columns = {
130         'rules_count': fields.function(_rules_count, string='# Analytic Rules', type='integer'),
131     }
132
133 class product_template(osv.Model):
134     _inherit = 'product.template'
135     
136     def _rules_count(self, cr, uid, ids, field_name, arg, context=None):
137         Analytic = self.pool['account.analytic.default']
138         res = {}
139         for product_tmpl_id in self.browse(cr, uid, ids, context=context):
140             res[product_tmpl_id.id] = sum([p.rules_count for p in product_tmpl_id.product_variant_ids])
141         return res
142
143     _columns = {
144         'rules_count': fields.function(_rules_count, string='# Analytic Rules', type='integer'),
145     }
146
147
148     def action_view_rules(self, cr, uid, ids, context=None):
149         products = self._get_products(cr, uid, ids, context=context)
150         result = self._get_act_window_dict(cr, uid, 'account_analytic_default.action_product_default_list', context=context)
151         result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]"
152         # Remove context so it is not going to filter on product_id with active_id of template
153         result['context'] = "{}"
154         return result
155
156 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: