diff --git a/addons/account/res_config.py b/addons/account/res_config.py index 9e994f735aa..0cf32abab40 100644 --- a/addons/account/res_config.py +++ b/addons/account/res_config.py @@ -135,16 +135,33 @@ class account_config_settings(osv.osv_memory): 'company_id', 'income_currency_exchange_account_id', type='many2one', relation='account.account', - string="Gain Exchange Rate Account", - domain="[('type', '=', 'other')]"), + string="Gain Exchange Rate Account", + domain="[('type', '=', 'other'), ('company_id', '=', company_id)]]"), 'expense_currency_exchange_account_id': fields.related( 'company_id', 'expense_currency_exchange_account_id', type="many2one", relation='account.account', string="Loss Exchange Rate Account", - domain="[('type', '=', 'other')]"), + domain="[('type', '=', 'other'), ('company_id', '=', company_id)]]"), } + def _check_account_gain(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids, context=context): + if obj.income_currency_exchange_account_id.company_id and obj.company_id != obj.income_currency_exchange_account_id.company_id: + return False + return True + + def _check_account_loss(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids, context=context): + if obj.expense_currency_exchange_account_id.company_id and obj.company_id != obj.expense_currency_exchange_account_id.company_id: + return False + return True + + _constraints = [ + (_check_account_gain, 'The company of the gain exchange rate account must be the same than the company selected.', ['income_currency_exchange_account_id']), + (_check_account_loss, 'The company of the loss exchange rate account must be the same than the company selected.', ['expense_currency_exchange_account_id']), + ] + def _default_company(self, cr, uid, context=None): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) return user.company_id.id diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py index d1947fb2c10..1dc7e83dc19 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py @@ -583,7 +583,7 @@ class hr_timesheet_sheet_sheet_day(osv.osv): (( select min(hrt.id) as id, - 'UTC' as timezone, + p.tz as timezone, l.date::date as name, s.id as sheet_id, sum(l.unit_amount) as total_timesheet, @@ -593,6 +593,10 @@ class hr_timesheet_sheet_sheet_day(osv.osv): hr_analytic_timesheet hrt JOIN account_analytic_line l ON l.id = hrt.line_id LEFT JOIN hr_timesheet_sheet_sheet s ON s.id = hrt.sheet_id + JOIN hr_employee e ON s.employee_id = e.id + JOIN resource_resource r ON e.resource_id = r.id + LEFT JOIN res_users u ON r.user_id = u.id + LEFT JOIN res_partner p ON u.partner_id = p.id group by l.date::date, s.id, timezone ) union ( select diff --git a/addons/l10n_be_invoice_bba/invoice.py b/addons/l10n_be_invoice_bba/invoice.py index 00a276431ec..f83bb98572c 100644 --- a/addons/l10n_be_invoice_bba/invoice.py +++ b/addons/l10n_be_invoice_bba/invoice.py @@ -189,13 +189,10 @@ class account_invoice(osv.osv): reference_type = vals['reference_type'] else: reference_type = inv.reference_type or '' - if reference_type == 'bba': - if vals.has_key('reference'): - bbacomm = vals['reference'] - else: - bbacomm = inv.reference or '' - if self.check_bbacomm(bbacomm): - reference = re.sub('\D', '', bbacomm) + + if reference_type == 'bba' and 'reference' in vals: + if self.check_bbacomm(vals['reference']): + reference = re.sub('\D', '', vals['reference']) vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++' same_ids = self.search(cr, uid, [('id', '!=', inv.id), ('type', '=', 'out_invoice'), diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 52329c440c7..5a18077c48e 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -1822,7 +1822,17 @@ class mail_thread(osv.AbstractModel): ('model', '=', self._name), ('res_id', '=', record_id)], limit=1, context=context) if msg_ids: - self.pool.get('mail.notification')._notify(cr, uid, msg_ids[0], partners_to_notify=partner_ids, context=context) + notification_obj = self.pool.get('mail.notification') + notification_obj._notify(cr, uid, msg_ids[0], partners_to_notify=partner_ids, context=context) + message = message_obj.browse(cr, uid, msg_ids[0], context=context) + if message.parent_id: + partner_ids_to_parent_notify = set(partner_ids).difference(partner.id for partner in message.parent_id.notified_partner_ids) + for partner_id in partner_ids_to_parent_notify: + notification_obj.create(cr, uid, { + 'message_id': message.parent_id.id, + 'partner_id': partner_id, + 'is_read': True, + }, context=context) def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None, values=None): """ Handle auto subscription. Two methods for auto subscription exist: @@ -1904,6 +1914,7 @@ class mail_thread(osv.AbstractModel): self._message_auto_subscribe_notify(cr, uid, ids, user_pids, context=context) + return True #------------------------------------------------------ diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 6532b32e167..2fb1e73f560 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -99,6 +99,16 @@ class mrp_workcenter(osv.osv): value = {'costs_hour': cost.standard_price} return {'value': value} + def _check_capacity_per_cycle(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids, context=context): + if obj.capacity_per_cycle <= 0.0: + return False + return True + + _constraints = [ + (_check_capacity_per_cycle, 'The capacity per cycle must be strictly positive.', ['capacity_per_cycle']), + ] + class mrp_routing(osv.osv): """ For specifying the routings of Work Centers. diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index d613b104b37..ae97007b0f0 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -402,7 +402,7 @@ - + @@ -416,8 +416,8 @@ - - + +
diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py index 320d5438a7d..01c6f247f66 100644 --- a/addons/product/pricelist.py +++ b/addons/product/pricelist.py @@ -381,7 +381,7 @@ class product_pricelist_version(osv.osv): 'active': fields.boolean('Active', help="When a version is duplicated it is set to non active, so that the " \ "dates do not overlaps with original version. You should change the dates " \ - "and reactivate the pricelist", copy=False), + "and reactivate the pricelist"), 'items_id': fields.one2many('product.pricelist.item', 'price_version_id', 'Price List Items', required=True, copy=True), 'date_start': fields.date('Start Date', help="First valid date for the version."), @@ -420,6 +420,13 @@ class product_pricelist_version(osv.osv): ['date_start', 'date_end']) ] + def copy(self, cr, uid, id, default=None, context=None): + # set active False to prevent overlapping active pricelist + # versions + if not default: + default = {} + default['active'] = False + return super(product_pricelist_version, self).copy(cr, uid, id, default, context=context) class product_pricelist_item(osv.osv): def _price_field_get(self, cr, uid, context=None): diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py index 47ab3d5bb05..28c48bc8a67 100644 --- a/addons/sale/wizard/sale_make_invoice_advance.py +++ b/addons/sale/wizard/sale_make_invoice_advance.py @@ -101,7 +101,7 @@ class sale_advance_payment_inv(osv.osv_memory): if wizard.amount <= 0.00: raise UserError(_('The value of Advance Amount must be positive.')) if wizard.advance_payment_method == 'percentage': - inv_amount = sale.amount_total * wizard.amount / 100 + inv_amount = sale.amount_untaxed * wizard.amount / 100 if not res.get('name'): res['name'] = self._translate_advance(cr, uid, percentage=True, context=dict(context, lang=sale.partner_id.lang)) % (wizard.amount) else: diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py index 2fcc661c079..7ff3f3001b8 100644 --- a/addons/stock_account/stock_account.py +++ b/addons/stock_account/stock_account.py @@ -79,13 +79,22 @@ class stock_quant(osv.osv): ''' if context is None: context = {} + account_period = self.pool['account.period'] super(stock_quant, self)._price_update(cr, uid, quant_ids, newprice, context=context) - ctx = context.copy() for quant in self.browse(cr, uid, quant_ids, context=context): move = self._get_latest_move(cr, uid, quant, context=context) - # this is where we post accounting entries for adjustment - ctx['force_valuation_amount'] = newprice - quant.cost - self._account_entry_move(cr, uid, [quant], move, context=ctx) + valuation_update = newprice - quant.cost + # this is where we post accounting entries for adjustment, if needed + if not quant.company_id.currency_id.is_zero(valuation_update): + # adjustment journal entry needed, cost has been updated + period_id = (context.get('force_period') or + account_period.find(cr, uid, move.date, context=context)[0]) + period = account_period.browse(cr, uid, period_id, context=context) + # If neg quant period already closed (likely with manual valuation), skip update + if period.state != 'done': + ctx = dict(context, force_valuation_amount=valuation_update) + self._account_entry_move(cr, uid, [quant], move, context=ctx) + #update the standard price of the product, only if we would have done it if we'd have had enough stock at first, which means #1) the product cost's method is 'real' #2) we just fixed a negative quant caused by an outgoing shipment diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index d3436cc072a..36dac599b96 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -849,6 +849,16 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM } } } + // Heuristic to assign a proper sequence number for new records that + // are added in a dataset containing other lines with existing sequence numbers + if (!self.datarecord.id && self.fields.sequence && + !_.has(values, 'sequence') && !_.isEmpty(self.dataset.cache)) { + // Find current max or min sequence (editable top/bottom) + var current = _[prepend_on_create ? "min" : "max"]( + _.map(self.dataset.cache, function(o){return o.values.sequence}) + ); + values['sequence'] = prepend_on_create ? current - 1 : current + 1; + } if (form_invalid) { self.set({'display_invalid_fields': true}); first_invalid_field.focus(); diff --git a/addons/website_sale_options/controllers/main.py b/addons/website_sale_options/controllers/main.py index f2b53d84fb9..95e981fe77c 100644 --- a/addons/website_sale_options/controllers/main.py +++ b/addons/website_sale_options/controllers/main.py @@ -23,8 +23,11 @@ class website_sale_options(website_sale): return r @http.route(['/shop/cart/update_option'], type='http', auth="public", methods=['POST'], website=True) - def cart_options_update_json(self, product_id, add_qty=1, set_qty=0, goto_shop=None, **kw): + def cart_options_update_json(self, product_id, add_qty=1, set_qty=0, goto_shop=None, lang=None, **kw): cr, uid, context, pool = request.cr, request.uid, request.context, request.registry + if lang: + context = dict(context, lang=lang) + request.website = request.website.with_context(context) order = request.website.sale_get_order(force_create=1) product = pool['product.product'].browse(cr, uid, int(product_id), context=context) @@ -57,11 +60,13 @@ class website_sale_options(website_sale): if not context.get('pricelist'): context['pricelist'] = int(pricelist) + website_context = kw.get('kwargs', {}).get('context', {}) + context = dict(context or {}, **website_context) from_currency = pool.get('product.price.type')._get_field_currency(cr, uid, 'list_price', context) to_currency = pricelist.currency_id compute_currency = lambda price: pool['res.currency']._compute(cr, uid, from_currency, to_currency, price, context=context) - product = pool['product.product'].browse(cr, uid, int(product_id), context=context) + request.website = request.website.with_context(context) return request.website._render("website_sale_options.modal", { 'product': product, diff --git a/addons/website_sale_options/static/src/js/website_sale.js b/addons/website_sale_options/static/src/js/website_sale.js index 871babd6550..2b8c042005b 100644 --- a/addons/website_sale_options/static/src/js/website_sale.js +++ b/addons/website_sale_options/static/src/js/website_sale.js @@ -27,6 +27,7 @@ $(document).ready(function () { var $a = $(this); $form.ajaxSubmit({ url: '/shop/cart/update_option', + data: {lang: openerp.website.get_context().lang}, success: function (quantity) { if (!$a.hasClass('js_goto_shop')) { window.location.href = window.location.href.replace(/shop([\/?].*)?$/, "shop/cart"); diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index f51ac267487..bcfff19b572 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -896,6 +896,8 @@ class users_view(osv.osv): def fields_get(self, cr, uid, allfields=None, context=None, write_access=True, attributes=None): res = super(users_view, self).fields_get(cr, uid, allfields, context, write_access, attributes) # add reified groups fields + if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'): + return res for app, kind, gs in self.pool['res.groups'].get_groups_by_application(cr, uid, context): if kind == 'selection': # selection group field