[IMP]: bugfixing and code cleaning in project and project_* modules
bzr revid: pap@tinyerp.co.in-20100709072750-dg3yv4fmn0g0edqm
This commit is contained in:
parent
5e003a77ba
commit
887706ce66
|
@ -27,5 +27,4 @@ import report
|
|||
import wizard
|
||||
import res_partner
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
"author": "Tiny",
|
||||
"website": "http://www.openerp.com",
|
||||
"category": "Generic Modules/Projects & Services",
|
||||
"depends": ["product", "analytic", "process", "mail_gateway","board"],
|
||||
"description": """Project management module that track multi-level projects, tasks,
|
||||
"depends": ["product", "analytic", "mail_gateway", "board"],
|
||||
"description": """Project management module tracks multi-level projects, tasks,
|
||||
work done on tasks, eso. It is able to render planning, order tasks, eso.
|
||||
Dashboard for project members that includes:
|
||||
* List of my open tasks
|
||||
|
@ -41,7 +41,6 @@ work done on tasks, eso. It is able to render planning, order tasks, eso.
|
|||
"wizard/project_task_delegate_view.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"project_data.xml",
|
||||
"project_wizard.xml",
|
||||
"project_view.xml",
|
||||
"project_report.xml",
|
||||
"process/task_process.xml",
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
Administrator shortcut
|
||||
Demo user startup menu
|
||||
|
@ -14,6 +13,7 @@
|
|||
<field name="sequence">3</field>
|
||||
<field name="res_id" ref="menu_board_project"/>
|
||||
</record-->
|
||||
|
||||
<record id="base.user_root" model="res.users">
|
||||
<field name="action_id" ref="open_board_project"/>
|
||||
</record>
|
||||
|
|
|
@ -6,22 +6,6 @@
|
|||
<field name="name">Project</field>
|
||||
</record>
|
||||
|
||||
<record id="view_task_tree" model="ir.ui.view">
|
||||
<field name="name">project.task.tree</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="type">tree</field>
|
||||
<field eval="99" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="red:date_deadline<current_date;blue:date_deadline==current_date;black:date_deadline>current_date" string="My Tasks">
|
||||
<field name="name"/>
|
||||
<field name="project_id"/>
|
||||
<field name="date_deadline"/>
|
||||
<field name="planned_hours"/>
|
||||
<field name="effective_hours"/>
|
||||
<field name="priority"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Editable My task -->
|
||||
<record id="view_task_tree" model="ir.ui.view">
|
||||
<field name="name">project.task.tree</field>
|
||||
|
@ -39,6 +23,7 @@
|
|||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_task_tree" model="ir.actions.act_window">
|
||||
<field name="name">My Open Tasks</field>
|
||||
<field name="res_model">project.task</field>
|
||||
|
@ -47,6 +32,7 @@
|
|||
<field name="domain">[('user_id','=',uid),('state','=','open')]</field>
|
||||
<field name="view_id" ref="view_task_tree"/>
|
||||
</record>
|
||||
|
||||
<record id="action_view_pending_task_tree" model="ir.actions.act_window">
|
||||
<field name="name">My Pending Tasks</field>
|
||||
<field name="res_model">project.task</field>
|
||||
|
@ -55,6 +41,7 @@
|
|||
<field name="domain">[('user_id','=',uid),('state','=','pending')]</field>
|
||||
<field name="view_id" ref="view_task_tree"/>
|
||||
</record>
|
||||
|
||||
<record id="action_view_task_tree_deadline" model="ir.actions.act_window">
|
||||
<field name="name">My Task's Deadlines</field>
|
||||
<field name="res_model">project.task</field>
|
||||
|
@ -125,17 +112,20 @@
|
|||
<field name="usage">menu</field>
|
||||
<field name="view_id" ref="board_project_form"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="next_id_86"
|
||||
name="Dashboard"
|
||||
icon="terp-graph"
|
||||
sequence="0"
|
||||
parent="base.menu_project_report"/>
|
||||
|
||||
<menuitem
|
||||
action="open_board_project"
|
||||
icon="terp-graph"
|
||||
id="menu_board_project"
|
||||
parent="next_id_86"
|
||||
sequence="1"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
|
||||
class project_installer(osv.osv_memory):
|
||||
|
@ -26,7 +27,8 @@ class project_installer(osv.osv_memory):
|
|||
|
||||
_columns = {
|
||||
# Project Management
|
||||
'project_long_term': fields.boolean('Long Term Planning',
|
||||
'project_long_term': fields.boolean(
|
||||
'Long Term Planning',
|
||||
help="Enables long-term projects tracking, including "
|
||||
"multiple-phase projects and resource allocation handling."),
|
||||
'project_wiki': fields.boolean('Specifications in a Wiki',
|
||||
|
@ -35,7 +37,7 @@ class project_installer(osv.osv_memory):
|
|||
help="Tracks and helps employees encode and validate timesheets "
|
||||
"and attendance."),
|
||||
'hr_timesheet_invoice': fields.boolean('Invoice Based on Hours',
|
||||
help="Helps generate invoice based on based on human resources "
|
||||
help="Helps generate invoice based on human resources "
|
||||
"costs and general expenses."),
|
||||
'account_budget': fields.boolean('Budgets',
|
||||
help="Helps accountants manage analytic and crossover budgets."),
|
||||
|
@ -49,12 +51,14 @@ class project_installer(osv.osv_memory):
|
|||
help="Implements and tracks the concepts and task types defined "
|
||||
"in the SCRUM methodology."),
|
||||
'project_gtd': fields.boolean('Getting Things Done',
|
||||
help="Embeds the Getting Things Done concepts into OpenERP's "
|
||||
help="Embeds the 'Getting Things Done concepts' into OpenERP's "
|
||||
"project management."),
|
||||
}
|
||||
|
||||
_defaults={
|
||||
'project_crm': True,
|
||||
'project_crm': True,
|
||||
}
|
||||
|
||||
project_installer()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -18,8 +18,8 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from lxml import etree
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from tools.translate import _
|
||||
|
@ -38,6 +38,7 @@ class project_task_type(osv.osv):
|
|||
_defaults = {
|
||||
'sequence': 1
|
||||
}
|
||||
|
||||
project_task_type()
|
||||
|
||||
class project(osv.osv):
|
||||
|
@ -46,10 +47,8 @@ class project(osv.osv):
|
|||
_inherits = {'account.analytic.account':"category_id"}
|
||||
|
||||
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
if context is None:
|
||||
context = {}
|
||||
if user == 1:
|
||||
return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
|
||||
return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
|
||||
if context and context.has_key('user_prefence') and context['user_prefence']:
|
||||
cr.execute("""SELECT project.id FROM project_project project
|
||||
LEFT JOIN account_analytic_account account ON account.id = project.category_id
|
||||
|
@ -61,8 +60,6 @@ class project(osv.osv):
|
|||
context=context, count=count)
|
||||
|
||||
def _complete_name(self, cr, uid, ids, name, args, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
for m in self.browse(cr, uid, ids, context=context):
|
||||
res[m.id] = (m.parent_id and (m.parent_id.name + '/') or '') + m.name
|
||||
|
@ -73,8 +70,6 @@ class project(osv.osv):
|
|||
parent=parent)
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, part=False, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
if not part:
|
||||
return {'value':{'contact_id': False, 'pricelist_id': False}}
|
||||
|
@ -84,8 +79,6 @@ class project(osv.osv):
|
|||
return {'value':{'contact_id': addr['contact'], 'pricelist_id': pricelist_id}}
|
||||
|
||||
def _progress_rate(self, cr, uid, ids, names, arg, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}.fromkeys(ids, 0.0)
|
||||
progress = {}
|
||||
if not ids:
|
||||
|
@ -143,13 +136,16 @@ class project(osv.osv):
|
|||
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages'),
|
||||
'project_escalation_id': fields.many2one('project.project','Project Escalation', help='If any issue is escalated from the current Project, it will be listed under the project selected here.'),
|
||||
}
|
||||
|
||||
_order = "sequence"
|
||||
|
||||
_defaults = {
|
||||
'active': True,
|
||||
'priority': 1,
|
||||
'sequence': 10,
|
||||
'warn_manager': True,
|
||||
}
|
||||
|
||||
def _check_dates(self, cr, uid, ids):
|
||||
leave = self.read(cr, uid, ids[0], ['date_start', 'date'])
|
||||
if leave['date_start'] and leave['date']:
|
||||
|
@ -168,6 +164,7 @@ class project(osv.osv):
|
|||
(_check_dates, 'Error! project start-date must be lower then project end-date.', ['date_start', 'date']),
|
||||
(_check_escalation, 'Error! You cannot assign escalation to the same project!', ['project_escalation_id'])
|
||||
]
|
||||
|
||||
def set_template(self, cr, uid, ids, context=None):
|
||||
res = self.setActive(cr, uid, ids, value=False, context=context)
|
||||
return res
|
||||
|
@ -255,16 +252,11 @@ class project(osv.osv):
|
|||
'search_view_id': search_view['res_id'],
|
||||
'nodestroy': True
|
||||
}
|
||||
# return result
|
||||
|
||||
# set active value for a project, its sub projects and its tasks
|
||||
def setActive(self, cr, uid, ids, value=True, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
task_obj = self.pool.get('project.task')
|
||||
for proj in self.browse(cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
self.write(cr, uid, [proj.id], {'state': value and 'open' or 'template'}, context)
|
||||
cr.execute('select id from project_task where project_id=%s', (proj.id,))
|
||||
tasks_id = [x[0] for x in cr.fetchall()]
|
||||
|
@ -273,9 +265,8 @@ class project(osv.osv):
|
|||
child_ids = self.search(cr, uid, [('parent_id','=', proj.id)])
|
||||
if child_ids:
|
||||
self.setActive(cr, uid, child_ids, value, context=None)
|
||||
if context is None:
|
||||
context = {}
|
||||
return True
|
||||
|
||||
project()
|
||||
|
||||
class task(osv.osv):
|
||||
|
@ -285,16 +276,12 @@ class task(osv.osv):
|
|||
_date_name = "date_start"
|
||||
|
||||
def _str_get(self, task, level=0, border='***', context=None):
|
||||
if context is None:
|
||||
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'+ \
|
||||
(task.description or '')+'\n\n'
|
||||
|
||||
# Compute: effective_hours, total_hours, progress
|
||||
def _hours_get(self, cr, uid, ids, field_names, args, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
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())
|
||||
|
@ -314,6 +301,8 @@ class task(osv.osv):
|
|||
return {'value':{'remaining_hours': planned - effective}}
|
||||
|
||||
def _default_project(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if 'project_id' in context and context['project_id']:
|
||||
return int(context['project_id'])
|
||||
return False
|
||||
|
@ -323,15 +312,11 @@ class task(osv.osv):
|
|||
#]
|
||||
|
||||
def copy_data(self, cr, uid, id, default={}, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
default = default or {}
|
||||
default['work_ids'] = []
|
||||
return super(task, self).copy_data(cr, uid, id, default, context)
|
||||
|
||||
def _check_dates(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
task = self.read(cr, uid, ids[0], ['date_start', 'date_end'])
|
||||
if task['date_start'] and task['date_end']:
|
||||
if task['date_start'] > task['date_end']:
|
||||
|
@ -346,7 +331,7 @@ class task(osv.osv):
|
|||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of tasks."),
|
||||
'type': fields.many2one('project.task.type', 'Stage',),
|
||||
'state': fields.selection([('draft', 'Draft'),('open', 'In Progress'),('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True,
|
||||
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.\
|
||||
help='If the task is created the state is \'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'),
|
||||
|
@ -370,6 +355,7 @@ class task(osv.osv):
|
|||
'manager_id': fields.related('project_id', 'category_id', 'user_id', type='many2one', relation='res.users', string='Project Manager'),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': 'draft',
|
||||
'priority': '2',
|
||||
|
@ -380,6 +366,7 @@ class task(osv.osv):
|
|||
'project_id': _default_project,
|
||||
'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_start, id"
|
||||
|
||||
_constraints = [
|
||||
|
@ -388,10 +375,9 @@ class task(osv.osv):
|
|||
#
|
||||
# Override view according to the company definition
|
||||
#
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
users_obj = self.pool.get('res.users')
|
||||
if context is None:
|
||||
context = {}
|
||||
obj_tm = users_obj.browse(cr, uid, uid, context).company_id.project_time_mode_id
|
||||
tm = obj_tm and obj_tm.name or 'Hours'
|
||||
|
||||
|
@ -424,6 +410,10 @@ class task(osv.osv):
|
|||
mod_obj = self.pool.get('ir.model.data')
|
||||
request = self.pool.get('res.request')
|
||||
tasks = self.browse(cr, uid, ids)
|
||||
task_id = ids[0]
|
||||
cntx = {}
|
||||
if len(args):
|
||||
cntx = args[0]
|
||||
for task in tasks:
|
||||
project = task.project_id
|
||||
if project:
|
||||
|
@ -437,8 +427,7 @@ class task(osv.osv):
|
|||
'ref_doc1': 'project.task,%d'% (task.id,),
|
||||
'ref_doc2': 'project.project,%d'% (project.id,),
|
||||
})
|
||||
elif project.warn_manager:
|
||||
task_id = ids[0]
|
||||
elif project.warn_manager and cntx.get('mail_send',False):
|
||||
mail_send = True
|
||||
message = _('Task ') + " '" + task.name + "' "+ _("is Done.")
|
||||
self.log(cr, uid, task.id, message)
|
||||
|
@ -454,11 +443,11 @@ class task(osv.osv):
|
|||
if mail_send:
|
||||
model_data_ids = mod_obj.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_project_close_task')])
|
||||
resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
|
||||
args[0].update({'task_id': task_id})
|
||||
cntx.update({'task_id': task_id})
|
||||
return {
|
||||
'name': _('Email Send to Customer'),
|
||||
'view_type': 'form',
|
||||
'context': args[0], # improve me
|
||||
'context': cntx, # improve me
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'close.task',
|
||||
'views': [(resource_id,'form')],
|
||||
|
@ -466,7 +455,9 @@ class task(osv.osv):
|
|||
'target': 'new',
|
||||
'nodestroy': True
|
||||
}
|
||||
return True
|
||||
else:
|
||||
self.write(cr, uid, [task_id], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
|
||||
return False
|
||||
|
||||
def do_reopen(self, cr, uid, ids, *args):
|
||||
request = self.pool.get('res.request')
|
||||
|
@ -562,11 +553,14 @@ class project_work(osv.osv):
|
|||
'user_id': fields.many2one('res.users', 'Done by', required=True),
|
||||
'company_id': fields.related('task_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True)
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'user_id': lambda obj, cr, uid, context: uid,
|
||||
'date': time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
_order = "date desc"
|
||||
|
||||
def create(self, cr, uid, vals, *args, **kwargs):
|
||||
if 'hours' in vals and (not vals['hours']):
|
||||
vals['hours'] = 0.00
|
||||
|
@ -588,10 +582,12 @@ class project_work(osv.osv):
|
|||
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))
|
||||
return super(project_work,self).unlink(cr, uid, ids, *args, **kwargs)
|
||||
|
||||
project_work()
|
||||
|
||||
class config_compute_remaining(osv.osv_memory):
|
||||
_name='config.compute.remaining'
|
||||
|
||||
def _get_remaining(self,cr, uid, ctx):
|
||||
task_obj = self.pool.get('project.task')
|
||||
if 'active_id' in ctx:
|
||||
|
@ -638,6 +634,7 @@ config_compute_remaining()
|
|||
class message(osv.osv):
|
||||
_name = "project.message"
|
||||
_description = "Message"
|
||||
|
||||
_columns = {
|
||||
'subject': fields.char('Subject', size=128, required="True"),
|
||||
'project_id': fields.many2one('project.project', 'Project', ondelete='cascade'),
|
||||
|
@ -655,7 +652,7 @@ class message(osv.osv):
|
|||
|
||||
_defaults = {
|
||||
'user_id': lambda self,cr,uid,ctx: uid,
|
||||
'date': lambda self,cr,uid,ctx: time.strftime('%Y-%m-%d'),
|
||||
'date': time.strftime('%Y-%m-%d'),
|
||||
'project_id': _default_project
|
||||
}
|
||||
|
||||
|
@ -667,6 +664,7 @@ class users(osv.osv):
|
|||
_columns = {
|
||||
'context_project_id': fields.many2one('project.project', 'Project')
|
||||
}
|
||||
|
||||
users()
|
||||
|
||||
class account_analytic_account(osv.osv):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!--
|
||||
Requests Links
|
||||
-->
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<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 name="name">Specific Developments</field>
|
||||
<field name="manager" ref="base.user_root"/>
|
||||
<field eval="[(6, 0, [ref('project_tt_specification'), ref('project_tt_development')])]" name="type_ids"/>
|
||||
</record>
|
||||
|
@ -64,7 +64,7 @@
|
|||
<field name="type" ref="project_tt_development"/>
|
||||
<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="description">BoM, After sales returns, interventions. Traceability.</field>
|
||||
<field name="name">Specific adaptation to MRP</field>
|
||||
</record>
|
||||
<record id="project_task_130" model="project.task">
|
||||
|
@ -146,7 +146,7 @@
|
|||
<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="name">MRP; functional layer</field>
|
||||
<field name="state">done</field>
|
||||
<field eval="time.strftime('%Y-%m-%d 12:12')" name="date_close"/>
|
||||
</record>
|
||||
|
@ -172,7 +172,7 @@
|
|||
<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>
|
||||
<field name="name">Customer doc</field>
|
||||
</record>
|
||||
<record id="project_task_197" model="project.task">
|
||||
<field name="sequence">30</field>
|
||||
|
@ -266,5 +266,6 @@
|
|||
- Create Users</field>
|
||||
<field name="subject">Configuration steps</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_project_installer" model="ir.ui.view">
|
||||
<field name="name">project.installer.view</field>
|
||||
<field name="model">project.installer</field>
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="base.res_config_installer"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<data>
|
||||
<form position="attributes">
|
||||
<attribute name="string">Project Modules Installation</attribute>
|
||||
</form>
|
||||
|
@ -16,12 +17,11 @@
|
|||
<xpath expr='//separator[@string="vsep"]' position='attributes'>
|
||||
<attribute name='string'></attribute>
|
||||
</xpath>
|
||||
<xpath expr="//label[@string='description']"
|
||||
position="attributes">
|
||||
<attribute name="string">Various OpenERP applications are available to bring your project management to the next levels of control and flexibility.</attribute>
|
||||
<xpath expr="//label[@string='description']" position="attributes">
|
||||
<attribute name="string">Various OpenERP applications are available to bring your project management to the next levels of control and flexibility.</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//button[@string='Install Modules']" position="attributes">
|
||||
<attribute name="string">Configure</attribute>
|
||||
<attribute name="string">Configure</attribute>
|
||||
</xpath>
|
||||
<group colspan="8">
|
||||
<field name="project_crm"/>
|
||||
|
@ -65,5 +65,6 @@
|
|||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -19,24 +19,13 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import re
|
||||
import os
|
||||
|
||||
import mx.DateTime
|
||||
import base64
|
||||
|
||||
from tools.translate import _
|
||||
|
||||
import tools
|
||||
from osv import fields,osv,orm
|
||||
from osv.orm import except_orm
|
||||
from osv import fields,osv
|
||||
|
||||
class project_tasks(osv.osv):
|
||||
_name = "project.task"
|
||||
_inherit = "project.task"
|
||||
|
||||
def msg_new(self, cr, uid, msg):
|
||||
def msg_new(self, cr, uid, msg):
|
||||
mailgate_obj = self.pool.get('mail.gateway')
|
||||
msg_body = mailgate_obj.msg_body_get(msg)
|
||||
data = {
|
||||
|
@ -72,14 +61,11 @@ class project_tasks(osv.osv):
|
|||
if msg_actions['priority'] in ('1','2','3','4','5'):
|
||||
data['priority'] = msg_actions['priority']
|
||||
|
||||
|
||||
self.write(cr, uid, [id], data)
|
||||
getattr(self,act)(cr, uid, [id])
|
||||
return True
|
||||
|
||||
def message_followers(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = []
|
||||
if isinstance(ids, (str, int, long)):
|
||||
select = [ids]
|
||||
|
@ -93,6 +79,8 @@ class project_tasks(osv.osv):
|
|||
return res
|
||||
|
||||
def msg_send(self, cr, uid, id, *args, **argv):
|
||||
return True
|
||||
return True
|
||||
|
||||
project_tasks()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -1,10 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 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 pooler
|
||||
import datetime
|
||||
|
||||
def timeformat_convert(cr, uid, time_string, context=None):
|
||||
def timeformat_convert(cr, uid, time_string):
|
||||
# Function to convert input time string:: 8.5 to output time string 8:30
|
||||
if context is None:
|
||||
context = {}
|
||||
split_list = str(time_string).split('.')
|
||||
hour_part = split_list[0]
|
||||
mins_part = split_list[1]
|
||||
|
@ -12,7 +31,7 @@ def timeformat_convert(cr, uid, time_string, context=None):
|
|||
converted_string = hour_part + ':' + str(round_mins)[0:2]
|
||||
return converted_string
|
||||
|
||||
def leaves_resource(cr,uid,calendar_id,resource_id=False,resource_calendar=False):
|
||||
def leaves_resource(cr, uid, calendar_id, resource_id=False, resource_calendar=False):
|
||||
# To get the leaves for the resource_ids working on phase
|
||||
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
|
@ -31,20 +50,20 @@ def leaves_resource(cr,uid,calendar_id,resource_id=False,resource_calendar=False
|
|||
leaves.sort()
|
||||
return leaves
|
||||
|
||||
def compute_working_calendar(cr,uid,calendar_id):
|
||||
def compute_working_calendar(cr, uid, calendar_id):
|
||||
# To change the format of working calendar to bring it into 'faces' format
|
||||
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
resource_week_pool = pool.get('resource.calendar.week')
|
||||
time_range = "8:00-8:00"
|
||||
non_working = ""
|
||||
wk = {"0":"mon","1":"tue","2":"wed","3":"thu","4":"fri","5":"sat","6":"sun"}
|
||||
wk = {"0":"mon", "1":"tue", "2":"wed", "3":"thu", "4":"fri", "5":"sat", "6":"sun"}
|
||||
wk_days = {}
|
||||
wk_time = {}
|
||||
wktime_list = []
|
||||
wktime_cal = []
|
||||
week_ids = resource_week_pool.search(cr, uid, [('calendar_id','=',calendar_id)])
|
||||
week_obj = resource_week_pool.read(cr, uid, week_ids, ['dayofweek','hour_from','hour_to'])
|
||||
week_obj = resource_week_pool.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'])
|
||||
|
||||
# Converting time formats into appropriate format required
|
||||
# and creating a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')]
|
||||
|
@ -80,3 +99,5 @@ def compute_working_calendar(cr,uid,calendar_id):
|
|||
wktime_cal.append((non_working[:-1],time_range))
|
||||
|
||||
return wktime_cal
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<menuitem
|
||||
icon="terp-project" id="base.menu_main_pm"
|
||||
name="Project" sequence="10"
|
||||
|
@ -148,6 +149,7 @@
|
|||
<field name="name" string="Project Name"/>
|
||||
<field name="user_id" string="Project Manager"/>
|
||||
<field name="partner_id" string="Partner"/>
|
||||
<field name="parent_id" invisible="1"/>
|
||||
<field name="planned_hours" widget="float_time"/>
|
||||
<field name="total_hours" widget="float_time"/>
|
||||
<field name="effective_hours" widget="float_time"/>
|
||||
|
@ -647,5 +649,6 @@
|
|||
<act_window domain="[('user_id', '=', active_id),('date', '>=', time.strftime('%Y-%m-01'))]" id="act_res_users_2_project_task_work_month" name="Month works" res_model="project.task.work" src_model="res.users" view_mode="tree,form" view_type="form"/>
|
||||
|
||||
<act_window domain="[('project_id', '=', active_id)]" id="act_project_messages" name="Messages" res_model="project.message" src_model="project.project"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<?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_duplicate_template"
|
||||
menu="False"
|
||||
model="project.project"
|
||||
name="project.duplicate.template" string="Duplicate Template"/>
|
||||
-->
|
||||
</data>
|
||||
</openerp>
|
|
@ -18,6 +18,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import project_report
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -118,6 +118,7 @@ class report_project_task_user(osv.osv):
|
|||
t.type
|
||||
|
||||
""")
|
||||
|
||||
report_project_task_user()
|
||||
|
||||
#This class is generated for project deshboard purpose
|
||||
|
@ -162,6 +163,7 @@ class project_vs_remaining_hours(osv.osv):
|
|||
GROUP BY pur.uid,aaa.state,aaa.name
|
||||
)
|
||||
""")
|
||||
|
||||
project_vs_remaining_hours()
|
||||
|
||||
class task_by_days(osv.osv):
|
||||
|
@ -192,6 +194,7 @@ class task_by_days(osv.osv):
|
|||
to_char(pt.create_date, 'YYYY-MM-DD'),pt.state,pt.project_id
|
||||
)
|
||||
""")
|
||||
|
||||
task_by_days()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<menuitem id="base.menu_project_report" name="Reporting" parent="base.menu_main_pm" sequence="50"/>
|
||||
|
||||
<record id="view_task_project_user_tree" model="ir.ui.view">
|
||||
|
@ -42,13 +43,13 @@
|
|||
<field name="model">report.project.task.user</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Tasks Analysis" type="bar">
|
||||
<field name="name"/>
|
||||
<field name="state" group="True"/>
|
||||
<field name="no_of_days" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<graph string="Tasks Analysis" type="bar">
|
||||
<field name="name"/>
|
||||
<field name="state" group="True"/>
|
||||
<field name="no_of_days" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_task_project_user_search" model="ir.ui.view">
|
||||
<field name="name">report.project.task.user.search</field>
|
||||
|
@ -174,7 +175,7 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_project_vs_remaining_hours_graph" model="ir.actions.act_window">
|
||||
<record id="action_project_vs_remaining_hours_graph" model="ir.actions.act_window">
|
||||
<field name="name">Project and remaining hours</field>
|
||||
<field name="res_model">project.vs.remaining.hours</field>
|
||||
<field name="view_type">form</field>
|
||||
|
@ -184,7 +185,7 @@
|
|||
</record>
|
||||
|
||||
<!-- Views and action for project issue dashboard -->
|
||||
<record id="view_task_by_days_tree" model="ir.ui.view">
|
||||
<record id="view_task_by_days_tree" model="ir.ui.view">
|
||||
<field name="name">task.by.days.tree</field>
|
||||
<field name="model">task.by.days</field>
|
||||
<field name="type">tree</field>
|
||||
|
|
|
@ -23,7 +23,7 @@ from osv import fields,osv
|
|||
|
||||
class res_partner(osv.osv):
|
||||
|
||||
""" Inherits partner and adds CRM information in the partner form """
|
||||
""" Inherits partner and adds Tasks information in the partner form """
|
||||
_inherit = 'res.partner'
|
||||
_columns = {
|
||||
'task_ids': fields.one2many('project.task', 'partner_id', 'Tasks'),
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
import time
|
||||
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
from tools import email_send as email
|
||||
|
||||
|
@ -42,7 +43,7 @@ class project_close_task(osv.osv_memory):
|
|||
if 'task_id' in context:
|
||||
task = self.pool.get('project.task').browse(cr, uid, context['task_id'])
|
||||
partner_id = task.partner_id or task.project_id.partner_id
|
||||
if partner_id and partner_id.address[0].email:
|
||||
if partner_id and len(partner_id.address) and partner_id.address[0].email:
|
||||
email = partner_id.address[0].email
|
||||
return email
|
||||
|
||||
|
@ -54,10 +55,15 @@ class project_close_task(osv.osv_memory):
|
|||
return task.description or task.name
|
||||
return ''
|
||||
|
||||
_defaults={
|
||||
_defaults = {
|
||||
'email': _get_email,
|
||||
'description': _get_desc,
|
||||
}
|
||||
|
||||
def close(self, cr, uid, ids, context=None):
|
||||
if 'task_id' in context:
|
||||
self.pool.get('project.task').write(cr, uid, [context['task_id']], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
|
||||
return {}
|
||||
|
||||
def confirm(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
|
@ -67,8 +73,10 @@ class project_close_task(osv.osv_memory):
|
|||
close_task = self.read(cr, uid, ids[0], [])
|
||||
to_adr = close_task['email']
|
||||
description = close_task['description']
|
||||
|
||||
if 'task_id' in context:
|
||||
for task in self.pool.get('project.task').browse(cr, uid, [context['task_id']], context=context):
|
||||
task_obj = self.pool.get('project.task')
|
||||
for task in task_obj.browse(cr, uid, [context['task_id']], context=context):
|
||||
project = task.project_id
|
||||
subject = "Task '%s' closed" % task.name
|
||||
if task.user_id and task.user_id.address_id and task.user_id.address_id.email:
|
||||
|
@ -89,9 +97,11 @@ class project_close_task(osv.osv_memory):
|
|||
footer = (project.warn_footer or '') % val
|
||||
body = u'%s\n%s\n%s\n\n-- \n%s' % (header, description, footer, signature)
|
||||
email(from_adr, [to_adr], subject, body.encode('utf-8'), email_bcc=[from_adr])
|
||||
task_obj.write(cr, uid, [task.id], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
|
||||
else:
|
||||
raise osv.except_osv(_('Error'), _("Couldn't send mail because the contact for this task (%s) has no email address!") % contact.name)
|
||||
raise osv.except_osv(_('Error'), _("Please specify the email address of partner."))
|
||||
return {}
|
||||
|
||||
project_close_task()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
<newline/>
|
||||
<field name="description" />
|
||||
</group>
|
||||
<group colspan="4" col="6">
|
||||
<button icon="gtk-cancel" special="cancel" string="_Close"/>
|
||||
<button icon="gtk-ok" name="confirm" string="Send Mail" type="object"/>
|
||||
<separator string="" colspan="6"/>
|
||||
<group colspan="6" col="6">
|
||||
<button icon="gtk-ok" name="confirm" string="Send and Close" type="object"/>
|
||||
<button icon="gtk-ok" string="Close" name="close" type="object"/>
|
||||
<button icon="gtk-cancel" special="cancel" string="_Cancel"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -102,19 +102,20 @@ class project_task_delegate(osv.osv_memory):
|
|||
'description': delegate_data['new_task_description'] or '',
|
||||
'child_ids': [],
|
||||
'work_ids': []
|
||||
})
|
||||
}, context)
|
||||
task_obj.write(cr, uid, [task.id], {
|
||||
'remaining_hours': delegate_data['planned_hours_me'],
|
||||
'planned_hours': delegate_data['planned_hours_me'] + (task.effective_hours or 0.0),
|
||||
'name': newname,
|
||||
})
|
||||
}, context)
|
||||
if delegate_data['state'] == 'pending':
|
||||
task_obj.do_pending(cr, uid, [task.id])
|
||||
task_obj.do_pending(cr, uid, [task.id], context)
|
||||
else:
|
||||
task_obj.do_close(cr, uid, [task.id])
|
||||
delegrate_user = user_obj.browse(cr, uid, delegate_data['user_id'], context=context)
|
||||
message = _('Task ') + " '" + delegate_data['name'] + "' "+ _("is Delegated to User:") +" '"+ delegrate_user.name +"' "
|
||||
self.log(cr, uid, task.id, message)
|
||||
context.update({'mail_send': False} )
|
||||
task_obj.do_close(cr, uid, [task.id], context)
|
||||
delegrate_user = user_obj.browse(cr, uid, delegate_data['user_id'], context=context)
|
||||
message = _('Task ') + " '" + delegate_data['name'] + "' "+ _("is Delegated to User:") +" '"+ delegrate_user.name +"' "
|
||||
self.log(cr, uid, task.id, message)
|
||||
return {}
|
||||
|
||||
project_task_delegate()
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
'crm',
|
||||
'project',
|
||||
'hr_timesheet_sheet',
|
||||
'resource'
|
||||
],
|
||||
'init_xml': [
|
||||
'project_issue_data.xml'
|
||||
|
|
|
@ -144,7 +144,6 @@ class project_issue(osv.osv, crm.crm_case):
|
|||
'create_date': fields.datetime('Creation Date', readonly=True),
|
||||
'write_date': fields.datetime('Update Date', readonly=True),
|
||||
'date_deadline': fields.date('Deadline'),
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
|
||||
select=True, help='Sales team to which Case belongs to.\
|
||||
Define Responsible user and Email account for mail gateway.'),
|
||||
|
@ -391,7 +390,6 @@ class project_issue(osv.osv, crm.crm_case):
|
|||
res = self.write(cr, uid, ids, vals)
|
||||
return res
|
||||
|
||||
|
||||
def msg_send(self, cr, uid, id, *args, **argv):
|
||||
|
||||
""" Send The Message
|
||||
|
|
|
@ -29,6 +29,7 @@ class project_issue(osv.osv):
|
|||
'timesheet_ids': fields.one2many('hr.analytic.timesheet', 'issue_id', 'Timesheets'),
|
||||
'analytic_account_id': fields.related('project_id', 'category_id', string='Analytic Account')
|
||||
}
|
||||
|
||||
project_issue()
|
||||
|
||||
class account_analytic_line(osv.osv):
|
||||
|
|
|
@ -29,4 +29,4 @@
|
|||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
|
@ -25,7 +25,7 @@
|
|||
"author": "Tiny",
|
||||
"website": "http://www.openerp.com",
|
||||
"category": "Generic Modules/Projects & Services",
|
||||
"depends": ["project", "resource"],
|
||||
"depends": ["resource", "project"],
|
||||
"description": """
|
||||
|
||||
Long Term Project management module that tracks planning, scheduling, resources allocation.
|
||||
|
|
|
@ -61,7 +61,6 @@ class project_compute_phases(osv.osv_memory):
|
|||
resource_obj = self.pool.get('resource.resource')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
phase_resource_obj = False
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
if phase:
|
||||
|
@ -134,14 +133,13 @@ class project_compute_phases(osv.osv_memory):
|
|||
|
||||
if context is None:
|
||||
context = {}
|
||||
project_obj = self.pool.get('project.project')
|
||||
phase_obj = self.pool.get('project.phase')
|
||||
data = self.read(cr, uid, ids, [], context=context)[0]
|
||||
if not data['project_id'] and data['target_project'] == 'one':
|
||||
raise osv.except_osv(_('Error!'), _('Please Specify Project to be schedule'))
|
||||
if data['project_id']: # If project mentioned find its phases
|
||||
project_id = project_obj.browse(cr, uid, data['project_id'], context=context)
|
||||
phase_ids = phase_obj.search(cr, uid, [('project_id', '=', project_id.id),
|
||||
project_id = data['project_id']
|
||||
phase_ids = phase_obj.search(cr, uid, [('project_id', '=', project_id),
|
||||
('state', 'in', ['draft', 'open', 'pending']),
|
||||
('previous_phase_ids', '=', False)
|
||||
])
|
||||
|
|
|
@ -160,4 +160,5 @@ class project_schedule_task(osv.osv_memory):
|
|||
return {}
|
||||
|
||||
project_schedule_task()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
"depends": ["project"],
|
||||
"author": "Tiny",
|
||||
"description": """
|
||||
This module provides the functionality to send messages within a project.'
|
||||
A user can send messages individually to other user also he can broadcast
|
||||
This module provides the functionality to send messages within a project.
|
||||
A user can send messages individually to other user. He can even broadcast
|
||||
it to all the users.
|
||||
""",
|
||||
'website': 'http://www.openerp.com',
|
||||
|
|
|
@ -498,7 +498,10 @@ class report_account_analytic_planning_stat(osv.osv):
|
|||
WHERE user_id=%s and account_id=%s and date>=%s and date<=%s''', (line.user_id.id, line.account_id.id, line.planning_id.date_from, line.planning_id.date_to))
|
||||
else:
|
||||
cr.execute('SELECT sum(unit_amount) FROM account_analytic_line WHERE account_id=%s AND date>=%s AND date<=%s', (line.account_id.id, line.planning_id.date_from, line.planning_id.date_to))
|
||||
result[line.id] = cr.fetchone()[0] * div2
|
||||
|
||||
sum = cr.fetchone()
|
||||
if sum and sum[0]:
|
||||
result[line.id] = sum[0] * div2
|
||||
return result
|
||||
|
||||
def _sum_amount_tasks(self, cr, uid, ids, name, args, context=None):
|
||||
|
@ -527,13 +530,15 @@ WHERE user_id=%s and account_id=%s and date>=%s and date<=%s''', (line.user_id.i
|
|||
WHERE
|
||||
''' + where + '''
|
||||
project_id IN (select id from project_project where category_id=%s) AND
|
||||
date_close>=%s AND
|
||||
date_close<=%s''', (
|
||||
date_end>=%s AND
|
||||
date_end<=%s''', (
|
||||
line.account_id.id,
|
||||
line.planning_id.date_from,
|
||||
line.planning_id.date_to)
|
||||
)
|
||||
result[line.id] = cr.fetchone()[0] /div * div2
|
||||
sum = cr.fetchone()
|
||||
if sum and sum[0]:
|
||||
result[line.id] = sum[0] /div * div2
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
|
|
|
@ -37,11 +37,12 @@ class project_project(osv.osv):
|
|||
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 %H:%M:%S')[:6])+(c-d)).strftime('%Y-%m-%d %H:%M:%S')
|
||||
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})
|
||||
return super(project_project,self).write(cr, uid, ids, vals, *args, **kwargs)
|
||||
|
||||
project_project()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -84,10 +84,10 @@ class project_work(osv.osv):
|
|||
timeline_id = obj_timesheet.create(cr, uid, vals=vals_line, context=kwargs['context'])
|
||||
|
||||
# Compute based on pricetype
|
||||
amount_unit=obj_timesheet.on_change_unit_amount(cr, uid, timeline_id,
|
||||
amount_unit = obj_timesheet.on_change_unit_amount(cr, uid, timeline_id,
|
||||
prod_id, amount, unit, context=kwargs['context'])
|
||||
|
||||
vals_line['amount'] = (-1) * vals['hours']* (amount_unit['value']['amount'] or 0.0)
|
||||
if amount_unit:
|
||||
vals_line['amount'] = (-1) * vals['hours']* (amount_unit.get('value',{}).get('amount',0.0) or 0.0)
|
||||
obj_timesheet.write(cr, uid, [timeline_id], vals_line, {})
|
||||
vals['hr_analytic_timesheet_id'] = timeline_id
|
||||
return super(project_work,self).create(cr, uid, vals, *args, **kwargs)
|
||||
|
@ -120,8 +120,10 @@ class project_work(osv.osv):
|
|||
unit = False
|
||||
amount_unit=obj.on_change_unit_amount(cr, uid, line_id,
|
||||
vals_line['product_id'], vals_line['unit_amount'], unit, context=context)
|
||||
|
||||
vals_line['amount'] = (-1) * vals['hours'] * (amount_unit['value']['amount'] or 0.0)
|
||||
|
||||
if amount_unit:
|
||||
vals_line['amount'] = (-1) * vals['hours'] * (amount_unit.get('value',{}).get('amount',0.0) or 0.0)
|
||||
|
||||
obj.write(cr, uid, [line_id], vals_line, context=context)
|
||||
|
||||
return super(project_work,self).write(cr, uid, ids, vals, context)
|
||||
|
|
Loading…
Reference in New Issue