Project management improvements

bzr revid: hda@tinyerp.com-20100119073547-dqn2c0i9ycx6kp3a
This commit is contained in:
HDA (OpenERP) 2010-01-19 13:05:47 +05:30
commit 92ae38eb0a
44 changed files with 2000 additions and 330 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -41,7 +41,7 @@ class account_analytic_account(osv.osv):
where_date += " AND l.date >= '" + context['from_date'] + "'"
if context.get('to_date',False):
where_date += " AND l.date <= '" + context['to_date'] + "'"
cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount<0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set))
r = dict(cr.fetchall())
for i in ids:
@ -51,13 +51,13 @@ class account_analytic_account(osv.osv):
def _debit_calc(self, cr, uid, ids, name, arg, context={}):
acc_set = ",".join(map(str, ids))
where_date = ''
if context.get('from_date',False):
where_date += " AND l.date >= '" + context['from_date'] + "'"
if context.get('to_date',False):
where_date += " AND l.date <= '" + context['to_date'] + "'"
cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount>0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set))
r= dict(cr.fetchall())
for i in ids:
@ -68,21 +68,21 @@ class account_analytic_account(osv.osv):
res = {}
ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
acc_set = ",".join(map(str, ids2))
for i in ids:
res.setdefault(i,0.0)
if not acc_set:
return res
where_date = ''
if context.get('from_date',False):
where_date += " AND l.date >= '" + context['from_date'] + "'"
if context.get('to_date',False):
where_date += " AND l.date <= '" + context['to_date'] + "'"
cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE a.id IN (%s) GROUP BY a.id" % (where_date,acc_set))
for account_id, sum in cr.fetchall():
res[account_id] = sum
@ -115,19 +115,19 @@ class account_analytic_account(osv.osv):
res = {}
ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
acc_set = ",".join(map(str, ids2))
for i in ids:
res.setdefault(i,0.0)
if not acc_set:
return res
where_date = ''
if context.get('from_date',False):
where_date += " AND l.date >= '" + context['from_date'] + "'"
if context.get('to_date',False):
where_date += " AND l.date <= '" + context['to_date'] + "'"
cr.execute('SELECT a.id, COALESCE(SUM(l.unit_amount), 0) \
FROM account_analytic_account a \
LEFT JOIN account_analytic_line l ON (a.id = l.account_id ' + where_date + ') \
@ -168,10 +168,10 @@ class account_analytic_account(osv.osv):
return result
_columns = {
'name' : fields.char('Account Name', size=64, required=True),
'name' : fields.char('Account Name', size=128, required=True),
'complete_name': fields.function(_complete_name_calc, method=True, type='char', string='Full Account Name'),
'code' : fields.char('Account Code', size=24),
'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the analytic account without removing it."),
# 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the analytic account without removing it."),
'type': fields.selection([('view','View'), ('normal','Normal')], 'Account Type'),
'description' : fields.text('Description'),
'parent_id': fields.many2one('account.analytic.account', 'Parent Analytic Account', select=2),
@ -189,11 +189,13 @@ class account_analytic_account(osv.osv):
'date': fields.date('Date End'),
'company_id': fields.many2one('res.company', 'Company', required=True),
'company_currency_id': fields.function(_get_company_currency, method=True, type='many2one', relation='res.currency', string='Currency'),
'state': fields.selection([('draft','Draft'), ('open','Open'), ('pending','Pending'), ('close','Close'),], 'State', required=True,
'state': fields.selection([('draft','Draft'),('open','Open'), ('pending','Pending'),('cancelled', 'Cancelled'),('close','Close'),('template', 'Template')], 'State', required=True,readonly=True,
help='* When an account is created its in \'Draft\' state.\
\n* If any associated partner is there, it can be in \'Open\' state.\
\n* If any pending balance is there it can be in \'Pending\'. \
\n* And finally when all the transactions are over, it can be in \'Close\' state.'),
\n* And finally when all the transactions are over, it can be in \'Close\' state. \
\n* The project can be in either if the states \'Template\' and \'Running\'.\n If it is template then we can make projects based on the template projects. If its in \'Running\' state it is a normal project.\
\n If it is to be reviewed then the state is \'Pending\'.\n When the project is completed the state is set to \'Done\'.'),
}
def _default_company(self, cr, uid, context={}):
@ -202,13 +204,14 @@ class account_analytic_account(osv.osv):
return user.company_id.id
return self.pool.get('res.company').search(cr, uid, [('parent_id', '=', False)])[0]
_defaults = {
'active' : lambda *a : True,
# 'active' : lambda *a : True,
'type' : lambda *a : 'normal',
'company_id': _default_company,
'state' : lambda *a : 'draft',
'state' : lambda *a : 'open',
'user_id' : lambda self,cr,uid,ctx : uid,
'partner_id': lambda self,cr, uid, ctx: ctx.get('partner_id', False),
'contact_id': lambda self,cr, uid, ctx: ctx.get('contact_id', False),
'date_start': lambda *a: time.strftime('%Y-%m-%d')
}
def check_recursion(self, cr, uid, ids, parent=None):

View File

@ -76,7 +76,7 @@
<newline/>
<field name="date_start"/>
<field name="date" select="2"/>
<field name="active" select="2"/>
<newline/>
<field name="quantity_max"/>
<field name="user_id"/>

View File

@ -36,7 +36,7 @@
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['base', 'process'],
'depends': ['base', 'process', 'resource'],
'init_xml': [],
'update_xml': [
'security/hr_security.xml',
@ -46,7 +46,8 @@
'process/hr_process.xml',
'hr_installer.xml'
],
'demo_xml': ['hr_demo.xml', 'hr_department_demo.xml'],
'demo_xml': ['hr_demo.xml',
'hr_department_demo.xml'],
'installable': True,
'active': False,
'certificate': '0086710558965',

104
addons/hr/hr.py Normal file → Executable file
View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -26,78 +26,16 @@ import math
from osv import fields, osv
from tools.translate import _
class hr_timesheet_group(osv.osv):
_name = "hr.timesheet.group"
_description = "Working Time"
_columns = {
'name' : fields.char("Group name", size=64, required=True),
'timesheet_id' : fields.one2many('hr.timesheet', 'tgroup_id', 'Working Time'),
'manager' : fields.many2one('res.users', 'Workgroup manager'),
}
def interval_min_get(self, cr, uid, id, dt_from, hours):
if not id:
return [(dt_from-DateTime.RelativeDateTime(hours=int(hours)*3), dt_from)]
todo = hours
cycle = 0
result = []
maxrecur = 100
current_hour = dt_from.hour
while (todo>0) and maxrecur:
cr.execute("select hour_from,hour_to from hr_timesheet where dayofweek='%s' and tgroup_id=%s order by hour_from desc", (dt_from.day_of_week,id))
for (hour_from,hour_to) in cr.fetchall():
if (hour_from<current_hour) and (todo>0):
m = min(hour_to, current_hour)
if (m-hour_from)>todo:
hour_from = m-todo
d1 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_from)),int((hour_from%1) * 60))
d2 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60))
result.append((d1, d2))
current_hour = hour_from
todo -= (m-hour_from)
dt_from -= DateTime.RelativeDateTime(days=1)
current_hour = 24
maxrecur -= 1
result.reverse()
return result
def interval_get(self, cr, uid, id, dt_from, hours, byday=True):
if not id:
return [(dt_from,dt_from+DateTime.RelativeDateTime(hours=int(hours)*3))]
todo = hours
cycle = 0
result = []
maxrecur = 100
current_hour = dt_from.hour
while (todo>0) and maxrecur:
cr.execute("select hour_from,hour_to from hr_timesheet where dayofweek='%s' and tgroup_id=%s order by hour_from", (dt_from.day_of_week,id))
for (hour_from,hour_to) in cr.fetchall():
if (hour_to>current_hour) and (todo>0):
m = max(hour_from, current_hour)
if (hour_to-m)>todo:
hour_to = m+todo
d1 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60))
d2 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60))
result.append((d1, d2))
current_hour = hour_to
todo -= (hour_to - m)
dt_from += DateTime.RelativeDateTime(days=1)
current_hour = 0
maxrecur -= 1
return result
hr_timesheet_group()
class hr_employee_category(osv.osv):
_name = "hr.employee.category"
_description = "Employee Category"
_columns = {
'name' : fields.char("Category", size=64, required=True),
'parent_id': fields.many2one('hr.employee.category', 'Parent Category', select=True),
'child_ids': fields.one2many('hr.employee.category', 'parent_id', 'Child Categories')
}
def _check_recursion(self, cr, uid, ids):
level = 100
while len(ids):
@ -107,23 +45,18 @@ class hr_employee_category(osv.osv):
return False
level -= 1
return True
_constraints = [
(_check_recursion, 'Error ! You cannot create recursive Categories.', ['parent_id'])
]
hr_employee_category()
class hr_employee(osv.osv):
_name = "hr.employee"
_description = "Employee"
_inherits = {'resource.resource':"resource_id"}
_columns = {
'name' : fields.char("Employee's Name", size=128, required=True),
'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the employee record without removing it."),
'company_id': fields.many2one('res.company', 'Company'),
'user_id' : fields.many2one('res.users', 'Related User', help='Related user name for an employee to manage his access rights.'),
'country_id' : fields.many2one('res.country', 'Nationality'),
'birthday' : fields.date("Birthday"),
'ssnid': fields.char('SSN No', size=32, help='Social Security Number'),
@ -142,11 +75,12 @@ class hr_employee(osv.osv):
'parent_id': fields.many2one('hr.employee', 'Manager', select=True),
'category_id' : fields.many2one('hr.employee.category', 'Category'),
'child_ids': fields.one2many('hr.employee', 'parent_id','Subordinates'),
'resource_id': fields.many2one('resource.resource','Resource',ondelete='cascade'),
}
_defaults = {
'active' : lambda *a: True,
}
def _check_recursion(self, cr, uid, ids):
level = 100
while len(ids):
@ -156,26 +90,10 @@ class hr_employee(osv.osv):
return False
level -= 1
return True
_constraints = [
(_check_recursion, 'Error ! You cannot create recursive Hierarchy of Employees.', ['parent_id'])
]
hr_employee()
class hr_timesheet(osv.osv):
_name = "hr.timesheet"
_description = "Timesheet Line"
_columns = {
'name' : fields.char("Name", size=64, required=True),
'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of week'),
'date_from' : fields.date('Starting date'),
'hour_from' : fields.float('Work from', size=8, required=True),
'hour_to' : fields.float("Work to", size=8, required=True),
'tgroup_id' : fields.many2one("hr.timesheet.group", "Employee's timesheet group", select=True),
}
_order = 'dayofweek, hour_from'
hr_timesheet()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,90 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Example employee -->
<record id="timesheet_group1" model="hr.timesheet.group">
<record id="timesheet_group1" model="resource.calendar">
<field name="name">38 Hours/Week</field>
</record>
<record id="employee1" model="hr.employee">
<field name="name">Fabien Pinckaers</field>
<!--<field name="regime">45</field>-->
<field name="user_id" ref="base.user_root"/>
<!--<field name="holiday_max">25</field>-->
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Monday morning</field>
<field name="dayofweek">0</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Monday evening</field>
<field name="dayofweek">0</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Tuesday morning</field>
<field name="dayofweek">1</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Tuesday evening</field>
<field name="dayofweek">1</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Wednesday morning</field>
<field name="dayofweek">2</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Wednesday evening</field>
<field name="dayofweek">2</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Thursday morning</field>
<field name="dayofweek">3</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Thursday evening</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="dayofweek">3</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Friday morning</field>
<field name="dayofweek">4</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="hr.timesheet">
<record model="resource.calendar.week">
<field name="name">Friday evening</field>
<field name="dayofweek">4</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="tgroup_id" ref="timesheet_group1"/>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
</data>
</openerp>

View File

