Update: Add EUR currency support for Slovak companies
- Modified get_cz_qr_code_base64() to support both CZK and EUR - Updated cz_to_iban() to better handle international IBANs (SK, etc.) - SPAYD QR now uses actual invoice currency in CC: field - Updated manifest description to reflect EUR support - Updated README with setup instructions for Slovak companies This allows Slovak companies with EUR accounts to generate SPAYD QR codes for Czech customers, enabling cross-border EUR payments via mobile banking. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
@@ -1,24 +1,81 @@
|
||||
🇨🇿 [Česká verze](README.cs.md)
|
||||
|
||||
# Czech QR Payments
|
||||
# Czech QR Payments (SPAYD)
|
||||
|
||||
This module adds QR codes to invoices for quick mobile payments. The codes are in SPAYD format, compatible with all major Czech banking apps.
|
||||
This module adds **SPAYD format QR codes** to invoices for quick mobile payments via Czech banking apps. Compatible with all major Czech banks (ČSOB, Komerční banka, Česká spořitelna, Raiffeisenbank, etc.).
|
||||
|
||||
* **Bank account format:** Enter Czech bank accounts in the standard Odoo field using the Czech format, e.g., `123-456/0800`
|
||||

|
||||
## ✅ Supported Features
|
||||
|
||||
* **Foreign accounts:** For foreign accounts, you can enter IBAN in the same field (standard Odoo field).
|
||||
* **Currency support:** Czech QR codes are generated for invoices in CZK currency. For foreign payments, the original Odoo QR code is preserved.
|
||||
* **Bank account formats:**
|
||||
- Czech local format: `123-456/0800` (automatically converted to IBAN)
|
||||
- IBAN format: `CZ6508000000001234567890`, `SK6509000000005123456789`, etc.
|
||||

|
||||
|
||||
* **Currency support:**
|
||||
- ✅ **CZK** - Standard Czech payments
|
||||
- ✅ **EUR** - Cross-border payments (for Slovak companies invoicing Czech customers)
|
||||
- ❌ Other currencies - Not supported (SPAYD is primarily for CZK and EUR)
|
||||
|
||||
* **Use cases:**
|
||||
- Czech company invoicing Czech customers in CZK
|
||||
- **Slovak company invoicing Czech customers in EUR** (your use case!)
|
||||
- Any company with a CZ/SK/EU IBAN invoicing Czech customers
|
||||
|
||||
## ⚡ Quick Setup for Slovak Companies
|
||||
|
||||
If you are a **Slovak company** invoicing **Czech customers in EUR**:
|
||||
|
||||
1. **Set up your EUR bank account:**
|
||||
- Go to **Accounting → Configuration → Journals**
|
||||
- Select your bank journal
|
||||
- In the **Bank Account** field, enter your **EUR IBAN** (e.g., `SK6509000000005123456789`)
|
||||
- Set **Currency** to **EUR**
|
||||
|
||||
2. **Create invoice for Czech customer:**
|
||||
- Set customer country to **Czech Republic (CZ)**
|
||||
- Set invoice currency to **EUR**
|
||||
- Confirm the invoice (post it)
|
||||
|
||||
3. **QR code generates automatically!**
|
||||
- The QR code will be in **SPAYD format** with `CC:EUR`
|
||||
- Czech customers can scan it with their banking app
|
||||
- Payment will be processed in EUR to your account
|
||||
|
||||
## Frequently Asked Questions (FAQ)
|
||||
|
||||
**The QR code is not generated on the invoice**
|
||||
Make sure you have the **QR Codes** option enabled in the **Invoicing** app configuration.
|
||||
**Q: The QR code is not generated on the invoice**
|
||||
A: Make sure you have:
|
||||
- The **QR Codes** option enabled in the **Invoicing** app configuration
|
||||
- A bank account set up for your company with the **same currency as the invoice** (EUR or CZK)
|
||||
- The invoice is **confirmed/posted**
|
||||

|
||||
|
||||
|
||||
**The QR code is generated on the invoice, but scanning it results in an error**
|
||||
Check whether a bank account for the Czech currency is set up for the main company. See "Bank account format" section above.
|
||||
**Q: The QR code is generated on the invoice, but scanning it results in an error**
|
||||
A: Check whether:
|
||||
- A bank account for the **invoice currency** (EUR or CZK) is set up for the company
|
||||
- The bank account number is in **valid format** (Czech format `123-456/0800` or IBAN)
|
||||
- The customer's banking app supports **SPAYD QR codes**
|
||||
|
||||
|
||||
**Q: Can I use EUR currency with this module?**
|
||||
A: ✅ **Yes!** This module now supports both **CZK and EUR** currencies. Perfect for Slovak companies invoicing Czech customers in EUR.
|
||||
|
||||
|
||||
**Q: Does this work with Slovak (SK) IBAN?**
|
||||
A: ✅ **Yes!** The module handles any valid IBAN (SK, CZ, DE, AT, etc.). If your bank account is already an IBAN, it will be used as-is.
|
||||
|
||||
|
||||
**Q: Can I use this for invoices in other currencies (USD, GBP)?**
|
||||
A: ❌ **No.** The SPAYD standard is designed for CZK and EUR. Other currencies are not supported by Czech banking apps via QR codes.
|
||||
|
||||
|
||||
**Q: I'm a Slovak company. Will Czech customers be able to pay EUR invoices via QR code?**
|
||||
A: ✅ **Yes**, if:
|
||||
- Your bank account is a **EUR account** (Slovak or international)
|
||||
- The invoice currency is **EUR**
|
||||
- The Czech customer's bank supports **cross-border EUR payments** (most do)
|
||||
- The QR code will contain `CC:EUR` and your SK/EUR IBAN
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
+22
-5
@@ -4,18 +4,35 @@
|
||||
'depends': ['account', 'base', 'l10n_cz'],
|
||||
'countries': ['cz'],
|
||||
'category': 'Accounting',
|
||||
'summary': 'Add Czech standard QR codes for payment to your invoices.',
|
||||
'summary': 'Add Czech standard QR codes (SPAYD) for payment to your invoices.',
|
||||
'description': """
|
||||
|
||||
Czech QR Payment Generator
|
||||
==========================
|
||||
Allow to generate czech banks compliant QR code for payment on the invoice, if the invoice currency is "CZK"
|
||||
Czech QR Payment Generator (SPAYD)
|
||||
===================================
|
||||
Allow to generate Czech banks compliant QR code for payment on the invoice.
|
||||
|
||||
Supports:
|
||||
---------
|
||||
* **CZK currency** - Standard Czech payments
|
||||
* **EUR currency** - For Slovak companies and international businesses invoicing Czech customers
|
||||
|
||||
Key Features:
|
||||
-------------
|
||||
* **Standard SPAYD Support:** Fully compatible with all major Czech banking apps.
|
||||
* **Standard SPAYD Support:** Fully compatible with all major Czech banking apps (ČSOB, Komerční banka, Česká spořitelna, etc.)
|
||||
* **Smart IBAN Conversion:** Automatically converts local account numbers (e.g. 123-456/0800) to IBAN format.
|
||||
* **Multi-country IBAN Support:** Works with Czech (CZ), Slovak (SK), and other SEPA IBANs.
|
||||
* **Integration:** Works with standard Odoo invoice templates.
|
||||
* **Currency Support:** CZK and EUR (for cross-border payments).
|
||||
|
||||
Usage for Slovak Companies:
|
||||
---------------------------
|
||||
If you are a Slovak company invoicing Czech customers in EUR:
|
||||
1. Set up your EUR bank account in Odoo
|
||||
2. Create invoice for Czech customer in EUR currency
|
||||
3. QR code will be automatically generated in SPAYD format
|
||||
4. Czech customer can scan and pay via their banking app
|
||||
|
||||
Note: Czech banks will process EUR payments if the recipient has a EUR account.
|
||||
""",
|
||||
'author': 'Ash technology s.r.o.',
|
||||
'website': 'https://github.com/ash-technology/l10n_cz_extra',
|
||||
|
||||
+23
-9
@@ -9,10 +9,14 @@ class AccountMove(models.Model):
|
||||
def get_cz_qr_code_base64(self):
|
||||
""" Returns Base64 PNG image for the invoice PDF """
|
||||
self.ensure_one()
|
||||
if self.currency_id.name != 'CZK':
|
||||
|
||||
# Support both EUR and CZK currencies
|
||||
# (for Slovak companies invoicing Czech customers in EUR)
|
||||
allowed_currencies = ['CZK', 'EUR']
|
||||
if self.currency_id.name not in allowed_currencies:
|
||||
return False
|
||||
|
||||
# Find bank: 1. Matching CZK, 2. No currency set (default)
|
||||
# Find bank: 1. Matching currency, 2. No currency set (default)
|
||||
bank = self.company_id.partner_id.bank_ids.filtered(lambda b: b.currency_id == self.currency_id)[:1]
|
||||
if not bank:
|
||||
bank = self.company_id.partner_id.bank_ids.filtered(lambda b: not b.currency_id)[:1]
|
||||
@@ -21,11 +25,13 @@ class AccountMove(models.Model):
|
||||
return False
|
||||
|
||||
# Build SPAYD string
|
||||
# Note: cz_to_iban handles both CZ format (123-456/0800) and IBAN format (SK..., CZ..., etc.)
|
||||
iban = self.cz_to_iban(bank.acc_number)
|
||||
amount = '%.2f' % self.amount_residual
|
||||
vs = ''.join(filter(str.isdigit, self.payment_reference or ''))[-10:]
|
||||
currency = self.currency_id.name or 'EUR'
|
||||
|
||||
spayd = f"SPD*1.0*ACC:{iban}*AM:{amount}*CC:CZK*X-VS:{vs}"
|
||||
spayd = f"SPD*1.0*ACC:{iban}*AM:{amount}*CC:{currency}*X-VS:{vs}"
|
||||
|
||||
# Generate QR Image
|
||||
qr = qrcode.make(spayd)
|
||||
@@ -35,23 +41,31 @@ class AccountMove(models.Model):
|
||||
|
||||
def cz_to_iban(self, acc_number):
|
||||
"""
|
||||
Converts '123-456/0800' or '456/0800' to a valid CZ IBAN.
|
||||
Converts Czech account number formats to IBAN.
|
||||
|
||||
Supports:
|
||||
- Czech local format: '123-456/0800' or '456/0800'
|
||||
- IBAN format: 'CZ6508000000001234567890', 'SK6509000000005123456789', etc.
|
||||
|
||||
Returns:
|
||||
str: Valid IBAN (uppercase) or original input if conversion fails
|
||||
"""
|
||||
if not acc_number:
|
||||
return ""
|
||||
|
||||
# Clean the input
|
||||
clean_acc = acc_number.replace(" ", "")
|
||||
clean_acc = acc_number.replace(" ", "").upper()
|
||||
|
||||
# If already an IBAN, return it
|
||||
if clean_acc.upper().startswith('CZ'):
|
||||
return clean_acc.upper()
|
||||
# If already an IBAN (any country), return it
|
||||
# IBAN format: 2-letter country code + 2-digit checksum + account number
|
||||
if len(clean_acc) >= 4 and clean_acc[:2].isalpha() and clean_acc[2:4].isdigit():
|
||||
return clean_acc
|
||||
|
||||
try:
|
||||
# Split into [prefix-main, bank_code]
|
||||
parts = clean_acc.split('/')
|
||||
if len(parts) != 2:
|
||||
return clean_acc # Fallback
|
||||
return clean_acc # Fallback for non-CZ format
|
||||
|
||||
bank_code = parts[1]
|
||||
account_parts = parts[0].split('-')
|
||||
|
||||
Reference in New Issue
Block a user