[MERGE] forward port branch 9.0 up to b795755
This commit is contained in:
@@ -352,7 +352,7 @@ class AccountBankStatement(models.Model):
|
|||||||
class AccountBankStatementLine(models.Model):
|
class AccountBankStatementLine(models.Model):
|
||||||
_name = "account.bank.statement.line"
|
_name = "account.bank.statement.line"
|
||||||
_description = "Bank Statement Line"
|
_description = "Bank Statement Line"
|
||||||
_order = "statement_id desc, sequence"
|
_order = "statement_id desc, sequence, id desc"
|
||||||
_inherit = ['ir.needaction_mixin']
|
_inherit = ['ir.needaction_mixin']
|
||||||
|
|
||||||
name = fields.Char(string='Memo', required=True)
|
name = fields.Char(string='Memo', required=True)
|
||||||
@@ -956,8 +956,23 @@ class AccountBankStatementLine(models.Model):
|
|||||||
aml_dict['currency_id'] = statement_currency.id
|
aml_dict['currency_id'] = statement_currency.id
|
||||||
|
|
||||||
# Create write-offs
|
# Create write-offs
|
||||||
|
# When we register a payment on an invoice, the write-off line contains the amount
|
||||||
|
# currency if all related invoices have the same currency. We apply the same logic in
|
||||||
|
# the manual reconciliation.
|
||||||
|
counterpart_aml = self.env['account.move.line']
|
||||||
|
for aml_dict in counterpart_aml_dicts:
|
||||||
|
counterpart_aml |= aml_dict.get('move_line', self.env['account.move.line'])
|
||||||
|
new_aml_currency = False
|
||||||
|
if counterpart_aml\
|
||||||
|
and len(counterpart_aml.mapped('currency_id')) == 1\
|
||||||
|
and counterpart_aml[0].currency_id\
|
||||||
|
and counterpart_aml[0].currency_id != company_currency:
|
||||||
|
new_aml_currency = counterpart_aml[0].currency_id
|
||||||
for aml_dict in new_aml_dicts:
|
for aml_dict in new_aml_dicts:
|
||||||
aml_dict['payment_id'] = payment_id
|
aml_dict['payment_id'] = payment_id
|
||||||
|
if new_aml_currency and not aml_dict.get('currency_id'):
|
||||||
|
aml_dict['currency_id'] = new_aml_currency.id
|
||||||
|
aml_dict['amount_currency'] = company_currency.with_context(ctx).compute(aml_dict['debit'] - aml_dict['credit'], new_aml_currency)
|
||||||
aml_obj.with_context(check_move_validity=False).create(aml_dict)
|
aml_obj.with_context(check_move_validity=False).create(aml_dict)
|
||||||
|
|
||||||
# Create counterpart move lines and reconcile them
|
# Create counterpart move lines and reconcile them
|
||||||
|
|||||||
@@ -918,6 +918,8 @@ class AccountMoveLine(models.Model):
|
|||||||
first_line_dict['account_id'] = self[0].account_id.id
|
first_line_dict['account_id'] = self[0].account_id.id
|
||||||
if 'analytic_account_id' in first_line_dict:
|
if 'analytic_account_id' in first_line_dict:
|
||||||
del first_line_dict['analytic_account_id']
|
del first_line_dict['analytic_account_id']
|
||||||
|
if 'tax_ids' in first_line_dict:
|
||||||
|
del first_line_dict['tax_ids']
|
||||||
|
|
||||||
# Writeoff line in specified writeoff account
|
# Writeoff line in specified writeoff account
|
||||||
second_line_dict = vals.copy()
|
second_line_dict = vals.copy()
|
||||||
@@ -1244,7 +1246,7 @@ class AccountMoveLine(models.Model):
|
|||||||
""" Prepare the values used to create() an account.analytic.line upon validation of an account.move.line having
|
""" Prepare the values used to create() an account.analytic.line upon validation of an account.move.line having
|
||||||
an analytic account. This method is intended to be extended in other modules.
|
an analytic account. This method is intended to be extended in other modules.
|
||||||
"""
|
"""
|
||||||
amount = (self.credit or 0.0) - (self.debit or 0.0)
|
amount = (self.debit or 0.0) - (self.credit or 0.0)
|
||||||
return {
|
return {
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
'date': self.date,
|
'date': self.date,
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ class TestReconciliation(AccountingTestCase):
|
|||||||
self.check_results(bank_stmt.move_line_ids, {
|
self.check_results(bank_stmt.move_line_ids, {
|
||||||
self.account_euro.id: {'debit': 40.0, 'credit': 0.0, 'amount_currency': 0, 'currency_id': False},
|
self.account_euro.id: {'debit': 40.0, 'credit': 0.0, 'amount_currency': 0, 'currency_id': False},
|
||||||
self.account_rcv.id: {'debit': 0.0, 'credit': 32.7, 'amount_currency': -41.97, 'currency_id': self.currency_usd_id, 'currency_diff': 0, 'amount_currency_diff': -8.03},
|
self.account_rcv.id: {'debit': 0.0, 'credit': 32.7, 'amount_currency': -41.97, 'currency_id': self.currency_usd_id, 'currency_diff': 0, 'amount_currency_diff': -8.03},
|
||||||
self.diff_income_account.id: {'debit': 0.0, 'credit': 7.3, 'amount_currency': 0, 'currency_id': False},
|
self.diff_income_account.id: {'debit': 0.0, 'credit': 7.3, 'amount_currency': -9.37, 'currency_id': self.currency_usd_id},
|
||||||
})
|
})
|
||||||
|
|
||||||
# The invoice should be paid, as the payments totally cover its total
|
# The invoice should be paid, as the payments totally cover its total
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import calendar
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
from openerp import api, fields, models, _
|
from openerp import api, fields, models, _
|
||||||
from openerp.exceptions import UserError, ValidationError
|
from openerp.exceptions import UserError, ValidationError
|
||||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
|
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
|
||||||
from openerp.tools import float_compare
|
from openerp.tools import float_compare, float_is_zero
|
||||||
|
|
||||||
|
|
||||||
class AccountAssetCategory(models.Model):
|
class AccountAssetCategory(models.Model):
|
||||||
@@ -150,14 +151,26 @@ class AccountAssetAsset(models.Model):
|
|||||||
if self.prorata:
|
if self.prorata:
|
||||||
amount = amount_to_depr / self.method_number
|
amount = amount_to_depr / self.method_number
|
||||||
if sequence == 1:
|
if sequence == 1:
|
||||||
days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1
|
if self.method_period % 12 != 0:
|
||||||
amount = (amount_to_depr / self.method_number) / total_days * days
|
date = datetime.strptime(self.date, '%Y-%m-%d')
|
||||||
|
month_days = calendar.monthrange(date.year, date.month)[1]
|
||||||
|
days = month_days - date.day + 1
|
||||||
|
amount = (amount_to_depr / self.method_number) / month_days * days
|
||||||
|
else:
|
||||||
|
days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1
|
||||||
|
amount = (amount_to_depr / self.method_number) / total_days * days
|
||||||
elif self.method == 'degressive':
|
elif self.method == 'degressive':
|
||||||
amount = residual_amount * self.method_progress_factor
|
amount = residual_amount * self.method_progress_factor
|
||||||
if self.prorata:
|
if self.prorata:
|
||||||
if sequence == 1:
|
if sequence == 1:
|
||||||
days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1
|
if self.method_period % 12 != 0:
|
||||||
amount = (residual_amount * self.method_progress_factor) / total_days * days
|
date = datetime.strptime(self.date, '%Y-%m-%d')
|
||||||
|
month_days = calendar.monthrange(date.year, date.month)[1]
|
||||||
|
days = month_days - date.day + 1
|
||||||
|
amount = (residual_amount * self.method_progress_factor) / month_days * days
|
||||||
|
else:
|
||||||
|
days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1
|
||||||
|
amount = (residual_amount * self.method_progress_factor) / total_days * days
|
||||||
return amount
|
return amount
|
||||||
|
|
||||||
def _compute_board_undone_dotation_nb(self, depreciation_date, total_days):
|
def _compute_board_undone_dotation_nb(self, depreciation_date, total_days):
|
||||||
@@ -210,6 +223,8 @@ class AccountAssetAsset(models.Model):
|
|||||||
sequence = x + 1
|
sequence = x + 1
|
||||||
amount = self._compute_board_amount(sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date)
|
amount = self._compute_board_amount(sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date)
|
||||||
amount = self.currency_id.round(amount)
|
amount = self.currency_id.round(amount)
|
||||||
|
if float_is_zero(amount, precision_rounding=self.currency_id.rounding):
|
||||||
|
continue
|
||||||
residual_amount -= amount
|
residual_amount -= amount
|
||||||
vals = {
|
vals = {
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
@@ -407,7 +422,7 @@ class AccountAssetAsset(models.Model):
|
|||||||
'res_model': 'account.move',
|
'res_model': 'account.move',
|
||||||
'view_id': False,
|
'view_id': False,
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'domain': [('id', 'in', move_ids)]
|
'domain': [('id', 'in', move_ids)],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class TestAccountAsset(common.TransactionCase):
|
|||||||
asset_modify_number_0.with_context({'active_id': account_asset_asset_office0.id}).modify()
|
asset_modify_number_0.with_context({'active_id': account_asset_asset_office0.id}).modify()
|
||||||
|
|
||||||
# I check the proper depreciation lines created.
|
# I check the proper depreciation lines created.
|
||||||
self.assertEqual(account_asset_asset_office0.method_number, len(account_asset_asset_office0.depreciation_line_ids) - 1)
|
self.assertEqual(account_asset_asset_office0.method_number, len(account_asset_asset_office0.depreciation_line_ids))
|
||||||
# I compute a asset on period.
|
# I compute a asset on period.
|
||||||
context = {
|
context = {
|
||||||
"active_ids": [self.ref("account_asset.menu_asset_depreciation_confirmation_wizard")],
|
"active_ids": [self.ref("account_asset.menu_asset_depreciation_confirmation_wizard")],
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ bus.Bus = Widget.extend({
|
|||||||
this._super();
|
this._super();
|
||||||
this.options = {};
|
this.options = {};
|
||||||
this.activated = false;
|
this.activated = false;
|
||||||
|
this.bus_id = _.uniqueId('bus');
|
||||||
this.channels = [];
|
this.channels = [];
|
||||||
this.last = 0;
|
this.last = 0;
|
||||||
this.stop = false;
|
this.stop = false;
|
||||||
@@ -32,15 +33,24 @@ bus.Bus = Widget.extend({
|
|||||||
this.trigger('window_focus', this.is_master);
|
this.trigger('window_focus', this.is_master);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$(window).on("focus", _.bind(this.focus_change, this, true));
|
$(window).on("focus." + this.bus_id, _.bind(this.focus_change, this, true));
|
||||||
$(window).on("blur", _.bind(this.focus_change, this, false));
|
$(window).on("blur." + this.bus_id, _.bind(this.focus_change, this, false));
|
||||||
$(window).on("unload", _.bind(this.focus_change, this, false));
|
$(window).on("unload." + this.bus_id, _.bind(this.focus_change, this, false));
|
||||||
_.each('click,keydown,keyup'.split(','), function(evtype) {
|
_.each('click,keydown,keyup'.split(','), function(evtype) {
|
||||||
$(window).on(evtype, function() {
|
$(window).on(evtype + "." + self.bus_id, function() {
|
||||||
self.last_presence = new Date().getTime();
|
self.last_presence = new Date().getTime();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
destroy: function () {
|
||||||
|
var self = this;
|
||||||
|
$(window).off("focus." + this.bus_id);
|
||||||
|
$(window).off("blur." + this.bus_id);
|
||||||
|
$(window).off("unload." + this.bus_id);
|
||||||
|
_.each('click,keydown,keyup'.split(','), function(evtype) {
|
||||||
|
$(window).off(evtype + "." + self.bus_id);
|
||||||
|
});
|
||||||
|
},
|
||||||
start_polling: function(){
|
start_polling: function(){
|
||||||
if(!this.activated){
|
if(!this.activated){
|
||||||
this.poll();
|
this.poll();
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class StockPicking(models.Model):
|
|||||||
def _compute_shipping_weight(self):
|
def _compute_shipping_weight(self):
|
||||||
self.shipping_weight = self.weight_bulk + sum([pack.shipping_weight for pack in self.package_ids])
|
self.shipping_weight = self.weight_bulk + sum([pack.shipping_weight for pack in self.package_ids])
|
||||||
|
|
||||||
carrier_price = fields.Float(string="Shipping Cost", readonly=True)
|
carrier_price = fields.Float(string="Shipping Cost")
|
||||||
delivery_type = fields.Selection(related='carrier_id.delivery_type', readonly=True)
|
delivery_type = fields.Selection(related='carrier_id.delivery_type', readonly=True)
|
||||||
carrier_id = fields.Many2one("delivery.carrier", string="Carrier")
|
carrier_id = fields.Many2one("delivery.carrier", string="Carrier")
|
||||||
volume = fields.Float(copy=False)
|
volume = fields.Float(copy=False)
|
||||||
@@ -91,6 +91,11 @@ class StockPicking(models.Model):
|
|||||||
weight_bulk = fields.Float('Bulk Weight', compute='_compute_bulk_weight')
|
weight_bulk = fields.Float('Bulk Weight', compute='_compute_bulk_weight')
|
||||||
shipping_weight = fields.Float("Weight for Shipping", compute='_compute_shipping_weight')
|
shipping_weight = fields.Float("Weight for Shipping", compute='_compute_shipping_weight')
|
||||||
|
|
||||||
|
@api.onchange('carrier_id')
|
||||||
|
def onchange_carrier(self):
|
||||||
|
if self.carrier_id.delivery_type in ['fixed', 'base_on_rule']:
|
||||||
|
self.carrier_price = self.carrier_id.price
|
||||||
|
|
||||||
@api.depends('product_id', 'move_lines')
|
@api.depends('product_id', 'move_lines')
|
||||||
def _cal_weight(self):
|
def _cal_weight(self):
|
||||||
for picking in self:
|
for picking in self:
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ var OdooSupport = Widget.extend({
|
|||||||
// bind event
|
// bind event
|
||||||
$(window).on("odoo_support_ready_to_bind", this, _.bind(this.bind_actions, this));
|
$(window).on("odoo_support_ready_to_bind", this, _.bind(this.bind_actions, this));
|
||||||
},
|
},
|
||||||
|
destroy: function () {
|
||||||
|
$(window).off("odoo_support_ready_to_bind");
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
bind_actions: function(event, button){
|
bind_actions: function(event, button){
|
||||||
if (button === 'usermenu'){
|
if (button === 'usermenu'){
|
||||||
$('.oe_user_menu_placeholder .odoo_support_contact').on('click', this, _.bind(this.click_action, this));
|
$('.oe_user_menu_placeholder .odoo_support_contact').on('click', this, _.bind(this.click_action, this));
|
||||||
|
|||||||
@@ -661,6 +661,10 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
|
|||||||
target: 'current'
|
target: 'current'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
destroy: function() {
|
||||||
|
this.$buttons.off().destroy();
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -461,6 +461,11 @@ var BasicComposer = Widget.extend({
|
|||||||
return this._super();
|
return this._super();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
destroy: function () {
|
||||||
|
$(window).off(this.fileupload_id);
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
toggle: function(state) {
|
toggle: function(state) {
|
||||||
this.$el.toggle(state);
|
this.$el.toggle(state);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ class PosOrder(models.Model):
|
|||||||
if move is None:
|
if move is None:
|
||||||
# Create an entry for the sale
|
# Create an entry for the sale
|
||||||
journal_id = self.env['ir.config_parameter'].sudo().get_param(
|
journal_id = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
'pos.closing.journal_id', default=order.sale_journal.id)
|
'pos.closing.journal_id_%s' % current_company.id, default=order.sale_journal.id)
|
||||||
move = self._create_account_move(
|
move = self._create_account_move(
|
||||||
order.session_id.start_at, order.name, int(journal_id), order.company_id.id)
|
order.session_id.start_at, order.name, int(journal_id), order.company_id.id)
|
||||||
|
|
||||||
@@ -598,7 +598,7 @@ class PosOrder(models.Model):
|
|||||||
if moves and not return_picking and not order_picking:
|
if moves and not return_picking and not order_picking:
|
||||||
moves.action_confirm()
|
moves.action_confirm()
|
||||||
moves.force_assign()
|
moves.force_assign()
|
||||||
moves.action_done()
|
moves.filtered(lambda m: m.product_id.tracking == 'none').action_done()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -608,9 +608,10 @@ class PosOrder(models.Model):
|
|||||||
picking.action_confirm()
|
picking.action_confirm()
|
||||||
picking.force_assign()
|
picking.force_assign()
|
||||||
# Mark pack operations as done
|
# Mark pack operations as done
|
||||||
for pack in picking.pack_operation_ids:
|
for pack in picking.pack_operation_ids.filtered(lambda x: x.product_id.tracking == 'none'):
|
||||||
pack.write({'qty_done': pack.product_qty})
|
pack.write({'qty_done': pack.product_qty})
|
||||||
picking.action_done()
|
if not any([(x.product_id.tracking != 'none') for x in picking.pack_operation_ids]):
|
||||||
|
picking.action_done()
|
||||||
|
|
||||||
def add_payment(self, data):
|
def add_payment(self, data):
|
||||||
"""Create a new payment for the order"""
|
"""Create a new payment for the order"""
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class PosSession(models.Model):
|
|||||||
company_id = session.config_id.journal_id.company_id.id
|
company_id = session.config_id.journal_id.company_id.id
|
||||||
orders = session.order_ids.filtered(lambda order: order.state == 'paid')
|
orders = session.order_ids.filtered(lambda order: order.state == 'paid')
|
||||||
journal_id = self.env['ir.config_parameter'].sudo().get_param(
|
journal_id = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
'pos.closing.journal_id', default=session.config_id.journal_id.id)
|
'pos.closing.journal_id_%s' % company_id, default=session.config_id.journal_id.id)
|
||||||
move = self.env['pos.order'].with_context(force_company=company_id)._create_account_move(session.start_at, session.name, int(journal_id), company_id)
|
move = self.env['pos.order'].with_context(force_company=company_id)._create_account_move(session.start_at, session.name, int(journal_id), company_id)
|
||||||
orders.with_context(force_company=company_id)._create_account_move_line(session, move)
|
orders.with_context(force_company=company_id)._create_account_move_line(session, move)
|
||||||
for order in session.order_ids.filtered(lambda o: o.state != 'done'):
|
for order in session.order_ids.filtered(lambda o: o.state != 'done'):
|
||||||
|
|||||||
@@ -1821,11 +1821,9 @@ var PaymentScreenWidget = ScreenWidget.extend({
|
|||||||
self.$('.next').removeClass('highlight');
|
self.$('.next').removeClass('highlight');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Check if the order is paid, then sends it to the backend,
|
|
||||||
// and complete the sale process
|
|
||||||
validate_order: function(force_validation) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
|
order_is_valid: function(force_validation) {
|
||||||
|
var self = this;
|
||||||
var order = this.pos.get_order();
|
var order = this.pos.get_order();
|
||||||
|
|
||||||
// FIXME: this check is there because the backend is unable to
|
// FIXME: this check is there because the backend is unable to
|
||||||
@@ -1835,7 +1833,7 @@ var PaymentScreenWidget = ScreenWidget.extend({
|
|||||||
'title': _t('Empty Order'),
|
'title': _t('Empty Order'),
|
||||||
'body': _t('There must be at least one product in your order before it can be validated'),
|
'body': _t('There must be at least one product in your order before it can be validated'),
|
||||||
});
|
});
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var plines = order.get_paymentlines();
|
var plines = order.get_paymentlines();
|
||||||
@@ -1845,12 +1843,12 @@ var PaymentScreenWidget = ScreenWidget.extend({
|
|||||||
'message': _t('Negative Bank Payment'),
|
'message': _t('Negative Bank Payment'),
|
||||||
'comment': _t('You cannot have a negative amount in a Bank payment. Use a cash payment method to return money to the customer.'),
|
'comment': _t('You cannot have a negative amount in a Bank payment. Use a cash payment method to return money to the customer.'),
|
||||||
});
|
});
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!order.is_paid() || this.invoicing) {
|
if (!order.is_paid() || this.invoicing) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The exact amount must be paid if there is no cash payment method defined.
|
// The exact amount must be paid if there is no cash payment method defined.
|
||||||
@@ -1864,7 +1862,7 @@ var PaymentScreenWidget = ScreenWidget.extend({
|
|||||||
title: _t('Cannot return change without a cash payment method'),
|
title: _t('Cannot return change without a cash payment method'),
|
||||||
body: _t('There is no cash payment method available in this point of sale to handle the change.\n\n Please pay the exact amount or add a cash payment method in the point of sale configuration'),
|
body: _t('There is no cash payment method available in this point of sale to handle the change.\n\n Please pay the exact amount or add a cash payment method in the point of sale configuration'),
|
||||||
});
|
});
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1885,9 +1883,16 @@ var PaymentScreenWidget = ScreenWidget.extend({
|
|||||||
self.validate_order('confirm');
|
self.validate_order('confirm');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
finalize_validation: function() {
|
||||||
|
var self = this;
|
||||||
|
var order = this.pos.get_order();
|
||||||
|
|
||||||
if (order.is_paid_with_cash() && this.pos.config.iface_cashdrawer) {
|
if (order.is_paid_with_cash() && this.pos.config.iface_cashdrawer) {
|
||||||
|
|
||||||
this.pos.proxy.open_cashbox();
|
this.pos.proxy.open_cashbox();
|
||||||
@@ -1937,6 +1942,14 @@ var PaymentScreenWidget = ScreenWidget.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Check if the order is paid, then sends it to the backend,
|
||||||
|
// and complete the sale process
|
||||||
|
validate_order: function(force_validation) {
|
||||||
|
if (this.order_is_valid(force_validation)) {
|
||||||
|
this.finalize_validation();
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
gui.define_screen({name:'payment', widget: PaymentScreenWidget});
|
gui.define_screen({name:'payment', widget: PaymentScreenWidget});
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
</group>
|
</group>
|
||||||
<group name="group_standard_price">
|
<group name="group_standard_price">
|
||||||
<field name="list_price" widget='monetary' options="{'currency_field': 'currency_id'}"/>
|
<field name="list_price" widget='monetary' options="{'currency_field': 'currency_id'}"/>
|
||||||
<label for="standard_price" groups="base.group_user" attrs="{'invisible': [('product_variant_count', '>', 1)]}"/>
|
<label for="standard_price" groups="base.group_user"/>
|
||||||
<div name="standard_price_uom" groups="base.group_user">
|
<div name="standard_price_uom" groups="base.group_user">
|
||||||
<field name="standard_price" widget='monetary' options="{'currency_field': 'currency_id'}" class="oe_inline"/>
|
<field name="standard_price" widget='monetary' options="{'currency_field': 'currency_id'}" class="oe_inline"/>
|
||||||
</div>
|
</div>
|
||||||
@@ -126,12 +126,12 @@
|
|||||||
<field name="categ_id" string="Internal Category"/>
|
<field name="categ_id" string="Internal Category"/>
|
||||||
</group>
|
</group>
|
||||||
<group name="group_lots_and_weight">
|
<group name="group_lots_and_weight">
|
||||||
<label for="weight" attrs="{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}"/>
|
<label for="weight" attrs="{'invisible':[('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}"/>
|
||||||
<div class="o_row" name="weight" attrs="{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}">
|
<div class="o_row" name="weight" attrs="{'invisible':[('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}">
|
||||||
<field name="weight"/>
|
<field name="weight"/>
|
||||||
</div>
|
</div>
|
||||||
<label for="volume" attrs="{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}"/>
|
<label for="volume" attrs="{'invisible':[('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}"/>
|
||||||
<div class="o_row" name="volume" attrs="{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}">
|
<div class="o_row" name="volume" attrs="{'invisible':[('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}">
|
||||||
<field name="volume" string="Volume"/>
|
<field name="volume" string="Volume"/>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
@@ -155,7 +155,6 @@
|
|||||||
<t t-name="kanban-tooltip">
|
<t t-name="kanban-tooltip">
|
||||||
<ul class="oe_kanban_tooltip">
|
<ul class="oe_kanban_tooltip">
|
||||||
<li><b>Project:</b> <field name="project_id"/></li>
|
<li><b>Project:</b> <field name="project_id"/></li>
|
||||||
<li><b>Category:</b> <field name="tag_ids"/></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</t>
|
</t>
|
||||||
<t t-name="kanban-box">
|
<t t-name="kanban-box">
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
<field name="name">report.intrastat.tree</field>
|
<field name="name">report.intrastat.tree</field>
|
||||||
<field name="model">report.intrastat</field>
|
<field name="model">report.intrastat</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Intrastat Data" create="false">
|
<tree string="Intrastat Data" create="false" delete="false">
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="month"/>
|
<field name="month"/>
|
||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
|
|||||||
+3
-2
@@ -812,13 +812,14 @@ class SaleOrderLine(models.Model):
|
|||||||
|
|
||||||
vals = {}
|
vals = {}
|
||||||
domain = {'product_uom': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
|
domain = {'product_uom': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
|
||||||
if not self.product_uom or (self.product_id.uom_id.category_id.id != self.product_uom.category_id.id):
|
if not self.product_uom or (self.product_id.uom_id.id != self.product_uom.id):
|
||||||
vals['product_uom'] = self.product_id.uom_id
|
vals['product_uom'] = self.product_id.uom_id
|
||||||
|
vals['product_uom_qty'] = 1.0
|
||||||
|
|
||||||
product = self.product_id.with_context(
|
product = self.product_id.with_context(
|
||||||
lang=self.order_id.partner_id.lang,
|
lang=self.order_id.partner_id.lang,
|
||||||
partner=self.order_id.partner_id.id,
|
partner=self.order_id.partner_id.id,
|
||||||
quantity=self.product_uom_qty,
|
quantity=vals.get('product_uom_qty') or self.product_uom_qty,
|
||||||
date=self.order_id.date_order,
|
date=self.order_id.date_order,
|
||||||
pricelist=self.order_id.pricelist_id.id,
|
pricelist=self.order_id.pricelist_id.id,
|
||||||
uom=self.product_uom.id
|
uom=self.product_uom.id
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
</field>
|
</field>
|
||||||
<field name="standard_price" position="replace">
|
<field name="standard_price" position="replace">
|
||||||
<field name="standard_price"
|
<field name="standard_price"
|
||||||
attrs="{'readonly':['&', ('valuation','=','real_time'), ('cost_method', 'in', ['standard', 'average'])], 'invisible': [('product_variant_count', '>', 1)]}" class="oe_inline"
|
attrs="{'readonly':['&', ('valuation','=','real_time'), ('cost_method', 'in', ['standard', 'average'])]}" class="oe_inline"
|
||||||
widget='monetary' options="{'currency_field': 'currency_id'}"/>
|
widget='monetary' options="{'currency_field': 'currency_id'}"/>
|
||||||
</field>
|
</field>
|
||||||
<div name="standard_price_uom" position="after">
|
<div name="standard_price_uom" position="after">
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
import models # noqa
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
||||||
|
|
||||||
import stock_dropshipping # noqa
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# coding: utf-8
|
|
||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
||||||
|
|
||||||
from openerp import models, api
|
|
||||||
|
|
||||||
class AccountInvoice(models.Model):
|
|
||||||
_inherit = 'account.invoice'
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _anglo_saxon_sale_move_lines(self, i_line):
|
|
||||||
for sale_line in i_line.sale_line_ids:
|
|
||||||
for proc in sale_line.procurement_ids:
|
|
||||||
if proc.purchase_line_id:
|
|
||||||
# if the invoice line is related to sale order lines having one of its
|
|
||||||
# procurement_ids with a purchase_line_id set, it means that it is a
|
|
||||||
# confirmed dropship and in that case we mustn't create the cost of
|
|
||||||
# sale line (because the product won't enter the stock)
|
|
||||||
return []
|
|
||||||
return super(AccountInvoice, self)._anglo_saxon_sale_move_lines(i_line)
|
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
if (odoo.debug && !_.isEmpty(debug_jobs)) log.push('\nDebug: ', debug_jobs);
|
if (odoo.debug && !_.isEmpty(debug_jobs)) log.push('\nDebug: ', debug_jobs);
|
||||||
|
|
||||||
if (odoo.debug || !_.isEmpty(failed) || !_.isEmpty(unloaded)) {
|
if (odoo.debug || !_.isEmpty(failed) || !_.isEmpty(unloaded)) {
|
||||||
console[_.isEmpty(unloaded) ? 'info' : 'error'].apply(console, log);
|
console[_.isEmpty(failed) || _.isEmpty(unloaded) ? 'info' : 'error'].apply(console, log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -76,6 +76,10 @@ var ControlPanel = Widget.extend({
|
|||||||
|
|
||||||
return this._super();
|
return this._super();
|
||||||
},
|
},
|
||||||
|
destroy: function() {
|
||||||
|
this._clear_breadcrumbs_handlers();
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* @return {Object} the Bus the ControlPanel is listening on
|
* @return {Object} the Bus the ControlPanel is listening on
|
||||||
*/
|
*/
|
||||||
@@ -108,7 +112,9 @@ var ControlPanel = Widget.extend({
|
|||||||
|
|
||||||
// Render the breadcrumbs
|
// Render the breadcrumbs
|
||||||
if (status.breadcrumbs) {
|
if (status.breadcrumbs) {
|
||||||
new_cp_content.$breadcrumbs = this._render_breadcrumbs(status.breadcrumbs);
|
this._clear_breadcrumbs_handlers();
|
||||||
|
this.$breadcrumbs = this._render_breadcrumbs(status.breadcrumbs);
|
||||||
|
new_cp_content.$breadcrumbs = this.$breadcrumbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detach control_panel old content and attach new elements
|
// Detach control_panel old content and attach new elements
|
||||||
@@ -207,6 +213,17 @@ var ControlPanel = Widget.extend({
|
|||||||
}
|
}
|
||||||
return $bc;
|
return $bc;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Private function that removes event handlers attached on the currently
|
||||||
|
* displayed breadcrumbs.
|
||||||
|
*/
|
||||||
|
_clear_breadcrumbs_handlers: function () {
|
||||||
|
if (this.$breadcrumbs) {
|
||||||
|
_.each(this.$breadcrumbs, function ($bc) {
|
||||||
|
$bc.off();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Private function that updates the SearchView's visibility and extend the
|
* Private function that updates the SearchView's visibility and extend the
|
||||||
* breadcrumbs area if the SearchView is not visible
|
* breadcrumbs area if the SearchView is not visible
|
||||||
|
|||||||
@@ -196,6 +196,12 @@ var View = Widget.extend({
|
|||||||
get_context: function () {
|
get_context: function () {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
destroy: function () {
|
||||||
|
if (this.$buttons) {
|
||||||
|
this.$buttons.off();
|
||||||
|
}
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
set_scrollTop: function(scrollTop) {
|
set_scrollTop: function(scrollTop) {
|
||||||
this.scrollTop = scrollTop;
|
this.scrollTop = scrollTop;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -463,6 +463,14 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
|
|||||||
}
|
}
|
||||||
this.active_view.controller.do_load_state(state, warm);
|
this.active_view.controller.do_load_state(state, warm);
|
||||||
},
|
},
|
||||||
|
destroy: function () {
|
||||||
|
if (this.control_elements) {
|
||||||
|
if (this.control_elements.$switch_buttons) {
|
||||||
|
this.control_elements.$switch_buttons.off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return ViewManager;
|
return ViewManager;
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com
|
|||||||
delete this.$dropdown;
|
delete this.$dropdown;
|
||||||
}
|
}
|
||||||
if (this.$input) {
|
if (this.$input) {
|
||||||
|
if (this.$input.data('ui-autocomplete')) {
|
||||||
|
this.$input.autocomplete("destroy");
|
||||||
|
}
|
||||||
this.$input.closest(".modal .modal-content").off('scroll');
|
this.$input.closest(".modal .modal-content").off('scroll');
|
||||||
this.$input.off('keyup blur autocompleteclose autocompleteopen ' +
|
this.$input.off('keyup blur autocompleteclose autocompleteopen ' +
|
||||||
'focus focusout change keydown');
|
'focus focusout change keydown');
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ var FormView = View.extend(common.FieldManagerMixin, {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
start: function() {
|
start: function() {
|
||||||
|
if (this.$pager) {
|
||||||
|
this.$pager.off();
|
||||||
|
}
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.rendering_engine.set_fields_registry(this.fields_registry);
|
this.rendering_engine.set_fields_registry(this.fields_registry);
|
||||||
|
|||||||
@@ -129,6 +129,12 @@ var GraphView = View.extend({
|
|||||||
this.widget.set_measure(this.active_measure);
|
this.widget.set_measure(this.active_measure);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
destroy: function () {
|
||||||
|
if (this.$buttons) {
|
||||||
|
this.$buttons.find('button').off(); // remove jquery's tooltip() handlers
|
||||||
|
}
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
core.view_registry.add('graph', GraphView);
|
core.view_registry.add('graph', GraphView);
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ var ListView = View.extend({
|
|||||||
render_buttons: function($node) {
|
render_buttons: function($node) {
|
||||||
if (!this.$buttons) {
|
if (!this.$buttons) {
|
||||||
this.$buttons = $(QWeb.render("ListView.buttons", {'widget': this}));
|
this.$buttons = $(QWeb.render("ListView.buttons", {'widget': this}));
|
||||||
this.$buttons.find('.o_list_button_add').click(this.proxy('do_add_record'));
|
this.$buttons.on('click', '.o_list_button_add', this.proxy('do_add_record'));
|
||||||
this.$buttons.appendTo($node);
|
this.$buttons.appendTo($node);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -827,6 +827,12 @@ var PivotView = View.extend({
|
|||||||
error: crash_manager.rpc_error.bind(crash_manager)
|
error: crash_manager.rpc_error.bind(crash_manager)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
destroy: function () {
|
||||||
|
if (this.$buttons) {
|
||||||
|
this.$buttons.find('button').off(); // remove jquery's tooltip() handlers
|
||||||
|
}
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function traverse_tree(root, f, arg1, arg2, arg3) {
|
function traverse_tree(root, f, arg1, arg2, arg3) {
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ var Sidebar = Widget.extend({
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
destroy: function() {
|
||||||
|
$(window).off(this.fileupload_id);
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
redraw: function() {
|
redraw: function() {
|
||||||
this.$el.html(QWeb.render('Sidebar', {widget: this}));
|
this.$el.html(QWeb.render('Sidebar', {widget: this}));
|
||||||
|
|
||||||
|
|||||||
@@ -113,11 +113,16 @@ var FieldTextHtmlSimple = widget.extend({
|
|||||||
},
|
},
|
||||||
text_to_html: function (text) {
|
text_to_html: function (text) {
|
||||||
var value = text || "";
|
var value = text || "";
|
||||||
if (value.match(/^\s*$/)) {
|
try {
|
||||||
value = '<p><br/></p>';
|
$(text)[0].innerHTML;
|
||||||
} else {
|
return text;
|
||||||
value = "<p>"+value.split(/<br\/?>/).join("<br/></p><p>")+"</p>";
|
} catch (e) {
|
||||||
value = value.replace(/<p><\/p>/g, '').replace('<p><p>', '<p>').replace('<p><p ', '<p ').replace('</p></p>', '</p>');
|
if (value.match(/^\s*$/)) {
|
||||||
|
value = '<p><br/></p>';
|
||||||
|
} else {
|
||||||
|
value = "<p>"+value.split(/<br\/?>/).join("<br/></p><p>")+"</p>";
|
||||||
|
value = value.replace(/<p><\/p>/g, '').replace('<p><p>', '<p>').replace('<p><p ', '<p ').replace('</p></p>', '</p>');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
@@ -213,7 +218,7 @@ var FieldTextHtml = widget.extend({
|
|||||||
self.$iframe.css("height", (self.$body.find("#oe_snippets").length ? 500 : 300) + "px");
|
self.$iframe.css("height", (self.$body.find("#oe_snippets").length ? 500 : 300) + "px");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$(window).on('resize', self.resize);
|
$(window).on('resize', this.resize);
|
||||||
|
|
||||||
var def = this._super.apply(this, arguments);
|
var def = this._super.apply(this, arguments);
|
||||||
this.$translate.remove();
|
this.$translate.remove();
|
||||||
@@ -374,7 +379,7 @@ var FieldTextHtml = widget.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
$(window).off('resize', self.resize);
|
$(window).off('resize', this.resize);
|
||||||
delete window.odoo[this.callback+"_editor"];
|
delete window.odoo[this.callback+"_editor"];
|
||||||
delete window.odoo[this.callback+"_content"];
|
delete window.odoo[this.callback+"_content"];
|
||||||
delete window.odoo[this.callback+"_updown"];
|
delete window.odoo[this.callback+"_updown"];
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ var KanbanRecord = Widget.extend({
|
|||||||
qweb_context[p] = _.bind(this[p], this);
|
qweb_context[p] = _.bind(this[p], this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.qweb_context = qweb_context;
|
||||||
this.content = this.qweb.render('kanban-box', qweb_context);
|
this.content = this.qweb.render('kanban-box', qweb_context);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -81,7 +82,18 @@ var KanbanRecord = Widget.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
start: function() {
|
start: function() {
|
||||||
|
var self = this;
|
||||||
this.add_widgets();
|
this.add_widgets();
|
||||||
|
this.$('[tooltip]').each(function () {
|
||||||
|
var $el = $(this);
|
||||||
|
var tooltip = $el.attr('tooltip');
|
||||||
|
if (tooltip) {
|
||||||
|
$el.tooltip({
|
||||||
|
'html': true,
|
||||||
|
'title': self.qweb.render(tooltip, self.qweb_context)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
renderElement: function () {
|
renderElement: function () {
|
||||||
@@ -172,14 +184,15 @@ var KanbanRecord = Widget.extend({
|
|||||||
if (elem == ev.currentTarget) {
|
if (elem == ev.currentTarget) {
|
||||||
ischild = false;
|
ischild = false;
|
||||||
}
|
}
|
||||||
|
var test_event = events && events.click && (events.click.length > 1 || events.click[0].namespace !== "tooltip");
|
||||||
if (ischild) {
|
if (ischild) {
|
||||||
children.push(elem);
|
children.push(elem);
|
||||||
if (events && events.click) {
|
if (test_event) {
|
||||||
// do not trigger global click if one child has a click event registered
|
// do not trigger global click if one child has a click event registered
|
||||||
trigger = false;
|
trigger = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trigger && events && events.click) {
|
if (trigger && test_event) {
|
||||||
_.each(events.click, function(click_event) {
|
_.each(events.click, function(click_event) {
|
||||||
if (click_event.selector) {
|
if (click_event.selector) {
|
||||||
// For each parent of original target, check if a
|
// For each parent of original target, check if a
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ var Tips = Class.extend({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.tips = [];
|
this.tips = [];
|
||||||
|
this.tipObjects = {};
|
||||||
this.view = null;
|
this.view = null;
|
||||||
|
|
||||||
var Tips = new Model('web.tip');
|
var Tips = new Model('web.tip');
|
||||||
@@ -27,69 +28,47 @@ var Tips = Class.extend({
|
|||||||
bus.on('view_shown', this, function(view) {
|
bus.on('view_shown', this, function(view) {
|
||||||
if (_.keys(view.fields_view).length === 0) {
|
if (_.keys(view.fields_view).length === 0) {
|
||||||
view.on('view_loaded', this, function(fields_view) {
|
view.on('view_loaded', this, function(fields_view) {
|
||||||
self.view = view;
|
if (this.view && this._eval_tips) {
|
||||||
self.on_view();
|
this.view.off('chatter_messages_displayed', this, this._eval_tips);
|
||||||
|
this.view.off('to_edit_mode', this, this._remove_tips);
|
||||||
|
this.view.off('to_view_mode', this, this._eval_tips);
|
||||||
|
this.view.off('view_list_rendered', this, this._eval_tips);
|
||||||
|
}
|
||||||
|
this.view = view;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
self.view = view;
|
this.view = view;
|
||||||
self.on_view();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
on_view: function() {
|
bus.on('DOM_updated', this, function() {
|
||||||
var self = this;
|
if (!this.view) return;
|
||||||
|
|
||||||
if (this._DOM_updated) {
|
var self = this;
|
||||||
bus.off('DOM_updated', this, this._DOM_updated);
|
var action_id = this.view.ViewManager.action ? this.view.ViewManager.action.id : null;
|
||||||
}
|
var model = this.view.fields_view.model;
|
||||||
this._DOM_updated = function() {
|
var mode = this.view.fields_view.type;
|
||||||
var action_id = self.view.ViewManager.action ? self.view.ViewManager.action.id : null;
|
var type = this.view.datarecord ? this.view.datarecord.type : null;
|
||||||
var model = self.view.fields_view.model;
|
|
||||||
var mode = self.view.fields_view.type;
|
this._eval_tips = function() { self.eval_tips(action_id, model, mode, type); };
|
||||||
|
this._remove_tips = function() { self.remove_tips(); };
|
||||||
|
|
||||||
if (mode == 'form') {
|
if (mode == 'form') {
|
||||||
self.on_form_view(action_id, model);
|
if ($('.oe_chatter').length > 0) {
|
||||||
}
|
this.view.on('chatter_messages_displayed', this, this._eval_tips);
|
||||||
else if (self.view.hasOwnProperty('editor')) {
|
} else {
|
||||||
if (self._view_list_rendered) {
|
this._eval_tips();
|
||||||
self.view.off('view_list_rendered', self, self._view_list_rendered);
|
|
||||||
}
|
}
|
||||||
self._view_list_rendered = function() { self.eval_tips(action_id, model, mode); };
|
this.view.on('to_edit_mode', this, this._remove_tips);
|
||||||
self.view.on('view_list_rendered', self, self._view_list_rendered);
|
this.view.on('to_view_mode', this, this._eval_tips);
|
||||||
|
}
|
||||||
|
else if (this.view.hasOwnProperty('editor')) {
|
||||||
|
this.view.on('view_list_rendered', this, this._eval_tips);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.eval_tips(action_id, model, mode);
|
this._eval_tips();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
bus.on('DOM_updated', this, this._DOM_updated);
|
|
||||||
},
|
|
||||||
|
|
||||||
on_form_view: function(action_id, model) {
|
|
||||||
var self = this;
|
|
||||||
var type = this.view.datarecord ? this.view.datarecord.type : null
|
|
||||||
|
|
||||||
if ($('.oe_chatter').length > 0) {
|
|
||||||
if (this._chatter_messages_displayed) {
|
|
||||||
this.view.off('chatter_messages_displayed', this, this._chatter_messages_displayed);
|
|
||||||
}
|
|
||||||
this._chatter_messages_displayed = function() { self.eval_tips(action_id, model, 'form', type); };
|
|
||||||
this.view.on('chatter_messages_displayed', this, this._chatter_messages_displayed);
|
|
||||||
} else {
|
|
||||||
this.eval_tips(action_id, model, 'form', type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._to_edit_mode) {
|
|
||||||
this.view.off('to_edit_mode', this, this._to_edit_mode);
|
|
||||||
}
|
|
||||||
this._to_edit_mode = function() { self.remove_tips(); };
|
|
||||||
this.view.on('to_edit_mode', this, this._to_edit_mode);
|
|
||||||
|
|
||||||
if (this._to_view_mode) {
|
|
||||||
this.view.off('to_view_mode', this, this._to_view_mode);
|
|
||||||
}
|
|
||||||
this._to_view_mode = function() { self.eval_tips(action_id, model, 'form', type); };
|
|
||||||
this.view.on('to_view_mode', this, this._to_view_mode);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
eval_tips: function(action_id, model, mode, type) {
|
eval_tips: function(action_id, model, mode, type) {
|
||||||
@@ -109,7 +88,7 @@ var Tips = Class.extend({
|
|||||||
filter.is_consumed = false;
|
filter.is_consumed = false;
|
||||||
tips = _.where(self.tips, filter);
|
tips = _.where(self.tips, filter);
|
||||||
// To take into account a tip without fixed model : e.g. a generic tip on the breadcrumb
|
// To take into account a tip without fixed model : e.g. a generic tip on the breadcrumb
|
||||||
tips = tips.concat(_.where(self.tips, {mode: mode, is_consumed: false, model:false}))
|
tips = tips.concat(_.where(self.tips, {mode: mode, is_consumed: false, model:false}));
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
tips = _.filter(tips, function(tip) {
|
tips = _.filter(tips, function(tip) {
|
||||||
@@ -123,14 +102,21 @@ var Tips = Class.extend({
|
|||||||
valid_tips = _.uniq(valid_tips.concat(tips));
|
valid_tips = _.uniq(valid_tips.concat(tips));
|
||||||
_.each(valid_tips, function(tip) {
|
_.each(valid_tips, function(tip) {
|
||||||
if (!tip.is_consumed) {
|
if (!tip.is_consumed) {
|
||||||
var t = new Tip(tip);
|
if (self.tipObjects[tip.id]) {
|
||||||
t.do_tip();
|
self.tipObjects[tip.id].destroy();
|
||||||
|
} else {
|
||||||
|
self.tipObjects[tip.id] = new Tip(tip);
|
||||||
|
}
|
||||||
|
self.tipObjects[tip.id].do_tip();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
remove_tips: function() {
|
remove_tips: function() {
|
||||||
$('.oe_breathing').remove();
|
for (var k in this.tipObjects) {
|
||||||
|
this.tipObjects[k].destroy();
|
||||||
|
}
|
||||||
|
this.tipObjects = {};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -275,27 +261,9 @@ var Tip = Class.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
end_tip: function() {
|
end_tip: function() {
|
||||||
var Tips = new Model('web.tip');
|
new Model('web.tip').call('consume', [this.tip.id], {});
|
||||||
|
|
||||||
this.$element.popover('destroy');
|
|
||||||
this.$element.removeClass('oe_tip_show_element');
|
|
||||||
this.$breathing.remove();
|
|
||||||
this.$helper.remove();
|
|
||||||
this.$overlay.remove();
|
|
||||||
this.$cross.remove();
|
|
||||||
|
|
||||||
$('.oe_tip_fix_parent').each(function() {
|
|
||||||
$(this).removeClass('oe_tip_fix_parent');
|
|
||||||
});
|
|
||||||
$(document).off('keyup.web_tip');
|
|
||||||
|
|
||||||
bus.off('resize', this, this._resize_position);
|
|
||||||
bus.off('resize', this, this._resize);
|
|
||||||
bus.off('image_loaded', this, this._resize);
|
|
||||||
bus.off('please_reposition_tip', this, this._resize);
|
|
||||||
|
|
||||||
Tips.call('consume', [this.tip.id], {});
|
|
||||||
this.tip.is_consumed = true;
|
this.tip.is_consumed = true;
|
||||||
|
this.destroy();
|
||||||
},
|
},
|
||||||
|
|
||||||
_set_breathing_position: function() {
|
_set_breathing_position: function() {
|
||||||
@@ -327,6 +295,29 @@ var Tip = Class.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
destroy: function () {
|
||||||
|
if (this.$element) {
|
||||||
|
this.$element.popover('destroy');
|
||||||
|
this.$element.removeClass('oe_tip_show_element');
|
||||||
|
this.$breathing.off().remove();
|
||||||
|
}
|
||||||
|
if (this.$helper) {
|
||||||
|
this.$helper.off().remove();
|
||||||
|
this.$overlay.off().remove();
|
||||||
|
this.$cross.off().remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.oe_tip_fix_parent').each(function() {
|
||||||
|
$(this).removeClass('oe_tip_fix_parent');
|
||||||
|
});
|
||||||
|
$(document).off('keyup.web_tip');
|
||||||
|
|
||||||
|
bus.off('resize', this, this._resize_position);
|
||||||
|
bus.off('resize', this, this._resize);
|
||||||
|
bus.off('image_loaded', this, this._resize);
|
||||||
|
bus.off('please_reposition_tip', this, this._resize);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
WebClient.include({
|
WebClient.include({
|
||||||
|
|||||||
@@ -367,7 +367,16 @@ options.registry.gallery_img = options.Class.extend({
|
|||||||
var gallery = $parent.data('snippet-editor').styles.gallery;
|
var gallery = $parent.data('snippet-editor').styles.gallery;
|
||||||
gallery.reapply();
|
gallery.reapply();
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
},
|
||||||
|
on_focus: function () {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
if (this._current_src && this._current_src !== this.$target.attr("src")) {
|
||||||
|
_.defer((function () {
|
||||||
|
snippet_editor.globalSelector.closest(this.$target.parent()).data('snippet-editor').styles.gallery.reapply();
|
||||||
|
}).bind(this));
|
||||||
|
}
|
||||||
|
this._current_src = this.$target.attr("src");
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -806,7 +806,7 @@ class HttpRequest(WebRequest):
|
|||||||
if request.httprequest.method == 'OPTIONS' and request.endpoint and request.endpoint.routing.get('cors'):
|
if request.httprequest.method == 'OPTIONS' and request.endpoint and request.endpoint.routing.get('cors'):
|
||||||
headers = {
|
headers = {
|
||||||
'Access-Control-Max-Age': 60 * 60 * 24,
|
'Access-Control-Max-Age': 60 * 60 * 24,
|
||||||
'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
|
'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, X-Debug-Mode'
|
||||||
}
|
}
|
||||||
return Response(status=200, headers=headers)
|
return Response(status=200, headers=headers)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user