@ -12,8 +12,12 @@
id="menu_hr_configuration"
name="Configuration"
parent="hr.menu_hr_root"
sequence="50" groups="group_hr_manager"/>
sequence="50" />
<!-- <menuitem
id="menu_hr_time"
name="Time Tracking"
parent="hr.menu_hr_root"/>
-->
<menuitem id="menu_view_employee_category_configuration_form" parent="hr.menu_hr_configuration" name="Employees" sequence="1"/>
<!--
==========
@ -105,6 +109,7 @@
</record>
<!-- <menuitem
id="menu_open_view_employee_list"
name="Employees"
action="open_view_employee_list"
groups="group_hr_manager"
parent="menu_hr_human_resources"/>
@ -167,62 +172,6 @@
<field eval="True" name="replace"/>
</ir_set>
<!--
============
Working Time
============
-->
<record id="create_group" model="ir.ui.view">
<field name="name">hr.timesheet.group.form</field>
<field name="model">hr.timesheet.group</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Working Time Category">
<field name="name" select="1"/>
<field name="manager" select="1"/>
<newline/>
<field colspan="4" name="timesheet_id" nolabel="1" widget="one2many_list"/>
</form>
</field>
</record>
<record id="edit_workgroup" model="ir.actions.act_window">
<field name="name">Working Schedules</field>
<field name="res_model">hr.timesheet.group</field>
<field name="view_type">form</field>
<field name="view_id" eval="False"/>
</record>
<menuitem action="edit_workgroup" id="menu_edit_workgroup" name="Work Schedules" parent="menu_view_employee_category_configuration_form" sequence="4"/>
<record id="view_timesheet_tree" model="ir.ui.view">
<field name="name">hr.timesheet.tree</field>
<field name="model">hr.timesheet</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Working Time">
<field name="name"/>
<field name="dayofweek"/>
<field name="hour_from" widget="float_time"/>
<field name="hour_to" widget="float_time"/>
</tree>
</field>
</record>
<record id="view_timesheet_form" model="ir.ui.view">
<field name="name">hr.timesheet.form</field>
<field name="model">hr.timesheet</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Working Time">
<field colspan="4" name="name" select="1"/>
<field name="date_from"/>
<field name="dayofweek" select="1"/>
<field name="hour_from" widget="float_time"/>
<field name="hour_to" widget="float_time"/>
</form>
</field>
</record>
<!--
============
Employee Category
@ -272,7 +221,6 @@
<menuitem action="open_view_categ_form" id="menu_view_employee_category_form" parent="menu_view_employee_category_configuration_form" sequence="1"/>
<record id="open_view_categ_tree" model="ir.actions.act_window">
<field name="name">Categories structure</field>
<field name="res_model">hr.employee.category</field>

View File

@ -1,10 +1,6 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_hr_timesheet_group","hr.timesheet.group","model_hr_timesheet_group","hr.group_hr_user",1,0,0,0
"access_hr_employee_category","hr.employee.category","model_hr_employee_category","hr.group_hr_user",1,0,0,0
"access_hr_employee","hr.employee","model_hr_employee","hr.group_hr_user",1,1,1,1
"access_hr_timesheet_manager","hr.timesheet manager","model_hr_timesheet","hr.group_hr_manager",1,1,1,1
"access_hr_timesheet","hr.timesheet","model_hr_timesheet","hr.group_hr_user",1,1,1,1
"access_hr_department","hr.department","model_hr_department","hr.group_hr_user",1,0,0,0
"access_hr_timesheet_group_manager","hr.timesheet.group.manager","model_hr_timesheet_group","hr.group_hr_manager",1,1,1,1
"access_hr_employee_category_manager","hr.employee.category.manager","model_hr_employee_category","hr.group_hr_manager",1,1,1,1
"access_hr_department_manager","hr.department.manager","model_hr_department","hr.group_hr_manager",1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
access_hr_timesheet_group hr.timesheet.group model_hr_timesheet_group hr.group_hr_user 1 0 0 0
2 access_hr_employee_category hr.employee.category model_hr_employee_category hr.group_hr_user 1 0 0 0
3 access_hr_employee hr.employee model_hr_employee hr.group_hr_user 1 1 1 1
access_hr_timesheet_manager hr.timesheet manager model_hr_timesheet hr.group_hr_manager 1 1 1 1
access_hr_timesheet hr.timesheet model_hr_timesheet hr.group_hr_user 1 1 1 1
4 access_hr_department hr.department model_hr_department hr.group_hr_user 1 0 0 0
access_hr_timesheet_group_manager hr.timesheet.group.manager model_hr_timesheet_group hr.group_hr_manager 1 1 1 1
5 access_hr_employee_category_manager hr.employee.category.manager model_hr_employee_category hr.group_hr_manager 1 1 1 1
6 access_hr_department_manager hr.department.manager model_hr_department hr.group_hr_manager 1 1 1 1

View File

@ -88,8 +88,8 @@
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_attendance_reason"/>
</record>
<menuitem sequence="9" id="menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Leaves"/>
<menuitem action="open_view_attendance_reason" id="menu_open_view_attendance_reason" parent="menu_open_view_attendance_reason_config"/>
<menuitem sequence="9" id="hr.menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Leaves"/>
<menuitem action="open_view_attendance_reason" id="menu_open_view_attendance_reason" parent="hr.menu_open_view_attendance_reason_config"/>
<record id="hr_attendance_employee" model="ir.ui.view">
<field name="name">hr.employee.form1</field>

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -85,7 +85,7 @@ class hr_contract(osv.osv):
'function' : fields.many2one('res.partner.function', 'Function'),
'date_start' : fields.date('Start Date', required=True),
'date_end' : fields.date('End Date'),
'working_hours_per_day_id' : fields.many2one('hr.timesheet.group','Working hours per day'),
'working_hours_per_day_id' : fields.many2one('resource.calendar','Working hours per day'),
'wage_type_id' : fields.many2one('hr.contract.wage.type', 'Wage Type', required=True),
'wage' : fields.float('Wage', required=True),
'notes' : fields.text('Notes'),

26
addons/hr_holidays/hr.py Normal file → Executable file
View File

@ -54,7 +54,7 @@ class hr_holidays_status(osv.osv):
return_false = False
if context and context.has_key('employee_id'):
if not context['employee_id']:
return_false = True
return_false = True
employee_id = context['employee_id']
else:
employee_ids = self.pool.get('hr.employee').search(cr, uid, [('user_id','=',uid)])
@ -71,9 +71,9 @@ class hr_holidays_status(osv.osv):
'color_name' : fields.selection([('red', 'Red'), ('lightgreen', 'Light Green'), ('lightblue','Light Blue'), ('lightyellow', 'Light Yellow'), ('magenta', 'Magenta'),('lightcyan', 'Light Cyan'),('black', 'Black'),('lightpink', 'Light Pink'),('brown', 'Brown'),('violet', 'Violet'),('lightcoral', 'Light Coral'),('lightsalmon', 'Light Salmon'),('lavender', 'Lavender'),('wheat', 'Wheat'),('ivory', 'Ivory')],'Color of the status', required=True, help='This color will be used in the leaves summary located in Reporting\Print Summary of Leaves'),
'limit' : fields.boolean('Allow to override Limit', help='If you thick this checkbox, the system will allow, for this section, the employees to take more leaves than the available ones.'),
'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the leave type without removing it."),
'max_leaves' : fields.function(_user_left_days, method=True, string='Maximum Leaves Allowed', help='This value is given by the sum of all holidays requests with a positive value.', multi='user_left_days'),
'leaves_taken' : fields.function(_user_left_days, method=True, string='Leaves Already Taken', help='This value is given by the sum of all holidays requests with a negative value.', multi='user_left_days'),
'remaining_leaves' : fields.function(_user_left_days, method=True, string='Remaining Leaves', multi='user_left_days'),
'max_leaves' : fields.function(_user_left_days, method=True, string='Maximum Leaves Allowed', help='This value is given by the sum of all holidays requests with a positive value.', multi='user_left_days'),
'leaves_taken' : fields.function(_user_left_days, method=True, string='Leaves Already Taken', help='This value is given by the sum of all holidays requests with a negative value.', multi='user_left_days'),
'remaining_leaves' : fields.function(_user_left_days, method=True, string='Remaining Leaves', multi='user_left_days'),
}
_defaults = {
@ -165,7 +165,6 @@ class hr_holidays(osv.osv):
_order = 'date_from desc'
def create(self, cr, uid, vals, context={}):
print 'create', vals, context
if context:
if context.has_key('type'):
vals['type'] = context['type']
@ -182,7 +181,7 @@ class hr_holidays(osv.osv):
#~ return True
#_constraints = [(_check_date, 'Start date should not be greater than end date! ', ['number_of_days'])]
def onchange_date_from(self, cr, uid, ids, date_to, date_from):
result = {}
if date_to and date_from:
@ -242,11 +241,10 @@ class hr_holidays(osv.osv):
'state':'validate',
}
ids2 = self.pool.get('hr.employee').search(cr, uid, [('user_id','=', uid)])
if ids2:
vals['manager_id'] = ids2[0]
else:
raise osv.except_osv(_('Warning !'),_('Either there is no Employee defined, or no User attached with it.'))
raise osv.except_osv(_('Warning !'),_('Either there is no Employee defined, or no User attached with it.'))
self.write(cr, uid, ids, vals)
return True
@ -269,6 +267,16 @@ class hr_holidays(osv.osv):
'number_of_days': nb,
'user_id': user_id
})
vals= {
'name':record.name,
'date_from':record.date_from,
'date_to':record.date_to,
'calendar_id':record.employee_id.calendar_id.id,
'company_id':record.employee_id.company_id.id,
'resource_id':record.employee_id.resource_id.id
}
self.pool.get('resource.calendar.leaves').create(cr,uid,vals)
return True
def holidays_refuse(self, cr, uid, ids, *args):
@ -325,7 +333,7 @@ class hr_holidays(osv.osv):
'date_to' : record.date_to,
'notes' : record.notes,
'number_of_days': record.number_of_days,
'number_of_days_temp': record.number_of_days_temp,
'number_of_days_temp': record.number_of_days_temp,
'type': record.type,
'allocation_type': record.allocation_type,
'parent_id': record.id,

View File

@ -258,6 +258,7 @@
<field name="view_mode">tree,form</field>
</record>
<menuitem sequence="9" id="hr.menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Leaves"/>
<!--<menuitem
action="open_view_holiday_status"
id="menu_open_view_holiday_status"
@ -265,7 +266,7 @@
<menuitem name="Leaves Statuses"
action="open_view_holiday_status"
id="menu_open_view_holiday_status"
parent="hr_attendance.menu_open_view_attendance_reason_config"/>
parent="hr.menu_open_view_attendance_reason_config"/>
<!-- Shortcuts -->
<act_window name="My Holiday Requests"

View File

@ -639,8 +639,10 @@ class hr_timesheet_sheet_sheet_day(osv.osv):
from
hr_attendance a
LEFT JOIN (hr_timesheet_sheet_sheet s
LEFT JOIN hr_employee e
ON (s.user_id = e.user_id))
LEFT JOIN resource_resource r
LEFT JOIN hr_employee e
ON (e.resource_id = r.id)
ON (s.user_id = r.user_id))
ON (a.employee_id = e.id
AND s.date_to >= date_trunc('day',a.name)
AND s.date_from <= a.name)

View File

@ -46,7 +46,7 @@
</tree>
</field>
</record>
<!--
<record id="hr_timesheet_day_form" model="ir.ui.view">
<field name="name">hr.timesheet.day.form</field>
<field name="model">hr_timesheet_sheet.sheet.day</field>
@ -61,7 +61,7 @@
</form>
</field>
</record>
<record id="hr_timesheet_day_tree" model="ir.ui.view">
<field name="name">hr.timesheet.day.tree</field>
<field name="model">hr_timesheet_sheet.sheet.day</field>
@ -76,7 +76,7 @@
</tree>
</field>
</record>
-->
<record id="hr_timesheet_sheet_form" model="ir.ui.view">
<field name="name">hr.timesheet.sheet.form</field>
<field name="model">hr_timesheet_sheet.sheet</field>
@ -266,7 +266,7 @@
</record>
<act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_by_day" name="Timesheet by Account" res_model="hr_timesheet_sheet.sheet.account" src_model="hr_timesheet_sheet.sheet"/>
<act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_by_account" name="Timesheet by Day" res_model="hr_timesheet_sheet.sheet.day" src_model="hr_timesheet_sheet.sheet"/>
<!-- <act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_by_account" name="Timesheet by Day" res_model="hr_timesheet_sheet.sheet.day" src_model="hr_timesheet_sheet.sheet"/> -->
<act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_2_hr_analytic_timesheet" name="Timesheet Lines" res_model="hr.analytic.timesheet" src_model="hr_timesheet_sheet.sheet"/>

View File

