Merge lp:~openerp-dev/openobject-addons/trunk-kanban-column-rga into lp:openobject-addons

Proposed by Vidhin Mehta (OpenERP)
Status: Work in progress
Proposed branch: lp:~openerp-dev/openobject-addons/trunk-kanban-column-rga
Merge into: lp:openobject-addons
Diff against target: 673 lines (+309/-95)
10 files modified
crm/crm.py (+50/-0)
crm/crm_case_section_view.xml (+1/-0)
hr/hr_view.xml (+2/-0)
hr_recruitment/hr_recruitment.py (+107/-37)
hr_recruitment/hr_recruitment_demo.xml (+30/-1)
hr_recruitment/hr_recruitment_menu.xml (+25/-20)
hr_recruitment/hr_recruitment_view.xml (+33/-33)
project/project.py (+57/-2)
project/project_view.xml (+1/-0)
project/security/ir.model.access.csv (+3/-2)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/trunk-kanban-column-rga
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+190307@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

8877. By Mahendra Barad(OpenERP)

[REV] revert the changes for global method

8876. By Mahendra Barad(OpenERP)

[Merge] merge with trunk

8875. By Mahendra Barad(OpenERP)

Merge with trunk

8874. By RGA(OpenERP)

[IMP] add context stage_m2m_field so we can link group with this field instead of add new group

8873. By RGA(OpenERP)

[IMP] hr_recruitment view add Application button on job position form view

8872. By RGA(OpenERP)

Merge with trunk

8871. By Mahendra Barad(OpenERP)

merge with trunk

8870. By Mahendra Barad(OpenERP)

[IMP]solve the deletion problem for stages

8869. By RGA(OpenERP)

Merge with lp:~openerp-dev/openobject-addons/trunk-kanban-column-exp-rga which add comman base stage

8868. By RGA(OpenERP)

