From 17ff8fa45c3a62677457899233aaca8b3d55a653 Mon Sep 17 00:00:00 2001 From: "Tommy (tong)" Date: Fri, 19 May 2023 04:30:48 +0000 Subject: [PATCH] [IMP] account_qr_code_emv,l10n_hk: add reference to emv qr code Impacted versions: - saas-16.3 Changes: This commit improve below features: - Add additional data field into qr code vals - Override the additional data field in l10n_hk to support the new field - Update l10n_hk unit tests - Change FPS Identifier label closes odoo/odoo#122224 X-original-commit: 27b729709e78855721111f6f8b34cd0532147ec8 Signed-off-by: Nicolas Viseur (vin) Signed-off-by: Tommy Ng (tong) --- addons/account_qr_code_emv/models/res_bank.py | 32 +++++++++++++------ addons/l10n_hk/models/res_bank.py | 5 ++- addons/l10n_hk/tests/test_l10n_hk_emv_qr.py | 8 ++--- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/addons/account_qr_code_emv/models/res_bank.py b/addons/account_qr_code_emv/models/res_bank.py index e1c42729e6b..b0865716eb8 100644 --- a/addons/account_qr_code_emv/models/res_bank.py +++ b/addons/account_qr_code_emv/models/res_bank.py @@ -1,5 +1,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. +import re + from odoo import _, api, models from odoo.addons.account_qr_code_emv.const import CURRENCY_MAPPING @@ -23,25 +25,35 @@ class ResPartnerBank(models.Model): def _get_merchant_account_info(self): return False + def _get_additional_data_field(self, comment): + return False + def _get_qr_vals(self, qr_method, amount, currency, debtor_partner, free_communication, structured_communication): if qr_method == 'emv_qr': merchant_account_info = self._get_merchant_account_info() currency_code = CURRENCY_MAPPING[currency.name] merchant_name = self.partner_id.name and self.partner_id.name[:25] or 'NA' merchant_city = self.partner_id.city and self.partner_id.city[:15] or '' + comment = structured_communication or free_communication or '' + comment = re.sub(r'/[^ A-Za-z0-9_@.\/#&+-]+/g', '', comment) + additional_data_field = self._get_additional_data_field(comment) qr_code_vals = [ - '000201', # Payload Format Indicator - '010212', # Dynamic QR Codes - f'26{len(merchant_account_info):02}{merchant_account_info}', # Merchant Account Information - '52040000', # Merchant Category Code - f'5303{currency_code}', # Transaction Currency - f'54{len(str(amount)):02}{amount}', # Transaction Amount - f'5802{self.partner_id.country_code}', # Country Code - f'59{len(merchant_name):02}{merchant_name}', # Merchant Name - f'60{len(merchant_city):02}{merchant_city}', # Merchant City - '6304', # CRC16 + '000201', # Payload Format Indicator + '010212', # Dynamic QR Codes + f'26{len(merchant_account_info):02}{merchant_account_info}', # Merchant Account Information + '52040000', # Merchant Category Code + f'5303{currency_code}', # Transaction Currency + f'54{len(str(amount)):02}{amount}', # Transaction Amount + f'5802{self.partner_id.country_code}', # Country Code + f'59{len(merchant_name):02}{merchant_name}', # Merchant Name + f'60{len(merchant_city):02}{merchant_city}', # Merchant City ] + + if additional_data_field: + qr_code_vals.append(f'62{len(additional_data_field):02}{additional_data_field}') # Additional Data Field + + qr_code_vals.append('6304') # CRC16 crc = self._get_crc16(bytes(''.join(qr_code_vals), 'utf-8')) qr_code_vals.append(format(crc, '04x').upper()) return qr_code_vals diff --git a/addons/l10n_hk/models/res_bank.py b/addons/l10n_hk/models/res_bank.py index 51cb68153f9..56861fc5eb9 100644 --- a/addons/l10n_hk/models/res_bank.py +++ b/addons/l10n_hk/models/res_bank.py @@ -12,7 +12,7 @@ class ResPartnerBank(models.Model): country_code = fields.Char(related='partner_id.country_code', string="Country Code") l10n_hk_fps_type = fields.Selection([('id', "FPS ID"), ('mobile', "Mobile Number"), ('email', "Email Address")], string='FPS Type') - l10n_hk_fps_identifier = fields.Char(string="FPS ID/Mobile Number/Email Address") + l10n_hk_fps_identifier = fields.Char(string="FPS Identifier", help="FPS ID, Mobile Number or Email Address") @api.constrains('l10n_hk_fps_type', 'l10n_hk_fps_identifier') def _check_l10n_hk_fps_identifier(self): @@ -41,6 +41,9 @@ class ResPartnerBank(models.Model): return f'0012hk.com.hkicl{fps_account}' return super()._get_merchant_account_info() + def _get_additional_data_field(self, comment): + return f'05{len(comment):02}{comment}' + def _get_error_messages_for_qr(self, qr_method, debtor_partner, currency): if qr_method == 'emv_qr' and self.country_code == 'HK': if currency.name not in ['HKD', 'CNY']: diff --git a/addons/l10n_hk/tests/test_l10n_hk_emv_qr.py b/addons/l10n_hk/tests/test_l10n_hk_emv_qr.py index 9c6a5fc1b61..708e5225342 100644 --- a/addons/l10n_hk/tests/test_l10n_hk_emv_qr.py +++ b/addons/l10n_hk/tests/test_l10n_hk_emv_qr.py @@ -74,16 +74,16 @@ class TestL10nHKEmvQrCode(AccountTestInvoicingCommon): def test_emv_qr_vals(self): self.emv_qr_invoice.qr_code_method = 'emv_qr' - unstruct_ref = self.emv_qr_invoice.ref or self.emv_qr_invoice.name + demo_payment_reference = 'INV/TEST/0001' emv_qr_vals = self.emv_qr_invoice.partner_bank_id._get_qr_vals( qr_method=self.emv_qr_invoice.qr_code_method, amount=self.emv_qr_invoice.amount_residual, currency=self.emv_qr_invoice.currency_id, debtor_partner=self.emv_qr_invoice.partner_id, - free_communication=unstruct_ref, - structured_communication=self.emv_qr_invoice.payment_reference, + free_communication=demo_payment_reference, + structured_communication=demo_payment_reference, ) # Check the whole qr code string qr_code_string = ''.join(emv_qr_vals) - self.assertEqual(qr_code_string, '00020101021226330012hk.com.hkicl0313+852-678912345204000053033445405100.05802HK5914company_1_data6002HK6304CD39') + self.assertEqual(qr_code_string, '00020101021226330012hk.com.hkicl0313+852-678912345204000053033445405100.05802HK5914company_1_data6002HK62170513INV/TEST/00016304264C')