summaryrefslogtreecommitdiff
path: root/addons/hr
diff options
context:
space:
mode:
authorVidhin Mehta <vme@tinyerp.com>2013-08-23 10:36:02 +0530
committerVidhin Mehta <vme@tinyerp.com>2013-08-23 10:36:02 +0530
commit75ddd5ccbec73c4a671b6a74efaa3d41dc2ea2db (patch)
tree50ed3620df15e8533760f5d47e754a1d39c1e856 /addons/hr
parent42f27a15275effd9c43dfe99e32c395ca6b3fd8a (diff)
parenta7f4b6aaa0359d12046e81183417c24f093cd7c3 (diff)
[MERGE]Trunk.
bzr revid: vme@tinyerp.com-20130823050602-33bqv07e7g8dhv7x
Diffstat (limited to 'addons/hr')
-rw-r--r--addons/hr/__init__.py1
-rw-r--r--addons/hr/__openerp__.py4
-rw-r--r--addons/hr/hr.py105
-rw-r--r--addons/hr/hr_demo.xml10
-rw-r--r--addons/hr/hr_view.xml29
-rw-r--r--addons/hr/mail_hr_view.xml19
-rw-r--r--addons/hr/res_users.py65
-rw-r--r--addons/hr/res_users_view.xml20
-rw-r--r--addons/hr/static/description/crm_game_01.png (renamed from addons/hr/html/crm_game_01.png)bin17867 -> 17867 bytes
-rw-r--r--addons/hr/static/description/crm_game_02.png (renamed from addons/hr/html/crm_game_02.png)bin12887 -> 12887 bytes
-rw-r--r--addons/hr/static/description/crm_game_03.png (renamed from addons/hr/html/crm_game_03.png)bin5800 -> 5800 bytes
-rw-r--r--addons/hr/static/description/hr_appraisal.png (renamed from addons/hr/html/hr_appraisal.png)bin43303 -> 43303 bytes
-rw-r--r--addons/hr/static/description/hr_employee.png (renamed from addons/hr/html/hr_employee.png)bin48997 -> 48997 bytes
-rw-r--r--addons/hr/static/description/hr_expense.png (renamed from addons/hr/html/hr_expense.png)bin45187 -> 45187 bytes
-rw-r--r--addons/hr/static/description/hr_illu_01.png (renamed from addons/hr/html/hr_illu_01.png)bin24366 -> 24366 bytes
-rw-r--r--addons/hr/static/description/hr_illu_02.png (renamed from addons/hr/html/hr_illu_02.png)bin22544 -> 22544 bytes
-rw-r--r--addons/hr/static/description/hr_kanban.png (renamed from addons/hr/html/hr_kanban.png)bin113589 -> 113589 bytes
-rw-r--r--addons/hr/static/description/hr_recruitment.png (renamed from addons/hr/html/hr_recruitment.png)bin92899 -> 92899 bytes
-rw-r--r--addons/hr/static/description/hr_social.png (renamed from addons/hr/html/hr_social.png)bin86616 -> 86616 bytes
-rw-r--r--addons/hr/static/description/hr_timesheet.png (renamed from addons/hr/html/hr_timesheet.png)bin61578 -> 61578 bytes
-rw-r--r--addons/hr/static/description/icon.png (renamed from addons/hr/static/src/img/icon.png)bin8676 -> 8676 bytes
-rw-r--r--addons/hr/static/description/index.html (renamed from addons/hr/html/index.html)2
-rw-r--r--addons/hr/static/src/css/hr.css5
-rw-r--r--addons/hr/static/src/js/suggestions.js78
-rw-r--r--addons/hr/static/src/xml/suggestions.xml36
25 files changed, 327 insertions, 47 deletions
diff --git a/addons/hr/__init__.py b/addons/hr/__init__.py
index 02ac7f16fd9..fbd01761f39 100644
--- a/addons/hr/__init__.py
+++ b/addons/hr/__init__.py
@@ -23,5 +23,6 @@ import hr_department
import hr
import res_config
+import res_users
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/hr/__openerp__.py b/addons/hr/__openerp__.py
index b4b8e982845..b074a80aa88 100644
--- a/addons/hr/__openerp__.py
+++ b/addons/hr/__openerp__.py
@@ -59,6 +59,8 @@ You can manage:
'hr_installer.xml',
'hr_data.xml',
'res_config_view.xml',
+ 'mail_hr_view.xml',
+ 'res_users_view.xml',
],
'demo': ['hr_demo.xml'],
'test': [
@@ -69,5 +71,7 @@ You can manage:
'application': True,
'auto_install': False,
'css': [ 'static/src/css/hr.css' ],
+ 'js': [ 'static/src/js/suggestions.js' ],
+ 'qweb': [ 'static/src/xml/suggestions.xml' ],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/hr/hr.py b/addons/hr/hr.py
index 7f704e42e5e..d19f1f7de8b 100644
--- a/addons/hr/hr.py
+++ b/addons/hr/hr.py
@@ -25,9 +25,11 @@ from openerp.modules.module import get_module_resource
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp import tools
+from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
+
class hr_employee_category(osv.osv):
def name_get(self, cr, uid, ids, context=None):
@@ -49,9 +51,9 @@ class hr_employee_category(osv.osv):
_name = "hr.employee.category"
_description = "Employee Category"
_columns = {
- 'name': fields.char("Category", size=64, required=True),
+ 'name': fields.char("Employee Tag", size=64, required=True),
'complete_name': fields.function(_name_get_fnc, type="char", string='Name'),
- 'parent_id': fields.many2one('hr.employee.category', 'Parent Category', select=True),
+ 'parent_id': fields.many2one('hr.employee.category', 'Parent Employee Tag', select=True),
'child_ids': fields.one2many('hr.employee.category', 'parent_id', 'Child Categories'),
'employee_ids': fields.many2many('hr.employee', 'employee_category_rel', 'category_id', 'emp_id', 'Employees'),
}
@@ -127,7 +129,7 @@ class hr_job(osv.osv):
}
_sql_constraints = [
- ('name_company_uniq', 'unique(name, company_id)', 'The name of the job position must be unique per company!'),
+ ('name_company_uniq', 'unique(name, company_id, department_id)', 'The name of the job position must be unique per department in company!'),
]
@@ -150,18 +152,21 @@ class hr_job(osv.osv):
class hr_employee(osv.osv):
_name = "hr.employee"
_description = "Employee"
+ _order = 'name_related'
_inherits = {'resource.resource': "resource_id"}
_inherit = ['mail.thread']
+ _mail_post_access = 'read'
+
def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
for obj in self.browse(cr, uid, ids, context=context):
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
-
+
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
-
+
_columns = {
#we need a related field in order to be able to sort the employee by name
'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
@@ -171,12 +176,12 @@ class hr_employee(osv.osv):
'sinid': fields.char('SIN No', size=32, help="Social Insurance Number"),
'identification_id': fields.char('Identification No', size=32),
'otherid': fields.char('Other Id', size=64),
- 'gender': fields.selection([('male', 'Male'),('female', 'Female')], 'Gender'),
+ 'gender': fields.selection([('male', 'Male'), ('female', 'Female')], 'Gender'),
'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'),
- 'department_id':fields.many2one('hr.department', 'Department'),
+ 'department_id': fields.many2one('hr.department', 'Department'),
'address_id': fields.many2one('res.partner', 'Working Address'),
'address_home_id': fields.many2one('res.partner', 'Home Address'),
- 'bank_account_id':fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
+ 'bank_account_id': fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
'work_phone': fields.char('Work Phone', size=32, readonly=False),
'mobile_phone': fields.char('Work Mobile', size=32, readonly=False),
'work_email': fields.char('Work Email', size=240),
@@ -187,7 +192,7 @@ class hr_employee(osv.osv):
'child_ids': fields.one2many('hr.employee', 'parent_id', 'Subordinates'),
'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True),
'coach_id': fields.many2one('hr.employee', 'Coach'),
- 'job_id': fields.many2one('hr.job', 'Job'),
+ 'job_id': fields.many2one('hr.job', 'Job Title'),
# image: all image fields are base64 encoded and PIL-supported
'image': fields.binary("Photo",
help="This field holds the image used as photo for the employee, limited to 1024x1024px."),
@@ -207,25 +212,42 @@ class hr_employee(osv.osv):
help="Small-sized photo of the employee. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
- 'passport_id':fields.char('Passport No', size=64),
+ 'passport_id': fields.char('Passport No', size=64),
'color': fields.integer('Color Index'),
'city': fields.related('address_id', 'city', type='char', string='City'),
'login': fields.related('user_id', 'login', type='char', string='Login', readonly=1),
'last_login': fields.related('user_id', 'date', type='datetime', string='Latest Connection', readonly=1),
}
- _order='name_related'
+ def _get_default_image(self, cr, uid, context=None):
+ image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
+ return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
+
+ defaults = {
+ 'active': 1,
+ 'image': _get_default_image,
+ 'color': 0,
+ }
def create(self, cr, uid, data, context=None):
- employee_id = super(hr_employee, self).create(cr, uid, data, context=context)
- try:
- (model, mail_group_id) = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'group_all_employees')
- employee = self.browse(cr, uid, employee_id, context=context)
- self.pool.get('mail.group').message_post(cr, uid, [mail_group_id],
- body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
- subtype='mail.mt_comment', context=context)
- except:
- pass # group deleted: do not push a message
+ if context is None:
+ context = {}
+ create_ctx = dict(context, mail_create_nolog=True)
+ employee_id = super(hr_employee, self).create(cr, uid, data, context=create_ctx)
+ employee = self.browse(cr, uid, employee_id, context=context)
+ if employee.user_id:
+ # send a copy to every user of the company
+ company_id = employee.user_id.partner_id.company_id.id
+ partner_ids = self.pool.get('res.partner').search(cr, uid, [
+ ('company_id', '=', company_id),
+ ('user_ids', '!=', False)], context=context)
+ else:
+ partner_ids = []
+ self.message_post(cr, uid, [employee_id],
+ body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
+ partner_ids=partner_ids,
+ subtype='mail.mt_comment', context=context
+ )
return employee_id
def unlink(self, cr, uid, ids, context=None):
@@ -246,7 +268,7 @@ class hr_employee(osv.osv):
company_id = self.pool.get('res.company').browse(cr, uid, company, context=context)
address = self.pool.get('res.partner').address_get(cr, uid, [company_id.partner_id.id], ['default'])
address_id = address and address['default'] or False
- return {'value': {'address_id' : address_id}}
+ return {'value': {'address_id': address_id}}
def onchange_department_id(self, cr, uid, ids, department_id, context=None):
value = {'parent_id': False}
@@ -259,17 +281,36 @@ class hr_employee(osv.osv):
work_email = False
if user_id:
work_email = self.pool.get('res.users').browse(cr, uid, user_id, context=context).email
- return {'value': {'work_email' : work_email}}
-
- def _get_default_image(self, cr, uid, context=None):
- image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
- return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
-
- _defaults = {
- 'active': 1,
- 'image': _get_default_image,
- 'color': 0,
- }
+ return {'value': {'work_email': work_email}}
+
+ def action_follow(self, cr, uid, ids, context=None):
+ """ Wrapper because message_subscribe_users take a user_ids=None
+ that receive the context without the wrapper. """
+ return self.message_subscribe_users(cr, uid, ids, context=context)
+
+ def action_unfollow(self, cr, uid, ids, context=None):
+ """ Wrapper because message_unsubscribe_users take a user_ids=None
+ that receive the context without the wrapper. """
+ return self.message_unsubscribe_users(cr, uid, ids, context=context)
+
+ def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
+ """Show the suggestion of employees if display_employees_suggestions if the
+ user perference allows it. """
+ user = self.pool.get('res.users').browse(cr, uid, uid, context)
+ if not user.display_employees_suggestions:
+ return []
+ else:
+ return super(hr_employee, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)
+
+ def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
+ """ Overwrite of the original method to always follow user_id field,
+ even when not track_visibility so that a user will follow it's employee
+ """
+ user_field_lst = []
+ for name, column_info in self._all_columns.items():
+ if name in auto_follow_fields and name in updated_fields and column_info.column._obj == 'res.users':
+ user_field_lst.append(name)
+ return user_field_lst
def _check_recursion(self, cr, uid, ids, context=None):
level = 100
diff --git a/addons/hr/hr_demo.xml b/addons/hr/hr_demo.xml
index 641d5b272cf..41b09c3aea3 100644
--- a/addons/hr/hr_demo.xml
+++ b/addons/hr/hr_demo.xml
@@ -91,14 +91,14 @@
<!--Employees-->
<record id="employee_fp" model="hr.employee">
- <field name="name">Peter Parker</field>
+ <field name="name">Pieter Parker</field>
<field name="user_id" ref="base.user_root"/>
<field name="department_id" ref="dep_management"/>
<field name="job_id" ref="hr.job_ceo"/>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_2')])]"/>
<field name="work_location">Grand-Rosière</field>
<field name="work_phone">+3281813700</field>
- <field name="work_email">peter@openerp.com</field>
+ <field name="work_email">pieter@openerp.com</field>
<field name="image">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</field>
</record>
@@ -139,7 +139,7 @@
</record>
<record id="employee_stw" model="hr.employee">
- <field name="name">Liam Neeson</field>
+ <field name="name">Liam Nelson</field>
<field name="department_id" ref="dep_rd"/>
<field name="parent_id" ref="employee_al"/>
<field name="job_id" ref="hr.job_developer"/>
@@ -212,7 +212,7 @@
</record>
<record id="employee_ngh" model="hr.employee">
- <field name="name">Famke Janssen</field>
+ <field name="name">Famke Jenssens</field>
<field name="department_id" ref="dep_sales"/>
<field name="parent_id" ref="employee_fp"/>
<field name="job_id" ref="hr.job_marketing"/>
@@ -255,7 +255,7 @@
</record>
<record id="employee_jep" model="hr.employee">
- <field name="name">Jean Pierre</field>
+ <field name="name">Jean-Pierre Carnaud</field>
<field name="department_id" ref="dep_ps"/>
<field name="job_id" ref="hr.job_consultant"/>
<field name="work_location">Grand-Rosière</field>
diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml
index ccd11bc0dc2..05a21c2908a 100644
--- a/addons/hr/hr_view.xml
+++ b/addons/hr/hr_view.xml
@@ -27,6 +27,10 @@
</h1>
<label for="category_ids" class="oe_edit_only" groups="base.group_hr_user"/>
<field name="category_ids" widget="many2many_tags" placeholder="e.g. Part Time" groups="base.group_hr_user"/>
+ <label for="work_email" class="oe_edit_only"/>
+ <field name="work_email" widget="email"/>
+ <label for="work_phone" class="oe_edit_only"/>
+ <field name="work_phone"/>
</div>
<div class="oe_right oe_button_box" name="button_box">
<!-- Put here related buttons -->
@@ -36,8 +40,6 @@
<group>
<group string="Contact Information">
<field name="address_id" on_change="onchange_address_id(address_id)" context="{'show_address': 1}" options='{"always_reload": True, "highlight_first_line": True}'/>
- <field name="work_email" widget="email"/>
- <field name="work_phone"/>
<field name="mobile_phone"/>
<field name="work_location"/>
</group>
@@ -136,6 +138,9 @@
<field name="arch" type="xml">
<kanban>
<field name="last_login"/>
+ <field name="message_is_follower"/>
+ <field name="message_follower_ids"/>
+ <field name="message_ids"/>
<templates>
<t t-name="kanban-box">
<div class="oe_employee_vignette">
@@ -154,10 +159,19 @@
</li>
<li t-if="record.job_id.raw_value"><field name="job_id"/></li>
<li t-if="record.work_location.raw_value"><field name="work_location"/></li>
- <li t-if="record.work_phone.raw_value">Tel: <field name="work_phone"/></li>
- <li t-if="record.mobile_phone.raw_value">Mobile: <field name="mobile_phone"/></li>
<li t-if="record.work_email.raw_value"><a t-attf-href="mailto:#{record.work_email.value}"><field name="work_email"/></a></li>
</ul>
+ <div class="oe_kanban_footer_left">
+ <span title='Messages'><span class='oe_e'>9</span><t t-esc="record.message_ids.raw_value.length"/></span>
+ <span title='Followers'><span class='oe_e'>+</span><t t-esc="record.message_follower_ids.raw_value.length"/></span>
+ </div>
+ <div class="oe_followers" groups="base.group_user">
+ <button t-if="record.message_is_follower.raw_value" name="action_unfollow" type="object" class="oe_follower oe_following">
+ <span class="oe_unfollow">Unfollow</span>
+ <span class="oe_following">Following</span>
+ </button>
+ <button t-if="! record.message_is_follower.raw_value" name="action_follow" type="object" class="oe_follower oe_notfollow">Follow</button>
+ </div>
</div>
</div>
<script>
@@ -334,12 +348,10 @@
<h1><field name="name" class="oe_inline"/></h1>
</div>
<group>
- <group>
+ <group name="job_data">
<field name="no_of_employee" groups="base.group_user"/>
<field name="no_of_recruitment" on_change="on_change_expected_employee(no_of_recruitment,no_of_employee)"/>
<field name="expected_employees" groups="base.group_user"/>
- </group>
- <group>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
<field name="department_id"/>
</group>
@@ -368,10 +380,9 @@
<tree string="Job">
<field name="name"/>
<field name="department_id"/>
- <field name="company_id" groups="base.group_multi_company"/>
- <field name="expected_employees"/>
<field name="no_of_employee"/>
<field name="no_of_recruitment"/>
+ <field name="expected_employees"/>
<field name="state"/>
</tree>
</field>
diff --git a/addons/hr/mail_hr_view.xml b/addons/hr/mail_hr_view.xml
new file mode 100644
index 00000000000..203878c7a77
--- /dev/null
+++ b/addons/hr/mail_hr_view.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="mail.action_mail_inbox_feeds" model="ir.actions.client">
+ <field name="params" eval="&quot;{
+ 'domain': [
+ ('to_read', '=', True),
+ ('starred', '=', False),
+ ],
+ 'view_mailbox': True,
+ 'view_inbox': True,
+ 'read_action': 'read',
+ 'show_compose_message': True
+ }&quot;"/>
+ </record>
+
+ </data>
+</openerp> \ No newline at end of file
diff --git a/addons/hr/res_users.py b/addons/hr/res_users.py
new file mode 100644
index 00000000000..c3550596281
--- /dev/null
+++ b/addons/hr/res_users.py
@@ -0,0 +1,65 @@
+from openerp.osv import fields, osv
+from openerp.tools.translate import _
+
+
+class res_users(osv.Model):
+ """ Update of res.users class
+ - if adding groups to an user, check if base.group_user is in it
+ (member of 'Employee'), create an employee form linked to it.
+ """
+ _name = 'res.users'
+ _inherit = ['res.users']
+
+ _columns = {
+ 'display_employees_suggestions': fields.boolean("Display Employees Suggestions"),
+ }
+
+ _defaults = {
+ 'display_employees_suggestions': True,
+ }
+
+ def __init__(self, pool, cr):
+ """ Override of __init__ to add access rights on
+ display_employees_suggestions fields. Access rights are disabled by
+ default, but allowed on some specific fields defined in
+ self.SELF_{READ/WRITE}ABLE_FIELDS.
+ """
+ init_res = super(res_users, self).__init__(pool, cr)
+ # duplicate list to avoid modifying the original reference
+ self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
+ self.SELF_WRITEABLE_FIELDS.append('display_employees_suggestions')
+ # duplicate list to avoid modifying the original reference
+ self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
+ self.SELF_READABLE_FIELDS.append('display_employees_suggestions')
+ return init_res
+
+ def stop_showing_employees_suggestions(self, cr, uid, user_id, context=None):
+ """Update display_employees_suggestions value to False"""
+ if context is None:
+ context = {}
+ self.write(cr, uid, user_id, {"display_employees_suggestions": False}, context)
+
+ def _create_welcome_message(self, cr, uid, user, context=None):
+ """Do not welcome new users anymore, welcome new employees instead"""
+ return True
+
+ def _message_post_get_eid(self, cr, uid, thread_id, context=None):
+ assert thread_id, "res.users does not support posting global messages"
+ if context and 'thread_model' in context:
+ context['thread_model'] = 'hr.employee'
+ if isinstance(thread_id, (list, tuple)):
+ thread_id = thread_id[0]
+ return self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', thread_id)], context=context)
+
+ def message_post(self, cr, uid, thread_id, context=None, **kwargs):
+ """ Redirect the posting of message on res.users to the related employee.
+ This is done because when giving the context of Chatter on the
+ various mailboxes, we do not have access to the current partner_id. """
+ if kwargs.get('type') == 'email':
+ return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
+ employee_ids = self._message_post_get_eid(cr, uid, thread_id, context=context)
+ if not employee_ids:
+ pass # dpo something
+ for employee_id in employee_ids:
+ res = self.pool.get('hr.employee').message_post(cr, uid, employee_id, context=context, **kwargs)
+ return res
diff --git a/addons/hr/res_users_view.xml b/addons/hr/res_users_view.xml
new file mode 100644
index 00000000000..0843269e716
--- /dev/null
+++ b/addons/hr/res_users_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<openerp>
+ <data>
+
+ <!-- Update user form !-->
+ <record id="view_users_form_mail" model="ir.ui.view">
+ <field name="name">res.users.form.hr</field>
+ <field name="model">res.users</field>
+ <field name="inherit_id" ref="mail.view_users_form_mail"/>
+ <field name="arch" type="xml">
+ <data>
+ <field name="display_groups_suggestions" position="after">
+ <field name="display_employees_suggestions"/>
+ </field>
+ </data>
+ </field>
+ </record>
+
+ </data>
+</openerp>
diff --git a/addons/hr/html/crm_game_01.png b/addons/hr/static/description/crm_game_01.png
index a3cd109c2de..a3cd109c2de 100644
--- a/addons/hr/html/crm_game_01.png
+++ b/addons/hr/static/description/crm_game_01.png
Binary files differ
diff --git a/addons/hr/html/crm_game_02.png b/addons/hr/static/description/crm_game_02.png
index 1a747e1ffe8..1a747e1ffe8 100644
--- a/addons/hr/html/crm_game_02.png
+++ b/addons/hr/static/description/crm_game_02.png
Binary files differ
diff --git a/addons/hr/html/crm_game_03.png b/addons/hr/static/description/crm_game_03.png
index 2fd14886179..2fd14886179 100644
--- a/addons/hr/html/crm_game_03.png
+++ b/addons/hr/static/description/crm_game_03.png
Binary files differ
diff --git a/addons/hr/html/hr_appraisal.png b/addons/hr/static/description/hr_appraisal.png
index f0052bfda61..f0052bfda61 100644
--- a/addons/hr/html/hr_appraisal.png
+++ b/addons/hr/static/description/hr_appraisal.png
Binary files differ
diff --git a/addons/hr/html/hr_employee.png b/addons/hr/static/description/hr_employee.png
index eff8730863f..eff8730863f 100644
--- a/addons/hr/html/hr_employee.png
+++ b/addons/hr/static/description/hr_employee.png
Binary files differ
diff --git a/addons/hr/html/hr_expense.png b/addons/hr/static/description/hr_expense.png
index 7fbc35711e1..7fbc35711e1 100644
--- a/addons/hr/html/hr_expense.png
+++ b/addons/hr/static/description/hr_expense.png
Binary files differ
diff --git a/addons/hr/html/hr_illu_01.png b/addons/hr/static/description/hr_illu_01.png
index ad65bb9b407..ad65bb9b407 100644
--- a/addons/hr/html/hr_illu_01.png
+++ b/addons/hr/static/description/hr_illu_01.png
Binary files differ
diff --git a/addons/hr/html/hr_illu_02.png b/addons/hr/static/description/hr_illu_02.png
index b5416926793..b5416926793 100644
--- a/addons/hr/html/hr_illu_02.png
+++ b/addons/hr/static/description/hr_illu_02.png
Binary files differ
diff --git a/addons/hr/html/hr_kanban.png b/addons/hr/static/description/hr_kanban.png
index c0782d6adca..c0782d6adca 100644
--- a/addons/hr/html/hr_kanban.png
+++ b/addons/hr/static/description/hr_kanban.png
Binary files differ
diff --git a/addons/hr/html/hr_recruitment.png b/addons/hr/static/description/hr_recruitment.png
index 1951b54a6f2..1951b54a6f2 100644
--- a/addons/hr/html/hr_recruitment.png
+++ b/addons/hr/static/description/hr_recruitment.png
Binary files differ
diff --git a/addons/hr/html/hr_social.png b/addons/hr/static/description/hr_social.png
index 215d4e3ba70..215d4e3ba70 100644
--- a/addons/hr/html/hr_social.png
+++ b/addons/hr/static/description/hr_social.png
Binary files differ
diff --git a/addons/hr/html/hr_timesheet.png b/addons/hr/static/description/hr_timesheet.png
index d06c3a924ec..d06c3a924ec 100644
--- a/addons/hr/html/hr_timesheet.png
+++ b/addons/hr/static/description/hr_timesheet.png
Binary files differ
diff --git a/addons/hr/static/src/img/icon.png b/addons/hr/static/description/icon.png
index 742f3e53e67..742f3e53e67 100644
--- a/addons/hr/static/src/img/icon.png
+++ b/addons/hr/static/description/icon.png
Binary files differ
diff --git a/addons/hr/html/index.html b/addons/hr/static/description/index.html
index 0bc3db084a4..f97cb462fe3 100644
--- a/addons/hr/html/index.html
+++ b/addons/hr/static/description/index.html
@@ -17,7 +17,7 @@ Get all your HR operations managed easily: knowledge sharing, recruitments, appr
Each need is provided by a specific app that you activate on demand.
</p>
<div class="oe_centeralign oe_websiteonly">
- <a href="http://www.openerp.com/start" class="oe_button oe_big oe_tacky">Start your <span class="oe_emph">free</span> trial</a>
+ <a href="http://www.openerp.com/start?app=hr" class="oe_button oe_big oe_tacky">Start your <span class="oe_emph">free</span> trial</a>
</div>
</div>
</div>
diff --git a/addons/hr/static/src/css/hr.css b/addons/hr/static/src/css/hr.css
index 16657394736..951ec4d02e3 100644
--- a/addons/hr/static/src/css/hr.css
+++ b/addons/hr/static/src/css/hr.css
@@ -68,3 +68,8 @@
margin: 2px 0;
padding: 0;
}
+
+.openerp .oe_employee_vignette .oe_followers {
+ width: auto;
+ float: none;
+}
diff --git a/addons/hr/static/src/js/suggestions.js b/addons/hr/static/src/js/suggestions.js
new file mode 100644
index 00000000000..3bc37e71344
--- /dev/null
+++ b/addons/hr/static/src/js/suggestions.js
@@ -0,0 +1,78 @@
+openerp.hr = function(session) {
+ var _t = session.web._t;
+ var QWeb = session.web.qweb;
+
+ var suggestions = session.suggestions;
+ var removed_suggested_employee = session.suggestions.removed_suggested_employee = [];
+
+ suggestions.Employees = session.web.Widget.extend({
+ events: {
+ 'click .oe_suggestion_remove.oe_suggestion_employee': 'stop_employee_suggestion',
+ 'click .oe_suggestion_remove_item.oe_suggestion_employee': 'remove_employee_suggestion',
+ 'click .oe_suggestion_follow': 'follow_employee',
+ },
+
+ init: function () {
+ this._super(this, arguments);
+ this.hr_employee = new session.web.DataSetSearch(this, 'hr.employee');
+ this.res_users = new session.web.DataSetSearch(this, 'res.users');
+ this.employees = [];
+ },
+
+ start: function () {
+ this._super.apply(this, arguments);
+ return this.fetch_suggested_employee();
+ },
+
+ fetch_suggested_employee: function () {
+ var self = this;
+ var employee = self.hr_employee.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_employee}).then(function (res) {
+ _(res).each(function (result) {
+ result['image']=self.session.url('/web/binary/image', {model: 'hr.employee', field: 'image_small', id: result.id});
+ });
+ self.employees = res;
+ });
+ return $.when(employee).done(this.proxy('display_suggested_employees'));
+ },
+
+ display_suggested_employees: function () {
+ var suggested_employees = this.$('.oe_sidebar_suggestion.oe_suggestion_employee');
+ if (suggested_employees) {
+ suggested_employees.remove();
+ }
+ if (this.employees.length === 0) {
+ return this.$el.empty();
+ }
+ return this.$el.empty().html(QWeb.render('hr.suggestions.employees', {'widget': this}));
+ },
+
+ follow_employee: function (event) {
+ var self = this;
+ var employee_id = parseInt($(event.currentTarget).attr('id'), 10);
+ return this.hr_employee.call('message_subscribe_users', [[employee_id], [this.session.uid], undefined]).then(function(res) {
+ self.fetch_suggested_employee();
+ });
+ },
+
+ remove_employee_suggestion: function (event) {
+ removed_suggested_employee.push($(event.currentTarget).attr('id'));
+ return this.fetch_suggested_employee();
+ },
+
+ stop_employee_suggestion: function (event) {
+ var self = this;
+ return this.res_users.call('stop_showing_employees_suggestions', [this.session.uid]).then(function(res) {
+ self.$(".oe_sidebar_suggestion.oe_suggestion_employee").hide();
+ });
+ }
+ });
+
+ session.mail.WallSidebar.include({
+ start: function () {
+ this._super.apply(this, arguments);
+ var sug_employees = new suggestions.Employees(this);
+ return sug_employees.appendTo(this.$('.oe_suggestions_employees'));
+ },
+ });
+
+};
diff --git a/addons/hr/static/src/xml/suggestions.xml b/addons/hr/static/src/xml/suggestions.xml
new file mode 100644
index 00000000000..f3095627bae
--- /dev/null
+++ b/addons/hr/static/src/xml/suggestions.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<template>
+
+ <!-- Employees placeholder in sidebar -->
+ <t t-extend="mail.wall.sidebar">
+ <t t-jquery=".oe_mail_wall_sidebar" t-operation="append">
+ <div class="oe_suggestions_employees"></div>
+ </t>
+ </t>
+
+ <!-- Suggested employees -->
+ <div t-name="hr.suggestions.employees" class="oe_sidebar_suggestion oe_suggestion_employee">
+ <div class="oe_suggest_title">
+ <a class="oe_suggestion_remove oe_suggestion_employee oe_e">X</a>
+ <h2>Suggested Employees</h2>
+ </div>
+ <div class="oe_suggest_items">
+ <t t-foreach="widget.employees" t-as="result">
+ <div class="oe_suggested_item">
+ <div class="oe_suggested_item_image">
+ <a t-attf-href="#model=hr.employee&amp;id=#{result.id}">
+ <img t-attf-src="{result.image}" t-attf-alt="{result.name}"/>
+ </a>
+ </div>
+ <div class="oe_suggested_item_content">
+ <a class="oe_suggestion_item_name" t-attf-href="#model=hr.employee&amp;id=#{result.id}"><t t-esc="result.name"/></a>
+ <a class="oe_suggestion_remove_item oe_suggestion_employee oe_e" t-attf-id="{result.id}">X</a>
+ <br/>
+ <button class="oe_suggestion_follow" t-att-id="result.id">Follow</button>
+ </div>
+ </div>
+ </t>
+ </div>
+ </div>
+
+</template>