diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py
index 6b8f07d0e52..647d80e61be 100644
--- a/addons/account/account_bank_statement.py
+++ b/addons/account/account_bank_statement.py
@@ -412,7 +412,7 @@ class account_bank_statement(osv.osv):
if t['state'] in ('draft'):
unlink_ids.append(t['id'])
else:
- raise osv.except_osv(_('Invalid action !'), _('Cannot delete bank statement which are already confirmed !'))
+ raise osv.except_osv(_('Invalid action !'), _('Cannot delete bank statement(s) which are already confirmed !'))
osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
return True
diff --git a/addons/account/account_installer.xml b/addons/account/account_installer.xml
index a9de51c3afb..a3570fae79a 100644
--- a/addons/account/account_installer.xml
+++ b/addons/account/account_installer.xml
@@ -73,7 +73,7 @@
- Add extra Accounting Addons to the ones already installed. Remember you can always install them at a later stage.
+ Add extra Accounting functionalities to the ones already installed.Configure
diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml
index d53fb9fe80a..ca489acd9bd 100644
--- a/addons/account/partner_view.xml
+++ b/addons/account/partner_view.xml
@@ -72,7 +72,7 @@
2
-
+
diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py
index b97edb9a546..cf96028f01c 100644
--- a/addons/analytic/analytic.py
+++ b/addons/analytic/analytic.py
@@ -282,6 +282,7 @@ class account_analytic_line(osv.osv):
_defaults = {
'date': time.strftime('%Y-%m-%d'),
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=c),
+ 'amount' : 0.00
}
_order = 'date desc'
diff --git a/addons/association/profile_association.py b/addons/association/profile_association.py
index f102d710fd8..eb9ac398500 100644
--- a/addons/association/profile_association.py
+++ b/addons/association/profile_association.py
@@ -27,13 +27,18 @@ class profile_association_config_install_modules_wizard(osv.osv_memory):
_inherit = 'res.config.installer'
_columns = {
- 'hr_expense':fields.boolean('Expenses Tracking', help="Tracks the personal expenses process, from the employee expense encoding, to the reimbursement of the employee up to the reinvoicing to the final customer."),
- 'project':fields.boolean('Project Management'),
- 'event_project':fields.boolean('Organization and management of Events', help="This module allows you to create retro planning for managing your events."),
+ 'hr_expense':fields.boolean('Expenses Tracking', help="Tracks and manages employee expenses, and can "
+ "automatically re-invoice clients if the expenses are "
+ "project-related."),
+ 'project':fields.boolean('Project Management',
+ help="Helps you manage your projects and tasks by tracking them, "
+ "generating plannings, etc..."),
+ 'event_project':fields.boolean('Events', help="Helps you to manage and organize your events."),
'project_gtd':fields.boolean('Getting Things Done',
help="GTD is a methodology to efficiently organise yourself and your tasks. This module fully integrates GTD principle with OpenERP's project management."),
- 'wiki': fields.boolean('Wiki',
- help="An integrated wiki content management system. This is really usefull to manage FAQ, quality manuals, etc.")
+ 'wiki': fields.boolean('Wiki', help="Lets you create wiki pages and page groups in order "
+ "to keep track of business knowledge and share it with "
+ "and between your employees."),
}
profile_association_config_install_modules_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py
index 4278e0a9179..dd843449c8c 100644
--- a/addons/audittrail/audittrail.py
+++ b/addons/audittrail/audittrail.py
@@ -35,15 +35,15 @@ class audittrail_rule(osv.osv):
_description = "Audittrail Rule"
_columns = {
"name": fields.char("Rule Name", size=32, required=True),
- "object_id": fields.many2one('ir.model', 'Object', required=True),
+ "object_id": fields.many2one('ir.model', 'Object', required=True, help="Select object for which you want to generate log."),
"user_id": fields.many2many('res.users', 'audittail_rules_users',
'user_id', 'rule_id', 'Users', help="if User is not added then it will applicable for all users"),
- "log_read": fields.boolean("Log Reads"),
- "log_write": fields.boolean("Log Writes"),
- "log_unlink": fields.boolean("Log Deletes"),
- "log_create": fields.boolean("Log Creates"),
- "log_action": fields.boolean("Log Action"),
- "log_workflow": fields.boolean("Log Workflow"),
+ "log_read": fields.boolean("Log Reads", help="Select this if you want to keep track of read/open on any record of the object of this rule"),
+ "log_write": fields.boolean("Log Writes", help="Select this if you want to keep track of modification on any record of the object of this rule"),
+ "log_unlink": fields.boolean("Log Deletes", help="Select this if you want to keep track of deletion on any record of the object of this rule"),
+ "log_create": fields.boolean("Log Creates",help="Select this if you want to keep track of creation on any record of the object of this rule"),
+ "log_action": fields.boolean("Log Action",help="Select this if you want to keep track of actions on the object of this rule"),
+ "log_workflow": fields.boolean("Log Workflow",help="Select this if you want to keep track of workflow on any record of the object of this rule"),
"state": fields.selection((("draft", "Draft"),
("subscribed", "Subscribed")),
"State", required=True),
diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml
index 526fe55f4a3..755f6680d34 100644
--- a/addons/base_action_rule/base_action_rule_view.xml
+++ b/addons/base_action_rule/base_action_rule_view.xml
@@ -14,11 +14,13 @@
form
diff --git a/addons/base_setup/installer.py b/addons/base_setup/installer.py
index 0c8478ba57d..f415447e5fb 100644
--- a/addons/base_setup/installer.py
+++ b/addons/base_setup/installer.py
@@ -58,7 +58,7 @@ class base_setup_installer(osv.osv_memory):
help="Helps you manage your purchase-related processes such as "
"requests for quotations, supplier invoices, etc..."),
'hr':fields.boolean('Human Resources',
- help="Helps you manage your human resources by encoding your employees structure, generating work sheets, tracking attendance and more"),
+ help="Helps you manage your human resources by encoding your employees structure, generating work sheets, tracking attendance and more."),
'point_of_sale':fields.boolean('Point of Sales',
help="Helps you get the most out of your points of sales with "
"fast sale encoding, simplified payment mode encoding, "
@@ -74,7 +74,7 @@ class base_setup_installer(osv.osv_memory):
# Vertical modules
'product_expiry':fields.boolean('Food Industry',
help="Installs a preselected set of OpenERP applications "
- "which will help you manage your industry"),
+ "which will help you manage your industry."),
'association':fields.boolean('Associations',
help="Installs a preselected set of OpenERP "
"applications which will help you manage your association "
diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py
index 63e683bafb7..55be22f198e 100644
--- a/addons/caldav/caldav_node.py
+++ b/addons/caldav/caldav_node.py
@@ -103,7 +103,12 @@ class node_calendar_collection(nodes.node_dir):
class node_calendar(nodes.node_class):
our_type = 'collection'
DAV_PROPS = {
- "http://calendarserver.org/ns/" : ('getctag',),
+ "DAV:": ('principal-collection-set'),
+ "http://cal.me.com/_namespace/" : ('user-state'),
+ "http://calendarserver.org/ns/" : (
+ 'dropbox-home-URL',
+ 'notification-URL',
+ 'getctag',),
'http://groupdav.org/': ('resourcetype',),
"urn:ietf:params:xml:ns:caldav" : (
'calendar-description',
@@ -114,6 +119,7 @@ class node_calendar(nodes.node_class):
'schedule-outbox-URL',)}
DAV_M_NS = {
"DAV:" : '_get_dav',
+ "http://cal.me.com/_namespace/": '_get_dav',
'http://groupdav.org/': '_get_gdav',
"http://calendarserver.org/ns/" : '_get_dav',
"urn:ietf:params:xml:ns:caldav" : '_get_caldav'}
@@ -134,6 +140,35 @@ class node_calendar(nodes.node_class):
result = self._get_ttag(cr) + ':' + str(time.time())
return str(result)
+ def _get_dav_dropbox_home_URL(self, cr):
+ import xml.dom.minidom
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ url = urllib.quote('/%s/%s' % (cr.dbname, res))
+ return url
+
+ def _get_dav_notification_URL(self, cr):
+ import xml.dom.minidom
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ url = urllib.quote('/%s/%s' % (cr.dbname, res))
+ return url
+
+ def _get_dav_user_state(self, cr):
+ #TODO
+ return True
+
+
def get_dav_resourcetype(self, cr):
res = [ ('collection', 'DAV:'),
(str(self.cal_type + '-collection'), 'http://groupdav.org/'),
@@ -258,6 +293,86 @@ class node_calendar(nodes.node_class):
def rmcol(self, cr):
return False
+
+ def _get_caldav_calendar_data(self, cr):
+ res = []
+ for child in self.children(cr):
+ res.append(child._get_caldav_calendar_data(cr))
+ return res
+
+ def _get_caldav_calendar_description(self, cr):
+ uid = self.context.uid
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ return calendar.description
+
+ def _get_dav_principal_collection_set(self, uri):
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, res)))
+ href.appendChild(huri)
+ return href
+
+ def _get_caldav_calendar_home_set(self, cr):
+ import xml.dom.minidom
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, calendar.collection_id.name)))
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ href.appendChild(huri)
+ return href
+
+ def _get_caldav_calendar_user_address_set(self, cr):
+ import xml.dom.minidom
+ dirobj = self.context._dirobj
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ user_obj = self.context._dirobj.pool.get('res.users')
+ user = user_obj.browse(cr, uid, uid, context=ctx)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ huri = doc.createTextNode('MAILTO:' + str(user.email) or str(user.name))
+ href.appendChild(huri)
+ return href
+
+ def _get_caldav_schedule_outbox_URL(self, cr):
+ return self._get_caldav_schedule_inbox_URL(cr)
+
+ def _get_caldav_schedule_inbox_URL(self, cr):
+ import xml.dom.minidom
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, res)))
+ href.appendChild(huri)
+ return href
+
class res_node_calendar(nodes.node_class):
our_type = 'file'
@@ -309,6 +424,9 @@ class res_node_calendar(nodes.node_class):
context.update({'model': self.model, 'res_id':self.res_id})
res = calendar_obj.export_cal(cr, uid, [self.calendar_id], context=context)
return res
+
+ def _get_caldav_calendar_data(self, cr):
+ return self.get_data(cr)
def get_data_len(self, cr, fil_obj = None):
return self.content_length
@@ -327,67 +445,6 @@ class res_node_calendar(nodes.node_class):
res = '%d' % (self.calendar_id)
return res
- def _get_caldav_calendar_data(self, cr):
- return self.get_data(cr)
-
-
- def _get_caldav_calendar_description(self, cr):
- uid = self.context.uid
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- return calendar.description
-
-
- def _get_caldav_calendar_home_set(self, cr):
- import xml.dom.minidom
- import urllib
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
-
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, calendar.collection_id.name)))
- href = doc.documentElement
- href.tagName = 'D:href'
- href.appendChild(huri)
- return href
-
- def _get_caldav_calendar_user_address_set(self, cr):
- import xml.dom.minidom
- dirobj = self.context._dirobj
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- user_obj = self.context._dirobj.pool.get('res.users')
- user = user_obj.browse(cr, uid, uid, context=ctx)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
- href = doc.documentElement
- href.tagName = 'D:href'
- huri = doc.createTextNode('MAILTO:' + user.email)
- href.appendChild(huri)
- return href
-
-
- def _get_caldav_schedule_inbox_URL(self, cr):
- import xml.dom.minidom
- import urllib
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- res = '%s/%s' %(calendar.name, calendar.collection_id.name)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
- href = doc.documentElement
- href.tagName = 'D:href'
- huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, res)))
- href.appendChild(huri)
- return href
-
def rm(self, cr):
uid = self.context.uid
@@ -401,7 +458,6 @@ class res_node_calendar(nodes.node_class):
return res
- def _get_caldav_schedule_outbox_URL(self, cr):
- return self._get_caldav_schedule_inbox_URL(cr)
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4
diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py
index 01c35880fbb..4f9afb034a4 100644
--- a/addons/caldav/calendar.py
+++ b/addons/caldav/calendar.py
@@ -453,7 +453,7 @@ class CalDAV(object):
else:
for key1, val1 in self.ical_get(field, 'mapping').items():
if val1 == data[map_field]:
- vevent.add(field).value = key1
+ vevent.add(field).value = key1.upper()
return vevent
def check_import(self, cr, uid, vals, context=None):
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index c8dde37d9e5..9b4f9e2ef96 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -587,7 +587,7 @@ class crm_case_categ(osv.osv):
_description = "Category of case"
_columns = {
- 'name': fields.char('Case Category Name', size=64, required=True, translate=True),
+ 'name': fields.char('Name', size=64, required=True, translate=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
'object_id': fields.many2one('ir.model', 'Object Name'),
}
@@ -636,7 +636,7 @@ class crm_case_stage(osv.osv):
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case stages."),
'object_id': fields.many2one('ir.model', 'Object Name'),
- 'probability': fields.float('Probability (%)', required=True),
+ 'probability': fields.float('Probability (%)', required=True, help="This percentage depicts the default/average probability of the Case for this stage to be a success"),
'on_change': fields.boolean('Change Probability Automatically', \
help="Change Probability on next and previous stages."),
'requirements': fields.text('Requirements')
diff --git a/addons/crm/crm_installer.py b/addons/crm/crm_installer.py
index 6797afc62e0..3860a69b51c 100644
--- a/addons/crm/crm_installer.py
+++ b/addons/crm/crm_installer.py
@@ -33,15 +33,15 @@ class crm_installer(osv.osv_memory):
_columns = {
'name': fields.char('Name', size=64),
- 'crm_helpdesk': fields.boolean('Helpdesk', help="Manages an Helpdesk service."),
+ 'crm_helpdesk': fields.boolean('Helpdesk', help="Manages a Helpdesk service."),
'crm_fundraising': fields.boolean('Fundraising', help="This may help associations in their fundraising process and tracking."),
'crm_claim': fields.boolean('Claims', help="Manages the suppliers and customers claims, including your corrective or preventive actions."),
'crm_caldav': fields.boolean('Calendar Synchronizing', help="Helps you to synchronize the meetings with other calendar clients and mobiles."),
'sale_crm': fields.boolean('Opportunity to Quotation', help="This module relates sale from opportunity cases in the CRM."),
- 'fetchmail': fields.boolean('Fetch Emails', help="Fetchmail Server."),
- 'thunderbird': fields.boolean('Thunderbird', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one"),
- 'outlook': fields.boolean('MS-Outlook', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one"),
- 'wiki_sale_faq': fields.boolean('Sale FAQ', help="Sale FAQ."),
+ 'fetchmail': fields.boolean('Fetch Emails', help="Allows you to receive E-Mails from POP/IMAP server."),
+ 'thunderbird': fields.boolean('Thunderbird', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
+ 'outlook': fields.boolean('MS-Outlook', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
+ 'wiki_sale_faq': fields.boolean('Sale FAQ', help="Helps you manage wiki pages for Frequently Asked Questions on Sales Application."),
}
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
diff --git a/addons/crm/crm_installer_view.xml b/addons/crm/crm_installer_view.xml
index 5fad3f41a3d..ece3bae31ec 100644
--- a/addons/crm/crm_installer_view.xml
+++ b/addons/crm/crm_installer_view.xml
@@ -16,7 +16,7 @@
- Enhance your CRM basic Application with additional Addons.
+ Enhance your core CRM Application with additional functionalities.13
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index da09795547a..0a552a4165a 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -125,6 +125,7 @@ class crm_lead(crm_case, osv.osv):
domain="['|',('section_id','=',section_id),('section_id','=',False)]"),
'channel_id': fields.many2one('res.partner.canal', 'Channel'),
+ 'contact_name': fields.char('Contact Name', size=64),
'partner_name': fields.char("Partner Name", size=64),
'optin': fields.boolean('Opt-In'),
'optout': fields.boolean('Opt-Out'),
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index 41d41ef0502..2df1369bbb1 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -55,7 +55,7 @@
-
@@ -235,8 +238,8 @@
-
-
+
+
@@ -299,7 +302,7 @@
-
+
@@ -337,6 +340,7 @@
help="Show Sales Team"/>
+
@@ -365,7 +369,7 @@
-
diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml
index 55ef2c7d5e3..06cb0280567 100644
--- a/addons/crm/crm_meeting_view.xml
+++ b/addons/crm/crm_meeting_view.xml
@@ -317,32 +317,31 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/crm/crm_opportunity_view.xml b/addons/crm/crm_opportunity_view.xml
index 8101a0bcfb2..c2713b91f89 100644
--- a/addons/crm/crm_opportunity_view.xml
+++ b/addons/crm/crm_opportunity_view.xml
@@ -133,7 +133,7 @@
-
+
-
-
@@ -272,7 +272,7 @@
+
+
+
-
-
-
-
+
diff --git a/addons/crm/crm_phonecall_menu.xml b/addons/crm/crm_phonecall_menu.xml
index 481e92ec134..8585ddc7fe4 100644
--- a/addons/crm/crm_phonecall_menu.xml
+++ b/addons/crm/crm_phonecall_menu.xml
@@ -13,7 +13,8 @@
groups="base.group_extended"
/>
-
+
diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml
index 4f60b91b3c2..0832c0a16ee 100644
--- a/addons/crm/crm_phonecall_view.xml
+++ b/addons/crm/crm_phonecall_view.xml
@@ -16,19 +16,6 @@
-
-
-
- Phonecall Campaigns
- crm.case.resource.type
- form
-
-
-
-
-
@@ -47,9 +34,10 @@
@@ -94,7 +82,7 @@
@@ -121,7 +109,7 @@
states="draft,pending" type="object"
icon="gtk-go-forward" />
+ states="open" type="object" icon="gtk-media-pause" />
@@ -172,7 +160,7 @@
@@ -219,10 +207,14 @@
string="Type" />
+
-
-
-
-
+ context="{'group_by':'date'}" help="Date of Call" />
diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml
index db248be7492..061888d02fb 100644
--- a/addons/crm/crm_view.xml
+++ b/addons/crm/crm_view.xml
@@ -113,7 +113,7 @@
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py
index 81a98a7e326..de77c842aa6 100644
--- a/addons/crm_claim/crm_claim.py
+++ b/addons/crm_claim/crm_claim.py
@@ -46,10 +46,8 @@ class crm_claim(crm.crm_case, osv.osv):
'ref' : fields.reference('Reference', selection=crm._links_get, size=128),
'ref2' : fields.reference('Reference 2', selection=crm._links_get, size=128),
'canal_id': fields.many2one('res.partner.canal', 'Channel', \
- help="The channels represent the different communication"\
- "modes available with the customer." \
- " With each commercial opportunity, you can indicate the"\
- "canall which is this opportunity source."),
+ help="The channels represent the different communication \
+ modes available with the customer."),
'planned_revenue': fields.float('Planned Revenue'),
'planned_cost': fields.float('Planned Costs'),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml
index 44b1eb34fd8..a341915bc39 100644
--- a/addons/crm_claim/crm_claim_view.xml
+++ b/addons/crm_claim/crm_claim_view.xml
@@ -35,21 +35,6 @@
-
-
-
- Claim Resource Type
- crm.case.resource.type
- form
-
- [('object_id.model', '=', 'crm.claim')]
- {'object_id':'crm.claim'}
-
-
-
-
@@ -57,7 +42,7 @@
crm.claimtree
-
+
@@ -168,7 +153,7 @@
-
+
-
+
@@ -205,7 +190,7 @@
-
@@ -269,7 +254,7 @@
@@ -339,6 +325,7 @@
context="{'default_partner_address_id': active_id}"
id="act_claim_partner_address"
name="Report a Claim"
+ view_mode="form,tree"
res_model="crm.claim"
src_model="res.partner.address"/>
diff --git a/addons/crm_claim/i18n/en_US.po b/addons/crm_claim/i18n/en_US.po
index 27818261434..b67bd61d7f9 100644
--- a/addons/crm_claim/i18n/en_US.po
+++ b/addons/crm_claim/i18n/en_US.po
@@ -87,8 +87,8 @@ msgstr "Day"
#. module: crm_claim
#: help:crm.claim,canal_id:0
-msgid "The channels represent the different communicationmodes available with the customer. With each commercial opportunity, you can indicate thecanall which is this opportunity source."
-msgstr "The channels represent the different communicationmodes available with the customer. With each commercial opportunity, you can indicate thecanall which is this opportunity source."
+msgid "The channels represent the different communication modes available with the customer."
+msgstr "The channels represent the different communication modes available with the customer."
#. module: crm_claim
#: help:crm.claim,section_id:0
diff --git a/addons/crm_claim/report/crm_claim_report.py b/addons/crm_claim/report/crm_claim_report.py
index fed4026aa02..e0dc7244f14 100644
--- a/addons/crm_claim/report/crm_claim_report.py
+++ b/addons/crm_claim/report/crm_claim_report.py
@@ -74,6 +74,8 @@ class crm_claim_report(osv.osv):
'type_id': fields.many2one('crm.case.resource.type', 'Claim Type',\
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.claim')]"),
+ 'date_closed': fields.date('Closed', readonly=True),
+ 'delay_expected': fields.float('Overpassed Deadline',digits=(16,2),readonly=True, group_operator="avg"),
}
def init(self, cr):
@@ -87,9 +89,10 @@ class crm_claim_report(osv.osv):
create or replace view crm_claim_report as (
select
min(c.id) as id,
- to_char(c.create_date, 'YYYY') as name,
- to_char(c.create_date, 'MM') as month,
- to_char(c.create_date, 'YYYY-MM-DD') as day,
+ to_char(c.date, 'YYYY') as name,
+ to_char(c.date, 'MM') as month,
+ to_char(c.date, 'YYYY-MM-DD') as day,
+ to_char(c.date_closed, 'YYYY-MM-DD') as date_closed,
c.state,
c.user_id,
c.stage_id,
@@ -101,13 +104,14 @@ class crm_claim_report(osv.osv):
c.priority as priority,
c.type_id as type_id,
date_trunc('day',c.create_date) as create_date,
- avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close
+ avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close,
+ extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24) as delay_expected
from
crm_claim c
- group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), \
+ group by to_char(c.date, 'YYYY'), to_char(c.date, 'MM'),to_char(c.date, 'YYYY-MM-DD'),\
c.state, c.user_id,c.section_id, c.stage_id,\
- c.categ_id,c.partner_id,c.company_id,c.create_date,to_char(c.create_date, 'YYYY-MM-DD')
- ,c.priority,c.type_id
+ c.categ_id,c.partner_id,c.company_id,c.create_date,
+ c.priority,c.type_id,c.date_deadline,c.date_closed
)""")
crm_claim_report()
diff --git a/addons/crm_claim/report/crm_claim_report_view.xml b/addons/crm_claim/report/crm_claim_report_view.xml
index edb3dc2b6db..db5973c1867 100644
--- a/addons/crm_claim/report/crm_claim_report_view.xml
+++ b/addons/crm_claim/report/crm_claim_report_view.xml
@@ -19,6 +19,7 @@
+
@@ -42,6 +43,7 @@
+
@@ -75,14 +77,17 @@
-
+
-
+
-
+
-
+ help="My team" />
-
+
-
+
@@ -139,42 +143,41 @@
-
-
-
-
-
+
-
-
-
+
-
-
-
+
+
+
+
+ domain="[]" context="{'group_by':'day'}"
+ help="Date of claim"/>
+ domain="[]" context="{'group_by':'month'}"
+ help="Month of claim"/>
+ domain="[]" context="{'group_by':'name'}"
+ help="Year of claim"/>
-
@@ -182,7 +185,7 @@
- Claims
+ Claims Analysiscrm.claim.reportformtree,graph
diff --git a/addons/crm_fundraising/crm_fundraising.py b/addons/crm_fundraising/crm_fundraising.py
index df7bc4a0789..0050642a5db 100644
--- a/addons/crm_fundraising/crm_fundraising.py
+++ b/addons/crm_fundraising/crm_fundraising.py
@@ -71,10 +71,8 @@ class crm_fundraising(crm.crm_case, osv.osv):
'ref': fields.reference('Reference', selection=crm._links_get, size=128),
'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
'canal_id': fields.many2one('res.partner.canal', 'Channel', \
- help="The channels represent the different communication "\
- "modes available with the customer." \
- " With each commercial opportunity, you can indicate\
- the canall which is this opportunity source."),
+ help="The channels represent the different communication \
+ modes available with the customer."),
'state': fields.selection(crm.AVAILABLE_STATES, 'State', size=16, readonly=True,
help='The state is set to \'Draft\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
diff --git a/addons/crm_fundraising/crm_fundraising_view.xml b/addons/crm_fundraising/crm_fundraising_view.xml
index 84af1b141c9..2021245c1f5 100644
--- a/addons/crm_fundraising/crm_fundraising_view.xml
+++ b/addons/crm_fundraising/crm_fundraising_view.xml
@@ -37,24 +37,6 @@
id="menu_crm_fundraising_stage_act"
parent="menu_config_fundrising" />
-
-
-
-
- Fundraising Resource Type
- crm.case.resource.type
- form
-
- [('object_id.model', '=', 'crm.fundraising')]
- {'object_id':'crm.fundraising'}
-
-
-
-
-
@@ -63,7 +45,7 @@
tree
+ colors="blue:state=='pending';grey:state in ('cancel', 'done')">
@@ -159,7 +141,7 @@
-
+
-
@@ -84,7 +85,7 @@
-
+
@@ -125,7 +126,7 @@
hr_evaluation.plan.phasetree
-
+
@@ -184,7 +185,7 @@
-
@@ -204,7 +205,7 @@
-
+
@@ -230,40 +231,40 @@
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
- Evaluation
+ Evaluationshr_evaluation.evaluationformtree,form,graph
- Each employee can be assigned to an evaluation plan. These plans define the frequency and the way you manage your periodic personnal evalautions. You will be able to define steps and attach interview forms to each step. OpenERP manages all kind of evaluations: bottom-up, top-down, self evaluation and final evaluation by the manager.
+ Each employee can be assigned to an evaluation plan. These plans define the frequency and the way you manage your periodic personnal evaluation. You will be able to define steps and attach interview forms to each step. OpenERP manages all kind of evaluations: bottom-up, top-down, self evaluation and final evaluation by the manager.
-
@@ -299,7 +300,7 @@
tree
-
+
@@ -327,26 +328,57 @@
-
+
+
+
+ Interview Request
+ hr.evaluation.interview
+ calendar
+
+
+
+
+
+
+
Interview Requestshr.evaluation.interviewform
- tree,form
+ [('is_evaluation' ,'=', True)]{"search_default_todo":1,"search_default_user_id":uid}Interview Requests are generated automatically by OpenERP according to employees evaluation plan. Each user receives automatic emails and requests to perform evaluation of their collegues periodically.
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+ calendar
+
+
+
+
+
+
+
@@ -44,15 +47,13 @@
-
-
-
+
+
+
-
-
@@ -62,24 +63,25 @@
-
-
-
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/hr_evaluation/security/ir.model.access.csv b/addons/hr_evaluation/security/ir.model.access.csv
index 181e412ce69..7c57d67d1cd 100644
--- a/addons/hr_evaluation/security/ir.model.access.csv
+++ b/addons/hr_evaluation/security/ir.model.access.csv
@@ -2,9 +2,9 @@
"access_hr_evaluation_evaluation_user","hr_evaluation.evaluation.user","model_hr_evaluation_evaluation","base.group_hr_user",1,1,1,1
"access_hr_evaluation_evaluation_manager","hr_evaluation.evaluation.manager","model_hr_evaluation_evaluation","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_plan_user","hr_evaluation.plan.user","model_hr_evaluation_evaluation","base.group_hr_user",1,0,0,0
-"access_hr_evaluation_plan_manager","hr_evaluation.plan.manager","model_hr_evaluation_plan","base.group_hr_manager",1,0,0,0
+"access_hr_evaluation_plan_manager","hr_evaluation.plan.manager","model_hr_evaluation_plan","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_plan_phase_user","hr_evaluation.plan.phase.user","model_hr_evaluation_plan_phase","base.group_hr_user",1,0,0,0
-"access_hr_evaluation_plan_phase_manager","hr_evaluation.plan.phase.manager","model_hr_evaluation_plan_phase","base.group_hr_manager",1,0,0,0
+"access_hr_evaluation_plan_phase_manager","hr_evaluation.plan.phase.manager","model_hr_evaluation_plan_phase","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_interview_user","hr.evaluation.interview.user","model_hr_evaluation_interview","base.group_hr_user",1,1,1,1
"access_hr_evaluation_interview_manager","hr.evaluation.interview.manager","model_hr_evaluation_interview","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_report","hr.evaluation.report","model_hr_evaluation_report","base.group_hr_manager",1,1,1,1
@@ -12,6 +12,10 @@
"access_hr_evaluation_plan_phase_system","hr_evaluation.plan.phase.system","model_hr_evaluation_plan_phase","base.group_system",1,1,1,1
"access_hr_evaluation_evaluation_system","hr_evaluation.evaluation.system","model_hr_evaluation_evaluation","base.group_system",1,0,0,0
"access_hr_evaluation_interview_system","hr.evaluation.interview.system","model_hr_evaluation_interview","base.group_system",1,0,0,0
+"access_hr_evaluation_evaluation_employee","hr_evaluation.evaluation.employee","model_hr_evaluation_evaluation","base.group_user",1,0,0,0
+"access_hr_evaluation_interview_employee","hr.evaluation.interview.employee","model_hr_evaluation_interview","base.group_user",1,0,0,0
+"access_hr_evaluation_user","hr_evaluation.user","model_hr_evaluation_plan","base.group_hr_user",1,1,1,1
+"access_hr_evaluation_employee","hr_evaluation.employee","model_hr_evaluation_plan","base.group_user",1,0,0,0
"access_survey_type_hr_manager","survey.type","survey.model_survey_type","base.group_hr_manager",1,1,1,1
"access_survey_hr_manager","survey.hr.manager","survey.model_survey","base.group_hr_manager",1,1,1,1
"access_survey_history_manager","survey.history","survey.model_survey_history","base.group_hr_manager",1,1,1,1
@@ -28,4 +32,11 @@
"access_survey_answer_hr_user","survey.answer.hr.user","survey.model_survey_answer","base.group_hr_user",1,1,1,0
"access_survey_response_answer_hr_user","survey.response.answer.hr.user","survey.model_survey_response_answer","base.group_hr_user",1,1,1,0
"access_survey_type_hr_user","survey.type.hr.user","survey.model_survey_type","base.group_hr_user",1,1,1,0
-"access_survey_question_hr_user","survey.question.hr.user","survey.model_survey_question","base.group_hr_user",1,1,1,0
\ No newline at end of file
+"access_survey_question_hr_user","survey.question.hr.user","survey.model_survey_question","base.group_hr_user",1,1,1,0
+"access_survey_page_hr_user","survey.page.hr.user","survey.model_survey_page","base.group_hr_user",1,1,1,1
+"access_survey_response_hr_user","survey.response.hr.user","survey.model_survey_response","base.group_hr_user",1,1,1,0
+"access_survey_history_hr_user","survey.history.hr.user","survey.model_survey_history","base.group_hr_user",1,1,1,0
+"access_survey_request_hr_user","survey.request.hr.user","survey.model_survey_request","base.group_hr_user",1,1,1,0
+"access_survey_question_column_heading_hr_user","survey.question.column.heading.hr.user","survey.model_survey_question_column_heading","base.group_hr_user",1,0,0,0
+"access_survey_response_line_hr_user","survey.response.line.hr.user","survey.model_survey_response_line","base.group_hr_user",1,1,1,0
+"access_survey_tbl_column_heading_hr_user","survey.tbl.column.heading.hr.user","survey.model_survey_tbl_column_heading","base.group_hr_user",1,1,1,0
diff --git a/addons/hr_evaluation/wizard/hr_evaluation_mail.py b/addons/hr_evaluation/wizard/hr_evaluation_mail.py
index 75aecf6a9f1..576c782bfd8 100644
--- a/addons/hr_evaluation/wizard/hr_evaluation_mail.py
+++ b/addons/hr_evaluation/wizard/hr_evaluation_mail.py
@@ -25,7 +25,7 @@ class hr_evaluation_reminder(osv.osv_memory):
_name = "hr.evaluation.reminder"
_description = "Sends Reminders to employess to fill the evaluations"
_columns = {
- 'evaluation_id': fields.many2one('hr_evaluation.evaluation', 'Evaluations', required=True)
+ 'evaluation_id': fields.many2one('hr.evaluation.interview', 'Interview', required=True)
}
def send_mail(self, cr, uid, ids, context=None):
diff --git a/addons/hr_expense/__openerp__.py b/addons/hr_expense/__openerp__.py
index fe06b0110c2..c9df8587153 100644
--- a/addons/hr_expense/__openerp__.py
+++ b/addons/hr_expense/__openerp__.py
@@ -51,6 +51,7 @@
'process/hr_expense_process.xml',
'report/hr_expense_report_view.xml',
'board_hr_expense_view.xml',
+ 'board_hr_expense_manager_view.xml'
],
'demo_xml': [
'hr_expense_demo.xml',
diff --git a/addons/hr_expense/board_hr_expense_manager_view.xml b/addons/hr_expense/board_hr_expense_manager_view.xml
new file mode 100644
index 00000000000..9063ac32458
--- /dev/null
+++ b/addons/hr_expense/board_hr_expense_manager_view.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ All Employee Expenses
+ hr.expense.expense
+ form
+ [('state','in',('confirm', 'accepted'))]
+
+
+
+
+ board.hr.manager.expense.form
+ board.board
+
+ form
+
+
+
+
+
+
+
+
+
diff --git a/addons/hr_expense/board_hr_expense_view.xml b/addons/hr_expense/board_hr_expense_view.xml
index 4b06cd758b1..69dbad767d9 100644
--- a/addons/hr_expense/board_hr_expense_view.xml
+++ b/addons/hr_expense/board_hr_expense_view.xml
@@ -13,7 +13,7 @@
My Expenseshr.expense.expenseform
- [('state','in',('draft', 'confirm')),('user_id','=',uid)]
+ [('state','in',('confirm', 'accepted')),('user_id','=',uid)]
diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py
index c5818536f8c..4003cded168 100644
--- a/addons/hr_expense/hr_expense.py
+++ b/addons/hr_expense/hr_expense.py
@@ -61,12 +61,12 @@ class hr_expense_expense(osv.osv):
_name = "hr.expense.expense"
_description = "Expense"
_columns = {
- 'name': fields.char('Expense Sheet', size=128, required=True),
+ 'name': fields.char('Description', size=128, required=True),
'id': fields.integer('Sheet ID', readonly=True),
'ref': fields.char('Reference', size=32),
'date': fields.date('Date'),
'journal_id': fields.many2one('account.journal', 'Force Journal', help = "The journal used when the expense is invoiced"),
- 'employee_id': fields.many2one('hr.employee', "Employee's Name", required=True),
+ 'employee_id': fields.many2one('hr.employee', "Employee", required=True),
'user_id': fields.many2one('res.users', 'User', required=True),
'date_confirm': fields.date('Confirmation Date', help = "Date of the confirmation of the sheet expense. It's filled when the button Confirm is pressed."),
'date_valid': fields.date('Validation Date', help = "Date of the acceptation of the sheet expense. It's filled when the button Accept is pressed."),
@@ -81,11 +81,11 @@ class hr_expense_expense(osv.osv):
'company_id': fields.many2one('res.company', 'Company', required=True),
'state': fields.selection([
('draft', 'Draft'),
- ('confirm', 'Waiting confirmation'),
- ('accepted', 'Accepted'),
+ ('confirm', 'Waiting Approval'),
+ ('accepted', 'Approved'),
('invoiced', 'Invoiced'),
('paid', 'Reimbursed'),
- ('cancelled', 'Cancelled')],
+ ('cancelled', 'Refused')],
'State', readonly=True, help='When the expense request is created the state is \'Draft\'.\n It is confirmed by the user and request is sent to admin, the state is \'Waiting Confirmation\'.\
\nIf the admin accepts it, the state is \'Accepted\'.\n If an invoice is made for the expense request, the state is \'Invoiced\'.\n If the expense is paid to user, the state is \'Reimbursed\'.'),
}
diff --git a/addons/hr_expense/hr_expense_demo.xml b/addons/hr_expense/hr_expense_demo.xml
index da348b02ab4..c3fa9e90c67 100644
--- a/addons/hr_expense/hr_expense_demo.xml
+++ b/addons/hr_expense/hr_expense_demo.xml
@@ -104,6 +104,17 @@
-
+
+ Employee Expense
+
+ [('employee_id.user_id','=',user.id)]
+
+
+
+ Manager Expense
+
+ ['|',('employee_id.user_id','=',user.id),('employee_id.parent_id.user_id','=',user.id )]
+
+
diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml
index 4d25c01e773..79c0d5513f0 100644
--- a/addons/hr_expense/hr_expense_view.xml
+++ b/addons/hr_expense/hr_expense_view.xml
@@ -27,12 +27,12 @@
tree
-
+
+
-
@@ -77,7 +77,7 @@
-
+
@@ -98,10 +98,10 @@
-
+
+
-
-
+
@@ -134,14 +134,16 @@
-
-
+
-
+
@@ -149,8 +151,9 @@
+
+
-
@@ -162,7 +165,7 @@
Expenseshr.expense.expenseform
- {"search_default_user_id":uid}
+ {"search_default_user_id":uid,'search_default_this':1}The OpenERP expenses management module allows you to track the full flow. Every month, the employees record their expenses. At the end of the month, their managers validates the expenses sheets which creates costs on projects/analytic accounts. The accountant validates the proposed entries and the employee can be reimbursed. You can also reinvoice the customer at the end of the flow.
diff --git a/addons/hr_expense/report/expense.rml b/addons/hr_expense/report/expense.rml
index 4ae45ad0aa2..fa9e78c68cd 100644
--- a/addons/hr_expense/report/expense.rml
+++ b/addons/hr_expense/report/expense.rml
@@ -181,7 +181,7 @@
-
diff --git a/addons/hr_recruitment/report/hr_recruitment_report.py b/addons/hr_recruitment/report/hr_recruitment_report.py
index 524a2265e23..2a2ab8fce2b 100644
--- a/addons/hr_recruitment/report/hr_recruitment_report.py
+++ b/addons/hr_recruitment/report/hr_recruitment_report.py
@@ -23,10 +23,10 @@ from osv import fields,osv
from hr_recruitment import hr_recruitment
AVAILABLE_STATES = [
- ('draft','Draft'),
+ ('draft','New'),
('open','Open'),
- ('cancel', 'Cancelled'),
- ('done', 'Closed'),
+ ('cancel', 'Refused'),
+ ('done', 'Hired'),
('pending','Pending')
]
@@ -69,10 +69,11 @@ class hr_recruitment_report(osv.osv):
'date_closed': fields.date('Closed', readonly=True),
'job_id': fields.many2one('hr.job', 'Applied Job',readonly=True),
'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage'),
- 'type_id': fields.many2one('crm.case.resource.type', 'Degree', domain="[('object_id.model', '=', 'hr.applicant')]"),
+ 'type_id': fields.many2one('hr.recruitment.degree', 'Degree'),
'department_id':fields.many2one('hr.department','Department',readonly=True),
'priority': fields.selection(hr_recruitment.AVAILABLE_PRIORITIES, 'Appreciation'),
'salary_prop' : fields.float("Salary Proposed"),
+ 'salary_prop_avg' : fields.float("Avg Salary Proposed", group_operator="avg"),
'salary_exp' : fields.float("Salary Expected"),
'partner_id': fields.many2one('res.partner', 'Partner',readonly=True),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact Name',readonly=True),
@@ -107,6 +108,7 @@ class hr_recruitment_report(osv.osv):
s.priority,
s.stage_id,
sum(salary_proposed) as salary_prop,
+ (sum(salary_proposed)/count(*)) as salary_prop_avg,
sum(salary_expected) as salary_exp,
extract('epoch' from (s.date_open-s.create_date))/(3600*24) as delay_open,
extract('epoch' from (s.date_closed-s.create_date))/(3600*24) as delay_close,
diff --git a/addons/hr_recruitment/report/hr_recruitment_report_view.xml b/addons/hr_recruitment/report/hr_recruitment_report_view.xml
index edb00d1f727..d1f06577fb2 100644
--- a/addons/hr_recruitment/report/hr_recruitment_report_view.xml
+++ b/addons/hr_recruitment/report/hr_recruitment_report_view.xml
@@ -21,11 +21,12 @@
-
-
-
-
+
+
+
+
+
@@ -49,18 +50,18 @@
-
-
+
-
+
+ domain="[('date','<=', (datetime.date (int(time.strftime('%%Y')), datetime.date.today().month, 1) - datetime.timedelta (days = 1)).strftime('%%Y-%%m-%%d')),('date','>',(datetime.date (int(time.strftime('%%Y')), datetime.date.today().month-1, 1)).strftime('%%Y-%%m-%%d'))]"
+ help="Recruitment during last month"/>
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -127,10 +130,10 @@
hr.recruitment.reportformtree,graph
- {'search_default_month':1,'search_default_User':1,'search_default_user_id':uid,'group_by_no_leaf':1,'group_by':[]}
+ {'search_default_month':1,'search_default_department':1,'group_by_no_leaf':1,'group_by':[]}
-
+
diff --git a/addons/hr_recruitment/security/ir.model.access.csv b/addons/hr_recruitment/security/ir.model.access.csv
index bc7bc365b00..92dc912180d 100644
--- a/addons/hr_recruitment/security/ir.model.access.csv
+++ b/addons/hr_recruitment/security/ir.model.access.csv
@@ -1,9 +1,10 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_hr_applicant_user","hr.applicant.user","model_hr_applicant","base.group_hr_user",1,1,1,1
-"access_hr_recruitment_report","hr.recruitment.report","model_hr_recruitment_report","base.group_hr_manager",1,0,0,0
+"access_hr_recruitment_report","hr.recruitment.report","model_hr_recruitment_report","base.group_hr_manager",1,1,1,1
"access_hr_recruitment_stage_user","hr.recruitment.stage.user","model_hr_recruitment_stage","base.group_hr_user",1,1,1,1
"access_hr_recruitment_degree","hr.recruitment.degree","model_hr_recruitment_degree","base.group_hr_user",1,1,1,1
"access_hr_recruitment_stage_system","hr.recruitment.stage.system","model_hr_recruitment_stage","base.group_system",1,1,1,1
-"access_hr_applicant_manager","hr.applicant.manager","model_hr_applicant","base.group_hr_manager",1,0,0,0
+"access_hr_applicant_manager","hr.applicant.manager","model_hr_applicant","base.group_hr_manager",1,1,1,1
"access_hr_applicant_system","hr.applicant.system","model_hr_applicant","base.group_system",1,0,0,0
-"access_hr_recruitment_stage_manager","hr.recruitment.stage.manager","model_hr_recruitment_stage","base.group_hr_manager",1,0,0,0
+"access_hr_recruitment_stage_manager","hr.recruitment.stage.manager","model_hr_recruitment_stage","base.group_hr_manager",1,1,1,1
+"access_hr_recruitment_degree_manager","hr.recruitment.degree.manager","model_hr_recruitment_degree","base.group_hr_manager",1,1,1,1
diff --git a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py
index 99d064a67e8..7cb5366a275 100644
--- a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py
+++ b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py
@@ -98,7 +98,7 @@ class job2phonecall(osv.osv_memory):
new_phonecall = phonecall_case_obj.browse(cr, uid, new_phonecall_id, context=context)
vals = {}
job_case_obj.write(cr, uid, [job.id], vals, context=context)
- job_case_obj.case_cancel(cr, uid, [job.id])
+# job_case_obj.case_cancel(cr, uid, [job.id])
phonecall_case_obj.case_open(cr, uid, [new_phonecall_id])
return {
diff --git a/addons/hr_timesheet/hr_timesheet.py b/addons/hr_timesheet/hr_timesheet.py
index de448ced584..ee4abdb35c4 100644
--- a/addons/hr_timesheet/hr_timesheet.py
+++ b/addons/hr_timesheet/hr_timesheet.py
@@ -64,7 +64,7 @@ class hr_analytic_timesheet(osv.osv):
if prod_id and unit_amount:
# find company
company_id = self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=context)
- res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount, company_id, unit, context=context)
+ res.update(self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount, company_id, unit, context=context))
# update unit of measurement
if prod_id:
uom = self.pool.get('product.product').browse(cr, uid, prod_id, context=context)
diff --git a/addons/hr_timesheet/hr_timesheet_view.xml b/addons/hr_timesheet/hr_timesheet_view.xml
index 6029336542d..4165f71d73f 100644
--- a/addons/hr_timesheet/hr_timesheet_view.xml
+++ b/addons/hr_timesheet/hr_timesheet_view.xml
@@ -16,8 +16,8 @@
-
+
@@ -67,16 +67,22 @@
-
-
+
+
+
+
+
+
+
+
+
+
@@ -113,7 +119,7 @@
hr.employee
-
+
diff --git a/addons/hr_timesheet/security/ir.model.access.csv b/addons/hr_timesheet/security/ir.model.access.csv
index 0b75f11e2c4..2b01017fb65 100644
--- a/addons/hr_timesheet/security/ir.model.access.csv
+++ b/addons/hr_timesheet/security/ir.model.access.csv
@@ -5,6 +5,12 @@
"access_product_product_user","product.product user","product.model_product_product","base.group_hr_user",1,0,0,0
"access_product_template_hr_timesheet","product.template.hr.timesheet","product.model_product_template","base.group_hr_user",1,0,0,0
"access_product_uom_hr_timesheet","product.uom.hr.timesheet","product.model_product_uom","base.group_hr_user",1,0,0,0
-"access_hr_analytic_timesheet_manager","hr.analytic.timesheet.manager","model_hr_analytic_timesheet","base.group_hr_manager",1,0,0,0
+"access_hr_analytic_timesheet_manager","hr.analytic.timesheet.manager","model_hr_analytic_timesheet","base.group_hr_manager",1,1,1,1
"access_hr_analytic_timesheet_system","hr.analytic.timesheet.system","model_hr_analytic_timesheet","base.group_system",1,0,0,0
+"access_hr_account_analytic_line_manager","account.account.analytic.line.manager","account.model_account_analytic_line","base.group_hr_manager",1,1,1,1
+"access_account_analytic_journal_manager","account.account.analytic.journal.manager","account.model_account_analytic_journal","base.group_hr_manager",1,1,1,1
+"access_product_product_manager","product.product.manager","product.model_product_product","base.group_hr_manager",1,1,1,1
+"access_product_template_hr_timesheet_manager","product.template.hr.timesheet.manager","product.model_product_template","base.group_hr_manager",1,1,1,1
+"access_product_uom_hr_timesheet_manager","product.uom.hr.timesheet.manager","product.model_product_uom","base.group_hr_manager",1,1,1,1
"access_hr_analytic_timesheet_employee","hr.analytic.timesheet.employee","model_hr_analytic_timesheet","base.group_user",1,1,1,0
+"access_account_analytic_line_user","account.account.analytic.line.user","account.model_account_analytic_line","base.group_user",1,0,0,0
diff --git a/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml b/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml
index 2d38011f279..ff61617661c 100644
--- a/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml
+++ b/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml
@@ -65,7 +65,7 @@
board.hr.timesheet.uninvoiced.formboard.boardform
-
+
diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py
index ed1c8394de1..7f79051edce 100644
--- a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py
+++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py
@@ -82,7 +82,7 @@ class account_analytic_line(osv.osv):
_inherit = 'account.analytic.line'
_columns = {
'invoice_id': fields.many2one('account.invoice', 'Invoice', ondelete="set null"),
- 'to_invoice': fields.many2one('hr_timesheet_invoice.factor', 'Type of Invoicing'),
+ 'to_invoice': fields.many2one('hr_timesheet_invoice.factor', 'Type of Invoicing', help="It allows to set the discount while making invoice"),
}
def unlink(self, cursor, user, ids, context=None):
diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
index 1befaebf168..6454f169fc0 100644
--- a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
+++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
@@ -21,6 +21,17 @@
+
hr.analytic.timesheet.formhr.analytic.timesheet
diff --git a/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml b/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml
index 163e641582c..ba155d3590a 100644
--- a/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml
+++ b/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml
@@ -60,7 +60,7 @@
domain="[('date','<=', time.strftime('%%Y-%%m-%%d')), ('date','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
help="Timesheet lines during last 7 days"/>
-
+
-
+
+
+
+
+
+
+
@@ -80,12 +86,6 @@
-
-
-
-
-
-
diff --git a/addons/hr_timesheet_invoice/security/ir.model.access.csv b/addons/hr_timesheet_invoice/security/ir.model.access.csv
index 7089e184f98..2dd928fc924 100644
--- a/addons/hr_timesheet_invoice/security/ir.model.access.csv
+++ b/addons/hr_timesheet_invoice/security/ir.model.access.csv
@@ -14,3 +14,7 @@
"access_report_timesheet_line","report.timesheet.line","model_report_timesheet_line","base.group_hr_manager",1,0,0,0
"access_account_invoice_hr_user","account.invoice.hr.user","account.model_account_invoice","base.group_hr_user",1,1,1,0
"access_account_fiscalyear_hr_user","account.fiscalyear.hr.user","account.model_account_fiscalyear","base.group_hr_user",1,1,1,0
+"access_account_invoice_hr_manager","account.invoice.hr.manager","account.model_account_invoice","base.group_hr_manager",1,1,1,1
+"access_hr_timesheet_invoice_factor_hr_manager","hr_timesheet_invoice.factor.hr.manager","model_hr_timesheet_invoice_factor","base.group_hr_manager",1,1,1,1
+"access_account_invoice_tax_hr_manager","account.invoice.tax.hr.manager","account.model_account_invoice_tax","base.group_hr_manager",1,1,1,1
+"access_report_timesheet_line_employee","report.timesheet.line.employee","model_report_timesheet_line","base.group_user",1,1,1,0
diff --git a/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml b/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml
index 1fa5206fa90..f299cb94298 100644
--- a/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml
+++ b/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml
@@ -52,7 +52,7 @@
board.hr.timesheet.formboard.board
-
+ form
@@ -77,5 +77,31 @@
+
+ My Total Attendances By Week
+ hr_timesheet_sheet.sheet
+ form
+ graph
+ [('user_id','=',uid)]
+
+
+
+ board.hr.timesheet.sheet.form
+ board.board
+
+ form
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
index d9b666cfbf1..19a9af3c33d 100644
--- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
@@ -148,10 +148,10 @@
-
+
-
+
@@ -313,7 +313,17 @@
-
+
+ hr.timesheet.sheet.sheet.graph
+ hr_timesheet_sheet.sheet
+ graph
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/report/hr_timesheet_report.py b/addons/hr_timesheet_sheet/report/hr_timesheet_report.py
index 100041ca35a..84ef868ab81 100644
--- a/addons/hr_timesheet_sheet/report/hr_timesheet_report.py
+++ b/addons/hr_timesheet_sheet/report/hr_timesheet_report.py
@@ -28,6 +28,7 @@ class hr_timesheet_report(osv.osv):
_auto = False
_columns = {
'year': fields.char('Year',size=64,required=False, readonly=True),
+ 'day': fields.char('Day', size=128, readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
@@ -50,6 +51,7 @@ class hr_timesheet_report(osv.osv):
select
min(t.id) as id,
l.date as date,
+ to_char(l.date, 'YYYY-MM-DD') as day,
to_char(l.date,'YYYY') as year,
to_char(l.date,'MM') as month,
sum(l.amount) as cost,
diff --git a/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml b/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml
index 4515215e4a1..9c0588f618e 100644
--- a/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml
+++ b/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml
@@ -21,7 +21,7 @@
-
+
@@ -41,37 +41,23 @@
-
-
+
-
+ domain="[('date','<=', time.strftime('%%Y-%%m-%%d')),('date','>=',time.strftime('%%Y-%%m-01'))]"
+ help="Timesheet in current month"/>
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -81,6 +67,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/report/timesheet_report_view.xml b/addons/hr_timesheet_sheet/report/timesheet_report_view.xml
index a786a123529..08abc6db63b 100644
--- a/addons/hr_timesheet_sheet/report/timesheet_report_view.xml
+++ b/addons/hr_timesheet_sheet/report/timesheet_report_view.xml
@@ -49,18 +49,17 @@
-
-
+
-
+ help="Timesheet in current month"/>
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -91,23 +104,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/addons/hr_timesheet_sheet/security/ir.model.access.csv b/addons/hr_timesheet_sheet/security/ir.model.access.csv
index de19d325f5f..116396612e8 100644
--- a/addons/hr_timesheet_sheet/security/ir.model.access.csv
+++ b/addons/hr_timesheet_sheet/security/ir.model.access.csv
@@ -5,7 +5,7 @@
"access_hr_timesheet_report","hr.timesheet.report","model_hr_timesheet_report","base.group_hr_manager",1,1,1,1
"access_hr_timesheet_sheet_sheet_manager","hr_timesheet_sheet.sheet.manager","model_hr_timesheet_sheet_sheet","base.group_hr_manager",1,1,1,1
"access_hr_timesheet_sheet_sheet_system","hr_timesheet_sheet.sheet.system","model_hr_timesheet_sheet_sheet","base.group_system",1,0,0,0
-"access_timesheet_report_manager","timesheet.report.manager","model_timesheet_report","base.group_hr_manager",1,1,1,1
+"access_timesheet_report_employee","timesheet.report.employee","model_timesheet_report","base.group_user",1,1,1,0
"access_hr_timesheet_sheet_sheet_employee","hr_timesheet_sheet.sheet.employee","model_hr_timesheet_sheet_sheet","base.group_user",1,1,1,0
"access_hr_timesheet_sheet_sheet_day_manager","hr_timesheet_sheet.sheet.day.manager","model_hr_timesheet_sheet_sheet_day","base.group_hr_manager",1,1,1,1
"access_hr_timesheet_sheet_sheet_account_manager","hr_timesheet_sheet.sheet.account.manager","model_hr_timesheet_sheet_sheet_account","base.group_hr_manager",1,1,1,1
diff --git a/addons/idea/report/report_vote_view.xml b/addons/idea/report/report_vote_view.xml
index 201bdd40721..9556f86a281 100644
--- a/addons/idea/report/report_vote_view.xml
+++ b/addons/idea/report/report_vote_view.xml
@@ -31,15 +31,15 @@
+ help="Idea Vote created in curren year"/>
+ help="Idea Vote created in current month"/>
+ help="Idea Vote created last month"/>
-
+
-
+
diff --git a/addons/lunch/test/test_lunch.yml b/addons/lunch/test/test_lunch.yml
index 6af4113f153..3183764d927 100644
--- a/addons/lunch/test/test_lunch.yml
+++ b/addons/lunch/test/test_lunch.yml
@@ -1,23 +1,23 @@
- |
- In order to test the Lunch module in OpenERP,
+ In order to test the Lunch module in OpenERP,
I will create one lunch order and then check the effect on cashboxes and cashmoves
-
+
- |
Given that I have a category of lunch products "Burger".
--
+-
!record {model: lunch.category, id: lunch_category_burger0}:
name: Burger
- |
Given that I have a product "Club1" in this category with a price of "2.75".
--
+-
!record {model: lunch.product, id: lunch_product_club1}:
category_id: lunch_category_burger0
name: Club1
- price: 2.75
+ price: 2.75
- |
Given that I have a cashbox "Employee Cashbox"
--
+-
!record {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
manager: base.user_root
name: Employee Cashbox
@@ -25,87 +25,87 @@
I create a lunch order "LU001" for the "Club1" product
- |
When I select the product "club1", the price of 2.75 is automatically proposed
--
+-
!record {model: lunch.order, id: lunch_order_0}:
date: '2010-04-19'
product: 'lunch_product_club1'
price: 2.75
user_id: base.user_root
-
+
- |
I check that lunch order is on draft state after having created it.
-
!assert {model: lunch.order, id: lunch_order_0}:
- - state == 'draft'
+ - state == 'draft'
- |
I confirm the order "LU001" using the "Confirm Order" wizard.
--
+-
!record {model: lunch.order.confirm, id: lunch_order_confirm_0}:
confirm_cashbox: 'lunch_cashbox_cashbox0'
-
- I click on "Confirm Order" button of this wizard.
+ I click on "Confirm Order" button of this wizard.
-
!python {model: lunch.order.confirm}: |
- self.confirm(cr, uid, [ref('lunch_order_confirm_0')], {'active_ids': [ref('lunch_order_0')]})
-
+ self.confirm(cr, uid, [ref('lunch_order_confirm_0')], {'active_ids': [ref('lunch_order_0')]})
+
- |
I check that the Cash Moves have been generated with the right box
name
-
- !assert {model: lunch.order, id: lunch_order_0}:
+ !assert {model: lunch.order, id: lunch_order_0}:
- cashmove.id != False
-
+
- |
I check that the Total on the "Employee Cashbox" is -2.75
-
+
-
!assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
- sum_remain == -2.75
-
+
- |
I create a new lunch order "LU002" for the "Club1" product, at another date.
--
+-
!record {model: lunch.order, id: lunch_order_1}:
date: '2010-04-22'
product: 'lunch_product_club1'
price: 2.75
user_id: base.user_root
-
+
- |
I confirm this order.open wizard and select "Employee Cashbox".
--
+-
!record {model: lunch.order.confirm, id: lunch_order_confirm_1}:
confirm_cashbox: 'lunch_cashbox_cashbox0'
- |
- Now I click on "Confirm Order" button of this wizard.
+ Now I click on "Confirm Order" button of this wizard.
-
!python {model: lunch.order.confirm}: |
self.confirm(cr, uid, [ref('lunch_order_confirm_1')], {'active_ids': [ref('lunch_order_1')]})
-
+
- |
I check that the Total on the "Employee Cashbox" is -5.50
-
!assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
- - sum_remain == -5.50
+ - sum_remain == -5.50
- |
I cancel the order "LU002"
--
+-
!record {model: lunch.order.cancel, id: lunch_order_cancel_0}:
{}
- |
- I click on "Yes" button of this wizard for cancel order.
-
+ I click on "Yes" button of this wizard for cancel order.
+
-
!python {model: lunch.order.cancel}: |
self.cancel(cr, uid, [ref('lunch_order_cancel_0')], {'active_ids': [ref('lunch_order_1')]})
-
+
- |
I test that the Cash Moves record have been removed for the order LU002.
-
- !assert {model: lunch.order, id: lunch_order_1}:
+ !assert {model: lunch.order, id: lunch_order_1}:
- cashmove.id == False
-
+
- |
I check that the Total on the "Employee Cashbox" is -2.75
-
@@ -113,7 +113,7 @@
- sum_remain == -2.75
- |
I reset the "Employee Cashbox" to zero using the "Set CashBox to Zero" wizard.
--
+-
!record {model: lunch.cashbox.clean, id: lunch_cashbox_clean_0}:
{}
-
@@ -121,10 +121,10 @@
-
!python {model: lunch.cashbox.clean, id: lunch_cashbox_clean_0}: |
self.set_to_zero(cr, uid, [ref('lunch_cashbox_clean_0')], {'active_ids': [ref('lunch_cashbox_cashbox0')]})
-
+
- |
- I check that the Total on the "Employee Cashbox" is 0.0
+ I check that the Total on the "Employee Cashbox" is -5.50
-
!assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
- sum_remain == 0.00
-
+
diff --git a/addons/mrp/installer.py b/addons/mrp/installer.py
index eeb00ece494..407d401e463 100644
--- a/addons/mrp/installer.py
+++ b/addons/mrp/installer.py
@@ -28,7 +28,7 @@ class mrp_installer(osv.osv_memory):
# Manufacturing Resource Planning
'stock_location': fields.boolean('Advanced Routes',
help="Manages product routes and paths within and between "
- "locations (e.g. warehouses)"),
+ "locations (e.g. warehouses)."),
'mrp_jit': fields.boolean('Just In Time Scheduling',
help="Enables Just In Time computation of procurement orders."
"\n\nWhile it's more resource intensive than the default "
@@ -37,7 +37,7 @@ class mrp_installer(osv.osv_memory):
"procurement scheduler manually."),
'mrp_operations': fields.boolean('Manufacturing Operations',
help="Enhances production orders with readiness states as well "
- "as the date of start and end of execution of the order."),
+ "as the start date and end date of execution of the order."),
'mrp_subproduct': fields.boolean('MRP Subproducts',
help="Enables multiple product output from a single production "
"order: without this, a production order can have only one "
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index 4fadcdce471..7aafee1a447 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -428,7 +428,7 @@ class mrp_repair(osv.osv):
raise osv.except_osv(_('Warning !'), _('No product defined on Fees!'))
if fee.product_id.property_account_income:
- account_id = fee.product_id.property_account_income
+ account_id = fee.product_id.property_account_income.id
elif fee.product_id.categ_id.property_account_income_categ:
account_id = fee.product_id.categ_id.property_account_income_categ.id
else:
diff --git a/addons/process/process_view.xml b/addons/process/process_view.xml
index b743c82f84f..f33af42c533 100644
--- a/addons/process/process_view.xml
+++ b/addons/process/process_view.xml
@@ -35,7 +35,7 @@
-
+
@@ -74,14 +74,14 @@
-
+
-
+
@@ -114,7 +114,7 @@
-
+
@@ -160,7 +160,7 @@
-
+
@@ -199,7 +199,7 @@
-
+
@@ -220,8 +220,8 @@
-
-
+
+
@@ -261,9 +261,8 @@
form
-
+
-
@@ -308,11 +307,13 @@
+
diff --git a/addons/product/security/ir.model.access.csv b/addons/product/security/ir.model.access.csv
index 1e1572a3c0a..7b8da0dd675 100644
--- a/addons/product/security/ir.model.access.csv
+++ b/addons/product/security/ir.model.access.csv
@@ -40,3 +40,4 @@
"access_product_ul_system","product.ul system","model_product_ul","base.group_system",1,1,1,1
"access_product_product_system","product.product system","model_product_product","base.group_system",1,0,0,0
"access_product_category_system","product.category.system","model_product_category","base.group_system",1,1,1,1
+"access_product_product_employee","product.product employee","model_product_product","base.group_user",1,0,0,0
diff --git a/addons/profile_tools/installer.py b/addons/profile_tools/installer.py
index 1e2ff655353..06be50a903f 100644
--- a/addons/profile_tools/installer.py
+++ b/addons/profile_tools/installer.py
@@ -25,9 +25,9 @@ class misc_tools_installer(osv.osv_memory):
_inherit = 'res.config.installer'
_columns = {
- 'lunch':fields.boolean('Lunch',help='Helps to manage Lunch Orders'),
- 'subscription':fields.boolean('Recurring Documents',help='Helps to add subscription on documents'),
- 'survey':fields.boolean('Survey',help='Manages Custom Surveys'),
+ 'lunch':fields.boolean('Lunch',help='Helps to manage Lunch Orders.'),
+ 'subscription':fields.boolean('Recurring Documents',help='Helps to add subscription on documents.'),
+ 'survey':fields.boolean('Survey',help='Manages Custom Surveys.'),
'idea':fields.boolean('Idea',help='Manages ideas and votes'),
'audittrail':fields.boolean('Audit Trail',help="Lets you to track user's operations on specific Objects."),
}
diff --git a/addons/project/installer.py b/addons/project/installer.py
index ef2c2b5e8c8..4662ebeda5d 100644
--- a/addons/project/installer.py
+++ b/addons/project/installer.py
@@ -31,32 +31,29 @@ class project_installer(osv.osv_memory):
'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',
- help=""),
'hr_timesheet_sheet': fields.boolean('Timesheets',
help="Tracks and helps employees encode and validate timesheets "
- "and attendance."),
+ "and attendances."),
'hr_timesheet_invoice': fields.boolean('Invoice Based on Hours',
- help="Helps generate invoice based on human resources "
+ help="Helps generate invoices based on human resources "
"costs and general expenses."),
'account_budget': fields.boolean('Budgets',
help="Helps accountants manage analytic and crossover budgets."),
'project_messages': fields.boolean('Project Messages',
help="Lets employees send messages to other members of the "
"projects they're working on."),
- 'project_crm': fields.boolean('Issues Tracker',
+ 'project_issue': fields.boolean('Issues Tracker',
help="Automatically synchronizes project tasks and crm cases."),
# Methodologies
'project_scrum': fields.boolean('SCRUM',
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 "
- "project management."),
+ help="GTD is a methodology to efficiently organise yourself and your tasks. This module fully integrates GTD principle with OpenERP's project management."),
}
_defaults={
- 'project_crm': True,
+ 'project_issue': True,
}
project_installer()
diff --git a/addons/project/project.py b/addons/project/project.py
index 6959a19fd03..274263682a6 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -251,7 +251,7 @@ class project(osv.osv):
context['active_test'] = False
default['state'] = 'open'
if not default.get('name', False):
- default['name'] = proj.name+_(' (copy)')
+ default['name'] = proj.name + _(' (copy)')
res = super(project, self).copy(cr, uid, id, default, context)
return res
@@ -393,6 +393,8 @@ class task(osv.osv):
if not default.get('remaining_hours', False):
default['remaining_hours'] = float(self.read(cr, uid, id, ['planned_hours'])['planned_hours'])
default['active'] = True
+ if not default.get('name', False):
+ default['name'] = self.browse(cr, uid, id, context=context).name + _(' (copy)')
return super(task, self).copy_data(cr, uid, id, default, context)
def _check_dates(self, cr, uid, ids, context=None):
@@ -401,7 +403,7 @@ class task(osv.osv):
if task['date_start'] > task['date_end']:
return False
return True
-
+
def _is_template(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for task in self.browse(cr, uid, ids, context=context):
@@ -415,7 +417,7 @@ class task(osv.osv):
'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),
'description': fields.text('Description'),
- 'priority' : fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Urgent'), ('0','Very urgent')], 'Importance'),
+ 'priority' : fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Urgent'), ('0','Very urgent')], 'Priority'),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of tasks."),
'type_id': 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,
@@ -425,8 +427,7 @@ class task(osv.osv):
'date_start': fields.datetime('Starting Date'),
'date_end': fields.datetime('Ending Date'),
'date_deadline': fields.date('Deadline'),
- '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."),
+ 'project_id': fields.many2one('project.project', 'Project', ondelete='cascade'),
'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'),
'child_ids': fields.many2many('project.task', 'project_task_parent_rel', 'parent_id', 'task_id', 'Delegated Tasks'),
'notes': fields.text('Notes'),
@@ -457,15 +458,15 @@ class task(osv.osv):
}
_order = "sequence, priority, date_start, id"
-
+
def _check_recursion(self, cr, uid, ids):
obj_task = self.browse(cr, uid, ids[0])
parent_ids = [x.id for x in obj_task.parent_ids]
children_ids = [x.id for x in obj_task.child_ids]
-
+
if (obj_task.id in children_ids) or (obj_task.id in parent_ids):
return False
-
+
while(ids):
cr.execute('SELECT DISTINCT task_id '\
'FROM project_task_parent_rel '\
@@ -518,6 +519,26 @@ class task(osv.osv):
res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm)
return res
+ def action_close(self, cr, uid, ids, context=None):
+ # This action open wizard to send email to partner or project manager after close task.
+ project_id = len(ids) and ids[0] or False
+ if not project_id: return False
+ task = self.browse(cr, uid, project_id, context=context)
+ project = task.project_id
+ res = self.do_close(cr, uid, [project_id], context=context)
+ if project.warn_manager or project.warn_customer:
+ return {
+ 'name': _('Send Email after close task'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'project.task.close',
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'nodestroy': True,
+ 'context': {'active_id': task.id}
+ }
+ return res
+
def do_close(self, cr, uid, ids, context=None):
"""
Close Task
@@ -539,7 +560,7 @@ class task(osv.osv):
'ref_doc1': 'project.task,%d'% (task.id,),
'ref_doc2': 'project.project,%d'% (project.id,),
})
-
+
for parent_id in task.parent_ids:
if parent_id.state in ('pending','draft'):
reopen = True
diff --git a/addons/project/project_installer.xml b/addons/project/project_installer.xml
index e12fa4d3815..2c22a4b6743 100644
--- a/addons/project/project_installer.xml
+++ b/addons/project/project_installer.xml
@@ -24,9 +24,8 @@
Configure
-
+
-
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index 421729ccda5..f8fe814e218 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -21,8 +21,8 @@
-
-
+
+
@@ -43,12 +43,13 @@
+
-
+
-
+
-
+
@@ -239,7 +240,7 @@
-
+
@@ -300,8 +301,11 @@
+
+
+
-
-
+
@@ -369,8 +372,8 @@
-
-
+
+
-
+
@@ -397,9 +400,10 @@
+
+
-
@@ -414,10 +418,7 @@
{"search_default_project_id":project_id, "search_default_user_id":uid, "search_default_current": 1}
- 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.
-
-Issues like bugs in a system, client complain, materials breakdown are collected here.A list view allows the manager to quickly check for them, assign them, make their status evolved.
-
+ 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.
@@ -486,10 +487,10 @@ Issues like bugs in a system, client complain, materials breakdown are collected
-
+
-
-
+
+
diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py
index b9c22faee8b..e411248db4b 100644
--- a/addons/project/report/project_report.py
+++ b/addons/project/report/project_report.py
@@ -49,7 +49,7 @@ class report_project_task_user(osv.osv):
'delay_endings_days': fields.float('Overpassed Deadline', digits=(16,2), readonly=True),
'nbr': fields.integer('# of tasks', readonly=True),
'priority' : fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Urgent'),
-('0','Very urgent')], 'Importance', readonly=True),
+('0','Very urgent')], 'Priority', readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')], 'Month', readonly=True),
'state': fields.selection([('draft', 'Draft'), ('open', 'In Progress'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')],'State', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True, groups="base.group_multi_company"),
diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml
index f269399877c..1ae5adc489a 100644
--- a/addons/project/report/project_report_view.xml
+++ b/addons/project/report/project_report_view.xml
@@ -58,18 +58,18 @@
-
-
+
+ domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')),('date_start','>=',time.strftime('%%Y-%%m-01'))]"
+ help="Current Month"/>
+ domain="[('date_start','<=', (datetime.date (int(time.strftime('%%Y')), datetime.date.today().month, 1) - datetime.timedelta (days = 1)).strftime('%%Y-%%m-%%d')),('date_start','>',(datetime.date (int(time.strftime('%%Y')), datetime.date.today().month-1, 1)).strftime('%%Y-%%m-%%d'))]"
+ help="Previous Month"/>
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml
index f968ffc51a3..97453dcb33b 100644
--- a/addons/project/security/project_security.xml
+++ b/addons/project/security/project_security.xml
@@ -6,6 +6,10 @@
Project / Financial Manager
+
+ Project / Financial User
+
+
Project / Manager
@@ -43,5 +47,12 @@
['|','|','|',('user_id','=',False),('user_id','=',user.id),('project_id.members','in', [user.id]),('project_id.user_id','=',user.id)]
+
+ Projects According to User
+
+
+ [('user_id','=',user.id)]
+
+
diff --git a/addons/project/wizard/project_task_close.py b/addons/project/wizard/project_task_close.py
index 99b6caef308..78ffa5a8338 100644
--- a/addons/project/wizard/project_task_close.py
+++ b/addons/project/wizard/project_task_close.py
@@ -56,24 +56,18 @@ class project_task_close(osv.osv_memory):
partner = task.partner_id or task.project_id.partner_id
if 'description' in fields:
- res.update({'description': task.description})
+ res.update({'description': task.description or False})
if 'manager_warn' in fields:
- res.update({'manager_warn': project.warn_manager})
+ res.update({'manager_warn': project.warn_manager or False})
if 'partner_warn' in fields:
- res.update({'partner_warn': project.warn_customer})
+ res.update({'partner_warn': project.warn_customer or False})
if 'manager_email' in fields:
res.update({'manager_email': manager and manager.user_email or False})
if partner and len(partner.address) and 'partner_email' in fields:
res.update({'partner_email': partner.address[0].email})
return res
- def done(self, cr, uid, ids, context=None):
- task_pool = self.pool.get('project.task')
- task_id = context.get('active_id', False)
- res = task_pool.do_close(cr, uid, [task_id], context=context)
- return res
-
- def confirm(self, cr, uid, ids, context=None):
+ def send(self, cr, uid, ids, context=None):
if context is None:
context = {}
@@ -83,7 +77,6 @@ class project_task_close(osv.osv_memory):
return {}
task = task_pool.browse(cr, uid, task_id, context=context)
for data in self.browse(cr, uid, ids, context=context):
- res = task_pool.do_close(cr, uid, [task.id], context=context)
if res:
# Send Warn Message by Email to Manager and Customer
if data.manager_warn and not data.manager_email:
diff --git a/addons/project/wizard/project_task_close_view.xml b/addons/project/wizard/project_task_close_view.xml
index 9692fe9a733..6c064784827 100644
--- a/addons/project/wizard/project_task_close_view.xml
+++ b/addons/project/wizard/project_task_close_view.xml
@@ -3,34 +3,32 @@
- Done Task
+ Send Emailproject.task.closeform
-
-
+
-
+
-
+
-
-
-
+
+
- Done Task
+ Send Emailir.actions.act_windowproject.task.closeform
diff --git a/addons/project/wizard/project_task_delegate.py b/addons/project/wizard/project_task_delegate.py
index 2ce74ceefc8..2430b8a0896 100644
--- a/addons/project/wizard/project_task_delegate.py
+++ b/addons/project/wizard/project_task_delegate.py
@@ -30,7 +30,7 @@ class project_task_delegate(osv.osv_memory):
_columns = {
'name': fields.char('Delegated Title', size=64, required=True, help="New title of the task delegated to the user"),
- 'prefix': fields.char('Your Task Title', size=64, required=True, help="New title of your own task to validate the work done"),
+ 'prefix': fields.char('Your Task Title', size=64, required=True, help="Title for your validation task"),
'user_id': fields.many2one('res.users', 'Assign To', required=True, help="User you want to delegate this task to"),
'new_task_description': fields.text('New Task Description', help="Reinclude the description of the task in the task of the user"),
'planned_hours': fields.float('Planned Hours', help="Estimated time to close this task by the delegated user"),
@@ -51,7 +51,7 @@ class project_task_delegate(osv.osv_memory):
project = task.project_id
manager = project.user_id or False
partner = task.partner_id or task.project_id.partner_id
-
+
if 'name' in fields:
if task.name.startswith(_('CHECK: ')):
newname = str(task.name).replace(_('CHECK: '), '')
diff --git a/addons/project/wizard/project_task_delegate_view.xml b/addons/project/wizard/project_task_delegate_view.xml
index 7bedecd8f53..dc299826419 100644
--- a/addons/project/wizard/project_task_delegate_view.xml
+++ b/addons/project/wizard/project_task_delegate_view.xml
@@ -15,17 +15,17 @@
-
+
-
+
-
+
-
+
diff --git a/addons/project/wizard/project_task_reevaluate_view.xml b/addons/project/wizard/project_task_reevaluate_view.xml
index 5e0e7c89069..db7bda3afe7 100644
--- a/addons/project/wizard/project_task_reevaluate_view.xml
+++ b/addons/project/wizard/project_task_reevaluate_view.xml
@@ -1,7 +1,7 @@
-
+
Re-evaluate Taskproject.task.reevaluate
@@ -14,7 +14,7 @@
-
+
diff --git a/addons/project_gtd/project_gtd.py b/addons/project_gtd/project_gtd.py
index 46031048ae9..f29780126e0 100644
--- a/addons/project_gtd/project_gtd.py
+++ b/addons/project_gtd/project_gtd.py
@@ -114,7 +114,7 @@ class project_task(osv.osv):
if res['type'] == 'search':
tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[]))
search_extended ='''''' % (len(tt)+7,_('Getting Things Done'))
- search_extended += '''''' % (_('Inbox'),)
+ search_extended += '''''' % (_('Inbox'),)
search_extended += ''''''
for time in tt:
if time.icon:
diff --git a/addons/project_gtd/project_gtd_view.xml b/addons/project_gtd/project_gtd_view.xml
index 5672fdafa7c..99e87fcb325 100644
--- a/addons/project_gtd/project_gtd_view.xml
+++ b/addons/project_gtd/project_gtd_view.xml
@@ -19,7 +19,7 @@
form
-
+
@@ -53,7 +53,7 @@
-
+
diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py
index 5c5a8907dc9..05e047914b7 100644
--- a/addons/project_issue/project_issue.py
+++ b/addons/project_issue/project_issue.py
@@ -70,7 +70,7 @@ class project_issue(crm.crm_case, osv.osv):
message = _('Issue ') + " '" + name + "' "+ _("is Closed.")
self.log(cr, uid, id, message)
return res
-
+
def _compute_day(self, cr, uid, ids, fields, args, context=None):
if context is None:
context = {}
@@ -152,7 +152,7 @@ class project_issue(crm.crm_case, osv.osv):
domain="[('partner_id','=',partner_id)]"),
'company_id': fields.many2one('res.company', 'Company'),
'description': fields.text('Description'),
- 'state': fields.selection([('draft', 'Draft'), ('open', 'Todo'), ('cancel', 'Cancelled'), ('done', 'Closed'),('pending', 'Pending'), ], 'State', size=16, readonly=True,
+ 'state': fields.selection([('draft', 'Draft'), ('open', 'To Do'), ('cancel', 'Cancelled'), ('done', 'Closed'),('pending', 'Pending'), ], 'State', size=16, readonly=True,
help='The state is set to \'Draft\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
@@ -409,7 +409,7 @@ class project(osv.osv):
'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.', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
'reply_to' : fields.char('Reply-To Email Address', size=256)
}
-
+
def _check_escalation(self, cr, uid, ids):
project_obj = self.browse(cr, uid, ids[0])
if project_obj.project_escalation_id:
diff --git a/addons/project_issue/project_issue_data.xml b/addons/project_issue/project_issue_data.xml
index 1c7f5c73c77..b5fa80b96bd 100644
--- a/addons/project_issue/project_issue_data.xml
+++ b/addons/project_issue/project_issue_data.xml
@@ -22,19 +22,16 @@
Version 4.2
- Version 5.0
- Version 6.0
-
diff --git a/addons/project_issue/project_issue_menu.xml b/addons/project_issue/project_issue_menu.xml
index 9c074ed2fd3..df76e808bff 100644
--- a/addons/project_issue/project_issue_menu.xml
+++ b/addons/project_issue/project_issue_menu.xml
@@ -12,10 +12,10 @@
formtree,calendar
-
+ {"search_default_user_id": uid, "search_default_current":1, "search_default_project_id":project_id}
- Issues like bugs in a system, client complain, materials breakdown are collected here.A list view allows the manager to quickly check for them, assign them, make their status evolved.
+ Issues like bugs in a system, client complain, materials breakdown are collected here. A list view allows the manager to quickly check for them, assign them, make their status evolved.
@@ -40,7 +40,7 @@
-
+
@@ -75,10 +75,10 @@
-
+
-
+
-
+
@@ -117,7 +117,7 @@
-
@@ -157,13 +157,13 @@
project.issuetree
-
+
-
+
@@ -174,11 +174,12 @@
-
+
+
@@ -190,8 +191,8 @@
-
-
+
+
@@ -204,25 +205,31 @@
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+ domain="[]" context="{'group_by':'create_date'}" help="Creation Month"/>
@@ -254,7 +261,7 @@
-
+
@@ -316,6 +323,6 @@
-
+
diff --git a/addons/project_issue/report/project_issue_report.py b/addons/project_issue/report/project_issue_report.py
index bf8085ba932..41ebaa3243e 100644
--- a/addons/project_issue/report/project_issue_report.py
+++ b/addons/project_issue/report/project_issue_report.py
@@ -87,7 +87,7 @@ class project_issue_report(osv.osv):
'company_id' : fields.many2one('res.company', 'Company'),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'project_id':fields.many2one('project.project', 'Project',readonly=True),
- 'type_id': fields.many2one('crm.case.resource.type', 'Version', domain="[('object_id.model', '=', 'project.issue')]"),
+ 'type_id': fields.many2one('crm.case.resource.type', 'Version'),
'assigned_to' : fields.many2one('res.users', 'Assigned to',readonly=True),
'partner_id': fields.many2one('res.partner','Partner',domain="[('object_id.model', '=', 'project.issue')]"),
'canal_id': fields.many2one('res.partner.canal', 'Channel',readonly=True),
diff --git a/addons/project_issue/report/project_issue_report_view.xml b/addons/project_issue/report/project_issue_report_view.xml
index 9ceded378ba..d1b421d59ca 100644
--- a/addons/project_issue/report/project_issue_report_view.xml
+++ b/addons/project_issue/report/project_issue_report_view.xml
@@ -54,14 +54,16 @@
-
+
-
-
-
+
+
@@ -83,7 +86,7 @@
+ help="My Sale Team" />
@@ -96,7 +99,7 @@
-
+
@@ -108,45 +111,42 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
-
-
-
-
+ domain="[]" context="{'group_by':'day'}" help="Current Day"/>
+ domain="[]" context="{'group_by':'month'}" help="Current Month"/>
+ domain="[]" context="{'group_by':'name'}" help="Current Year"/>
-
diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py
index 79baff679cc..79837416d97 100644
--- a/addons/project_long_term/project_long_term.py
+++ b/addons/project_long_term/project_long_term.py
@@ -21,9 +21,10 @@
import time
from datetime import date, datetime, timedelta
-
from tools.translate import _
from osv import fields, osv
+from resource.faces import task as Task
+import operator
class project_phase(osv.osv):
_name = "project.phase"
@@ -181,38 +182,55 @@ class project_phase(osv.osv):
uom_obj = self.pool.get('product.uom')
if context is None:
context = {}
+ res = super(project_phase, self).write(cr, uid, ids, vals, context=context)
if context.get('scheduler',False):
- return super(project_phase, self).write(cr, uid, ids, vals, context=context)
+ return res
# Consider calendar and efficiency if the phase is performed by a resource
# otherwise consider the project's working calendar
+
+ #TOCHECK : why need this ?
if isinstance(ids, (int, long)):
ids = [ids]
- phase = self.browse(cr, uid, ids[0], context=context)
- calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)],context=context)
- if resource_id:
+ default_uom_id = self._get_default_uom_id(cr, uid)
+ for phase in self.browse(cr, uid, ids, context=context):
+ calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
+ resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)],context=context)
+ if resource_id:
cal_id = resource_obj.browse(cr, uid, resource_id[0], context=context).calendar_id.id
if cal_id:
calendar_id = cal_id
- default_uom_id = self._get_default_uom_id(cr, uid)
- avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
- # Change the date_start and date_end
- # for previous and next phases respectively based on valid condition
- if vals.get('date_start', False) and vals['date_start'] < phase.date_start:
+
+ avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
+ # Change the date_start and date_end
+ # for previous and next phases respectively based on valid condition
+ if vals.get('date_start', False) and vals['date_start'] < phase.date_start:
dt_start = datetime.strptime(vals['date_start'], '%Y-%m-%d')
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id, dt_start, avg_hours or 0.0, resource_id and resource_id[0] or False)
if work_times:
vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d')
for prv_phase in phase.previous_phase_ids:
+ if prv_phase.id == phase.id:
+ continue
self._check_date_start(cr, uid, prv_phase, dt_start, context=context)
- if vals.get('date_end', False) and vals['date_end'] > phase.date_end:
+
+ if vals.get('date_end', False) and vals['date_end'] > phase.date_end:
dt_end = datetime.strptime(vals['date_end'], '%Y-%m-%d')
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id, dt_end, avg_hours or 0.0, resource_id and resource_id[0] or False)
if work_times:
vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d')
for next_phase in phase.next_phase_ids:
+ if next_phase.id == phase.id:
+ continue
self._check_date_end(cr, uid, next_phase, dt_end, context=context)
- return super(project_phase, self).write(cr, uid, ids, vals, context=context)
+
+ return res
+
+ def copy(self, cr, uid, id, default=None, context=None):
+ if default is None:
+ default = {}
+ if not default.get('name', False):
+ default['name'] = self.browse(cr, uid, id, context=context).name + _(' (copy)')
+ return super(project_phase, self).copy(cr, uid, id, default, context)
def set_draft(self, cr, uid, ids, *args):
self.write(cr, uid, ids, {'state': 'draft'})
@@ -234,6 +252,118 @@ class project_phase(osv.osv):
self.write(cr, uid, ids, {'state': 'done'})
return True
+ def generate_resources(self, cr, uid, ids, context=None):
+ """
+ Return a list of Resource Class objects for the resources allocated to the phase.
+ """
+ res = {}
+ if context is None:
+ context = {}
+ resource_pool = self.pool.get('resource.resource')
+ for phase in self.browse(cr, uid, ids, context=context):
+ user_ids = map(lambda x:x.resource_id.user_id.id, phase.resource_ids)
+ project = phase.project_id
+ calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
+ resource_objs = resource_pool.generate_resources(cr, uid, user_ids, calendar_id, context=context)
+ res[phase.id] = resource_objs
+ return res
+
+ def generate_schedule(self, cr, uid, ids, start_date, calendar_id=False, context=None):
+ """
+ Schedule phase with the start date till all the next phases are completed.
+ @param: start_dsate : start date for the phase
+ @param: calendar_id : working calendar of the project
+ """
+ if context is None:
+ context = {}
+ resource_pool = self.pool.get('resource.resource')
+ uom_pool = self.pool.get('product.uom')
+ phase_resource = False
+ if context is None:
+ context = {}
+ default_uom_id = self._get_default_uom_id(cr, uid)
+ for phase in self.browse(cr, uid, ids, context=context):
+ 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 = resource_pool.generate_resources(cr, uid, [phase.responsible_id.id], calendar_id, context=context)
+ avg_hours = uom_pool._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
+ duration = str(avg_hours) + 'H'
+ # Create a new project for each phase
+ def Project():
+ start = start_date
+ minimum_time_unit = 1
+ resource = phase_resource_obj
+ # If project has working calendar then that
+ # else the default one would be considered
+ if calendar_id:
+ working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
+ vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id))
+
+ def phase():
+ effort = duration
+
+ project = Task.BalancedProject(Project)
+ s_date = project.phase.start.to_datetime()
+ e_date = project.phase.end.to_datetime()
+ # Recalculate date_start and date_end
+ # according to constraints on date start and date end on phase
+ if phase.constraint_date_start and str(s_date) < phase.constraint_date_start:
+ start_date = datetime.strptime(phase.constraint_date_start, '%Y-%m-%d')
+ else:
+ start_date = s_date
+ if phase.constraint_date_end and str(e_date) > phase.constraint_date_end:
+ end_date= datetime.strptime(phase.constraint_date_end, '%Y-%m-%d')
+ date_start = phase.constraint_date_end
+ else:
+ end_date = e_date
+ date_start = end_date
+ # Write the calculated dates back
+ ctx = context.copy()
+ ctx.update({'scheduler': True})
+ self.write(cr, uid, [phase.id], {
+ 'date_start': start_date.strftime('%Y-%m-%d'),
+ 'date_end': end_date.strftime('%Y-%m-%d')
+ }, context=ctx)
+
+ # Recursive call till all the next phases scheduled
+ for phase in phase.next_phase_ids:
+ if phase.state in ['draft', 'open', 'pending']:
+ id_cal = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
+ self.generate_schedule(cr, uid, [phase.id], date_start, id_cal, context=context)
+ else:
+ continue
+ return True
+
+ def schedule_tasks(self, cr, uid, ids, context=None):
+ """
+ Schedule the tasks according to resource available and priority.
+ """
+ task_pool = self.pool.get('project.task')
+ resource_pool = self.pool.get('resource.resource')
+ if context is None:
+ context = {}
+ resources_list = self.generate_resources(cr, uid, ids, context=context)
+ return_msg = {}
+ for phase in self.browse(cr, uid, ids, context=context):
+ start_date = phase.date_start
+ if not start_date and phase.project_id.date_start:
+ start_date = phase.project_id.date_start
+ if not start_date:
+ start_date = datetime.now().strftime("%Y-%m-%d")
+ resources = resources_list.get(phase.id, [])
+ calendar_id = phase.project_id.resource_calendar_id.id
+ task_ids = map(lambda x : x.id, (filter(lambda x : x.state in ['open', 'draft', 'pending'] , phase.task_ids)))
+ if task_ids:
+ task_pool.generate_schedule(cr, uid, task_ids, resources, calendar_id, start_date, context=context)
+
+ if not task_ids:
+ warning_msg = _("No tasks to compute for Phase '%s'.") % (phase.name)
+ if "warning" not in return_msg:
+ return_msg["warning"] = warning_msg
+ else:
+ return_msg["warning"] = return_msg["warning"] + "\n" + warning_msg
+ return return_msg
project_phase()
class project_resource_allocation(osv.osv):
@@ -259,14 +389,172 @@ class project(osv.osv):
'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"),
'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
}
+ def generate_members(self, cr, uid, ids, context=None):
+ """
+ Return a list of Resource Class objects for the resources allocated to the phase.
+ """
+ res = {}
+ resource_pool = self.pool.get('resource.resource')
+ if context is None:
+ context = {}
+ for project in self.browse(cr, uid, ids, context=context):
+ user_ids = map(lambda x:x.id, project.members)
+ calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
+ resource_objs = resource_pool.generate_resources(cr, uid, user_ids, calendar_id, context=context)
+ res[project.id] = resource_objs
+ return res
+
+ def schedule_phases(self, cr, uid, ids, context=None):
+ """
+ Schedule the phases.
+ """
+ if context is None:
+ context = {}
+ if type(ids) in (long, int,):
+ ids = [ids]
+ phase_pool = self.pool.get('project.phase')
+ for project in self.browse(cr, uid, ids, context=context):
+ phase_ids = phase_pool.search(cr, uid, [('project_id', '=', project.id),
+ ('state', 'in', ['draft', 'open', 'pending']),
+ ('previous_phase_ids', '=', False)
+ ])
+ start_date = project.date_start
+ if not start_date:
+ start_date = datetime.now().strftime("%Y-%m-%d")
+ start_dt = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d %H:%M")
+ calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
+ phase_pool.generate_schedule(cr, uid, phase_ids, start_dt, calendar_id, context=context)
+ return True
+
+ def schedule_tasks(self, cr, uid, ids, context=None):
+ """
+ Schedule the tasks according to resource available and priority.
+ """
+ if type(ids) in (long, int,):
+ ids = [ids]
+ user_pool = self.pool.get('res.users')
+ task_pool = self.pool.get('project.task')
+ resource_pool = self.pool.get('resource.resource')
+ if context is None:
+ context = {}
+
+ resources_list = self.generate_members(cr, uid, ids, context=context)
+ return_msg = {}
+ for project in self.browse(cr, uid, ids, context=context):
+ start_date = project.date_start
+ if not start_date:
+ start_date = datetime.now().strftime("%Y-%m-%d")
+ resources = resources_list.get(project.id, [])
+ calendar_id = project.resource_calendar_id.id
+ task_ids = task_pool.search(cr, uid, [('project_id', '=', project.id),
+ ('state', 'in', ['draft', 'open', 'pending'])
+ ])
+
+
+ if task_ids:
+ task_pool.generate_schedule(cr, uid, task_ids, resources, calendar_id, start_date, context=context)
+ else:
+ warning_msg = _("No tasks to compute for Project '%s'.") % (project.name)
+ if "warning" not in return_msg:
+ return_msg["warning"] = warning_msg
+ else:
+ return_msg["warning"] = return_msg["warning"] + "\n" + warning_msg
+
+ return return_msg
project()
-class task(osv.osv):
+class resource_resource(osv.osv):
+ _inherit = "resource.resource"
+ def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
+ if context is None:
+ context = {}
+ if context.get('project_id',False):
+ project_pool = self.pool.get('project.project')
+ project_rec = project_pool.browse(cr, uid, context['project_id'])
+ user_ids = [user_id.id for user_id in project_rec.members]
+ args.append(('user_id','in',user_ids))
+ return super(resource_resource, self).search(cr, uid, args, offset, limit, order, context, count)
+
+resource_resource()
+
+class project_task(osv.osv):
_inherit = "project.task"
_columns = {
'phase_id': fields.many2one('project.phase', 'Project Phase'),
}
+
+ def generate_schedule(self, cr, uid, ids, resources, calendar_id, start_date, context=None):
+ """
+ Schedule the tasks according to resource available and priority.
+ """
+ if not ids:
+ return False
+ if context is None:
+ context = {}
+ user_pool = self.pool.get('res.users')
+ project_pool = self.pool.get('project.project')
+ priority_dict = {'0': 1000, '1': 800, '2': 500, '3': 300, '4': 100}
+ # Create dynamic no of tasks with the resource specified
+ def create_tasks(task_number, eff, priorty=500, obj=False):
+ def task():
+ """
+ task is a dynamic method!
+ """
+ effort = eff
+ if obj:
+ resource = obj
+ priority = priorty
+ task.__doc__ = "TaskNO%d" %task_number
+ task.__name__ = "task%d" %task_number
+ return task
-task()
+ # Create a 'Faces' project with all the tasks and resources
+ def Project():
+ title = "Project"
+ start = datetime.strftime(datetime.strptime(start_date, "%Y-%m-%d"), "%Y-%m-%d %H:%M")
+ try:
+ resource = reduce(operator.or_, resources)
+ except:
+ raise osv.except_osv(_('Error'), _('Should have Resources Allocation or Project Members!'))
+ minimum_time_unit = 1
+ if calendar_id: # If project has working calendar
+ working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
+ vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
+ # Dynamic creation of tasks
+ task_number = 0
+ for openobect_task in self.browse(cr, uid, ids, context=context):
+ hours = str(openobect_task.planned_hours )+ 'H'
+ if openobect_task.priority in priority_dict.keys():
+ priorty = priority_dict[openobect_task.priority]
+ real_resource = False
+ if openobect_task.user_id:
+ for task_resource in resources:
+ if task_resource.__name__ == task_resource:
+ real_resource = task_resource
+ break
+
+ task = create_tasks(task_number, hours, priorty, real_resource)
+ task_number += 1
+
+
+ face_projects = Task.BalancedProject(Project)
+ loop_no = 0
+ # Write back the computed dates
+ for face_project in face_projects:
+ s_date = face_project.start.to_datetime()
+ e_date = face_project.end.to_datetime()
+ if loop_no > 0:
+ ctx = context.copy()
+ ctx.update({'scheduler': True})
+ user_id = user_pool.search(cr, uid, [('name', '=', face_project.booked_resource[0].__name__)])
+ self.write(cr, uid, [ids[loop_no-1]], {
+ 'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
+ 'date_end': e_date.strftime('%Y-%m-%d %H:%M:%S'),
+ 'user_id': user_id[0]
+ }, context=ctx)
+
+ loop_no += 1
+ return True
+project_task()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/project_long_term_demo.xml b/addons/project_long_term/project_long_term_demo.xml
index 7718048dc05..30acac99377 100644
--- a/addons/project_long_term/project_long_term_demo.xml
+++ b/addons/project_long_term/project_long_term_demo.xml
@@ -1,741 +1,393 @@
-
-
-
-
-
- en_US
- Demo User1
-
- Mr Demo
-
-
-
-
-
- demo1
- demo1
-
-
-
-
-
- en_US
- Manager1
+
+
+
+
+ Phoung
-
-
-
-
-
- manager1
- manager1
-
+ phu
+ phu
-
-
-
- en_US
- Manager2
+
+ Anthony
-
-
-
-
-
- manager2
- manager2
-
+ al
+ al
-
-
-
- en_US
- user1
+
+ Qwintin
-
-
-
-
-
- user1
- USER1
-
+ qdp
+ qdp
-
-
-
- en_US
- user2
+
+ Francois
-
-
-
-
-
- user2
- user2
-
+ fpi
+ fpi
-
-
-
- en_US
- user_finance
+
+ Julien
+
+ jth
+ jth
+
+
+ Alien
+
+ apr
+ apr
+
+
+ Fabian
-
-
-
-
-
- user_finance
- user_finance
-
+ fbs
+ fbs
-
-
- en_US
- user_design1
-
-
-
-
-
-
- user_design1
- user_design1
-
-
-
-
-
- en_US
- user_design2
-
-
-
-
-
-
- user_design2
- user_design2
-
-
-
-
-
- en_US
- user_developer1
-
-
-
-
-
-
- user_developer1
- user_developer1
-
-
-
-
-
- en_US
- user_developer2
-
-
-
-
-
-
- user_developer2
- user_developer1
-
-
-
-
-
- en_US
- user_tester1
-
-
-
-
-
-
- user_tester1
- user_tester1
-
-
-
-
-
- en_US
- user_tester2
-
-
-
-
-
-
- user_tester2
- user_tester2
-
-
-
-
-
- en_US
- user_analyst
-
-
-
-
-
-
- user_analyst
- user_analyst
-
-
-
-
-
-
-
-
+
+
+ Analyst
-
-
- user
-
-
-
- Programmer
-
-
+
+
+ Project Manager
- user
-
-
-
+
+
+ Technical Leader
+
+
+
+
+
+ Developer
+
+
+
+
+
+ Designer
+
+
+
+
+ Tester
-
-
- user
-
-
-
- Web Designer
-
-
+
+
+ Project Finacial Manager
- user
+
+
-
-
-
-
-
-
-
-
-
+
+ opennormal
- Develop an OpenERP Website.
-
-
-
-
-
- OpenERP Website Development
+ Integrate an Sale and Warehouse Management.
+
+
+ Integrate an Sale and Warehouse Management.
-
+
- Information Gathering and Understanding
+ Collect Requirement and Make SRS
-
-
-
- draft
-
-
-
-
-
+
+ 30
+
+
-
-
- Planning
+
+
+ Design Model
-
-
-
- draft
-
-
-
-
-
+
+ 20
+
+
-
-
- Web Design
+
+
+ Planning and compute Risk analysis, Time chart
-
-
-
- draft
-
-
-
-
-
+
+ 20
+
+
-
-
- Development, Integration and Testing
+
+
+ Development and Integration
-
-
-
- draft
-
-
-
-
-
+
+ 90
+
+
-
-
- Website Deployment
+
+
+ Review and Testing
-
-
-
- draft
-
-
-
-
-
+
+ 30
+
+
+
+
+
+
+ Deployement and Training
+
+
+ 10
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+
+
-
- open
-
-
+ 2
-
-
-
-
+ Prepare Requirements Document
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Define Website Goals, Purposes and Target Audience
-
-
-
-
+
+ Make SRS
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Use Cases
-
-
-
-
+
+ Design Use Cases
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Budget Planning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Quality Planning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Risk Management Planning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Create Project Schedules
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Dataflow Design
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ User Interface Design
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Task Level WBS
-
-
-
-
+
+ Develop Module in Sale Management
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Modular Programming
-
-
-
-
+
+ Develop module in Warehouse
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Integrate Modules
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Unit Testing
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Regression Test
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Documentation
-
-
-
-
+
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Performance Tuning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Deploy Website
-
-
-
-
+
+ Deploy and Review on Customer System
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Presentation
-
-
-
-
+
+ Training and Presentation
+
+
+
+
+
+
diff --git a/addons/project_long_term/project_long_term_view.xml b/addons/project_long_term/project_long_term_view.xml
index ee763b759b6..a3ff3b39669 100644
--- a/addons/project_long_term/project_long_term_view.xml
+++ b/addons/project_long_term/project_long_term_view.xml
@@ -30,7 +30,7 @@
-
+
@@ -60,8 +60,9 @@
-
+
+
@@ -89,16 +90,21 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -115,9 +121,9 @@
-
-
+
+
@@ -184,7 +190,7 @@
tree
-
+
@@ -228,23 +234,26 @@
-
+
-
+
-
-
-
+
-
+
+
+
+
+
+
@@ -257,7 +266,7 @@
tree,form,gantt,calendar{'search_default_responsible_id':uid}
- You can subdivide your larger projects into several phases. For each phase, you can define your resources allocation (humans or engine), describe de differend task and link your phase with previous and next one, add constraints date and scheduling. A gantt view of your project phase is also available from this menu. Gantt view is a graphically draw of the project plan; it includes any task dependencies by visually adjusting task durations and priorities, and by linking tasks to each other.
+ You can subdivide your larger projects into several phases. For each phase, you can define your resources allocation (humans or engine), describe de differend task and link your phase with previous and next one, add constraints date and scheduling. A gantt view of your project phase is also available from this menu. Gantt view is a graphically draw of the project plan; it includes any task dependencies by visually adjusting task durations and priorities, and by linking tasks to each other.
@@ -297,10 +306,10 @@
res_model="project.task"
src_model="project.phase"
view_mode="tree,form"
- domain="[('phase_id','=',active_id)]"/>
+ context="{'search_default_phase_id': [active_id]}"/>
diff --git a/addons/project_long_term/security/ir.model.access.csv b/addons/project_long_term/security/ir.model.access.csv
index 3653cd375f1..7af7984d7e6 100644
--- a/addons/project_long_term/security/ir.model.access.csv
+++ b/addons/project_long_term/security/ir.model.access.csv
@@ -1,9 +1,10 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_project_phase","project.phase","model_project_phase",project.group_project_user,1,1,1,0
-"access_project_resource_allocation","project.resource.allocation","model_project_resource_allocation",project.group_project_user,1,1,1,0
-"access_project_phase_manager","project.phase manager","model_project_phase",project.group_project_manager,1,0,0,0
-"access_project_resource_allocation_manager","project.resource.allocation manager","model_project_resource_allocation",project.group_project_manager,1,0,0,0
-"access_project_resource_allocation_system","project.resource.allocation system","model_project_resource_allocation",base.group_system,1,0,0,0
-"access_project_phase_system","project.phase system","model_project_phase",base.group_system,1,0,0,0
-"access_resource_resource_user","resource.resource user","resource.model_resource_resource",project.group_project_user,1,1,1,1
+"access_project_phase","project.phase","model_project_phase","project.group_project_user",1,1,1,0
+"access_project_resource_allocation","project.resource.allocation","model_project_resource_allocation","project.group_project_user",1,1,1,0
+"access_project_phase_manager","project.phase manager","model_project_phase","project.group_project_manager",1,0,0,0
+"access_project_resource_allocation_manager","project.resource.allocation manager","model_project_resource_allocation","project.group_project_manager",1,0,0,0
+"access_project_resource_allocation_system","project.resource.allocation system","model_project_resource_allocation","base.group_system",1,0,0,0
+"access_project_phase_system","project.phase system","model_project_phase","base.group_system",1,0,0,0
+"access_resource_resource_user","resource.resource user","resource.model_resource_resource","project.group_project_user",1,0,1,1
"access_resource_calendar_leaves_user","resource.calendar.leaves user","resource.model_resource_calendar_leaves","project.group_project_user",1,1,1,1
+"access_resource_resource_manager","resource.resource manager","resource.model_resource_resource","project.group_project_manager",1,1,1,1
diff --git a/addons/project_long_term/test/schedule_phase_tasks.yml b/addons/project_long_term/test/schedule_phase_tasks.yml
index 323d9cbc8f2..150d80af822 100644
--- a/addons/project_long_term/test/schedule_phase_tasks.yml
+++ b/addons/project_long_term/test/schedule_phase_tasks.yml
@@ -2,32 +2,31 @@
Create project 'Develop an outlook-openerp synchronization plugin'
-
!record {model: project.project, id: project_project_project0}:
- company_id: base.main_company
- name: Project123
+ name: Develop an outlook-openerp synchronization plugin
members:
- - project_long_term.res_users_manager0
- - project_long_term.res_users_user0
- - project_long_term.res_users_userfinance0
- - project_long_term.res_users_userdesign0
- - project_long_term.res_users_userdeveloper0
- - project_long_term.res_users_usertester0
- - project_long_term.res_users_useranalyst0
+ - project_long_term.res_users_project_manager
+ - project_long_term.res_users_technical_leader
+ - project_long_term.res_users_developer
+ - project_long_term.res_users_designer
+ - project_long_term.res_users_tester
+ - project_long_term.res_users_analyst
+ - project_long_term.res_users_finacial_manager
-
Create phase 'Develop GUI' in Outlook
-
!record {model: project.phase, id: project_phase_phase0}:
date_start: '2010-06-02'
duration: 200.0
- name: phase123
+ name: Develop GUI in Outlook
product_uom: product.uom_day
project_id: project_project_project0
state: draft
resource_ids:
- - resource_id: project_long_term.resource_resource_analyst0
+ - resource_id: project_long_term.resource_analyst
useability: 80.0
- - resource_id: project_long_term.resource_resource_programmer0
+ - resource_id: project_long_term.resource_developer
useability: 30.0
- - resource_id: project_long_term.resource_resource_webdesigner0
+ - resource_id: project_long_term.resource_designer
useability: 30.0
@@ -35,66 +34,60 @@
Create the phase task 'Develop GUI for Server Configuration'
-
!record {model: project.task, id: project_task_t0}:
- name: t1
+ name: Develop GUI for Server Configuration
planned_hours: 20.0
remaining_hours: 20.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for Modules Configuration'
-
!record {model: project.task, id: project_task_t1}:
- name: t2
+ name: Develop GUI for Modules Configuration
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for OpenERP Synchronisation'
-
!record {model: project.task, id: project_task_t2}:
- name: t3
+ name: Develop GUI for OpenERP Synchronisation
planned_hours: 30.0
remaining_hours: 30.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
- Create the phase task 'Develop required Menus'
+ Create the phase task 'Design required GUI/Menus'
-
!record {model: project.task, id: project_task_3}:
- name: t4
+ name: Design required GUI/Menus
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdesign0
+ user_id: project_long_term.res_users_designer
-
Schedule phase tasks
-
- !python {model: project.schedule.tasks}: |
- res = self.compute_date(cr, uid, {"lang": "en_US", "tz": False,
- "active_id": ref("project_phase_phase0"),
- # rest may be obsolete:
- # "active_model": "project.phase", "active_ids": [ref("project_phase_phase0")],
- # "record_id": 138, "project_id": ref("project_project_project0"),
- })
- print res
+ !python {model: project.phase}: |
+ res = self.schedule_tasks(cr, uid, [ref("project_phase_phase0")])
-
Check if tasks scheduled, check that either of task's start_date, end_date and user_id is not null
-
!python {model: project.phase}: |
- phase=self.browse(cr, uid, [ref("project_phase_phase0")])[0]
+ phase = self.browse(cr, uid, [ref("project_phase_phase0")])[0]
for task in phase.task_ids:
if (not task.user_id) or (not task.date_start) or (not task.date_end):
raise AssertionError("Phase Tasks not scheduled: %d uid=%r start=%r end=%r" % \
- (task.id, task.user_id, task.date_start, task.date_end))
\ No newline at end of file
+ (task.id, task.user_id, task.date_start, task.date_end))
diff --git a/addons/project_long_term/test/schedule_project_phases.yml b/addons/project_long_term/test/schedule_project_phases.yml
index 66bca5ff97d..e06feaaa4ca 100644
--- a/addons/project_long_term/test/schedule_project_phases.yml
+++ b/addons/project_long_term/test/schedule_project_phases.yml
@@ -2,7 +2,6 @@
Create a project 'World Bank's Project'
-
!record {model: project.project, id: project_project_worldbanksproject0}:
- company_id: base.main_company
name: "World Bank's Project"
priority: 4
@@ -15,7 +14,6 @@
name: "Defining Client's Basic Idea of Project"
product_uom: product.uom_day
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -27,7 +25,6 @@
name: Establishing Project Feasibility
product_uom: product.uom_day
project_id: project_project_worldbanksproject0
- state: draft
-
Create project phase 'Preparation of Engineering Designs'
@@ -38,7 +35,6 @@
name: Preparation of Engineering Designs
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -50,7 +46,6 @@
name: Procurement of Works and Goods
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -62,7 +57,6 @@
name: Project Construction
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -74,7 +68,6 @@
name: Project Completion
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
Set previous phase for phase 'Establishing Project Feasibility'
@@ -125,11 +118,8 @@
-
Schedule project phases
-
- !python {model: project.compute.phases}: |
- self.check_selection(cr, uid, [ref("project_compute_phases_0")], {"lang": "en_US",
- "project_id": False, "tz": False, "active_model": "ir.ui.menu", "department_id":
- False, "section_id": False, "record_id": 279, "active_ids": [ref("project_long_term.menu_compute_phase")],
- "active_id": ref("project_long_term.menu_compute_phase"), })
+ !python {model: project.project}: |
+ self.schedule_phases(cr, uid, ref("project_project_worldbanksproject0"))
-
Check if phases scheduled, check that either of phase's start_date, end_date and user_id is not null
@@ -140,4 +130,4 @@
if (not phase.responsible_id) or (not phase.date_start) or (not phase.date_end):
raise AssertionError("Tasks not scheduled")
-
\ No newline at end of file
+
diff --git a/addons/project_long_term/test/schedule_project_tasks.yml b/addons/project_long_term/test/schedule_project_tasks.yml
index b1cd70487f7..dfc4cf1fc5e 100644
--- a/addons/project_long_term/test/schedule_project_tasks.yml
+++ b/addons/project_long_term/test/schedule_project_tasks.yml
@@ -2,103 +2,93 @@
Create project 'Develop a thunderbird-openerp synchronization plugin'
-
!record {model: project.project, id: project_project_project1}:
- company_id: base.main_company
- name: Project2
+ name: Develop a thunderbird-openerp synchronization plugin
members:
- - project_long_term.res_users_manager0
- - project_long_term.res_users_user0
- - project_long_term.res_users_userfinance0
- - project_long_term.res_users_userdesign0
- - project_long_term.res_users_userdeveloper0
- - project_long_term.res_users_usertester0
- - project_long_term.res_users_useranalyst0
+ - project_long_term.res_users_project_manager
+ - project_long_term.res_users_technical_leader
+ - project_long_term.res_users_developer
+ - project_long_term.res_users_designer
+ - project_long_term.res_users_tester
+ - project_long_term.res_users_analyst
+ - project_long_term.res_users_finacial_manager
-
- Create phase 'Develop GUI' in Thunderbird
+ Create phase 'Develop GUI' in thunderbird
-
!record {model: project.phase, id: project_phase_phase1}:
date_start: '2010-06-02'
- duration: 100.0
- name: phase22
+ duration: 200.0
+ name: Develop GUI in thunderbird
product_uom: product.uom_day
project_id: project_project_project1
state: draft
resource_ids:
- - resource_id: project_long_term.resource_resource_analyst0
+ - resource_id: project_long_term.resource_analyst
useability: 80.0
- - resource_id: project_long_term.resource_resource_programmer0
+ - resource_id: project_long_term.resource_developer
useability: 30.0
- - resource_id: project_long_term.resource_resource_webdesigner0
+ - resource_id: project_long_term.resource_designer
useability: 30.0
-
Create the phase task 'Develop GUI for Server Configuration'
-
- !record {model: project.task, id: project_task_t00}:
- name: t1
+ !record {model: project.task, id: project_task_t10}:
+ name: Develop GUI for Server Configuration
planned_hours: 20.0
remaining_hours: 20.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for Modules Configuration'
-
!record {model: project.task, id: project_task_t11}:
- name: t2
+ name: Develop GUI for Modules Configuration
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for OpenERP Synchronisation'
-
- !record {model: project.task, id: project_task_t22}:
- name: t3
+ !record {model: project.task, id: project_task_t12}:
+ name: Develop GUI for OpenERP Synchronisation
planned_hours: 30.0
remaining_hours: 30.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
-
-
+ user_id: project_long_term.res_users_developer
-
- Create the phase task 'Develop required Menus'
+ Create the phase task 'Design required GUI/Menus'
-
- !record {model: project.task, id: project_task_t33}:
- name: t4
+ !record {model: project.task, id: project_task_13}:
+ name: Design required GUI/Menus
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
-
--
- Get the project to schedule the tasks
--
- !record {model: project.compute.tasks, id: project_compute_tasks_0}:
- project_id: project_project_project1
+ user_id: project_long_term.res_users_designer
-
Schedule tasks
-
- !python {model: project.compute.tasks}: |
- self.compute_date(cr, uid, [ref("project_compute_tasks_0")], {"lang": "en_US", "tz": False,
- "active_id": ref("project_long_term.menu_compute_tasks"),
- "active_model": "ir.ui.menu", "active_ids": [ref("project_long_term.menu_compute_tasks")],
- })
+ !python {model: project.project}: |
+ self.schedule_tasks(cr, uid, ref("project_project_project1"))
-
Check if tasks scheduled, check that either of task's start_date, end_date and user_id is not null
-
!python {model: project.project}: |
- prj=self.browse(cr, uid, [ref("project_project_project1")])[0]
+ prj = self.browse(cr, uid, [ref("project_project_project1")])[0]
for task in prj.tasks:
if (not task.user_id) or (not task.date_start) or (not task.date_end):
raise AssertionError("Project Tasks not scheduled")
diff --git a/addons/project_long_term/wizard/__init__.py b/addons/project_long_term/wizard/__init__.py
index 5056cad3b77..c1e6d838111 100644
--- a/addons/project_long_term/wizard/__init__.py
+++ b/addons/project_long_term/wizard/__init__.py
@@ -22,6 +22,5 @@
import project_compute_phases
import project_compute_tasks
import project_schedule_tasks
-import working_calendar
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/wizard/project_compute_phases.py b/addons/project_long_term/wizard/project_compute_phases.py
index 75631fb3d18..c43dea56e91 100644
--- a/addons/project_long_term/wizard/project_compute_phases.py
+++ b/addons/project_long_term/wizard/project_compute_phases.py
@@ -18,18 +18,11 @@
# along with this program. If not, see .
#
##############################################################################
-
import datetime
-from resource.faces import *
-from new import classobj
-
from tools.translate import _
from osv import fields, osv
-import working_calendar as wkcal
-
class project_compute_phases(osv.osv_memory):
-
_name = 'project.compute.phases'
_description = 'Project Compute Phases'
_columns = {
@@ -48,118 +41,24 @@ class project_compute_phases(osv.osv_memory):
data_select = self.read(cr, uid, ids, ['target_project'])[0]
return self.compute_date(cr, uid, ids, context=context)
- def _phase_schedule(self, cr, uid, phase, start_date, calendar_id=False, context=None):
- if context is None:
- context = {}
- """Schedule phase with the start date till all the next phases are completed.
-
- Arguements: start_dsate -- start date for the phase
- calendar_id -- working calendar of the project
-
- """
- phase_obj = self.pool.get('project.phase')
- 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:
- leaves = []
- time_efficiency = 1.0
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)])
-
- if resource_id:
- # Create a new resource object with
- # all the attributes of the Resource Class
- 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,
- 'vacation': tuple(leaves),
- 'efficiency': time_efficiency
- })
- default_uom_id = phase_obj._get_default_uom_id(cr, uid)
- avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
- duration = str(avg_hours) + 'H'
- # Create a new project for each phase
- def Project():
- start = start_date
- minimum_time_unit = 1
- resource = phase_resource_obj
- # If project has working calendar then that
- # else the default one would be considered
- if calendar_id:
- working_days = wkcal.compute_working_calendar(cr, uid, calendar_id, context=context)
- vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
-
- def phase():
- effort = duration
-
- project = BalancedProject(Project)
- s_date = project.phase.start.to_datetime()
- e_date = project.phase.end.to_datetime()
- # Recalculate date_start and date_end
- # according to constraints on date start and date end on phase
- if phase.constraint_date_start and str(s_date) < phase.constraint_date_start:
- start_date = datetime.datetime.strptime(phase.constraint_date_start, '%Y-%m-%d')
- else:
- start_date = s_date
- if phase.constraint_date_end and str(e_date) > phase.constraint_date_end:
- end_date= datetime.datetime.strptime(phase.constraint_date_end, '%Y-%m-%d')
- date_start = phase.constraint_date_end
- else:
- end_date = e_date
- date_start = end_date
- # Write the calculated dates back
- ctx = context.copy()
- ctx.update({'scheduler': True})
- phase_obj.write(cr, uid, [phase.id], {
- 'date_start': start_date.strftime('%Y-%m-%d'),
- 'date_end': end_date.strftime('%Y-%m-%d')
- }, context=ctx)
-
- # Recursive call till all the next phases scheduled
- for phase in phase.next_phase_ids:
- if phase.state in ['draft', 'open', 'pending']:
- id_cal = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- self._phase_schedule(cr, uid, phase, date_start, id_cal, context=context)
- else:
- continue
-
+
def compute_date(self, cr, uid, ids, context=None):
"""
Compute the phases for scheduling.
"""
-
if context is None:
context = {}
- phase_obj = self.pool.get('project.phase')
+ project_pool = self.pool.get('project.project')
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 = data['project_id']
- phase_ids = phase_obj.search(cr, uid, [('project_id', '=', project_id),
- ('state', 'in', ['draft', 'open', 'pending']),
- ('previous_phase_ids', '=', False)
- ])
+ project_ids = [data['project_id']]
else: # Else take all the draft,open,pending states phases
- phase_ids = phase_obj.search(cr, uid,[('state', 'in', ['draft', 'open', 'pending']),
- ('previous_phase_ids', '=', False)
- ], context=context)
- phase_ids.sort()
- phases = phase_obj.browse(cr, uid, phase_ids, context=context)
- for phase in phases:
- start_date = phase.project_id.date_start
- if not phase.project_id.date_start:
- start_date = datetime.datetime.now().strftime("%Y-%m-%d")
- start_dt = datetime.datetime.strftime((datetime.datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d %H:%M")
- calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- self._phase_schedule(cr, uid, phase, start_dt, calendar_id, context=context)
+ project_ids = project_pool.search(cr, uid, [], context=context)
+
+ project_pool.schedule_phases(cr, uid, project_ids, context=context)
return self._open_phases_list(cr, uid, data, context=context)
def _open_phases_list(self, cr, uid, data, context=None):
@@ -173,10 +72,7 @@ class project_compute_phases(osv.osv_memory):
result = mod_obj._get_id(cr, uid, 'project_long_term', 'act_project_phase_list')
id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
result = act_obj.read(cr, uid, [id], context=context)[0]
- result['domain'] = [('state', 'not in', ['cancelled','done'])]
- if data['project_id']:
- result['domain'] = [('project_id', '=', data['project_id']),
- ('state', 'not in', ['cancelled','done'])]
+ result['context'] = {"search_default_project_id":data['project_id'], "search_default_responsible_id":uid, "search_default_current": 1}
return result
project_compute_phases()
diff --git a/addons/project_long_term/wizard/project_compute_phases_view.xml b/addons/project_long_term/wizard/project_compute_phases_view.xml
index 8818684e8fa..9d5754af09c 100644
--- a/addons/project_long_term/wizard/project_compute_phases_view.xml
+++ b/addons/project_long_term/wizard/project_compute_phases_view.xml
@@ -16,7 +16,7 @@
-
+
diff --git a/addons/project_long_term/wizard/project_compute_tasks.py b/addons/project_long_term/wizard/project_compute_tasks.py
index 8e98f26b353..cb74649502f 100644
--- a/addons/project_long_term/wizard/project_compute_tasks.py
+++ b/addons/project_long_term/wizard/project_compute_tasks.py
@@ -20,14 +20,10 @@
##############################################################################
import datetime
-from resource.faces import *
-from new import classobj
-import operator
from tools.translate import _
from osv import osv, fields
-import working_calendar as wkcal
class project_compute_tasks(osv.osv_memory):
_name = 'project.compute.tasks'
@@ -40,108 +36,32 @@ class project_compute_tasks(osv.osv_memory):
"""
Schedule the tasks according to resource available and priority.
"""
- project_obj = self.pool.get('project.project')
+ project_pool = self.pool.get('project.project')
task_pool = self.pool.get('project.task')
- resource_obj = self.pool.get('resource.resource')
- user_obj = self.pool.get('res.users')
-
if context is None:
context = {}
-
+ context['compute_by'] = 'project'
data = self.read(cr, uid, ids, [])[0]
project_id = data['project_id']
- project = project_obj.browse(cr, uid, project_id, context=context)
- task_ids = task_pool.search(cr, uid, [('project_id', '=', project_id),
- ('state', 'in', ['draft', 'open', 'pending'])
- ])
- if task_ids:
- task_ids.sort()
- tasks = task_pool.browse(cr, uid, task_ids, context=context)
- calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
- start_date = project.date_start
- if not project.date_start:
- start_date = datetime.datetime.now().strftime("%Y-%m-%d")
- date_start = datetime.datetime.strftime(datetime.datetime.strptime(start_date, "%Y-%m-%d"), "%Y-%m-%d %H:%M")
- # Create Resource Class objects which are the Project Members
- resources = []
- for user in project.members:
- leaves = []
- time_efficiency = 1.0
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', user.id)], context=context)
- if resource_id:
-# resource = resource_obj.browse(cr, uid, resource_id, context=context)[0]
- resource = resource_obj.read(cr, uid, resource_id, ['calendar_id', 'time_efficiency'], context=context)[0]
- if resource.get('calendar_id', False):
- leaves = wkcal.compute_leaves(cr, uid, calendar_id , resource_id[0], resource['calendar_id'] and resource['calendar_id'][0] or False)
- time_efficiency = resource.get('time_efficiency')
- resources.append(classobj((user.name.encode('utf8')), (Resource,), {
- '__doc__': user.name,
- '__name__': user.name,
- 'vacation': tuple(leaves),
- 'efficiency': time_efficiency
- }))
- priority_dict = {'0': 1000, '1': 800, '2': 500, '3': 300,'4': 100}
- # Create dynamic no of tasks with the resource specified
- def create_tasks(j, eff, priorty=500, obj=None):
- def task():
- """
- task is a dynamic method!
- """
- effort = eff
- if obj:
- resource = obj
- priority = priorty
- task.__doc__ = "TaskNO%d" %j
- task.__name__ = "task%d" %j
- return task
+ project_pool.schedule_tasks(cr, uid, [project_id], context=context)
+ return self._open_task_list(cr, uid, data, context=context)
- # Create a 'Faces' project with all the tasks and resources
- def Project():
- title = project.name
- start = date_start
- try:
- resource = reduce(operator.or_, resources)
- except:
- raise osv.except_osv(_('Error'), _('Project must have members assigned !'))
- minimum_time_unit = 1
- if calendar_id: # If project has calendar
- working_days = wkcal.compute_working_calendar(cr, uid, calendar_id)
- vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
- # Dynamic Creation of tasks
- i = 0
- for each_task in tasks:
- hours = str(each_task.planned_hours )+ 'H'
- if each_task.priority in priority_dict.keys():
- priorty = priority_dict[each_task.priority]
- rcre = False
- if each_task.user_id:
- for resrce in resources:
- if resrce.__name__ == each_task.user_id.name: # check me!!
- rcre = resrce
- break
- task = create_tasks(i, hours, priorty, rcre)
- i += 1
-
- project = BalancedProject(Project)
- loop_no = 0
- # Write back the computed dates
- for t in project:
- s_date = t.start.to_datetime()
- e_date = t.end.to_datetime()
- if loop_no == 0:
- project_obj.write(cr, uid, [project_id], {'date': e_date}, context=context)
- else:
- ctx = context.copy()
- ctx.update({'scheduler': True})
- user_id = user_obj.search(cr, uid, [('name', '=', t.booked_resource[0].__name__)])
- task_pool.write(cr, uid, [tasks[loop_no-1].id], {
- 'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'date_end': e_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'user_id': user_id[0]
- }, context=ctx)
-
- loop_no +=1
- return {}
+ def _open_task_list(self, cr, uid, data, context=None):
+ """
+ Return the scheduled task list.
+ """
+ if context is None:
+ context = {}
+ mod_obj = self.pool.get('ir.model.data')
+ act_obj = self.pool.get('ir.actions.act_window')
+ result = mod_obj._get_id(cr, uid, 'project', 'action_view_task')
+ id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
+ result = {}
+ if not id:
+ return result
+ result = act_obj.read(cr, uid, [id], context=context)[0]
+ result['context'] = {"search_default_project_id":data['project_id'], "search_default_user_id":uid, "search_default_current": 1}
+ return result
project_compute_tasks()
diff --git a/addons/project_long_term/wizard/project_compute_tasks_view.xml b/addons/project_long_term/wizard/project_compute_tasks_view.xml
index e0cd30d5622..e6540fafff9 100644
--- a/addons/project_long_term/wizard/project_compute_tasks_view.xml
+++ b/addons/project_long_term/wizard/project_compute_tasks_view.xml
@@ -9,13 +9,13 @@
-
+
-
+
diff --git a/addons/project_long_term/wizard/project_schedule_tasks.py b/addons/project_long_term/wizard/project_schedule_tasks.py
index c64e800c9c6..0d9e9f381f1 100644
--- a/addons/project_long_term/wizard/project_schedule_tasks.py
+++ b/addons/project_long_term/wizard/project_schedule_tasks.py
@@ -20,17 +20,9 @@
##############################################################################
import datetime
-from resource.faces import *
-from new import classobj
-import operator
-
from tools.translate import _
-from osv import osv, fields
-
-import working_calendar as wkcal
-
+from osv import fields, osv
class project_schedule_task(osv.osv_memory):
-
_name = "project.schedule.tasks"
_description = 'project.schedule.tasks'
_columns = {
@@ -46,126 +38,17 @@ class project_schedule_task(osv.osv_memory):
res = super(project_schedule_task, self).default_get(cr, uid, fields_list, context)
self.compute_date(cr, uid, context=context)
return res
-
- def create_resources(self, cr, uid, phase, context=None):
- """
- Return a list of Resource Class objects for the resources allocated to the phase.
- """
- resource_objs = []
-
- if context is None:
- context = {}
-
- for resource in phase.resource_ids:
- res = resource.resource_id
- leaves = []
- resource_eff = res.time_efficiency
- resource_cal = res.calendar_id.id
- if resource_cal:
- cal_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- leaves = wkcal.compute_leaves(cr, uid, cal_id, res.id, resource_cal, context=context)
- resource_objs.append(classobj(res.user_id.name.encode('utf8'), (Resource,),{
- '__doc__': res.user_id.name,
- '__name__': res.user_id.name,
- 'vacation': tuple(leaves),
- 'efficiency': resource_eff,
- }))
- return resource_objs
-
+
def compute_date(self, cr, uid, context=None):
"""
Schedule the tasks according to resource available and priority.
"""
-
- phase_obj = self.pool.get('project.phase')
- task_obj = self.pool.get('project.task')
- user_obj = self.pool.get('res.users')
-
+ phase_pool = self.pool.get('project.phase')
if context is None:
- # It makes no sense to continue on empty context
- return { 'warning': _("You must select some project phase to compute on")}
-
+ context = {}
if not 'active_id' in context:
return {}
- phase = phase_obj.browse(cr, uid, context['active_id'], context=context)
- task_ids = map(lambda x : x.id, (filter(lambda x : x.state in ['open', 'draft', 'pending'] , phase.task_ids)))
- if task_ids:
- task_ids.sort()
- tasks = task_obj.browse(cr, uid, task_ids, context=context)
- start_date = str(phase.date_start)
- if not phase.date_start:
- if not phase.project_id.date_start:
- start_date = datetime.datetime.now().strftime("%Y-%m-%d")
- else:
- start_date = phase.project_id.date_start
- date_start = datetime.datetime.strftime(datetime.datetime.strptime(start_date, "%Y-%m-%d"), "%Y-%m-%d %H:%M")
- calendar_id = phase.project_id.resource_calendar_id.id
- resources = self.create_resources(cr, uid, phase)
- priority_dict = {'0': 1000, '1': 800, '2': 500, '3': 300, '4': 100}
- # Create dynamic no of tasks with the resource specified
- def create_tasks(j, eff, priorty=500, obj=False):
- def task():
- """
- task is a dynamic method!
- """
- effort = eff
- if obj:
- resource = obj
- priority = priorty
- task.__doc__ = "TaskNO%d" %j
- task.__name__ = "task%d" %j
- return task
-
- # Create a 'Faces' project with all the tasks and resources
- def Project():
- title = "Project"
- start = date_start
- try:
- resource = reduce(operator.or_, resources)
- except:
- raise osv.except_osv(_('Error'), _('Phase must have resources assigned !'))
- minimum_time_unit = 1
- if calendar_id: # If project has working calendar
- working_days = wkcal.compute_working_calendar(cr, uid, calendar_id)
- vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
- # Dynamic creation of tasks
- i = 0
- for each_task in tasks:
- hours = str(each_task.planned_hours )+ 'H'
- if each_task.priority in priority_dict.keys():
- priorty = priority_dict[each_task.priority]
- resc = False
- if each_task.user_id:
- for resrce in resources:
- if resrce.__name__ == each_task.user_id.name:
- resc = resrce
- break
-
- task = create_tasks(i, hours, priorty, resc)
- i += 1
-
- project = BalancedProject(Project)
-
- loop_no = 0
- # Write back the computed dates
- for t in project:
- s_date = t.start.to_datetime()
- e_date = t.end.to_datetime()
- if loop_no > 0:
- ctx = context.copy()
- ctx.update({'scheduler': True})
- user_id = user_obj.search(cr, uid, [('name', '=', t.booked_resource[0].__name__)])
- task_obj.write(cr, uid, [tasks[loop_no-1].id], {
- 'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'date_end': e_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'user_id': user_id[0]
- }, context=ctx)
-
- loop_no += 1
- else:
- return {"warning": _("No tasks to compute for this phase") }
- return {}
-
+ return phase_pool.schedule_tasks(cr, uid, [context['active_id']], context=context)
project_schedule_task()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/wizard/working_calendar.py b/addons/project_long_term/wizard/working_calendar.py
deleted file mode 100644
index 139875b6236..00000000000
--- a/addons/project_long_term/wizard/working_calendar.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2009 Tiny SPRL ().
-#
-# 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 .
-#
-##############################################################################
-
-import datetime
-
-import pooler
-
-def convert_timeformat(cr, uid, time_string, context=None):
- if context is None:
- context = {}
- """ Convert input time string: 8.5 to output time string 8:30."""
-
- split_list = str(time_string).split('.')
- hour_part = split_list[0]
- mins_part = split_list[1]
- round_mins = int(round(float(mins_part) * 60,-2))
- converted_string = hour_part + ':' + str(round_mins)[0:2]
- return converted_string
-
-def compute_leaves(cr, uid, calendar_id, resource_id=False, resource_calendar=False, context=None):
-
- if context is None:
- context = {}
-
- """Compute the leaves from the working calendar of the resource.
-
- Arguements: calendar_id -- working calendar of the project
- resource_id -- resource working on phase/task
- resource_calendar -- working calendar of the resource
-
- """
-
- pool = pooler.get_pool(cr.dbname)
- resource_calendar_leaves_obj = pool.get('resource.calendar.leaves')
- leave_list = []
- if resource_id:
- leave_ids = resource_calendar_leaves_obj.search(cr, uid, ['|', ('calendar_id', '=', calendar_id),
- ('calendar_id', '=', resource_calendar),
- ('resource_id', '=', resource_id)
- ], context=context)
- else:
- leave_ids = resource_calendar_leaves_obj.search(cr, uid, [('calendar_id', '=', calendar_id),
- ('resource_id', '=', False)
- ], context=context)
- leaves = resource_calendar_leaves_obj.read(cr, uid, leave_ids, ['date_from', 'date_to'], context=context)
- for i in range(len(leaves)):
- dt_start = datetime.datetime.strptime(leaves[i]['date_from'], '%Y-%m-%d %H:%M:%S')
- dt_end = datetime.datetime.strptime(leaves[i]['date_to'], '%Y-%m-%d %H:%M:%S')
- no = dt_end - dt_start
- [leave_list.append((dt_start + datetime.timedelta(days=x)).strftime('%Y-%m-%d')) for x in range(int(no.days + 1))]
- leave_list.sort()
- return leave_list
-
-def compute_working_calendar(cr, uid, calendar_id, context=None):
-
- if context is None:
- context = {}
-
- """Change the format of working calendar from 'Openerp' format to bring it into 'Faces' format.
-
- Arguement: calendar_id -- working calendar of the project
-
- """
-
- pool = pooler.get_pool(cr.dbname)
- resource_attendance_obj = pool.get('resource.calendar.attendance')
- time_range = "8:00-8:00"
- non_working = ""
- week_days = {"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_attendance_obj.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context)
- weeks = resource_attendance_obj.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'], context=context)
- # Convert time formats into appropriate format required
- # and create a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')]
- for week in weeks:
- res_str = ""
- if week_days.has_key(week['dayofweek']):
- day = week_days[week['dayofweek']]
- wk_days[week['dayofweek']] = week_days[week['dayofweek']]
- hour_from_str = convert_timeformat(cr, uid, week['hour_from'])
- hour_to_str = convert_timeformat(cr, uid, week['hour_to'])
- res_str = hour_from_str + '-' + hour_to_str
- wktime_list.append((day, res_str))
- # Convert into format like [('mon', '8:00-12:00', '13:00-18:00')]
- for item in wktime_list:
- if wk_time.has_key(item[0]):
- wk_time[item[0]].append(item[1])
- else:
- wk_time[item[0]] = [item[0]]
- wk_time[item[0]].append(item[1])
- for k,v in wk_time.items():
- wktime_cal.append(tuple(v))
- # Add for the non-working days like: [('sat, sun', '8:00-8:00')]
- for k, v in wk_days.items():
- if week_days.has_key(k):
- week_days.pop(k)
- for v in week_days.itervalues():
- non_working += v + ','
- if non_working:
- wktime_cal.append((non_working[:-1], time_range))
- return wktime_cal
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_mailgate/project_mailgate_view.xml b/addons/project_mailgate/project_mailgate_view.xml
index b31eb85328e..8c8816ebbd5 100644
--- a/addons/project_mailgate/project_mailgate_view.xml
+++ b/addons/project_mailgate/project_mailgate_view.xml
@@ -8,9 +8,9 @@
-
+
-
+