diff --git a/addons/account/account.py b/addons/account/account.py index 673d6a04fc2..d07da1d0179 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -1680,7 +1680,8 @@ class account_move_reconcile(osv.osv): if not total: self.pool.get('account.move.line').write(cr, uid, map(lambda x: x.id, rec.line_partial_ids), - {'reconcile_id': rec.id } + {'reconcile_id': rec.id }, + context=context ) return True diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index b7d4e6b7fb9..bbe70b3881e 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -802,11 +802,14 @@ class account_move_line(osv.osv): if self.pool.get('res.currency').is_zero(cr, uid, currency_id, total): res = self.reconcile(cr, uid, merges+unmerge, context=context, writeoff_acc_id=writeoff_acc_id, writeoff_period_id=writeoff_period_id, writeoff_journal_id=writeoff_journal_id) return res + # marking the lines as reconciled does not change their validity, so there is no need + # to revalidate their moves completely. + reconcile_context = dict(context, novalidate=True) r_id = move_rec_obj.create(cr, uid, { 'type': type, 'line_partial_ids': map(lambda x: (4,x,False), merges+unmerge) - }, context=context) - move_rec_obj.reconcile_partial_check(cr, uid, [r_id] + merges_rec, context=context) + }, context=reconcile_context) + move_rec_obj.reconcile_partial_check(cr, uid, [r_id] + merges_rec, context=reconcile_context) return True def reconcile(self, cr, uid, ids, type='auto', writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False, context=None): @@ -931,11 +934,14 @@ class account_move_line(osv.osv): writeoff_line_ids = [writeoff_line_ids[1]] ids += writeoff_line_ids + # marking the lines as reconciled does not change their validity, so there is no need + # to revalidate their moves completely. + reconcile_context = dict(context, novalidate=True) r_id = move_rec_obj.create(cr, uid, { 'type': type, 'line_id': map(lambda x: (4, x, False), ids), 'line_partial_ids': map(lambda x: (3, x, False), ids) - }) + }, context=reconcile_context) # the id of the move.reconcile is written in the move.line (self) by the create method above # because of the way the line_id are defined: (4, x, False) for id in ids: diff --git a/addons/account_anglo_saxon/invoice.py b/addons/account_anglo_saxon/invoice.py index 0b3c573b943..ce9c89ad531 100644 --- a/addons/account_anglo_saxon/invoice.py +++ b/addons/account_anglo_saxon/invoice.py @@ -127,14 +127,14 @@ class account_invoice_line(osv.osv): if line.get('invl_id', 0) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) - if inv.currency_id.id != company_currency: - standard_price = self.pool.get('res.currency').compute(cr, uid, company_currency, inv.currency_id.id, standard_price, context={'date': inv.date_invoice}) if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id: #for average/fifo/lifo costing method, fetch real cost price from incomming moves stock_move_obj = self.pool.get('stock.move') valuation_stock_move = stock_move_obj.search(cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context) if valuation_stock_move: valuation_price_unit = stock_move_obj.browse(cr, uid, valuation_stock_move[0], context=context).price_unit + if inv.currency_id.id != company_currency: + valuation_price_unit = self.pool.get('res.currency').compute(cr, uid, company_currency, inv.currency_id.id, valuation_price_unit, context={'date': inv.date_invoice}) if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc: price_diff = round(i_line.price_unit - valuation_price_unit, account_prec) line.update({'price': round(valuation_price_unit * line['quantity'], account_prec)}) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index ae2d0dcdcfb..3ac0efb3263 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -358,7 +358,7 @@ class account_voucher(osv.osv): \n* The \'Posted\' status is used when user create voucher,a voucher number is generated and voucher entries are created in account \ \n* The \'Cancelled\' status is used when user cancel voucher.'), 'amount': fields.float('Total', digits_compute=dp.get_precision('Account'), required=True, readonly=True, states={'draft':[('readonly',False)]}), - 'tax_amount':fields.float('Tax Amount', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}), + 'tax_amount':fields.float('Tax Amount', digits_compute=dp.get_precision('Account'), readonly=True), 'reference': fields.char('Ref #', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Transaction reference number."), 'number': fields.char('Number', size=32, readonly=True,), 'move_id':fields.many2one('account.move', 'Account Entry'), @@ -1323,10 +1323,14 @@ class account_voucher(osv.osv): if voucher.payment_option == 'with_writeoff': account_id = voucher.writeoff_acc_id.id write_off_name = voucher.comment - elif voucher.type in ('sale', 'receipt'): - account_id = voucher.partner_id.property_account_receivable.id + elif voucher.partner_id: + if voucher.type in ('sale', 'receipt'): + account_id = voucher.partner_id.property_account_receivable.id + else: + account_id = voucher.partner_id.property_account_payable.id else: - account_id = voucher.partner_id.property_account_payable.id + # fallback on account of voucher + account_id = voucher.account_id.id sign = voucher.type == 'payment' and -1 or 1 move_line = { 'name': write_off_name or name, diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index 3e4f1635914..2fc8f04112e 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -159,7 +159,7 @@ account.voucher form tree,form,graph - {'type':'general'} + {} diff --git a/addons/auth_oauth/auth_oauth.py b/addons/auth_oauth/auth_oauth.py index 34b6aa44936..f9fb206f51e 100644 --- a/addons/auth_oauth/auth_oauth.py +++ b/addons/auth_oauth/auth_oauth.py @@ -21,4 +21,5 @@ class auth_oauth_provider(osv.osv): } _defaults = { 'enabled' : False, + 'css_class' : "zocial", } diff --git a/addons/point_of_sale/report/pos_order_report.py b/addons/point_of_sale/report/pos_order_report.py index 5489ccf7099..501a829a46e 100644 --- a/addons/point_of_sale/report/pos_order_report.py +++ b/addons/point_of_sale/report/pos_order_report.py @@ -27,7 +27,7 @@ class pos_order_report(osv.osv): _description = "Point of Sale Orders Statistics" _auto = False _columns = { - 'date': fields.date('Date Order', readonly=True), + 'date': fields.datetime('Date Order', readonly=True), 'partner_id':fields.many2one('res.partner', 'Partner', readonly=True), 'product_id':fields.many2one('product.product', 'Product', readonly=True), 'state': fields.selection([('draft', 'New'), ('paid', 'Closed'), ('done', 'Synchronized'), ('invoiced', 'Invoiced'), ('cancel', 'Cancelled')], diff --git a/addons/product/product.py b/addons/product/product.py index 8496245ea91..76270b6e796 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -684,6 +684,9 @@ class product_product(osv.osv): unlink_ids = [] unlink_product_tmpl_ids = [] for product in self.browse(cr, uid, ids, context=context): + # Check if product still exists, in case it has been unlinked by unlinking its template + if not product.exists(): + continue tmpl_id = product.product_tmpl_id.id # Check if the product is last product of this template other_product_ids = self.search(cr, uid, [('product_tmpl_id', '=', tmpl_id), ('id', '!=', product.id)], context=context) diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index 2d5dea89d35..7cec0137155 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -126,7 +126,7 @@ class stock_partial_picking(osv.osv_memory): # Overridden to inject the purchase price as true 'cost price' when processing # incoming pickings. def _product_cost_for_average_update(self, cr, uid, move): - if move.picking_id.purchase_id: + if move.picking_id.purchase_id and move.purchase_line_id: return {'cost': move.purchase_line_id.price_unit, 'currency': move.picking_id.purchase_id.currency_id.id} return super(stock_partial_picking, self)._product_cost_for_average_update(cr, uid, move) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 23469171fcb..a68538f46dd 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -28,6 +28,12 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO import openerp.addons.decimal_precision as dp from openerp import workflow +class res_company(osv.Model): + _inherit = "res.company" + _columns = { + 'sale_note': fields.text('Default Terms and Conditions', translate=True, help="Default terms and conditions for quotations."), + } + class sale_order(osv.osv): _name = "sale.order" _inherit = ['mail.thread', 'ir.needaction_mixin'] @@ -987,12 +993,6 @@ class sale_order_line(osv.osv): raise osv.except_osv(_('Invalid Action!'), _('Cannot delete a sales order line which is in state \'%s\'.') %(rec.state,)) return super(sale_order_line, self).unlink(cr, uid, ids, context=context) -class res_company(osv.Model): - _inherit = "res.company" - _columns = { - 'sale_note': fields.text('Default Terms and Conditions', translate=True, help="Default terms and conditions for quotations."), - } - class mail_compose_message(osv.Model): _inherit = 'mail.compose.message' diff --git a/addons/stock/product.py b/addons/stock/product.py index 1cd93225d45..724a2097ba0 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -277,6 +277,8 @@ class product_product(osv.osv): if prodlot_id: prodlot_clause = ' and prodlot_id = %s ' where += [prodlot_id] + elif 'prodlot_id' in context and not prodlot_id: + prodlot_clause = ' and prodlot_id is null ' # TODO: perhaps merge in one query. if 'in' in what: diff --git a/addons/stock/test/opening_stock.yml b/addons/stock/test/opening_stock.yml index 9efcfd3af99..5dfb5c4b9fa 100644 --- a/addons/stock/test/opening_stock.yml +++ b/addons/stock/test/opening_stock.yml @@ -37,6 +37,36 @@ !python {model: product.product}: | product = self.browse(cr, uid, ref('product_product_6'), context=context) assert product.qty_available == 10, "Stock is not updated." +- + I update the current stock of the Ice-cream with 10 kgm without Production Lot. +- + !record {model: stock.change.product.qty, id: change_qty_nolot}: + location_id: location_monitor_small + new_quantity: 10 + product_id: product_product_6 +- + !python {model: stock.change.product.qty}: | + self.change_product_qty(cr, uid, [ref('change_qty_nolot')], context=dict(context, active_id=ref('product_product_6'))) +- + I check available stock of Ice-cream after update stock. +- + !python {model: product.product}: | + product = self.browse(cr, uid, ref('product_product_6'), context=context) + assert product.qty_available == 20, "Real stock is not updated." +- + I revert 10kgm updated stock again with no production lot in order to level the stock +- + !record {model: stock.change.product.qty, id: change_qty_nolot_1}: + location_id: location_monitor_small + new_quantity: 0 + product_id: product_product_6 +- + !python {model: stock.change.product.qty}: | + self.change_product_qty(cr, uid, [ref('change_qty_nolot_1')], context=dict(context, active_id=ref('product_product_6'))) +- + !python {model: product.product}: | + product = self.browse(cr, uid, ref('product_product_6'), context=context) + assert product.qty_available == 10, "Real stock is not updated." - Stock user can merge inventory, so let's check data with giving the access rights of user. - diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 7ac552ffb85..4ee3f5f25ae 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -860,7 +860,8 @@ class Proxy(http.Controller): from werkzeug.test import Client from werkzeug.wrappers import BaseResponse - return Client(request.httprequest.app, BaseResponse).get(path).data + base_url = request.httprequest.base_url + return Client(request.httprequest.app, BaseResponse).get(path, base_url=base_url).data class Database(http.Controller): diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index a11f0a4e771..6c9379f958d 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2810,7 +2810,7 @@ instance.web.form.FieldTextHtml = instance.web.form.AbstractField.extend(instanc if (! this.get("effective_readonly")) { self._updating_editor = false; this.$textarea = this.$el.find('textarea'); - var width = ((this.node.attrs || {}).editor_width || '100%'); + var width = ((this.node.attrs || {}).editor_width || 'auto'); var height = ((this.node.attrs || {}).editor_height || 250); this.$textarea.cleditor({ width: width, // width not including margins, borders or padding diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 144de8eb21c..4bff19baf30 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -258,7 +258,7 @@ if (!focus_field){ focus_field = _.find(self.editor.form.fields_order, function(field){ return fields[field] && fields[field].$el.is(':visible:has(input)'); }); } - if (focus_field) fields[focus_field].$el.find('input').select(); + if (focus_field && fields[focus_field]) fields[focus_field].$el.find('input').select(); return record.attributes; }); }).fail(function () { diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 864353ab891..238058c0ce9 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1266,16 +1266,18 @@ -
- - - Edit - - + diff --git a/addons/web_calendar/static/src/js/web_calendar.js b/addons/web_calendar/static/src/js/web_calendar.js index 3b7f41999e2..8728b22f746 100644 --- a/addons/web_calendar/static/src/js/web_calendar.js +++ b/addons/web_calendar/static/src/js/web_calendar.js @@ -1091,6 +1091,7 @@ openerp.web_calendar = function(instance) { var self = this; var def = $.Deferred(); var defaults = {}; + var created = false; _.each($.extend({}, this.data_template, data), function(val, field_name) { defaults['default_' + field_name] = val; @@ -1130,9 +1131,14 @@ openerp.web_calendar = function(instance) { } }); pop.on('create_completed', self, function(id) { - self.trigger('slowadded'); + created = true; + self.trigger('slowadded'); }); def.then(function() { + if (created) { + var parent = self.getParent(); + parent.$calendar.fullCalendar('refetchEvents'); + } self.trigger('close'); }); return def; diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml index d6eba17d0f4..0b7f540f4ac 100644 --- a/openerp/addons/base/res/res_partner_view.xml +++ b/openerp/addons/base/res/res_partner_view.xml @@ -183,7 +183,7 @@ - + diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index f10703e3679..946f9c288d5 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -1264,9 +1264,9 @@ class function(_column): # if we already have a value, don't recompute it. # This happen if case of stored many2one fields if values and not multi and name in values[0]: - result = {v['id']: v[name] for v in values} + result = dict((v['id'], v[name]) for v in values) elif values and multi and all(n in values[0] for n in name): - result = {v['id']: dict((n, v[n]) for n in name) for v in values} + result = dict((v['id'], dict((n, v[n]) for n in name)) for v in values) else: result = self._fnct(obj, cr, uid, ids, name, self._arg, context) if multi: