Revert "[PATCH] Upstream patch - 25122021"

This commit is contained in:
Parthiv Patel
2021-12-25 09:59:09 +00:00
parent 44ba6871a2
commit 4ac89b776b
1601 changed files with 5190 additions and 7204 deletions

View File

@@ -1,7 +1,7 @@
Odoo Accounting
Flectra Accounting
---------------
The Odoo <a href="https://www.odoo.com/page/accounting">Open Source Accounting</a> app allows a better way to
The Flectra <a href="https://www.flectrahq.com/page/accounting">Open Source Accounting</a> app allows a better way to
collaborate with your accountants, your customers and control your suppliers.
Activate features on demand, from integrated analytic accounting to budget,
@@ -11,7 +11,7 @@ A Smart User Interface
----------------------
Record transactions in a few clicks and easily manage all financial activities
in one place. Odoo's user interface is designed with productivity in mind.
in one place. Flectra's user interface is designed with productivity in mind.
A Better Way To Work Together
-------------------------------
@@ -57,12 +57,12 @@ Everything you need to grow
---------------------------
Manage your assets, track expenses, control budgets, multi-level analytic
accounting; Odoo has all the features you need to sustain all your business
accounting; Flectra has all the features you need to sustain all your business
activities.
Scale With Your Organization
----------------------------
Odoo supports multiple currencies, multiple users with different access rights,
Flectra supports multiple currencies, multiple users with different access rights,
multiple companies with real time consolidation and unlimited analytic plans.

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name' : 'Invoicing',
'version' : '1.1',
@@ -8,12 +8,12 @@
'description': """
Invoicing & Payments
====================
The specific and easy-to-use Invoicing system in Odoo allows you to keep track of your accounting, even when you are not an accountant. It provides an easy way to follow up on your vendors and customers.
The specific and easy-to-use Invoicing system in Flectra allows you to keep track of your accounting, even when you are not an accountant. It provides an easy way to follow up on your vendors and customers.
You could use this simplified accounting in case you work with an (external) account to keep your books, and you still want to keep track of payments. This module also offers you an easy method of registering payments, without having to encode complete abstracts of account.
""",
'category': 'Accounting/Accounting',
'website': 'https://www.odoo.com/page/billing',
'website': 'https://www.flectrahq.com/page/billing',
'images' : ['images/accounts.jpeg','images/bank_statement.jpeg','images/cash_register.jpeg','images/chart_of_accounts.jpeg','images/customer_invoice.jpeg','images/journal_entries.jpeg'],
'depends' : ['base_setup', 'product', 'analytic', 'portal', 'digest'],
'data': [

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import onboarding
from . import portal

View File

@@ -135,7 +135,7 @@ class AccountJournal(models.Model):
compute='_compute_inbound_payment_method_ids',
store=True,
readonly=False,
help="Manual: Get paid by cash, check or any other method outside of Odoo, Flectra.\n"
help="Manual: Get paid by cash, check or any other method outside of Flectra.\n"
"Electronic: Get paid automatically through a payment acquirer by requesting a transaction"
" on a card saved by the customer when buying or subscribing online (payment token).\n"
"Batch Deposit: Encase several customer checks at once by generating a batch deposit to"
@@ -152,8 +152,8 @@ class AccountJournal(models.Model):
compute='_compute_outbound_payment_method_ids',
store=True,
readonly=False,
help="Manual:Pay bill by cash or any other method outside of Odoo, Flectra.\n"
"Check:Pay bill by check and print it from Odoo, Flectra.\n"
help="Manual:Pay bill by cash or any other method outside of Flectra.\n"
"Check:Pay bill by check and print it from Flectra.\n"
"SEPA Credit Transfer: Pay bill from a SEPA Credit Transfer file you submit to your"
" bank. Enable this option from the settings."
)

View File

