diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 42f3effd6f9..06e59232ac9 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -114,7 +114,7 @@ class account_invoice(osv.osv): #we check if the invoice is partially reconciled and if there are other invoices #involved in this partial reconciliation (and we sum these invoices) for line in aml.reconcile_partial_id.line_partial_ids: - if line.invoice: + if line.invoice and invoice.type == line.invoice.type: nb_inv_in_partial_rec += 1 #store the max invoice id as for this invoice we will make a balance instead of a simple division max_invoice_id = max(max_invoice_id, line.invoice.id) diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 790f34a4f7f..8f4d66e65ec 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -1453,7 +1453,7 @@ diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index a0d14e889cb..b73dad2d385 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -664,13 +664,20 @@ class account_analytic_account(osv.osv): partner_payment_term = contract.partner_id.property_payment_term and contract.partner_id.property_payment_term.id or False + currency_id = False + if contract.pricelist_id: + currency_id = contract.pricelist_id.currency_id.id + elif contract.partner_id.property_product_pricelist: + currency_id = contract.partner_id.property_product_pricelist.currency_id.id + elif contract.company_id: + currency_id = contract.company_id.currency_id.id inv_data = { 'reference': contract.code or False, 'account_id': contract.partner_id.property_account_receivable.id, 'type': 'out_invoice', 'partner_id': contract.partner_id.id, - 'currency_id': contract.partner_id.property_product_pricelist.id or False, + 'currency_id': currency_id, 'journal_id': len(journal_ids) and journal_ids[0] or False, 'date_invoice': contract.recurring_next_date, 'origin': contract.name, diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index c9516b6135f..aa94be88041 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -1366,6 +1366,7 @@ class account_voucher(osv.osv): move_pool = self.pool.get('account.move') move_line_pool = self.pool.get('account.move.line') for voucher in self.browse(cr, uid, ids, context=context): + local_context = dict(context, force_company=voucher.journal_id.company_id.id) if voucher.move_id: continue company_currency = self._get_company_currency(cr, uid, voucher.id, context) @@ -1380,7 +1381,7 @@ class account_voucher(osv.osv): # Get the name of the account_move just created name = move_pool.browse(cr, uid, move_id, context=context).name # Create the first line of the voucher - move_line_id = move_line_pool.create(cr, uid, self.first_move_line_get(cr,uid,voucher.id, move_id, company_currency, current_currency, context), context) + move_line_id = move_line_pool.create(cr, uid, self.first_move_line_get(cr,uid,voucher.id, move_id, company_currency, current_currency, local_context), local_context) move_line_brw = move_line_pool.browse(cr, uid, move_line_id, context=context) line_total = move_line_brw.debit - move_line_brw.credit rec_list_ids = [] @@ -1392,9 +1393,9 @@ class account_voucher(osv.osv): line_total, rec_list_ids = self.voucher_move_line_create(cr, uid, voucher.id, line_total, move_id, company_currency, current_currency, context) # Create the writeoff line if needed - ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id, line_total, move_id, name, company_currency, current_currency, context) + ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id, line_total, move_id, name, company_currency, current_currency, local_context) if ml_writeoff: - move_line_pool.create(cr, uid, ml_writeoff, context) + move_line_pool.create(cr, uid, ml_writeoff, local_context) # We post the voucher. self.write(cr, uid, [voucher.id], { 'move_id': move_id, @@ -1605,7 +1606,11 @@ class account_bank_statement(osv.osv): bank_st_line_obj = self.pool.get('account.bank.statement.line') st_line = bank_st_line_obj.browse(cr, uid, st_line_id, context=context) if st_line.voucher_id: - voucher_obj.write(cr, uid, [st_line.voucher_id.id], {'number': next_number}, context=context) + voucher_obj.write(cr, uid, [st_line.voucher_id.id], + {'number': next_number, + 'date': st_line.date, + 'period_id': st_line.statement_id.period_id.id}, + context=context) if st_line.voucher_id.state == 'cancel': voucher_obj.action_cancel_draft(cr, uid, [st_line.voucher_id.id], context=context) voucher_obj.signal_proforma_voucher(cr, uid, [st_line.voucher_id.id]) diff --git a/addons/account_voucher/wizard/account_statement_from_invoice.py b/addons/account_voucher/wizard/account_statement_from_invoice.py index de5121a819b..059989801d1 100644 --- a/addons/account_voucher/wizard/account_statement_from_invoice.py +++ b/addons/account_voucher/wizard/account_statement_from_invoice.py @@ -94,7 +94,7 @@ class account_statement_from_invoice_lines(osv.osv_memory): 'account_id': result['value'].get('account_id', statement.journal_id.default_credit_account_id.id), 'company_id': statement.company_id.id, 'currency_id': statement.currency.id, - 'date': line.date, + 'date': statement.date, 'amount': sign*amount, 'payment_rate': result['value']['payment_rate'], 'payment_rate_currency_id': result['value']['payment_rate_currency_id'], @@ -119,7 +119,7 @@ class account_statement_from_invoice_lines(osv.osv_memory): 'statement_id': statement_id, 'ref': line.ref, 'voucher_id': voucher_id, - 'date': time.strftime('%Y-%m-%d'), + 'date': statement.date, }, context=context) return {'type': 'ir.actions.act_window_close'} diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 159baf3a9e7..ca4a15bca6e 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -268,10 +268,14 @@ def log_fct(cr, uid_orig, model, method, fct_src, *args, **kw): new_values = get_data(cr, uid_orig, pool, res_ids, model, method) elif method == 'read': res = fct_src(cr, uid_orig, model.model, method, *args, **kw) + if isinstance(res, dict): + records = [res] + else: + records = res # build the res_ids and the old_values dict. Here we don't use get_data() to # avoid performing an additional read() res_ids = [] - for record in res: + for record in records: res_ids.append(record['id']) old_values[(model.id, record['id'])] = {'value': record, 'text': record} # log only the fields read @@ -279,7 +283,9 @@ def log_fct(cr, uid_orig, model, method, fct_src, *args, **kw): elif method == 'unlink': res_ids = args[0] old_values = get_data(cr, uid_orig, pool, res_ids, model, method) - res = fct_src(cr, uid_orig, model.model, method, *args, **kw) + # process_data first as fct_src will unlink the record + self.process_data(cr, uid_orig, pool, res_ids, model, method, old_values, new_values, field_list) + return fct_src(cr, uid_orig, model.model, method, *args, **kw) else: # method is write, action or workflow action res_ids = [] if args: @@ -322,7 +328,7 @@ def get_data(cr, uid, pool, res_ids, model, method): data = {} resource_pool = pool[model.model] # read all the fields of the given resources in super admin mode - for resource in resource_pool.read(cr, SUPERUSER_ID, res_ids): + for resource in resource_pool.read(cr, SUPERUSER_ID, res_ids, resource_pool._all_columns): values = {} values_text = {} resource_id = resource['id'] @@ -456,7 +462,9 @@ def process_data(cr, uid, pool, res_ids, model, method, old_values=None, new_val # if at least one modification has been found for model_id, resource_id in lines: - name = pool[model.model].name_get(cr, uid, [resource_id])[0][1] + line_model = pool.get('ir.model').browse(cr, SUPERUSER_ID, model_id).model + name = pool.get(line_model).name_get(cr, uid, [resource_id])[0][1] + vals = { 'method': method, 'object_id': model_id, diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 58728a77aef..e48533ebeb4 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -275,6 +275,13 @@ class base_action_rule(osv.osv): if action.filter_id: domain = eval(action.filter_id.domain) ctx.update(eval(action.filter_id.context)) + if 'lang' not in ctx: + # Filters might be language-sensitive, attempt to reuse creator lang + # as we are usually running this as super-user in background + [filter_meta] = action.filter_id.perm_read() + user_id = filter_meta['write_uid'] and filter_meta['write_uid'][0] or \ + filter_meta['create_uid'][0] + ctx['lang'] = self.pool['res.users'].browse(cr, uid, user_id).lang record_ids = model.search(cr, uid, domain, context=ctx) # determine when action should occur for the records diff --git a/addons/email_template/email_template_view.xml b/addons/email_template/email_template_view.xml index 5429341e154..4f7828cb531 100644 --- a/addons/email_template/email_template_view.xml +++ b/addons/email_template/email_template_view.xml @@ -60,7 +60,7 @@

