Skip to content

Commit 938ffb9

Browse files
committed
[MERGE] forward port branch 10.0 up to 6466aa4
2 parents 1f9e92d + 6466aa4 commit 938ffb9

File tree

80 files changed

+956
-408
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+956
-408
lines changed

README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[![Build Status](http://runbot.odoo.com/runbot/badge/flat/1/master.svg)](http://runbot.odoo.com/runbot)
2-
[![Tech Doc](http://img.shields.io/badge/master-docs-8f8f8f.svg?style=flat)](http://www.odoo.com/documentation/master)
3-
[![Help](http://img.shields.io/badge/master-help-8f8f8f.svg?style=flat)](https://www.odoo.com/forum/help-1)
4-
[![Nightly Builds](http://img.shields.io/badge/master-nightly-8f8f8f.svg?style=flat)](http://nightly.odoo.com/)
2+
[![Tech Doc](http://img.shields.io/badge/master-docs-875A7B.svg?style=flat)](http://www.odoo.com/documentation/master)
3+
[![Help](http://img.shields.io/badge/master-help-875A7B.svg?style=flat)](https://www.odoo.com/forum/help-1)
4+
[![Nightly Builds](http://img.shields.io/badge/master-nightly-875A7B.svg?style=flat)](http://nightly.odoo.com/)
55

66
Odoo
77
----
@@ -27,14 +27,14 @@ a full-featured <a href="https://www.odoo.com">Open Source ERP</a> when you inst
2727

2828
Getting started with Odoo
2929
-------------------------
30-
For a standard installation please follow the <a href="https://www.odoo.com/documentation/9.0/setup/install.html">Setup instructions</a>
30+
For a standard installation please follow the <a href="https://www.odoo.com/documentation/master/setup/install.html">Setup instructions</a>
3131
from the documentation.
3232

3333
If you are a developer you may type the following command at your terminal:
3434

35-
wget -O- https://raw.githubusercontent.com/odoo/odoo/10.0/setup/setup_dev.py | python
35+
wget -O- https://raw.githubusercontent.com/odoo/odoo/master/setup/setup_dev.py | python
3636

37-
Then follow <a href="https://www.odoo.com/documentation/9.0/tutorials.html">the developer tutorials</a>
37+
Then follow <a href="https://www.odoo.com/documentation/master/tutorials.html">the developer tutorials</a>
3838

3939

4040
For Odoo employees

addons/account/models/account.py

+4
Original file line numberDiff line numberDiff line change
@@ -731,13 +731,17 @@ def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, par
731731
else:
732732
total_included += tax_amount
733733

734+
# Keep base amount used for the current tax
735+
tax_base = base
736+
734737
if tax.include_base_amount:
735738
base += tax_amount
736739

737740
taxes.append({
738741
'id': tax.id,
739742
'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name,
740743
'amount': tax_amount,
744+
'base': tax_base,
741745
'sequence': tax.sequence,
742746
'account_id': tax.account_id.id,
743747
'refund_account_id': tax.refund_account_id.id,

addons/account/models/account_bank_statement.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,13 @@ def button_journal_entries(self):
250250
context = dict(self._context or {})
251251
context['journal_id'] = self.journal_id.id
252252
return {
253-
'name': _('Journal Items'),
253+
'name': _('Journal Entries'),
254254
'view_type': 'form',
255255
'view_mode': 'tree,form',
256-
'res_model': 'account.move.line',
256+
'res_model': 'account.move',
257257
'view_id': False,
258258
'type': 'ir.actions.act_window',
259-
'domain': [('statement_id', 'in', self.ids)],
259+
'domain': [('id', 'in', self.mapped('move_line_ids').mapped('move_id').ids)],
260260
'context': context,
261261
}
262262

@@ -366,6 +366,7 @@ class AccountBankStatementLine(models.Model):
366366
journal_entry_ids = fields.One2many('account.move', 'statement_line_id', 'Journal Entries', copy=False, readonly=True)
367367
amount_currency = fields.Monetary(help="The amount expressed in an optional other currency if it is a multi-currency entry.")
368368
currency_id = fields.Many2one('res.currency', string='Currency', help="The optional other currency if it is a multi-currency entry.")
369+
state = fields.Selection(related='statement_id.state' , string='Status', readonly=True)
369370
move_name = fields.Char(string='Journal Entry Name', readonly=True,
370371
default=False, copy=False,
371372
help="Technical field holding the number given to the journal entry, automatically set when the statement line is reconciled then stored to set the same number again if the line is cancelled, set to draft and re-processed again.")

addons/account/models/account_invoice.py

+36-18
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
from odoo.exceptions import UserError, RedirectWarning, ValidationError
1313

1414
import odoo.addons.decimal_precision as dp
15+
import logging
16+
17+
_logger = logging.getLogger(__name__)
1518

1619
# mapping invoice type to journal type
1720
TYPE2JOURNAL = {
@@ -592,23 +595,33 @@ def get_formview_id(self):
592595
else:
593596
return self.env.ref('account.invoice_form').id
594597

598+
def _prepare_tax_line_vals(self, line, tax):
599+
""" Prepare values to create an account.invoice.tax line
600+
601+
The line parameter is an account.invoice.line, and the
602+
tax parameter is the output of account.tax.compute_all().
603+
"""
604+
vals = {
605+
'invoice_id': self.id,
606+
'name': tax['name'],
607+
'tax_id': tax['id'],
608+
'amount': tax['amount'],
609+
'base': tax['base'],
610+
'manual': False,
611+
'sequence': tax['sequence'],
612+
'account_analytic_id': tax['analytic'] and line.account_analytic_id.id or False,
613+
'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),
614+
}
615+
return vals
616+
595617
@api.multi
596618
def get_taxes_values(self):
597619
tax_grouped = {}
598620
for line in self.invoice_line_ids:
599621
price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
600622
taxes = line.invoice_line_tax_ids.compute_all(price_unit, self.currency_id, line.quantity, line.product_id, self.partner_id)['taxes']
601623
for tax in taxes:
602-
val = {
603-
'invoice_id': self.id,
604-
'name': tax['name'],
605-
'tax_id': tax['id'],
606-
'amount': tax['amount'],
607-
'manual': False,
608-
'sequence': tax['sequence'],
609-
'account_analytic_id': tax['analytic'] and line.account_analytic_id.id or False,
610-
'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),
611-
}
624+
val = self._prepare_tax_line_vals(line, tax)
612625

613626
# If the taxes generate moves on the same financial account as the invoice line,
614627
# propagate the analytic account from the invoice line to the tax line.
@@ -623,6 +636,7 @@ def get_taxes_values(self):
623636
tax_grouped[key] = val
624637
else:
625638
tax_grouped[key]['amount'] += val['amount']
639+
tax_grouped[key]['base'] += val['base']
626640
return tax_grouped
627641

628642
@api.multi
@@ -1336,15 +1350,19 @@ class AccountInvoiceTax(models.Model):
13361350

13371351
@api.depends('invoice_id.invoice_line_ids')
13381352
def _compute_base_amount(self):
1353+
tax_grouped = {}
1354+
for invoice in self.mapped('invoice_id'):
1355+
tax_grouped[invoice.id] = invoice.get_taxes_values()
13391356
for tax in self:
1340-
base = 0.0
1341-
for line in tax.invoice_id.invoice_line_ids:
1342-
if tax.tax_id in line.invoice_line_tax_ids:
1343-
price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
1344-
base += (line.invoice_line_tax_ids - tax.tax_id).compute_all(
1345-
price_unit, line.invoice_id.currency_id, line.quantity, line.product_id, line.invoice_id.partner_id
1346-
)['base']
1347-
tax.base = base
1357+
key = self.env['account.tax'].browse(tax.tax_id.id).get_grouping_key({
1358+
'tax_id': tax.tax_id.id,
1359+
'account_id': tax.account_id.id,
1360+
'account_analytic_id': tax.account_analytic_id.id,
1361+
})
1362+
if tax.invoice_id and key in tax_grouped[tax.invoice_id.id]:
1363+
tax.base = tax_grouped[tax.invoice_id.id][key]['base']
1364+
else:
1365+
_logger.warning('Tax Base Amount not computable probably due to a change in an underlying tax (%s).', tax.tax_id.name)
13481366

13491367
invoice_id = fields.Many2one('account.invoice', string='Invoice', ondelete='cascade', index=True)
13501368
name = fields.Char(string='Tax Description', required=True)

addons/account/models/account_move.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -1037,10 +1037,13 @@ def create(self, vals):
10371037
# the provided values were not already multi-currency
10381038
if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
10391039
vals['currency_id'] = account.currency_id.id
1040-
ctx = {}
1041-
if 'date' in vals:
1042-
ctx['date'] = vals['date']
1043-
vals['amount_currency'] = account.company_id.currency_id.with_context(ctx).compute(amount, account.currency_id)
1040+
if self._context.get('skip_full_reconcile_check') == 'amount_currency_excluded':
1041+
vals['amount_currency'] = 0.0
1042+
else:
1043+
ctx = {}
1044+
if 'date' in vals:
1045+
ctx['date'] = vals['date']
1046+
vals['amount_currency'] = account.company_id.currency_id.with_context(ctx).compute(amount, account.currency_id)
10441047

10451048
if not ok:
10461049
raise UserError(_('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.'))

addons/account/models/chart_template.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def migrate_tags_on_taxes(cr, registry):
3939
('description', '=', tax_template.description)
4040
])
4141
if len(tax_id.ids) == 1:
42-
tax_id.sudo().write({'tag_ids': [(6, 0, [tax_template.tag_ids.ids])]})
42+
tax_id.sudo().write({'tag_ids': [(6, 0, tax_template.tag_ids.ids)]})
4343

4444
# ---------------------------------------------------------------
4545
# Account Templates: Account, Tax, Tax Code and chart. + Wizard
@@ -399,7 +399,9 @@ def generate_account_reconcile_model(self, tax_template_ref, acc_template_ref, c
399399
:rtype: dict
400400
"""
401401
self.ensure_one()
402-
account_reconcile_models = self.env['account.reconcile.model.template'].search([])
402+
account_reconcile_models = self.env['account.reconcile.model.template'].search([
403+
('account_id.chart_template_id', '=', self.id)
404+
])
403405
for account_reconcile_model in account_reconcile_models:
404406
vals = {
405407
'name': account_reconcile_model.name,

addons/account/models/partner.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -445,5 +445,5 @@ def open_partner_history(self):
445445
'''
446446
action = self.env.ref('account.action_invoice_refund_out_tree')
447447
result = action.read()[0]
448-
result['domain'] = "[('id','in',[" + ','.join(map(str, self.ids)) + "])]"
448+
result['domain'] = [('partner_id', 'in', self.ids)]
449449
return result

addons/account/tests/test_account_supplier_invoice.py

+62
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,65 @@ def test_supplier_invoice(self):
4141
#I cancel the account move which is in posted state and verifies that it gives warning message
4242
with self.assertRaises(Warning):
4343
invoice.move_id.button_cancel()
44+
45+
def test_supplier_invoice2(self):
46+
tax_fixed = self.env['account.tax'].create({
47+
'sequence': 10,
48+
'name': 'Tax 10.0 (Fixed)',
49+
'amount': 10.0,
50+
'amount_type': 'fixed',
51+
'include_base_amount': True,
52+
})
53+
tax_percent_included_base_incl = self.env['account.tax'].create({
54+
'sequence': 20,
55+
'name': 'Tax 50.0% (Percentage of Price Tax Included)',
56+
'amount': 50.0,
57+
'amount_type': 'division',
58+
'include_base_amount': True,
59+
})
60+
tax_percentage = self.env['account.tax'].create({
61+
'sequence': 30,
62+
'name': 'Tax 20.0% (Percentage of Price)',
63+
'amount': 20.0,
64+
'amount_type': 'percent',
65+
'include_base_amount': False,
66+
})
67+
analytic_account = self.env['account.analytic.account'].create({
68+
'name': 'test account',
69+
})
70+
71+
# Should be changed by automatic on_change later
72+
invoice_account = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_receivable').id)], limit=1).id
73+
invoice_line_account = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_expenses').id)], limit=1).id
74+
75+
invoice = self.env['account.invoice'].create({'partner_id': self.env.ref('base.res_partner_2').id,
76+
'account_id': invoice_account,
77+
'type': 'in_invoice',
78+
})
79+
80+
invoice_line = self.env['account.invoice.line'].create({'product_id': self.env.ref('product.product_product_4').id,
81+
'quantity': 5.0,
82+
'price_unit': 100.0,
83+
'invoice_id': invoice.id,
84+
'name': 'product that cost 100',
85+
'account_id': invoice_line_account,
86+
'invoice_line_tax_ids': [(6, 0, [tax_fixed.id, tax_percent_included_base_incl.id, tax_percentage.id])],
87+
'account_analytic_id': analytic_account.id,
88+
})
89+
invoice.compute_taxes()
90+
91+
# check that Initially supplier bill state is "Draft"
92+
self.assertTrue((invoice.state == 'draft'), "Initially vendor bill state is Draft")
93+
94+
#change the state of invoice to open by clicking Validate button
95+
invoice.signal_workflow('invoice_open')
96+
97+
# Check if amount and corresponded base is correct for all tax scenarios given on a computational base
98+
# 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)
99+
invoice_tax = invoice.tax_line_ids.sorted(key=lambda r: r.sequence)
100+
self.assertEquals(invoice_tax.mapped('amount'), [50.0, 550.0, 220.0])
101+
self.assertEquals(invoice_tax.mapped('base'), [500.0, 550.0, 1100.0])
102+
103+
#I cancel the account move which is in posted state and verifies that it gives warning message
104+
with self.assertRaises(Warning):
105+
invoice.move_id.button_cancel()

addons/account/views/account_view.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@
556556
<sheet>
557557
<div class="oe_button_box" name="button_box">
558558
<button class="oe_stat_button" name="button_journal_entries"
559-
string="Journal Items" type="object"
559+
string="Journal Entries" type="object"
560560
attrs="{'invisible':[('move_line_ids','=',[])]}" icon="fa-bars"/>
561561
<field name="move_line_ids" invisible="1"/>
562562
</div>
@@ -884,6 +884,7 @@
884884
<field name="type"/>
885885
</group>
886886
<group>
887+
<field name="include_initial_balance"/>
887888
</group>
888889
</group>
889890
<separator string="Description"/>

addons/account/views/partner_view.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
icon="fa-pencil-square-o"
103103
name="open_partner_history"
104104
attrs="{'invisible': [('customer', '=', False)]}"
105-
context="{'search_default_partner_id': active_id,'default_partner_id': active_id}">
105+
context="{'default_partner_id': active_id}">
106106
<div class="o_form_field o_stat_info">
107107
<span class="o_stat_value"><field name="total_invoiced" widget='monetary' options="{'currency_field': 'currency_id'}"/></span>
108108
<span class="o_stat_text">Invoiced</span>

addons/account/views/web_planner_data.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@
447447
<span class="fa fa-copy fa-4x"></span>
448448
<h3><strong>Contracts &amp; Subscriptions</strong></h3>
449449
<p>Manage time &amp; material contracts or fixed-price recurring subscriptions.</p>
450-
<a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'account_analytic_analysis')"
450+
<a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'sale_contract')"
451451
class="btn odoo_purple">
452452
<span class="fa fa-arrow-circle-o-down"/> Install Now
453453
</a>

addons/account_asset/models/account_asset.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def _compute_board_amount(self, sequence, residual_amount, amount_to_depr, undon
153153
else:
154154
if self.method == 'linear':
155155
amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
156-
if self.prorata and self.category_id.type == 'purchase':
156+
if self.prorata:
157157
amount = amount_to_depr / self.method_number
158158
if sequence == 1:
159159
days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1
@@ -174,7 +174,7 @@ def _compute_board_undone_dotation_nb(self, depreciation_date, total_days):
174174
while depreciation_date <= end_date:
175175
depreciation_date = date(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+self.method_period)
176176
undone_dotation_number += 1
177-
if self.prorata and self.category_id.type == 'purchase':
177+
if self.prorata:
178178
undone_dotation_number += 1
179179
return undone_dotation_number
180180

@@ -378,7 +378,7 @@ def copy_data(self, default=None):
378378

379379
@api.multi
380380
def _compute_entries(self, date, group_entries=False):
381-
depreciation_ids = self.env['account.asset.depreciation.line'].with_context(depreciation_date=date).search([
381+
depreciation_ids = self.env['account.asset.depreciation.line'].search([
382382
('asset_id', 'in', self.ids), ('depreciation_date', '<=', date),
383383
('move_check', '=', False)])
384384
if group_entries:

addons/account_cancel/views/account_views.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
<attribute name="options">{'reload_on_button': true}</attribute>
5454
</field>
5555
<xpath expr="//field[@name='bank_account_id']" position="after">
56-
<button name="button_cancel_reconciliation" attrs="{'invisible': [('journal_entry_ids', '=', [])]}" string="Cancel" type="object" icon="fa-undo text-warning"/>
56+
<field name="state" invisible="1"/>
57+
<button name="button_cancel_reconciliation" attrs="{'invisible': ['|',('journal_entry_ids', '=', []), ('state', '=', 'confirm')]}" string="Cancel" type="object" icon="fa fa-undo text-warning"/>
5758
</xpath>
5859
</field>
5960
</record>

0 commit comments

Comments
 (0)