Merge with trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'crm/crm.py'
2--- crm/crm.py 2013-10-06 11:58:08 +0000
3+++ crm/crm.py 2013-10-10 08:36:19 +0000
4@@ -85,7 +85,57 @@
5 'type': 'both',
6 'case_default': True,
7 }
8+ def create(self, cr, uid, value, context=None):
9+ if context is None: context = {}
10+ stage_id = self.search(cr, uid, [('name','=', value.get('name'))], context=context, limit=1)
11+ section_id = context.get('default_section_id', False)
12+ if section_id and stage_id:
13+ return self._stage_modify(cr, uid, stage_id[0], section_id, value, context=context)
14+ create_return = super(crm_case_stage, self).create(cr, uid, value, context=context)
15+ if section_id:
16+ self.pool.get('crm.case.section').write(cr ,uid, section_id, {'stage_ids': [(4, create_return)]}, context=context)
17+ return create_return
18+
19+ def _stage_modify(self, cr, uid, stage_id, section_id, value, context=None):
20+ crm_lead = self.pool.get('crm.lead')
21+ section_browse = self.pool.get('crm.case.section').browse(cr, uid, section_id, context=context)
22+ crm_lead_ids = crm_lead.search(cr, uid, [('stage_id','=', stage_id),('section_id','=', section_id)], context=context)
23+ stage_ids = self.search(cr, uid, [('name','=', value.get('name'))], context=context, limit=1)
24+ if not stage_ids:
25+ value['state'] = self.browse(cr, uid, stage_id, context=context).name
26+ value['section_ids'] = [(6, 0, [section_id])]
27+ new_stage_id = self.copy(cr, uid, stage_id, default=value, context=context)
28+ else:
29+ new_stage_id = stage_ids[0]
30+
31+ section_write = section_browse.write({'stage_ids': [(3, stage_id),(4, new_stage_id)]}, context=context)
32+ crm_write = crm_lead.write(cr, uid, crm_lead_ids, {'stage_id': new_stage_id} , context=context)
33+ if section_write and crm_write:
34+ return new_stage_id
35+ return False
36
37+ def write(self, cr, uid, ids, value, context=None):
38+ if context is None: context = {}
39+ section_id = context.get('default_section_id', False)
40+ if value.get('name') and section_id:
41+ for stage_id in ids:
42+ return self._stage_modify(cr, uid, stage_id, section_id, value, context=context)
43+ return True
44+ return super(crm_case_stage, self).write(cr, uid, ids, value, context=context)
45+
46+ def unlink(self, cr, uid, ids, context=None):
47+ if context is None: context = {}
48+ section_id = context.get('default_section_id', False)
49+ if section_id:
50+ crm_lead = self.pool.get('crm.lead')
51+ for stage_id in ids:
52+ crm_lead_ids = crm_lead.search(cr, uid, [('stage_id','=',stage_id),('section_id','=', section_id)])
53+ crm_write = crm_lead.write(cr, uid, crm_lead_ids, {'stage_id': False} , context=context)
54+ section_write = self.pool.get('crm.case.section').write(cr, uid, section_id, {'stage_ids': [(3, stage_id)]}, context=context)
55+ if not crm_write or not section_write:
56+ return False
57+ return True
58+ return super(crm_case_stage,self).unlink(cr, uid, ids, context)
59
60 class crm_case_section(osv.osv):
61 """ Model for sales teams. """
62
63=== modified file 'crm/crm_case_section_view.xml'
64--- crm/crm_case_section_view.xml 2013-09-13 08:42:35 +0000
65+++ crm/crm_case_section_view.xml 2013-10-10 08:36:19 +0000
66@@ -48,6 +48,7 @@
67 'stage_type': 'opportunity',
68 'default_type': 'opportunity',
69 'default_user_id': uid,
70+ 'stage_m2m_field':'stage_ids',
71 }
72 </field>
73 <field name="help" type="html">
74
75=== modified file 'hr/hr_view.xml'
76--- hr/hr_view.xml 2013-10-06 13:12:25 +0000
77+++ hr/hr_view.xml 2013-10-10 08:36:19 +0000
78@@ -336,6 +336,8 @@
79 <field name="state" widget="statusbar" statusbar_visible="recruit,open"/>
80 </header>
81 <sheet>
82+ <div name="hr_applicant_button" class="oe_right oe_button_box">
83+ </div>
84 <div class="oe_title">
85 <label for="name" class="oe_edit_only"/>
86 <h1><field name="name" class="oe_inline"/></h1>
87
88=== modified file 'hr_recruitment/hr_recruitment.py'
89--- hr_recruitment/hr_recruitment.py 2013-09-19 14:23:38 +0000
90+++ hr_recruitment/hr_recruitment.py 2013-10-10 08:36:19 +0000
91@@ -51,14 +51,79 @@
92 _columns = {
93 'name': fields.char('Name', size=64, required=True, translate=True),
94 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of stages."),
95- 'department_id':fields.many2one('hr.department', 'Specific to a Department', help="Stages of the recruitment process may be different per department. If this stage is common to all departments, keep this field empty."),
96 'fold': fields.boolean('Hide in views if empty', help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
97 'requirements': fields.text('Requirements'),
98+ 'case_default': fields.boolean('Default to New Job'),
99+ 'job_ids': fields.many2many('hr.job', 'job_stage_rel', 'stage_id','job_id', 'Stages')
100 }
101+
102+ def _get_default_job_id(self, cr, uid, ctx={}):
103+ job = ctx.get('default_job_id', False)
104+ if type(job) is int:
105+ return [job]
106+ return job
107+
108 _defaults = {
109 'sequence': 1,
110 'fold': False,
111+ 'job_ids': _get_default_job_id,
112+ 'case_default': True
113 }
114+
115+ def _stage_modify(self, cr, uid, stage_id, job_id, vals, context=None):
116+ hr_applicant = self.pool.get('hr.applicant')
117+ hr_job = self.pool.get('hr.job').browse(cr, uid, job_id, context=context)
118+ hr_applicant_ids = hr_applicant.search(cr, uid, [('stage_id','=', stage_id),('job_id','=', job_id)], context=context)
119+ stage_ids = self.search(cr, uid, [('name','=', vals['name'])], context=context)
120+ if not stage_ids:
121+ vals['job_ids'] = [(6, 0, [job_id])]
122+ new_stage_id = self.copy(cr, uid, stage_id, default=vals, context=context)
123+ else:
124+ new_stage_id = stage_ids[0]
125+
126+ hr_job_write = hr_job.write({'stage_ids': [(4, new_stage_id),(3, stage_id)]}, context=context)
127+ hr_applicant_write = hr_applicant.write(cr, uid, hr_applicant_ids, {'stage_id': new_stage_id} , context=context)
128+ if hr_job_write and hr_applicant_write:
129+ return new_stage_id
130+ return False
131+
132+ def create(self, cr, uid, vals, context=None):
133+ if context is None:
134+ context = {}
135+ stage_ids = self.search(cr, uid, [('name','=', vals.get('name'))], context=context, limit=1)
136+ job_id = context.get('default_job_id')
137+ if job_id and stage_ids:
138+ return self._stage_modify(cr, uid, stage_ids[0], job_id, vals, context=context)
139+ create_return = super(hr_recruitment_stage, self).create(cr, uid, vals, context=context)
140+ if job_id:
141+ self.pool.get('hr.job').write(cr, uid, job_id, {'stage_ids': [(4, create_return)]}, context=context)
142+ return create_return
143+
144+ def write(self, cr, uid, ids, vals, context=None):
145+ if context is None:
146+ context = {}
147+ job_id = context.get('default_job_id')
148+ if vals.get('name') and job_id:
149+ for stage_id in ids:
150+ return self._stage_modify(cr, uid, stage_id, job_id, vals, context=context)
151+ return True
152+ return super(hr_recruitment_stage, self).write(cr, uid, ids, vals, context=context)
153+
154+ def unlink(self, cr, uid, ids, context=None):
155+ if context is None:
156+ context = {}
157+ job_id = context.get('default_job_id', False)
158+ if job_id:
159+ hr_application = self.pool.get('hr.applicant')
160+ for stage_id in ids:
161+ applicant_ids = hr_application.search(cr, uid, [('stage_id','=',stage_id),('job_id','=',job_id)])
162+ hr_app_write = hr_application.write(cr, uid, applicant_ids, {'stage_id': False} , context=context)
163+ hr_job_write = self.pool.get('hr.job').write(cr, uid, job_id, {'stage_ids': [(3, stage_id)]}, context=context)
164+ if not hr_app_write or not hr_job_write:
165+ return False
166+ return True
167+ return super(hr_recruitment_stage,self).unlink(cr, uid, ids, context)
168+
169
170 class hr_recruitment_degree(osv.osv):
171 """ Degree of HR Recruitment """
172@@ -87,29 +152,29 @@
173 },
174 }
175
176- def _get_default_department_id(self, cr, uid, context=None):
177+ def _get_default_job_id(self, cr, uid, context=None):
178 """ Gives default department by checking if present in the context """
179- return (self._resolve_department_id_from_context(cr, uid, context=context) or False)
180-
181+ return (self._resolve_job_id_from_context(cr, uid, context=context) or False)
182+
183 def _get_default_stage_id(self, cr, uid, context=None):
184 """ Gives default stage_id """
185- department_id = self._get_default_department_id(cr, uid, context=context)
186+ department_id = self._get_default_job_id(cr, uid, context=context)
187 return self.stage_find(cr, uid, [], department_id, [('sequence', '=', '1')], context=context)
188
189- def _resolve_department_id_from_context(self, cr, uid, context=None):
190- """ Returns ID of department based on the value of 'default_department_id'
191- context key, or None if it cannot be resolved to a single
192+ def _resolve_job_id_from_context(self, cr, uid, context=None):
193+ """ Returns ID of job based on the value of 'default_job_id'
194+ context key, or None if it cannot be resolved to a single
195 department.
196 """
197 if context is None:
198 context = {}
199- if type(context.get('default_department_id')) in (int, long):
200- return context.get('default_department_id')
201- if isinstance(context.get('default_department_id'), basestring):
202- department_name = context['default_department_id']
203- department_ids = self.pool.get('hr.department').name_search(cr, uid, name=department_name, context=context)
204- if len(department_ids) == 1:
205- return int(department_ids[0][0])
206+ if type(context.get('default_job_id')) in (int, long):
207+ return context.get('default_job_id')
208+ if isinstance(context.get('default_job_id'), basestring):
209+ job_name = context['default_job_id']
210+ job_ids = self.pool.get('hr.job').name_search(cr, uid, name=job_name, context=context)
211+ if len(job_ids) == 1:
212+ return int(job_ids[0][0])
213 return None
214
215 def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
216@@ -121,13 +186,14 @@
217 order = "%s desc" % order
218 # retrieve section_id from the context and write the domain
219 # - ('id', 'in', 'ids'): add columns that should be present
220- # - OR ('department_id', '=', False), ('fold', '=', False): add default columns that are not folded
221- # - OR ('department_id', 'in', department_id), ('fold', '=', False) if department_id: add department columns that are not folded
222- department_id = self._resolve_department_id_from_context(cr, uid, context=context)
223+ # - OR ('job_id', '=', False), ('fold', '=', False): add default columns that are not folded
224+ # - OR ('job_id', 'in', job_id), ('fold', '=', False) if job_id: add department columns that are not folded
225+ job_id = self._resolve_job_id_from_context(cr, uid, context=context)
226 search_domain = []
227- if department_id:
228- search_domain += ['|', ('department_id', '=', department_id)]
229- search_domain += ['|', ('id', 'in', ids), ('department_id', '=', False)]
230+ if job_id:
231+ search_domain += ['|', ('job_ids', '=', job_id)]
232+ search_domain += [('id', 'in', ids)]
233+ search_domain += ['|', '|', ('id', 'in', ids), ('job_ids', '=', False), ('case_default', '=', True)]
234 stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
235 result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
236 # restore order of the search
237@@ -181,7 +247,7 @@
238 'create_date': fields.datetime('Creation Date', readonly=True, select=True),
239 'write_date': fields.datetime('Update Date', readonly=True),
240 'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage', track_visibility='onchange',
241- domain="['|', ('department_id', '=', department_id), ('department_id', '=', False)]"),
242+ domain="[('job_ids', '=', job_id)]"),
243 'last_stage_id': fields.many2one('hr.recruitment.stage', 'Last Stage',
244 help='Stage of the applicant before being in the current stage. Used for lost cases analysis.'),
245 'categ_ids': fields.many2many('hr.applicant_category', string='Tags'),
246@@ -222,7 +288,7 @@
247 'active': lambda *a: 1,
248 'user_id': lambda s, cr, uid, c: uid,
249 'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
250- 'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c),
251+ 'job_id': lambda s, cr, uid, c: s._get_default_job_id(cr, uid, c),
252 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'hr.applicant', context=c),
253 'color': 0,
254 'date_last_stage_update': fields.datetime.now,
255@@ -239,11 +305,6 @@
256 return {'value': {'department_id': job_record.department_id.id}}
257 return {}
258
259- def onchange_department_id(self, cr, uid, ids, department_id=False, stage_id=False, context=None):
260- if not stage_id:
261- stage_id = self.stage_find(cr, uid, [], department_id, [('sequence', '=', '1')], context=context)
262- return {'value': {'stage_id': stage_id}}
263-
264 def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):
265 data = {'partner_phone': False,
266 'partner_mobile': False,
267@@ -264,17 +325,16 @@
268 if isinstance(cases, (int, long)):
269 cases = self.browse(cr, uid, cases, context=context)
270 # collect all section_ids
271- department_ids = []
272+ job_ids = []
273 if section_id:
274- department_ids.append(section_id)
275+ job_ids.append(section_id)
276 for case in cases:
277- if case.department_id:
278- department_ids.append(case.department_id.id)
279+ if case.job_id:
280+ job_ids.append(case.job_id.id)
281 # OR all section_ids and OR with case_default
282 search_domain = []
283- if department_ids:
284- search_domain += ['|', ('department_id', 'in', department_ids)]
285- search_domain.append(('department_id', '=', False))
286+ if job_ids:
287+ search_domain += ['|', ('job_ids', 'in', job_ids)]
288 # AND with the domain in parameter
289 search_domain += list(domain)
290 # perform search, return the first found
291@@ -466,8 +526,18 @@
292 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="restrict", required=True,
293 help="Email alias for this job position. New emails will automatically "
294 "create new applicants for this job position."),
295- }
296-
297+ 'stage_ids':fields.many2many('hr.recruitment.stage', 'job_stage_rel','job_id', 'stage_id', 'Stages')
298+ }
299+
300+
301+ def _get_stage_common(self, cr, uid, context):
302+ ids = self.pool.get('hr.recruitment.stage').search(cr, uid, [('case_default','=',1)], context=context)
303+ return ids
304+
305+ _defaults = {
306+ 'alias_domain': False, # always hide alias during creation
307+ 'stage_ids': _get_stage_common,
308+ }
309 def _auto_init(self, cr, context=None):
310 """Installation hook to create aliases for all jobs and avoid constraint errors."""
311 return self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job, self)._auto_init,
312
313=== modified file 'hr_recruitment/hr_recruitment_demo.xml'
314--- hr_recruitment/hr_recruitment_demo.xml 2013-03-13 09:37:09 +0000
315+++ hr_recruitment/hr_recruitment_demo.xml 2013-10-10 08:36:19 +0000
316@@ -124,6 +124,35 @@
317
318 <record id="hr.job_developer" model="hr.job">
319 <field name="survey_id" ref="survey_job_0"/>
320- </record>
321+ <field name= "stage_ids" eval="[(4, stage_job1),(4, stage_job2),(4, stage_job3),(4, stage_job4),(4, stage_job5),(4, stage_job6)]" />
322+ </record>
323+ <record id="hr.job_ceo" model="hr.job">
324+ <field name="survey_id" ref="survey_job_0"/>
325+ <field name= "stage_ids" eval="[(4, stage_job3),(4, stage_job4),(4, stage_job5),(4, stage_job6)]" />
326+ </record>
327+ <record id="hr.job_cto" model="hr.job">
328+ <field name="survey_id" ref="survey_job_0"/>
329+ <field name= "stage_ids" eval="[(4, stage_job1),(4, stage_job4),(4, stage_job5),(4, stage_job6)]" />
330+ </record>
331+ <record id="hr.job_hrm" model="hr.job">
332+ <field name="survey_id" ref="survey_job_0"/>
333+ <field name= "stage_ids" eval="[(4, stage_job1),(4, stage_job2),(4, stage_job3),(4, stage_job4)]" />
334+ </record>
335+ <record id="hr.job_consultant" model="hr.job">
336+ <field name="survey_id" ref="survey_job_0"/>
337+ <field name= "stage_ids" eval="[(4, stage_job1),(4, stage_job2),(4, stage_job3),(4, stage_job4)]" />
338+ </record>
339+
340+ <record id="hr.job_marketing" model="hr.job">
341+ <field name="survey_id" ref="survey_job_0"/>
342+ <field name= "stage_ids" eval="[(4, stage_job1),(4, stage_job2),(4, stage_job3),(4, stage_job4)]" />
343+ </record>
344+
345+ <record id="hr.job_trainee" model="hr.job">
346+ <field name="survey_id" ref="survey_job_0"/>
347+ <field name= "stage_ids" eval="[(4, stage_job1),(4, stage_job2),(4, stage_job3),(4, stage_job4)]" />
348+ </record>
349+
350+
351 </data>
352 </openerp>
353\ No newline at end of file
354
355=== modified file 'hr_recruitment/hr_recruitment_menu.xml'
356--- hr_recruitment/hr_recruitment_menu.xml 2013-03-04 15:13:55 +0000
357+++ hr_recruitment/hr_recruitment_menu.xml 2013-10-10 08:36:19 +0000
358@@ -1,26 +1,6 @@
359 <?xml version="1.0"?>
360 <openerp>
361 <data>
362-
363- ######################## JOB OPPORTUNITIES (menu) ###########################
364- <record model="ir.actions.act_window" id="crm_case_categ0_act_job">
365- <field name="name">Applications</field>
366- <field name="res_model">hr.applicant</field>
367- <field name="view_mode">kanban,tree,form,graph,calendar</field>
368- <field name="view_id" eval="False"/>
369- <field name="search_view_id" ref="view_crm_case_jobs_filter"/>
370- <field name="help" type="html">
371- <p>
372- OpenERP helps you track applicants in the recruitment
373- process and follow up all operations: meetings, interviews, etc.
374- </p><p>
375- Applicants and their attached CV are created automatically when an email is sent.
376- If you install the document management modules, all resumes are indexed automatically,
377- so that you can easily search through their content.
378- </p>
379- </field>
380- </record>
381-
382 <record model="ir.actions.act_window.view" id="action_hr_sec_kanban_view_act_job">
383 <field name="sequence" eval="0"/>
384 <field name="view_mode">kanban</field>
385@@ -64,6 +44,31 @@
386
387 <menuitem parent="hr.menu_hr_configuration" id="hr.menu_hr_job" action="hr.action_hr_job" sequence="2"/>
388
389+ <menuitem name="Recruitment"
390+ id="menu_hr_recruitment_recruitment"
391+ parent="hr.menu_hr_configuration"
392+ sequence="40"/>
393+
394+ <menuitem
395+ id="menu_hr_recruitment_stage"
396+ name="Stages"
397+ parent="menu_hr_recruitment_recruitment"
398+ action="hr_recruitment_stage_act"
399+ sequence="1" groups="base.group_no_one"/>
400+
401+ <menuitem
402+ id="menu_hr_recruitment_degree"
403+ name="Degrees"
404+ parent="menu_hr_recruitment_recruitment"
405+ action="hr_recruitment_degree_action"
406+ sequence="5" groups="base.group_no_one"/>
407+
408+ <menuitem
409+ id="menu_hr_recruitment_source"
410+ parent="menu_hr_recruitment_recruitment"
411+ action="hr_recruitment_source_action"
412+ groups="base.group_no_one"
413+ sequence="10"/>
414
415 </data>
416 </openerp>
417
418=== modified file 'hr_recruitment/hr_recruitment_view.xml'
419--- hr_recruitment/hr_recruitment_view.xml 2013-09-04 14:11:22 +0000
420+++ hr_recruitment/hr_recruitment_view.xml 2013-10-10 08:36:19 +0000
421@@ -2,11 +2,6 @@
422 <openerp>
423 <data>
424
425- <menuitem name="Recruitment"
426- id="menu_hr_recruitment_recruitment"
427- parent="hr.menu_hr_configuration"
428- sequence="40"/>
429-
430 <act_window
431 id="act_hr_applicant_to_meeting"
432 name="Meetings"
433@@ -32,8 +27,7 @@
434 </p>
435 </field>
436 </record>
437-
438-
439+
440 <!-- Jobs -->
441 <record model="ir.ui.view" id="crm_case_tree_view_job">
442 <field name="name">Applicants</field>
443@@ -120,7 +114,7 @@
444 <field name="survey" invisible="1"/>
445 <field name="response" invisible="1"/>
446 <field name="job_id" on_change="onchange_job(job_id)"/>
447- <field name="department_id" on_change="onchange_department_id(department_id, stage_id)"/>
448+ <field name="department_id"/>
449 <label for="availability"/>
450 <div>
451 <field name="availability" class="oe_inline"/> <label string="Day(s)" class="oe_inline"/>
452@@ -204,6 +198,25 @@
453 </search>
454 </field>
455 </record>
456+
457+ <!-- Applications Action-->
458+ <record model="ir.actions.act_window" id="crm_case_categ0_act_job">
459+ <field name="name">Applications</field>
460+ <field name="res_model">hr.applicant</field>
461+ <field name="view_mode">kanban,tree,form,graph,calendar</field>
462+ <field name="view_id" eval="False"/>
463+ <field name="search_view_id" ref="view_crm_case_jobs_filter"/>
464+ <field name="help" type="html">
465+ <p>
466+ OpenERP helps you track applicants in the recruitment
467+ process and follow up all operations: meetings, interviews, etc.
468+ </p><p>
469+ Applicants and their attached CV are created automatically when an email is sent.
470+ If you install the document management modules, all resumes are indexed automatically,
471+ so that you can easily search through their content.
472+ </p>
473+ </field>
474+ </record>
475
476 <!-- CRM Lead Calendar View -->
477 <record model="ir.ui.view" id="hr_applicant_calendar_view">
478@@ -330,6 +343,14 @@
479 <field name="alias_contact" class="oe_inline" string="Accept Emails From"/>
480 </group>
481 </xpath>
482+ <xpath expr="//div[@name='hr_applicant_button']" position="inside">
483+ <button name="%(crm_case_categ0_act_job)d" string="Applications" type="action"
484+ context="{'search_default_job_id': active_id, 'default_job_id': active_id, 'stage_m2m_field':'stage_ids'}"/>
485+ </xpath>
486+ <xpath expr="//field[@name='requirements']" position="after">
487+ <separator string="Recruitment Stages" />
488+ <field name="stage_ids" nolabel="1"/>
489+ </xpath>
490 </field>
491 </record>
492
493@@ -341,7 +362,6 @@
494 <tree string="Stages">
495 <field name="sequence" invisible="1"/>
496 <field name="name"/>
497- <field name="department_id"/>
498 </tree>
499 </field>
500 </record>
501@@ -356,15 +376,16 @@
502 <group string="Stage Definition">
503 <group>
504 <field name="name"/>
505- <field name="department_id"/>
506+ <field name="fold"/>
507+ <field name="case_default"/>
508 </group>
509 <group>
510 <field name="sequence"/>
511- <field name="fold"/>
512 </group>
513 </group>
514 <separator string="Requirements"/>
515 <field name="requirements"/>
516+ <field name="job_ids" invisible="1"/>
517 </sheet>
518 </form>
519 </field>
520@@ -385,14 +406,7 @@
521 </p>
522 </field>
523 </record>
524-
525- <menuitem
526- id="menu_hr_recruitment_stage"
527- name="Stages"
528- parent="menu_hr_recruitment_recruitment"
529- action="hr_recruitment_stage_act"
530- sequence="1" groups="base.group_no_one"/>
531-
532+
533 <!-- Degree Tree View -->
534 <record model="ir.ui.view" id="hr_recruitment_degree_tree">
535 <field name="name">hr.recruitment.degree.tree</field>
536@@ -429,13 +443,6 @@
537 <field name="view_id" ref="hr_recruitment_degree_tree"/>
538 </record>
539
540- <menuitem
541- id="menu_hr_recruitment_degree"
542- name="Degrees"
543- parent="menu_hr_recruitment_recruitment"
544- action="hr_recruitment_degree_action"
545- sequence="5" groups="base.group_no_one"/>
546-
547 <!-- Source Tree View -->
548 <record model="ir.ui.view" id="hr_recruitment_source_tree">
549 <field name="name">hr.recruitment.source.tree</field>
550@@ -465,12 +472,5 @@
551 <field name="view_type">form</field>
552 </record>
553
554- <menuitem
555- id="menu_hr_recruitment_source"
556- parent="menu_hr_recruitment_recruitment"
557- action="hr_recruitment_source_action"
558- groups="base.group_no_one"
559- sequence="10"/>
560-
561 </data>
562 </openerp>
563
564=== modified file 'project/project.py'
565--- project/project.py 2013-09-19 14:23:38 +0000
566+++ project/project.py 2013-10-10 08:36:19 +0000
567@@ -44,14 +44,69 @@
568 'fold': fields.boolean('Folded by Default',
569 help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
570 }
571-
572+
573+ def _get_default_project_id(self, cr, uid, context=None):
574+ project = self.pool['project.task']._get_default_project_id(cr, uid, context=context)
575+ if type(project) in (long, int,):
576+ return [project]
577+ return project
578+
579 _defaults = {
580 'sequence': 1,
581 'fold': False,
582 'case_default': False,
583- 'project_ids': lambda self, cr, uid, ctx=None: self.pool['project.task']._get_default_project_id(cr, uid, context=ctx),
584+ 'project_ids':_get_default_project_id
585 }
586 _order = 'sequence'
587+
588+ def write(self, cr, uid, ids, value, context=None):
589+ if context is None:context = {}
590+ project_id = context.get('default_project_id', False)
591+ if project_id and value.get('name'):
592+ for id in ids:
593+ return self._stage_modify(cr, uid, id, project_id, value, context=context)
594+ return True
595+ return super(project_task_type, self).write(cr, uid, ids, value, context=context)
596+
597+ def _stage_modify(self, cr, uid, stage_id, project_id, vals, context=None):
598+ project = self.pool.get('project.project').browse(cr, uid, project_id, context=context)
599+ project_task = self.pool.get('project.task')
600+ stage_ids = self.search(cr, uid, [('name','=', vals.get('name'))], context=context, limit=1)
601+ task_ids = project_task.search(cr, uid, [('stage_id','=', stage_id),('project_id','=', project_id)], context=context)
602+
603+ if not stage_ids:
604+ vals['project_ids'] = [(6, 0, [project_id])]
605+ new_stage_id = self.copy(cr, uid, stage_id, default=vals, context=context)
606+ else:
607+ new_stage_id = stage_ids[0]
608+
609+ project_write = project.write({'type_ids': [(3, stage_id),(4, new_stage_id),]}, context=context)
610+ task_write = project_task.write(cr, uid, task_ids, {'stage_id': new_stage_id} , context=context)
611+ if project_write and task_write:
612+ return new_stage_id
613+ return False
614+
615+ def create(self, cr, uid, value, context=None):
616+ if context is None:context = {}
617+ stage_id = self.search(cr, uid, [('name','=', value.get('name'))], context=context, limit=1)
618+ project_id = context.get('default_project_id', False)
619+ if project_id and stage_id:
620+ return self._stage_modify(cr, uid, stage_id[0], project_id, value, context=context)
621+ return super(project_task_type, self).create(cr, uid, value, context=context)
622+
623+ def unlink(self, cr, uid, ids, context=None):
624+ if context is None: context = {}
625+ project_id = context.get('default_project_id')
626+ if project_id:
627+ project_task = self.pool.get('project.task')
628+ for stage_id in ids:
629+ task_ids = project_task.search(cr, uid, [('stage_id','=', stage_id),('project_id','=', project_id)])
630+ task_write = project_task.write(cr, uid, task_ids, {'stage_id': False} , context=context)
631+ project_write = self.pool.get('project.project').write(cr, uid, project_id, {'type_ids': [(3, stage_id)]}, context=context)
632+ if not project_write or not task_write:
633+ return False
634+ return True
635+ return super(project_task_type,self).unlink(cr, uid, ids, context)
636
637
638 class project(osv.osv):
639
640=== modified file 'project/project_view.xml'
641--- project/project_view.xml 2013-10-08 13:56:50 +0000
642+++ project/project_view.xml 2013-10-10 08:36:19 +0000
643@@ -52,6 +52,7 @@
644 'search_default_project_id': [active_id],
645 'default_project_id': active_id,
646 'active_test': False,
647+ 'stage_m2m_field':'type_ids'
648 }</field>
649 <field name="search_view_id" ref="view_task_search_form"/>
650 <field name="help" type="html">
651
652=== modified file 'project/security/ir.model.access.csv'
653--- project/security/ir.model.access.csv 2013-09-11 11:07:55 +0000
654+++ project/security/ir.model.access.csv 2013-10-10 08:36:19 +0000
655@@ -3,7 +3,8 @@
656 access_project_project_manager,project.project,model_project_project,project.group_project_manager,1,1,1,1
657 access_account_analytic_account_user,account.analytic.account,analytic.model_account_analytic_account,project.group_project_user,1,0,0,0
658 access_account_analytic_account,account.analytic.account,analytic.model_account_analytic_account,project.group_project_manager,1,1,1,1
659-access_project_task_type_user,project.task.type user,model_project_task_type,project.group_project_user,1,1,1,1
660+access_project_task_type_manager,project.task.type manager,model_project_task_type,project.group_project_manager,1,1,1,1
661+access_project_task_type_user,project.task.type user,model_project_task_type,project.group_project_user,1,0,0,0
662 access_project_task,project.task,model_project_task,project.group_project_user,1,1,1,1
663 access_project_task_work,project.task.work,model_project_task_work,project.group_project_user,1,1,1,1
664 access_report_project_task_user,report.project.task.user,model_report_project_task_user,project.group_project_manager,1,1,1,1
665@@ -11,7 +12,7 @@
666 access_task_on_partner,project.task on partners,model_project_task,base.group_user,1,0,0,0
667 access_project_on_partner,project.project on partners,model_project_project,base.group_user,1,0,0,0
668 access_project_task_sale_user,project.task salesman,model_project_task,base.group_sale_salesman,1,1,1,1
669-access_project_task_type_sale_user,project.task.type salesman,project.model_project_task_type,base.group_sale_salesman,1,1,1,1
670+access_project_task_type_sale_user,project.task.type salesman,project.model_project_task_type,base.group_sale_salesman,1,0,0,0
671 access_project_task_history_sale_user,project.task.history salesman,project.model_project_task_history,base.group_sale_salesman,1,1,1,1
672 access_project_project_sale_user,project.project salesman,model_project_project,base.group_sale_salesman,1,0,0,0
673 access_account_analytic_line_project,account.analytic.line project,analytic.model_account_analytic_line,project.group_project_manager,1,1,1,1

Subscribers

People subscribed via source and target branches

to all changes: