diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py
index 74aea3dfc01..2d09a925ca7 100644
--- a/addons/mail/wizard/mail_compose_message.py
+++ b/addons/mail/wizard/mail_compose_message.py
@@ -130,7 +130,7 @@ class mail_compose_message(osv.TransientModel):
'wizard_id', 'attachment_id', 'Attachments'),
'filter_id': fields.many2one('ir.filters', 'Filters'),
}
-
+ #TODO change same_thread to False in trunk (Require view update)
_defaults = {
'composition_mode': 'comment',
'body': lambda self, cr, uid, ctx={}: '',
@@ -268,6 +268,8 @@ class mail_compose_message(osv.TransientModel):
'mail.message', 0,
context=context)
mail_values['attachment_ids'] = m2m_attachment_ids
+ if not mail_values.get('reply_to'):
+ mail_values['reply_to'] = mail_values['email_from']
self.pool.get('mail.mail').create(cr, uid, mail_values, context=context)
else:
subtype = 'mail.mt_comment'
@@ -321,10 +323,10 @@ class mail_compose_message(osv.TransientModel):
if email_dict.get('email_from'):
mail_values['email_from'] = email_dict.pop('email_from')
# replies redirection: mass mailing only
- if not wizard.same_thread:
- mail_values['reply_to'] = email_dict.pop('reply_to', None)
- else:
+ if wizard.same_thread and wizard.post:
email_dict.pop('reply_to', None)
+ else:
+ mail_values['reply_to'] = email_dict.pop('reply_to', None)
mail_values.update(email_dict)
# mass mailing without post: mail_mail values
if mass_mail_mode and not wizard.post:
diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml
index 948d9b3832c..23931649402 100644
--- a/addons/mail/wizard/mail_compose_message_view.xml
+++ b/addons/mail/wizard/mail_compose_message_view.xml
@@ -47,10 +47,10 @@
+ attrs="{'invisible':['|', ('composition_mode', '!=', 'mass_mail'), ('post', '=', False)]}"/>
+ attrs="{'invisible':['|', '&', ('same_thread', '=', True), ('post', '=', True), ('composition_mode', '!=', 'mass_mail')],
+ 'required':['&', '|', ('post', '=', False), ('same_thread', '=', False), ('composition_mode', '=', 'mass_mail')]}"/>
diff --git a/addons/mass_mailing/mail_thread.py b/addons/mass_mailing/mail_thread.py
index 0570596ba12..a4ff15a1a3f 100644
--- a/addons/mass_mailing/mail_thread.py
+++ b/addons/mass_mailing/mail_thread.py
@@ -48,6 +48,7 @@ class MailThread(osv.Model):
if bounce_alias in email_to:
bounce_match = tools.bounce_re.search(email_to)
if bounce_match:
+ bounced_model, bounced_thread_id = None, False
bounced_mail_id = bounce_match.group(1)
stat_ids = self.pool['mail.mail.statistics'].set_bounced(cr, uid, mail_mail_ids=[bounced_mail_id], context=context)
for stat in self.pool['mail.mail.statistics'].browse(cr, uid, stat_ids, context=context):
@@ -55,7 +56,7 @@ class MailThread(osv.Model):
bounced_thread_id = stat.res_id
_logger.info('Routing mail from %s to %s with Message-Id %s: bounced mail from mail %s, model: %s, thread_id: %s',
email_from, email_to, message_id, bounced_mail_id, bounced_model, bounced_thread_id)
- if bounced_model and bounced_model in self.pool and hasattr(self.pool[bounced_model], 'message_receive_bounce'):
+ if bounced_model and bounced_model in self.pool and hasattr(self.pool[bounced_model], 'message_receive_bounce') and bounced_thread_id:
self.pool[bounced_model].message_receive_bounce(cr, uid, [bounced_thread_id], mail_id=bounced_mail_id, context=context)
return False
diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py
index 5266147fef0..8b93e2a9bb6 100644
--- a/addons/mrp/procurement.py
+++ b/addons/mrp/procurement.py
@@ -111,9 +111,6 @@ class procurement_order(osv.osv):
bom_result = production_obj.action_compute(cr, uid,
[produce_id], properties=[x.id for x in procurement.property_ids])
production_obj.signal_button_confirm(cr, uid, [produce_id])
- if res_id:
- move_obj.write(cr, uid, [res_id],
- {'location_id': procurement.location_id.id})
self.production_order_create_note(cr, uid, ids, context=context)
return res
diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index 30fcff2e5e6..1f3564e3429 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -474,11 +474,12 @@ class pos_session(osv.osv):
account_move_obj = self.pool.get('account.move')
pos_order_obj = self.pool.get('pos.order')
for session in self.browse(cr, uid, ids, context=context):
+ local_context = dict(context or {}, force_company=session.config_id.journal_id.company_id.id)
order_ids = [order.id for order in session.order_ids if order.state == 'paid']
- move_id = account_move_obj.create(cr, uid, {'ref' : session.name, 'journal_id' : session.config_id.journal_id.id, }, context=context)
+ move_id = account_move_obj.create(cr, uid, {'ref' : session.name, 'journal_id' : session.config_id.journal_id.id, }, context=local_context)
- pos_order_obj._create_account_move_line(cr, uid, order_ids, session, move_id, context=context)
+ pos_order_obj._create_account_move_line(cr, uid, order_ids, session, move_id, context=local_context)
for order in session.order_ids:
if order.state not in ('paid', 'invoiced'):
@@ -948,22 +949,16 @@ class pos_order(osv.osv):
# Tricky, via the workflow, we only have one id in the ids variable
"""Create a account move line of order grouped by products or not."""
account_move_obj = self.pool.get('account.move')
- account_move_line_obj = self.pool.get('account.move.line')
account_period_obj = self.pool.get('account.period')
account_tax_obj = self.pool.get('account.tax')
- user_proxy = self.pool.get('res.users')
property_obj = self.pool.get('ir.property')
cur_obj = self.pool.get('res.currency')
- period = account_period_obj.find(cr, uid, context=context)[0]
-
#session_ids = set(order.session_id for order in self.browse(cr, uid, ids, context=context))
if session and not all(session.id == order.session_id.id for order in self.browse(cr, uid, ids, context=context)):
raise osv.except_osv(_('Error!'), _('Selected orders do not have the same session!'))
- current_company = user_proxy.browse(cr, uid, uid, context=context).company_id
-
grouped_data = {}
have_to_group_by = session and session.config_id.group_by or False
@@ -983,7 +978,7 @@ class pos_order(osv.osv):
if order.state != 'paid':
continue
- user_company = user_proxy.browse(cr, order.user_id.id, order.user_id.id).company_id
+ current_company = order.sale_journal.company_id
group_tax = {}
account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context)
@@ -1004,6 +999,7 @@ class pos_order(osv.osv):
# if have_to_group_by:
sale_journal_id = order.sale_journal.id
+ period = account_period_obj.find(cr, uid, context=dict(context or {}, company_id=current_company.id))[0]
# 'quantity': line.qty,
# 'product_id': line.product_id.id,
@@ -1013,7 +1009,7 @@ class pos_order(osv.osv):
'journal_id' : sale_journal_id,
'period_id' : period,
'move_id' : move_id,
- 'company_id': user_company and user_company.id or False,
+ 'company_id': current_company.id,
})
if data_type == 'product':
@@ -1054,7 +1050,10 @@ class pos_order(osv.osv):
cur = order.pricelist_id.currency_id
for line in order.lines:
tax_amount = 0
- taxes = [t for t in line.product_id.taxes_id]
+ taxes = []
+ for t in line.product_id.taxes_id:
+ if t.company_id.id == current_company.id:
+ taxes.append(t)
computed_taxes = account_tax_obj.compute_all(cr, uid, taxes, line.price_unit * (100.0-line.discount) / 100.0, line.qty)['taxes']
for tax in computed_taxes:
diff --git a/addons/point_of_sale/report/pos_details_summary.py b/addons/point_of_sale/report/pos_details_summary.py
index a4facaabcac..d6600926bd6 100644
--- a/addons/point_of_sale/report/pos_details_summary.py
+++ b/addons/point_of_sale/report/pos_details_summary.py
@@ -99,13 +99,10 @@ class pos_details_summary(report_sxw.rml_parse):
def _get_tax_amount(self, objects):
res = {}
- list_ids = []
for order in objects:
for line in order.lines:
- if len(line.product_id.taxes_id):
- tax = line.product_id.taxes_id[0]
- res[tax.name] = (line.price_unit * line.qty * (1-(line.discount or 0.0) / 100.0)) + (tax.id in list_ids and res[tax.name] or 0)
- list_ids.append(tax.id)
+ for tax in line.product_id.taxes_id:
+ res[tax.name] = res.setdefault(tax.name, 0.0) + (line.price_subtotal_incl - line.price_subtotal)
return res
def _get_sales_total(self, objects):
diff --git a/addons/point_of_sale/report/pos_details_summary.rml b/addons/point_of_sale/report/pos_details_summary.rml
index b1c71db7d40..6564f821010 100644
--- a/addons/point_of_sale/report/pos_details_summary.rml
+++ b/addons/point_of_sale/report/pos_details_summary.rml
@@ -232,7 +232,7 @@
- [[ t[0] ]]
+ [[ t[0].name ]]
[[ formatLang(t[1], currency_obj=company.currency_id) ]]
diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py
index 279f921f6c9..6f47d6d39d7 100644
--- a/addons/product/pricelist.py
+++ b/addons/product/pricelist.py
@@ -244,13 +244,15 @@ class product_pricelist(osv.osv):
for seller in product.seller_ids:
if (not partner) or (seller.name.id<>partner):
continue
- product_default_uom = product.uom_id.id
+ qty_in_seller_uom = qty
+ from_uom = context.get('uom') or product.uom_id.id
seller_uom = seller.product_uom and seller.product_uom.id or False
- if seller_uom and product_default_uom and product_default_uom != seller_uom:
+ if seller_uom and from_uom and from_uom != seller_uom:
+ qty_in_seller_uom = product_uom_obj._compute_qty(cr, uid, from_uom, qty, to_uom_id=seller_uom)
+ else:
uom_price_already_computed = True
- qty = product_uom_obj._compute_qty(cr, uid, product_default_uom, qty, to_uom_id=seller_uom)
for line in seller.pricelist_ids:
- if line.min_quantity <= qty:
+ if line.min_quantity <= qty_in_seller_uom:
price = line.price
else:
diff --git a/addons/project/project.py b/addons/project/project.py
index f03a4242de3..e5dcf5de2cf 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -358,6 +358,11 @@ class project(osv.osv):
default['state'] = 'open'
default['line_ids'] = []
default['tasks'] = []
+
+ # Don't prepare (expensive) data to copy children (analytic accounts),
+ # they are discarded in analytic.copy(), and handled in duplicate_template()
+ default['child_ids'] = []
+
proj = self.browse(cr, uid, id, context=context)
if not default.get('name', False):
default.update(name=_("%s (copy)") % (proj.name))
@@ -690,23 +695,13 @@ class task(osv.osv):
return {'value': vals}
def duplicate_task(self, cr, uid, map_ids, context=None):
- for new in map_ids.values():
- task = self.browse(cr, uid, new, context)
- child_ids = [ ch.id for ch in task.child_ids]
- if task.child_ids:
- for child in task.child_ids:
- if child.id in map_ids.keys():
- child_ids.remove(child.id)
- child_ids.append(map_ids[child.id])
-
- parent_ids = [ ch.id for ch in task.parent_ids]
- if task.parent_ids:
- for parent in task.parent_ids:
- if parent.id in map_ids.keys():
- parent_ids.remove(parent.id)
- parent_ids.append(map_ids[parent.id])
- #FIXME why there is already the copy and the old one
- self.write(cr, uid, new, {'parent_ids':[(6,0,set(parent_ids))], 'child_ids':[(6,0, set(child_ids))]})
+ mapper = lambda t: map_ids.get(t.id, t.id)
+ for task in self.browse(cr, uid, map_ids.values(), context):
+ new_child_ids = set(map(mapper, task.child_ids))
+ new_parent_ids = set(map(mapper, task.parent_ids))
+ if new_child_ids or new_parent_ids:
+ task.write({'parent_ids': [(6,0,list(new_parent_ids))],
+ 'child_ids': [(6,0,list(new_child_ids))]})
def copy_data(self, cr, uid, id, default=None, context=None):
if default is None:
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index e40d219ef10..4fa0e760df1 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -176,7 +176,7 @@
-
+
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index 176771bfd8d..d0b32f188a1 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -77,9 +77,9 @@
-
+
-
+
-
+
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index 81f16c5eb40..6d0214fba67 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -20,8 +20,8 @@
-
-
+
+ {"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}
diff --git a/addons/stock/product.py b/addons/stock/product.py
index 8161dc3ebaa..3eddf0a1c72 100644
--- a/addons/stock/product.py
+++ b/addons/stock/product.py
@@ -379,8 +379,6 @@ class product_product(osv.osv):
"In a context with a single Warehouse, this includes "
"goods stored in the Stock Location of this Warehouse, or any "
"of its children.\n"
- "stored in the Stock Location of the Warehouse of this Shop, "
- "or any of its children.\n"
"Otherwise, this includes goods stored in any Stock Location "
"with 'internal' type."),
'incoming_qty': fields.function(_product_available, multi='qty_available',
@@ -392,9 +390,6 @@ class product_product(osv.osv):
"In a context with a single Warehouse, this includes "
"goods arriving to the Stock Location of this Warehouse, or "
"any of its children.\n"
- "In a context with a single Shop, this includes goods "
- "arriving to the Stock Location of the Warehouse of this "
- "Shop, or any of its children.\n"
"Otherwise, this includes goods arriving to any Stock "
"Location with 'internal' type."),
'outgoing_qty': fields.function(_product_available, multi='qty_available',
@@ -406,9 +401,6 @@ class product_product(osv.osv):
"In a context with a single Warehouse, this includes "
"goods leaving the Stock Location of this Warehouse, or "
"any of its children.\n"
- "In a context with a single Shop, this includes goods "
- "leaving the Stock Location of the Warehouse of this "
- "Shop, or any of its children.\n"
"Otherwise, this includes goods leaving any Stock "
"Location with 'internal' type."),
'track_production': fields.boolean('Track Manufacturing Lots', help="Forces to specify a Serial Number for all moves containing this product and generated by a Manufacturing Order"),