[FIX] l10n_ch_sale: create correct payment reference for swiss loca
Steps to reproduce: - Install website_sale, contact, l10n_ch - make sure your company is in Switzerland and has all the address information - in settings, activate QR - in Accounting/Journals/Bank:add a bank account (iban: CH4431999123000889012; qr-iban: CH11 3000 5228 1308 3501 F) - install and enable the provider "Wire Transfer" - From the Website, create an order and make sure the customer set an Invoicing address in Switzerland (address + Country) - Validate the order - In Website/unpaid orders: select your order and Confirm the order - Create and confirm the invoice - Print the invoice Issue: User Error is raised Cause: With Swiss QR code you need to have a valid payment reference. That is, an ISR reference such as in https://github.com/odoo/odoo/blob/c6631df1c5b0b6d4c2268a826ca150edd0ca653e/addons/l10n_ch/models/account_invoice.py#L90 But when you create an order from the website, it creates an automatic reference "SO0001" which, when converted to an invoice, stays the same. Since the reference is prepoluted, the `_compute_l10n_ch_isr_number` will not be triggered and therefore will raise an error when trying to print the invoice. Solution: Check if the Customer Invoice Journal uses the swiss reference model, then we know that the swiss loca is installed and can call the correct function to compute the reference/ Note: In the test we check that `payment_custom` is installed. It is because the `_set_pending` method checks taht the payment_provider.code is "custom"="wire_transfer" in which case the sale order reference is computed https://github.com/odoo/odoo/blob/b4ed9537895ecee48ed146add4257af0aebeb3f4/addons/sale/models/payment_transaction.py#L54-L56 opw-3334534 closes odoo/odoo#127338 X-original-commit: dfa4844e57b67d16b181e1e58813cdbbc7efa956 Signed-off-by: Yolann Sabaux (yosa) <yosa@odoo.com> Signed-off-by: Olivier Colson (oco) <oco@odoo.com> Co-authored-by: flvr-odoo <flvr@odoo.com>
This commit is contained in:
committed by
oco-odoo
co-authored by
flvr-odoo
parent
fd2fb212c5
commit
7cc4b6cfe8
@@ -905,3 +905,11 @@ class AccountJournal(models.Model):
|
||||
""" Check if the payment method is available on this journal. """
|
||||
self.ensure_one()
|
||||
return self.filtered_domain(self.env['account.payment.method']._get_payment_method_domain(payment_method_code))
|
||||
|
||||
def _process_reference_for_sale_order(self, order_reference):
|
||||
'''
|
||||
returns the order reference to be used for the payment.
|
||||
Hook to be overriden: see l10n_ch for an example.
|
||||
'''
|
||||
self.ensure_one()
|
||||
return order_reference
|
||||
|
||||
@@ -30,16 +30,20 @@ class AccountMove(models.Model):
|
||||
self.ensure_one()
|
||||
if self.partner_bank_id.l10n_ch_qr_iban and self.l10n_ch_is_qr_valid and self.name:
|
||||
invoice_ref = re.sub(r'[^\d]', '', self.name)
|
||||
# keep only the last digits if it exceed boundaries
|
||||
ref_payload_len = L10N_CH_QRR_NUMBER_LENGTH - 1
|
||||
extra = len(invoice_ref) - ref_payload_len
|
||||
if extra > 0:
|
||||
invoice_ref = invoice_ref[extra:]
|
||||
internal_ref = invoice_ref.zfill(ref_payload_len)
|
||||
return mod10r(internal_ref)
|
||||
return self._compute_qrr_number(invoice_ref)
|
||||
else:
|
||||
return False
|
||||
|
||||
@api.model
|
||||
def _compute_qrr_number(self, invoice_ref):
|
||||
# keep only the last digits if it exceed boundaries
|
||||
ref_payload_len = L10N_CH_QRR_NUMBER_LENGTH - 1
|
||||
extra = len(invoice_ref) - ref_payload_len
|
||||
if extra > 0:
|
||||
invoice_ref = invoice_ref[extra:]
|
||||
internal_ref = invoice_ref.zfill(ref_payload_len)
|
||||
return mod10r(internal_ref)
|
||||
|
||||
def _get_invoice_reference_ch_invoice(self):
|
||||
""" This sets QRR reference number which is generated based on customer's `Bank Account` and set it as
|
||||
`Payment Reference` of the invoice when invoice's journal is using Switzerland's communication standard
|
||||
|
||||
@@ -15,3 +15,16 @@ class AccountJournal(models.Model):
|
||||
invoice_reference_model = fields.Selection(selection_add=[
|
||||
('ch', 'Switzerland')
|
||||
], ondelete={'ch': lambda recs: recs.write({'invoice_reference_model': 'odoo'})})
|
||||
|
||||
def _process_reference_for_sale_order(self, order_reference):
|
||||
'''
|
||||
Returns the order reference to be used for the payment, respecting the QRR standard.
|
||||
'''
|
||||
self.ensure_one()
|
||||
if self.invoice_reference_model == 'ch':
|
||||
# converting the sale order name into a unique number. Letters are converted to their base10 value
|
||||
invoice_ref = "".join([a if a.isdigit() else str(ord(a)) for a in order_reference])
|
||||
# id_number = self.company_id.bank_ids.l10n_ch_postal or ''
|
||||
order_reference = self.env['account.move']._compute_qrr_number(invoice_ref)
|
||||
return order_reference
|
||||
return super()._process_reference_for_sale_order(order_reference)
|
||||
|
||||
@@ -5,6 +5,7 @@ import time
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import tagged
|
||||
from odoo.tools.misc import mod10r
|
||||
|
||||
CH_IBAN = 'CH15 3881 5158 3845 3843 7'
|
||||
QR_IBAN = 'CH21 3080 8001 2345 6782 7'
|
||||
@@ -180,3 +181,40 @@ class TestSwissQR(AccountTestInvoicingCommon):
|
||||
self.invoice1.partner_bank_id = qriban_account
|
||||
self.invoice1.action_post()
|
||||
self.swissqr_generated(self.invoice1, ref_type="QRR")
|
||||
|
||||
def test_swiss_order_reference_qrr_for_qr_code(self):
|
||||
"""
|
||||
Test that the order reference is correctly generated for QR-Code
|
||||
We summon the skipTest if Sale is not installed (instead of creating a whole module for one test)
|
||||
"""
|
||||
if 'sale.order' not in self.env:
|
||||
self.skipTest('`sale` is not installed')
|
||||
|
||||
payment_custom = self.env['ir.module.module']._get('payment_custom')
|
||||
if payment_custom.state != 'installed':
|
||||
self.skipTest("payment_custom module is not installed")
|
||||
|
||||
provider = self.env['payment.provider'].create({
|
||||
'name': 'Test',
|
||||
'code': 'custom',
|
||||
})
|
||||
invoice_journal = self.env['account.journal'].search(
|
||||
[('type', '=', 'sale'), ('company_id', '=', self.env.company.id)], limit=1)
|
||||
invoice_journal.write({'invoice_reference_model': 'ch'})
|
||||
order = self.env['sale.order'].create({
|
||||
'name': "S00001",
|
||||
'partner_id': self.env['res.partner'].search([("name", '=', 'Partner')])[0].id,
|
||||
'order_line': [
|
||||
(0, 0, {'product_id': self.product_a.id, 'price_unit': 100}),
|
||||
],
|
||||
})
|
||||
payment_transaction = self.env['payment.transaction'].create({
|
||||
'provider_id': provider.id,
|
||||
'sale_order_ids': [order.id],
|
||||
'partner_id': self.env['res.partner'].search([("name", '=', 'Partner')])[0].id,
|
||||
'amount': 100,
|
||||
'currency_id': self.env.company.currency_id.id,
|
||||
})
|
||||
payment_transaction._set_pending()
|
||||
|
||||
self.assertEqual(order.reference, mod10r(order.reference[:-1]))
|
||||
|
||||
@@ -17,11 +17,16 @@ class PaymentTransaction(models.Model):
|
||||
def _compute_sale_order_reference(self, order):
|
||||
self.ensure_one()
|
||||
if self.provider_id.so_reference_type == 'so_name':
|
||||
return order.name
|
||||
order_reference = order.name
|
||||
else:
|
||||
# self.provider_id.so_reference_type == 'partner'
|
||||
identification_number = order.partner_id.id
|
||||
return '%s/%s' % ('CUST', str(identification_number % 97).rjust(2, '0'))
|
||||
order_reference = '%s/%s' % ('CUST', str(identification_number % 97).rjust(2, '0'))
|
||||
|
||||
invoice_journal = self.env['account.journal'].search([('type', '=', 'sale'), ('company_id', '=', self.env.company.id)], limit=1)
|
||||
order_reference = invoice_journal._process_reference_for_sale_order(order_reference)
|
||||
|
||||
return order_reference
|
||||
|
||||
@api.depends('sale_order_ids')
|
||||
def _compute_sale_order_ids_nbr(self):
|
||||
|
||||
Reference in New Issue
Block a user