diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 520b3ddad80..1caddec7f37 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -1272,7 +1272,7 @@ class account_move_line(osv.osv): period = period_obj.browse(cr, uid, period_id, context=context) for (state,) in result: if state == 'done': - raise UserError(_('You can not add/modify entries in a closed period %s of journal %s.') % (period.name,journal.name)) + raise UserError(_('You can not add/modify entries in a closed period %s of journal %s.') % (period.name, journal.name)) if not result: jour_period_obj.create(cr, uid, { 'name': (journal.code or journal.name)+':'+(period.name or ''), diff --git a/addons/base_import/models.py b/addons/base_import/models.py index 9778391521a..784ae7f49f1 100644 --- a/addons/base_import/models.py +++ b/addons/base_import/models.py @@ -158,12 +158,19 @@ class ir_import(orm.TransientModel): all the fields to traverse :rtype: list(Field) """ + string_match = None for field in fields: # FIXME: should match all translations & original # TODO: use string distance (levenshtein? hamming?) - if header.lower() == field['name'].lower() \ - or header.lower() == field['string'].lower(): + if header.lower() == field['name'].lower(): return [field] + if header.lower() == field['string'].lower(): + # matching string are not reliable way because + # strings have no unique constraint + string_match = field + if string_match: + # this behavior is only applied if there is no matching field['name'] + return [string_match] if '/' not in header: return [] diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index ea0eef6535d..4bcd2e58905 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -480,13 +480,13 @@ class calendar_alarm_manager(osv.AbstractModel): def get_next_notif(self, cr, uid, context=None): ajax_check_every_seconds = 300 - partner = self.pool['res.users'].read(cr, SUPERUSER_ID, uid, ['calendar_last_notif_ack'], context=context) + partner = self.pool['res.users'].read(cr, SUPERUSER_ID, uid, ['partner_id', 'calendar_last_notif_ack'], context=context) all_notif = [] if not partner: return [] - all_events = self.get_next_potential_limit_alarm(cr, uid, ajax_check_every_seconds, partner_id=partner['id'], mail=False, context=context) + all_events = self.get_next_potential_limit_alarm(cr, uid, ajax_check_every_seconds, partner_id=partner['partner_id'][0], mail=False, context=context) for event in all_events: # .values() max_delta = all_events[event]['max_duration'] @@ -586,7 +586,7 @@ class calendar_alarm(osv.Model): def _update_cron(self, cr, uid, context=None): try: cron = self.pool['ir.model.data'].get_object( - cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context) + cr, SUPERUSER_ID, 'calendar', 'ir_cron_scheduler_alarm', context=context) except ValueError: return False return cron.toggle(model=self._name, domain=[('type', '=', 'email')]) diff --git a/addons/google_calendar/google_calendar.py b/addons/google_calendar/google_calendar.py index 1eb3f918d3e..df90f78f5d1 100644 --- a/addons/google_calendar/google_calendar.py +++ b/addons/google_calendar/google_calendar.py @@ -976,7 +976,9 @@ class calendar_event(osv.Model): _inherit = "calendar.event" def get_fields_need_update_google(self, cr, uid, context=None): - return ['name', 'description', 'allday', 'date', 'date_end', 'stop', 'attendee_ids', 'alarm_ids', 'location', 'class', 'active'] + return ['name', 'description', 'allday', 'start', 'date_end', 'stop', + 'attendee_ids', 'alarm_ids', 'location', 'class', 'active', + 'start_date', 'start_datetime', 'stop_date', 'stop_datetime'] def write(self, cr, uid, ids, vals, context=None): if context is None: diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 2e0823add68..ac4154e80d0 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -319,7 +319,7 @@ class mail_compose_message(osv.TransientModel): # static wizard (mail.message) values mail_values = { 'subject': wizard.subject, - 'body': wizard.body, + 'body': wizard.body or '', 'parent_id': wizard.parent_id and wizard.parent_id.id, 'partner_ids': [partner.id for partner in wizard.partner_ids], 'attachment_ids': [attach.id for attach in wizard.attachment_ids], diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index fbcee18d3e4..851f7368497 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -214,6 +214,8 @@ class mrp_bom(osv.osv): @param properties: List of related properties. @return: False or BoM id. """ + if not context: + context = {} if properties is None: properties = [] if product_id: @@ -231,6 +233,8 @@ class mrp_bom(osv.osv): else: # neither product nor template, makes no sense to search return False + if context.get('company_id'): + domain = domain + [('company_id', '=', context['company_id'])] domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATE_FORMAT)), '|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT))] # order to prioritize bom with product_id over the one without diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index 8eb61d6c5cc..a0a9863491e 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -87,7 +87,7 @@ class procurement_order(osv.osv): else: properties = [x.id for x in procurement.property_ids] bom_id = bom_obj._bom_find(cr, uid, product_id=procurement.product_id.id, - properties=properties, context=context) + properties=properties, context=dict(context, company_id=procurement.company_id.id)) bom = bom_obj.browse(cr, uid, bom_id, context=context) routing_id = bom.routing_id.id return { diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py index fa73c994a38..77e3b0d27b6 100644 --- a/addons/mrp/stock.py +++ b/addons/mrp/stock.py @@ -44,6 +44,23 @@ class StockMove(osv.osv): if move.raw_material_production_id and move.location_dest_id.usage == 'production' and move.raw_material_production_id.product_id.track_production and not move.consumed_for: raise UserError(_("Because the product %s requires it, you must assign a serial number to your raw material %s to proceed further in your production. Please use the 'Produce' button to do so.") % (move.raw_material_production_id.product_id.name, move.product_id.name)) + # TODO master: remove me, no longer used + def _check_phantom_bom(self, cr, uid, move, context=None): + """check if product associated to move has a phantom bom + return list of ids of mrp.bom for that product """ + user_company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id + #doing the search as SUPERUSER because a user with the permission to write on a stock move should be able to explode it + #without giving him the right to read the boms. + domain = [ + '|', ('product_id', '=', move.product_id.id), + '&', ('product_id', '=', False), ('product_tmpl_id.product_variant_ids', '=', move.product_id.id), + ('type', '=', 'phantom'), + '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)), + '|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)), + ('company_id', '=', user_company)] + return self.pool.get('mrp.bom').search(cr, SUPERUSER_ID, domain, context=context) + + def _action_explode(self, cr, uid, move, context=None): """ Explodes pickings. @param move: Stock moves diff --git a/addons/mrp_operations/mrp_operations.py b/addons/mrp_operations/mrp_operations.py index 86a50626558..d86c8e6cd63 100644 --- a/addons/mrp_operations/mrp_operations.py +++ b/addons/mrp_operations/mrp_operations.py @@ -337,7 +337,7 @@ class mrp_production(osv.osv): for po in self.browse(cr, uid, ids, context=context): direction[po.id] = cmp(po.date_start, vals.get('date_start', False)) result = super(mrp_production, self).write(cr, uid, ids, vals, context=context) - if (vals.get('workcenter_lines', False) or vals.get('date_start', False)) and update: + if (vals.get('workcenter_lines', False) or vals.get('date_start', False) or vals.get('date_planned', False)) and update: self._compute_planned_workcenter(cr, uid, ids, context=context, mini=mini) for d in direction: if direction[d] == 1: diff --git a/addons/payment_adyen/models/adyen.py b/addons/payment_adyen/models/adyen.py index 52336cb48d9..6539ebb5ae0 100644 --- a/addons/payment_adyen/models/adyen.py +++ b/addons/payment_adyen/models/adyen.py @@ -172,7 +172,7 @@ class TxAdyen(osv.Model): }) return True else: - error = _('Paypal: feedback error') + error = _('Adyen: feedback error') _logger.info(error) tx.write({ 'state': 'error', diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index d1c4dff4cec..c8b07da4cc6 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -1362,9 +1362,9 @@ class pos_order_line(osv.osv): 'name': fields.char('Line No', required=True, copy=False), 'notice': fields.char('Discount Notice'), 'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True, change_default=True), - 'price_unit': fields.float(string='Unit Price', digits_compute=dp.get_precision('Account')), + 'price_unit': fields.float(string='Unit Price', digits_compute=dp.get_precision('Product Price')), 'qty': fields.float('Quantity', digits_compute=dp.get_precision('Product UoS')), - 'price_subtotal': fields.function(_amount_line_all, multi='pos_order_line_amount', digits_compute=dp.get_precision('Account'), string='Subtotal w/o Tax', store=True), + 'price_subtotal': fields.function(_amount_line_all, multi='pos_order_line_amount', digits_compute=dp.get_precision('Product Price'), string='Subtotal w/o Tax', store=True), 'price_subtotal_incl': fields.function(_amount_line_all, multi='pos_order_line_amount', digits_compute=dp.get_precision('Account'), string='Subtotal', store=True), 'discount': fields.float('Discount (%)', digits_compute=dp.get_precision('Account')), 'order_id': fields.many2one('pos.order', 'Order Ref', ondelete='cascade'), diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index ba751839ab1..4976d8da07e 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1646,34 +1646,34 @@ openerp.point_of_sale.load_models = function load_models(instance, module){ //mo }, /* ---- Payment Status --- */ get_subtotal : function(){ - return this.orderlines.reduce((function(sum, orderLine){ + return round_pr(this.orderlines.reduce((function(sum, orderLine){ return sum + orderLine.get_display_price(); - }), 0); + }), 0), this.pos.currency.rounding); }, get_total_with_tax: function() { - return this.orderlines.reduce((function(sum, orderLine) { + return round_pr(this.orderlines.reduce((function(sum, orderLine) { return sum + orderLine.get_price_with_tax(); - }), 0); + }), 0), this.pos.currency.rounding); }, get_total_without_tax: function() { - return this.orderlines.reduce((function(sum, orderLine) { + return round_pr(this.orderlines.reduce((function(sum, orderLine) { return sum + orderLine.get_price_without_tax(); - }), 0); + }), 0), this.pos.currency.rounding); }, get_total_discount: function() { - return this.orderlines.reduce((function(sum, orderLine) { + return round_pr(this.orderlines.reduce((function(sum, orderLine) { return sum + (orderLine.get_unit_price() * (orderLine.get_discount()/100) * orderLine.get_quantity()); - }), 0); + }), 0), this.pos.currency.rounding); }, get_total_tax: function() { - return this.orderlines.reduce((function(sum, orderLine) { + return round_pr(this.orderlines.reduce((function(sum, orderLine) { return sum + orderLine.get_tax(); - }), 0); + }), 0), this.pos.currency.rounding); }, get_total_paid: function() { - return this.paymentlines.reduce((function(sum, paymentLine) { + return round_pr(this.paymentlines.reduce((function(sum, paymentLine) { return sum + paymentLine.get_amount(); - }), 0); + }), 0), this.pos.currency.rounding); }, get_tax_details: function(){ var details = {}; diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index b31472cb63e..0e817695a6d 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -1453,6 +1453,7 @@ openerp.point_of_sale.load_screens = function load_screens(instance, module){ // this.inputbuffer = ""; this.firstinput = true; + this.decimal_point = instance.web._t.database.parameters.decimal_point; // This is a keydown handler that prevents backspace from // doing a back navigation @@ -1515,7 +1516,14 @@ openerp.point_of_sale.load_screens = function load_screens(instance, module){ // this.inputbuffer = newbuf; var order = this.pos.get_order(); if (order.selected_paymentline) { - order.selected_paymentline.set_amount(parseFloat(this.inputbuffer)); + var amount; + try{ + amount = instance.web.parse_value(this.inputbuffer, {type: "float"}); + } + catch(e){ + amount = 0; + } + order.selected_paymentline.set_amount(amount); this.order_changes(); this.render_paymentlines(); this.$('.paymentline.selected .edit').text(this.inputbuffer); diff --git a/addons/point_of_sale/static/src/js/widget_base.js b/addons/point_of_sale/static/src/js/widget_base.js index a391b3d19d3..a4006723fe8 100644 --- a/addons/point_of_sale/static/src/js/widget_base.js +++ b/addons/point_of_sale/static/src/js/widget_base.js @@ -48,6 +48,7 @@ openerp.point_of_sale.load_basewidget = function load_basewidget(instance, modul if (typeof amount === 'number') { amount = round_di(amount,decimals).toFixed(decimals); + amount = openerp.instances[this.session.name].web.format_value(parseFloat(amount), { type : 'float' }); } return amount; diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 449e5511dc9..9e5ce7e5008 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -1174,7 +1174,10 @@
diff --git a/addons/pos_restaurant/static/src/js/splitbill.js b/addons/pos_restaurant/static/src/js/splitbill.js
index f3d672ca7ac..519bc7104c0 100644
--- a/addons/pos_restaurant/static/src/js/splitbill.js
+++ b/addons/pos_restaurant/static/src/js/splitbill.js
@@ -43,7 +43,7 @@ openerp.pos_restaurant.load_splitbill = function(instance, module){
}
}else{
if( split.quantity < line.get_quantity()){
- split.quantity += line.get_unit().rounding;
+ split.quantity += line.get_unit().is_unit ? 1 : line.get_unit().rounding;
if(split.quantity > line.get_quantity()){
split.quantity = line.get_quantity();
}
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index d0fde9e74ad..8c928e11b77 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -1666,7 +1666,7 @@ class account_invoice(osv.Model):
else:
user_id = uid
po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
- for order in purchase_order_obj.browse(cr, uid, po_ids, context=context):
+ for order in purchase_order_obj.browse(cr, user_id, po_ids, context=context):
purchase_order_obj.message_post(cr, user_id, order.id, body=_("Invoice received"), context=context)
invoiced = []
shipped = True
@@ -1679,8 +1679,8 @@ class account_invoice(osv.Model):
if all(line.invoice_id.state not in ['draft', 'cancel'] for line in po_line.invoice_lines):
invoiced.append(po_line.id)
if invoiced and shipped:
- self.pool['purchase.order.line'].write(cr, uid, invoiced, {'invoiced': True})
- workflow.trg_write(uid, 'purchase.order', order.id, cr)
+ self.pool['purchase.order.line'].write(cr, user_id, invoiced, {'invoiced': True})
+ workflow.trg_write(user_id, 'purchase.order', order.id, cr)
return res
def confirm_paid(self, cr, uid, ids, context=None):
diff --git a/addons/report/models/report.py b/addons/report/models/report.py
index 604bf5aa37b..11937235a77 100644
--- a/addons/report/models/report.py
+++ b/addons/report/models/report.py
@@ -39,7 +39,6 @@ import lxml.html
import os
import subprocess
from contextlib import closing
-from datetime import datetime
from distutils.version import LooseVersion
from functools import partial
from pyPdf import PdfFileWriter, PdfFileReader
@@ -141,7 +140,6 @@ class Report(osv.Model):
context = dict(context, translatable=context.get('lang') != request.website.default_lang_code)
values.update(
time=time,
- datetime=datetime,
context_timestamp=lambda t: fields.datetime.context_timestamp(cr, uid, t, context),
translate_doc=translate_doc,
editable=True,
diff --git a/addons/report/views/layouts.xml b/addons/report/views/layouts.xml
index 620bfb9b3b5..37d93226e7f 100644
--- a/addons/report/views/layouts.xml
+++ b/addons/report/views/layouts.xml
@@ -124,7 +124,7 @@