diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index e0fbfbc1873..131ca0f3a53 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -1220,10 +1220,15 @@ class AccountMove(models.Model):
lang_env = move.with_context(lang=move.partner_id.lang).env
tax_lines = move.line_ids.filtered(lambda line: line.tax_line_id)
res = {}
+ # There are as many tax line as there are repartition lines
+ done_taxes = set()
for line in tax_lines:
res.setdefault(line.tax_line_id.tax_group_id, {'base': 0.0, 'amount': 0.0})
res[line.tax_line_id.tax_group_id]['amount'] += line.price_subtotal
- res[line.tax_line_id.tax_group_id]['base'] += line.tax_base_amount
+ if line.tax_line_id.id not in done_taxes:
+ # The base should be added ONCE
+ res[line.tax_line_id.tax_group_id]['base'] += line.tax_base_amount
+ done_taxes.add(line.tax_line_id.id)
res = sorted(res.items(), key=lambda l: l[0].sequence)
move.amount_by_group = [(
group.name, amounts['amount'],
@@ -1315,7 +1320,7 @@ class AccountMove(models.Model):
self.env['account.move.line'].flush(['debit', 'credit', 'move_id'])
self.env['account.move'].flush(['journal_id'])
self._cr.execute('''
- SELECT line.move_id
+ SELECT line.move_id, ROUND(SUM(debit - credit), currency.decimal_places)
FROM account_move_line line
JOIN account_move move ON move.id = line.move_id
JOIN account_journal journal ON journal.id = move.journal_id
@@ -1329,7 +1334,8 @@ class AccountMove(models.Model):
query_res = self._cr.fetchall()
if query_res:
ids = [res[0] for res in query_res]
- raise UserError(_("Cannot create unbalanced journal entry. Ids: %s") % str(ids))
+ sums = [res[1] for res in query_res]
+ raise UserError(_("Cannot create unbalanced journal entry. Ids: %s\nDifferences debit - credit: %s") % (ids, sums))
def _check_fiscalyear_lock_date(self):
for move in self:
@@ -2060,7 +2066,6 @@ class AccountMove(models.Model):
"""
if any(not move.is_invoice(include_receipts=True) for move in self):
raise UserError(_("Only invoices could be printed."))
- self._check_tax_lock_date()
self.filtered(lambda inv: not inv.invoice_sent).write({'invoice_sent': True})
if self.user_has_groups('account.group_account_invoice'):
@@ -2309,7 +2314,7 @@ class AccountMoveLine(models.Model):
),
(
'check_accountable_required_fields',
- "CHECK(display_type IN ('line_section', 'line_note') OR account_id IS NOT NULL)",
+ "CHECK(COALESCE(display_type IN ('line_section', 'line_note'), 'f') OR account_id IS NOT NULL)",
"Missing required account on accountable invoice line."
),
(
@@ -2794,7 +2799,7 @@ class AccountMoveLine(models.Model):
currency = record.company_id.currency_id
audit_str = ''
for tag in record.tag_ids:
- tag_amount = (tag.tax_negate and -1 or 1) * (record.move_id.is_outbound() and -1 or 1) * record.balance
+ tag_amount = (tag.tax_negate and -1 or 1) * (record.move_id.is_inbound() and -1 or 1) * record.balance
if tag.tax_report_line_ids:
#Then, the tag comes from a report line, and hence has a + or - sign (also in its name)
diff --git a/addons/account/models/account_reconcile_model.py b/addons/account/models/account_reconcile_model.py
index 56a8fc81a4e..147c8334a67 100644
--- a/addons/account/models/account_reconcile_model.py
+++ b/addons/account/models/account_reconcile_model.py
@@ -265,6 +265,7 @@ class AccountReconcileModel(models.Model):
'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
'debit': line_balance > 0 and line_balance or 0,
'credit': line_balance < 0 and -line_balance or 0,
+ 'reconcile_model_id': self.id,
}
new_aml_dicts.append(writeoff_line)
@@ -298,6 +299,7 @@ class AccountReconcileModel(models.Model):
'analytic_tag_ids': [(6, 0, self.second_analytic_tag_ids.ids)],
'debit': line_balance > 0 and line_balance or 0,
'credit': line_balance < 0 and -line_balance or 0,
+ 'reconcile_model_id': self.id,
}
new_aml_dicts.append(second_writeoff_line)
diff --git a/addons/account/models/reconciliation_widget.py b/addons/account/models/reconciliation_widget.py
index a52aa1ee3b3..d17d1e21ef4 100644
--- a/addons/account/models/reconciliation_widget.py
+++ b/addons/account/models/reconciliation_widget.py
@@ -556,10 +556,8 @@ class AccountReconciliation(models.AbstractModel):
])
domain = expression.OR([domain_reconciliation, domain_matching])
- partner_domain = []
if partner_id:
- partner_domain = [('partner_id', '=', partner_id)]
- domain = expression.AND([domain, partner_domain])
+ domain = expression.AND([domain, [('partner_id', '=', partner_id)]])
if mode == 'rp':
domain = expression.AND([domain,
[('account_id.internal_type', 'in', ['receivable', 'payable', 'liquidity'])]
@@ -572,14 +570,10 @@ class AccountReconciliation(models.AbstractModel):
# Domain factorized for all reconciliation use cases
if search_str:
str_domain = self._domain_move_lines(search_str=search_str)
- if not partner_id:
- partner_domain = [('partner_id.name', 'ilike', search_str)]
-
str_domain = expression.OR([
str_domain,
- partner_domain,
+ [('partner_id.name', 'ilike', search_str)]
])
-
domain = expression.AND([
domain,
str_domain
@@ -596,7 +590,6 @@ class AccountReconciliation(models.AbstractModel):
if st_line.company_id.account_bank_reconciliation_start:
domain = expression.AND([domain, [('date', '>=', st_line.company_id.account_bank_reconciliation_start)]])
-
return domain
@api.model
diff --git a/addons/account/models/res_users.py b/addons/account/models/res_users.py
index 6b379668fa3..d564746dfd6 100644
--- a/addons/account/models/res_users.py
+++ b/addons/account/models/res_users.py
@@ -12,8 +12,12 @@ class Users(models.Model):
def _check_one_user_type(self):
super(Users, self)._check_one_user_type()
- g1 = self.env.ref('account.group_show_line_subtotals_tax_included')
- g2 = self.env.ref('account.group_show_line_subtotals_tax_excluded')
+ g1 = self.env.ref('account.group_show_line_subtotals_tax_included', False)
+ g2 = self.env.ref('account.group_show_line_subtotals_tax_excluded', False)
+
+ if not g1 or not g2:
+ # A user cannot be in a non-existant group
+ return
if self._has_multiple_groups([g1.id, g2.id]):
raise ValidationError(_("A user cannot have both Tax B2B and Tax B2C.\n"
diff --git a/addons/account/tests/account_test_no_chart.py b/addons/account/tests/account_test_no_chart.py
index fbd895fdb46..61cbe3e47a6 100644
--- a/addons/account/tests/account_test_no_chart.py
+++ b/addons/account/tests/account_test_no_chart.py
@@ -83,12 +83,16 @@ class TestAccountNoChartCommon(SavepointCase):
'code': 'AJ-PURC',
'type': 'purchase',
'company_id': cls.env.user.company_id.id,
+ 'default_debit_account_id': cls.account_expense.id,
+ 'default_credit_account_id': cls.account_expense.id,
})
cls.journal_sale = cls.env['account.journal'].create({
'name': 'Sale Journal - Test',
'code': 'AJ-SALE',
'type': 'sale',
'company_id': cls.env.user.company_id.id,
+ 'default_debit_account_id': cls.account_income.id,
+ 'default_credit_account_id': cls.account_income.id,
})
cls.journal_general = cls.env['account.journal'].create({
'name': 'General Journal - Test',
diff --git a/addons/account/tests/test_account_move_entry.py b/addons/account/tests/test_account_move_entry.py
index 587dfc48deb..d3c3503ff5a 100644
--- a/addons/account/tests/test_account_move_entry.py
+++ b/addons/account/tests/test_account_move_entry.py
@@ -60,6 +60,7 @@ class TestAccountMove(InvoiceTestCommon):
self.env['account.move'].create(self.test_move.copy_data())
def test_misc_tax_lock_date_1(self):
+ self.test_move.post()
# Set the tax lock date after the journal entry date.
self.test_move.company_id.tax_lock_date = fields.Date.from_string('2017-01-01')
diff --git a/addons/account/tests/test_account_move_partner_count.py b/addons/account/tests/test_account_move_partner_count.py
index 7ec2b6cc410..68527cf7572 100644
--- a/addons/account/tests/test_account_move_partner_count.py
+++ b/addons/account/tests/test_account_move_partner_count.py
@@ -1,9 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from odoo.tests import tagged
from odoo.tests.common import TransactionCase
+@tagged('post_install', '-at_install')
class TestAccountMovePartnerCount(TransactionCase):
def setUp(self):
@@ -14,6 +16,13 @@ class TestAccountMovePartnerCount(TransactionCase):
with self.registry.cursor() as cr:
env = self.env(cr=cr)
self.partner = self.env['res.partner'].with_env(env).create({'name': 'Lucien'})
+ user_type_income = env.ref('account.data_account_type_direct_costs')
+ self.account_income = self.env['account.account'].with_env(env).create({
+ 'code': 'TESTCOUNT42',
+ 'name': 'Sale - Test Account',
+ 'user_type_id': user_type_income.id
+ })
+
self.journal = self.env['account.journal'].with_env(env).create({
'name': 'Journal',
'code': '7775',
@@ -28,6 +37,7 @@ class TestAccountMovePartnerCount(TransactionCase):
self.line = self.env['account.move.line'].with_env(env).create({
'move_id': self.move.id,
'name': 'account move line test',
+ 'account_id': self.account_income.id,
})
def tearDown(self):
@@ -38,6 +48,7 @@ class TestAccountMovePartnerCount(TransactionCase):
move.state = 'draft'
move.unlink()
self.journal.with_env(env).unlink()
+ self.account_income.with_env(env).unlink()
self.partner.with_env(env).unlink()
def test_account_move_count(self):
diff --git a/addons/account/tests/test_reconciliation_widget.py b/addons/account/tests/test_reconciliation_widget.py
index 99769bc2f2e..0baa2c23f8b 100644
--- a/addons/account/tests/test_reconciliation_widget.py
+++ b/addons/account/tests/test_reconciliation_widget.py
@@ -57,6 +57,7 @@ class TestReconciliationWidget(TestReconciliation):
def test_filter_partner1(self):
inv1 = self.create_invoice(currency_id=self.currency_euro_id)
inv2 = self.create_invoice(currency_id=self.currency_euro_id)
+ partner = inv1.partner_id
receivable1 = inv1.line_ids.filtered(lambda l: l.account_id.internal_type == 'receivable')
receivable2 = inv2.line_ids.filtered(lambda l: l.account_id.internal_type == 'receivable')
@@ -75,7 +76,33 @@ class TestReconciliationWidget(TestReconciliation):
'date': time.strftime('%Y-07-15'),
})
- # This is like opening the widget, and type "deco" in the filter
+ # This is like input a partner in the widget
+ mv_lines_rec = self.env['account.reconciliation.widget'].get_move_lines_for_bank_statement_line(
+ bank_stmt_line.id,
+ partner_id=partner.id,
+ excluded_ids=[],
+ search_str=False,
+ mode="rp",
+ )
+ mv_lines_ids = [l['id'] for l in mv_lines_rec]
+
+ self.assertIn(receivable1.id, mv_lines_ids)
+ self.assertIn(receivable2.id, mv_lines_ids)
+
+ # With a partner set, type the invoice reference in the filter
+ mv_lines_rec = self.env['account.reconciliation.widget'].get_move_lines_for_bank_statement_line(
+ bank_stmt_line.id,
+ partner_id=partner.id,
+ excluded_ids=[],
+ search_str=inv1.invoice_payment_ref,
+ mode="rp",
+ )
+ mv_lines_ids = [l['id'] for l in mv_lines_rec]
+
+ self.assertIn(receivable1.id, mv_lines_ids)
+ self.assertNotIn(receivable2.id, mv_lines_ids)
+
+ # Without a partner set, type "deco" in the filter
mv_lines_rec = self.env['account.reconciliation.widget'].get_move_lines_for_bank_statement_line(
bank_stmt_line.id,
partner_id=False,
@@ -88,8 +115,7 @@ class TestReconciliationWidget(TestReconciliation):
self.assertIn(receivable1.id, mv_lines_ids)
self.assertIn(receivable2.id, mv_lines_ids)
- # This is like clicking on the first receivable
- partner = inv1.partner_id
+ # With a partner set, type "deco" in the filter and click on the first receivable
mv_lines_rec = self.env['account.reconciliation.widget'].get_move_lines_for_bank_statement_line(
bank_stmt_line.id,
partner_id=partner.id,
diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml
index a488cc09ed0..07e733d0b42 100644
--- a/addons/account/views/account_view.xml
+++ b/addons/account/views/account_view.xml
@@ -1265,7 +1265,7 @@ action = model.setting_init_bank_account_action()
-
+
diff --git a/addons/auth_signup/models/res_partner.py b/addons/auth_signup/models/res_partner.py
index b92e5dc55f5..259a5838b30 100644
--- a/addons/auth_signup/models/res_partner.py
+++ b/addons/auth_signup/models/res_partner.py
@@ -109,7 +109,7 @@ class ResPartner(models.Model):
allow_signup = self.env['res.users']._get_signup_invitation_scope() == 'b2c'
for partner in self:
- if allow_signup and not partner.user_ids:
+ if allow_signup and not partner.sudo().user_ids:
partner = partner.sudo()
partner.signup_prepare()
res[partner.id]['auth_signup_token'] = partner.signup_token
diff --git a/addons/digest/data/res_config_settings_data.xml b/addons/digest/data/res_config_settings_data.xml
index cbd93e4fef0..cacc318daf0 100644
--- a/addons/digest/data/res_config_settings_data.xml
+++ b/addons/digest/data/res_config_settings_data.xml
@@ -1,10 +1,10 @@
-
-
+
+
digest.default_digest_emails
True
-
+
digest.default_digest_id
diff --git a/addons/event/controllers/main.py b/addons/event/controllers/main.py
index f844e6a5d51..723d30aaa51 100644
--- a/addons/event/controllers/main.py
+++ b/addons/event/controllers/main.py
@@ -10,8 +10,6 @@ class EventController(Controller):
@route(['''/event//ics'''], type='http', auth="public")
def event_ics_file(self, event, **kwargs):
- if not event or not event.registration_ids:
- return request.not_found()
files = event._get_ics_file()
if not event.id in files:
return NotFound()
diff --git a/addons/hr_org_chart/controllers/hr_org_chart.py b/addons/hr_org_chart/controllers/hr_org_chart.py
index 8df4c81ae40..f9160767995 100644
--- a/addons/hr_org_chart/controllers/hr_org_chart.py
+++ b/addons/hr_org_chart/controllers/hr_org_chart.py
@@ -14,8 +14,8 @@ class HrOrgChartController(http.Controller):
return None
employee_id = int(employee_id)
- if ('context' in kw and 'allowed_company_ids' in kw['context']):
- cids = kw['context']['allowed_company_ids']
+ if 'allowed_company_ids' in request.env.context:
+ cids = request.env.context['allowed_company_ids']
else:
cids = [request.env.company.id]
diff --git a/addons/l10n_fr/data/account_fiscal_position_template_data.xml b/addons/l10n_fr/data/account_fiscal_position_template_data.xml
index c1b3663520f..c82d89442e7 100644
--- a/addons/l10n_fr/data/account_fiscal_position_template_data.xml
+++ b/addons/l10n_fr/data/account_fiscal_position_template_data.xml
@@ -54,6 +54,11 @@
+
+
+
+
+
@@ -64,6 +69,11 @@
+
+
+
+
+
@@ -146,11 +156,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -168,22 +198,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -203,11 +253,21 @@
+
+
+
+
+
+
+
+
+
+
@@ -280,6 +340,11 @@
+
+
+
+
+
@@ -291,12 +356,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/l10n_fr/data/account_tax_data.xml b/addons/l10n_fr/data/account_tax_data.xml
index 3f72c43b63e..41fc79e15a1 100644
--- a/addons/l10n_fr/data/account_tax_data.xml
+++ b/addons/l10n_fr/data/account_tax_data.xml
@@ -46,6 +46,47 @@
]"/>
+
+
+ TVA à l'encaissement (vente) 10,0%
+ TVA 10%
+
+ percent
+ on_payment
+
+
+ sale
+
+
+
+
+
TVA à l'encaissement (vente) 20,0%
@@ -367,6 +408,48 @@
]"/>
+
+
+ TVA à l'encaissement (vente) 10,0% TTC
+ TVA 10% TTC
+
+
+ percent
+ on_payment
+
+
+ sale
+
+
+
+
+
TVA à l'encaissement (vente) 20,0% TTC
@@ -693,6 +776,88 @@
]"/>
+
+
+ TVA à l'encaissement (achat) 20,0%
+ TVA 20%
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
+
+
+ TVA à l'encaissement (achat) 10,0%
+ TVA 10%
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
TVA déductible (achat) 8,5%
@@ -810,6 +975,47 @@
]"/>
+
+
+ TVA à l'encaissement (achat) 5,5%
+ TVA 5,5%
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
TVA déductible (achat) 2,1%
@@ -851,6 +1057,47 @@
+
+
+ TVA à l'encaissement (achat) 2,1%
+ TVA 2,1%
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
TVA déductible (achat) 20,0% TTC
@@ -891,6 +1138,48 @@
]"/>
+
+
+ TVA à l'encaissement (achat) 20,0% TTC
+ TVA 20% TTC
+
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
TVA déductible (achat) 8,5% TTC
@@ -931,6 +1220,48 @@
]"/>
+
+
+ TVA à l'encaissement (achat) 10,0% TTC
+ TVA 10% TTC
+
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
TVA déductible (achat) 10,0% TTC
@@ -1011,6 +1342,48 @@
]"/>
+
+
+ TVA à l'encaissement (achat) 5,5% TTC
+ TVA 5,5% TTC
+
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
TVA déductible (achat) 2,1% TTC
@@ -1051,6 +1424,48 @@
]"/>
+
+
+ TVA à l'encaissement (achat) 2,1% TTC
+ TVA 2,1% TTC
+
+
+ percent
+ on_payment
+
+
+ purchase
+
+
+
+
+
diff --git a/addons/l10n_in/data/account_data.xml b/addons/l10n_in/data/account_data.xml
index c1fb9299c1e..c20cfa8839f 100644
--- a/addons/l10n_in/data/account_data.xml
+++ b/addons/l10n_in/data/account_data.xml
@@ -3,6 +3,12 @@
+
+ SGST
+
+
+ CGST
+
IGST
diff --git a/addons/l10n_in/data/account_tax_template_data.xml b/addons/l10n_in/data/account_tax_template_data.xml
index 6c0d3b8892e..374628bb05d 100644
--- a/addons/l10n_in/data/account_tax_template_data.xml
+++ b/addons/l10n_in/data/account_tax_template_data.xml
@@ -459,14 +459,14 @@ if tax > result:result=tax
-
- GST 1%
- GST 1%
- sale
+
+ SGST Sale 0.5%
+ SGST 0.5%
+ none
percent
- 1.0
+ 0.5
-
+
+
+
+
+ CGST Sale 0.5%
+ CGST 0.5%
+ none
+ percent
+ 0.5
+
+
+
+
+
+
+
+ GST 1%
+ GST 1%
+ sale
+ group
+ 1.0
+
+
+
+
+
+
+ SGST Sale 1%
+ SGST 1%
+ none
+ percent
+ 1
+
+
+
+
+
+
+
+ CGST Sale 1%
+ CGST 1%
+ none
+ percent
+ 1
+
+
+
+
@@ -511,10 +614,21 @@ if tax > result:result=tax
GST 2%
GST 2%
sale
- percent
+ group
2.0
+
+
+
+
+ SGST Sale 14%
+ SGST 14%
+ none
+ percent
+ 14
+
+
+
+
+
+ CGST Sale 14%
+ CGST 14%
+ none
+ percent
+ 14
+
+
+
+
@@ -559,10 +695,21 @@ if tax > result:result=tax
GST 28%
GST 28%
sale
- percent
+ group
28.0
+
+
+
+
+ SGST Sale 9%
+ SGST 9%
+ none
+ percent
+ 9
+
+
+
+
+
+ CGST Sale 9%
+ CGST 9%
+ none
+ percent
+ 9
+
+
+
+
@@ -607,43 +776,74 @@ if tax > result:result=tax
GST 18%
GST 18%
sale
- percent
+ group
18.0
+
+
+
+
+ SGST Sale 6%
+ SGST 6%
+ none
+ percent
+ 6
+
+
+
+
+
+ CGST Sale 6%
+ CGST 6%
+ none
+ percent
+ 6
+
+
+
+ GST 12%
GST 12%
sale
- percent
+ group
12.0
+
+
+
+
+ SGST Sale 2.5%
+ SGST 2.5%
+ none
+ percent
+ 2.5
+
+
+
+
+
+ CGST Sale 2.5%
+ CGST 2.5%
+ none
+ percent
+ 2.5
+
+
+
+
@@ -703,49 +936,12 @@ if tax > result:result=tax
GST 5%
GST 5%
sale
- percent
+ group
5.0
0
-
-
+
@@ -1166,31 +1362,25 @@ if tax > result:result=tax
-
- GST 1%
- GST 1%
- purchase
+
+ SGST Purchase 0.5%
+ SGST 0.5%
+ none
percent
- 1.0
+ 0.5
-
+
+
+
+
+ CGST Purchase 0.5%
+ CGST 0.5%
+ none
+ percent
+ 0.5
+
+
+
+
+
+ GST 1%
+ GST 1%
+ purchase
+ group
+ 1.0
+
+
+
+
+
+
+ SGST Purchase 1%
+ SGST 1%
+ none
+ percent
+ 1
+
+
+
+
+
+
+
+ CGST Purchase 1%
+ CGST 1%
+ none
+ percent
+ 1
+
+
+
+
+
+
+
GST 2%
GST 2%
purchase
- percent
+ group
2.0
+
+
+
+
+ SGST Purchase 14%
+ SGST 14%
+ none
+ percent
+ 14
+
+
+
+
+
+ CGST Purchase 14%
+ CGST 14%
+ none
+ percent
+ 14
+
+
+
+
@@ -1264,10 +1595,21 @@ if tax > result:result=tax
GST 28%
GST 28%
purchase
- percent
+ group
28.0
+
+
+
+
+ SGST Purchase 9%
+ SGST 9%
+ none
+ percent
+ 9
+
+
+
+
+
+ CGST Purchase 9%
+ CGST 9%
+ none
+ percent
+ 9
+
+
+
+
@@ -1312,10 +1676,21 @@ if tax > result:result=tax
GST 18%
GST 18%
purchase
- percent
+ group
18.0
+
+
+
+
+ SGST Purchase 6%
+ SGST 6%
+ none
+ percent
+ 6
+
+
+
+
+
+
+ CGST Purchase 6%
+ CGST 6%
+ none
+ percent
+ 6
+
+
+
@@ -1360,10 +1757,21 @@ if tax > result:result=tax
GST 12%
GST 12%
purchase
- percent
+ group
12.0
+
+
+
+
+ SGST Purchase 2.5%
+ SGST 2.5%
+ none
+ percent
+ 2.5
+
+
+
+
+
+ CGST Purchase 2.5%
+ CGST 2.5%
+ none
+ percent
+ 2.5
+
+
+
+
@@ -1408,49 +1838,12 @@ if tax > result:result=tax
GST 5%
GST 5%
purchase
- percent
+ group
5.0
0
-
-
+
diff --git a/addons/l10n_it_edi/models/account_invoice.py b/addons/l10n_it_edi/models/account_invoice.py
index 2938c6630ff..062e7f184a2 100644
--- a/addons/l10n_it_edi/models/account_invoice.py
+++ b/addons/l10n_it_edi/models/account_invoice.py
@@ -109,7 +109,7 @@ class AccountMove(models.Model):
raise UserError(_("%s must have a country.") % (seller.display_name))
# <1.4.1>
- if not buyer.vat and not buyer.l10n_it_codice_fiscale and buyer.country_id.code != 'IT':
+ if not buyer.vat and not buyer.l10n_it_codice_fiscale and buyer.country_id.code == 'IT':
raise UserError(_("The buyer, %s, or his company must have either a VAT number either a tax code (Codice Fiscale).") % (buyer.display_name))
# <1.4.2>
@@ -270,11 +270,12 @@ class AccountMove(models.Model):
'body': _('Sending file: %s to ES: %s') % (self.l10n_it_einvoice_id.name, self.env.company.l10n_it_address_recipient_fatturapa),
'author_id': self.env.user.partner_id.id,
'email_from': self.env.company.l10n_it_address_send_fatturapa,
+ 'reply_to': self.env.company.l10n_it_address_send_fatturapa,
'mail_server_id': self.env.company.l10n_it_mail_pec_server_id.id,
'attachment_ids': [(6, 0, self.l10n_it_einvoice_id.ids)],
})
- mail_fattura = self.env['mail.mail'].create({
+ mail_fattura = self.env['mail.mail'].with_context(wo_return_path=True).create({
'mail_message_id': message.id,
'email_to': self.env.company.l10n_it_address_recipient_fatturapa,
})
diff --git a/addons/l10n_it_edi/models/ir_mail_server.py b/addons/l10n_it_edi/models/ir_mail_server.py
index 51e4a0a23a3..2d2f33540a1 100644
--- a/addons/l10n_it_edi/models/ir_mail_server.py
+++ b/addons/l10n_it_edi/models/ir_mail_server.py
@@ -360,3 +360,17 @@ class FetchmailServer(models.Model):
if descrizione:
output_str += "
Errore %s: %s" % (element[0].text, descrizione)
return output_str + ""
+
+class IrMailServer(models.Model):
+ _name = "ir.mail_server"
+ _inherit = "ir.mail_server"
+
+ def build_email(self, email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
+ attachments=None, message_id=None, references=None, object_id=False, subtype='plain', headers=None,
+ body_alternative=None, subtype_alternative='plain'):
+
+ if self.env.context.get('wo_return_path') and headers:
+ headers.pop('Return-Path', False)
+ return super(IrMailServer, self).build_email(email_from, email_to, subject, body, email_cc=email_cc, email_bcc=email_bcc, reply_to=reply_to,
+ attachments=attachments, message_id=message_id, references=references, object_id=object_id, subtype=subtype, headers=headers,
+ body_alternative=body_alternative, subtype_alternative=subtype_alternative)
diff --git a/addons/mail/static/src/js/discuss.js b/addons/mail/static/src/js/discuss.js
index 6eeeaecf7c3..de5ce88b742 100644
--- a/addons/mail/static/src/js/discuss.js
+++ b/addons/mail/static/src/js/discuss.js
@@ -280,6 +280,8 @@ var Discuss = AbstractAction.extend({
this.options.channelQuickSearchThreshold = 20;
}
+ this._isMessagingReady = this.call('mail_service', 'isReady');
+ this._isStarted = false;
this._threadsScrolltop = {};
this._composerStates = {};
this._defaultThreadID = this.options.active_id ||
@@ -291,68 +293,20 @@ var Discuss = AbstractAction.extend({
this._updateThreads.bind(this), 100, { leading: false });
this.controlPanelParams.modelName = 'mail.message';
- },
- /**
- * @override
- */
- willStart: function () {
- return Promise.all([this._super(), this.call('mail_service', 'isReady')]);
+ this.call('mail_service', 'getMailBus').on('messaging_ready', this, this._onMessagingReady);
},
/**
* @override
*/
start: function () {
var self = this;
-
- this._basicComposer = new BasicComposer(this, {
- mentionPartnersRestricted: true,
- showTyping: true,
+ this._isStarted = true;
+ return this._super.apply(this, arguments).then(function () {
+ if (!self._isMessagingReady) {
+ return;
+ }
+ return self._initRender();
});
- this._extendedComposer = new ExtendedComposer(this, {
- mentionPartnersRestricted: true,
- showTyping: true,
- });
- this._basicComposer
- .on('post_message', this, this._onPostMessage)
- .on('input_focused', this, this._onComposerFocused);
- this._extendedComposer
- .on('post_message', this, this._onPostMessage)
- .on('input_focused', this, this._onComposerFocused);
- this._renderButtons();
-
- var defs = [];
- defs.push(
- this._renderThread()
- );
- defs.push(
- this._basicComposer.appendTo(this.$('.o_mail_discuss_content')));
- defs.push(
- this._extendedComposer.appendTo(this.$('.o_mail_discuss_content')));
- defs.push(this._super.apply(this, arguments));
-
- return Promise.all(defs)
- .then(function () {
- return self._setThread(self._defaultThreadID);
- })
- .then(function () {
- self._initThreads();
- self._startListening();
- self._threadWidget.$el.on('scroll', null, _.debounce(function () {
- if (
- self._threadWidget.getScrolltop() < 20 &&
- !self._threadWidget.$('.o_mail_no_content').length &&
- !self._thread.isAllHistoryLoaded(self.domain)
- ) {
- self._loadMoreMessages();
- }
- if (
- self._threadWidget.isAtBottom() &&
- self._thread.getType() !== 'mailbox'
- ) {
- self._thread.markAsRead();
- }
- }, 100));
- });
},
/**
* @override
@@ -381,8 +335,8 @@ var Discuss = AbstractAction.extend({
this.call('mail_service', 'getMailBus').trigger('discuss_open', true);
if (this._thread) {
this._threadWidget.scrollToPosition(this._threadsScrolltop[this._thread.getID()]);
+ this._loadEnoughMessages();
}
- this._loadEnoughMessages();
},
/**
* @override
@@ -546,6 +500,60 @@ var Discuss = AbstractAction.extend({
}
}
},
+ /**
+ * @private
+ */
+ _initRender: function () {
+ var self = this;
+ this._basicComposer = new BasicComposer(this, {
+ mentionPartnersRestricted: true,
+ showTyping: true,
+ });
+ this._extendedComposer = new ExtendedComposer(this, {
+ mentionPartnersRestricted: true,
+ showTyping: true,
+ });
+ this._basicComposer
+ .on('post_message', this, this._onPostMessage)
+ .on('input_focused', this, this._onComposerFocused);
+ this._extendedComposer
+ .on('post_message', this, this._onPostMessage)
+ .on('input_focused', this, this._onComposerFocused);
+ this._renderButtons();
+
+ var defs = [];
+ defs.push(
+ this._renderThread()
+ );
+ defs.push(
+ this._basicComposer.appendTo(this.$('.o_mail_discuss_content')));
+ defs.push(
+ this._extendedComposer.appendTo(this.$('.o_mail_discuss_content')));
+
+ return Promise.all(defs)
+ .then(function () {
+ return self._setThread(self._defaultThreadID);
+ })
+ .then(function () {
+ self._initThreads();
+ self._startListening();
+ self._threadWidget.$el.on('scroll', null, _.debounce(function () {
+ if (
+ self._threadWidget.getScrolltop() < 20 &&
+ !self._threadWidget.$('.o_mail_no_content').length &&
+ !self._thread.isAllHistoryLoaded(self.domain)
+ ) {
+ self._loadMoreMessages();
+ }
+ if (
+ self._threadWidget.isAtBottom() &&
+ self._thread.getType() !== 'mailbox'
+ ) {
+ self._thread.markAsRead();
+ }
+ }, 100));
+ });
+ },
/**
* Renders the mainside bar with current threads
*
@@ -1400,6 +1408,20 @@ var Discuss = AbstractAction.extend({
this._fetchAndRenderThread();
}
},
+ /**
+ * @private
+ */
+ _onMessagingReady: function () {
+ if (this._isMessagingReady) {
+ return;
+ }
+ this._isMessagingReady = true;
+ if (!this._isStarted) {
+ return;
+ }
+ this.$('.o_mail_discuss_loading').remove();
+ this._initRender();
+ },
/**
* @private
* @param {MouseEvent} ev
diff --git a/addons/mail/static/src/js/services/mail_document_thread_manager.js b/addons/mail/static/src/js/services/mail_document_thread_manager.js
index 6bb66b1b439..652567baf14 100644
--- a/addons/mail/static/src/js/services/mail_document_thread_manager.js
+++ b/addons/mail/static/src/js/services/mail_document_thread_manager.js
@@ -34,7 +34,7 @@ MailManager.include({
this.call('local_storage', 'getItem', key);
}
}
- this.isReady().then(this._updateDocumentThreadWindows.bind(this, this._documentThreadWindowStates));
+ this._mailBus.on('messaging_ready', this, this._updateDocumentThreadWindows.bind(this, this._documentThreadWindowStates));
// listen to localStorage changes to synchronize DocumentThread's
// windows between tabs
this.call('local_storage', 'onStorage', this, this._onStorage);
diff --git a/addons/mail/static/src/js/services/mail_manager.js b/addons/mail/static/src/js/services/mail_manager.js
index 27208f0edfc..015ebfa01a3 100644
--- a/addons/mail/static/src/js/services/mail_manager.js
+++ b/addons/mail/static/src/js/services/mail_manager.js
@@ -46,6 +46,7 @@ var PREVIEW_MSG_MAX_SIZE = 350; // optimal for native english speakers
var MailManager = AbstractService.extend({
dependencies: ['ajax', 'bus_service', 'local_storage'],
+ _isReady: false,
_ODOOBOT_ID: ["ODOOBOT", "ODOOBOT"], // authorID for transient messages
/**
@@ -294,7 +295,7 @@ var MailManager = AbstractService.extend({
* This is the case when it has fetched the initial state from the server,
* by means of the route 'mail/init_messaging'
*
- * @returns {Promise}
+ * @returns {boolean}
*/
isReady: function () {
return this._isReady;
@@ -636,7 +637,7 @@ var MailManager = AbstractService.extend({
*/
_fetchMailStateFromServer: function () {
var self = this;
- this._isReady = session.is_bound.then(function () {
+ session.is_bound.then(function () {
var context = _.extend(
{ isMobile: config.device.isMobile },
session.user_context
@@ -648,6 +649,8 @@ var MailManager = AbstractService.extend({
}).then(function (result) {
self._updateInternalStateFromServer(result);
self.call('bus_service', 'startPolling');
+ self._isReady = true;
+ self._mailBus.trigger('messaging_ready');
});
},
/**
diff --git a/addons/mail/static/src/js/systray/systray_activity_menu.js b/addons/mail/static/src/js/systray/systray_activity_menu.js
index 7dcd1ca058f..fce3247e15b 100644
--- a/addons/mail/static/src/js/systray/systray_activity_menu.js
+++ b/addons/mail/static/src/js/systray/systray_activity_menu.js
@@ -19,9 +19,6 @@ var ActivityMenu = Widget.extend({
'click .o_mail_preview': '_onActivityFilterClick',
'show.bs.dropdown': '_onActivityMenuShow',
},
- willStart: function () {
- return Promise.resolve(this.call('mail_service', 'isReady'));
- },
start: function () {
this._$activitiesPreview = this.$('.o_mail_systray_dropdown_items');
this.call('mail_service', 'getMailBus').on('activity_updated', this, this._updateCounter);
diff --git a/addons/mail/static/src/js/systray/systray_messaging_menu.js b/addons/mail/static/src/js/systray/systray_messaging_menu.js
index 9a9b21fe953..4a27ed0713f 100644
--- a/addons/mail/static/src/js/systray/systray_messaging_menu.js
+++ b/addons/mail/static/src/js/systray/systray_messaging_menu.js
@@ -27,12 +27,6 @@ var MessagingMenu = Widget.extend({
'click .o_thread_window_expand': '_onClickExpand',
'show.bs.dropdown': '_onShowDropdown',
},
- /**
- * @override
- */
- willStart: function () {
- return Promise.all([this._super.apply(this, arguments), this.call('mail_service', 'isReady')]);
- },
/**
* @override
*/
@@ -40,8 +34,10 @@ var MessagingMenu = Widget.extend({
this._$filterButtons = this.$('.o_filter_button');
this._$previews = this.$('.o_mail_systray_dropdown_items');
this._filter = false;
+ this._isMessagingReady = this.call('mail_service', 'isReady');
this._updateCounter();
var mailBus = this.call('mail_service', 'getMailBus');
+ mailBus.on('messaging_ready', this, this._onMessagingReady);
mailBus.on('update_needaction', this, this._updateCounter);
mailBus.on('new_channel', this, this._updateCounter);
mailBus.on('update_thread_unread_counter', this, this._updateCounter);
@@ -235,6 +231,9 @@ var MessagingMenu = Widget.extend({
_updatePreviews: function () {
// Display spinner while waiting for conversations preview
this._$previews.html(QWeb.render('Spinner'));
+ if (!this._isMessagingReady) {
+ return;
+ }
this._getPreviews()
.then(this._renderPreviews.bind(this));
},
@@ -257,7 +256,11 @@ var MessagingMenu = Widget.extend({
* @private
*/
_updateCounter: function () {
+ if (!this._isMessagingReady) {
+ return;
+ }
var counter = this._computeCounter();
+ this.$('.o_mail_messaging_menu_icon').removeClass('fa-spinner fa-spin');
this.$('.o_notification_counter').text(counter);
this.$el.toggleClass('o_no_notification', !counter);
if (this._isShown()) {
@@ -346,6 +349,16 @@ var MessagingMenu = Widget.extend({
var $preview = $(ev.currentTarget).closest('.o_mail_preview');
this._markAsRead($preview);
},
+ /**
+ * @private
+ */
+ _onMessagingReady: function () {
+ if (this._isMessagingReady) {
+ return;
+ }
+ this._isMessagingReady = true;
+ this._updateCounter();
+ },
});
// Systray menu items display order matches order in the list
diff --git a/addons/mail/static/src/js/thread_field.js b/addons/mail/static/src/js/thread_field.js
index ea64d1fc9e3..218a4b552ec 100644
--- a/addons/mail/static/src/js/thread_field.js
+++ b/addons/mail/static/src/js/thread_field.js
@@ -20,23 +20,21 @@ var ThreadField = AbstractField.extend({
*/
init: function () {
this._super.apply(this, arguments);
+ this._isMessagingReady = this.call('mail_service', 'isReady');
+ this._isStarted = false;
+ this.call('mail_service', 'getMailBus').on('messaging_ready', this, this._onMessagingReady);
// Used to automatically mark document thread as read at the moment we
// access the document and render the thread.
this._markAsReadOnNextRender = false;
this._setDocumentThread();
},
- /**
- * @override
- */
- willStart: function () {
- return this.alive(this.call('mail_service', 'isReady'));
- },
/**
* @override
*/
start: function () {
var self = this;
+ this._isStarted = true;
this.dp = new concurrency.DropPrevious();
this._threadWidget = new ThreadWidget(this, {
@@ -160,6 +158,9 @@ var ThreadField = AbstractField.extend({
* If it is a new document in create mode, unset the document thread.
*/
_setDocumentThread: function () {
+ if (!this._isMessagingReady) {
+ return;
+ }
var params = {
messageIDs: this.value.res_ids,
name: this.recordData.display_name,
@@ -186,6 +187,19 @@ var ThreadField = AbstractField.extend({
_onLoadMoreMessages: function () {
this._fetchAndRenderThread({ forceFetch: true });
},
+ /**
+ * @private
+ */
+ _onMessagingReady: function () {
+ if (this._isMessagingReady) {
+ return;
+ }
+ this._isMessagingReady = true;
+ if (!this._isStarted) {
+ return;
+ }
+ this._setDocumentThread();
+ },
/**
* @private
* @param {mail.model.Message}
diff --git a/addons/mail/static/src/scss/discuss.scss b/addons/mail/static/src/scss/discuss.scss
index 21ff765dfdb..d7a01bdf26f 100644
--- a/addons/mail/static/src/scss/discuss.scss
+++ b/addons/mail/static/src/scss/discuss.scss
@@ -7,6 +7,18 @@
height: 100%;
overflow: hidden;
+ .o_mail_discuss_loading {
+ display: flex;
+ flex: 1 1 auto;
+ align-items: center;
+ justify-content: center;
+ min-height: 100%;
+
+ > i {
+ margin-right: 5px;
+ }
+ }
+
.o_mail_discuss_sidebar {
width: $o-mail-chat-sidebar-width;
height: 100%;
diff --git a/addons/mail/static/src/xml/discuss.xml b/addons/mail/static/src/xml/discuss.xml
index 71138ae1f24..3b21d7f230a 100644
--- a/addons/mail/static/src/xml/discuss.xml
+++ b/addons/mail/static/src/xml/discuss.xml
@@ -8,8 +8,15 @@
-->
diff --git a/addons/mail/static/src/xml/systray.xml b/addons/mail/static/src/xml/systray.xml
index dfa1d02b76c..dc275079e28 100644
--- a/addons/mail/static/src/xml/systray.xml
+++ b/addons/mail/static/src/xml/systray.xml
@@ -7,7 +7,7 @@
-
+