[MERGE] forward port branch saas-11 up to 8411b89
This commit is contained in:
@@ -736,6 +736,9 @@ class AccountTax(models.Model):
|
|||||||
else:
|
else:
|
||||||
total_included += tax_amount
|
total_included += tax_amount
|
||||||
|
|
||||||
|
# Keep base amount used for the current tax
|
||||||
|
tax_base = base
|
||||||
|
|
||||||
if tax.include_base_amount:
|
if tax.include_base_amount:
|
||||||
base += tax_amount
|
base += tax_amount
|
||||||
|
|
||||||
@@ -743,6 +746,7 @@ class AccountTax(models.Model):
|
|||||||
'id': tax.id,
|
'id': tax.id,
|
||||||
'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name,
|
'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name,
|
||||||
'amount': tax_amount,
|
'amount': tax_amount,
|
||||||
|
'base': tax_base,
|
||||||
'sequence': tax.sequence,
|
'sequence': tax.sequence,
|
||||||
'account_id': tax.account_id.id,
|
'account_id': tax.account_id.id,
|
||||||
'refund_account_id': tax.refund_account_id.id,
|
'refund_account_id': tax.refund_account_id.id,
|
||||||
|
|||||||
@@ -374,6 +374,7 @@ class AccountBankStatementLine(models.Model):
|
|||||||
journal_entry_ids = fields.One2many('account.move', 'statement_line_id', 'Journal Entries', copy=False, readonly=True)
|
journal_entry_ids = fields.One2many('account.move', 'statement_line_id', 'Journal Entries', copy=False, readonly=True)
|
||||||
amount_currency = fields.Monetary(help="The amount expressed in an optional other currency if it is a multi-currency entry.")
|
amount_currency = fields.Monetary(help="The amount expressed in an optional other currency if it is a multi-currency entry.")
|
||||||
currency_id = fields.Many2one('res.currency', string='Currency', help="The optional other currency if it is a multi-currency entry.")
|
currency_id = fields.Many2one('res.currency', string='Currency', help="The optional other currency if it is a multi-currency entry.")
|
||||||
|
state = fields.Selection(related='statement_id.state' , string='Status', readonly=True)
|
||||||
|
|
||||||
@api.one
|
@api.one
|
||||||
@api.constrains('amount')
|
@api.constrains('amount')
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ from openerp.tools.misc import formatLang
|
|||||||
from openerp.exceptions import UserError, RedirectWarning, ValidationError
|
from openerp.exceptions import UserError, RedirectWarning, ValidationError
|
||||||
|
|
||||||
import openerp.addons.decimal_precision as dp
|
import openerp.addons.decimal_precision as dp
|
||||||
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# mapping invoice type to journal type
|
# mapping invoice type to journal type
|
||||||
TYPE2JOURNAL = {
|
TYPE2JOURNAL = {
|
||||||
@@ -544,6 +547,25 @@ class AccountInvoice(models.Model):
|
|||||||
else:
|
else:
|
||||||
return self.env.ref('account.invoice_form').id
|
return self.env.ref('account.invoice_form').id
|
||||||
|
|
||||||
|
def _prepare_tax_line_vals(self, line, tax):
|
||||||
|
""" Prepare values to create an account.invoice.tax line
|
||||||
|
|
||||||
|
The line parameter is an account.invoice.line, and the
|
||||||
|
tax parameter is the output of account.tax.compute_all().
|
||||||
|
"""
|
||||||
|
vals = {
|
||||||
|
'invoice_id': self.id,
|
||||||
|
'name': tax['name'],
|
||||||
|
'tax_id': tax['id'],
|
||||||
|
'amount': tax['amount'],
|
||||||
|
'base': tax['base'],
|
||||||
|
'manual': False,
|
||||||
|
'sequence': tax['sequence'],
|
||||||
|
'account_analytic_id': tax['analytic'] and line.account_analytic_id.id or False,
|
||||||
|
'account_id': self.type in ('out_invoice', 'in_invoice') and (tax['account_id'] or line.account_id.id) or (tax['refund_account_id'] or line.account_id.id),
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def get_taxes_values(self):
|
def get_taxes_values(self):
|
||||||
tax_grouped = {}
|
tax_grouped = {}
|
||||||
@@ -551,16 +573,7 @@ class AccountInvoice(models.Model):
|
|||||||
price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
|
price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
|
||||||
taxes = line.invoice_line_tax_ids.compute_all(price_unit, self.currency_id, line.quantity, line.product_id, self.partner_id)['taxes']
|
taxes = line.invoice_line_tax_ids.compute_all(price_unit, self.currency_id, line.quantity, line.product_id, self.partner_id)['taxes']
|
||||||
for tax in taxes:
|
for tax in taxes:
|
||||||
val = {
|
val = self._prepare_tax_line_vals(line, tax)
|
||||||
'invoice_id': self.id,
|
|
||||||
'name': tax['name'],
|
|
||||||
'tax_id': tax['id'],
|
|
||||||
'amount': tax['amount'],
|
|
||||||
'manual': False,
|
|
||||||
'sequence': tax['sequence'],
|
|
||||||
'account_analytic_id': tax['analytic'] and line.account_analytic_id.id or False,
|
|
||||||
'account_id': self.type in ('out_invoice', 'in_invoice') and (tax['account_id'] or line.account_id.id) or (tax['refund_account_id'] or line.account_id.id),
|
|
||||||
}
|
|
||||||
|
|
||||||
# If the taxes generate moves on the same financial account as the invoice line,
|
# If the taxes generate moves on the same financial account as the invoice line,
|
||||||
# propagate the analytic account from the invoice line to the tax line.
|
# propagate the analytic account from the invoice line to the tax line.
|
||||||
@@ -575,6 +588,7 @@ class AccountInvoice(models.Model):
|
|||||||
tax_grouped[key] = val
|
tax_grouped[key] = val
|
||||||
else:
|
else:
|
||||||
tax_grouped[key]['amount'] += val['amount']
|
tax_grouped[key]['amount'] += val['amount']
|
||||||
|
tax_grouped[key]['base'] += val['base']
|
||||||
return tax_grouped
|
return tax_grouped
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -1306,15 +1320,19 @@ class AccountInvoiceTax(models.Model):
|
|||||||
_order = 'sequence'
|
_order = 'sequence'
|
||||||
|
|
||||||
def _compute_base_amount(self):
|
def _compute_base_amount(self):
|
||||||
|
tax_grouped = {}
|
||||||
|
for invoice in self.mapped('invoice_id'):
|
||||||
|
tax_grouped[invoice.id] = invoice.get_taxes_values()
|
||||||
for tax in self:
|
for tax in self:
|
||||||
base = 0.0
|
key = self.env['account.tax'].browse(tax.tax_id.id).get_grouping_key({
|
||||||
for line in tax.invoice_id.invoice_line_ids:
|
'tax_id': tax.tax_id.id,
|
||||||
if tax.tax_id in line.invoice_line_tax_ids:
|
'account_id': tax.account_id.id,
|
||||||
price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
|
'account_analytic_id': tax.account_analytic_id.id,
|
||||||
base += (line.invoice_line_tax_ids - tax.tax_id).compute_all(
|
})
|
||||||
price_unit, line.invoice_id.currency_id, line.quantity, line.product_id, line.invoice_id.partner_id
|
if tax.invoice_id and key in tax_grouped[tax.invoice_id.id]:
|
||||||
)['base']
|
tax.base = tax_grouped[tax.invoice_id.id][key]['base']
|
||||||
tax.base = base
|
else:
|
||||||
|
_logger.warning('Tax Base Amount not computable probably due to a change in an underlying tax (%s).', tax.tax_id.name)
|
||||||
|
|
||||||
invoice_id = fields.Many2one('account.invoice', string='Invoice', ondelete='cascade', index=True)
|
invoice_id = fields.Many2one('account.invoice', string='Invoice', ondelete='cascade', index=True)
|
||||||
name = fields.Char(string='Tax Description', required=True)
|
name = fields.Char(string='Tax Description', required=True)
|
||||||
|
|||||||
@@ -41,3 +41,65 @@ class TestAccountSupplierInvoice(AccountingTestCase):
|
|||||||
#I cancel the account move which is in posted state and verifies that it gives warning message
|
#I cancel the account move which is in posted state and verifies that it gives warning message
|
||||||
with self.assertRaises(Warning):
|
with self.assertRaises(Warning):
|
||||||
invoice.move_id.button_cancel()
|
invoice.move_id.button_cancel()
|
||||||
|
|
||||||
|
def test_supplier_invoice2(self):
|
||||||
|
tax_fixed = self.env['account.tax'].create({
|
||||||
|
'sequence': 10,
|
||||||
|
'name': 'Tax 10.0 (Fixed)',
|
||||||
|
'amount': 10.0,
|
||||||
|
'amount_type': 'fixed',
|
||||||
|
'include_base_amount': True,
|
||||||
|
})
|
||||||
|
tax_percent_included_base_incl = self.env['account.tax'].create({
|
||||||
|
'sequence': 20,
|
||||||
|
'name': 'Tax 50.0% (Percentage of Price Tax Included)',
|
||||||
|
'amount': 50.0,
|
||||||
|
'amount_type': 'division',
|
||||||
|
'include_base_amount': True,
|
||||||
|
})
|
||||||
|
tax_percentage = self.env['account.tax'].create({
|
||||||
|
'sequence': 30,
|
||||||
|
'name': 'Tax 20.0% (Percentage of Price)',
|
||||||
|
'amount': 20.0,
|
||||||
|
'amount_type': 'percent',
|
||||||
|
'include_base_amount': False,
|
||||||
|
})
|
||||||
|
analytic_account = self.env['account.analytic.account'].create({
|
||||||
|
'name': 'test account',
|
||||||
|
})
|
||||||
|
|
||||||
|
# Should be changed by automatic on_change later
|
||||||
|
invoice_account = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_receivable').id)], limit=1).id
|
||||||
|
invoice_line_account = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_expenses').id)], limit=1).id
|
||||||
|
|
||||||
|
invoice = self.env['account.invoice'].create({'partner_id': self.env.ref('base.res_partner_2').id,
|
||||||
|
'account_id': invoice_account,
|
||||||
|
'type': 'in_invoice',
|
||||||
|
})
|
||||||
|
|
||||||
|
invoice_line = self.env['account.invoice.line'].create({'product_id': self.env.ref('product.product_product_4').id,
|
||||||
|
'quantity': 5.0,
|
||||||
|
'price_unit': 100.0,
|
||||||
|
'invoice_id': invoice.id,
|
||||||
|
'name': 'product that cost 100',
|
||||||
|
'account_id': invoice_line_account,
|
||||||
|
'invoice_line_tax_ids': [(6, 0, [tax_fixed.id, tax_percent_included_base_incl.id, tax_percentage.id])],
|
||||||
|
'account_analytic_id': analytic_account.id,
|
||||||
|
})
|
||||||
|
invoice.compute_taxes()
|
||||||
|
|
||||||
|
# check that Initially supplier bill state is "Draft"
|
||||||
|
self.assertTrue((invoice.state == 'draft'), "Initially vendor bill state is Draft")
|
||||||
|
|
||||||
|
#change the state of invoice to open by clicking Validate button
|
||||||
|
invoice.signal_workflow('invoice_open')
|
||||||
|
|
||||||
|
# Check if amount and corresponded base is correct for all tax scenarios given on a computational base
|
||||||
|
# Keep in mind that tax amount can be changed by the user at any time before validating (based on the invoice and tax laws applicable)
|
||||||
|
invoice_tax = invoice.tax_line_ids.sorted(key=lambda r: r.sequence)
|
||||||
|
self.assertEquals(invoice_tax.mapped('amount'), [50.0, 550.0, 220.0])
|
||||||
|
self.assertEquals(invoice_tax.mapped('base'), [500.0, 550.0, 1100.0])
|
||||||
|
|
||||||
|
#I cancel the account move which is in posted state and verifies that it gives warning message
|
||||||
|
with self.assertRaises(Warning):
|
||||||
|
invoice.move_id.button_cancel()
|
||||||
|
|||||||
@@ -446,7 +446,7 @@
|
|||||||
<span class="fa fa-copy fa-4x"></span>
|
<span class="fa fa-copy fa-4x"></span>
|
||||||
<h3><strong>Contracts & Subscriptions</strong></h3>
|
<h3><strong>Contracts & Subscriptions</strong></h3>
|
||||||
<p>Manage time & material contracts or fixed-price recurring subscriptions.</p>
|
<p>Manage time & material contracts or fixed-price recurring subscriptions.</p>
|
||||||
<a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'account_analytic_analysis')"
|
<a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'sale_contract')"
|
||||||
class="btn odoo_purple">
|
class="btn odoo_purple">
|
||||||
<span class="fa fa-arrow-circle-o-down"/> Install Now
|
<span class="fa fa-arrow-circle-o-down"/> Install Now
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ class AccountAssetAsset(models.Model):
|
|||||||
else:
|
else:
|
||||||
if self.method == 'linear':
|
if self.method == 'linear':
|
||||||
amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
|
amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
|
||||||
if self.prorata and self.category_id.type == 'purchase':
|
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
|
days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1
|
||||||
@@ -168,7 +168,7 @@ class AccountAssetAsset(models.Model):
|
|||||||
while depreciation_date <= end_date:
|
while depreciation_date <= end_date:
|
||||||
depreciation_date = date(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+self.method_period)
|
depreciation_date = date(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+self.method_period)
|
||||||
undone_dotation_number += 1
|
undone_dotation_number += 1
|
||||||
if self.prorata and self.category_id.type == 'purchase':
|
if self.prorata:
|
||||||
undone_dotation_number += 1
|
undone_dotation_number += 1
|
||||||
return undone_dotation_number
|
return undone_dotation_number
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,8 @@
|
|||||||
<attribute name="options">{'reload_on_button': true}</attribute>
|
<attribute name="options">{'reload_on_button': true}</attribute>
|
||||||
</field>
|
</field>
|
||||||
<xpath expr="//field[@name='bank_account_id']" position="after">
|
<xpath expr="//field[@name='bank_account_id']" position="after">
|
||||||
<button name="button_cancel_reconciliation" attrs="{'invisible': [('journal_entry_ids', '=', [])]}" string="Cancel" type="object" icon="fa-undo text-warning"/>
|
<field name="state" invisible="1"/>
|
||||||
|
<button name="button_cancel_reconciliation" attrs="{'invisible': ['|',('journal_entry_ids', '=', []), ('state', '=', 'confirm')]}" string="Cancel" type="object" icon="fa fa-undo text-warning"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -198,7 +198,14 @@ class BaseActionRule(models.Model):
|
|||||||
|
|
||||||
# subscribe followers
|
# subscribe followers
|
||||||
if self.act_followers and hasattr(records, 'message_subscribe'):
|
if self.act_followers and hasattr(records, 'message_subscribe'):
|
||||||
records.message_subscribe(self.act_followers.ids)
|
followers = self.env['mail.followers'].sudo().search(
|
||||||
|
[('res_model', '=', records._name),
|
||||||
|
('res_id', 'in', records.ids),
|
||||||
|
('partner_id', 'in', self.act_followers.ids),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if not len(followers) == len(self.act_followers):
|
||||||
|
records.message_subscribe(self.act_followers.ids)
|
||||||
|
|
||||||
# execute server actions
|
# execute server actions
|
||||||
if self.server_action_ids:
|
if self.server_action_ids:
|
||||||
|
|||||||
@@ -410,6 +410,10 @@ var PosDB = core.Class.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only necessary when we store a new, validated order. Orders
|
||||||
|
// that where already stored should already have been removed.
|
||||||
|
this.remove_unpaid_order(order);
|
||||||
|
|
||||||
orders.push({id: order_id, data: order});
|
orders.push({id: order_id, data: order});
|
||||||
this.save('orders',orders);
|
this.save('orders',orders);
|
||||||
return order_id;
|
return order_id;
|
||||||
|
|||||||
@@ -1896,7 +1896,7 @@ var PaymentScreenWidget = ScreenWidget.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if the change is too large, it's probably an input error, make the user confirm.
|
// if the change is too large, it's probably an input error, make the user confirm.
|
||||||
if (!force_validation && (order.get_total_with_tax() * 1000 < order.get_total_paid())) {
|
if (!force_validation && order.get_total_with_tax() > 0 && (order.get_total_with_tax() * 1000 < order.get_total_paid())) {
|
||||||
this.gui.show_popup('confirm',{
|
this.gui.show_popup('confirm',{
|
||||||
title: _t('Please Confirm Large Amount'),
|
title: _t('Please Confirm Large Amount'),
|
||||||
body: _t('Are you sure that the customer wants to pay') +
|
body: _t('Are you sure that the customer wants to pay') +
|
||||||
|
|||||||
@@ -195,10 +195,7 @@ class PurchaseOrder(models.Model):
|
|||||||
taxes_ids = line.product_id.supplier_taxes_id.filtered(lambda tax: tax.company_id == requisition.company_id).ids
|
taxes_ids = line.product_id.supplier_taxes_id.filtered(lambda tax: tax.company_id == requisition.company_id).ids
|
||||||
|
|
||||||
# Compute quantity and price_unit
|
# Compute quantity and price_unit
|
||||||
if requisition.type_id.quantity_copy != 'copy':
|
if line.product_uom_id != line.product_id.uom_po_id:
|
||||||
product_qty = 0
|
|
||||||
price_unit = line.price_unit
|
|
||||||
elif line.product_uom_id != line.product_id.uom_po_id:
|
|
||||||
ProductUOM = self.env['product.uom']
|
ProductUOM = self.env['product.uom']
|
||||||
product_qty = ProductUOM._compute_qty_obj(
|
product_qty = ProductUOM._compute_qty_obj(
|
||||||
line.product_uom_id, line.product_qty, line.product_id.uom_po_id)
|
line.product_uom_id, line.product_qty, line.product_id.uom_po_id)
|
||||||
@@ -208,6 +205,9 @@ class PurchaseOrder(models.Model):
|
|||||||
product_qty = line.product_qty
|
product_qty = line.product_qty
|
||||||
price_unit = line.price_unit
|
price_unit = line.price_unit
|
||||||
|
|
||||||
|
if requisition.type_id.quantity_copy != 'copy':
|
||||||
|
product_qty = 0
|
||||||
|
|
||||||
# Compute price_unit in appropriate currency
|
# Compute price_unit in appropriate currency
|
||||||
if requisition.company_id.currency_id != currency:
|
if requisition.company_id.currency_id != currency:
|
||||||
price_unit = requisition.company_id.currency_id.compute(price_unit, currency)
|
price_unit = requisition.company_id.currency_id.compute(price_unit, currency)
|
||||||
@@ -262,6 +262,24 @@ class PurchaseOrder(models.Model):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class PurchaseOrderLine(models.Model):
|
||||||
|
_inherit = "purchase.order.line"
|
||||||
|
|
||||||
|
@api.onchange('product_qty', 'product_uom')
|
||||||
|
def _onchange_quantity(self):
|
||||||
|
res = super(PurchaseOrderLine, self)._onchange_quantity()
|
||||||
|
if self.order_id.requisition_id:
|
||||||
|
for line in self.order_id.requisition_id.line_ids:
|
||||||
|
if line.product_id == self.product_id:
|
||||||
|
if line.product_uom_id != self.product_uom:
|
||||||
|
self.price_unit = self.env['product.uom']._compute_price(
|
||||||
|
line.product_uom_id.id, line.price_unit, to_uom_id=self.product_uom.id)
|
||||||
|
else:
|
||||||
|
self.price_unit = line.price_unit
|
||||||
|
break
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
class ProductTemplate(models.Model):
|
class ProductTemplate(models.Model):
|
||||||
_inherit = 'product.template'
|
_inherit = 'product.template'
|
||||||
|
|
||||||
|
|||||||
@@ -430,6 +430,7 @@ var FormWidget = Widget.extend(InvisibilityChangerMixin, {
|
|||||||
this.process_modifiers();
|
this.process_modifiers();
|
||||||
this._super();
|
this._super();
|
||||||
this.$el.addClass(this.node.attrs["class"] || "");
|
this.$el.addClass(this.node.attrs["class"] || "");
|
||||||
|
this.$el.attr('style', this.node.attrs.style);
|
||||||
},
|
},
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
$.fn.tooltip('destroy');
|
$.fn.tooltip('destroy');
|
||||||
|
|||||||
@@ -141,6 +141,24 @@ class TestViewSaving(common.TransactionCase):
|
|||||||
Company = self.registry('res.company')
|
Company = self.registry('res.company')
|
||||||
View = self.registry('ir.ui.view')
|
View = self.registry('ir.ui.view')
|
||||||
|
|
||||||
|
# create a view with an xmlid, like the file import would
|
||||||
|
with self.env.norecompute():
|
||||||
|
self.view_id = View.create(self.cr, self.uid, {
|
||||||
|
'name': "Test View",
|
||||||
|
'type': 'qweb',
|
||||||
|
'arch': ET.tostring(self.arch, encoding='utf-8').decode('utf-8')
|
||||||
|
})
|
||||||
|
imd = self.env['ir.model.data'].create({
|
||||||
|
'module': 'website',
|
||||||
|
'name': 'test_view',
|
||||||
|
'model': 'ir.ui.view',
|
||||||
|
'res_id': self.view_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
# the xml_id of the view should not be flagged as 'noupdate'
|
||||||
|
self.assertEqual(View.browse(self.cr, self.uid, self.view_id).model_data_id, imd)
|
||||||
|
self.assertFalse(imd.noupdate)
|
||||||
|
|
||||||
replacement = ET.tostring(h.DIV(
|
replacement = ET.tostring(h.DIV(
|
||||||
h.H3("Column 2"),
|
h.H3("Column 2"),
|
||||||
h.UL(
|
h.UL(
|
||||||
@@ -152,6 +170,9 @@ class TestViewSaving(common.TransactionCase):
|
|||||||
View.save(self.cr, self.uid, res_id=self.view_id, value=replacement,
|
View.save(self.cr, self.uid, res_id=self.view_id, value=replacement,
|
||||||
xpath='/div/div[2]')
|
xpath='/div/div[2]')
|
||||||
|
|
||||||
|
# the xml_id of the view should be flagged as 'noupdate'
|
||||||
|
self.assertTrue(imd.noupdate)
|
||||||
|
|
||||||
company = Company.browse(self.cr, self.uid, 1)
|
company = Company.browse(self.cr, self.uid, 1)
|
||||||
self.assertEqual(company.name, "Acme Corporation")
|
self.assertEqual(company.name, "Acme Corporation")
|
||||||
self.assertEqual(company.phone, "+12 3456789")
|
self.assertEqual(company.phone, "+12 3456789")
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ div#blog_angle_down a:hover {
|
|||||||
top: 20%;
|
top: 20%;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
left: 0;
|
left: 15px;
|
||||||
right: 0;
|
right: 15px;
|
||||||
}
|
}
|
||||||
.blog_title h1 {
|
.blog_title h1 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ div#blog_angle_down
|
|||||||
top: 20%
|
top: 20%
|
||||||
margin-right: auto
|
margin-right: auto
|
||||||
margin-left: auto
|
margin-left: auto
|
||||||
left: 0
|
left: 15px
|
||||||
right: 0
|
right: 15px
|
||||||
h1
|
h1
|
||||||
font-weight: bold
|
font-weight: bold
|
||||||
|
|
||||||
|
|||||||
@@ -229,10 +229,11 @@ actual arch.
|
|||||||
for view, view_wo_lang in zip(self, self.with_context(lang=None)):
|
for view, view_wo_lang in zip(self, self.with_context(lang=None)):
|
||||||
view_wo_lang.arch = view.arch_base
|
view_wo_lang.arch = view.arch_base
|
||||||
|
|
||||||
|
@api.depends('write_date')
|
||||||
def _compute_model_data_id(self):
|
def _compute_model_data_id(self):
|
||||||
# get the last ir_model_data record corresponding to self
|
# get the first ir_model_data record corresponding to self
|
||||||
domain = [('model', '=', 'ir.ui.view'), ('res_id', 'in', self.ids)]
|
domain = [('model', '=', 'ir.ui.view'), ('res_id', 'in', self.ids)]
|
||||||
for data in self.env['ir.model.data'].search_read(domain, ['res_id']):
|
for data in self.env['ir.model.data'].search_read(domain, ['res_id'], order='id desc'):
|
||||||
view = self.browse(data['res_id'])
|
view = self.browse(data['res_id'])
|
||||||
view.model_data_id = data['id']
|
view.model_data_id = data['id']
|
||||||
|
|
||||||
@@ -343,7 +344,15 @@ actual arch.
|
|||||||
values['name'] = "%s %s" % (values.get('model'), values['type'])
|
values['name'] = "%s %s" % (values.get('model'), values['type'])
|
||||||
|
|
||||||
self.clear_caches()
|
self.clear_caches()
|
||||||
return super(View, self).create(self._compute_defaults(values))
|
|
||||||
|
if 'install_mode_data' in self._context:
|
||||||
|
# the view is created from a data file by installing a module; delay
|
||||||
|
# the recomputation of field 'model_data_id' until its xmlid record
|
||||||
|
# is created
|
||||||
|
with self.env.norecompute():
|
||||||
|
return super(View, self).create(self._compute_defaults(values))
|
||||||
|
else:
|
||||||
|
return super(View, self).create(self._compute_defaults(values))
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ from odoo.tests import common
|
|||||||
from odoo.tools import mute_logger
|
from odoo.tools import mute_logger
|
||||||
|
|
||||||
|
|
||||||
|
class ViewXMLID(common.TransactionCase):
|
||||||
|
def test_model_data_id(self):
|
||||||
|
""" Check whether views know their xmlid record. """
|
||||||
|
view = self.env.ref('base.view_company_form')
|
||||||
|
self.assertTrue(view)
|
||||||
|
self.assertTrue(view.model_data_id)
|
||||||
|
self.assertEqual(view.model_data_id.complete_name, 'base.view_company_form')
|
||||||
|
|
||||||
class ViewCase(common.TransactionCase):
|
class ViewCase(common.TransactionCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ViewCase, self).setUp()
|
super(ViewCase, self).setUp()
|
||||||
|
|||||||
Reference in New Issue
Block a user