@@ -131,7 +131,7 @@ class account_journal(models.Model):
data[:0] = [build_graph_data(last_month, amount)]
[graph_title, graph_key] = self._graph_title_and_key()
color = '#875A7B' if 'e' in version else '#7c7bad'
color = '#009EFB' if 'e' in version else '#7c7bad'
is_sample_data = not last_stmt and len(query_result) == 0
if is_sample_data:
@@ -231,9 +231,9 @@ class account_journal(models.Model):
last_balance = last_statement.balance_end
has_at_least_one_statement = bool(last_statement)
bank_account_balance, nb_lines_bank_account_balance = self._get_journal_bank_account_balance(
domain=[('parent_state', '=', 'posted')])
domain=[('move_id.state', '=', 'posted')])
outstanding_pay_account_balance, nb_lines_outstanding_pay_account_balance = self._get_journal_outstanding_payments_account_balance(
domain=[('parent_state', '=', 'posted')])
domain=[('move_id.state', '=', 'posted')])
self._cr.execute('''
SELECT COUNT(st_line.id)

View File

@@ -2124,7 +2124,7 @@ class AccountMove(models.Model):
values['total_amount_currency'] += sign * line.amount_currency
values['total_residual_currency'] += sign * line.amount_residual_currency
elif not line.tax_exigible and not line.reconciled:
elif not line.tax_exigible:
values['to_process_lines'] += line
currencies.add(line.currency_id or line.company_currency_id)
@@ -2594,8 +2594,6 @@ class AccountMove(models.Model):
if not self.env.su and not self.env.user.has_group('account.group_account_invoice'):
raise AccessError(_("You don't have the access rights to post an invoice."))
for move in to_post:
if move.partner_bank_id and not move.partner_bank_id.active:
raise UserError(_("The recipient bank account link to this invoice is archived.\nSo you cannot confirm the invoice."))
if move.state == 'posted':
raise UserError(_('The entry %s (id %s) is already posted.') % (move.name, move.id))
if not move.line_ids.filtered(lambda line: not line.display_type):

View File

@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from lxml import etree
from flectra import models, fields, api, _
from flectra.exceptions import UserError, ValidationError
@@ -45,14 +44,10 @@ class AccountPayment(models.Model):
is_matched = fields.Boolean(string="Is Matched With a Bank Statement", store=True,
compute='_compute_reconciliation_status',
help="Technical field indicating if the payment has been matched with a statement line.")
available_partner_bank_ids = fields.Many2many(
comodel_name='res.partner.bank',
compute='_compute_available_partner_bank_ids',
)
partner_bank_id = fields.Many2one('res.partner.bank', string="Recipient Bank Account",
readonly=False, store=True,
compute='_compute_partner_bank_id',
domain="[('id', 'in', available_partner_bank_ids)]",
domain="[('partner_id', '=', partner_id)]",
check_company=True)
is_internal_transfer = fields.Boolean(string="Is Internal Transfer",
readonly=False, store=True,
@@ -66,9 +61,9 @@ class AccountPayment(models.Model):
readonly=False, store=True,
compute='_compute_payment_method_id',
domain="[('id', 'in', available_payment_method_ids)]",
help="Manual: Get paid by cash, check or any other method outside of Odoo, Flectra.\n"\
help="Manual: Get paid by cash, check or any other method outside of Flectra.\n"\
"Electronic: Get paid automatically through a payment acquirer by requesting a transaction on a card saved by the customer when buying or subscribing online (payment token).\n"\
"Check: Pay bill by check and print it from Odoo, Flectra.\n"\
"Check: Pay bill by check and print it from Flectra.\n"\
"Batch Deposit: Encase several customer checks at once by generating a batch deposit to submit to your bank. When encoding the bank statement in Flectra, you are suggested to reconcile the transaction with the batch deposit.To enable batch deposit, module account_batch_payment must be installed.\n"\
"SEPA Credit Transfer: Pay bill from a SEPA Credit Transfer file you submit to your bank. To enable sepa credit transfer, module account_sepa must be installed ")
available_payment_method_ids = fields.Many2many('account.payment.method',
@@ -337,19 +332,20 @@ class AccountPayment(models.Model):
payment.require_partner_bank_account = payment.state == 'draft' and payment.payment_method_code in self._get_method_codes_needing_bank_account()
@api.depends('partner_id', 'company_id', 'payment_type')
def _compute_available_partner_bank_ids(self):
for pay in self:
if pay.payment_type == 'inbound':
pay.available_partner_bank_ids = pay.journal_id.bank_account_id
else:
pay.available_partner_bank_ids = pay.partner_id.bank_ids\
.filtered(lambda x: x.company_id.id in (False, pay.company_id.id))._origin
@api.depends('available_partner_bank_ids', 'journal_id')
def _compute_partner_bank_id(self):
''' The default partner_bank_id will be the first available on the partner. '''
for pay in self:
pay.partner_bank_id = pay.available_partner_bank_ids[:1]._origin
if pay.payment_type == 'inbound':
bank_partner = pay.company_id.partner_id
else:
bank_partner = pay.partner_id
available_partner_bank_accounts = bank_partner.bank_ids.filtered(lambda x: x.company_id.id in (False, pay.company_id.id))
if available_partner_bank_accounts:
if pay.partner_bank_id not in available_partner_bank_accounts:
pay.partner_bank_id = available_partner_bank_accounts[0]._origin
else:
pay.partner_bank_id = False
@api.depends('partner_id', 'destination_account_id', 'journal_id')
def _compute_is_internal_transfer(self):
@@ -577,29 +573,6 @@ class AccountPayment(models.Model):
# LOW-LEVEL METHODS
# -------------------------------------------------------------------------
@api.model
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
# OVERRIDE to add the 'available_partner_bank_ids' field dynamically inside the view.
# TO BE REMOVED IN MASTER
res = super().fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
if view_type == 'form':
form_view_id = self.env['ir.model.data'].xmlid_to_res_id('account.view_account_payment_form')
if res.get('view_id') == form_view_id:
tree = etree.fromstring(res['arch'])
if len(tree.xpath("//field[@name='available_partner_bank_ids']")) == 0:
# Don't force people to update the account module.
form_view = self.env.ref('account.view_account_payment_form')
arch_tree = etree.fromstring(form_view.arch)
if arch_tree.tag == 'form':
arch_tree.insert(0, etree.Element('field', attrib={
'name': 'available_partner_bank_ids',
'invisible': '1',
}))
form_view.sudo().write({'arch': etree.tostring(arch_tree, encoding='unicode')})
return super().fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
return res
@api.model_create_multi
def create(self, vals_list):
# OVERRIDE

View File

@@ -296,7 +296,6 @@ class AccountReconcileModel(models.Model):
name = ' '.join([x for x in [base_line_dict.get('name', ''), tax_res['name']] if x])
new_aml_dicts.append({
'account_id': tax_res['account_id'] or base_line_dict['account_id'],
'journal_id': base_line_dict.get('journal_id', False),
'name': name,
'partner_id': base_line_dict.get('partner_id'),
'balance': balance,
@@ -650,42 +649,30 @@ class AccountReconcileModel(models.Model):
if partner:
st_line_subquery += r" AND aml.partner_id = %s" % partner.id
else:
st_line_fields_consideration = [
(self.match_text_location_label, 'st_line.payment_ref'),
(self.match_text_location_note, 'st_line_move.narration'),
(self.match_text_location_reference, 'st_line_move.ref'),
]
no_partner_query = " OR ".join([
r"""
st_line_subquery += r"""
AND
(
substring(REGEXP_REPLACE(st_line.payment_ref, '[^0-9\s]', '', 'g'), '\S(?:.*\S)*') != ''
AND
(
substring(REGEXP_REPLACE(""" + sql_field + """, '[^0-9\s]', '', 'g'), '\S(?:.*\S)*') != ''
AND
(
(""" + self._get_select_communication_flag() + """)
OR
(""" + self._get_select_payment_reference_flag() + """)
)
(""" + self._get_select_communication_flag() + """)
OR
(""" + self._get_select_payment_reference_flag() + """)
)
OR
(
/* We also match statement lines without partners with amls
whose partner's name's parts (splitting on space) are all present
within the payment_ref, in any order, with any characters between them. */
)
OR
(
/* We also match statement lines without partners with amls
whose partner's name's parts (splitting on space) are all present
within the payment_ref, in any order, with any characters between them. */
aml_partner.name IS NOT NULL
AND """ + unaccent(sql_field) + r""" ~* ('^' || (
SELECT string_agg(concat('(?=.*\m', chunk[1], '\M)'), '')
FROM regexp_matches(""" + unaccent("aml_partner.name") + r""", '\w{3,}', 'g') AS chunk
))
)
"""
for consider_field, sql_field in st_line_fields_consideration
if consider_field
])
if no_partner_query:
st_line_subquery += " AND " + no_partner_query
aml_partner.name IS NOT NULL
AND """ + unaccent("st_line.payment_ref") + r""" ~* ('^' || (
SELECT string_agg(concat('(?=.*\m', chunk[1], '\M)'), '')
FROM regexp_matches(""" + unaccent("aml_partner.name") + r""", '\w{3,}', 'g') AS chunk
))
)
"""
st_lines_queries.append(r"st_line.id = %s AND (%s)" % (st_line.id, st_line_subquery))

View File

@@ -524,7 +524,7 @@ class AccountTax(models.Model):
price_include = self._context.get('force_price_include', tax.price_include)
#compute the tax_amount
if not skip_checkpoint and price_include and total_included_checkpoints.get(i) and sum_repartition_factor != 0:
if not skip_checkpoint and price_include and total_included_checkpoints.get(i):
# We know the total to reach for that tax, so we make a substraction to avoid any rounding issues
tax_amount = total_included_checkpoints[i] - (base + cumulated_tax_included_amount)
cumulated_tax_included_amount = 0

View File

@@ -166,7 +166,7 @@ class AccountChartTemplate(models.Model):
return self.env['account.account'].create({
'name': _("Bank Suspense Account"),
'code': self.env['account.account']._search_new_account_code(company, code_digits, company.bank_account_code_prefix or ''),
'user_type_id': self.env.ref('account.data_account_type_current_assets').id,
'user_type_id': self.env.ref('account.data_account_type_current_liabilities').id,
'company_id': company.id,
})

View File

@@ -168,17 +168,11 @@ class AccountFiscalPosition(models.Model):
# This can be easily overridden to apply more complex fiscal rules
PartnerObj = self.env['res.partner']
partner = PartnerObj.browse(partner_id)
delivery = PartnerObj.browse(delivery_id)
company = self.env.company
eu_country_codes = set(self.env.ref('base.europe').country_ids.mapped('code'))
intra_eu = vat_exclusion = False
if company.vat and partner.vat:
intra_eu = company.vat[:2] in eu_country_codes and partner.vat[:2] in eu_country_codes
vat_exclusion = company.vat[:2] == partner.vat[:2]
# If company and partner have the same vat prefix (and are both within the EU), use invoicing
if not delivery or (intra_eu and vat_exclusion):
# if no delivery use invoicing
if delivery_id:
delivery = PartnerObj.browse(delivery_id)
else:
delivery = partner
# partner manually set fiscal position always win

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_invoice_report
from . import account_journal

View File

@@ -100,7 +100,7 @@ class AccountInvoiceReport(models.Model):
-line.balance * currency_table.rate AS price_subtotal,
-COALESCE(
-- Average line price
(line.balance / NULLIF(line.quantity, 0.0)) * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END)
(line.balance / NULLIF(line.quantity, 0.0))
-- convert to template uom
* (NULLIF(COALESCE(uom_line.factor, 1), 0.0) / NULLIF(COALESCE(uom_template.factor, 1), 0.0)),
0.0) * currency_table.rate AS price_average,

View File

@@ -12,12 +12,12 @@ class TestAccountIncomingSupplierInvoice(AccountTestInvoicingCommon):
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
cls.env['ir.config_parameter'].sudo().set_param('mail.catchall.domain', 'test-company.flectra.com')
cls.env['ir.config_parameter'].sudo().set_param('mail.catchall.domain', 'test-company.flectrahq.com')
cls.internal_user = cls.env['res.users'].create({
'name': 'Internal User',
'login': 'internal.user@test.flectra.com',
'email': 'internal.user@test.flectra.com',
'login': 'internal.user@test.flectrahq.com',
'email': 'internal.user@test.flectrahq.com',
})
cls.supplier_partner = cls.env['res.partner'].create({

View File

@@ -103,7 +103,6 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
'price_subtotal': vals[1],
'quantity': vals[2],
} for vals in expected_values_list]
self.assertRecordValues(reports, expected_values_dict)
def test_invoice_report_multiple_types(self):
@@ -113,7 +112,7 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
[1000, 1000, 1],
[250, 750, 3],
[6, 6, 1],
[20, -20, -1],
[20, -20, -1],
[600, -600, -1],
[-20, -20, -1],
[-20, -20, -1],
[-600, -600, -1],
])

View File

@@ -1942,121 +1942,6 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
(self.tax_account_1, -20.0, -13.33),
])
def test_reconcile_cash_basis_exchange_difference_transfer_account_check_entries_4(self):
''' Test the generation of the exchange difference for a tax cash basis journal entry when the tax
account is a reconcile one.
'''
currency_id = self.currency_data['currency'].id
cash_basis_transition_account = self.env['account.account'].create({
'code': '209.01.01',
'name': 'Cash Basis Transition Account',
'user_type_id': self.env.ref('account.data_account_type_current_liabilities').id,
'company_id': self.company_data['company'].id,
'reconcile': True,
})
self.cash_basis_tax_a_third_amount.write({
'cash_basis_transition_account_id': cash_basis_transition_account.id,
})
# Rate 1/3 in 2016.
cash_basis_move = self.env['account.move'].create({
'move_type': 'entry',
'date': '2016-01-01',
'line_ids': [
# Base Tax line
(0, 0, {
'debit': 0.0,
'credit': 100.0,
'amount_currency': -300.0,
'currency_id': currency_id,
'account_id': self.company_data['default_account_revenue'].id,
'tax_ids': [(6, 0, self.cash_basis_tax_a_third_amount.ids)],
'tax_exigible': False,
}),
# Tax line
(0, 0, {
'debit': 0.0,
'credit': 33.33,
'amount_currency': -100.0,
'currency_id': currency_id,
'account_id': cash_basis_transition_account.id,
'tax_repartition_line_id': self.cash_basis_tax_a_third_amount.invoice_repartition_line_ids.filtered(lambda line: line.repartition_type == 'tax').id,
'tax_exigible': False,
}),
# Receivable lines
(0, 0, {
'debit': 133.33,
'credit': 0.0,
'amount_currency': 400.0,
'currency_id': currency_id,
'account_id': self.extra_receivable_account_1.id,
}),
]
})
# Rate 1/2 in 2017.
payment_move = self.env['account.move'].create({
'move_type': 'entry',
'date': '2017-01-01',
'line_ids': [
(0, 0, {
'debit': 0.0,
'credit': 200.0,
'amount_currency': -400.0,
'currency_id': currency_id,
'account_id': self.extra_receivable_account_1.id,
}),
(0, 0, {
'debit': 200.0,
'credit': 0.0,
'amount_currency': 400.0,
'currency_id': currency_id,
'account_id': self.company_data['default_account_revenue'].id,
}),
]
})
(cash_basis_move + payment_move).action_post()
self.assertAmountsGroupByAccount([
# Account Balance Amount Currency
(cash_basis_transition_account, -33.33, -100.0),
(self.tax_account_1, 0.0, 0.0),
])
receivable_lines = (cash_basis_move + payment_move).line_ids\
.filtered(lambda line: line.account_id == self.extra_receivable_account_1)
res = receivable_lines.reconcile()
self.assertEqual(len(res.get('tax_cash_basis_moves', [])), 1)
# Tax values based on payment
# Invoice amount 300 (amount currency) with payment rate 2 (400 payment amount divided by 200 invoice balance)
# - Base amount: 150 company currency
# - Tax amount: 50 company currency
self.assertRecordValues(res['tax_cash_basis_moves'].line_ids, [
# Base amount:
{'debit': 150.0, 'credit': 0.0, 'amount_currency': 300.0, 'currency_id': currency_id, 'account_id': self.cash_basis_base_account.id},
{'debit': 0.0, 'credit': 150.0, 'amount_currency': -300.0, 'currency_id': currency_id, 'account_id': self.cash_basis_base_account.id},
# tax:
{'debit': 50.0, 'credit': 0.0, 'amount_currency': 100.0, 'currency_id': currency_id, 'account_id': cash_basis_transition_account.id},
{'debit': 0.0, 'credit': 50.0, 'amount_currency': -100.0, 'currency_id': currency_id, 'account_id': self.tax_account_1.id},
])
exchange_diff = res['full_reconcile'].exchange_move_id
# Exchange difference
# 66.67 amount residual on the payment line after reconciling receivable line of the cash basis move with the payment counterpart
# 50.00 difference of the cash_basis_move base line and the CABA entry created by the system
self.assertRecordValues(exchange_diff.line_ids, [
{'debit': 66.67, 'credit': 0.0, 'currency_id': currency_id, 'account_id': self.extra_receivable_account_1.id},
{'debit': 0.0, 'credit': 66.67, 'currency_id': currency_id, 'account_id': self.company_data['company'].income_currency_exchange_account_id.id},
{'debit': 50.0, 'credit': 0.0, 'currency_id': currency_id, 'account_id': self.cash_basis_base_account.id},
{'debit': 0.0, 'credit': 50.0, 'currency_id': currency_id, 'account_id': self.cash_basis_base_account.id},
])
def test_reconcile_cash_basis_revert(self):
''' Ensure the cash basis journal entry can be reverted. '''
self.cash_basis_transfer_account.reconcile = True

View File

@@ -14,9 +14,6 @@ class TestAccountPayment(AccountTestInvoicingCommon):
cls.payment_debit_account_id = cls.copy_account(cls.company_data['default_journal_bank'].payment_debit_account_id)
cls.payment_credit_account_id = cls.copy_account(cls.company_data['default_journal_bank'].payment_credit_account_id)
cls.bank_journal_1 = cls.company_data['default_journal_bank']
cls.bank_journal_2 = cls.company_data['default_journal_bank'].copy()
cls.partner_bank_account1 = cls.env['res.partner.bank'].create({
'acc_number': "0123456789",
'partner_id': cls.partner_a.id,
@@ -27,18 +24,13 @@ class TestAccountPayment(AccountTestInvoicingCommon):
'partner_id': cls.partner_a.id,
'acc_type': 'bank',
})
cls.comp_bank_account1 = cls.env['res.partner.bank'].create({
cls.comp_bank_account = cls.env['res.partner.bank'].create({
'acc_number': "985632147",
'partner_id': cls.env.company.partner_id.id,
'acc_type': 'bank',
})
cls.comp_bank_account2 = cls.env['res.partner.bank'].create({
'acc_number': "741258963",
'partner_id': cls.env.company.partner_id.id,
'acc_type': 'bank',
})
cls.bank_journal_1.write({
cls.company_data['default_journal_bank'].write({
'payment_debit_account_id': cls.payment_debit_account_id.id,
'payment_credit_account_id': cls.payment_credit_account_id.id,
'inbound_payment_method_ids': [(6, 0, cls.env.ref('account.account_payment_method_manual_in').ids)],
@@ -774,34 +766,17 @@ class TestAccountPayment(AccountTestInvoicingCommon):
},
])
def test_suggested_default_partner_bank(self):
""" Ensure the 'partner_bank_id' is well computed on payments. When the payment is inbound, the money must be
received by a bank account linked to the company. In case of outbound payment, the bank account must be found
on the partner.
def test_payment_partner_bank_inbound(self):
""" Test the bank account is well recomputed for inbound payments. In that case, the recipient
bank account must be the one set on the company.
"""
payment = self.env['account.payment'].create({
'journal_id': self.bank_journal_1.id,
'amount': 50.0,
'payment_type': 'outbound',
'partner_type': 'supplier',
'partner_id': self.partner_a.id,
})
self.assertRecordValues(payment, [{
'available_partner_bank_ids': self.partner_a.bank_ids.ids,
'partner_bank_id': self.partner_bank_account1.id,
}])
self.assertRecordValues(payment, [{'partner_bank_id': self.partner_bank_account1.id}])
payment.payment_type = 'inbound'
self.assertRecordValues(payment, [{
'available_partner_bank_ids': [],
'partner_bank_id': False,
}])
self.bank_journal_2.bank_account_id = self.comp_bank_account2
# A sequence is automatically added on the first move. We need to clean it before changing the journal.
payment.name = False
payment.journal_id = self.bank_journal_2
self.assertRecordValues(payment, [{
'available_partner_bank_ids': self.comp_bank_account2.ids,
'partner_bank_id': self.comp_bank_account2.id,
}])
self.assertRecordValues(payment, [{'partner_bank_id': self.comp_bank_account.id}])

View File

@@ -10,7 +10,7 @@ class TestAccountPaymentRegister(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
cls.currency_data_3 = cls.setup_multi_currency_data({
'name': "Umbrella",
'symbol': '',
@@ -35,10 +35,7 @@ class TestAccountPaymentRegister(AccountTestInvoicingCommon):
})
cls.manual_payment_method_out = cls.env.ref('account.account_payment_method_manual_out')
cls.bank_journal_1 = cls.company_data['default_journal_bank']
cls.bank_journal_2 = cls.company_data['default_journal_bank'].copy()
cls.bank_journal_1.write({
cls.company_data['default_journal_bank'].write({
'payment_debit_account_id': cls.payment_debit_account_id.id,
'payment_credit_account_id': cls.payment_credit_account_id.id,
'inbound_payment_method_ids': [(6, 0, (
@@ -52,16 +49,11 @@ class TestAccountPaymentRegister(AccountTestInvoicingCommon):
))],
})
cls.partner_bank_account1 = cls.env['res.partner.bank'].create({
cls.partner_bank_account = cls.env['res.partner.bank'].create({
'acc_number': "0123456789",
'partner_id': cls.partner_a.id,
'acc_type': 'bank',
})
cls.partner_bank_account2 = cls.env['res.partner.bank'].create({
'acc_number': "9876543210",
'partner_id': cls.partner_a.id,
'acc_type': 'bank',
})
cls.comp_bank_account1 = cls.env['res.partner.bank'].create({
'acc_number': "985632147",
'partner_id': cls.env.company.partner_id.id,
@@ -485,9 +477,6 @@ class TestAccountPaymentRegister(AccountTestInvoicingCommon):
''' Choose to pay multiple batches, one with two customer invoices (1000 + 2000)
and one with a vendor bill of 600, by splitting payments.
'''
self.in_invoice_1.partner_bank_id = self.partner_bank_account1
self.in_invoice_2.partner_bank_id = self.partner_bank_account2
active_ids = (self.in_invoice_1 + self.in_invoice_2 + self.in_invoice_3).ids
payments = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=active_ids).create({
'group_payment': False,
@@ -495,22 +484,16 @@ class TestAccountPaymentRegister(AccountTestInvoicingCommon):
self.assertRecordValues(payments, [
{
'journal_id': self.bank_journal_1.id,
'ref': 'BILL/2017/01/0001',
'payment_method_id': self.manual_payment_method_out.id,
'partner_bank_id': self.partner_bank_account1.id,
},
{
'journal_id': self.bank_journal_1.id,
'ref': 'BILL/2017/01/0002',
'payment_method_id': self.manual_payment_method_out.id,
'partner_bank_id': self.partner_bank_account2.id,
},
{
'journal_id': self.bank_journal_1.id,
'ref': 'BILL/2017/01/0003',
'payment_method_id': self.manual_payment_method_out.id,
'partner_bank_id': False,
},
])
self.assertRecordValues(payments[0].line_ids.sorted('balance') + payments[1].line_ids.sorted('balance') + payments[2].line_ids.sorted('balance'), [
@@ -567,6 +550,27 @@ class TestAccountPaymentRegister(AccountTestInvoicingCommon):
},
])
def test_register_payment_custom_bank_account(self):
""" Ensure the user is able to select a custom bank account when registering a payment and this bank account
lands correctly on the generated payment.
"""
self.out_invoice_1.partner_bank_id = self.comp_bank_account1
ctx = {'active_model': 'account.move', 'active_ids': self.out_invoice_1.ids}
wizard_form = Form(self.env['account.payment.register'].with_context(**ctx))
wizard = wizard_form.save()
# The bank account set on the invoice must be the default suggested value.
self.assertRecordValues(wizard, [{'partner_bank_id': self.comp_bank_account1.id}])
wizard_form = Form(wizard)
wizard_form.partner_bank_id = self.comp_bank_account2
wizard = wizard_form.save()
payments = wizard._create_payments()
# The user should be able to set a custom bank account.
self.assertRecordValues(payments, [{'partner_bank_id': self.comp_bank_account2.id}])
def test_register_payment_constraints(self):
# Test to register a payment for a draft journal entry.
self.out_invoice_1.button_draft()
@@ -831,82 +835,3 @@ class TestAccountPaymentRegister(AccountTestInvoicingCommon):
'reconciled': False,
},
])
def test_suggested_default_partner_bank_inbound_payment(self):
""" Test the suggested bank account on the wizard for inbound payment. """
self.out_invoice_1.partner_bank_id = False
ctx = {'active_model': 'account.move', 'active_ids': self.out_invoice_1.ids}
wizard = self.env['account.payment.register'].with_context(**ctx).create({})
self.assertRecordValues(wizard, [{
'journal_id': self.bank_journal_1.id,
'available_partner_bank_ids': [],
'partner_bank_id': False,
}])
self.bank_journal_2.bank_account_id = self.out_invoice_1.partner_bank_id = self.comp_bank_account2
wizard = self.env['account.payment.register'].with_context(**ctx).create({})
self.assertRecordValues(wizard, [{
'journal_id': self.bank_journal_2.id,
'available_partner_bank_ids': self.comp_bank_account2.ids,
'partner_bank_id': self.comp_bank_account2.id,
}])
wizard.journal_id = self.bank_journal_1
self.assertRecordValues(wizard, [{
'journal_id': self.bank_journal_1.id,
'available_partner_bank_ids': [],
'partner_bank_id': False,
}])
def test_suggested_default_partner_bank_outbound_payment(self):
""" Test the suggested bank account on the wizard for outbound payment. """
self.in_invoice_1.partner_bank_id = False
ctx = {'active_model': 'account.move', 'active_ids': self.in_invoice_1.ids}
wizard = self.env['account.payment.register'].with_context(**ctx).create({})
self.assertRecordValues(wizard, [{
'journal_id': self.bank_journal_1.id,
'available_partner_bank_ids': self.partner_a.bank_ids.ids,
'partner_bank_id': self.partner_bank_account1.id,
}])
self.in_invoice_1.partner_bank_id = self.partner_bank_account2
wizard = self.env['account.payment.register'].with_context(**ctx).create({})
self.assertRecordValues(wizard, [{
'journal_id': self.bank_journal_1.id,
'available_partner_bank_ids': self.partner_a.bank_ids.ids,
'partner_bank_id': self.partner_bank_account2.id,
}])
wizard.journal_id = self.bank_journal_2
self.assertRecordValues(wizard, [{
'journal_id': self.bank_journal_2.id,
'available_partner_bank_ids': self.partner_a.bank_ids.ids,
'partner_bank_id': self.partner_bank_account2.id,
}])
def test_register_payment_inbound_multiple_bank_account(self):
""" Pay customer invoices with different bank accounts. """
self.out_invoice_1.partner_bank_id = self.comp_bank_account1
self.out_invoice_2.partner_bank_id = self.comp_bank_account2
self.bank_journal_2.bank_account_id = self.comp_bank_account2
ctx = {'active_model': 'account.move', 'active_ids': (self.out_invoice_1 + self.out_invoice_2).ids}
wizard = self.env['account.payment.register'].with_context(**ctx).create({'journal_id': self.bank_journal_2.id})
payments = wizard._create_payments()
self.assertRecordValues(payments, [
{
'journal_id': self.bank_journal_2.id,
'ref': 'INV/2017/01/0001',
'payment_method_id': self.manual_payment_method_in.id,
'partner_bank_id': self.comp_bank_account2.id,
},
{
'journal_id': self.bank_journal_2.id,
'ref': 'INV/2017/01/0002',
'payment_method_id': self.manual_payment_method_in.id,
'partner_bank_id': self.comp_bank_account2.id,
},
])

View File

@@ -258,51 +258,6 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
self.bank_line_5.id: {'aml_ids': [self.invoice_line_6.id], 'model': self.rule_1, 'partner': self.bank_line_5.partner_id},
}, statements=self.bank_st_2)
def test_matching_fields_match_text_location_no_partner(self):
self.bank_line_2.unlink() # One line is enough for this test
self.bank_line_1.partner_id = None
self.partner_1.name = "Bernard Gagnant"
self.rule_1.write({
'match_partner': False,
'match_partner_ids': [(5, 0, 0)],
'line_ids': [(5, 0, 0)],
})
st_line_initial_vals = {'ref': None, 'payment_ref': 'nothing', 'narration': None}
recmod_initial_vals = {'match_text_location_label': False, 'match_text_location_note': False, 'match_text_location_reference': False}
rec_mod_options_to_fields = {
'match_text_location_label': 'payment_ref',
'match_text_location_note': 'narration',
'match_text_location_reference': 'ref',
}
for rec_mod_field, st_line_field in rec_mod_options_to_fields.items():
self.rule_1.write({**recmod_initial_vals, rec_mod_field: True})
# Fully reinitialize the statement line
self.bank_line_1.write(st_line_initial_vals)
# Nothing should match
self._check_statement_matching(self.rule_1, {
self.bank_line_1.id: {'aml_ids': []},
}, statements=self.bank_st)
# Test matching with the invoice ref
self.bank_line_1.write({st_line_field: self.invoice_line_1.move_id.payment_reference})
self._check_statement_matching(self.rule_1, {
self.bank_line_1.id: {'aml_ids': self.invoice_line_1.ids, 'model': self.rule_1, 'partner': self.env['res.partner']},
}, statements=self.bank_st)
# Test matching with the partner name (reinitializing the statement line first)
self.bank_line_1.write({**st_line_initial_vals, st_line_field: self.partner_1.name})
self._check_statement_matching(self.rule_1, {
self.bank_line_1.id: {'aml_ids': self.invoice_line_1.ids, 'model': self.rule_1, 'partner': self.env['res.partner']},
}, statements=self.bank_st)
def test_matching_fields_match_journal_ids(self):
self.rule_1.match_journal_ids |= self.cash_st.journal_id
self._check_statement_matching(self.rule_1, {

View File

@@ -1073,61 +1073,3 @@ class TestTax(TestTaxCommon):
],
(tax_10_fix + tax_21).compute_all(1210),
)
def test_price_included_repartition_sum_0(self):
""" Tests the case where a tax with a non-zero value has a sum
of tax repartition factors of zero and is included in price. It
shouldn't behave in the same way as a 0% tax.
"""
test_tax = self.env['account.tax'].create({
'name': "Definitely not a 0% tax",
'amount_type': 'percent',
'amount': 42,
'price_include': True,
'invoice_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
}),
(0,0, {
'factor_percent': -100,
'repartition_type': 'tax',
}),
],
'refund_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
}),
(0,0, {
'factor_percent': -100,
'repartition_type': 'tax',
}),
],
})
compute_all_res = test_tax.compute_all(100)
self._check_compute_all_results(
100, # 'total_included'
100, # 'total_excluded'
[
# base , amount
# ---------------
(100, 42),
(100, -42),
# ---------------
],
compute_all_res
)

View File

@@ -332,18 +332,18 @@
<field name="tax_line_id" string="Originator Tax"/>
<field name="reconcile_model_id"/>
<separator/>
<filter string="Unposted" name="unposted" domain="[('parent_state', '=', 'draft')]" help="Unposted Journal Items"/>
<filter string="Posted" name="posted" domain="[('parent_state', '=', 'posted')]" help="Posted Journal Items"/>
<filter string="Unposted" name="unposted" domain="[('move_id.state', '=', 'draft')]" help="Unposted Journal Items"/>
<filter string="Posted" name="posted" domain="[('move_id.state', '=', 'posted')]" help="Posted Journal Items"/>
<separator/>
<filter string="To Check" name="to_check" domain="[('move_id.to_check', '=', True)]"/>
<separator/>
<filter string="Unreconciled" domain="[('full_reconcile_id', '=', False), ('balance', '!=', 0), ('account_id.reconcile', '=', True)]" help="Journal items where matching number isn't set" name="unreconciled"/>
<separator/>
<filter string="Sales" name="sales" domain="[('journal_id.type', '=', 'sale')]" context="{'default_journal_type': 'sale'}"/>
<filter string="Purchases" name="purchases" domain="[('journal_id.type', '=', 'purchase')]" context="{'default_journal_type': 'purchase'}"/>
<filter string="Bank" name="bank" domain="[('journal_id.type', '=', 'bank')]" context="{'default_journal_type': 'bank'}"/>
<filter string="Cash" name="cash" domain="[('journal_id.type', '=', 'cash')]" context="{'default_journal_type': 'cash'}"/>
<filter string="Miscellaneous" domain="[('journal_id.type', '=', 'general')]" name="misc_filter" context="{'default_journal_type': 'general'}"/>
<filter string="Sales" name="sales" domain="[('move_id.journal_id.type', '=', 'sale')]" context="{'default_journal_type': 'sale'}"/>
<filter string="Purchases" name="purchases" domain="[('move_id.journal_id.type', '=', 'purchase')]" context="{'default_journal_type': 'purchase'}"/>
<filter string="Bank" name="bank" domain="[('move_id.journal_id.type', '=', 'bank')]" context="{'default_journal_type': 'bank'}"/>
<filter string="Cash" name="cash" domain="[('move_id.journal_id.type', '=', 'cash')]" context="{'default_journal_type': 'cash'}"/>
<filter string="Miscellaneous" domain="[('move_id.journal_id.type', '=', 'general')]" name="misc_filter" context="{'default_journal_type': 'general'}"/>
<separator/>
<filter string="Payable" domain="[('account_id.internal_type', '=', 'payable')]" help="From Payable accounts" name="payable"/>
<filter string="Receivable" domain="[('account_id.internal_type', '=', 'receivable')]" help="From Receivable accounts" name="receivable"/>
@@ -1300,7 +1300,7 @@
<field name="context">{'journal_type':'general', 'search_default_posted':1}</field>
<field name="name">Journal Items</field>
<field name="res_model">account.move.line</field>
<field name="domain">[('display_type', 'not in', ('line_section', 'line_note')), ('parent_state', '!=', 'cancel')]</field>
<field name="domain">[('display_type', 'not in', ('line_section', 'line_note')), ('move_id.state', '!=', 'cancel')]</field>
<field name="view_id" ref="view_move_line_tree"/>
<field name="view_mode">tree,pivot,graph,form,kanban</field>
</record>

View File

@@ -158,7 +158,6 @@
<field name="show_partner_bank_account" invisible="1"/>
<field name="require_partner_bank_account" invisible="1"/>
<field name="hide_payment_method" invisible="1"/>
<field name="available_partner_bank_ids" invisible="1"/>
<field name="available_payment_method_ids" invisible="1"/>
<field name="suitable_journal_ids" invisible="1"/>
<field name="country_code" invisible="1"/>

View File

@@ -156,7 +156,7 @@
attrs="{'invisible': [('match_partner', '=', False)]}"/>
</group>
<group attrs="{'invisible': [('rule_type', '!=', 'invoice_matching')]}">
<span class="o_form_label o_td_label">Match Invoice/bill with</span>
<label for="match_text_location_label" string="Match Invoice/bill with"/>
<div>
<span class="o_form_label" style="width: 2% !important"> </span>
<label for="match_text_location_label" string="Label"/>

View File

@@ -99,7 +99,7 @@
</div>
<div class="o_setting_right_pane" name="l10n_eu_service_right_pane">
<label for="module_l10n_eu_service"/>
<a href="https://www.flectra.com/documentation/14.0/applications/finance/accounting/taxation/taxes/eu_distance_selling.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<a href="https://doc.flectrahq.com/2.0/applications/finance/accounting/taxation/taxes/eu_distance_selling.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<div class="text-muted">
Apply VAT of the EU country to which goods and services are delivered.
</div>

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_automatic_entry_wizard

View File

@@ -82,9 +82,9 @@ class AccountPaymentRegister(models.TransientModel):
readonly=False, store=True,
compute='_compute_payment_method_id',
domain="[('id', 'in', available_payment_method_ids)]",
help="Manual: Get paid by cash, check or any other method outside of Odoo, Flectra.\n"\
help="Manual: Get paid by cash, check or any other method outside of Flectra.\n"\
"Electronic: Get paid automatically through a payment acquirer by requesting a transaction on a card saved by the customer when buying or subscribing online (payment token).\n"\
"Check: Pay bill by check and print it from Odoo, Flectra.\n"\
"Check: Pay bill by check and print it from Flectra.\n"\
"Batch Deposit: Encase several customer checks at once by generating a batch deposit to submit to your bank. When encoding the bank statement in Flectra, you are suggested to reconcile the transaction with the batch deposit.To enable batch deposit, module account_batch_payment must be installed.\n"\
"SEPA Credit Transfer: Pay bill from a SEPA Credit Transfer file you submit to your bank. To enable sepa credit transfer, module account_sepa must be installed ")
available_payment_method_ids = fields.Many2many('account.payment.method',
@@ -127,58 +127,6 @@ class AccountPaymentRegister(models.TransientModel):
labels = set(line.name or line.move_id.ref or line.move_id.name for line in batch_result['lines'])
return ' '.join(sorted(labels))
@api.model
def _get_batch_journal(self, batch_result):
""" Helper to compute the journal based on the batch.
:param batch_result: A batch returned by '_get_batches'.
:return: An account.journal record.
"""
key_values = batch_result['key_values']
foreign_currency_id = key_values['currency_id']
partner_bank_id = key_values['partner_bank_id']
currency_domain = [('currency_id', '=', foreign_currency_id)]
partner_bank_domain = [('bank_account_id', '=', partner_bank_id)]
default_domain = [
('type', 'in', ('bank', 'cash')),
('company_id', '=', batch_result['lines'].company_id.id),
]
if partner_bank_id:
extra_domains = (
currency_domain + partner_bank_domain,
partner_bank_domain,
currency_domain,
[],
)
else:
extra_domains = (
currency_domain,
[],
)
for extra_domain in extra_domains:
journal = self.env['account.journal'].search(default_domain + extra_domain, limit=1)
if journal:
return journal
return self.env['account.journal']
@api.model
def _get_batch_available_partner_banks(self, batch_result, journal):
key_values = batch_result['key_values']
company = batch_result['lines'].company_id
# A specific bank account is set on the journal. The user must use this one.
if key_values['payment_type'] == 'inbound':
# Receiving money on a bank account linked to the journal.
return journal.bank_account_id
else:
# Sending money to a bank account owned by a partner.
return batch_result['lines'].partner_id.bank_ids.filtered(lambda x: x.company_id.id in (False, company.id))._origin
@api.model
def _get_line_batch_key(self, line):
''' Turn the line passed as parameter to a dictionary defining on which way the lines
@@ -186,15 +134,15 @@ class AccountPaymentRegister(models.TransientModel):
:return: A python dictionary.
'''
move = line.move_id
partner_bank_account = self.env['res.partner.bank']
if move.is_invoice(include_receipts=True):
partner_bank_account = move.partner_bank_id._origin
return {
'partner_id': line.partner_id.id,
'account_id': line.account_id.id,
'currency_id': line.currency_id.id,
'currency_id': (line.currency_id or line.company_currency_id).id,
'partner_bank_id': partner_bank_account.id,
'partner_type': 'customer' if line.account_internal_type == 'receivable' else 'supplier',
'payment_type': 'inbound' if line.balance > 0.0 else 'outbound',
@@ -225,7 +173,6 @@ class AccountPaymentRegister(models.TransientModel):
'lines': self.env['account.move.line'],
})
batches[serialized_key]['lines'] += line
return list(batches.values())
@api.model
@@ -280,6 +227,7 @@ class AccountPaymentRegister(models.TransientModel):
'partner_id': False,
'partner_type': False,
'payment_type': wizard_values_from_batch['payment_type'],
'partner_bank_id': False,
'source_currency_id': False,
'source_amount': False,
'source_amount_currency': False,
@@ -308,40 +256,39 @@ class AccountPaymentRegister(models.TransientModel):
else:
wizard.group_payment = False
@api.depends('can_edit_wizard', 'company_id')
@api.depends('company_id', 'source_currency_id')
def _compute_journal_id(self):
for wizard in self:
if wizard.can_edit_wizard:
batch = wizard._get_batches()[0]
wizard.journal_id = wizard._get_batch_journal(batch)
else:
wizard.journal_id = self.env['account.journal'].search([
('type', 'in', ('bank', 'cash')),
('company_id', '=', wizard.company_id.id),
], limit=1)
domain = [
('type', 'in', ('bank', 'cash')),
('company_id', '=', wizard.company_id.id),
]
journal = None
if wizard.source_currency_id:
journal = self.env['account.journal'].search(domain + [('currency_id', '=', wizard.source_currency_id.id)], limit=1)
if not journal:
journal = self.env['account.journal'].search(domain, limit=1)
wizard.journal_id = journal
@api.depends('can_edit_wizard', 'journal_id')
@api.depends('company_id', 'can_edit_wizard')
def _compute_available_partner_bank_ids(self):
for wizard in self:
if wizard.can_edit_wizard:
batch = wizard._get_batches()[0]
wizard.available_partner_bank_ids = wizard._get_batch_available_partner_banks(batch, wizard.journal_id)
batches = wizard._get_batches()
bank_partners = batches[0]['lines'].move_id.bank_partner_id
wizard.available_partner_bank_ids = bank_partners.bank_ids\
.filtered(lambda x: x.company_id.id in (False, wizard.company_id.id))._origin
else:
wizard.available_partner_bank_ids = None
wizard.available_partner_bank_ids = False
@api.depends('journal_id', 'available_partner_bank_ids')
@api.depends('available_partner_bank_ids')
def _compute_partner_bank_id(self):
for wizard in self:
if wizard.can_edit_wizard:
batch = wizard._get_batches()[0]
partner_bank_id = batch['key_values']['partner_bank_id']
available_partner_banks = wizard.available_partner_bank_ids._origin
if partner_bank_id and partner_bank_id in available_partner_banks.ids:
wizard.partner_bank_id = self.env['res.partner.bank'].browse(partner_bank_id)
else:
wizard.partner_bank_id = available_partner_banks[:1]
batches = wizard._get_batches()
wizard.partner_bank_id = self.env['res.partner.bank'].browse(batches[0]['key_values']['partner_bank_id'])
else:
wizard.partner_bank_id = None
wizard.partner_bank_id = False
@api.depends('journal_id')
def _compute_currency_id(self):
@@ -432,7 +379,7 @@ class AccountPaymentRegister(models.TransientModel):
'name': 'available_partner_bank_ids',
'invisible': '1',
}))
form_view.sudo().write({'arch': etree.tostring(arch_tree, encoding='unicode')})
form_view.arch = etree.tostring(arch_tree, encoding='unicode')
return super().fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
return res
@@ -480,7 +427,7 @@ class AccountPaymentRegister(models.TransientModel):
raise UserError(_("You can't register payments for journal items being either all inbound, either all outbound."))
res['line_ids'] = [(6, 0, available_lines.ids)]
return res
# -------------------------------------------------------------------------
@@ -512,12 +459,6 @@ class AccountPaymentRegister(models.TransientModel):
def _create_payment_vals_from_batch(self, batch_result):
batch_values = self._get_wizard_values_from_batch(batch_result)
if batch_values['payment_type'] == 'inbound':
partner_bank_id = self.journal_id.bank_account_id.id
else:
partner_bank_id = batch_result['key_values']['partner_bank_id']
return {
'date': self.payment_date,
'amount': batch_values['source_amount_currency'],
@@ -527,7 +468,7 @@ class AccountPaymentRegister(models.TransientModel):
'journal_id': self.journal_id.id,
'currency_id': batch_values['source_currency_id'],
'partner_id': batch_values['partner_id'],
'partner_bank_id': partner_bank_id,
'partner_bank_id': batch_result['key_values']['partner_bank_id'],
'payment_method_id': self.payment_method_id.id,
'destination_account_id': batch_result['lines'][0].account_id.id
}

View File

@@ -13,7 +13,7 @@ class FinancialYearOpeningWizard(models.TransientModel):
company_id = fields.Many2one(comodel_name='res.company', required=True)
opening_move_posted = fields.Boolean(string='Opening Move Posted', compute='_compute_opening_move_posted')
opening_date = fields.Date(string='Opening Date', required=True, related='company_id.account_opening_date', help="Date from which the accounting is managed in Odoo, Flectra. It is the date of the opening entry.", readonly=False)
opening_date = fields.Date(string='Opening Date', required=True, related='company_id.account_opening_date', help="Date from which the accounting is managed in Flectra. It is the date of the opening entry.", readonly=False)
fiscalyear_last_day = fields.Integer(related="company_id.fiscalyear_last_day", required=True, readonly=False,
help="The last day of the month will be used if the chosen day doesn't exist.")
fiscalyear_last_month = fields.Selection(related="company_id.fiscalyear_last_month", readonly=False,

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models
from . import wizard

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Check Printing Base',

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_journal
from . import account_move

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="70" height="70" viewBox="0 0 70 70"><defs><path id="a" d="M4 0h61c4 0 5 1 5 5v60c0 4-1 5-5 5H4c-3 0-4-1-4-5V5c0-4 1-5 4-5z"/><linearGradient id="c" x1="100%" x2="0%" y1="0%" y2="100%"><stop offset="0%" stop-color="#DA956B"/><stop offset="100%" stop-color="#CC7039"/></linearGradient><path id="d" d="M50.25 52.79l-3.61-3.11v-8.95H24.347v14.439H42.08l2.882 3.243h-21.43c-.985 0-1.782-.785-1.782-1.754v-13.59h-3.86a.884.884 0 0 1-.89-.877v-9.648c0-1.938 1.595-3.509 3.563-3.509h1.187v-12.28c0-.969.797-1.754 1.781-1.754h20.637c.473 0 .926.185 1.26.514l4.3 4.235c.334.329.522.775.522 1.24v8.045h1.188c1.967 0 3.562 1.571 3.562 3.509v9.648a.884.884 0 0 1-.89.877h-3.86v9.723zm-21.926-7.05c0 1.41 4.636 1.052 4.636 3.734 0 1.284-1.015 2.381-2.664 2.61v1.063c0 .148-.135.268-.301.268h-1.004c-.166 0-.3-.12-.3-.268v-1.08c-.992-.151-1.875-.56-2.478-1.075a.248.248 0 0 1-.033-.355l.762-.911a.326.326 0 0 1 .431-.048c.625.448 1.433.804 2.204.804.899 0 1.308-.478 1.308-.922 0-1.313-4.636-1.028-4.636-3.796 0-1.18.97-2.136 2.441-2.433v-1.117c0-.148.135-.268.301-.268h1.004c.166 0 .301.12.301.268v1.059c.807.083 1.681.365 2.29.847.105.082.132.219.065.328l-.59.976c-.087.143-.294.185-.442.09-.56-.36-1.248-.635-1.918-.635-.836 0-1.377.338-1.377.86zm-3.977-14.367H46.64v-8.14H43.6c-.676-.022-1.013-.354-1.013-.998v-2.923l-18.24-.07v12.131zm24.715 5.263c.984 0 1.782-.785 1.782-1.754 0-.97-.798-1.755-1.782-1.755-.983 0-1.78.786-1.78 1.755 0 .969.797 1.754 1.78 1.754zm-7.031 12.698c1.61.343 2.64.782 3.089 1.317l5.773 6.88-2.328 1.954-5.774-6.88c-.34-.404-.592-1.495-.76-3.27zm7.072 10.736l2.33-1.954 1.282 1.529c.428.51.383.982-.135 1.416l-.776.651c-.517.434-.99.397-1.418-.113l-1.283-1.529zm.494-5.272l.01-.009a.5.5 0 0 1 .704.062l2.334 2.781a.5.5 0 0 1-.061.705l-.01.008a.5.5 0 0 1-.705-.061l-2.334-2.782a.5.5 0 0 1 .062-.704zM35 44h9v.998h-9V44zm0 3h9v.998h-9V47z"/><path id="e" d="M50.25 50.79l-3.61-3.11v-8.95H24.347v14.439H42.08l2.882 3.243h-21.43c-.985 0-1.782-.785-1.782-1.754v-13.59h-3.86a.884.884 0 0 1-.89-.877v-9.648c0-1.938 1.595-3.509 3.563-3.509h1.187v-12.28c0-.969.797-1.754 1.781-1.754h20.637c.473 0 .926.185 1.26.514l4.3 4.235c.334.329.522.775.522 1.24v8.045h1.188c1.967 0 3.562 1.571 3.562 3.509v9.648a.884.884 0 0 1-.89.877h-3.86v9.723zm-21.926-7.05c0 1.41 4.636 1.052 4.636 3.734 0 1.284-1.015 2.381-2.664 2.61v1.063c0 .148-.135.268-.301.268h-1.004c-.166 0-.3-.12-.3-.268v-1.08c-.992-.151-1.875-.56-2.478-1.075a.248.248 0 0 1-.033-.355l.762-.911a.326.326 0 0 1 .431-.048c.625.448 1.433.804 2.204.804.899 0 1.308-.478 1.308-.922 0-1.313-4.636-1.028-4.636-3.796 0-1.18.97-2.136 2.441-2.433v-1.117c0-.148.135-.268.301-.268h1.004c.166 0 .301.12.301.268v1.059c.807.083 1.681.365 2.29.847.105.082.132.219.065.328l-.59.976c-.087.143-.294.185-.442.09-.56-.36-1.248-.635-1.918-.635-.836 0-1.377.338-1.377.86zm-3.977-14.367H46.64v-8.14H43.6c-.676-.022-1.013-.354-1.013-.998v-2.923l-18.24-.07v12.131zm24.715 5.263c.984 0 1.782-.785 1.782-1.754 0-.97-.798-1.755-1.782-1.755-.983 0-1.78.786-1.78 1.755 0 .969.797 1.754 1.78 1.754zm-7.031 12.698c1.61.343 2.64.782 3.089 1.317l5.773 6.88-2.328 1.954-5.774-6.88c-.34-.404-.592-1.495-.76-3.27zm7.072 10.736l2.33-1.954 1.282 1.529c.428.51.383.982-.135 1.416l-.776.651c-.517.434-.99.397-1.418-.113l-1.283-1.529zm.494-5.272l.01-.009a.5.5 0 0 1 .704.062l2.334 2.781a.5.5 0 0 1-.061.705l-.01.008a.5.5 0 0 1-.705-.061l-2.334-2.782a.5.5 0 0 1 .062-.704zM35 42h9v.998h-9V42zm0 3h9v.998h-9V45z"/></defs><g fill="none" fill-rule="evenodd"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><g mask="url(#b)"><path fill="url(#c)" d="M0 0H70V70H0z"/><path fill="#FFF" fill-opacity=".383" d="M4 1h61c2.667 0 4.333.667 5 2V0H0v3c.667-1.333 2-2 4-2z"/><path fill="#393939" d="M42.865 69H4c-2 0-4-1-4-4V38.062l22.272-24.547L24.037 13H44.02L49 17v13h5.814v10.707l-4.599 5.878v4.163l-1.966 2.081.555.876.84-.876 2.964 3.459-.858.636L53 58.5 42.865 69z" opacity=".324"/><path fill="#000" fill-opacity=".383" d="M4 69h61c2.667 0 4.333-1 5-3v4H0v-4c.667 2 2 3 4 3z"/><use fill="#000" fill-rule="nonzero" opacity=".3" xlink:href="#d"/><use fill="#FFF" fill-rule="nonzero" xlink:href="#e"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import print_prenumbered_checks

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models
from . import wizard

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Debit Notes',

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_move

View File

@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import test_out_debit_note

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_debit_note

View File

@@ -11,7 +11,6 @@ import base64
import io
import logging
import pathlib
import re
_logger = logging.getLogger(__name__)
@@ -507,88 +506,21 @@ class AccountEdiFormat(models.Model):
:param vat: The vat number of the partner.
:returns: A partner or an empty recordset if not found.
'''
def search_with_vat(extra_domain):
if not vat:
return None
domains = []
for value, domain in (
(name, [('name', 'ilike', name)]),
(phone, expression.OR([[('phone', '=', phone)], [('mobile', '=', phone)]])),
(mail, [('email', '=', mail)]),
(vat, [('vat', 'like', vat)]),
):
if value is not None:
domains.append(domain)
# Sometimes, the vat is specified with some whitespaces.
normalized_vat = vat.replace(' ', '')
country_prefix = re.match('^[a-zA-Z]{2}|^', vat).group()
partner = self.env['res.partner'].search(extra_domain + [('vat', 'in', (normalized_vat, vat))], limit=1)
# Try to remove the country code prefix from the vat.
if not partner and country_prefix:
partner = self.env['res.partner'].search(extra_domain + [
('vat', 'in', (normalized_vat[2:], vat[2:])),
('country_id.code', '=', country_prefix.upper()),
], limit=1)
# The country could be not specified on the partner.
if not partner:
partner = self.env['res.partner'].search(extra_domain + [
('vat', 'in', (normalized_vat[2:], vat[2:])),
('country_id', '=', False),
], limit=1)
# The vat could be a string of alphanumeric values without country code but with missing zeros at the
# beginning.
if not partner:
try:
vat_only_numeric = str(int(re.sub('^\D{2}', '', normalized_vat) or 0))
except ValueError:
vat_only_numeric = None
if vat_only_numeric:
query = self.env['res.partner']._where_calc(extra_domain + [('active', '=', True)])
tables, where_clause, where_params = query.get_sql()
if country_prefix:
vat_prefix_regex = f'({country_prefix})?'
else:
vat_prefix_regex = '([A-z]{2})?'
self._cr.execute(f'''
SELECT res_partner.id
FROM {tables}
WHERE {where_clause}
AND res_partner.vat ~ %s
LIMIT 1
''', where_params + ['^%s0*%s$' % (vat_prefix_regex, vat_only_numeric)])
partner_row = self._cr.fetchone()
if partner_row:
partner = self.env['res.partner'].browse(partner_row[0])
return partner
def search_with_phone_mail(extra_domain):
domains = []
if phone:
domains.append([('phone', '=', phone)])
domains.append([('mobile', '=', phone)])
if mail:
domains.append([('email', '=', mail)])
if not domains:
return None
domain = expression.OR(domains)
if extra_domain:
domain = expression.AND([domain, extra_domain])
return self.env['res.partner'].search(domain, limit=1)
def search_with_name(extra_domain):
if not name:
return None
return self.env['res.partner'].search([('name', 'ilike', name)] + extra_domain, limit=1)
for search_method in (search_with_vat, search_with_phone_mail, search_with_name):
for extra_domain in ([('company_id', '=', self.env.company.id)], []):
partner = search_method(extra_domain)
if partner:
return partner
return self.env['res.partner']
domain = expression.AND([
expression.OR(domains),
[('company_id', 'in', [False, self.env.company.id])],
])
return self.env['res.partner'].search(domain, limit=1)
def _retrieve_product(self, name=None, default_code=None, barcode=None):
'''Search all products and find one that matches one of the parameters.

View File

@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import common
from . import test_edi
from . import test_import_vendor_bill

View File

@@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
from flectra.addons.account.tests.common import AccountTestInvoicingCommon
from flectra.tests import tagged
@tagged('post_install', '-at_install')
class TestImportVendorBill(AccountTestInvoicingCommon):
def test_retrieve_partner(self):
def retrieve_partner(vat, import_vat):
self.partner_a.with_context(no_vat_validation=True).vat = vat
self.partner_a.flush()
return self.env['account.edi.format']._retrieve_partner(vat=import_vat)
self.assertEqual(self.partner_a, retrieve_partner('BE0477472701', 'BE0477472701'))
self.assertEqual(self.partner_a, retrieve_partner('BE0477472701', '0477472701'))
self.assertEqual(self.partner_a, retrieve_partner('BE0477472701', '477472701'))
self.assertEqual(self.partner_a, retrieve_partner('0477472701', 'BE0477472701'))
self.assertEqual(self.partner_a, retrieve_partner('477472701', 'BE0477472701'))
self.assertEqual(self.env['res.partner'], retrieve_partner('DE0477472701', 'BE0477472701'))
self.assertEqual(self.partner_a, retrieve_partner('CHE-107.787.577 IVA', 'CHE-107.787.577 IVA')) # note that base_vat forces the space

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import common
from . import test_edi

View File

@@ -58,7 +58,7 @@ class AccountEdiFormat(models.Model):
if not edi_document.attachment_id:
return
pdf_writer.embed_flectra_attachment(edi_document.attachment_id, subtype='application/xml')
pdf_writer.embed_flectra_attachment(edi_document.attachment_id)
if not pdf_writer.is_pdfa and str2bool(self.env['ir.config_parameter'].sudo().get_param('edi.use_pdfa', 'False')):
try:
pdf_writer.convert_to_pdfa()
@@ -137,7 +137,7 @@ class AccountEdiFormat(models.Model):
return self.env['ir.attachment'].create({
'name': 'factur-x.xml',
'datas': base64.encodebytes(xml_content),
'mimetype': 'application/xml'
'mimetype': '/application#2Fxml'
})
def _is_facturx(self, filename, tree):

View File

@@ -2,10 +2,10 @@
{
'name': 'Proxy features for account_edi',
'description': """
This module adds generic features to register an Odoo DB on the proxy responsible for receiving data (via requests from web-services).
This module adds generic features to register an Flectra DB on the proxy responsible for receiving data (via requests from web-services).
- An edi_proxy_user has a unique identification on a specific format (for example, the vat for Peppol) which
allows to identify him when receiving a document addressed to him. It is linked to a specific company on a specific
Odoo database.
Flectra database.
- Encryption features allows to decrypt all the user's data when receiving it from the proxy.
- Authentication offers an additionnal level of security to avoid impersonification, in case someone gains to the user's database.
""",

View File

@@ -1,10 +1,10 @@
# Translation of Odoo Server.
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * account_edi_proxy_client
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0+e\n"
"Project-Id-Version: Flectra Server 2.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-03 13:44+0000\n"
"PO-Revision-Date: 2021-06-03 13:44+0000\n"

View File

@@ -17,7 +17,7 @@ import logging
_logger = logging.getLogger(__name__)
SERVER_URL = 'https://l10n-it-edi.api.flectra.com'
SERVER_URL = 'https://l10n-it-edi.api.flectrahq.com'
TIMEOUT = 30

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Accounting/Fleet bridge',
'category': 'Accounting/Accounting',

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_move
from . import fleet_vehicle

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Irreversible Lock Date',
'version': '1.0',

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import portal
from . import payment

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import payment

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': "Define Taxes as Python Code",

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_tax

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models
from . import report

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
# Copyright (c) 2011 CCI Connect asbl (http://www.cciconnect.be) All Rights Reserved.
# Philmer <philmer@cciconnect.be>

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import accounting_assert_test

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import report_account_test

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Adyen for Platforms',

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import adyen_platforms

View File

@@ -3,12 +3,12 @@
<data noupdate="1">
<record model="ir.config_parameter" id="adyen_platforms_proxy_url">
<field name="key">adyen_platforms.proxy_url</field>
<field name="value">https://payment-adyen.flectra.com/payment_proxy_adyen/</field>
<field name="value">https://payment-adyen.flectrahq.com/payment_proxy_adyen/</field>
</record>
<record model="ir.config_parameter" id="adyen_platforms_onboarding_url">
<field name="key">adyen_platforms.onboarding_url</field>
<field name="value">https://www.flectra.com/flectra_adyen/</field>
<field name="value">https://www.flectrahq.com/flectra_adyen/</field>
</record>
<record id="adyen_sync_cron" model="ir.cron">

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import adyen_account
from . import adyen_transaction

View File

@@ -159,10 +159,10 @@ class AdyenAccount(models.Model):
adyen_account_id = super(AdyenAccount, self).create(values)
self.env.company.adyen_account_id = adyen_account_id.id
# Create account on flectra.com, proxy and Adyen
# Create account on flectrahq.com, proxy and Adyen
response = adyen_account_id._adyen_rpc('create_account_holder', adyen_account_id._format_data())
# Save adyen_uuid and proxy_token, that have been generated by flectra.com and the proxy
# Save adyen_uuid and proxy_token, that have been generated by flectrahq.com and the proxy
adyen_account_id.with_context(update_from_adyen=True).write({
'adyen_uuid': response['adyen_uuid'],
'proxy_token': response['proxy_token'],
@@ -192,8 +192,8 @@ class AdyenAccount(models.Model):
def action_create_redirect(self):
'''
Accessing the FormView to create an Adyen account needs to be done through this action.
The action will redirect the user to accounts.flectra.com to link an Flectra user_id to the Adyen
account. After logging in on flectra.com the user will be redirected to his DB with a token in
The action will redirect the user to accounts.flectrahq.com to link an Flectra user_id to the Adyen
account. After logging in on flectrahq.com the user will be redirected to his DB with a token in
the URL. This token is then needed to create the Adyen account.
'''
if self.env.company.adyen_account_id:

View File

@@ -71,7 +71,7 @@
services. You may not use the payment services for different types of product and
services than as registered with your application. In particular you confirm that you
will not use the payment services for any type of product or service appearing in the
<a href="https://www.flectra.com/flectra_adyen/static/src/pdf/marketpay_prohibited_products_and_services.pdf">
<a href="https://www.flectrahq.com/flectra_adyen/static/src/pdf/marketpay_prohibited_products_and_services.pdf">
Prohibited Products and Services List of our Processor</a>. If we or our
Processor at any time discover that the information you provided about your
business is incorrect or has changed without informing us or if you violate any of
@@ -83,7 +83,7 @@
<h3>Contractual Relationship</h3>
<p>The payment processing services ordered by you by placing this order will be
provided to you by Adyen N.V. (hereafter “Processor”), with which you are
entering into a direct agreement by confirming this order. Flectra S.A.
entering into a direct agreement by confirming this order. FlectraHQ Inc., Odoo S.A.
(hereafter “We /Us”) will assist and support you in your use of the services to be
provided by the Processor and we will provide you first line assistance with and
enable you to connect to the systems of Processor to be able to use its services.
@@ -102,8 +102,8 @@
<input type="checkbox" class="opt_in_checkbox"/>
I confirm I have taken notice of and accept the following terms and restrictions:
<ul>
<li>Adyen MarketPay Terms and Conditions (click <a href="https://www.flectra.com/flectra_adyen/static/src/pdf/marketpay_terms_and_conditions.pdf">here</a> to download and review)</li>
<li>Adyen Restricted and Prohibited Products and Services list (click <a href="https://www.flectra.com/flectra_adyen/static/src/pdf/marketpay_prohibited_products_and_services.pdf">here</a> to download and review)</li>
<li>Adyen MarketPay Terms and Conditions (click <a href="https://www.flectrahq.com/flectra_adyen/static/src/pdf/marketpay_terms_and_conditions.pdf">here</a> to download and review)</li>
<li>Adyen Restricted and Prohibited Products and Services list (click <a href="https://www.flectrahq.com/flectra_adyen/static/src/pdf/marketpay_prohibited_products_and_services.pdf">here</a> to download and review)</li>
</ul>
</main>
</t>

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name' : 'Analytic Accounting',
@@ -10,7 +10,7 @@
Module for defining analytic accounting object.
===============================================
In Odoo, analytic accounts are linked to general accounts but are treated
In Flectra, analytic accounts are linked to general accounts but are treated
totally independently. So, you can enter various different analytic operations
that have no counterpart in the general financial accounts.
""",

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import analytic_account

View File

@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Attachments List and Document Indexation',
'version': '2.1',

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import ir_attachment

View File

@@ -1,7 +1,7 @@
Adds support for authentication by LDAP server.
===============================================
This module allows users to login with their LDAP username and password, and
will automatically create Odoo users for them on the fly.
will automatically create Flectra users for them on the fly.
**Note:** This module only work on servers that have Python's ``python-ldap`` module installed.
@@ -10,7 +10,7 @@ Configuration:
After installing this module, you need to configure the LDAP parameters in the
General Settings menu. Different companies may have different
LDAP servers, as long as they have unique usernames (usernames need to be unique
in Odoo, even across multiple companies).
in Flectra, even across multiple companies).
Anonymous LDAP binding is also supported (for LDAP servers that allow it), by
simply keeping the LDAP user and password empty in the LDAP configuration.
@@ -26,24 +26,24 @@ manpage: manpage:`ldap.conf(5)`.
Security Considerations:
------------------------
Users' LDAP passwords are never stored in the Odoo database, the LDAP server
Users' LDAP passwords are never stored in the Flectra database, the LDAP server
is queried whenever a user needs to be authenticated. No duplication of the
password occurs, and passwords are managed in one place only.
Odoo does not manage password changes in the LDAP, so any change of password
Flectra does not manage password changes in the LDAP, so any change of password
should be conducted by other means in the LDAP directory directly (for LDAP users).
It is also possible to have local Odoo users in the database along with
It is also possible to have local Flectra users in the database along with
LDAP-authenticated users (the Administrator account is one obvious example).
Here is how it works:
---------------------
* The system first attempts to authenticate users against the local Odoo
* The system first attempts to authenticate users against the local Flectra
database;
* if this authentication fails (for example because the user has no local
password), the system then attempts to authenticate against LDAP;
As LDAP users have blank passwords by default in the local Odoo database
As LDAP users have blank passwords by default in the local Flectra database
(which means no access), the first step always fails and the LDAP server is
queried to do the authentication.
@@ -61,6 +61,6 @@ allows pre-setting the default groups and menus of the first-time users.
assigned as local password for each new LDAP user, effectively setting
a *master password* for these users (until manually changed). You
usually do not want this. One easy way to setup a template user is to
login once with a valid LDAP user, let Odoo create a blank local
login once with a valid LDAP user, let Flectra create a blank local
user with the same login (and a blank password), then rename this new
user to a username that does not exist in LDAP, and setup its groups

View File

@@ -1,3 +1,3 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -1,4 +1,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Authentication via LDAP',

View File

@@ -1,4 +1,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import res_company
from . import res_company_ldap

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'OAuth2 Authentication',
@@ -8,7 +8,7 @@
Allow users to login through OAuth2 Provider.
=============================================
""",
'maintainer': 'Odoo S.A.',
'maintainer': 'FlectraHQ Inc., Odoo S.A.',
'depends': ['base', 'web', 'base_setup', 'auth_signup'],
'data': [
'data/auth_oauth_data.xml',

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import main

View File

@@ -2,13 +2,13 @@
<flectra>
<data noupdate="1">
<record id="provider_openerp" model="auth.oauth.provider">
<field name="name">Flectra.com Accounts</field>
<field name="auth_endpoint">https://accounts.flectra.com/oauth2/auth</field>
<field name="name">flectrahq.com Accounts</field>
<field name="auth_endpoint">https://accounts.flectrahq.com/oauth2/auth</field>
<field name="scope">userinfo</field>
<field name="validation_endpoint">https://accounts.flectra.com/oauth2/tokeninfo</field>
<field name="validation_endpoint">https://accounts.flectrahq.com/oauth2/tokeninfo</field>
<field name="data_endpoint"></field>
<field name="css_class">fa fa-fw o_custom_icon</field>
<field name="body">Log in with Flectra.com</field>
<field name="body">Log in with flectrahq.com</field>
<field name="enabled" eval="True"/>
</record>
<record id="provider_facebook" model="auth.oauth.provider">

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import auth_oauth
from . import res_config_settings

View File

@@ -10,7 +10,7 @@
.o_custom_icon {
margin: 0 0.15em;
@include size(1em);
border: 3px solid #875A7B;
border: 3px solid #009EFB;
border-radius: 100%;
transform: translateY(2px);
}

View File

@@ -21,7 +21,7 @@
</div>
<div class="o_setting_right_pane">
<label string="Google Authentication" for="auth_oauth_google_enabled"/>
<a href="https://www.flectra.com/documentation/14.0/applications/general/auth/google.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<a href="https://doc.flectrahq.com/2.0/applications/general/auth/google.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<div class="text-muted">
Allow users to sign in with their Google account
</div>
@@ -30,7 +30,7 @@
<label for="auth_oauth_google_client_id" string="Client ID:" class="col-lg-3 o_light_label"/>
<field name="auth_oauth_google_client_id" placeholder="e.g. 1234-xyz.apps.googleusercontent.com"/>
</div>
<a href="https://www.flectra.com/documentation/14.0/applications/general/auth/google.html" target="_blank"><i class="fa fa-fw fa-arrow-right"/>Tutorial</a>
<a href="https://doc.flectrahq.com/2.0/applications/general/auth/google.html" target="_blank"><i class="fa fa-fw fa-arrow-right"/>Tutorial</a>
</div>
</div>
</div>

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Signup',

View File

@@ -5,7 +5,7 @@ import werkzeug
from flectra import http, _
from flectra.addons.auth_signup.models.res_users import SignupError
from flectra.addons.web.controllers.main import ensure_db, Home, SIGN_UP_REQUEST_PARAMS
from flectra.addons.web.controllers.main import ensure_db, Home
from flectra.addons.base_setup.controllers.main import BaseSetup
from flectra.exceptions import UserError
from flectra.http import request
@@ -101,7 +101,7 @@ class AuthSignupHome(Home):
def get_auth_signup_qcontext(self):
""" Shared helper returning the rendering context for signup and reset password """
qcontext = {k: v for (k, v) in request.params.items() if k in SIGN_UP_REQUEST_PARAMS}
qcontext = request.params.copy()
qcontext.update(self.get_auth_signup_config())
if not qcontext.get('token') and request.session.get('auth_signup_token'):
qcontext['token'] = request.session.get('auth_signup_token')

View File

@@ -45,7 +45,7 @@
You may change your password by following this link which will remain valid during 24 hours:<br/>
<div style="margin: 16px 0px 16px 0px;">
<a href="${object.signup_url}"
style="background-color: #875A7B; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
style="background-color: #009EFB; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
Change password
</a>
</div>
@@ -91,7 +91,7 @@
<tr><td align="center" style="min-width: 590px;">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;">
<tr><td style="text-align: center; font-size: 13px;">
Powered by <a target="_blank" href="https://www.flectra.com?utm_source=db&amp;utm_medium=auth" style="color: #875A7B;">Flectra</a>
Powered by <a target="_blank" href="https://www.flectrahq.com?utm_source=db&amp;utm_medium=auth" style="color: #009EFB;">Flectra</a>
</td></tr>
</table>
</td></tr>
@@ -140,7 +140,7 @@
You have been invited by ${object.create_uid.name} of ${object.company_id.name} to connect on Flectra.
<div style="margin: 16px 0px 16px 0px;">
<a href="${object.signup_url}"
style="background-color: #875A7B; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
style="background-color: #009EFB; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
Accept invitation
</a>
</div>
@@ -149,7 +149,7 @@
Your sign in email is: <b><a href="/web/login?login=${object.email}" target="_blank">${object.email}</a></b><br /><br />
Never heard of Flectra? Its an all-in-one business software loved by 3+ million users. It will considerably improve your experience at work and increase your productivity.
<br /><br />
Have a look at the <a href="https://www.flectra.com/page/tour?utm_source=db&amp;utm_medium=auth" style="color: #875A7B;">Flectra Tour</a> to discover the tool.
Have a look at the <a href="https://www.flectrahq.com/page/tour?utm_source=db&amp;utm_medium=auth" style="color: #009EFB;">Flectra Tour</a> to discover the tool.
<br /><br />
Enjoy Flectra!<br />
--<br/>The ${object.company_id.name} Team
@@ -189,7 +189,7 @@
<tr><td align="center" style="min-width: 590px;">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;">
<tr><td style="text-align: center; font-size: 13px;">
Powered by <a target="_blank" href="https://www.flectra.com?utm_source=db&amp;utm_medium=auth" style="color: #875A7B;">Flectra</a>
Powered by <a target="_blank" href="https://www.flectrahq.com?utm_source=db&amp;utm_medium=auth" style="color: #009EFB;">Flectra</a>
</td></tr>
</table>
</td></tr>
@@ -290,7 +290,7 @@
To gain access to your account, you can use the following link:
<div style="margin: 16px 0px 16px 0px;">
<a href="/web/login?auth_login=${object.email}"
style="background-color: #875A7B; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
style="background-color: #009EFB; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
Go to My Account
</a>
</div>
@@ -335,7 +335,7 @@
<tr><td align="center" style="min-width: 590px;">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;">
<tr><td style="text-align: center; font-size: 13px;">
Powered by <a target="_blank" href="https://www.flectra.com?utm_source=db&amp;utm_medium=auth" style="color: #875A7B;">Flectra</a>
Powered by <a target="_blank" href="https://www.flectrahq.com?utm_source=db&amp;utm_medium=auth" style="color: #009EFB;">Flectra</a>
</td></tr>
</table>
</td></tr>

View File

@@ -117,7 +117,7 @@
<span class="alert alert-info" role="status">
<i class="fa fa-warning"/>
Two-factor authentication not enabled
<a href="https://www.flectra.com/documentation/14.0/applications/general/auth/2fa.html"
<a href="https://doc.flectrahq.com/2.0/applications/general/auth/2fa.html"
title="What is this?" class="o_doc_link" target="_blank"></a>
</span>
<button name="totp_enable_wizard" type="object" string="Enable two-factor authentication"
@@ -129,7 +129,7 @@
<span class="text-success">
<i class="fa fa-check-circle"/>
Two-factor authentication enabled
<a href="https://www.flectra.com/documentation/14.0/applications/general/auth/2fa.html"
<a href="https://doc.flectrahq.com/2.0/applications/general/auth/2fa.html"
title="What is this?" class="o_doc_link" target="_blank"></a>
</span>
<button name="totp_disable" type="object" string="(Disable two-factor authentication)"

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'City Addresses',
'summary': 'Add a many2one field city on addresses',

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import res_city
from . import res_country

View File

@@ -24,11 +24,6 @@ class Partner(models.Model):
self.zip = False
self.state_id = False
@api.model
def _address_fields(self):
"""Returns the list of address fields that are synced from the parent."""
return super(Partner, self)._address_fields() + ['city_id',]
@api.model
def _fields_view_get_address(self, arch):
arch = super(Partner, self)._fields_view_get_address(arch)

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models
from flectra import api, SUPERUSER_ID

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Extended Addresses',
'summary': 'Add extra fields on addresses',

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import res_company
from . import res_country

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import test_street_fields

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import models

Some files were not shown because too many files have changed in this diff Show More