bzr revid: uco@tinyerp.com-20100803130042-93e7wznbh9mak4e1
This commit is contained in:
uco (Open ERP)
2010-08-03 18:30:42 +05:30
17 changed files with 131 additions and 56 deletions
+2 -2
View File
@@ -1601,8 +1601,8 @@ class account_tax(osv.osv):
#
# Fields used for the VAT declaration
#
'base_code_id': fields.many2one('account.tax.code', 'Base Code', help="Use this code for the VAT declaration."),
'tax_code_id': fields.many2one('account.tax.code', 'Tax Code', help="Use this code for the VAT declaration."),
'base_code_id': fields.many2one('account.tax.code', 'Account Base Code', help="Use this code for the VAT declaration."),
'tax_code_id': fields.many2one('account.tax.code', 'Account Tax Code', help="Use this code for the VAT declaration."),
'base_sign': fields.float('Base Code Sign', help="Usually 1 or -1."),
'tax_sign': fields.float('Tax Code Sign', help="Usually 1 or -1."),
@@ -345,6 +345,8 @@
</td>
</tr>
</blockTable>
<section>
<para style="Standard"><font color="white">[[lines(o.id) and removeParentNode('para') or removeParentNode('section') ]]</font></para>
<blockTable colWidths="100.0,125.0,83.0,88.0,100.0" style="Table_Journal_Detail">[[ display_currency(data) == False or removeParentNode('blockTable') ]]
<tr>
<td>
@@ -364,7 +366,10 @@
</td>
</tr>
</blockTable>
</section>
<section>
<blockTable colWidths="100.0,100.0,73.0,80.0,80.0,80.0" style="Table_Journal_Detail">[[ display_currency(data) or removeParentNode('blockTable') ]]
<para style="Standard"><font color="white">[[lines(o.id) and removeParentNode('para') or removeParentNode('section') ]]</font></para>
<tr>
<td><para style="terp_default_9"><font>[[ repeatIn(lines(o.id),'line')]]</font> [[ line['code'] ]]</para></td>
<td><para style="terp_default_9">[[ line['name'] ]]</para></td>
@@ -374,6 +379,7 @@
<td><para style="terp_default_Right_9">[[ line['currency_id'] and formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]]</para></td>
</tr>
</blockTable>
</section>
<para style="terp_default_2">
<font color="white"> </font>
</para>
@@ -191,7 +191,7 @@
</para>
<blockTable colWidths="80.0,80.0,100.0,140.0,80.0,80.0" style="Table2_header">
<tr>
<td><para style="terp_tblheader_General_Centre">Chat Account</para></td>
<td><para style="terp_tblheader_General_Centre">Chart of Account</para></td>
<td><para style="terp_tblheader_General_Centre">Fiscal Year</para></td>
<td><para style="terp_tblheader_General_Centre">Journals</para></td>
<td><para style="terp_tblheader_General_Centre">Filter By [[ get_filter(data)!='No Filter' and get_filter(data) ]]</para></td>
@@ -8,7 +8,7 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Report Options">
<group height="500" width="800">
<group>
<field name="chart_account_id" widget='selection'/>
<field name="fiscalyear_id"/>
<group colspan="2" name='Journals'>
+7
View File
@@ -20,6 +20,7 @@
##############################################################################
from osv import fields, osv
from tools.translate import _
class res_company(osv.osv):
_inherit = 'res.company'
@@ -30,6 +31,12 @@ class res_company(osv.osv):
"forget to setup the right unit of measure in your employees.",
),
}
def write(self, cr, uid, ids,vals, context={}):
task_ids=self.pool.get('project.task').search(cr, uid, [('state','in',['open', 'pending'])])
if ('project_time_mode_id' in vals) and task_ids:
raise osv.except_osv(_('Error !'), _('You can not modify Project Time Unit as there are open or pending tasks created with current time unit.))
return super(res_company,self).write(cr, uid, ids, vals, context=context)
res_company()
+97 -26
View File
@@ -92,7 +92,26 @@ where prp.id in %s''',(tuple(ids),))
child_ids = self.get_all_child_projects(cr, uid, child_ids)
return ids+child_ids
def _get_user_and_default_uom_ids(self, cr, uid):
users_obj = self.pool.get('res.users')
model_data_obj = self.pool.get('ir.model.data')
model_data_id = model_data_obj._get_id(cr, uid, 'product', 'uom_hour')
default_uom = user_uom = model_data_obj.read(cr, uid, [model_data_id], ['res_id'])[0]['res_id']
obj_tm = users_obj.browse(cr, uid, uid).company_id.project_time_mode_id
if obj_tm:
user_uom = obj_tm.id
return user_uom, default_uom
def _compute_duration(self, cr, uid, duration=0.0, to_uom='default'):
uom_obj = self.pool.get('product.uom')
user_uom, default_uom = self._get_user_and_default_uom_ids(cr, uid)
if to_uom == 'default':
return uom_obj._compute_qty(cr, uid, user_uom, duration, default_uom)
else:
return uom_obj._compute_qty(cr, uid, default_uom, duration, user_uom)
def _progress_rate(self, cr, uid, ids, names, arg, context=None):
res = {}.fromkeys(ids, 0.0)
progress = {}
@@ -127,11 +146,18 @@ where prp.id in %s''',(tuple(ids),))
p = tocompute.pop()
for i in range(3):
s[i] += progress.get(p, (0.0, 0.0, 0.0))[i]
user_uom, def_uom = self._get_user_and_default_uom_ids(cr, uid)
if user_uom != def_uom:
s[0] = self._compute_duration(cr, uid, s[0])
s[1] = self._compute_duration(cr, uid, s[1])
s[2] = self._compute_duration(cr, uid, s[2])
if project.state == 'close':
progress_rate = 100.0
else:
progress_rate = s[1] and round(min(100.0 * s[2] / s[1], 99.99), 2)
res[project.id] = {
'planned_hours': s[0],
'effective_hours': s[2],
@@ -145,7 +171,7 @@ where prp.id in %s''',(tuple(ids),))
if proj.tasks:
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 = {
'complete_name': fields.function(_complete_name, method=True, string="Project Name", type='char', size=250),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the project without removing it."),
@@ -234,11 +260,10 @@ where prp.id in %s''',(tuple(ids),))
default['name'] = proj.name+_(' (copy)')
res = super(project, self).copy(cr, uid, id, default, context)
task_ids = task_obj.search(cr, uid, [('project_id','=', res), ('active','=',False)])
task_ids = task_obj.search(cr, uid, [('project_id','=', res), ('active','=',True)])
tasks = task_obj.browse(cr, uid, task_ids)
for task in tasks:
date_deadline = None
date_end = None
if task.date_start:
ds = date(*time.strptime(task.date_start,'%Y-%m-%d %H:%M:%S')[:3])
if task.date_deadline:
@@ -246,11 +271,11 @@ where prp.id in %s''',(tuple(ids),))
diff = dd-ds
date_deadline = (datetime.now()+diff).strftime('%Y-%m-%d %H:%M:%S')
task_obj.write(cr, uid, task.id, {'active':True,
'date_start':time.strftime('%Y-%m-%d %H:%M:%S'),
'date_start': False,
'date_end': False,
'date_deadline':date_deadline,
'date_end':date_end})
})
ids = self.search(cr, uid, [('parent_id','child_of', [res])])
return res
def duplicate_template(self, cr, uid, ids, context=None):
@@ -317,29 +342,46 @@ class task(osv.osv):
_description = "Task"
_log_create = True
_date_name = "date_start"
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
for domain in args:
if len(domain) == 3 and domain[0] == 'project_id':
id = isinstance(domain[2], list) and int(domain[2][0]) or int(domain[2])
if id:
if self.pool.get('project.project').read(cr, user, id, ['state'])['state'] == 'template':
args.append(['active', '=', False])
return super(task, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
def _str_get(self, task, level=0, border='***', context=None):
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'+ \
(task.description or '')+'\n\n'
# Compute: effective_hours, total_hours, progress
def _hours_get(self, cr, uid, ids, field_names, args, context=None):
project_obj = self.pool.get('project.project')
res = {}
cr.execute("SELECT task_id, COALESCE(SUM(hours),0) FROM project_task_work WHERE task_id IN %s GROUP BY task_id",(tuple(ids),))
hours = dict(cr.fetchall())
user_uom, default_uom = project_obj._get_user_and_default_uom_ids(cr, uid)
if user_uom != default_uom:
for task in self.browse(cr, uid, ids, context=context):
if hours.get(task.id, False):
dur_in_user_uom = project_obj._compute_duration(cr, uid, duration=hours.get(task.id, 0.0), to_uom='user')
hours[task.id] = dur_in_user_uom
for task in self.browse(cr, uid, ids, context=context):
res[task.id] = {'effective_hours': hours.get(task.id, 0.0), 'total_hours': task.remaining_hours + hours.get(task.id, 0.0)}
res[task.id]['delay_hours'] = res[task.id]['total_hours'] - task.planned_hours
res[task.id]['progress'] = 0.0
if (task.remaining_hours + hours.get(task.id, 0.0)):
if task.state != 'done':
res[task.id]['progress'] = round(min(100.0 * hours.get(task.id, 0.0) / res[task.id]['total_hours'], 99.99), 2)
if task.state in ('done', 'cancel'):
res[task.id]['progress'] = round(min(100.0 * hours.get(task.id, 0.0) / res[task.id]['total_hours'], 99.99),2)
if task.state in ('done','cancelled'):
res[task.id]['progress'] = 100.0
res[task.id]['delay_hours'] = res[task.id]['total_hours'] - task.planned_hours
return res
def onchange_planned(self, cr, uid, ids, planned = 0.0, effective = 0.0):
return {'value':{'remaining_hours': planned - effective}}
@@ -357,6 +399,7 @@ class task(osv.osv):
def copy_data(self, cr, uid, id, default={}, context=None):
default = default or {}
default['work_ids'] = []
default['remaining_hours'] = float(self.read(cr, uid, id, ['planned_hours'])['planned_hours'])
default['active'] = True
return super(task, self).copy_data(cr, uid, id, default, context)
@@ -375,7 +418,7 @@ class task(osv.osv):
if task.project_id.active == False or task.project_id.state == 'template':
res[task.id] = False
return res
_columns = {
'active': fields.function(_is_template, method=True, store=True, string='Not a Template Task', type='boolean', help="This field is computed automatically and have the same behavior than the boolean 'active' field: if the task is linked to a template or unactivated project, it will be hidden unless specifically asked."),
'name': fields.char('Task Summary', size=128, required=True),
@@ -397,7 +440,7 @@ class task(osv.osv):
'notes': fields.text('Notes'),
'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."),
'remaining_hours': fields.float('Remaining Hours', digits=(16,2), help="Total remaining time, can be re-estimated periodically by the assignee of the task."),
'total_hours': fields.function(_hours_get, method=True, string='Total Hours', multi='hours', store=True, help="Computed as: Time Spent + Remaining Time."),
'progress': fields.function(_hours_get, method=True, string='Progress (%)', multi='hours', store=True, help="Computed as: Time Spent / Total Time."),
'delay_hours': fields.function(_hours_get, method=True, string='Delay Hours', multi='hours', store=True, help="Computed as difference of the time estimated by the project manager and the real time to close the task."),
@@ -614,27 +657,55 @@ class project_work(osv.osv):
}
_order = "date desc"
def create(self, cr, uid, vals, *args, **kwargs):
if 'hours' in vals and (not vals['hours']):
if (not 'task_id' in vals) or (not 'hours' in vals):
return super(project_work,self).create(cr, uid, vals, *args, **kwargs)
if not vals['hours']:
vals['hours'] = 0.00
if 'task_id' in vals:
cr.execute('update project_task set remaining_hours=remaining_hours - %s where id=%s', (vals.get('hours',0.0), vals['task_id']))
project_obj = self.pool.get('project.project')
user_uom, default_uom = project_obj._get_user_and_default_uom_ids(cr, uid)
duration = vals['hours']
if user_uom != default_uom:
duration = project_obj._compute_duration(cr, uid, duration=duration, to_uom='user')
cr.execute('update project_task set remaining_hours=remaining_hours - %s where id=%s', (duration, vals['task_id']))
return super(project_work,self).create(cr, uid, vals, *args, **kwargs)
def write(self, cr, uid, ids, vals, context=None):
if context is None:
context = {}
if 'hours' in vals and (not vals['hours']):
vals['hours'] = 0.00
if 'hours' in vals:
if not vals['hours']:
vals['hours'] = 0.00
project_obj = self.pool.get('project.project')
user_uom, default_uom = project_obj._get_user_and_default_uom_ids(cr, uid)
duration = vals['hours']
if user_uom == default_uom:
for work in self.browse(cr, uid, ids, context):
cr.execute('update project_task set remaining_hours=remaining_hours - %s + (%s) where id=%s', (vals.get('hours',0.0), work.hours, work.task_id.id))
cr.execute('update project_task set remaining_hours=remaining_hours - %s + (%s) where id=%s', (duration, work.hours, work.task_id.id))
else:
for work in self.browse(cr, uid, ids, context):
duration = project_obj._compute_duration(cr, uid, duration=duration, to_uom='user')
del_work = project_obj._compute_duration(cr, uid, duration=work.hours, to_uom='user')
cr.execute('update project_task set remaining_hours=remaining_hours - %s + (%s) where id=%s', (duration, del_work, work.task_id.id))
return super(project_work,self).write(cr, uid, ids, vals, context)
def unlink(self, cr, uid, ids, *args, **kwargs):
for work in self.browse(cr, uid, ids):
cr.execute('update project_task set remaining_hours=remaining_hours + %s where id=%s', (work.hours, work.task_id.id))
context = kwargs.get('context', {})
project_obj = self.pool.get('project.project')
user_uom, default_uom = project_obj._get_user_and_default_uom_ids(cr, uid)
if user_uom == default_uom:
for work in self.browse(cr, uid, ids, context):
cr.execute('update project_task set remaining_hours=remaining_hours + %s where id=%s', (work.hours, work.task_id.id))
else:
for work in self.browse(cr, uid, ids, context):
duration = project_obj._compute_duration(cr, uid, duration=work.hours, to_uom='user')
cr.execute('update project_task set remaining_hours=remaining_hours + %s where id=%s', (duration, work.task_id.id))
return super(project_work,self).unlink(cr, uid, ids, *args, **kwargs)
project_work()
+1 -6
View File
@@ -424,11 +424,6 @@
groups="base.group_extended"/>
<separator orientation="vertical"/>
<filter string="Deadlines" domain="[('date_deadline','&lt;&gt;',False)]" help="Show only tasks having a deadline" icon="terp-gnome-cpu-frequency-applet+"/>
<filter name="template" domain="[('active', '=', False)]"
string="Template"
icon="terp-project"
groups="base.group_extended"
help="Change Type"/>
<separator orientation="vertical"/>
<field name="name" select="1"/>
<field name="project_id" select="1">
@@ -460,7 +455,7 @@
<field name="view_mode">tree,form,calendar,gantt,graph</field>
<field eval="False" name="filter"/>
<field name="view_id" ref="view_task_tree2"/>
<field name="context">{"search_default_project_id":project_id, "search_default_user_id":uid, 'search_default_current': 1}</field>
<field name="context">{"search_default_project_id":project_id, "search_default_user_id":uid, "search_default_current": 1}</field>
<field name="search_view_id" ref="view_task_search_form"/>
<field name="help">In OpenERP, a project is made of a set of activities (or tasks) for completion.A list view allows the manager to quickly check for task status and make it evolve, delegate task, etc. A search tool allows a multi-criteria sort of activities.
-1
View File
@@ -43,7 +43,6 @@ class project_gtd_context(osv.osv):
_columns = {
'name': fields.char('Context', size=64, required=True, select=1),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of contexts."),
'project_default_id': fields.many2one('project.project', 'Default Project', required=True),
}
_defaults = {
'sequence': 1
-4
View File
@@ -5,22 +5,18 @@
<record model="project.gtd.context" id="context_office">
<field name="name">Office</field>
<field name="sequence">0</field>
<field name="project_default_id" ref="project.project_project_9"/>
</record>
<record model="project.gtd.context" id="context_travel">
<field name="name">Travel</field>
<field name="sequence">2</field>
<field name="project_default_id" ref="project.project_project_9"/>
</record>
<record model="project.gtd.context" id="context_car">
<field name="name">Car</field>
<field name="sequence">1</field>
<field name="project_default_id" ref="project.project_project_9"/>
</record>
<record model="project.gtd.context" id="context_home">
<field name="name">Home</field>
<field name="sequence">3</field>
<field name="project_default_id" ref="project.project_project_9"/>
</record>
<record model="project.gtd.timebox" id="timebox_daily">
-2
View File
@@ -2,8 +2,6 @@
Create a task 'Develop time management module' with monthly timebox
-
!record {model: project.task, id: project_task_developtimemanagementmodule0}:
date_end: '2010-06-04 10:00:00'
date_start: '2010-06-02 14:42:21'
name: Develop time management module
planned_hours: 15.0
project_id: project.project_project_22
@@ -27,7 +27,7 @@ class project_issue(osv.osv):
_description = 'project issue'
_columns = {
'timesheet_ids': fields.one2many('hr.analytic.timesheet', 'issue_id', 'Timesheets'),
'analytic_account_id': fields.related('project_id', 'analytic_account_id', string='Analytic Account')
'analytic_account_id': fields.related('project_id', 'analytic_account_id', type='many2one', relation='account.analytic.account',string='Analytic Account')
}
project_issue()
@@ -133,7 +133,7 @@
<page string="Task Detail">
<group colspan="4" col="4">
<field name="name"/>
<field name="project_id"/>
<field name="project_id" required="1"/>
<field name="user_id"/>
</group>
<group colspan="2" col="2">
@@ -136,8 +136,8 @@
-
!python {model: project.project}: |
prj=self.browse(cr, uid, [ref("project_project_worldbanksproject0")])[0]
for task in prj.tasks:
if (not task.user_id) or (not task.date_start) or (not task.date_end):
for phase in prj.phase_ids:
if (not phase.responsible_id) or (not phase.date_start) or (not phase.date_end):
raise AssertionError("Tasks not scheduled")
@@ -74,6 +74,8 @@ class project_compute_phases(osv.osv_memory):
resource = resource_obj.browse(cr, uid, resource_id, context=context)[0]
time_efficiency = resource.time_efficiency
leaves = wkcal.compute_leaves(cr, uid, calendar_id , resource.id, resource.calendar_id.id)
if not phase.responsible_id:
raise osv.except_osv(_('No responsible person assigned !'),_("You must assign a responsible person for phase '%s' !") % (phase.name,))
phase_resource_obj = classobj((phase.responsible_id.name.encode('utf8')), (Resource,),
{'__doc__': phase.responsible_id.name,
'__name__': phase.responsible_id.name,
@@ -3,4 +3,4 @@
<data>
<report id="report_planning" model="report_account_analytic.planning" name="report_account_analytic.planning.print" rml="project_planning/report/report_planning.rml" string="Planning"/>
</data>
</openerp>
</openerp>
+2 -2
View File
@@ -24,8 +24,8 @@
'version': '0.1',
'category': 'Generic Modules/Projects & Services',
'description': """
- If deadline date of project is changed
then the deadline date for all the tasks will change to the same """,
- If end date of project is changed
then the deadline date and start date for all the tasks will change accordingly """,
'author': 'OpenERP SA',
'depends': ['base', 'project'],
'init_xml': [],
@@ -35,12 +35,13 @@ class project_project(osv.osv):
if prj.date:
old_end_date = date(*time.strptime(prj.date,'%Y-%m-%d')[:3])
for task in prj.tasks:
start_dt = (datetime(*time.strptime(task.date_start,'%Y-%m-%d %H:%M:%S')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d %H:%M:%S')
if task.date_deadline:
deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d %H:%M:%S')
self.pool.get('project.task').write(cr, uid, task.id, {'date_start':start_dt, 'date_deadline':deadline_dt})
else:
self.pool.get('project.task').write(cr, uid, task.id, {'date_start':start_dt})
if task.date_start:
start_dt = (date(*time.strptime(str(task.date_start),'%Y-%m-%d %H:%M:%S')[:3])+(new_end_date-old_end_date)).strftime('%Y-%m-%d %H:%M:%S')
if task.date_deadline:
deadline_dt = (datetime(*time.strptime(str(task.date_deadline),'%Y-%m-%d')[:3])+(new_end_date-old_end_date)).strftime('%Y-%m-%d')
self.pool.get('project.task').write(cr, uid, task.id, {'date_start':start_dt, 'date_deadline':deadline_dt})
else:
self.pool.get('project.task').write(cr, uid, task.id, {'date_start':start_dt})
return super(project_project,self).write(cr, uid, ids, vals, *args, **kwargs)
project_project()