[MERGE] forward port of branch 7.0 up to 3a0af6a
[odoo/odoo.git] / addons / sale / res_config.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Business Applications
5 #    Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
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 logging
23
24 from openerp.osv import fields, osv
25 from openerp.tools.translate import _
26
27 _logger = logging.getLogger(__name__)
28
29
30 class sale_configuration(osv.TransientModel):
31     _inherit = 'sale.config.settings'
32
33     def set_group_product_variant(self, cr, uid, ids, context=None):
34         """ This method is automatically called by res_config as it begins
35             with set. It is used to implement the 'one group or another'
36             behavior. We have to perform some group manipulation by hand
37             because in res_config.execute(), set_* methods are called
38             after group_*; therefore writing on an hidden res_config file
39             could not work.
40             If group_product_variant is checked: remove group_product_mono
41             from group_user, remove the users. Otherwise, just add
42             group_product_mono in group_user.
43             The inverse logic about group_product_variant is managed by the
44             normal behavior of 'group_product_variant' field.
45         """
46         def ref(xml_id):
47             mod, xml = xml_id.split('.', 1)
48             return self.pool['ir.model.data'].get_object(cr, uid, mod, xml, context)
49
50         for obj in self.browse(cr, uid, ids, context=context):
51             config_group = ref('product.group_product_mono')
52             base_group = ref('base.group_user')
53             if obj.group_product_variant:
54                 base_group.write({'implied_ids': [(3, config_group.id)]})
55                 config_group.write({'users': [(3, u.id) for u in base_group.users]})
56             else:
57                 base_group.write({'implied_ids': [(4, config_group.id)]})
58         return True
59
60     _columns = {
61         'group_invoice_so_lines': fields.boolean('Generate invoices based on the sales order lines',
62             implied_group='sale.group_invoice_so_lines',
63             help="To allow your salesman to make invoices for sales order lines using the menu 'Lines to Invoice'."),
64         'timesheet': fields.boolean('Prepare invoices based on timesheets',
65             help='For modifying account analytic view to show important data to project manager of services companies.'
66                  'You can also view the report of account analytic summary user-wise as well as month wise.\n'
67                  '-This installs the module account_analytic_analysis.'),
68         'module_account_analytic_analysis': fields.boolean('Use contracts management',
69             help='Allows to define your customer contracts conditions: invoicing '
70                  'method (fixed price, on timesheet, advance invoice), the exact pricing '
71                  '(650€/day for a developer), the duration (one year support contract).\n'
72                  'You will be able to follow the progress of the contract and invoice automatically.\n'
73                  '-It installs the account_analytic_analysis module.'),
74         'time_unit': fields.many2one('product.uom', 'The default working time unit for services is'),
75         'group_sale_pricelist':fields.boolean("Use pricelists to adapt your price per customers",
76             implied_group='product.group_sale_pricelist',
77             help="""Allows to manage different prices based on rules per category of customers.
78 Example: 10% for retailers, promotion of 5 EUR on this product, etc."""),
79         'group_uom':fields.boolean("Allow using different units of measure",
80             implied_group='product.group_uom',
81             help="""Allows you to select and maintain different units of measure for products."""),
82         'group_discount_per_so_line': fields.boolean("Allow setting a discount on the sales order lines",
83             implied_group='sale.group_discount_per_so_line',
84             help="Allows you to apply some discount per sales order line."),
85         'group_product_variant': fields.boolean("Support multiple variants per products  ",
86             implied_group='product.group_product_variant',
87             help="""Allow to manage several variants per product. As an example, if you  sell T-Shirts, for the same "Linux T-Shirt", you may have variants on  sizes or colors; S, M, L, XL, XXL."""),
88         'module_warning': fields.boolean("Allow configuring alerts by customer or products",
89             help='Allow to configure notification on products and trigger them when a user wants to sell a given product or a given customer.\n'
90                  'Example: Product: this product is deprecated, do not purchase more than 5.\n'
91                  'Supplier: don\'t forget to ask for an express delivery.'),
92         'module_sale_margin': fields.boolean("Display margins on sales orders",
93             help='This adds the \'Margin\' on sales order.\n'
94                  'This gives the profitability by calculating the difference between the Unit Price and Cost Price.\n'
95                  '-This installs the module sale_margin.'),
96         'module_website_quote': fields.boolean("Allow online quotations and templates",
97             help='This adds the online quotation'),
98         'module_sale_journal': fields.boolean("Allow batch invoicing of delivery orders through journals",
99             help='Allows you to categorize your sales and deliveries (picking lists) between different journals, '
100                  'and perform batch operations on journals.\n'
101                  '-This installs the module sale_journal.'),
102         'module_analytic_user_function': fields.boolean("One employee can have different roles per contract",
103             help='Allows you to define what is the default function of a specific user on a given account.\n'
104                  'This is mostly used when a user encodes his timesheet. The values are retrieved and the fields are auto-filled. '
105                  'But the possibility to change these values is still available.\n'
106                  '-This installs the module analytic_user_function.'),
107         'module_project': fields.boolean("Project"),
108         'module_sale_stock': fields.boolean("Trigger delivery orders automatically from sales orders",
109             help='Allows you to Make Quotation, Sale Order using different Order policy and Manage Related Stock.\n'
110                  '-This installs the module sale_stock.'),
111         'group_sale_delivery_address': fields.boolean("Allow a different address for delivery and invoicing ",
112             implied_group='sale.group_delivery_invoice_address',
113             help="Allows you to specify different delivery and invoice addresses on a sales order."),
114     }
115
116     def default_get(self, cr, uid, fields, context=None):
117         ir_model_data = self.pool.get('ir.model.data')
118         res = super(sale_configuration, self).default_get(cr, uid, fields, context)
119         if res.get('module_project'):
120             user = self.pool.get('res.users').browse(cr, uid, uid, context)
121             res['time_unit'] = user.company_id.project_time_mode_id.id
122         else:
123             product = ir_model_data.xmlid_to_object(cr, uid, 'product.product_product_consultant')
124             if product and product.exists():
125                 res['time_unit'] = product.uom_id.id
126         res['timesheet'] = res.get('module_account_analytic_analysis')
127         return res
128
129     def _get_default_time_unit(self, cr, uid, context=None):
130         ids = self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Hour'))], context=context)
131         return ids and ids[0] or False
132
133     _defaults = {
134         'time_unit': _get_default_time_unit,
135     }
136
137     def set_sale_defaults(self, cr, uid, ids, context=None):
138         ir_model_data = self.pool.get('ir.model.data')
139         wizard = self.browse(cr, uid, ids)[0]
140
141         if wizard.time_unit:
142             product = ir_model_data.xmlid_to_object(cr, uid, 'product.product_product_consultant')
143             if product and product.exists():
144                 product.write({'uom_id': wizard.time_unit.id, 'uom_po_id': wizard.time_unit.id})
145             else:
146                 _logger.warning("Product with xml_id 'product.product_product_consultant' not found, UoMs not updated!")
147
148         if wizard.module_project and wizard.time_unit:
149             user = self.pool.get('res.users').browse(cr, uid, uid, context)
150             user.company_id.write({'project_time_mode_id': wizard.time_unit.id})
151         return {}
152
153     def onchange_task_work(self, cr, uid, ids, task_work, context=None):
154         return {'value': {
155             'module_project_timesheet': task_work,
156             'module_project_mrp': task_work,
157         }}
158
159     def onchange_timesheet(self, cr, uid, ids, timesheet, context=None):
160         return {'value': {
161             'timesheet': timesheet,
162             'module_account_analytic_analysis': timesheet,
163         }}
164
165 class account_config_settings(osv.osv_memory):
166     _inherit = 'account.config.settings'
167     _columns = {
168         'module_sale_analytic_plans': fields.boolean('Use multiple analytic accounts on sales',
169             help="""This allows install module sale_analytic_plans."""),
170         'group_analytic_account_for_sales': fields.boolean('Analytic accounting for sales',
171             implied_group='sale.group_analytic_accounting',
172             help="Allows you to specify an analytic account on sales orders."),
173     }
174
175     def onchange_sale_analytic_plans(self, cr, uid, ids, module_sale_analytic_plans, context=None):
176         """ change group_analytic_account_for_sales following module_sale_analytic_plans """
177         if not module_sale_analytic_plans:
178             return {}
179         return {'value': {'group_analytic_account_for_sales': module_sale_analytic_plans}}
180
181 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: