1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
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.
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.
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/>.
20 ##############################################################################
25 from osv import fields, osv
26 from tools.translate import _
27 from lxml import etree
28 from osv import fields, osv
31 #Application and feature chooser, this could be done by introspecting ir.modules
33 class base_setup_installer(osv.osv_memory):
34 _name = 'base.setup.installer'
35 _inherit = 'res.config.installer'
38 ('sale','crm'): ['sale_crm'],
39 ('sale','project'): ['project_mrp'],
43 'crm':fields.boolean('Customer Relationship Management',
44 help="Helps you track and manage relations with customers such as"
45 " leads, requests or issues. Can automatically send "
46 "reminders, escalate requests or trigger business-specific "
47 "actions based on standard events."),
48 'sale':fields.boolean('Sales Management',
49 help="Helps you handle your quotations, sale orders and invoicing"
51 'project':fields.boolean('Project Management',
52 help="Helps you manage your projects and tasks by tracking them, "
53 "generating plannings, etc..."),
54 'knowledge':fields.boolean('Knowledge Management',
55 help="Lets you install addons geared towards sharing knowledge "
56 "with and between your employees."),
57 'stock':fields.boolean('Warehouse Management',
58 help="Helps you manage your inventory and main stock operations: delivery orders, receptions, etc."),
59 'mrp':fields.boolean('Manufacturing',
60 help="Helps you manage your manufacturing processes and generate "
61 "reports on those processes."),
62 'account_voucher':fields.boolean('Invoicing & Payments',
63 help="Allows you to create your invoices and track the payments. It is an easier version of the accounting module for managers who are not accountants."),
64 'account_accountant':fields.boolean('Accounting & Finance',
65 help="Helps you handle your accounting needs, if you are not an accountant, we suggest you to install only the Invoicing "),
66 'purchase':fields.boolean('Purchase Management',
67 help="Helps you manage your purchase-related processes such as "
68 "requests for quotations, supplier invoices, etc..."),
69 'hr':fields.boolean('Human Resources',
70 help="Helps you manage your human resources by encoding your employees structure, generating work sheets, tracking attendance and more."),
71 'point_of_sale':fields.boolean('Point of Sales',
72 help="Helps you get the most out of your points of sales with "
73 "fast sale encoding, simplified payment mode encoding, "
74 "automatic picking lists generation and more."),
75 'marketing':fields.boolean('Marketing',
76 help="Helps you manage your marketing campaigns step by step."),
77 'profile_tools':fields.boolean('Extra Tools',
78 help="Lets you install various interesting but non-essential tools "
79 "like Survey, Lunch and Ideas box."),
80 'report_designer':fields.boolean('Advanced Reporting',
81 help="Lets you install various tools to simplify and enhance "
82 "OpenERP's report creation."),
84 'product_expiry':fields.boolean('Food Industry',
85 help="Installs a preselected set of OpenERP applications "
86 "which will help you manage your industry."),
87 'association':fields.boolean('Associations',
88 help="Installs a preselected set of OpenERP "
89 "applications which will help you manage your association "
91 'auction':fields.boolean('Auction Houses',
92 help="Installs a preselected set of OpenERP "
93 "applications selected to help you manage your auctions "
94 "as well as the business processes around them."),
95 'account_analytic_plans': fields.boolean('Multiple Analytic Plans',
96 help="Allows invoice lines to impact multiple analytic accounts "
98 'account_payment': fields.boolean('Suppliers Payment Management',
99 help="Streamlines invoice payment and creates hooks to plug "
100 "automated payment systems in."),
101 'account_followup': fields.boolean('Followups Management',
102 help="Helps you generate reminder letters for unpaid invoices, "
103 "including multiple levels of reminding and customized "
104 "per-partner policies."),
105 'account_anglo_saxon': fields.boolean('Anglo-Saxon Accounting',
106 help="This module will support the Anglo-Saxons accounting methodology by "
107 "changing the accounting logic with stock transactions."),
108 'account_asset': fields.boolean('Assets Management',
109 help="Helps you to manage your assets and their depreciation entries."),
110 # Manufacturing Resource Planning
111 'stock_location': fields.boolean('Advanced Routes',
112 help="Manages product routes and paths within and between "
113 "locations (e.g. warehouses)."),
114 'mrp_jit': fields.boolean('Just In Time Scheduling',
115 help="Enables Just In Time computation of procurement orders."
116 "\n\nWhile it's more resource intensive than the default "
117 "setup, the JIT computer avoids having to wait for the "
118 "procurement scheduler to run or having to run the "
119 "procurement scheduler manually."),
120 'mrp_operations': fields.boolean('Manufacturing Operations',
121 help="Enhances production orders with readiness states as well "
122 "as the start date and end date of execution of the order."),
123 'mrp_subproduct': fields.boolean('MRP Subproducts',
124 help="Enables multiple product output from a single production "
125 "order: without this, a production order can have only one "
127 'mrp_repair': fields.boolean('Repairs',
128 help="Enables warranty and repair management (and their impact "
129 "on stocks and invoicing)."),
130 # Knowledge Management
131 'document_ftp':fields.boolean('Shared Repositories (FTP)',
132 help="Provides an FTP access to your OpenERP's "
133 "Document Management System. It lets you access attachments "
134 "and virtual documents through a standard FTP client."),
135 'document_webdav':fields.boolean('Shared Repositories (WebDAV)',
136 help="Provides a WebDAV access to your OpenERP's Document "
137 "Management System. Lets you access attachments and "
138 "virtual documents through your standard file browser."),
139 'wiki':fields.boolean('Collaborative Content (Wiki)',
140 help="Lets you create wiki pages and page groups in order "
141 "to keep track of business knowledge and share it with "
142 "and between your employees."),
144 'wiki_faq':fields.boolean('Template: Internal FAQ',
145 help="Creates a skeleton internal FAQ pre-filled with "
146 "documentation about OpenERP's Document Management "
148 'wiki_quality_manual':fields.boolean('Template: Quality Manual',
149 help="Creates an example skeleton for a standard quality manual."),
151 'base_report_designer':fields.boolean('OpenOffice Report Designer',help="Adds wizards to Import/Export .SXW report which "
152 "you can modify in OpenOffice.Once you have modified it you can "
153 "upload the report using the same wizard."),
154 'base_report_creator':fields.boolean('Query Builder',help="Allows you to create any statistic "
155 "reports on several objects. It's a SQL query builder and browser for end users."),
156 'lunch':fields.boolean('Lunch',help='A simple module to help you to manage Lunch orders.'),
157 'subscription':fields.boolean('Recurring Documents',help='Helps to generate automatically recurring documents.'),
158 'survey':fields.boolean('Survey',help='Allows you to organize surveys.'),
159 'idea':fields.boolean('Ideas Box',help='Promote ideas of the employees, votes and discussion on best ideas.'),
160 'share':fields.boolean('Web Share',help='Allows you to give restricted access to your OpenERP documents to external users, ' \
161 'such as customers, suppliers, or accountants. You can share any OpenERP Menu such as your project tasks, support requests, invoices, etc.'),
162 'pad': fields.boolean('Collaborative Note Pads',
163 help="This module creates a tighter integration between a Pad "
164 "instance of your choosing and your OpenERP Web Client by "
165 "letting you easily link pads to OpenERP objects via "
166 "OpenERP attachments."),
167 'email_template':fields.boolean('Automated E-Mails',
168 help="Helps you to design templates of emails and integrate them in your different processes."),
169 'marketing_campaign':fields.boolean('Marketing Campaigns',
170 help="Helps you to manage marketing campaigns and automate actions and communication steps."),
171 'crm_profiling':fields.boolean('Profiling Tools',
172 help="Helps you to perform segmentation of partners and design segmentation questionnaires"),
173 # Human Resources Management
174 'hr_holidays': fields.boolean('Leaves Management',
175 help="Tracks employee leaves, allocation requests and planning."),
176 'hr_expense': fields.boolean('Expenses',
177 help="Tracks and manages employee expenses, and can "
178 "automatically re-invoice clients if the expenses are "
180 'hr_recruitment': fields.boolean('Recruitment Process',
181 help="Helps you manage and streamline your recruitment process."),
182 'hr_timesheet_sheet':fields.boolean('Timesheets',
183 help="Tracks and helps employees encode and validate timesheets "
185 'hr_contract': fields.boolean("Employee's Contracts",
186 help="Extends employee profiles to help manage their contracts."),
187 'hr_evaluation': fields.boolean('Periodic Evaluations',
188 help="Lets you create and manage the periodic evaluation and "
189 "performance review of employees."),
190 'hr_attendance': fields.boolean('Attendances',
191 help="Simplifies the management of employee's attendances."),
192 'hr_payroll': fields.boolean('Payroll',
193 help="Generic Payroll system."),
194 'hr_payroll_account': fields.boolean('Payroll Accounting',
195 help="Generic Payroll system Integrated with Accountings."),
197 'project_long_term': fields.boolean(
198 'Long Term Planning',
199 help="Enables long-term projects tracking, including "
200 "multiple-phase projects and resource allocation handling."),
201 'hr_timesheet_sheet': fields.boolean('Timesheets',
202 help="Tracks and helps employees encode and validate timesheets "
204 'project_timesheet': fields.boolean('Bill Time on Tasks',
205 help="Helps generate invoices based on time spent on tasks, if activated on the project."),
206 'account_budget': fields.boolean('Budgets',
207 help="Helps accountants manage analytic and crossover budgets."),
208 'project_issue': fields.boolean('Issues Tracker',
209 help="Automatically synchronizes project tasks and crm cases."),
211 'project_scrum': fields.boolean('Methodology: SCRUM',
212 help="Implements and tracks the concepts and task types defined "
213 "in the SCRUM methodology."),
214 'project_gtd': fields.boolean('Methodology: Getting Things Done',
215 help="GTD is a methodology to efficiently organise yourself and your tasks. This module fully integrates GTD principle with OpenERP's project management."),
216 'purchase_requisition':fields.boolean('Purchase Requisition',help="Manages your Purchase Requisition and allows you to easily keep track and manage all your purchase orders."),
217 'purchase_analytic_plans': fields.boolean('Purchase Analytic Plans',help="Manages analytic distribution and purchase orders."),
218 'delivery': fields.boolean('Delivery Costs',
219 help="Allows you to compute delivery costs on your quotations."),
220 'sale_journal': fields.boolean('Invoicing journals',
221 help="Allows you to group and invoice your delivery orders according to different invoicing types: daily, weekly, etc."),
222 'sale_layout': fields.boolean('Sales Orders Print Layout',
223 help="Provides some features to improve the layout of the Sales Order reports."),
224 'sale_margin': fields.boolean('Margins in Sales Orders',
225 help="Gives the margin of profitability by calculating "
226 "the difference between Unit Price and Cost Price."),
227 'sale_order_dates': fields.boolean('Full Dates on Sales Orders',
228 help="Adds commitment, requested and effective dates on Sales Orders."),
229 'hr_expense':fields.boolean('Resources Management: Expenses Tracking', help="Tracks and manages employee expenses, and can "
230 "automatically re-invoice clients if the expenses are "
232 'event_project':fields.boolean('Event Management: Events', help="Helps you to manage and organize your events."),
233 'project_gtd':fields.boolean('Getting Things Done',
234 help="GTD is a methodology to efficiently organise yourself and your tasks. This module fully integrates GTD principle with OpenERP's project management."),
235 'wiki': fields.boolean('Wiki', help="Lets you create wiki pages and page groups in order "
236 "to keep track of business knowledge and share it with "
237 "and between your employees."),
238 'name': fields.char('Name', size=64),
239 'crm_helpdesk': fields.boolean('Helpdesk', help="Manages a Helpdesk service."),
240 'crm_fundraising': fields.boolean('Fundraising', help="This may help associations in their fundraising process and tracking."),
241 'crm_claim': fields.boolean('Claims', help="Manages the suppliers and customers claims, including your corrective or preventive actions."),
242 'import_sugarcrm': fields.boolean('Import Data from SugarCRM', help="Help you to import and update data from SugarCRM to OpenERP"),
243 'crm_caldav': fields.boolean('Calendar Synchronizing', help="Helps you to synchronize the meetings with other calendar clients and mobiles."),
244 'sale_crm': fields.boolean('Opportunity to Quotation', help="Create a Quotation from an Opportunity."),
245 'fetchmail': fields.boolean('Fetch Emails', help="Allows you to receive E-Mails from POP/IMAP server."),
246 'thunderbird': fields.boolean('Thunderbird Plug-In', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
247 'outlook': fields.boolean('MS-Outlook Plug-In', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
248 'wiki_sale_faq': fields.boolean('Sale FAQ', help="Helps you manage wiki pages for Frequently Asked Questions on Sales Application."),
249 'import_google': fields.boolean('Google Import', help="Imports contacts and events from your google account."),
253 'mrp_jit': lambda self,cr,uid,*a: self.pool.get('res.users').browse(cr, uid, uid).view == 'simple',
255 'marketing_campaign': lambda *a: 1,
258 def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
259 res = super(base_setup_installer, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
260 doc = etree.XML(res['arch'])
261 for module in ['project_gtd','hr_expense']:
263 for node in doc.xpath("//field[@name='%s']" % (module)):
266 node.set('invisible', '1')
267 res['arch'] = etree.tostring(doc)
268 #Checking sale module is installed or not
269 cr.execute("SELECT * from ir_module_module where state='installed' and name = 'sale'")
270 count = cr.fetchall()
272 doc = etree.XML(res['arch'])
273 nodes = doc.xpath("//field[@name='sale_crm']")
275 node.set('invisible', '0')
276 node.set('modifiers', '{}')
277 res['arch'] = etree.tostring(doc)
280 def _if_knowledge(self, cr, uid, ids, context=None):
281 if self.pool.get('res.users').browse(cr, uid, uid, context=context)\
283 return ['document_ftp']
286 def _if_misc_tools(self, cr, uid, ids, context=None):
287 return ['profile_tools']
289 def onchange_moduleselection(self, cr, uid, ids, *args, **kargs):
292 closed, total = self.get_current_progress(cr, uid)
293 progress = round(100. * closed / (total + len(filter(None, args))))
294 value.update({'progress':progress})
298 return {'value':value}
301 def execute(self, cr, uid, ids, context=None):
302 module_pool = self.pool.get('ir.module.module')
303 modules_selected = []
304 datas = self.read(cr, uid, ids, context=context)[0]
305 for mod in datas.keys():
306 if mod in ('id', 'progress'):
309 modules_selected.append(mod)
311 module_ids = module_pool.search(cr, uid, [('name', 'in', modules_selected)], context=context)
313 for module in module_pool.browse(cr, uid, module_ids, context=context):
314 if module.state == 'uninstalled':
315 module_pool.state_update(cr, uid, [module.id], 'to install', ['uninstalled'], context)
318 elif module.state == 'installed':
319 cr.execute("update ir_actions_todo set state='open' \
320 from ir_model_data as data where data.res_id = ir_actions_todo.id \
321 and ir_actions_todo.type='special'\
322 and data.model = 'ir.actions.todo' and data.module=%s", (module.name, ))
324 self.pool = pooler.restart_pool(cr.dbname, update_module=True)[1]
329 #Migrate data from another application Conf wiz
331 class migrade_application_installer_modules(osv.osv_memory):
332 _name = 'migrade.application.installer.modules'
333 _inherit = 'res.config.installer'
335 'import_saleforce': fields.boolean('Import Saleforce',
336 help="For Import Saleforce"),
337 'import_sugarcrm': fields.boolean('Import Sugarcrm',
338 help="For Import Sugarcrm"),
339 'sync_google_contact': fields.boolean('Sync Google Contact',
340 help="For Sync Google Contact"),
341 'quickbooks_ippids': fields.boolean('Quickbooks Ippids',
342 help="For Quickbooks Ippids"),
345 class product_installer(osv.osv_memory):
346 _name = 'product.installer'
347 _inherit = 'res.config'
349 'customers': fields.selection([('create','Create'), ('import','Import')], 'Customers', size=32, required=True, help="Import or create customers"),
353 'customers': 'create',
356 def execute(self, cr, uid, ids, context=None):
359 data_obj = self.pool.get('ir.model.data')
360 val = self.browse(cr, uid, ids, context=context)[0]
361 if val.customers == 'create':
362 id2 = data_obj._get_id(cr, uid, 'base', 'view_partner_form')
364 id2 = data_obj.browse(cr, uid, id2, context=context).res_id
368 'res_model': 'res.partner',
369 'views': [(id2, 'form')],
370 'type': 'ir.actions.act_window',
374 if val.customers == 'import':
375 return {'type': 'ir.actions.act_window'}
377 # Define users preferences for new users (ir.values)
379 def _lang_get(self, cr, uid, context=None):
380 obj = self.pool.get('res.lang')
381 ids = obj.search(cr, uid, [('translatable','=',True)])
382 res = obj.read(cr, uid, ids, ['code', 'name'], context=context)
383 res = [(r['code'], r['name']) for r in res]
386 def _tz_get(self,cr,uid, context=None):
387 return [(x, x) for x in pytz.all_timezones]
389 class user_preferences_config(osv.osv_memory):
390 _name = 'user.preferences.config'
391 _inherit = 'res.config'
393 'context_tz': fields.selection(_tz_get, 'Timezone', size=64,
394 help="Set default for new user's timezone, used to perform timezone conversions "
395 "between the server and the client."),
396 'context_lang': fields.selection(_lang_get, 'Language', required=True,
397 help="Sets default language for the all user interface, when UI "
398 "translations are available. If you want to Add new Language, you can add it from 'Load an Official Translation' wizard from 'Administration' menu."),
399 'view': fields.selection([('simple','Simplified'),
400 ('extended','Extended')],
401 'Interface', required=True, help= "If you use OpenERP for the first time we strongly advise you to select the simplified interface, which has less features but is easier. You can always switch later from the user preferences." ),
402 'menu_tips': fields.boolean('Display Tips', help="Check out this box if you want to always display tips on each menu action"),
406 'view' : lambda self,cr,uid,*args: self.pool.get('res.users').browse(cr, uid, uid).view or 'simple',
407 'context_lang' : 'en_US',
411 def default_get(self, cr, uid, fields, context=None):
414 res = super(user_preferences_config, self).default_get(cr, uid, fields, context=context)
415 res_default = self.pool.get('ir.values').get(cr, uid, 'default', False, ['res.users'])
416 for id, field, value in res_default:
417 res.update({field: value})
420 def execute(self, cr, uid, ids, context=None):
421 user_obj = self.pool.get('res.users')
422 user_ids = user_obj.search(cr, uid, [], context=context)
423 for o in self.browse(cr, uid, ids, context=context):
424 user_obj.write(cr , uid, user_ids ,{'context_tz' : o.context_tz, 'context_lang' : o.context_lang, 'view' : o.view, 'menu_tips' : o.menu_tips}, context=context)
425 ir_values_obj = self.pool.get('ir.values')
426 ir_values_obj.set(cr, uid, 'default', False, 'context_tz', ['res.users'], o.context_tz)
427 ir_values_obj.set(cr, uid, 'default', False, 'context_lang', ['res.users'], o.context_lang)
428 ir_values_obj.set(cr, uid, 'default', False, 'view', ['res.users'], o.view)
429 ir_values_obj.set(cr, uid, 'default', False, 'menu_tips', ['res.users'], o.menu_tips)
432 # Specify Your Terminology
434 class specify_partner_terminology(osv.osv_memory):
435 _name = 'base.setup.terminology'
436 _inherit = 'res.config'
438 'partner': fields.selection([('Customer','Customer'),
441 ('Patient','Patient'),
442 ('Partner','Partner'),
447 'Choose how to call a Customer', required=True ),
450 'partner' :'Partner',
453 def make_translations(self, cr, uid, ids, name, type, src, value, res_id=0, context=None):
454 trans_obj = self.pool.get('ir.translation')
455 user_obj = self.pool.get('res.users')
456 context_lang = user_obj.browse(cr, uid, uid, context=context).context_lang
457 existing_trans_ids = trans_obj.search(cr, uid, [('name','=',name), ('lang','=',context_lang), ('type','=',type), ('src','=',src), ('res_id','=',res_id)])
458 if existing_trans_ids:
459 trans_obj.write(cr, uid, existing_trans_ids, {'value': value}, context=context)
461 create_id = trans_obj.create(cr, uid, {'name': name,'lang': context_lang, 'type': type, 'src': src, 'value': value , 'res_id': res_id}, context=context)
464 def execute(self, cr, uid, ids, context=None):
465 def _case_insensitive_replace(ref_string, src, value):
467 pattern = re.compile(src, re.IGNORECASE)
468 return pattern.sub(_(value), _(ref_string))
469 trans_obj = self.pool.get('ir.translation')
470 fields_obj = self.pool.get('ir.model.fields')
471 menu_obj = self.pool.get('ir.ui.menu')
472 act_window_obj = self.pool.get('ir.actions.act_window')
473 for o in self.browse(cr, uid, ids, context=context):
474 #translate label of field
475 field_ids = fields_obj.search(cr, uid, [('field_description','ilike','Customer')])
476 for f_id in fields_obj.browse(cr ,uid, field_ids, context=context):
477 field_ref = f_id.model_id.model + ',' + f_id.name
478 self.make_translations(cr, uid, ids, field_ref, 'field', f_id.field_description, _case_insensitive_replace(f_id.field_description,'Customer',o.partner), context=context)
479 #translate help tooltip of field
480 for obj in self.pool.obj_pool.values():
481 for field_name, field_rec in obj._columns.items():
482 if field_rec.help.lower().count('customer'):
483 field_ref = obj._name + ',' + field_name
484 self.make_translations(cr, uid, ids, field_ref, 'help', field_rec.help, _case_insensitive_replace(field_rec.help,'Customer',o.partner), context=context)
486 menu_ids = menu_obj.search(cr,uid, [('name','ilike','Customer')])
487 for m_id in menu_obj.browse(cr, uid, menu_ids, context=context):
488 menu_name = m_id.name
489 menu_ref = 'ir.ui.menu' + ',' + 'name'
490 self.make_translations(cr, uid, ids, menu_ref, 'model', menu_name, _case_insensitive_replace(menu_name,'Customer',o.partner), res_id=m_id.id, context=context)
491 #translate act window name
492 act_window_ids = act_window_obj.search(cr, uid, [('name','ilike','Customer')])
493 for act_id in act_window_obj.browse(cr ,uid, act_window_ids, context=context):
494 act_ref = 'ir.actions.act_window' + ',' + 'name'
495 self.make_translations(cr, uid, ids, act_ref, 'model', act_id.name, _case_insensitive_replace(act_id.name,'Customer',o.partner), res_id=act_id.id, context=context)
496 #translate act window tooltips
497 act_window_ids = act_window_obj.search(cr, uid, [('help','ilike','Customer')])
498 for act_id in act_window_obj.browse(cr ,uid, act_window_ids, context=context):
499 act_ref = 'ir.actions.act_window' + ',' + 'help'
500 self.make_translations(cr, uid, ids, act_ref, 'model', act_id.help, _case_insensitive_replace(act_id.help,'Customer',o.partner), res_id=act_id.id, context=context)
503 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: