mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2025-02-25 18:55:21 -06:00
Revert "[PATCH] Upstream patch - 25122021"
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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': [
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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],
|
||||
])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}])
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
])
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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.
|
||||
""",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
""",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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&utm_medium=auth" style="color: #875A7B;">Flectra</a>
|
||||
Powered by <a target="_blank" href="https://www.flectrahq.com?utm_source=db&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? It’s 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&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&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&utm_medium=auth" style="color: #875A7B;">Flectra</a>
|
||||
Powered by <a target="_blank" href="https://www.flectrahq.com?utm_source=db&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&utm_medium=auth" style="color: #875A7B;">Flectra</a>
|
||||
Powered by <a target="_blank" href="https://www.flectrahq.com?utm_source=db&utm_medium=auth" style="color: #009EFB;">Flectra</a>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user