Projects are used to organize your activities; plan
tasks, track issues, invoice timesheets. You can define
internal projects (R&D, Improve Sales Process),
private projects (My Todos) or customer ones.
-
-
- You will be able collaborate with internal users on
- projects or invite customers to share your activities.
+
+ You will be able collaborate with internal users on
+ projects or invite customers to share your activities.
@@ -801,7 +799,7 @@
-
+
diff --git a/addons/project/res_config.py b/addons/project/res_config.py
index 6642dbf485d..85b4bd7001b 100644
--- a/addons/project/res_config.py
+++ b/addons/project/res_config.py
@@ -30,7 +30,7 @@ class project_configuration(osv.osv_memory):
'module_project_mrp': fields.boolean('Generate tasks from sale orders',
help ="""This feature automatically creates project tasks from service products in sale orders.
More precisely, tasks are created for procurement lines with product of type 'Service',
- procurement method 'Make to Order', and supply method 'Produce'.
+ procurement method 'Make to Order', and supply method 'Manufacture'.
This installs the module project_mrp."""),
'module_pad': fields.boolean("Use integrated collaborative note pads on task",
help="""Lets the company customize which Pad installation should be used to link to new pads
@@ -52,7 +52,7 @@ class project_configuration(osv.osv_memory):
'module_project_issue_sheet': fields.boolean("Invoice working time on issues",
help="""Provides timesheet support for the issues/bugs management in project.
This installs the module project_issue_sheet."""),
- 'group_tasks_work_on_tasks': fields.boolean("Compute work activities on tasks",
+ 'group_tasks_work_on_tasks': fields.boolean("Log work activities on tasks",
implied_group='project.group_tasks_work_on_tasks',
help="Allows you to compute work on tasks."),
'group_time_work_estimation_tasks': fields.boolean("Manage time estimation on tasks",
@@ -72,4 +72,9 @@ class project_configuration(osv.osv_memory):
user = self.pool.get('res.users').browse(cr, uid, uid, context)
user.company_id.write({'project_time_mode_id': config.time_unit.id})
+ def onchange_time_estimation_project_timesheet(self, cr, uid, ids, group_time_work_estimation_tasks, module_project_timesheet):
+ if group_time_work_estimation_tasks or module_project_timesheet:
+ return {'value': {'group_tasks_work_on_tasks': True}}
+ return {}
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project/res_config_view.xml b/addons/project/res_config_view.xml
index 56803484adf..207f35da72e 100644
--- a/addons/project/res_config_view.xml
+++ b/addons/project/res_config_view.xml
@@ -29,7 +29,7 @@
diff --git a/addons/project_mrp/project_procurement.py b/addons/project_mrp/project_procurement.py
index 299a74f52aa..f9f6fb6a279 100644
--- a/addons/project_mrp/project_procurement.py
+++ b/addons/project_mrp/project_procurement.py
@@ -73,6 +73,7 @@ class procurement_order(osv.osv):
'date_deadline': procurement.date_planned,
'planned_hours': planned_hours,
'remaining_hours': planned_hours,
+ 'partner_id': procurement.sale_line_id and procurement.sale_line_id.order_id.partner_id.id or False,
'user_id': procurement.product_id.product_manager.id,
'notes': procurement.note,
'procurement_id': procurement.id,
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 9fe05da33fc..72ae354faa6 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -318,21 +318,26 @@ class purchase_order(osv.osv):
for po in self.browse(cr, uid, ids, context=context):
pick_ids += [picking.id for picking in po.picking_ids]
- res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_in_form')
- res_id = res and res[1] or False
-
- return {
- 'name': _('Receptions'),
- 'view_type': 'form',
- 'view_mode': 'form',
- 'view_id': [res_id],
- 'res_model': 'stock.picking',
- 'context': "{'contact_display': 'partner'}",
- 'type': 'ir.actions.act_window',
- 'nodestroy': True,
- 'target': 'current',
- 'res_id': pick_ids and pick_ids[0] or False,
- }
+ action_model, action_id = tuple(mod_obj.get_object_reference(cr, uid, 'stock', 'action_picking_tree4'))
+ action = self.pool.get(action_model).read(cr, uid, action_id, context=context)
+ ctx = eval(action['context'])
+ ctx.update({
+ 'search_default_purchase_id': ids[0]
+ })
+ if pick_ids and len(pick_ids) == 1:
+ form_view_ids = [view_id for view_id, view in action['views'] if view == 'form']
+ view_id = form_view_ids and form_view_ids[0] or False
+ action.update({
+ 'views': [],
+ 'view_mode': 'form',
+ 'view_id': view_id,
+ 'res_id': pick_ids[0]
+ })
+
+ action.update({
+ 'context': ctx,
+ })
+ return action
def wkf_approve_order(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'state': 'approved', 'date_approve': fields.date.context_today(self,cr,uid,context=context)})
@@ -863,6 +868,12 @@ class purchase_order_line(osv.osv):
supplier_delay = int(supplier_info.delay) if supplier_info else 0
return datetime.strptime(date_order_str, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=supplier_delay)
+ def _check_product_uom_group(self, cr, uid, context=None):
+ group_uom = self.pool.get('ir.model.data').get_object(cr, uid, 'product', 'group_uom')
+ res = [user for user in group_uom.users if user.id == uid]
+ return len(res) and True or False
+
+
def onchange_product_id(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
name=False, price_unit=False, context=None):
@@ -908,7 +919,8 @@ class purchase_order_line(osv.osv):
uom_id = product_uom_po_id
if product.uom_id.category_id.id != product_uom.browse(cr, uid, uom_id, context=context).category_id.id:
- res['warning'] = {'title': _('Warning!'), 'message': _('Selected Unit of Measure does not belong to the same category as the product Unit of Measure.')}
+ if self._check_product_uom_group(cr, uid, context=context):
+ res['warning'] = {'title': _('Warning!'), 'message': _('Selected Unit of Measure does not belong to the same category as the product Unit of Measure.')}
uom_id = product_uom_po_id
res['value'].update({'product_uom': uom_id})
@@ -1083,15 +1095,15 @@ class procurement_order(osv.osv):
procurement_order()
-class mail_message(osv.osv):
- _name = 'mail.message'
- _inherit = 'mail.message'
+class mail_mail(osv.osv):
+ _name = 'mail.mail'
+ _inherit = 'mail.mail'
- def _postprocess_sent_message(self, cr, uid, message, context=None):
- if message.model == 'purchase.order':
+ def _postprocess_sent_message(self, cr, uid, mail, context=None):
+ if mail.model == 'purchase.order':
wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'purchase.order', message.res_id, 'send_rfq', cr)
- return super(mail_message, self)._postprocess_sent_message(cr, uid, message=message, context=context)
+ wf_service.trg_validate(uid, 'purchase.order', mail.res_id, 'send_rfq', cr)
+ return super(mail_mail, self)._postprocess_sent_message(cr, uid, mail=mail, context=context)
-mail_message()
+mail_mail()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index 9a2bd02f9a2..d8e6942f7fc 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -14,19 +14,40 @@
+
+
+ Pricelist Versions
+ ir.actions.act_window
+ product.pricelist.version
+ form
+
+ [('pricelist_id.type','=','purchase')]
+
+
+ Click to add a pricelist version.
+
+ There can be more than one version of a pricelist, each of
+ these must be valid during a certain period of time. Some
+ examples of versions: Main Prices, 2010, 2011, Summer Sales,
+ etc.
+
@@ -349,7 +370,7 @@
Quotationsir.actions.act_windowpurchase.order
- {'search_default_draft': 1}
+ {}[('state','in',('draft','sent','confirmed'))]tree,form,graph,calendar
diff --git a/addons/purchase/purchase_workflow.xml b/addons/purchase/purchase_workflow.xml
index 00fb5517568..212ce304e07 100644
--- a/addons/purchase/purchase_workflow.xml
+++ b/addons/purchase/purchase_workflow.xml
@@ -145,7 +145,7 @@
- invoice_method<>'order'
+ invoice_method<>'order' and invoiced
diff --git a/addons/purchase/res_config.py b/addons/purchase/res_config.py
index bf7512a8666..19b059d4d5b 100644
--- a/addons/purchase/res_config.py
+++ b/addons/purchase/res_config.py
@@ -46,10 +46,6 @@ class purchase_config_settings(osv.osv_memory):
'group_purchase_delivery_address': fields.boolean("Allow a different address for incoming products and invoicings",
implied_group='purchase.group_delivery_invoice_address',
help="Allows you to specify different delivery and invoice addresses on a purchase order."),
- 'module_purchase_analytic_plans': fields.boolean('Allow using multiple analytic accounts on the same order',
- help ="""Allows the user to maintain several analysis plans. These let you split
- lines on a purchase order between several accounts and analytic plans.
- This installs the module purchase_analytic_plans."""),
'module_warning': fields.boolean("Alerts by products or supplier",
help="""Allow to configure warnings on products and trigger them when a user wants to purchase a given product or a given supplier.
Example: Product: this product is deprecated, do not purchase more than 5.
@@ -62,6 +58,12 @@ class purchase_config_settings(osv.osv_memory):
help="""Purchase Requisitions are used when you want to request quotations from several suppliers for a given set of products.
You can configure per product if you directly do a Request for Quotation
to one supplier or if you want a purchase requisition to negotiate with several suppliers."""),
+ 'module_purchase_analytic_plans': fields.boolean('Use multiple analytic accounts on purchase orders',
+ help ="""Allows the user to maintain several analysis plans. These let you split lines on a purchase order between several accounts and analytic plans.
+ This installs the module purchase_analytic_plans."""),
+ 'group_analytic_account_for_purchases': fields.boolean('Analytic accounting for purchases',
+ implied_group='purchase.group_analytic_accounting',
+ help="Allows you to specify an analytic account on purchase orders."),
}
_defaults = {
@@ -75,7 +77,8 @@ class account_config_settings(osv.osv_memory):
_inherit = 'account.config.settings'
_columns = {
'module_purchase_analytic_plans': fields.boolean('Use multiple analytic accounts on orders',
- help="""This allows install module purchase_analytic_plans."""),
+ help ="""Allows the user to maintain several analysis plans. These let you split lines on a purchase order between several accounts and analytic plans.
+ This installs the module purchase_analytic_plans."""),
'group_analytic_account_for_purchases': fields.boolean('Analytic accounting for purchases',
implied_group='purchase.group_analytic_accounting',
help="Allows you to specify an analytic account on purchase orders."),
diff --git a/addons/purchase/res_config_view.xml b/addons/purchase/res_config_view.xml
index 6453752a638..f659d7b437f 100644
--- a/addons/purchase/res_config_view.xml
+++ b/addons/purchase/res_config_view.xml
@@ -74,6 +74,10 @@
Here you can track all the product receptions of purchase
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index ba85a62ca1d..feaf411cb54 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -771,7 +771,8 @@ class sale_order(osv.osv):
'default_res_id': ids[0],
'default_use_template': True,
'default_template_id': template_id,
- })
+ 'mark_so_as_sent': True
+ })
return {
'view_type': 'form',
'view_mode': 'form',
@@ -1476,15 +1477,14 @@ class sale_order_line(osv.osv):
sale_order_line()
-class mail_message(osv.osv):
- _inherit = 'mail.message'
-
- def _postprocess_sent_message(self, cr, uid, message, context=None):
- if message.model == 'sale.order':
+class mail_compose_message(osv.osv):
+ _inherit = 'mail.compose.message'
+ def send_mail(self, cr, uid, ids, context=None):
+ context = context or {}
+ if context.get('mark_so_as_sent', False) and context.get('default_res_id', False):
wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'sale.order', message.res_id, 'quotation_sent', cr)
- return super(mail_message, self)._postprocess_sent_message(cr, uid, message=message, context=context)
-
-mail_message()
+ wf_service.trg_validate(uid, 'sale.order', context.get('default_res_id', False), 'quotation_sent', cr)
+ return super(mail_compose_message, self).send_mail(cr, uid, ids, context=context)
+mail_compose_message()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml
index be871b87796..e54ba158b9b 100644
--- a/addons/sale_crm/sale_crm_view.xml
+++ b/addons/sale_crm/sale_crm_view.xml
@@ -9,8 +9,8 @@
-
-
+
+
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index f96c3582a6d..5b7acea2d86 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -673,6 +673,13 @@ class stock_picking(osv.osv):
]
def action_process(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ context.update({
+ 'active_model': self._name,
+ 'active_ids': ids,
+ 'active_id': len(ids) and ids[0] or False
+ })
return {
'view_type': 'form',
'view_mode': 'form',
diff --git a/addons/stock/wizard/stock_partial_picking.py b/addons/stock/wizard/stock_partial_picking.py
index 68e053b9e22..2cf0a743faa 100644
--- a/addons/stock/wizard/stock_partial_picking.py
+++ b/addons/stock/wizard/stock_partial_picking.py
@@ -107,21 +107,10 @@ class stock_partial_picking(osv.osv_memory):
picking_ids = context.get('active_ids', [])
active_model = context.get('active_model')
- if active_model == 'purchase.order':
- for purchase_order in self.pool.get('purchase.order').browse(cr, uid, picking_ids, context=context):
- picking_ids = [picking_id.id for picking_id in purchase_order.picking_ids]
- elif active_model == 'sale.order':
- for sale_order in self.pool.get('sale.order').browse(cr, uid, picking_ids, context=context):
- picking_ids = [picking.id for picking in sale_order.picking_ids]
-
if not picking_ids or len(picking_ids) != 1:
# Partial Picking Processing may only be done for one picking at a time
return res
- # The check about active_model is there in case the client mismatched the context during propagation of it
- # (already seen in previous bug where context passed was containing ir.ui.menu as active_model and the menu
- # ID as active_id). Though this should be fixed in clients now, this place is sensitive enough to ensure the
- # consistancy of the context.
- assert active_model in ('stock.picking', 'stock.picking.in', 'stock.picking.out', 'purchase.order', 'sale.order'), 'Bad context propagation'
+ assert active_model in ('stock.picking', 'stock.picking.in', 'stock.picking.out'), 'Bad context propagation'
picking_id, = picking_ids
if 'picking_id' in fields:
res.update(picking_id=picking_id)
diff --git a/addons/web_linkedin/static/src/xml/linkedin.xml b/addons/web_linkedin/static/src/xml/linkedin.xml
index 1a8009ab066..4956fd7df5a 100644
--- a/addons/web_linkedin/static/src/xml/linkedin.xml
+++ b/addons/web_linkedin/static/src/xml/linkedin.xml
@@ -30,7 +30,7 @@
LinkedIn access was not enabled on this server.
- Please ask your administrator to configure it in Settings > Configuration > Linkedin.
+ Please ask your administrator to configure it in Settings > Configuration > Sales > Social Network Integration.