Body

- + diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index ee4dcac5414..f60ee1a2a3f 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -369,10 +369,11 @@ class mail_thread(osv.AbstractModel): track_ctx = dict(context) if 'lang' not in track_ctx: track_ctx['lang'] = self.pool.get('res.users').browse(cr, uid, uid, context=context).lang - tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx) - if tracked_fields: - initial_values = {thread_id: dict((item, False) for item in tracked_fields)} - self.message_track(cr, uid, [thread_id], tracked_fields, initial_values, context=track_ctx) + if not context.get('mail_notrack'): + tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx) + if tracked_fields: + initial_values = {thread_id: dict((item, False) for item in tracked_fields)} + self.message_track(cr, uid, [thread_id], tracked_fields, initial_values, context=track_ctx) return thread_id def write(self, cr, uid, ids, values, context=None): @@ -393,7 +394,11 @@ class mail_thread(osv.AbstractModel): result = super(mail_thread, self).write(cr, uid, ids, values, context=context) self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values) - # Perform the tracking + if not context.get('mail_notrack'): + # Perform the tracking + tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context) + else: + tracked_fields = None if tracked_fields: self.message_track(cr, uid, ids, tracked_fields, initial_values, context=track_ctx) return result @@ -414,6 +419,9 @@ class mail_thread(osv.AbstractModel): return res def copy(self, cr, uid, id, default=None, context=None): + # avoid tracking multiple temporary changes during copy + context = dict(context or {}, mail_notrack=True) + default = default or {} default['message_ids'] = [] default['message_follower_ids'] = [] @@ -1549,18 +1557,23 @@ class mail_thread(osv.AbstractModel): """ Add partners to the records followers. """ if context is None: context = {} + # not necessary for computation, but saves an access right check + if not partner_ids: + return True mail_followers_obj = self.pool.get('mail.followers') subtype_obj = self.pool.get('mail.message.subtype') user_pid = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id if set(partner_ids) == set([user_pid]): - if context.get('operation', '') != 'create': - try: - self.check_access_rights(cr, uid, 'read') + try: + self.check_access_rights(cr, uid, 'read') + if context.get('operation', '') == 'create': + self.check_access_rule(cr, uid, ids, 'create') + else: self.check_access_rule(cr, uid, ids, 'read') - except (osv.except_osv, orm.except_orm): - return False + except (osv.except_osv, orm.except_orm): + return False else: self.check_access_rights(cr, uid, 'write') self.check_access_rule(cr, uid, ids, 'write') @@ -1605,6 +1618,9 @@ class mail_thread(osv.AbstractModel): def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None): """ Remove partners from the records followers. """ + # not necessary for computation, but saves an access right check + if not partner_ids: + return True user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0] if set(partner_ids) == set([user_pid]): self.check_access_rights(cr, uid, 'read') diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 938d6a01f6d..c103e4d4ab2 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -197,6 +197,7 @@ openerp_mail_followers = function(session, mail) { // clean and display title var node_user_list = this.$('.oe_follower_list').empty(); this.$('.oe_follower_title').html(this._format_followers(this.followers.length)); + self.message_is_follower = _.indexOf(this.followers.map(function (rec) { return rec[2]['is_uid']}), true) != -1; // truncate number of displayed followers var truncated = this.followers.slice(0, this.displayed_nb); _(truncated).each(function (record) { @@ -207,9 +208,6 @@ openerp_mail_followers = function(session, mail) { 'is_editable': record[2]['is_editable'], 'avatar_url': mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record[0]), } - if (partner.is_uid) { - self.message_is_follower = partner.is_uid; - } $(session.web.qweb.render('mail.followers.partner', {'record': partner, 'widget': self})).appendTo(node_user_list); // On mouse-enter it will show the edit_subtype pencil. if (partner.is_editable) { diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 3a7a5469ee1..9696fab789d 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -135,14 +135,14 @@ and - - + + - , others... + , others... <<< @@ -150,8 +150,8 @@ @@ -177,7 +177,7 @@

- +

@@ -263,11 +263,11 @@

- + - + : - +

@@ -283,8 +283,8 @@
- - + + updated document @@ -303,20 +303,20 @@ - - + + , - and more + and more notified • - + • @@ -333,7 +333,7 @@
show more message show one more message - show more messages + show more messages
@@ -353,7 +353,7 @@ --> - + 8 diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index a936b8237d6..6e8682cb533 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -43,13 +43,13 @@ - +
-
And more.
+
And more.
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 @@