Purpose ======= - Add the SwissQR Code on the invoice in aim to replace the actual ISR - Improve the settings of the SEPA QR Code to make it more user friendly Specifications ============== - ln_ch: - Add a SwissQR Code on the invoice to fit the Switzerland QR-Bill Format - Use the "partner_bank_id" field to generate the QR Code - Add function to get the address number out of the field "street" and "street2" - account: - Remove the SEPA QR Code's journal settings from the general setting - Display the "partner_bank_id" field on the invoice "Other info" page - Use the "partner_bank_id" field to generate the QR Code - website_sale: - Add a check box on the payment acquirers to use the SEPA QR Code on the e-commerce - Use the payment acquirer "journal_id" field to generate the SEPA QR Code
162 lines
9.8 KiB
Python
162 lines
9.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, _
|
|
|
|
|
|
class ResConfigSettings(models.TransientModel):
|
|
_inherit = 'res.config.settings'
|
|
|
|
has_accounting_entries = fields.Boolean(compute='_compute_has_chart_of_accounts')
|
|
currency_id = fields.Many2one('res.currency', related="company_id.currency_id", required=True,
|
|
string='Currency', help="Main currency of the company.")
|
|
currency_exchange_journal_id = fields.Many2one(
|
|
'account.journal',
|
|
related='company_id.currency_exchange_journal_id',
|
|
string="Exchange Gain or Loss Journal",
|
|
domain="[('company_id', '=', company_id), ('type', '=', 'general')]",
|
|
help='The accounting journal where automatic exchange differences will be registered')
|
|
has_chart_of_accounts = fields.Boolean(compute='_compute_has_chart_of_accounts', string='Company has a chart of accounts')
|
|
chart_template_id = fields.Many2one('account.chart.template', string='Template',
|
|
domain="[('visible','=', True)]")
|
|
sale_tax_id = fields.Many2one('account.tax', string="Default Sale Tax", related='company_id.account_sale_tax_id')
|
|
purchase_tax_id = fields.Many2one('account.tax', string="Default Purchase Tax", related='company_id.account_purchase_tax_id')
|
|
tax_calculation_rounding_method = fields.Selection([
|
|
('round_per_line', 'Round calculation of taxes per line'),
|
|
('round_globally', 'Round globally calculation of taxes '),
|
|
], related='company_id.tax_calculation_rounding_method', string='Tax calculation rounding method')
|
|
module_account_accountant = fields.Boolean(string='Accounting')
|
|
group_analytic_accounting = fields.Boolean(string='Analytic Accounting',
|
|
implied_group='analytic.group_analytic_accounting')
|
|
group_analytic_tags = fields.Boolean(string='Analytic Tags', implied_group='analytic.group_analytic_tags')
|
|
group_warning_account = fields.Boolean(string="Warnings in Invoices", implied_group='account.group_warning_account')
|
|
group_cash_rounding = fields.Boolean(string="Cash Rounding", implied_group='account.group_cash_rounding')
|
|
group_fiscal_year = fields.Boolean(string='Fiscal Years', implied_group='account.group_fiscal_year')
|
|
# group_show_line_subtotals_tax_excluded and group_show_line_subtotals_tax_included are opposite,
|
|
# so we can assume exactly one of them will be set, and not the other.
|
|
# We need both of them to coexist so we can take advantage of automatic group assignation.
|
|
group_show_line_subtotals_tax_excluded = fields.Boolean(
|
|
"Show line subtotals without taxes (B2B)",
|
|
implied_group='account.group_show_line_subtotals_tax_excluded',
|
|
group='base.group_portal,base.group_user,base.group_public')
|
|
group_show_line_subtotals_tax_included = fields.Boolean(
|
|
"Show line subtotals with taxes (B2C)",
|
|
implied_group='account.group_show_line_subtotals_tax_included',
|
|
group='base.group_portal,base.group_user,base.group_public')
|
|
group_products_in_bills = fields.Boolean(string="Use products in vendor bills",
|
|
implied_group='account.group_products_in_bills',
|
|
group='base.group_user',
|
|
help="Disable this option to use a simplified versions of vendor bills, where products are hidden.")
|
|
show_line_subtotals_tax_selection = fields.Selection([
|
|
('tax_excluded', 'Tax-Excluded'),
|
|
('tax_included', 'Tax-Included')], string="Line Subtotals Tax Display",
|
|
required=True, default='tax_excluded',
|
|
config_parameter='account.show_line_subtotals_tax_selection')
|
|
module_account_asset = fields.Boolean(string='Assets Management')
|
|
module_account_deferred_revenue = fields.Boolean(string="Revenue Recognition")
|
|
module_account_budget = fields.Boolean(string='Budget Management')
|
|
module_account_payment = fields.Boolean(string='Invoice Online Payment')
|
|
module_account_reports = fields.Boolean("Dynamic Reports")
|
|
module_account_reports_followup = fields.Boolean("Follow-up Levels")
|
|
module_account_check_printing = fields.Boolean("Allow check printing and deposits")
|
|
module_account_batch_payment = fields.Boolean(string='Use batch payments',
|
|
help='This allows you grouping payments into a single batch and eases the reconciliation process.\n'
|
|
'-This installs the account_batch_payment module.')
|
|
module_account_sepa = fields.Boolean(string='SEPA Credit Transfer (SCT)')
|
|
module_account_sepa_direct_debit = fields.Boolean(string='Use SEPA Direct Debit')
|
|
module_account_plaid = fields.Boolean(string="Plaid Connector")
|
|
module_account_yodlee = fields.Boolean("Bank Interface - Sync your bank feeds automatically")
|
|
module_account_bank_statement_import_qif = fields.Boolean("Import .qif files")
|
|
module_account_bank_statement_import_ofx = fields.Boolean("Import in .ofx format")
|
|
module_account_bank_statement_import_csv = fields.Boolean("Import in .csv format")
|
|
module_account_bank_statement_import_camt = fields.Boolean("Import in CAMT.053 format")
|
|
module_currency_rate_live = fields.Boolean(string="Automatic Currency Rates")
|
|
module_print_docsaway = fields.Boolean(string="Docsaway")
|
|
module_account_intrastat = fields.Boolean(string='Intrastat')
|
|
module_product_margin = fields.Boolean(string="Allow Product Margin")
|
|
module_l10n_eu_service = fields.Boolean(string="EU Digital Goods VAT")
|
|
module_account_taxcloud = fields.Boolean(string="Account TaxCloud")
|
|
tax_exigibility = fields.Boolean(string='Cash Basis', related='company_id.tax_exigibility')
|
|
tax_cash_basis_journal_id = fields.Many2one('account.journal', related='company_id.tax_cash_basis_journal_id', string="Tax Cash Basis Journal")
|
|
invoice_reference_type = fields.Selection(string='Communication',
|
|
related='company_id.invoice_reference_type', help='Default Reference Type on Invoices.')
|
|
account_bank_reconciliation_start = fields.Date(string="Bank Reconciliation Threshold",
|
|
related='company_id.account_bank_reconciliation_start',
|
|
help="""The bank reconciliation widget won't ask to reconcile payments older than this date.
|
|
This is useful if you install accounting after having used invoicing for some time and
|
|
don't want to reconcile all the past payments with bank statements.""")
|
|
|
|
qr_code = fields.Boolean(string='Display SEPA QR code', related='company_id.qr_code')
|
|
invoice_is_print = fields.Boolean(string='Print', related='company_id.invoice_is_print')
|
|
invoice_is_email = fields.Boolean(string='Send Email', related='company_id.invoice_is_email')
|
|
|
|
@api.multi
|
|
def set_values(self):
|
|
super(ResConfigSettings, self).set_values()
|
|
if self.group_multi_currency:
|
|
self.env.ref('base.group_user').write({'implied_ids': [(4, self.env.ref('product.group_sale_pricelist').id)]})
|
|
""" install a chart of accounts for the given company (if required) """
|
|
if self.chart_template_id and self.chart_template_id != self.company_id.chart_template_id:
|
|
self.chart_template_id.load_for_current_company(15.0, 15.0)
|
|
|
|
@api.depends('company_id')
|
|
def _compute_has_chart_of_accounts(self):
|
|
self.has_chart_of_accounts = bool(self.company_id.chart_template_id)
|
|
self.chart_template_id = self.company_id.chart_template_id or False
|
|
self.has_accounting_entries = self.env['account.chart.template'].existing_accounting(self.company_id)
|
|
|
|
@api.onchange('show_line_subtotals_tax_selection')
|
|
def _onchange_sale_tax(self):
|
|
if self.show_line_subtotals_tax_selection == "tax_excluded":
|
|
self.update({
|
|
'group_show_line_subtotals_tax_included': False,
|
|
'group_show_line_subtotals_tax_excluded': True,
|
|
})
|
|
else:
|
|
self.update({
|
|
'group_show_line_subtotals_tax_included': True,
|
|
'group_show_line_subtotals_tax_excluded': False,
|
|
})
|
|
|
|
@api.onchange('group_analytic_accounting')
|
|
def onchange_analytic_accounting(self):
|
|
if self.group_analytic_accounting:
|
|
self.module_account_accountant = True
|
|
|
|
@api.onchange('module_account_budget')
|
|
def onchange_module_account_budget(self):
|
|
if self.module_account_budget:
|
|
self.group_analytic_accounting = True
|
|
|
|
@api.onchange('module_account_yodlee')
|
|
def onchange_account_yodlee(self):
|
|
if self.module_account_yodlee:
|
|
self.module_account_plaid = True
|
|
|
|
@api.onchange('tax_exigibility')
|
|
def _onchange_tax_exigibility(self):
|
|
res = {}
|
|
tax = self.env['account.tax'].search([
|
|
('company_id', '=', self.env.user.company_id.id), ('tax_exigibility', '=', 'on_payment')
|
|
], limit=1)
|
|
if not self.tax_exigibility and tax:
|
|
self.tax_exigibility = True
|
|
res['warning'] = {
|
|
'title': _('Error!'),
|
|
'message': _('You cannot disable this setting because some of your taxes are cash basis. '
|
|
'Modify your taxes first before disabling this setting.')
|
|
}
|
|
return res
|
|
|
|
@api.model
|
|
def create(self, values):
|
|
# Optimisation purpose, saving a res_config even without changing any values will trigger the write of all
|
|
# related values, including the currency_id field on res_company. This in turn will trigger the recomputation
|
|
# of account_move_line related field company_currency_id which can be slow depending on the number of entries
|
|
# in the database. Thus, if we do not explicitly change the currency_id, we should not write it on the company
|
|
if ('company_id' in values and 'currency_id' in values):
|
|
company = self.env['res.company'].browse(values.get('company_id'))
|
|
if company.currency_id.id == values.get('currency_id'):
|
|
values.pop('currency_id')
|
|
return super(ResConfigSettings, self).create(values)
|