@ -40,21 +40,14 @@ from tools.translate import _
class mrp_workcenter(osv.osv):
_name = 'mrp.workcenter'
_description = 'Work Center'
_inherits = {'resource.resource':"resource_id"}
_columns = {
'name': fields.char('Work Center Name', size=64, required=True),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the work center without removing it."),
'type': fields.selection([('machine','Machine'),('hr','Human Resource'),('tool','Tool')], 'Type', required=True),
'code': fields.char('Code', size=16),
'timesheet_id': fields.many2one('hr.timesheet.group', 'Working Time', help="The normal working time of the workcenter."),
# 'name': fields.char('Work Center Name', size=64, required=True),
'note': fields.text('Description', help="Description of the workcenter. Explain here what's a cycle according to this workcenter."),
'capacity_per_cycle': fields.float('Capacity per Cycle', help="Number of operations this workcenter can do in parallel. If this workcenter represents a team of 5 workers, the capacity per cycle is 5."),
'time_cycle': fields.float('Time for 1 cycle (hour)', help="Time in hours for doing one cycle."),
'time_start': fields.float('Time before prod.', help="Time in hours for the setup."),
'time_stop': fields.float('Time after prod.', help="Time in hours for the cleaning."),
'time_efficiency': fields.float('Efficiency factor', help="Factor to adjust the work center cycle and before and after production durations"),
'costs_hour': fields.float('Cost per hour'),
'costs_hour_account_id': fields.many2one('account.analytic.account', 'Hour Account', domain=[('type','<>','view')],
help="Complete this only if you want automatic analytic accounting entries on production orders."),
@ -63,15 +56,12 @@ class mrp_workcenter(osv.osv):
help="Complete this only if you want automatic analytic accounting entries on production orders."),
'costs_journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal'),
'costs_general_account_id': fields.many2one('account.account', 'General Account', domain=[('type','<>','view')]),
'company_id': fields.many2one('res.company','Company',required=True),
# 'company_id': fields.many2one('res.company','Company',required=True),
'resource_id': fields.many2one('resource.resource','Resource',ondelete='cascade'),
}
_defaults = {
'active': lambda *a: 1,
'type': lambda *a: 'machine',
'time_efficiency': lambda *a: 1.0,
'capacity_per_cycle': lambda *a: 1.0,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.workcenter', context=c)
}
}
mrp_workcenter()
@ -130,7 +120,7 @@ class mrp_routing_workcenter(osv.osv):
'cycle_nbr': fields.float('Number of Cycles', required=True,
help="Time in hours for doing one cycle."),
'hour_nbr': fields.float('Number of Hours', required=True, help="Cost per hour"),
'routing_id': fields.many2one('mrp.routing', 'Parent Routing', select=True, ondelete='cascade',
'routing_id': fields.many2one('mrp.routing', 'Parent Routing', select=True, ondelete='cascade',
help="Routing indicates all the workcenters used, for how long and/or cycles." \
"If Routing is indicated then,the third tab of a production order (workcenters) will be automatically pre-completed."),
'note': fields.text('Description')
@ -175,7 +165,7 @@ class mrp_bom(osv.osv):
'name': fields.char('Name', size=64, required=True),
'code': fields.char('Code', size=16),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the bills of material without removing it."),
'type': fields.selection([('normal','Normal BoM'),('phantom','Sets / Phantom')], 'BoM Type', required=True,
'type': fields.selection([('normal','Normal BoM'),('phantom','Sets / Phantom')], 'BoM Type', required=True,
help= "If a sub-product is used in several products, it can be useful to create its own BoM."\
"Though if you don't want separated production orders for this sub-product, select Set/Phantom as BoM type."\
"If a Phantom BoM is used for a root product, it will be sold and shipped as a set of components, instead of being produced."),
@ -833,7 +823,7 @@ class mrp_procurement(osv.osv):
help='When a procurement is created the state is set to \'Draft\'.\n If the procurement is confirmed, the state is set to \'Confirmed\'.\
\nAfter confirming the state is set to \'Running\'.\n If any exception arises in the order then the state is set to \'Exception\'.\n Once the exception is removed the state becomes \'Ready\'.\n It is in \'Waiting\'. state when the procurement is waiting for another one to finish.'),
'note' : fields.text('Note'),
'company_id': fields.many2one('res.company','Company',required=True),
'company_id': fields.many2one('res.company','Company',required=True),
}
_defaults = {
'state': lambda *a: 'draft',
@ -1205,7 +1195,7 @@ class stock_warehouse_orderpoint(osv.osv):
'qty_multiple': fields.integer('Qty Multiple', required=True,
help="The requisition quantity will by rounded up to this multiple."),
'procurement_id': fields.many2one('mrp.procurement', 'Purchase Order'),
'company_id': fields.many2one('res.company','Company',required=True),
'company_id': fields.many2one('res.company','Company',required=True),
}
_defaults = {
'active': lambda *a: 1,

View File

@ -120,8 +120,8 @@
</group>
<notebook colspan="4">
<page string="Work Center">
<field name="type"/>
<field name="timesheet_id"/>
<field name="resource_type"/>
<field name="calendar_id"/>
<separator colspan="4" string="Description"/>
<field colspan="4" name="note" nolabel="1"/>
<separator colspan="4" string="Capacity Information"/>

View File

@ -27,6 +27,6 @@
"access_account_account","account.account mrp_worker","account.model_account_account","mrp.group_mrp_user",1,0,0,0
"access_purchase_order_mrp_worker","purchase.order mrp_worker","purchase.model_purchase_order","mrp.group_mrp_user",1,0,0,0
"access_purchase_order_line_mrp_worker","purchase.order.line mrp_worker","purchase.model_purchase_order_line","mrp.group_mrp_user",1,0,0,0
"access_hr_timesheet_group_mrp_worker","hr.timesheet.group mrp_worker","hr.model_hr_timesheet_group","mrp.group_mrp_user",1,0,0,0
"access_hr_timesheet_group_mrp_worker","resource.calendar mrp_worker","resource.model_resource_calendar","mrp.group_mrp_user",1,0,0,0
"access_mrp_procurement_stock_worker","mrp.procurement stock_worker","model_mrp_procurement","stock.group_stock_user",1,1,1,1
"access_mrp_production_stock_worker","mrp.production stock_worker","model_mrp_production","stock.group_stock_user",1,0,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
27 access_account_account account.account mrp_worker account.model_account_account mrp.group_mrp_user 1 0 0 0
28 access_purchase_order_mrp_worker purchase.order mrp_worker purchase.model_purchase_order mrp.group_mrp_user 1 0 0 0
29 access_purchase_order_line_mrp_worker purchase.order.line mrp_worker purchase.model_purchase_order_line mrp.group_mrp_user 1 0 0 0
30 access_hr_timesheet_group_mrp_worker hr.timesheet.group mrp_worker resource.calendar mrp_worker hr.model_hr_timesheet_group resource.model_resource_calendar mrp.group_mrp_user 1 0 0 0
31 access_mrp_procurement_stock_worker mrp.procurement stock_worker model_mrp_procurement stock.group_stock_user 1 1 1 1
32 access_mrp_production_stock_worker mrp.production stock_worker model_mrp_production stock.group_stock_user 1 0 0 0

View File

@ -60,7 +60,7 @@ class mrp_production_workcenter_line(osv.osv):
res[op.id]= False
if op.date_planned:
d = DateTime.strptime(op.date_planned,'%Y-%m-%d %H:%M:%S')
i = self.pool.get('hr.timesheet.group').interval_get(cr, uid, op.workcenter_id.timesheet_id.id or False, d, op.hour or 0.0)
i = self.pool.get('resource.calendar').interval_get(cr, uid, op.workcenter_id.calendar_id.id or False, d, op.hour or 0.0)
if i:
res[op.id] = i[-1][1].strftime('%Y-%m-%d %H:%M:%S')
else:
@ -204,10 +204,10 @@ class mrp_production(osv.osv):
self.pool.get('mrp.production.workcenter.line').write(cr, uid, [wc.id], {
'date_planned':dt.strftime('%Y-%m-%d %H:%M:%S')
}, context=context, update=False)
i = self.pool.get('hr.timesheet.group').interval_get(
i = self.pool.get('resource.calendar').interval_get(
cr,
uid,
wc.workcenter_id.timesheet_id and wc.workcenter_id.timesheet_id.id or False,
wc.workcenter_id.calendar_id and wc.workcenter_id.calendar_id.id or False,
dt,
wc.hour or 0.0
)
@ -235,10 +235,10 @@ class mrp_production(osv.osv):
if l.production_id and (l.production_id.date_finnished>dt):
if l.production_id.state not in ('done','cancel'):
for wc in l.production_id.workcenter_lines:
i = self.pool.get('hr.timesheet.group').interval_min_get(
i = self.pool.get('resource.calendar').interval_min_get(
cr,
uid,
wc.workcenter_id.timesheet_id.id or False,
wc.workcenter_id.calendar_id.id or False,
dt, wc.hour or 0.0
)
dt = i[0][0]

View File

@ -245,7 +245,7 @@ class product_template(osv.osv):
'description': fields.text('Description',translate=True),
'description_purchase': fields.text('Purchase Description',translate=True),
'description_sale': fields.text('Sale Description',translate=True),
'type': fields.selection([('product','Stockable Product'),('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Will change the way requisitions are processed. Consumables are stockable products with infinite stock, or for use when you have no inventory management in the system."),
'type': fields.selection([('product','Stockable Product'),('rima','Rima'),('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Will change the way requisitions are processed. Consumables are stockable products with infinite stock, or for use when you have no inventory management in the system."),
'supply_method': fields.selection([('produce','Produce'),('buy','Buy')], 'Supply method', required=True, help="Produce will generate production order or tasks, according to the product type. Purchase will trigger purchase orders when requested."),
'sale_delay': fields.float('Customer Lead Time', help="This is the average time between the confirmation of the customer order and the delivery of the finished products. It's the time you promise to your customers."),
'produce_delay': fields.float('Manufacturing Lead Time', help="Average time to produce this product. This is only for the production order and, if it is a multi-level bill of material, it's only for the level of this product. Different lead times will be summed for all levels and purchase orders."),

View File

@ -41,7 +41,9 @@ works done on tasks, eso. It is able to render planning, order tasks, eso.
"process/task_process.xml",
"project_installer.xml",
],
'demo_xml': ['project_demo.xml'],
'demo_xml': [#'project_demo.xml'
],
'installable': True,
'active': False,
'certificate': '0075116868317',

View File

@ -20,11 +20,10 @@
##############################################################################
from lxml import etree
from mx import DateTime
from mx.DateTime import now
import mx.DateTime
import datetime
import time
from tools.translate import _
from osv import fields, osv
from tools.translate import _
@ -46,7 +45,7 @@ project_task_type()
class project(osv.osv):
_name = "project.project"
_description = "Project"
_inherits = {'account.analytic.account':"category_id"}
def _complete_name(self, cr, uid, ids, name, args, context):
res = {}
for m in self.browse(cr, uid, ids, context=context):
@ -88,7 +87,7 @@ class project(osv.osv):
tocompute = [project]
while tocompute:
p = tocompute.pop()
tocompute += p.child_id
tocompute += p.child_ids
for i in range(3):
s[i] += progress.get(p.id, (0.0,0.0,0.0))[i]
res[project.id] = {
@ -105,52 +104,60 @@ class project(osv.osv):
raise osv.except_osv(_('Operation Not Permitted !'), _('You can not delete a project with tasks. I suggest you to deactivate it.'))
return super(project, self).unlink(cr, uid, ids, *args, **kwargs)
_columns = {
'name': fields.char("Project Name", size=128, required=True),
'complete_name': fields.function(_complete_name, method=True, string="Project Name", type='char', size=128),
# 'name': fields.char("Project Name", size=128, required=True),
# 'complete_name': fields.function(_complete_name, method=True, string="Project Name", type='char', size=128),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the project without removing it."),
'category_id': fields.many2one('account.analytic.account','Analytic Account', help="Link this project to an analytic account if you need financial management on projects. It enables you to connect projects with budgets, planning, cost and revenue analysis, timesheets on projects, etc."),
'priority': fields.integer('Sequence'),
'manager': fields.many2one('res.users', 'Project Manager'),
# 'manager': fields.many2one('res.users', 'Project Manager'),
'warn_manager': fields.boolean('Warn Manager', help="If you check this field, the project manager will receive a request each time a task is completed by his team."),
'members': fields.many2many('res.users', 'project_user_rel', 'project_id', 'uid', 'Project Members', help="Project's member. Not used in any computation, just for information purpose."),
'resource_ids': fields.many2many('resource.resource', 'project_resource_rel', 'project_id', 'resource_id', 'Project Members', help="Project's member. Not used in any computation, just for information purpose."),
'tasks': fields.one2many('project.task', 'project_id', "Project tasks"),
'parent_id': fields.many2one('project.project', 'Parent Project',\
help="If you have [?] in the name, it means there are no analytic account linked to project."),
'child_id': fields.one2many('project.project', 'parent_id', 'Subproject'),
# 'parent_id': fields.many2one('project.project', 'Parent Project',\
# help="If you have [?] in the name, it means there are no analytic account linked to project."),
# 'child_id': fields.one2many('project.project', 'parent_id', 'Subproject'),
'planned_hours': fields.function(_progress_rate, multi="progress", method=True, string='Planned Time', help="Sum of planned hours of all tasks related to this project."),
'effective_hours': fields.function(_progress_rate, multi="progress", method=True, string='Time Spent', help="Sum of spent hours of all tasks related to this project."),
'total_hours': fields.function(_progress_rate, multi="progress", method=True, string='Total Time', help="Sum of total hours of all tasks related to this project."),
'progress_rate': fields.function(_progress_rate, multi="progress", method=True, string='Progress', type='float', help="Percent of tasks closed according to the total of tasks todo."),
'date_start': fields.date('Starting Date'),
'date_end': fields.date('Expected End'),
'partner_id': fields.many2one('res.partner', 'Partner'),
'contact_id': fields.many2one('res.partner.address', 'Contact'),
# 'partner_id': fields.many2one('res.partner', 'Partner'),
# 'contact_id': fields.many2one('res.partner.address', 'Contact'),
'warn_customer': fields.boolean('Warn Partner', help="If you check this, the user will have a popup when closing a task that propose a message to send by email to the customer."),
'warn_header': fields.text('Mail Header', help="Header added at the beginning of the email for the warning message sent to the customer when a task is closed."),
'warn_footer': fields.text('Mail Footer', help="Footer added at the beginning of the email for the warning message sent to the customer when a task is closed."),
'notes': fields.text('Notes', help="Internal description of the project."),
'timesheet_id': fields.many2one('hr.timesheet.group', 'Working Time', help="Timetable working hours to adjust the gantt diagram report"),
'state': fields.selection([('template', 'Template'), ('open', 'Running'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', required=True, readonly=True,
help='The project can be in either if the states \'Template\' and \'Running\'.\n If it is template then we can make projects based on the template projects. If its in \'Running\' state it is a normal project.\
\n If it is to be reviewed then the state is \'Pending\'.\n When the project is completed the state is set to \'Done\'.'),
'company_id': fields.many2one('res.company', 'Company'),
# 'notes': fields.text('Notes', help="Internal description of the project."),
'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report"),
# 'state': fields.selection([('template', 'Template'), ('open', 'Running'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', required=True, readonly=True,
# help='The project can be in either if the states \'Template\' and \'Running\'.\n If it is template then we can make projects based on the template projects. If its in \'Running\' state it is a normal project.\
# \n If it is to be reviewed then the state is \'Pending\'.\n When the project is completed the state is set to \'Done\'.'),
# 'company_id': fields.many2one('res.company', 'Company'),
# 'timesheet_id': fields.many2one('hr.timesheet.group', 'Working Time', help="Timetable working hours to adjust the gantt diagram report"),
'allowed_task_type': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Allowed Task Types'),
}
_defaults = {
'active': lambda *a: True,
'manager': lambda object,cr,uid,context: uid,
# 'manager': lambda object,cr,uid,context: uid,
'priority': lambda *a: 1,
'date_start': lambda *a: time.strftime('%Y-%m-%d'),
'state': lambda *a: 'open',
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.project', context=c)
# 'state': lambda *a: 'open',
# 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.project', context=c)
}
def _check_dates(self, cr, uid, ids):
leave = self.read(cr, uid, ids[0],['date_start','date'])
if leave['date_start'] and leave['date']:
if leave['date_start'] > leave['date']:
return False
return True
_order = "parent_id,priority,name"
_constraints = [
(check_recursion, 'Error ! You can not create recursive projects.', ['parent_id'])
(_check_dates, 'Error! project start-date must be lower then project end-date.', ['date_start', 'date'])
]
# _order = "parent_id,priority,name"
# _constraints = [
# (check_recursion, 'Error ! You can not create recursive projects.', ['parent_id'])
# ]
# toggle activity of projects, their sub projects and their tasks
def set_template(self, cr, uid, ids, context={}):
res = self.setActive(cr, uid, ids, value=False, context=context)
@ -226,6 +233,29 @@ class task(osv.osv):
_name = "project.task"
_description = "Tasks"
_date_name = "date_start"
# def compute_date(self,cr,uid):
# project_id = self.pool.get('project.project').search(cr,uid,[])
# for i in range(len(project_id)):
# task_ids = self.pool.get('project.task').search(cr,uid,[('project_id','=',project_id[i])])
# if task_ids:
# task_obj = self.pool.get('project.task').browse(cr,uid,task_ids)
# task_1 = task_obj[0]
# task_1.date_start = self.pool.get('project.project').browse(cr,uid,project_id[i]).date_start
# dt = mx.DateTime.strptime(task_1.date_start,"%Y-%m-%d").strftime("%Y-%m-%d")
# def Project_1():
# title = "New Project"
# start = dt
#
# def task1():
# start = dt
# effort = task_1.planned_hours
# title = "Task 1"
## project_1 = BalancedProject(Project_1)
## for t in project_1:
## print 'details:::',t.indent_name(), t.start, t.end, t.effort
def _str_get(self, task, level=0, border='***', context={}):
return border+' '+(task.user_id and task.user_id.name.upper() or '')+(level and (': L'+str(level)) or '')+(' - %.1fh / %.1fh'%(task.effective_hours or 0.0,task.planned_hours))+' '+border+'\n'+ \
border[0]+' '+(task.name or '')+'\n'+ \
@ -235,12 +265,12 @@ class task(osv.osv):
result = {}
for task in self.browse(cr, uid, ids, context=context):
result[task.id] = self._str_get(task, border='===')
t2 = task.parent_id
t2 = task.parent_ids
level = 0
while t2:
level -= 1
result[task.id] = self._str_get(t2, level) + result[task.id]
t2 = t2.parent_id
t2 = t2.parent_ids
t3 = map(lambda x: (x,1), task.child_ids)
while t3:
t2 = t3.pop(0)
@ -265,8 +295,19 @@ class task(osv.osv):
res[task.id]['delay_hours'] = res[task.id]['total_hours'] - task.planned_hours
return res
def onchange_planned(self, cr, uid, ids, planned, effective=0.0):
return {'value':{'remaining_hours': planned-effective}}
def onchange_planned(self, cr, uid, ids, planned, effective, date_start,occupation_rate=0.0):
result = {}
for res in self.browse(cr, uid, ids):
if date_start and planned:
resource_id = self.pool.get('resource.resource').search(cr,uid,[('user_id','=',res.user_id.id)])
resource_obj = self.pool.get('resource.resource').browse(cr,uid,resource_id)[0]
d = mx.DateTime.strptime(date_start,'%Y-%m-%d %H:%M:%S')
hrs = (planned)/(occupation_rate)
work_times = self.pool.get('resource.calendar').interval_get(cr, uid, resource_obj.calendar_id.id or False, d, hrs or 0.0, resource_obj.id)
result['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
result['remaining_hours'] = planned-effective
return {'value':result}
def _default_project(self, cr, uid, context={}):
if 'project_id' in context and context['project_id']:
@ -282,6 +323,13 @@ class task(osv.osv):
default['work_ids'] = []
return super(task, self).copy_data(cr, uid, id, default, context)
def _check_date(self,cr,uid,ids):
for res in self.browse(cr,uid,ids):
if res.date_start and res.date_end:
if res.date_start > res.date_end:
return False
return True
_columns = {
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the task without removing it."),
'name': fields.char('Task Summary', size=128, required=True),
@ -293,15 +341,16 @@ class task(osv.osv):
help='If the task is created the state \'Draft\'.\n If the task is started, the state becomes \'In Progress\'.\n If review is needed the task is in \'Pending\' state.\
\n If the task is over, the states is set to \'Done\'.'),
'date_start': fields.datetime('Starting Date'),
'date_end': fields.datetime('Ending Date'),
'date_deadline': fields.datetime('Deadline'),
'date_close': fields.datetime('Date Closed', readonly=True),
'project_id': fields.many2one('project.project', 'Project', ondelete='cascade',
help="If you have [?] in the project name, it means there are no analytic account linked to this project."),
'parent_id': fields.many2one('project.task', 'Parent Task'),
'child_ids': fields.one2many('project.task', 'parent_id', 'Delegated Tasks'),
'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'),
'child_ids': fields.many2many('project.task', 'project_task_child_rel', 'task_id', 'child_id', 'Delegated Tasks'),
'history': fields.function(_history_get, method=True, string="Task Details", type="text"),
'notes': fields.text('Notes'),
'occupation_rate': fields.float('Occupation Rate', help='The occupation rate fields indicates how much of his time a user is working on a task. A 100% occupation rate means the user works full time on the tasks. The ending date of a task is computed like this: Starting Date + Duration / Occupation Rate.'),
'planned_hours': fields.float('Planned Hours', required=True, help='Estimated time to do the task, usually set by the project manager when the task is in draft state.'),
'effective_hours': fields.function(_hours_get, method=True, string='Hours Spent', multi='hours', store=True, help="Computed using the sum of the task work done."),
'remaining_hours': fields.float('Remaining Hours', digits=(16,4), help="Total remaining time, can be re-estimated periodically by the assignee of the task."),
@ -325,6 +374,7 @@ class task(osv.osv):
'active': lambda *a: True,
'date_start': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'project_id': _default_project,
'occupation_rate':lambda *a: '1',
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
}
_order = "sequence, priority, date_deadline, id"
@ -366,24 +416,24 @@ class task(osv.osv):
for task in tasks:
project = task.project_id
if project:
if project.warn_manager and project.manager and (project.manager.id != uid):
if project.warn_manager and project.user_id and (project.user_id.id != uid):
request.create(cr, uid, {
'name': _("Task '%s' closed") % task.name,
'state': 'waiting',
'act_from': uid,
'act_to': project.manager.id,
'act_to': project.user_id.id,
'ref_partner_id': task.partner_id.id,
'ref_doc1': 'project.task,%d'% (task.id,),
'ref_doc2': 'project.project,%d'% (project.id,),
})
self.write(cr, uid, [task.id], {'state': 'done', 'date_close':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
if task.parent_id and task.parent_id.state in ('pending','draft'):
if task.parent_ids and task.parent_ids.state in ('pending','draft'):
reopen = True
for child in task.parent_id.child_ids:
for child in task.parent_ids.child_ids:
if child.id != task.id and child.state not in ('done','cancelled'):
reopen = False
if reopen:
self.do_reopen(cr, uid, [task.parent_id.id])
self.do_reopen(cr, uid, [task.parent_ids.id])
return True
def do_reopen(self, cr, uid, ids, *args):
@ -391,12 +441,12 @@ class task(osv.osv):
tasks = self.browse(cr, uid, ids)
for task in tasks:
project = task.project_id
if project and project.warn_manager and project.manager.id and (project.manager.id != uid):
if project and project.warn_manager and project.user_id.id and (project.user_id.id != uid):
request.create(cr, uid, {
'name': _("Task '%s' set in progress") % task.name,
'state': 'waiting',
'act_from': uid,
'act_to': project.manager.id,
'act_to': project.user_id.id,
'ref_partner_id': task.partner_id.id,
'ref_doc1': 'project.task,%d' % task.id,
'ref_doc2': 'project.project,%d' % project.id,
@ -410,12 +460,12 @@ class task(osv.osv):
tasks = self.browse(cr, uid, ids)
for task in tasks:
project = task.project_id
if project.warn_manager and project.manager and (project.manager.id != uid):
if project.warn_manager and project.user_id and (project.user_id.id != uid):
request.create(cr, uid, {
'name': _("Task '%s' cancelled") % task.name,
'state': 'waiting',
'act_from': uid,
'act_to': project.manager.id,
'act_to': project.user_id.id,
'ref_partner_id': task.partner_id.id,
'ref_doc1': 'project.task,%d' % task.id,
'ref_doc2': 'project.project,%d' % project.id,

View File

@ -30,11 +30,11 @@
<field name="arch" type="xml">
<form string="Project">
<group colspan="6" col="6">
<field name="name" select="1"/>
<field name="parent_id"/>
<field name="manager" select="1"/>
<field name="name" string="Project Name" select="1"/>
<field name="parent_id" string="Parent Project"/>
<field name="user_id" string="Project Manager" select="1"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="date"/>
<field name="progress_rate" widget="progressbar"/>
</group>
<notebook colspan="4">
@ -42,14 +42,14 @@
<field name="warn_manager"/>
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
<field name="priority"/>
<field name="timesheet_id"/>
<field name="resource_calendar_id"/>
<field name="active" select="2"/>
<field name="planned_hours" widget="float_time"/>
<field name="effective_hours" widget="float_time"/>
<field name="category_id" select="2" context="{'default_name':name}"/>
<newline/>
<separator colspan="4" string="Project's members"/>
<field colspan="4" name="members" nolabel="1"/>
<field colspan="4" name="resource_ids" nolabel="1"/>
<group col="9" colspan="8">
<field name="state" select="1"/>
<button name="set_template" string="Set as Template" type="object" states="open" icon="gtk-convert"/>
@ -89,7 +89,7 @@
<!-- <tree string="Tasks">-->
<field name="sequence"/>
<field name="name"/>
<field name="user_id"/>
<field name="user_id" string="Project Manager"/>
<field name="date_deadline"/>
<field name="planned_hours" sum="Planned" widget="float_time"/>
<field name="delay_hours" sum="Delay" widget="float_time"/>
@ -103,7 +103,7 @@
<field nolabel="1" name="allowed_task_type" colspan="4" groups="base.group_extended"/>
</page>
<page string="Notes">
<field colspan="4" name="notes" nolabel="1"/>
<field colspan="4" name="description" nolabel="1"/>
</page>
</notebook>
<newline/>
@ -117,9 +117,9 @@
<field name="priority" eval="5"/>
<field name="arch" type="xml">
<tree string="Projects">
<field name="complete_name"/>
<field name="manager"/>
<field name="partner_id"/>
<field name="complete_name" string="Project Name"/>
<field name="user_id" string="Project Manager"/>
<field name="partner_id" string="Partner"/>
<field name="effective_hours" widget="float_time"/>
<field name="total_hours" widget="float_time"/>
<field name="state"/>
@ -134,11 +134,11 @@
<field name="arch" type="xml">
<search string="Search Project">
<group col='8' colspan='4'>
<filter icon="terp-project" string="My Projects" domain="[('manager', '=', uid)]" help="My Projects"/>
<filter icon="terp-project" string="My Projects" domain="[('user_id', '=', uid)]" help="My Projects"/>
<filter icon="terp-project" string="Templates" domain="[('state','=','template')]" help="Template Projects"/>
<separator orientation="vertical"/>
<field name="name" select='1'/>
<field name="partner_id" select='1'/>
<field name="name" string="Project Name" select='1'/>
<field name="partner_id" string="Partner" select='1'/>
<field name="state" select="1"/>
</group>
</search>
@ -149,12 +149,12 @@
<field name="name">project.project.tree</field>
<field name="model">project.project</field>
<field name="type">tree</field>
<field name="field_parent">child_id</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Projects">
<field name="name"/>
<field name="manager"/>
<field name="partner_id"/>
<field name="name" string="Project Name"/>
<field name="user_id" string="Project Manager"/>
<field name="partner_id" string="Partner"/>
<field name="planned_hours" widget="float_time"/>
<field name="total_hours" widget="float_time"/>
<field name="effective_hours" widget="float_time"/>
@ -218,11 +218,11 @@
<field name="name">project.project.tree</field>
<field name="model">project.project</field>
<field name="type">tree</field>
<field name="field_parent">child_id</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="My projects">
<field name="name"/>
<field name="partner_id"/>
<field name="name" string="Project Name"/>
<field name="partner_id" string="Partner"/>
<field name="planned_hours" widget="float_time"/>
<field name="effective_hours" widget="float_time"/>
<field name="progress_rate" widget="progressbar"/>
@ -283,7 +283,10 @@
<field name="name" select="1"/>
<field name="project_id" required="1" select="1"/>
<field name="total_hours" widget="float_time"/>
<field name="date_start"/>
<field name="date_deadline" select="2"/>
<field name="occupation_rate"/>
<field name="date_end"/>
<field name="user_id" select="1"/>
<field name="progress" widget="progressbar"/>
</group>
@ -294,7 +297,7 @@
name="planned_hours"
widget="float_time"
attrs="{'readonly':[('state','!=','draft')]}"
on_change="onchange_planned(planned_hours,effective_hours)"/>
on_change="onchange_planned(planned_hours,effective_hours,date_start,occupation_rate)"/>
<field name="remaining_hours" select="2" widget="float_time" attrs="{'readonly':[('state','!=','draft')]}" colspan="2"/>
<button name="%(action_config_compute_remaining)d" string="Review" type="action" colspan="1" target="new" states="open,pending" icon="gtk-edit"/>
</group>
@ -325,8 +328,9 @@
</group>
</page>
<page groups="base.group_extended" string="Delegations">
<field name="parent_id"/>
<newline/>
<separator string="Parent Tasks" colspan="4"/>
<field colspan="4" height="150" name="parent_ids" nolabel="1"/>
<separator string="Delegated tasks" colspan="4"/>
<field colspan="4" height="150" name="child_ids" nolabel="1" attrs="{'readonly':[('state','!=','draft')]}">
<tree string="Delegated tasks">
<field name="name"/>
@ -340,6 +344,7 @@
</field>
<field colspan="4" name="history" nolabel="1"/>
</page>
<page groups="base.group_extended" string="Extra Info" attrs="{'readonly':[('state','=','done')]}">
<group colspan="2" col="2">
<separator string="Planning" colspan="2"/>
@ -575,7 +580,7 @@
</record>
<menuitem action="open_task_type_form" id="menu_task_types" parent="project.menu_definitions"/>
<act_window domain="[('manager', '=', active_id)]" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/>
<act_window domain="[('user_id', '=', active_id)]" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/>
<act_window
domain="[('project_id', '=', active_id)]"

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -58,7 +58,7 @@ def _compute_tasks(cr, uid, task_list, date_begin):
# Compute the closing date of the task
tasks[task.id] = []
res = pooler.get_pool(cr.dbname).get('hr.timesheet.group').interval_get(cr, uid, task.project_id.timesheet_id.id, date_start, task.remaining_hours)
res = pooler.get_pool(cr.dbname).get('resource.calendar').interval_get(cr, uid, task.project_id.resource_calendar_id.id, date_start, task.remaining_hours)
for (d1,d2) in res:
tasks[task.id].append((d1, d2, task.name, task.user_id.login))
date_close = tasks[task.id][-1][1]
@ -72,7 +72,7 @@ def _compute_tasks(cr, uid, task_list, date_begin):
def _compute_project(cr, uid, project, date_begin):
tasks, last_date = _compute_tasks(cr, uid, project.tasks, date_begin)
for proj in project.child_id:
for proj in project.child_ids:
d0 = DateTime.strptime(proj.date_start,'%Y-%m-%d')
if d0 > last_date:
last_date = d0

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import project
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name" : "Long Term Project Management",
"version": "1.1",
"author" : "Tiny",
"website" : "http://www.openerp.com",
"category" : "Generic Modules/Projects & Services",
"depends" : ["project"],
"description": """Long Term Project management module that track planning, scheduling, resources allocation.
""",
"init_xml" : [],
"demo_xml" : [#"project_demo.xml"
],
"update_xml": [
"project_view.xml",
],
'installable': True,
'active': False,
'certificate': None,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from lxml import etree
from mx import DateTime
from mx.DateTime import now
import time
from tools.translate import _
from osv import fields, osv
from tools.translate import _
class project_phase(osv.osv):
_name = "project.phase"
_description = "Project Phase"
def _check_recursion(self,cr,uid,ids):
obj_self = self.browse(cr, uid, ids[0])
prev_ids = obj_self.previous_phase_ids
next_ids = obj_self.next_phase_ids
#it should nither be in prev_ids nor in next_ids
if (obj_self in prev_ids) or (obj_self in next_ids):
return False
ids = [id for id in prev_ids if id in next_ids]
#both prev_ids and next_ids must be unique
if ids:
return False
#unrelated project
prev_ids = [rec.id for rec in prev_ids]
next_ids = [rec.id for rec in next_ids]
#iter prev_ids
while prev_ids:
cr.execute('select distinct prv_phase_id from project_phase_previous_rel where phase_id in ('+','.join(map(str, prev_ids))+')')
prv_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall()))
if obj_self.id in prv_phase_ids:
return False
ids = [id for id in prv_phase_ids if id in next_ids]
if ids:
return False
prev_ids = prv_phase_ids
#iter next_ids
while next_ids:
cr.execute('select distinct next_phase_id from project_phase_next_rel where phase_id in ('+','.join(map(str, next_ids))+')')
next_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall()))
if obj_self.id in next_phase_ids:
return False
ids = [id for id in next_phase_ids if id in prev_ids]
if ids:
return False
next_ids = next_phase_ids
return True
_columns = {
'name': fields.char("Phase Name", size=64, required=True),
'date_start': fields.datetime('Starting Date'),
'date_end': fields.datetime('End Date'),
'constraint_date_start': fields.datetime('Constraint Starting Date'),
'constraint_date_end': fields.datetime('Constraint End Date'),
'project_id': fields.many2one('project.project', 'Project', required=True),
'next_phase_ids': fields.many2many('project.phase', 'project_phase_next_rel', 'phase_id', 'next_phase_id', 'Next Phases'),
'previous_phase_ids': fields.many2many('project.phase', 'project_phase_previous_rel', 'phase_id', 'prv_phase_id', 'Previous Phases'),
'duration': fields.float('Duration'),
'product_uom': fields.many2one('product.uom', 'Duration UoM', help="UoM (Unit of Measure) is the unit of measurement for Duration"),
'task_ids': fields.one2many('project.task', 'phase_id', "Project Tasks"),
'resource_ids': fields.one2many('project.resource.allocation', 'phase_id', "Project Resources"),
}
_defaults = {
'date_start': lambda *a: time.strftime('%Y-%m-%d'),
}
_order = "name"
_constraints = [
(_check_recursion,'Error ! Loops In Phases Not Allowed',['next_phase_ids','previous_phase_ids'])
]
project_phase()
class project_resource_allocation(osv.osv):
_name = 'project.resource.allocation'
_description = 'Project Resource Allocation'
_columns = {
'resource_id': fields.many2one('resource.resource', 'Resource', required=True),
'phase_id': fields.many2one('project.phase', 'Project Phase', required=True),
'useability': fields.float('Useability', help="Useability of this ressource for this project phase in percentage (=50%)"),
}
_defaults = {
'useability': lambda *a: 100,
}
project_resource_allocation()
class project(osv.osv):
_inherit = "project.project"
_columns = {
'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases")
}
project()
class task(osv.osv):
_inherit = "project.task"
_columns = {
'phase_id': fields.many2one('project.phase', 'Project Phase')
}
def _check_dates(self, cr, uid, ids):
leave = self.read(cr, uid, ids[0],['date_start','date_end'])
if leave['date_start'] and leave['date_end']:
if leave['date_start'] > leave['date_end']:
return False
return True
_constraints = [
(_check_dates, 'Error! task start-date must be lower then task end-date.', ['date_start', 'date_end'])
]
task()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!--
Requests Links
-->
<record id="req_link_project" model="res.request.link">
<field name="name">Project</field>
<field name="object">project.project</field>
</record>
<record id="req_link_task" model="res.request.link">
<field name="name">Project task</field>
<field name="object">project.task</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record forcecreate="True" id="ir_cron_scheduler_action" model="ir.cron">
<field name="name">Calculate Project Task Length Scheduler</field>
<field eval="False" name="active"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
<field eval="True" name="active"/>
<field eval="'project.project'" name="model"/>
<field eval="'compute_date'" name="function"/>
<!--<field model="project.project" search="[]" name="args"/>
<field eval="select id from project.project" name="args"/>-->
</record>
</data>
</openerp>

View File

@ -0,0 +1,252 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!--
Resource: project.project
-->
<record id="base.main_company" model="res.company">
<field name="project_time_mode_id" ref="product.uom_hour"></field>
</record>
<record id="project_tt_analysis" model="project.task.type">
<field name="name">Analysis</field>
</record>
<record id="project_tt_feature" model="project.task.type">
<field name="name">New Feature</field>
</record>
<record id="project_tt_quote" model="project.task.type">
<field name="name">Quotation</field>
</record>
<record id="project_tt_bug" model="project.task.type">
<field name="name">Bug</field>
</record>
<record id="project_project_9" model="project.project">
<field name="warn_manager">1</field>
<field name="name">Open ERP Integration</field>
<field name="manager" ref="base.user_root"/>
</record>
<record id="project_project_21" model="project.project">
<field name="warn_manager">1</field>
<field name="priority">10</field>
<field name="parent_id" ref="project_project_9"/>
<field name="name">Study + Prototype</field>
<field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/>
<field name="manager" ref="base.user_root"/>
</record>
<record id="project_project_22" model="project.project">
<field name="priority">20</field>
<field name="parent_id" ref="project_project_9"/>
<field name="name">Specific Developements</field>
<field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/>
<field name="manager" ref="base.user_root"/>
</record>
<record id="project_project_23" model="project.project">
<field name="priority">30</field>
<field name="parent_id" ref="project_project_9"/>
<field name="name">Install, data import, configuration</field>
<field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/>
<field name="manager" ref="base.user_root"/>
</record>
<record id="project_task_116" model="project.task">
<field name="planned_hours">38.0</field>
<field name="remaining_hours">38.0</field>
<field name="type" ref="project_tt_feature"/>
<field name="user_id" ref="base.user_root"/>
<field name="project_id" ref="project_project_22"/>
<field name="description">BoM, After sales returns, interventions. Tracability.</field>
<field name="name">Specific adaptation to MRP</field>
</record>
<record id="project_task_130" model="project.task">
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field name="type" ref="project_tt_feature"/>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_23"/>
<field name="name">Data importation + Doc</field>
</record>
<record id="project_task_131" model="project.task">
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field name="type" ref="project_tt_feature"/>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_23"/>
<field name="name">Modifications asked by the customer.</field>
</record>
<record id="project_task_184" model="project.task">
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field name="type" ref="project_tt_feature"/>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="priority">0</field>
<field name="project_id" ref="project_project_21"/>
<field name="name">Customer analysis + Architecture</field>
</record>
<record id="project_task_186" model="project.task">
<field name="sequence">15</field>
<field name="planned_hours">8.0</field>
<field name="remaining_hours">8.0</field>
<field name="type" ref="project_tt_feature"/>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_21"/>
<field name="name">Internal testing + Software Install</field>
<field name="date_deadline">2008-06-06</field>
</record>
<record id="project_task_188" model="project.task">
<field name="sequence">17</field>
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field name="type" ref="project_tt_feature"/>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="priority">2</field>
<field name="state">open</field>
<field name="project_id" ref="project_project_21"/>
<field name="name">Analysis, Data Importation</field>
</record>
<record id="project_task_189" model="project.task">
<field name="sequence">20</field>
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field name="state">open</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_23"/>
<field name="name">Parameters</field>
</record>
<record id="project_task_190" model="project.task">
<field name="sequence">20</field>
<field name="planned_hours">32.0</field>
<field name="remaining_hours">32.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="state">open</field>
<field name="project_id" ref="project_project_21"/>
<field name="name">Start of the doc redaction + MRP</field>
</record>
<record id="project_task_192" model="project.task">
<field name="sequence">25</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_21"/>
<field name="state">done</field>
<field name="name">MRP Tests</field>
</record>
<record id="project_task_193" model="project.task">
<field name="sequence">29</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field name="user_id" ref="base.user_root"/>
<field name="project_id" ref="project_project_21"/>
<field name="name">MRP; functionnal layer</field>
<field name="state">done</field>
<field eval="time.strftime('%Y-%m-%d 12:12')" name="date_close"/>
</record>
<record id="project_task_194" model="project.task">
<field name="sequence">30</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Products Adaptation</field>
</record>
<record id="project_task_195" model="project.task">
<field name="sequence">30</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_23"/>
<field name="name">Install + Super User Training</field>
</record>
<record id="project_task_196" model="project.task">
<field name="sequence">30</field>
<field name="planned_hours">32.0</field>
<field name="remaining_hours">32.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Customer docs</field>
</record>
<record id="project_task_197" model="project.task">
<field name="sequence">30</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_21"/>
<field name="name">Development of the presentation layer</field>
</record>
<record id="project_task_198" model="project.task">
<field name="sequence">40</field>
<field name="planned_hours">32.0</field>
<field name="remaining_hours">32.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_21"/>
<field name="name">Free Time</field>
</record>
<record id="project_task_199" model="project.task">
<field name="sequence">40</field>
<field name="planned_hours">50.0</field>
<field name="remaining_hours">50.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Specific tests</field>
</record>
<record id="project_task_200" model="project.task">
<field name="sequence">40</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Sale module</field>
</record>
<record id="project_task_201" model="project.task">
<field name="sequence">40</field>
<field name="planned_hours">32.0</field>
<field name="remaining_hours">32.0</field>
<field name="user_id" ref="base.user_root"/>
<field name="project_id" ref="project_project_23"/>
<field name="state">open</field>
<field name="name">In house training</field>
<field name="date_deadline">2007-06-06</field>
</record>
<record id="project_task_202" model="project.task">
<field name="sequence">50</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field name="user_id" ref="base.user_root"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Validation + latest modifications.</field>
</record>
<record id="project_task_203" model="project.task">
<field name="sequence">50</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Adaptations buy module</field>
</record>
<record id="project_task_204" model="project.task">
<field name="sequence">60</field>
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_21"/>
<field name="name">Presentation of the software.</field>
</record>
<record id="project_task_205" model="project.task">
<field name="sequence">60</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Adaptations Stock module</field>
</record>
<record id="project_task_206" model="project.task">
<field name="sequence">70</field>
<field name="planned_hours">24.0</field>
<field name="remaining_hours">24.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
<field name="name">Latest in house tests</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<report auto="False" id="report_project_task_gantt" model="project.task" name="project.tasks.gantt" string="Gantt Representation"/>
<report auto="False" id="report_project_project_gantt" model="project.project" name="project.project.gantt" string="Gantt Representation"/>
</data>
</openerp>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_project_resource_allocation_form" model="ir.ui.view">
<field name="name">project.resource.allocation.form</field>
<field name="model">project.resource.allocation</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Project Resource Allocation">
<field name="resource_id" select="1"/>
<field name="phase_id"/>
<field name="useability"/>
</form>
</field>
</record>
<record id="view_project_resource_allocation_list" model="ir.ui.view">
<field name="name">project.resource.allocation.list</field>
<field name="model">project.resource.allocation</field>
<field name="type">tree</field>
<field name="priority" eval="5"/>
<field name="arch" type="xml">
<tree string="Project Resource Allocation">
<field name="resource_id"/>
<field name="phase_id"/>
<field name="useability"/>
</tree>
</field>
</record>
<record id="view_project_phase_form" model="ir.ui.view">
<field name="name">project.phase.form</field>
<field name="model">project.phase</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Project Phase">
<group colspan="6" col="6">
<field name="name" select="1"/>
<field name="project_id"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="constraint_date_start"/>
<field name="constraint_date_end"/>
<field name="duration"/>
<field name="product_uom"/>
</group>
<notebook colspan="4">
<page string="Task Detail">
<separator colspan="4" string="Project's Tasks"/>
<field colspan="4" name="task_ids" nolabel="1"/>
</page>
<page string="Resource Allocation Detail">
<separator colspan="4" string="Resource Allocation"/>
<field colspan="4" name="resource_ids" nolabel="1"/>
</page>
<page string="Other Info">
<separator colspan="4" string="Next Phases"/>
<field colspan="4" name="next_phase_ids" nolabel="1"/>
<separator colspan="4" string="Previous Phases"/>
<field colspan="4" name="previous_phase_ids" nolabel="1"/>
</page>
</notebook>
<newline/>
</form>
</field>
</record>
<record id="view_project_phase_list" model="ir.ui.view">
<field name="name">project.phase.list</field>
<field name="model">project.phase</field>
<field name="type">tree</field>
<field name="priority" eval="5"/>
<field name="arch" type="xml">
<tree string="Project Phases">
<field name="name"/>
<field name="project_id"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="duration"/>
<field name="product_uom"/>
</tree>
</field>
</record>
<record id="act_project_phase" model="ir.actions.act_window">
<field name="name">Project phases</field>
<field name="res_model">project.phase</field>
<field name="view_type">form</field>
</record>
<act_window
id="project_phase_task_list"
name="Related Tasks"
res_model="project.task"
src_model="project.phase"
view_mode="tree,form"
domain="[('phase_id','=',active_id)]"/>
<menuitem id="project.menu_all_project" parent="project.menu_main" name="Projects"/>
<menuitem action="act_project_phase" id="menu_project_phase" parent="project.menu_all_project"/>
</data>
</openerp>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard id="wizard_close_task" menu="False" model="project.task" name="project.task.close" string="Close Task"/>
<wizard id="wizard_delegate_task" menu="False" model="project.task" name="project.task.delegate" string="Delegate Task"/>
<wizard id="wizard_attachment_task" model="project.task" name="project.task.attachment" string="All Attachments"/>
</data>
</openerp>

View File

@ -314,7 +314,7 @@ Business Days - (Time Allocation of Tasks + Time Allocation without Tasks + Holi
WHERE holidays.employee_id IN
(
SELECT emp.id
FROM hr_employee emp WHERE emp.user_id = users.id
FROM hr_employee emp, resource_resource res WHERE emp.resource_id = res.id and res.user_id = users.id
)
AND holidays.state IN ('validate')
AND holidays.type = 'remove'

26
addons/resource/__init__.py Executable file
View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import resource
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

49
addons/resource/__terp__.py Executable file
View File

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name" : "Resource",
"version" : "1.1",
"author" : "Tiny",
"category" : "Generic Modules/Projects",
"website" : "http://www.openerp.com",
"description": """
Module for resource management. You can manage:
* Leave/Holidays or Days off of the company
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['base', 'process'],
'init_xml': [],
'update_xml': [
#'security/resource_security.xml',
# 'security/ir.model.access.csv',
'resource_view.xml',
],
'demo_xml': [#'resource_demo.xml'
],
'installable': True,
'active': False,
'certificate': None,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

90
addons/resource/hr_demo.xml Executable file
View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Example employee -->
<record id="timesheet_group1" model="resource.calendar">
<field name="name">38 Hours/Week</field>
</record>
<record id="employee1" model="hr.employee">
<field name="name">Fabien Pinckaers</field>
<!--<field name="regime">45</field>-->
<field name="user_id" ref="base.user_root"/>
<!--<field name="holiday_max">25</field>-->
</record>
<record model="resource.calendar.week">
<field name="name">Monday morning</field>
<field name="dayofweek">0</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Monday evening</field>
<field name="dayofweek">0</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Tuesday morning</field>
<field name="dayofweek">1</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Tuesday evening</field>
<field name="dayofweek">1</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Wednesday morning</field>
<field name="dayofweek">2</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Wednesday evening</field>
<field name="dayofweek">2</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Thursday morning</field>
<field name="dayofweek">3</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Thursday evening</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="dayofweek">3</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Friday morning</field>
<field name="dayofweek">4</field>
<field name="hour_from">08</field>
<field name="hour_to">12</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
<record model="resource.calendar.week">
<field name="name">Friday evening</field>
<field name="dayofweek">4</field>
<field name="hour_from">13</field>
<field name="hour_to">18</field>
<field name="calendar_id" ref="timesheet_group1"/>
</record>
</data>
</openerp>

153
addons/resource/hr_department.py Executable file
View File

@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields,osv
import tools
class hr_department(osv.osv):
_name = "hr.department"
_columns = {
'name': fields.char('Department Name', size=64, required=True),
'company_id': fields.many2one('res.company', 'Company', select=True, required=True),
'parent_id': fields.many2one('hr.department', 'Parent Department', select=True),
'child_ids': fields.one2many('hr.department', 'parent_id', 'Child Departments'),
'note': fields.text('Note'),
'manager_id': fields.many2one('res.users', 'Manager', required=True),
'member_ids': fields.many2many('res.users', 'hr_department_user_rel', 'department_id', 'user_id', 'Members'),
}
def _get_members(self,cr, uid, context={}):
mids = self.search(cr, uid, [('manager_id','=',uid)])
result = {uid:1}
for m in self.browse(cr, uid, mids, context):
for user in m.member_ids:
result[user.id] = 1
return result.keys()
def _check_recursion(self, cr, uid, ids):
level = 100
while len(ids):
cr.execute('select distinct parent_id from hr_department where id in ('+','.join(map(str, ids))+')')
ids = filter(None, map(lambda x:x[0], cr.fetchall()))
if not level:
return False
level -= 1
return True
_constraints = [
(_check_recursion, 'Error! You can not create recursive departments.', ['parent_id'])
]
hr_department()
class ir_action_window(osv.osv):
_inherit = 'ir.actions.act_window'
def read(self, cr, uid, ids, fields=None, context=None,
load='_classic_read'):
select = ids
if isinstance(ids, (int, long)):
select = [ids]
res = super(ir_action_window, self).read(cr, uid, select, fields=fields,
context=context, load=load)
for r in res:
mystring = 'department_users_get()'
if mystring in (r.get('domain', '[]') or ''):
r['domain'] = r['domain'].replace(mystring, str(
self.pool.get('hr.department')._get_members(cr, uid)))
if isinstance(ids, (int, long)):
if res:
return res[0]
else:
return False
return res
ir_action_window()
class res_users(osv.osv):
_inherit = 'res.users'
_description = 'res.users'
def _parent_compute(self, cr, uid, ids, name, args, context={}):
result = {}
obj_dept = self.pool.get('hr.department')
for user_id in ids:
ids_dept = obj_dept.search(cr, uid, [('member_ids', 'in', [user_id])])
parent_ids = []
if ids_dept:
data_dept = obj_dept.read(cr, uid, ids_dept, ['manager_id'])
parent_ids = map(lambda x: x['manager_id'][0], data_dept)
result[user_id] = parent_ids
return result
def _parent_search(self, cr, uid, obj, name, args):
parent = []
for arg in args:
if arg[0] == 'parent_id':
parent = arg[2]
child_ids = self._child_compute(cr, uid, parent,name, args, {})
if not child_ids:
return [('id', 'in', [0])]
return [('id', 'in', child_ids.get(uid,[]))]
def _child_compute(self, cr, uid, ids, name, args, context={}):
obj_dept = self.pool.get('hr.department')
obj_user = self.pool.get('res.users')
result = {}
for manager_id in ids:
child_ids = []
mgnt_dept_ids = obj_dept.search(cr, uid, [('manager_id', '=', manager_id)])
ids_dept = obj_dept.search(cr, uid, [('id', 'child_of', mgnt_dept_ids)])
if ids_dept:
data_dept = obj_dept.read(cr, uid, ids_dept, ['member_ids'])
childs = map(lambda x: x['member_ids'], data_dept)
childs = tools.flatten(childs)
childs = obj_user.search(cr, uid, [('id','in',childs),('active','=',True)])
if manager_id in childs:
childs.remove(manager_id)
child_ids.extend(tools.flatten(childs))
set = {}
map(set.__setitem__, child_ids, [])
child_ids = set.keys()
else:
child_ids = []
result[manager_id] = child_ids
return result
def _child_search(self, cr, uid, obj, name, args):
parent = []
for arg in args:
if arg[0] == 'child_ids':
parent = arg[2]
child_ids = self._child_compute(cr, uid, parent,name, args, {})
if not child_ids:
return [('id', 'in', [0])]
return [('id', 'in', child_ids.get(uid,[]))]
_columns = {
'parent_id': fields.function(_parent_compute, relation='res.users',fnct_search=_parent_search, method=True, string="Managers", type='many2many'),
'child_ids': fields.function(_child_compute, relation='res.users', fnct_search=_child_search,method=True, string="Subordinates", type='many2many'),
}
res_users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="dep_management" model="hr.department">
<field name="name">Management</field>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
</record>
<record id="dep_administration" model="hr.department">
<field name="name">Administration</field>
<field name="parent_id" ref="dep_management"/>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
</record>
<record id="dep_technical" model="hr.department">
<field name="name">Technical department</field>
<field name="parent_id" ref="dep_management"/>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
</record>
<record id="dep_it" model="hr.department">
<field name="name">IT</field>
<field name="parent_id" ref="dep_technical"/>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
</record>
<record id="dep_marketing" model="hr.department">
<field name="name">Marketing</field>
<field name="parent_id" ref="dep_management"/>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
</record>
<record id="dep_sales" model="hr.department">
<field name="name">Sales</field>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
<field name="parent_id" ref="dep_management"/>
</record>
<record id="dep_sales_europe" model="hr.department">
<field name="name">Sales Europe</field>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
<field name="parent_id" ref="dep_sales"/>
</record>
<record id="dep_sales_america" model="hr.department">
<field name="name">Sales America</field>
<field name="company_id" ref="base.main_company"/>
<field name="manager_id" ref="base.user_root"/>
<field name="parent_id" ref="dep_sales"/>
</record>
</data>
</openerp>

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!--
======================
department
======================
-->
<record id="view_department_form" model="ir.ui.view">
<field name="name">hr.department.form</field>
<field name="model">hr.department</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="department">
<field colspan="4" name="name" select="1"/>
<field name="company_id" select="1" widget="selection" groups="base.group_multi_company"/>
<field name="parent_id" select="2"/>
<field colspan="4" name="manager_id" select="1"/>
<notebook colspan="4" >
<page string="Members">
<field colspan="4" name="member_ids" nolabel="1"/>
</page>
<page string="Notes">
<field colspan="4" name="note" nolabel="1"/>
</page>
</notebook>
</form>
</field>
</record>
<record id="view_department_tree" model="ir.ui.view">
<field name="name">hr.department.tree</field>
<field name="model">hr.department</field>
<field name="type">tree</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Companies">
<field name="name"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="manager_id"/>
</tree>
</field>
</record>
<record id="open_module_tree_department_tree" model="ir.actions.act_window">
<field name="name">Departments</field>
<field name="res_model">hr.department</field>
<field name="view_type">tree</field>
<field name="domain">[('parent_id','=',False)]</field>
</record>
<menuitem action="open_module_tree_department_tree" id="menu_department_tree" parent="base.menu_users"/>
<record id="open_module_tree_department" model="ir.actions.act_window">
<field name="name">Departments</field>
<field name="res_model">hr.department</field>
<field name="view_type">form</field>
</record>
<menuitem action="open_module_tree_department" id="menu_department_def" parent="hr.menu_department_tree"/>
<!-- res.users inherit -->
<record model="ir.ui.view" id="view_users_form_inherit">
<field name="name">res.users.form</field>
<field name="type">form</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Departements Informations">
<separator string="Managers" colspan="4"/>
<field name="parent_id" nolabel="1" colspan="4"/>
<separator string="Subordinates" colspan="4"/>
<field name="child_ids" nolabel="1" colspan="4"/>
</page>
</notebook>
</field>
</record>
</data>
</openerp>

296
addons/resource/hr_view.xml Executable file
View File

@ -0,0 +1,296 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<menuitem icon="terp-hr" id="menu_hr_root" name="Human Resources"/>
<menuitem
id="menu_hr_reporting"
name="Reporting"
parent="hr.menu_hr_root"
sequence="40" />
<menuitem
id="menu_hr_configuration"
name="Configuration"
parent="hr.menu_hr_root"
sequence="5" groups="group_hr_manager"/>
<!--
==========
Employee
==========
-->
<record id="view_employee_form" model="ir.ui.view">
<field name="name">hr.employee.form</field>
<field name="model">hr.employee</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Employee">
<group colspan="4" col="4">
<field name="name" select="1"/>
<field name="active" select="1"/>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
<field name="user_id"/>
</group>
<notebook colspan="4">
<page string="Personal Information">
<group col="2" colspan="2">
<separator colspan="2" string="Social IDs"/>
<field name="ssnid"/>
<field name="sinid"/>
<field name="otherid"/>
</group>
<group col="2" colspan="2">
<separator string="Status" colspan="2"/>
<field name="gender"/>
<field name="marital"/>
<field name="country_id"/>
<field name="birthday"/>
</group>
<group col="2" colspan="2">
<separator string="Contact Information" colspan="2"/>
<field name="address_home_id" colspan="2"/>
<field name="address_id" colspan="2"/>
<field name="work_phone"/>
<field name="work_email" widget="email" />
<field name="work_location"/>
</group>
<group col="4" colspan="2">
<separator string="Job Information" colspan="4"/>
<field name="parent_id" select="1" colspan="4"/>
<field name="category_id" colspan="4" widget="selection"/>
</group>
</page>
<page string="Notes">
<field colspan="4" nolabel="1" name="notes"/>
</page>
</notebook>
</form>
</field>
</record>
<record id="view_employee_tree" model="ir.ui.view">
<field name="name">hr.employee.tree</field>
<field name="model">hr.employee</field>
<field name="type">tree</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Employees">
<field name="name"/>
<field name="work_phone"/>
<field name="work_email"/>
<field name="address_id"/>
<field name="parent_id"/>
</tree>
</field>
</record>
<record id="open_view_employee_tree" model="ir.actions.act_window">
<field name="name">Employees Structure</field>
<field name="res_model">hr.employee</field>
<field name="view_type">tree</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_employee_tree"/>
<field name="domain">[('parent_id','=',False)]</field>
</record>
<record id="open_view_employee_list" model="ir.actions.act_window">
<field name="name">Employees</field>
<field name="res_model">hr.employee</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False"/>
</record>
<menuitem
id="menu_open_view_employee_list"
name="Employees"
groups="group_hr_manager"
parent="hr.menu_hr_root"/>
<menuitem
action="open_view_employee_tree"
id="menu_open_view_employee_tree"
parent="menu_open_view_employee_list"/>
<record id="open_view_employee_list_my" model="ir.actions.act_window">
<field name="name">All Employees</field>
<field name="res_model">hr.employee</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
</record>
<menuitem
action="open_view_employee_list_my"
id="menu_open_view_employee_list_my"
parent="menu_open_view_employee_list"/>
<!--
=======================
Employee architecture
=======================
-->
<record id="view_partner_tree2" model="ir.ui.view">
<field name="name">hr.employee.tree</field>
<field name="model">hr.employee</field>
<field name="type">tree</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Employees">
<field name="name"/>
<field name="user_id"/>
<field name="address_id"/>
</tree>
</field>
</record>
<record id="action2" model="ir.actions.act_window">
<field name="name">Employee Hierarchy</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">hr.employee</field>
<field name="domain">[('id','in',active_ids)]</field>
<field name="view_type">tree</field>
<field name="view_id" ref="view_partner_tree2"/>
</record>
<ir_set>
<field eval="'action'" name="key"/>
<field eval="'client_action_multi'" name="key2"/>
<field eval="['hr.employee']" name="models"/>
<field name="name">Employees Hierarchy</field>
<field eval="'ir.actions.act_window,'+str(action2)" name="value"/>
<field eval="True" name="isobject"/>
<field eval="True" name="replace"/>
</ir_set>
<!--
============
Working Time
============
-->
<record id="create_group" model="ir.ui.view">
<field name="name">resource.calendar.form</field>
<field name="model">resource.calendar</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Working Time Category">
<field name="name" select="1"/>
<field name="manager" select="1"/>
<newline/>
<field colspan="4" name="week_id" nolabel="1" widget="one2many_list"/>
</form>
</field>
</record>
<record id="edit_workgroup" model="ir.actions.act_window">
<field name="name">Working Time Categories</field>
<field name="res_model">resource.calendar</field>
<field name="view_type">form</field>
<field name="view_id" eval="False"/>
</record>
<menuitem action="edit_workgroup" id="menu_edit_workgroup" parent="hr.menu_hr_configuration"/>
<record id="view_timesheet_tree" model="ir.ui.view">
<field name="name">resource.calendar.week.tree</field>
<field name="model">resource.calendar.week</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Working Time">
<field name="name"/>
<field name="dayofweek"/>
<field name="hour_from" widget="float_time"/>
<field name="hour_to" widget="float_time"/>
</tree>
</field>
</record>
<record id="view_timesheet_form" model="ir.ui.view">
<field name="name">resource.calendar.week.form</field>
<field name="model">resource.calendar.week</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Working Time">
<field colspan="4" name="name" select="1"/>
<field name="date_from"/>
<field name="dayofweek" select="1"/>
<field name="hour_from" widget="float_time"/>
<field name="hour_to" widget="float_time"/>
</form>
</field>
</record>
<!--
============
Employee Category
============
-->
<record id="view_employee_category_form" model="ir.ui.view">
<field name="name">hr.employee.category.form</field>
<field name="model">hr.employee.category</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Employee Category">
<field name="name" select="1"/>
<field name="parent_id" select="1"/>
</form>
</field>
</record>
<record id="view_employee_category_list" model="ir.ui.view">
<field name="name">hr.employee.category.list</field>
<field name="model">hr.employee.category</field>
<field name="type">tree</field>
<field eval="8" name="priority"/>
<field name="arch" type="xml">
<tree string="Employees Categories">
<field name="name"/>
<field name="parent_id"/>
</tree>
</field>
</record>
<record id="view_employee_category_tree" model="ir.ui.view">
<field name="name">hr.employee.category.tree</field>
<field name="model">hr.employee.category</field>
<field name="type">tree</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Employees Categories">
<field name="name"/>
</tree>
</field>
</record>
<record id="open_view_categ_form" model="ir.actions.act_window">
<field name="name">Categories of Employee</field>
<field name="res_model">hr.employee.category</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem action="open_view_categ_form" id="menu_view_employee_category_form" parent="hr.menu_hr_configuration"/>
<record id="open_view_categ_tree" model="ir.actions.act_window">
<field name="name">Categories structure</field>
<field name="res_model">hr.employee.category</field>
<field name="view_type">tree</field>
<field name="view_id" ref="view_employee_category_tree"/>
<field name="domain">[('parent_id','=',False)]</field>
</record>
<record id="hr_employee_normal_action_tree" model="ir.actions.act_window">
<field name="name">Employees</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">hr.employee</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('category_id','child_of',[active_id])]</field>
<field name="context">{'category_id':active_id}</field>
</record>
<record id="hr_employee_category_open" model="ir.values">
<field eval="'tree_but_open'" name="key2"/>
<field eval="'hr.employee.category'" name="model"/>
<field name="name">Employees by Categories</field>
<field eval="'ir.actions.act_window,%d'%hr_employee_normal_action_tree" name="value"/>
<field eval="True" name="object"/>
</record>
<menuitem action="open_view_categ_tree" id="menu_view_employee_category_tree" parent="hr.menu_view_employee_category_form"/>
</data>
</openerp>

191
addons/resource/resource.py Executable file
View File

@ -0,0 +1,191 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import mx.DateTime
import time
import math
from osv import fields, osv
from tools.translate import _
class resource_calendar(osv.osv):
_name = "resource.calendar"
_description = "Resource Calendar"
_columns = {
'name' : fields.char("Name", size=64, required=True),
'company_id' : fields.many2one('res.company', 'Company', required=True),
'week_id' : fields.one2many('resource.calendar.week', 'calendar_id', 'Working Time'),
'manager' : fields.many2one('res.users', 'Workgroup manager'),
}
_defaults = {
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.calendar', c)
}
def interval_min_get(self, cr, uid, id, dt_from, hours , resource=0):
dt_leave = []
if not id:
return [(dt_from-mx.DateTime.RelativeDateTime(hours=int(hours)*3), dt_from)]
if resource:
resource_leave_ids = self.pool.get('resource.calendar.leaves').search(cr,uid,[('resource_id','=',resource)])
if resource_leave_ids:
res_leaves = self.pool.get('resource.calendar.leaves').read(cr,uid,resource_leave_ids,['date_from','date_to'])
for i in range(len(res_leaves)):
dtf = mx.DateTime.strptime(res_leaves[i]['date_from'],'%Y-%m-%d %H:%M:%S')
dtt = mx.DateTime.strptime(res_leaves[i]['date_to'],'%Y-%m-%d %H:%M:%S')
leave_days = ((dtt - dtf).days) + 1
for x in range(int(leave_days)):
dt_leave.append((dtf + mx.DateTime.RelativeDateTime(days=x)).strftime('%Y-%m-%d'))
dt_leave.sort()
todo = hours
cycle = 0
result = []
maxrecur = 100
current_hour = dt_from.hour
while (todo>0) and maxrecur:
cr.execute("select hour_from,hour_to from resource_calendar_week where dayofweek='%s' and calendar_id=%s order by hour_from", (dt_from.day_of_week,id))
for (hour_from,hour_to) in cr.fetchall():
if (hour_to>current_hour) and (todo>0):
m = max(hour_from, current_hour)
if (hour_to-m)>todo:
hour_to = m+todo
d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60))
d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60))
dt1 = d1.strftime('%Y-%m-%d')
dt2 = d2.strftime('%Y-%m-%d')
for i in range(len(dt_leave)):
if dt1 == dt_leave[i]:
dt_from += mx.DateTime.RelativeDateTime(days=1)
d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60))
d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60))
dt1 = d1.strftime('%Y-%m-%d')
dt2 = d2.strftime('%Y-%m-%d')
result.append((d1, d2))
current_hour = hour_to
todo -= (hour_to - m)
dt_from += mx.DateTime.RelativeDateTime(days=1)
current_hour = 0
maxrecur -= 1
return result
def interval_get(self, cr, uid, id, dt_from, hours, resource=0, byday=True):
dt_leave = []
if not id:
return [(dt_from,dt_from+mx.DateTime.RelativeDateTime(hours=int(hours)*3))]
if resource:
resource_leave_ids = self.pool.get('resource.calendar.leaves').search(cr,uid,[('resource_id','=',resource)])
if resource_leave_ids:
res_leaves = self.pool.get('resource.calendar.leaves').read(cr,uid,resource_leave_ids,['date_from','date_to'])
for i in range(len(res_leaves)):
dtf = mx.DateTime.strptime(res_leaves[i]['date_from'],'%Y-%m-%d %H:%M:%S')
dtt = mx.DateTime.strptime(res_leaves[i]['date_to'],'%Y-%m-%d %H:%M:%S')
no = dtt - dtf
leave_days = no.days + 1
for x in range(int(leave_days)):
dt_leave.append((dtf + mx.DateTime.RelativeDateTime(days=x)).strftime('%Y-%m-%d'))
dt_leave.sort()
todo = hours
cycle = 0
result = []
maxrecur = 100
current_hour = dt_from.hour
while (todo>0) and maxrecur:
cr.execute("select hour_from,hour_to from resource_calendar_week where dayofweek='%s' and calendar_id=%s order by hour_from", (dt_from.day_of_week,id))
for (hour_from,hour_to) in cr.fetchall():
if (hour_to>current_hour) and (todo>0):
m = max(hour_from, current_hour)
if (hour_to-m)>todo:
hour_to = m+todo
d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60))
d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60))
dt1 = d1.strftime('%Y-%m-%d')
dt2 = d2.strftime('%Y-%m-%d')
for i in range(len(dt_leave)):
if dt1 == dt_leave[i]:
dt_from += mx.DateTime.RelativeDateTime(days=1)
d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60))
d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60))
dt1 = d1.strftime('%Y-%m-%d')
dt2 = d2.strftime('%Y-%m-%d')
result.append((d1, d2))
current_hour = hour_to
todo -= (hour_to - m)
dt_from += mx.DateTime.RelativeDateTime(days=1)
current_hour = 0
maxrecur -= 1
return result
resource_calendar()
class resource_calendar_week(osv.osv):
_name = "resource.calendar.week"
_description = "Work Detail"
_columns = {
'name' : fields.char("Name", size=64, required=True),
'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of week'),
'date_from' : fields.date('Starting date'),
'hour_from' : fields.float('Work from', size=8, required=True),
'hour_to' : fields.float("Work to", size=8, required=True),
'calendar_id' : fields.many2one("resource.calendar", "Resource's Calendar", required=True),
}
_order = 'dayofweek, hour_from'
resource_calendar_week()
class resource_resource(osv.osv):
_name = "resource.resource"
_description = "Resource Detail"
_columns = {
'name' : fields.char("Name", size=64, required=True ),
'code': fields.char('Code', size=16),
'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the resource record without removing it."),
'company_id' : fields.many2one('res.company', 'Company', required=True),
'resource_type': fields.selection([('user','Human'),('material','Material')], 'Resource Type', required=True),
'user_id' : fields.many2one('res.users', 'User',help='Related user name for the resource to manage its access.'),
'time_efficiency' : fields.float('Efficiency factor', size=8, help="This field depict the efficiency of the resource to complete tasks. e.g resource put alone on a phase of 5 days with 5 tasks assigned to him, will show a load of 100% for this phase by default, but if we put a efficency of 200%, then his load will only be 50%."),
'calendar_id' : fields.many2one("resource.calendar", "Working time", help="Define the schedule of resource"),
}
_defaults = {
'resource_type' : lambda *a: 'user',
'time_efficiency' : lambda *a: 1,
'active' : lambda *a: True,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.resource', c)
}
resource_resource()
class resource_calendar_leaves(osv.osv):
_name = "resource.calendar.leaves"
_description = "Leave Detail"
_columns = {
'name' : fields.char("Name", size=64),
'company_id' : fields.related('calendar_id','company_id',type='many2one',relation='res.company',string="Company",readonly=True),
'calendar_id' : fields.many2one("resource.calendar", "Working time"),
'date_from' : fields.datetime('Start Date', required=True),
'date_to' : fields.datetime('End Date', required=True),
'resource_id' : fields.many2one("resource.resource", "Resource", help="If empty, this is a generic holiday for the company. If a resource is set, the holiday/leave is only for this resource"),
}
def check_dates(self, cr, uid, ids):
leave = self.read(cr, uid, ids[0],['date_from','date_to'])
if leave['date_from'] and leave['date_to']:
if leave['date_from'] > leave['date_to']:
return False
return True
_constraints = [
(check_dates, 'Error! leave start-date must be lower then leave end-date.', ['date_from', 'date_to'])
]
resource_calendar_leaves()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

174
addons/resource/resource_view.xml Executable file
View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<menuitem icon="terp-hr" id="menu_resource_root" name="Resources Management"/>
<menuitem
id="menu_resource_reporting"
name="Reporting"
parent="menu_resource_root"
sequence="40" />
<menuitem
id="menu_resource_configuration"
name="Configuration"
parent="menu_resource_root"
sequence="5"/>
<record id="resource_calendar_form" model="ir.ui.view">
<field name="name">resource.calendar.form</field>
<field name="model">resource.calendar</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Resource Calendar">
<field name="name" select="1"/>
<field name="manager" select="1"/>
<field name="company_id" select="1"/>
<newline/>
<field colspan="4" name="week_id" nolabel="1" widget="one2many_list"/>
</form>
</field>
</record>
<record id="action_resource_calendar_form" model="ir.actions.act_window">
<field name="name">Resource Calendar</field>
<field name="res_model">resource.calendar</field>
<field name="view_type">form</field>
<field name="view_id" eval="False"/>
</record>
<menuitem string="Resource Calendar" action="action_resource_calendar_form" id="menu_resource_calendar_form" parent="menu_resource_configuration"/>
<record id="view_resource_calendar_week_tree" model="ir.ui.view">
<field name="name">resource.calendar.week.tree</field>
<field name="model">resource.calendar.week</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Working Time">
<field name="name"/>
<field name="dayofweek"/>
<field name="hour_from" widget="float_time"/>
<field name="hour_to" widget="float_time"/>
</tree>
</field>
</record>
<record id="view_resource_calendar_week_form" model="ir.ui.view">
<field name="name">resource.calendar.week.form</field>
<field name="model">resource.calendar.week</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Working Time">
<field colspan="4" name="name" select="1"/>
<field name="date_from"/>
<field name="dayofweek" select="1"/>
<field name="hour_from" widget="float_time"/>
<field name="hour_to" widget="float_time"/>
</form>
</field>
</record>
<record id="view_resource_calendar" model="ir.ui.view">
<field name="name">resource.calendar.leaves.calendar</field>
<field name="model">resource.calendar.leaves</field>
<field name="type">calendar</field>
<field name="arch" type="xml">
<calendar color="resource_id" date_start="date_from" string="Resource">
<field name="name"/>
</calendar>
</field>
</record>
<act_window
id="resource_calendar_closing_days"
name="Closing Days"
res_model="resource.calendar.leaves"
src_model="resource.calendar"
view_mode="calendar,tree,form"
domain="[('calendar_id','=',active_id), ('resource_id','=',False)]"/>
<act_window
id="resource_calendar_resources_leaves"
name="Resources Leaves"
res_model="resource.calendar.leaves"
src_model="resource.calendar"
view_mode="calendar,tree,form"
domain="[('calendar_id','=',active_id), ('resource_id','!=',False)]"/>
<record id="resource_resource_form" model="ir.ui.view">
<field name="name">resource.resource.form</field>
<field name="model">resource.resource</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Resource">
<field name="name" />
<field name="active"/>
<field name="company_id" />
<field name="calendar_id" />
<field name="resource_type" />
<field name="user_id" attrs="{'required':[('resource_type','=','user')]}"/>
<field name="time_efficiency" />
</form>
</field>
</record>
<record id="resource_resource_tree" model="ir.ui.view">
<field name="name">resource.resource.tree</field>
<field name="model">resource.resource</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Resource">
<field name="name" />
<field name="company_id" />
<field name="calendar_id" />
<field name="resource_type" />
<field name="user_id" />
<field name="time_efficiency" />
</tree>
</field>
</record>
<record id="action_resource_resource_tree" model="ir.actions.act_window">
<field name="name">Resources</field>
<field name="res_model">resource.resource</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem action="action_resource_resource_tree" id="menu_resource_resource_tree" parent="menu_resource_root"/>
<record id="resource_calendar_leave_form" model="ir.ui.view">
<field name="name">resource.calendar.leaves.form</field>
<field name="model">resource.calendar.leaves</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Leave Detail">
<field name="name" />
<field name="company_id" />
<field name="calendar_id" />
<field name="date_from" />
<field name="date_to" />
<field name="resource_id" />
</form>
</field>
</record>
<record id="resource_calendar_leave_tree" model="ir.ui.view">
<field name="name">resource.calendar.leaves.tree</field>
<field name="model">resource.calendar.leaves</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Leave Detail">
<field name="name" />
<field name="company_id" />
<field name="calendar_id" />
<field name="date_from" />
<field name="date_to" />
<field name="resource_id" />
</tree>
</field>
</record>
<record id="action_resource_calendar_leave_tree" model="ir.actions.act_window">
<field name="name">Leaves</field>
<field name="res_model">resource.calendar.leaves</field>
<field name="view_mode">tree,form,calendar</field>
</record>
<menuitem action="action_resource_calendar_leave_tree" id="menu_resource_calendar_leave_tree" parent="menu_resource_root"/>
</data>
</openerp>

View File

@ -0,0 +1,5 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_hr_timesheet_group","resource.calendar","model_resource_calendar","hr.group_hr_user",1,0,0,0
"access_hr_timesheet","hr.timesheet","model_hr_timesheet","hr.group_hr_user",1,1,1,1
"access_hr_timesheet_manager","hr.timesheet manager","model_hr_timesheet","hr.group_hr_manager",1,1,1,1
"access_hr_timesheet_group_manager","hr.timesheet.group.manager","model_hr_timesheet_group","hr.group_hr_manager",1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_timesheet_group resource.calendar model_resource_calendar hr.group_hr_user 1 0 0 0
3 access_hr_timesheet hr.timesheet model_hr_timesheet hr.group_hr_user 1 1 1 1
4 access_hr_timesheet_manager hr.timesheet manager model_hr_timesheet hr.group_hr_manager 1 1 1 1
5 access_hr_timesheet_group_manager hr.timesheet.group.manager model_hr_timesheet_group hr.group_hr_manager 1 1 1 1

View File

@ -134,6 +134,7 @@
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, 'lang' in context and context['lang'], False, parent.date_order, product_packaging, parent.fiscal_position)"
domain="[('product_id','=',product_id)]"
groups="base.group_extended"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
<separator colspan="4" string="Manual Description"/>
<field colspan="4" name="name" select="2"/>

View File

@ -175,6 +175,8 @@ class product_product(osv.osv):
}
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(product_product,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
if context == None:
context = {}
if ('location' in context) and context['location']:
location_info = self.pool.get('stock.location').browse(cr, uid, context['location'])
fields=res.get('fields',{})