Initial commit: L10N_Europe packages
70
odoo-bringout-oca-ocb-l10n_ch/README.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Switzerland - Accounting
|
||||
|
||||
|
||||
Swiss localization
|
||||
==================
|
||||
This module defines a chart of account for Switzerland (Swiss PME/KMU 2015), taxes and enables the generation of ISR and QR-bill when you print an invoice or send it by mail.
|
||||
|
||||
An ISR will be generated if you specify the information it needs :
|
||||
- The bank account you expect to be paid on must be set, and have a valid postal reference.
|
||||
- Your invoice must have been set assigned a bank account to receive its payment
|
||||
(this can be done manually, but a default value is automatically set if you have defined a bank account).
|
||||
- You must have set the postal references of your bank.
|
||||
- Your invoice must be in EUR or CHF (as ISRs do not accept other currencies)
|
||||
|
||||
A QR-bill will be generated if:
|
||||
- The partner set on your invoice has a complete address (street, city, postal code and country) in Switzerland
|
||||
- The option to generate the Swiss QR-code is selected on the invoice (done by default)
|
||||
- A correct account number/QR IBAN is set on your bank journal
|
||||
- (when using a QR-IBAN): the payment reference of the invoice is a QR-reference
|
||||
|
||||
The generation of the ISR and QR-bill is automatic if you meet the previous criteria.
|
||||
|
||||
Here is how it works:
|
||||
- Printing the invoice will trigger the download of three files: the invoice, its ISR and its QR-bill
|
||||
- Clicking the 'Send by mail' button will attach three files to your draft mail : the invoice, the ISR and the QR-bill.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-ocb-l10n_ch
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
This addon depends on:
|
||||
- account
|
||||
- l10n_multilang
|
||||
- base_iban
|
||||
- l10n_din5008
|
||||
|
||||
## Manifest Information
|
||||
|
||||
- **Name**: Switzerland - Accounting
|
||||
- **Version**: 11.2
|
||||
- **Category**: Accounting/Localizations/Account Charts
|
||||
- **License**: LGPL-3
|
||||
- **Installable**: False
|
||||
|
||||
## Source
|
||||
|
||||
Based on [OCA/OCB](https://github.com/OCA/OCB) branch 16.0, addon `l10n_ch`.
|
||||
|
||||
## License
|
||||
|
||||
This package maintains the original LGPL-3 license from the upstream Odoo project.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Overview: doc/OVERVIEW.md
|
||||
- Architecture: doc/ARCHITECTURE.md
|
||||
- Models: doc/MODELS.md
|
||||
- Controllers: doc/CONTROLLERS.md
|
||||
- Wizards: doc/WIZARDS.md
|
||||
- Install: doc/INSTALL.md
|
||||
- Usage: doc/USAGE.md
|
||||
- Configuration: doc/CONFIGURATION.md
|
||||
- Dependencies: doc/DEPENDENCIES.md
|
||||
- Troubleshooting: doc/TROUBLESHOOTING.md
|
||||
- FAQ: doc/FAQ.md
|
||||
32
odoo-bringout-oca-ocb-l10n_ch/doc/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
U[Users] -->|HTTP| V[Views and QWeb Templates]
|
||||
V --> C[Controllers]
|
||||
V --> W[Wizards – Transient Models]
|
||||
C --> M[Models and ORM]
|
||||
W --> M
|
||||
M --> R[Reports]
|
||||
DX[Data XML] --> M
|
||||
S[Security – ACLs and Groups] -. enforces .-> M
|
||||
|
||||
subgraph L10n_ch Module - l10n_ch
|
||||
direction LR
|
||||
M:::layer
|
||||
W:::layer
|
||||
C:::layer
|
||||
V:::layer
|
||||
R:::layer
|
||||
S:::layer
|
||||
DX:::layer
|
||||
end
|
||||
|
||||
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
|
||||
```
|
||||
|
||||
Notes
|
||||
- Views include tree/form/kanban templates and report templates.
|
||||
- Controllers provide website/portal routes when present.
|
||||
- Wizards are UI flows implemented with `models.TransientModel`.
|
||||
- Data XML loads data/demo records; Security defines groups and access.
|
||||
3
odoo-bringout-oca-ocb-l10n_ch/doc/CONFIGURATION.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Configuration
|
||||
|
||||
Refer to Odoo settings for l10n_ch. Configure related models, access rights, and options as needed.
|
||||
3
odoo-bringout-oca-ocb-l10n_ch/doc/CONTROLLERS.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Controllers
|
||||
|
||||
This module does not define custom HTTP controllers.
|
||||
8
odoo-bringout-oca-ocb-l10n_ch/doc/DEPENDENCIES.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Dependencies
|
||||
|
||||
This addon depends on:
|
||||
|
||||
- [account](../../odoo-bringout-oca-ocb-account)
|
||||
- [l10n_multilang](../../odoo-bringout-oca-ocb-l10n_multilang)
|
||||
- [base_iban](../../odoo-bringout-oca-ocb-base_iban)
|
||||
- [l10n_din5008](../../odoo-bringout-oca-ocb-l10n_din5008)
|
||||
4
odoo-bringout-oca-ocb-l10n_ch/doc/FAQ.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# FAQ
|
||||
|
||||
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
|
||||
- Q: How to enable? A: Start server with --addon l10n_ch or install in UI.
|
||||
7
odoo-bringout-oca-ocb-l10n_ch/doc/INSTALL.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Install
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-ocb-l10n_ch"
|
||||
# or
|
||||
uv pip install odoo-bringout-oca-ocb-l10n_ch"
|
||||
```
|
||||
19
odoo-bringout-oca-ocb-l10n_ch/doc/MODELS.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Models
|
||||
|
||||
Detected core models and extensions in l10n_ch.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class account_bank_statement_line
|
||||
class account_chart_template
|
||||
class account_journal
|
||||
class account_move
|
||||
class ir_actions_report
|
||||
class res_company
|
||||
class res_config_settings
|
||||
class res_partner_bank
|
||||
```
|
||||
|
||||
Notes
|
||||
- Classes show model technical names; fields omitted for brevity.
|
||||
- Items listed under _inherit are extensions of existing models.
|
||||
6
odoo-bringout-oca-ocb-l10n_ch/doc/OVERVIEW.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Overview
|
||||
|
||||
Packaged Odoo addon: l10n_ch. Provides features documented in upstream Odoo 16 under this addon.
|
||||
|
||||
- Source: OCA/OCB 16.0, addon l10n_ch
|
||||
- License: LGPL-3
|
||||
30
odoo-bringout-oca-ocb-l10n_ch/doc/REPORTS.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Reports
|
||||
|
||||
Report definitions and templates in l10n_ch.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ReportSwissQR
|
||||
AbstractModel <|-- ReportSwissQR
|
||||
```
|
||||
|
||||
## Available Reports
|
||||
|
||||
### PDF/Document Reports
|
||||
- **QR-bill** (PDF/Print)
|
||||
- **QR-bill Header** (PDF/Print)
|
||||
- **ISR** (PDF/Print)
|
||||
|
||||
|
||||
## Report Files
|
||||
|
||||
- **__init__.py** (Python logic)
|
||||
- **isr_report.xml** (XML template/definition)
|
||||
- **swissqr_report.py** (Python logic)
|
||||
- **swissqr_report.xml** (XML template/definition)
|
||||
|
||||
## Notes
|
||||
- Named reports above are accessible through Odoo's reporting menu
|
||||
- Python files define report logic and data processing
|
||||
- XML files contain report templates, definitions, and formatting
|
||||
- Reports are integrated with Odoo's printing and email systems
|
||||
34
odoo-bringout-oca-ocb-l10n_ch/doc/SECURITY.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Security
|
||||
|
||||
Access control and security definitions in l10n_ch.
|
||||
|
||||
## Access Control Lists (ACLs)
|
||||
|
||||
Model access permissions defined in:
|
||||
- **[ir.model.access.csv](../l10n_ch/security/ir.model.access.csv)**
|
||||
- 1 model access rules
|
||||
|
||||
## Record Rules
|
||||
|
||||
Row-level security rules defined in:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Security Layers"
|
||||
A[Users] --> B[Groups]
|
||||
B --> C[Access Control Lists]
|
||||
C --> D[Models]
|
||||
B --> E[Record Rules]
|
||||
E --> F[Individual Records]
|
||||
end
|
||||
```
|
||||
|
||||
Security files overview:
|
||||
- **[ir.model.access.csv](../l10n_ch/security/ir.model.access.csv)**
|
||||
- Model access permissions (CRUD rights)
|
||||
|
||||
Notes
|
||||
- Access Control Lists define which groups can access which models
|
||||
- Record Rules provide row-level security (filter records by user/group)
|
||||
- Security groups organize users and define permission sets
|
||||
- All security is enforced at the ORM level by Odoo
|
||||
5
odoo-bringout-oca-ocb-l10n_ch/doc/TROUBLESHOOTING.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Troubleshooting
|
||||
|
||||
- Ensure Python and Odoo environment matches repo guidance.
|
||||
- Check database connectivity and logs if startup fails.
|
||||
- Validate that dependent addons listed in DEPENDENCIES.md are installed.
|
||||
7
odoo-bringout-oca-ocb-l10n_ch/doc/USAGE.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Usage
|
||||
|
||||
Start Odoo including this addon (from repo root):
|
||||
|
||||
```bash
|
||||
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon l10n_ch
|
||||
```
|
||||
9
odoo-bringout-oca-ocb-l10n_ch/doc/WIZARDS.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Wizards
|
||||
|
||||
Transient models exposed as UI wizards in l10n_ch.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class QrInvoiceWizard
|
||||
class SwissSetupBarBankConfigWizard
|
||||
```
|
||||
31
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/__init__.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
||||
from . import report
|
||||
from . import wizard
|
||||
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
|
||||
def load_translations(env):
|
||||
env.ref('l10n_ch.l10nch_chart_template').process_coa_translations()
|
||||
|
||||
|
||||
def init_settings(env):
|
||||
'''If the company is localized in Switzerland, activate the cash rounding by default.
|
||||
'''
|
||||
# The cash rounding is activated by default only if the company is localized in Switzerland or Liechtenstein.
|
||||
for company in env['res.company'].search([('partner_id.country_id.code', 'in', ["CH", "LI"])]):
|
||||
res_config_id = env['res.config.settings'].create({
|
||||
'company_id': company.id,
|
||||
'group_cash_rounding': True
|
||||
})
|
||||
# We need to call execute, otherwise the "implied_group" in fields are not processed.
|
||||
res_config_id.execute()
|
||||
|
||||
|
||||
def post_init(cr, registry):
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
load_translations(env)
|
||||
init_settings(env)
|
||||
72
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/__manifest__.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
# Main contributor: Nicolas Bessi. Camptocamp SA
|
||||
# Financial contributors: Hasa SA, Open Net SA,
|
||||
# Prisme Solutions Informatique SA, Quod SA
|
||||
# Translation contributors: brain-tec AG, Agile Business Group
|
||||
{
|
||||
'name': "Switzerland - Accounting",
|
||||
'description': """
|
||||
Swiss localization
|
||||
==================
|
||||
This module defines a chart of account for Switzerland (Swiss PME/KMU 2015), taxes and enables the generation of ISR and QR-bill when you print an invoice or send it by mail.
|
||||
|
||||
An ISR will be generated if you specify the information it needs :
|
||||
- The bank account you expect to be paid on must be set, and have a valid postal reference.
|
||||
- Your invoice must have been set assigned a bank account to receive its payment
|
||||
(this can be done manually, but a default value is automatically set if you have defined a bank account).
|
||||
- You must have set the postal references of your bank.
|
||||
- Your invoice must be in EUR or CHF (as ISRs do not accept other currencies)
|
||||
|
||||
A QR-bill will be generated if:
|
||||
- The partner set on your invoice has a complete address (street, city, postal code and country) in Switzerland
|
||||
- The option to generate the Swiss QR-code is selected on the invoice (done by default)
|
||||
- A correct account number/QR IBAN is set on your bank journal
|
||||
- (when using a QR-IBAN): the payment reference of the invoice is a QR-reference
|
||||
|
||||
The generation of the ISR and QR-bill is automatic if you meet the previous criteria.
|
||||
|
||||
Here is how it works:
|
||||
- Printing the invoice will trigger the download of three files: the invoice, its ISR and its QR-bill
|
||||
- Clicking the 'Send by mail' button will attach three files to your draft mail : the invoice, the ISR and the QR-bill.
|
||||
""",
|
||||
'version': '11.2',
|
||||
'category': 'Accounting/Localizations/Account Charts',
|
||||
|
||||
'depends': ['account', 'l10n_multilang', 'base_iban', 'l10n_din5008'],
|
||||
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'data/l10n_ch_chart_data.xml',
|
||||
'data/account.account.template.csv',
|
||||
'data/l10n_ch_chart_post_data.xml',
|
||||
'data/account_tax_group_data.xml',
|
||||
'data/account_tax_report_data.xml',
|
||||
'data/account_vat2011_data.xml',
|
||||
'data/account_tax_template_data_2024.xml',
|
||||
'data/account_fiscal_position_data.xml',
|
||||
'data/account_fiscal_position_data_2024.xml',
|
||||
'data/account_chart_template_data.xml',
|
||||
'report/isr_report.xml',
|
||||
'report/swissqr_report.xml',
|
||||
'views/res_bank_view.xml',
|
||||
'views/account_invoice_view.xml',
|
||||
'views/account_invoice.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/setup_wizard_views.xml',
|
||||
'views/qr_invoice_wizard_view.xml'
|
||||
],
|
||||
|
||||
'demo': [
|
||||
'demo/account_cash_rounding.xml',
|
||||
'demo/demo_company.xml',
|
||||
'demo/res_partner_demo.xml',
|
||||
],
|
||||
'post_init_hook': 'post_init',
|
||||
'assets': {
|
||||
'web.report_assets_common': [
|
||||
'l10n_ch/static/src/scss/**/*',
|
||||
],
|
||||
},
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
"id","name","code","account_type","chart_template_id/id","reconcile"
|
||||
"ch_coa_1060","Securities (with stock exchange price)","1060","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1069","Accumulated depreciation on securities","1069","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1091","Transfer account: Salaries","1091","asset_current","l10n_ch.l10nch_chart_template","True"
|
||||
"ch_coa_1099","Transfer account: miscellaneous","1099","asset_current","l10n_ch.l10nch_chart_template","True"
|
||||
"ch_coa_1100","Accounts receivable from goods and services (Debtors)","1100","asset_receivable","l10n_ch.l10nch_chart_template","True"
|
||||
"ch_coa_1101","Receivable (PoS)","1101","asset_receivable","l10n_ch.l10nch_chart_template","True"
|
||||
"ch_coa_1109","Del credere (Acc. depr. on debtors)","1109","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1140","Advances and loans","1140","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1149","Advances and loans adjustments","1149","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1170","Input Tax (VAT) receivable on material, goods, services, energy","1170","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1171","Input Tax (VAT) receivable on investments, other operating expenses","1171","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1176","Withholding Tax (WT) receivable","1176","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1180","Receivables from social insurances and social security institutions","1180","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1189","Withholding tax","1189","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1190","Other short-term receivables","1190","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1199","Accumulated depreciation on short-terms receivables","1199","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1200","Goods / Merchandise (Trade)","1200","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1207","Accumulated depreciation on Goods / Merchandise (Trade)","1207","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1208","Downpayment on Goods / Merchandise (Trade)","1208","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1209","Correction on Goods / Merchandise (Trade)","1209","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1210","Raw materials","1210","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1217","Accumulated depreciation on raw material","1217","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1218","Downpayment on raw material","1218","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1219","Correction on raw material","1219","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1220","Auxiliary material","1220","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1230","Consumables","1230","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1250","Consignments Goods ","1250","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1260","Finished products","1260","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1267","Accumulated depreciation on Finished products","1267","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1269","Correction on Finished products","1269","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1270","Products in process / Unfinished products","1270","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1277","Accumulated depreciation on Products in process / Unfinished products","1277","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1279","Correction on Products in process / Unfinished products","1279","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1280","Work in progress","1280","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1287","Accumulated depreciation on work in progress","1287","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1289","Correction on work in progress","1289","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1300","Accrued revenue and deferred expense (Accounts paid in advance)","1300","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1301","Deferred expense (Accounts paid in advance)","1301","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1400","Long-term securities","1400","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1409","Accumulated depreciation on long-term securities","1409","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1440","Loan (Asset)","1440","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1441","Mortgages","1441","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1449","Accumulated depreciation on long term receivables","1449","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1480","Participations","1480","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1489","Accumulated depreciation on participations","1489","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1500","Machinery","1500","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1509","Accumulated depreciation on machinery","1509","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1510","Equipment","1510","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1519","Accumulated depreciation on equipment","1519","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1520","Office Equipment (including Information & Communication Technology)","1520","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1529","Accumulated depreciation on office equipment (incl. ICT)","1529","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1530","Vehicles","1530","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1539","Accumulated depreciation on vehicles","1539","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1540","Tools","1540","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1549","Accumulated depreciation on tools","1549","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1550","Warehouse","1550","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1559","Accumulated depreciation on warehouse","1559","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1570","Equipments and Facilities","1570","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1579","Accumulated depreciation on Equipments and Facilities","1579","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1590","Other movable tangible assets","1590","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1599","Accumulated depreciation on Other movable tangible assets","1599","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1600","Real Estate","1600","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1609","Accumulated depreciation on real estate","1609","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1700","Patents, Licences","1700","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1709","Accumulated depreciation on Patents, Licences","1709","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1770","Goodwill","1770","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1779","Accumulated depreciation on goodwill","1779","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_1850","Non-paid-in share capital","1850","asset_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2000","Accounts payable from goods and services (Creditors)","2000","liability_payable","l10n_ch.l10nch_chart_template","True"
|
||||
"ch_coa_2030","Prepayments received","2030","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2100","Bank Overdraft (Bank)","2100","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2120","Leasing bondings","2120","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2140","Other interest-bearing short terms liabilities","2140","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2160","Dettes envers l'actionnaire","2160","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2200","Sales Tax (VAT) owed","2200","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2201","VAT payable","2201","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2206","Withholding Tax (WT) owed","2206","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2208","Direct Taxes","2208","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2210","Others short term liabilities","2210","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2261","Dividend payouts resolved (Dividends)","2261","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2270","Social insurances owed","2270","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2279","Withholding taxes","2279","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2300","Deferred revenue and accrued expenses (Accounts received in advance)","2300","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2301","Deferred revenue (Accounts Received in Advance)","2301","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2330","Short-term provisions","2330","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2400","Bank debts","2400","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2420","Finance lease commitments","2420","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2430","Debentures","2430","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2450","Loans","2450","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2451","Mortgages","2451","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2500","Other long term liabilities","2500","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2600","Long-term provisions","2600","liability_current","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2800","Share capital","2800","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2900","Legal capital reserves","2900","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2940","Valuation Reserves","2940","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2950","Legal retained earnings (Reserves)","2950","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2960","Voluntary retained earnings","2960","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2970","Profits brought forward / Losses brought forward","2970","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2979","Annual profit or annual loss","2979","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_2980","Treasury stock, shares, participation rights (negative item) ","2980","equity","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3000","Sales of products (Manufacturing)","3000","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3009","Deductions on sales","3009","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3200","Sales of goods (Trade)","3200","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3400","Revenues from services","3400","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3600","Other revenues","3600","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3700","Own services","3700","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3710","Own consumption","3710","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3800","Financial discount","3800","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3801","Discounts and price reduction","3801","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3802","Rebates","3802","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3803","Third-party commissions","3803","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3804","Collection fees","3804","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3805","Losses from bad debts","3805","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3806","Exchange rate differences","3806","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3807","Shipping & Returns","3807","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3900","Changes in inventories of unfinished and finished products","3900","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3901","Change in inventories of finished goods","3901","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_3940","Change in the value of unbilled services","3940","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4000","Cost of raw materials (Manufacturing)","4000","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4008","Inventory changes","4008","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4009","Deductions obtained on purchases","4009","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4070","Purchase Loans","4070","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4071","Customs duties on importation","4071","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4072","Transport costs at purchase","4072","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4080","Inventory changes","4080","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4086","Loss of material","4086","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4200","Cost of materials (Trade)","4200","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4400","Cost of purchased services","4400","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4500","Electricity","4500","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4510","Gas","4510","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4520","Fuel oil","4520","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4521","Coal, briquettes, wood","4521","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4530","Petrol","4530","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4540","Water","4540","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4800","Change in inventories of goods","4800","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4801","Change in raw material inventories","4801","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4900","Financial Discounts","4900","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4901","Discounts and price reductions","4901","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4991","Cash Difference Loss","4991","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4992","Cash Difference Gain","4992","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4092","Rebates","4902","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4903","Commissions on purchases","4903","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_4906","Exchange rate differences","4906","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_5000","Wages and salaries","5000","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_5700","Social benefits","5700","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_5800","Other staff cost","5800","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_5900","Temporary staff expenditures","5900","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6000","Rent","6000","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6100","Maintenance & repair expenses","6100","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6105","Leasing movable tangible fixed assets","6105","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6200","Vehicle expenses","6200","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6260","Vehicules leasing and renting","6260","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6300","Insurance premiums","6300","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6400","Energy expenses & disposal expenses","6400","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6500","Administration expenses","6500","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6570","IT leasing","6570","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6600","Promotion and advertising expenses","6600","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6700","Other operating expenses","6700","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6800","Depreciations","6800","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6900","Financial expenses (Interest expenses, Securities expenses, Participations expenses)","6900","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_6950","Financial revenues (Interest revenues, Securities revenues, Participations revenues)","6950","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_7000","Non-core business revenues","7000","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_7010","Non-core business expenses","7010","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_7500","Revenues from operational real estate","7500","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_7510","Expenses from operational real estate","7510","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_8000","Non-operational expenses","8000","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_8100","Non-operational revenues","8100","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_8500","Extraordinary expenses","8500","expense","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_8510","Extraordinary revenues","8510","income","l10n_ch.l10nch_chart_template","False"
|
||||
"ch_coa_8900","Direct Taxes","8900","expense","l10n_ch.l10nch_chart_template","False"
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<function model="account.chart.template" name="try_loading">
|
||||
<value eval="[ref('l10n_ch.l10nch_chart_template')]"/>
|
||||
</function>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Fiscal Position Templates -->
|
||||
<record id="fiscal_position_template_1" model="account.fiscal.position.template">
|
||||
<field name="name">Suisse national (+Liechtenstein)</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="auto_apply" eval="True"/>
|
||||
<field name="country_group_id" ref="base.ch_and_li"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_template_import" model="account.fiscal.position.template">
|
||||
<field name="sequence">1</field>
|
||||
<field name="name">Import/Export</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="auto_apply" eval="True"/>
|
||||
</record>
|
||||
|
||||
<!-- Fiscal Position Tax Templates (pre-2024 rates change) -->
|
||||
<record id="fiscal_position_tax_template_3" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_25_purchase" />
|
||||
<field name="tax_dest_id" ref="vat_O_import" />
|
||||
</record>
|
||||
<record id="fiscal_position_tax_template_4" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_25_invest" />
|
||||
<field name="tax_dest_id" ref="vat_O_import" />
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_5" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_37_purchase" />
|
||||
<field name="tax_dest_id" ref="vat_O_import" />
|
||||
</record>
|
||||
<record id="fiscal_position_tax_template_6" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_37_invest" />
|
||||
<field name="tax_dest_id" ref="vat_O_import" />
|
||||
</record>
|
||||
|
||||
|
||||
<record id="fiscal_position_tax_template_9" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_77_purchase_reverse" />
|
||||
<field name="tax_dest_id" ref="vat_O_import" />
|
||||
</record>
|
||||
<record id="fiscal_position_tax_template_10" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_77_invest" />
|
||||
<field name="tax_dest_id" ref="vat_O_import" />
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_14" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_25" />
|
||||
<field name="tax_dest_id" ref="vat_XO" />
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_15" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_37" />
|
||||
<field name="tax_dest_id" ref="vat_XO" />
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_17" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import" />
|
||||
<field name="tax_src_id" ref="vat_77" />
|
||||
<field name="tax_dest_id" ref="vat_XO" />
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Fiscal Position Tax Templates (post-2024 rates change) -->
|
||||
<record id="fiscal_position_tax_template_1_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_purchase_26"/>
|
||||
<field name="tax_dest_id" ref="vat_O_import"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_2_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_purchase_26_invest"/>
|
||||
<field name="tax_dest_id" ref="vat_O_import"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_3_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_purchase_38"/>
|
||||
<field name="tax_dest_id" ref="vat_O_import"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_4_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_purchase_38_invest"/>
|
||||
<field name="tax_dest_id" ref="vat_O_import"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_5_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_purchase_81_reverse"/>
|
||||
<field name="tax_dest_id" ref="vat_O_import"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_6_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_purchase_81_invest"/>
|
||||
<field name="tax_dest_id" ref="vat_O_import"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_7_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_sale_26"/>
|
||||
<field name="tax_dest_id" ref="vat_XO"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_8_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_sale_38"/>
|
||||
<field name="tax_dest_id" ref="vat_XO"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_template_9_2024" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_template_import"/>
|
||||
<field name="tax_src_id" ref="vat_sale_81"/>
|
||||
<field name="tax_dest_id" ref="vat_XO"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Account Tax Group (pre-2024 rates change) -->
|
||||
<record id="tax_group_tva_0" model="account.tax.group">
|
||||
<field name="name">VAT 0%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
<record id="tax_group_tva_25" model="account.tax.group">
|
||||
<field name="name">VAT 2.5%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
<record id="tax_group_tva_37" model="account.tax.group">
|
||||
<field name="name">VAT 3.7%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
<record id="tax_group_tva_77" model="account.tax.group">
|
||||
<field name="name">VAT 7.7%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
<record id="tax_group_tva_100" model="account.tax.group">
|
||||
<field name="name">VAT 100%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
<!-- Account Tax Group (post-2024 rates change) -->
|
||||
<record id="tax_group_vat_26" model="account.tax.group">
|
||||
<field name="name">VAT 2.6%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
<record id="tax_group_vat_38" model="account.tax.group">
|
||||
<field name="name">VAT 3.8%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
<record id="tax_group_vat_81" model="account.tax.group">
|
||||
<field name="name">VAT 8.1%</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,474 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="tax_report" model="account.report">
|
||||
<field name="name">Tax Report</field>
|
||||
<field name="root_report_id" ref="account.generic_tax_report"/>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
<field name="filter_fiscal_position" eval="True"/>
|
||||
<field name="availability_condition">country</field>
|
||||
<field name="column_ids">
|
||||
<record id="tax_report_balance" model="account.report.column">
|
||||
<field name="name">Balance</field>
|
||||
<field name="expression_label">balance</field>
|
||||
</record>
|
||||
</field>
|
||||
<field name="line_ids">
|
||||
<record id="account_tax_report_line_chiffre_af" model="account.report.line">
|
||||
<field name="name">I. TURNOVER</field>
|
||||
<field name="sequence" eval="0"/> <!-- Sequence is force to avoid order problem when updating within the same version. -->
|
||||
<field name="children_ids">
|
||||
<record id="account_tax_report_line_chtax_200" model="account.report.line">
|
||||
<field name="name">200 - Total amount of agreed or collected consideration incl. from supplies opted for taxation, transfer of supplies acc. to the notification procedure and supplies provided abroad (worldwide turnover)</field>
|
||||
<field name="code">tax_ch_200</field>
|
||||
<field name="aggregation_formula">tax_ch_302a.balance + tax_ch_303a.balance + tax_ch_312a.balance + tax_ch_313a.balance + tax_ch_342a.balance + tax_ch_343a.balance + tax_ch_205.balance + tax_ch_289.balance</field>
|
||||
<field name="sequence" eval="1"/>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_205" model="account.report.line">
|
||||
<field name="name">205 - Consideration reported in Ref. 200 from supplies exempt from the tax without credit (art. 21) where the option for their taxation according to art. 22 has been exercised</field>
|
||||
<field name="code">tax_ch_205</field>
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_205_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">205</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_220_289" model="account.report.line"> <!-- FIXME in master: the xml is as it is for historical reasons but it does represent box 220 only -->
|
||||
<field name="name">220 - Supplies exempt from the tax (e.g. export, art. 23) and supplies provided to institutional and individual beneficiaries that are exempt from liability for tax (art. 107 para. 1 lit. a)</field>
|
||||
<field name="code">tax_ch_220</field>
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_220_289_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">220</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_221" model="account.report.line">
|
||||
<field name="name">221 - Supplies provided abroad</field>
|
||||
<field name="code">tax_ch_221</field>
|
||||
<field name="sequence" eval="4"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_221_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">221</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_225" model="account.report.line">
|
||||
<field name="name">225 - Transfer of supplies according to the notification procedure (art. 38, please submit Form 764)</field>
|
||||
<field name="code">tax_ch_225</field>
|
||||
<field name="sequence" eval="5"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_225_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">225</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_230" model="account.report.line">
|
||||
<field name="name">230 - Supplies provided on Swiss territory exempt from the tax without credit (art. 21) and where the option for their taxation according to art. 22 has not been exercised</field>
|
||||
<field name="code">tax_ch_230</field>
|
||||
<field name="sequence" eval="6"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_230_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">230</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_235" model="account.report.line">
|
||||
<field name="name">235 - Reduction of consideration (discounts, rebates etc.)</field>
|
||||
<field name="code">tax_ch_235</field>
|
||||
<field name="sequence" eval="7"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_235_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">235</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_280" model="account.report.line">
|
||||
<field name="name">280 - Miscellaneous (e.g. land value, purchase prices in case of margin taxation)</field>
|
||||
<field name="code">tax_ch_280</field>
|
||||
<field name="sequence" eval="8"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_280_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">280</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_289" model="account.report.line">
|
||||
<field name="name">289 - Deductions (Total Ref. 220 to 280)</field>
|
||||
<field name="code">tax_ch_289</field>
|
||||
<field name="aggregation_formula">tax_ch_220.balance + tax_ch_221.balance + tax_ch_225.balance + tax_ch_230.balance + tax_ch_235.balance + tax_ch_280.balance</field>
|
||||
<field name="sequence" eval="9"/>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_299" model="account.report.line">
|
||||
<field name="name">299 - Taxable turnover (Ref. 200 minus Ref. 289)</field>
|
||||
<field name="aggregation_formula">tax_ch_200.balance - tax_ch_289.balance</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_calc_impot" model="account.report.line">
|
||||
<field name="name">II - TAX CALCULATION</field>
|
||||
<field name="sequence" eval="11"/>
|
||||
<field name="children_ids">
|
||||
<record id="account_tax_report_line_supplies_1" model="account.report.line">
|
||||
<field name="name">Supplies CHF from 01.01.2024</field>
|
||||
<field name="sequence" eval="12"/>
|
||||
<field name="children_ids">
|
||||
<record id="account_tax_report_line_chtax_303a" model="account.report.line">
|
||||
<field name="name">303a - Standard rate (8,1%): Supplies CHF from 01.01.2024</field>
|
||||
<field name="code">tax_ch_303a</field>
|
||||
<field name="sequence" eval="13"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_303a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">303a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_313a" model="account.report.line">
|
||||
<field name="name">313a - Reduced rate (2,6%): Supplies CHF from 01.01.2024</field>
|
||||
<field name="code">tax_ch_313a</field>
|
||||
<field name="sequence" eval="14"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_313a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">313a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_343a" model="account.report.line">
|
||||
<field name="name">343a - Accommodation rate (3,8%): Supplies CHF from 01.01.2024</field>
|
||||
<field name="code">tax_ch_343a</field>
|
||||
<field name="sequence" eval="15"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_343a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">343a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_383a" model="account.report.line">
|
||||
<field name="name">383a - Acquisition tax: Supplies CHF from 01.01.2024</field>
|
||||
<field name="code">tax_ch_383a</field>
|
||||
<field name="sequence" eval="16"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_383a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">383a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_supplies_2" model="account.report.line">
|
||||
<field name="name">Supplies CHF to 31.12.2023</field>
|
||||
<field name="sequence" eval="17"/>
|
||||
<field name="children_ids">
|
||||
<record id="account_tax_report_line_chtax_302a" model="account.report.line">
|
||||
<field name="name">302a - Standard rate (7,7%): Supplies CHF to 31.12.2023</field>
|
||||
<field name="code">tax_ch_302a</field>
|
||||
<field name="sequence" eval="18"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_302a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">302a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_312a" model="account.report.line">
|
||||
<field name="name">312a - Reduced rate (2,5%): Supplies CHF to 31.12.2023</field>
|
||||
<field name="code">tax_ch_312a</field>
|
||||
<field name="sequence" eval="19"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_312a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">312a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_342a" model="account.report.line">
|
||||
<field name="name">342a - Accommodation rate (3,7%): Supplies CHF to 31.12.2023</field>
|
||||
<field name="code">tax_ch_342a</field>
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_342a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">342a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_382a" model="account.report.line">
|
||||
<field name="name">382a - Acquisition tax: Supplies CHF to 31.12.2023</field>
|
||||
<field name="code">tax_ch_382a</field>
|
||||
<field name="sequence" eval="21"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_382a_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">382a</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_tax_amount_1" model="account.report.line">
|
||||
<field name="name">Tax amount CHF / cent. from 01.01.2024</field>
|
||||
<field name="sequence" eval="22"/>
|
||||
<field name="children_ids">
|
||||
<record id="account_tax_report_line_chtax_303b" model="account.report.line">
|
||||
<field name="name">303b - Standard rate (8,1%): Tax amount CHF / cent. from 01.01.2024</field>
|
||||
<field name="code">tax_ch_303b</field>
|
||||
<field name="sequence" eval="23"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_303b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">303b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_313b" model="account.report.line">
|
||||
<field name="name">313b - Reduced rate (2,6%): Tax amount CHF / cent. from 01.01.2024</field>
|
||||
<field name="code">tax_ch_313b</field>
|
||||
<field name="sequence" eval="24"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_313b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">313b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_343b" model="account.report.line">
|
||||
<field name="name">343b - Accommodation rate (3,8%): Tax amount CHF / cent. from 01.01.2024</field>
|
||||
<field name="code">tax_ch_343b</field>
|
||||
<field name="sequence" eval="25"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_343b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">343b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_383b" model="account.report.line">
|
||||
<field name="name">383b - Acquisition tax: Tax amount CHF / cent. from 01.01.2024</field>
|
||||
<field name="code">tax_ch_383b</field>
|
||||
<field name="sequence" eval="26"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_383b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">383b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_tax_amount_2" model="account.report.line">
|
||||
<field name="name">Tax amount CHF / cent. to 31.12.2023</field>
|
||||
<field name="sequence" eval="27"/>
|
||||
<field name="children_ids">
|
||||
<record id="account_tax_report_line_chtax_302b" model="account.report.line">
|
||||
<field name="name">302b - Standard rate (7,7%): Tax amount CHF / cent. to 31.12.2023</field>
|
||||
<field name="code">tax_ch_302b</field>
|
||||
<field name="sequence" eval="28"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_302b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">302b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_312b" model="account.report.line">
|
||||
<field name="name">312b - Reduced rate (2,5%): Tax amount CHF / cent. to 31.12.2023</field>
|
||||
<field name="code">tax_ch_312b</field>
|
||||
<field name="sequence" eval="29"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_312b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">312b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_342b" model="account.report.line">
|
||||
<field name="name">342b - Accommodation rate (3,7%): Tax amount CHF / cent. to 31.12.2023</field>
|
||||
<field name="code">tax_ch_342b</field>
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_342b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">342b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_382b" model="account.report.line">
|
||||
<field name="name">382b - Acquisition tax: Tax amount CHF / cent. to 31.12.2023</field>
|
||||
<field name="code">tax_ch_382b</field>
|
||||
<field name="sequence" eval="31"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_382b_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">382b</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_399" model="account.report.line">
|
||||
<field name="name">399 - Total amount of tax due</field>
|
||||
<field name="code">tax_ch_399</field>
|
||||
<field name="aggregation_formula">tax_ch_302b.balance + tax_ch_303b.balance + tax_ch_312b.balance + tax_ch_313b.balance + tax_ch_342b.balance + tax_ch_343b.balance + tax_ch_382b.balance + tax_ch_383b.balance</field>
|
||||
<field name="sequence" eval="32"/>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_400" model="account.report.line">
|
||||
<field name="name">400 - Input tax on cost of materials and supplies of services</field>
|
||||
<field name="code">tax_ch_400</field>
|
||||
<field name="sequence" eval="33"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_400_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">400</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_405" model="account.report.line">
|
||||
<field name="name">405 - Input tax on investments and other operating costs</field>
|
||||
<field name="code">tax_ch_405</field>
|
||||
<field name="sequence" eval="34"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_405_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">405</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_410" model="account.report.line">
|
||||
<field name="name">410 - De-taxation (art. 32)</field>
|
||||
<field name="code">tax_ch_410</field>
|
||||
<field name="sequence" eval="35"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_410_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">410</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_415" model="account.report.line">
|
||||
<field name="name">415 - Correction of the input tax deduction: mixed use (art. 30), own use (art. 31)</field>
|
||||
<field name="code">tax_ch_415</field>
|
||||
<field name="sequence" eval="36"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_415_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">415</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_420" model="account.report.line">
|
||||
<field name="name">420 - Reduction of the input tax deduction: Flow of funds, which are not deemed to be consideration, such as subsidies, tourist charges (art. 33 para. 2)</field>
|
||||
<field name="code">tax_ch_420</field>
|
||||
<field name="sequence" eval="37"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_420_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">420</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_479" model="account.report.line">
|
||||
<field name="name">479 - Total Ref. 400 to 420</field>
|
||||
<field name="code">tax_ch_479</field>
|
||||
<field name="aggregation_formula">tax_ch_400.balance + tax_ch_405.balance + tax_ch_410.balance - tax_ch_415.balance - tax_ch_420.balance</field>
|
||||
<field name="sequence" eval="38"/>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_500" model="account.report.line">
|
||||
<field name="name">500 - Amount payable</field>
|
||||
<field name="sequence" eval="39"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_500_formula" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">aggregation</field>
|
||||
<field name="formula">tax_ch_399.balance - tax_ch_479.balance</field>
|
||||
<field name="subformula">if_above(CHF(0))</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_510" model="account.report.line">
|
||||
<field name="name">510 - Credit in favour of the taxable person</field>
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_510_formula" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">aggregation</field>
|
||||
<field name="formula">tax_ch_479.balance - tax_ch_399.balance</field>
|
||||
<field name="subformula">if_above(CHF(0))</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_autres_mouv" model="account.report.line">
|
||||
<field name="name">III. OTHER CASH FLOWS</field>
|
||||
<field name="aggregation_formula">tax_ch_900.balance + tax_ch_910.balance</field>
|
||||
<field name="sequence" eval="41"/>
|
||||
<field name="children_ids">
|
||||
<record id="account_tax_report_line_chtax_900" model="account.report.line">
|
||||
<field name="name">900 - Subsidies, tourist funds collected by tourist offices, contributions from cantonal water, sewage or waste funds (art. 18 para. 2 lit. a to c)</field>
|
||||
<field name="code">tax_ch_900</field>
|
||||
<field name="sequence" eval="42"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_900_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">900</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_tax_report_line_chtax_910" model="account.report.line">
|
||||
<field name="name">910 - Donations, dividends, payments of damages etc. (art. 18 para. 2 lit. d to l)</field>
|
||||
<field name="code">tax_ch_910</field>
|
||||
<field name="sequence" eval="43"/>
|
||||
<field name="expression_ids">
|
||||
<record id="account_tax_report_line_chtax_910_tag" model="account.report.expression">
|
||||
<field name="label">balance</field>
|
||||
<field name="engine">tax_tags</field>
|
||||
<field name="formula">910</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,563 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Account Tax Templates (post-2024 rates change) -->
|
||||
<record model="account.tax.template" id="vat_sale_26">
|
||||
<field name="name">2.6% Sales</field>
|
||||
<field name="description">2.6%</field>
|
||||
<field name="amount" eval="2.6"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_26"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_313a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_313b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_313a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_313b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_sale_26_incl">
|
||||
<field name="name">2.6% Sales (incl.)</field>
|
||||
<field name="description">2.6% incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="2.6"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_26"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_313a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_313b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_313a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_313b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_26">
|
||||
<field name="name">2.6% on goods and services</field>
|
||||
<field name="description">2.6% purch.</field>
|
||||
<field name="amount" eval="2.6"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_26"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_26_incl">
|
||||
<field name="name">2.6% on goods and services (incl.)</field>
|
||||
<field name="description">2.6% purch. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="2.6"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_26"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_26_invest">
|
||||
<field name="name">2.6% on invest. and others expenses</field>
|
||||
<field name="description">2.6% invest.</field>
|
||||
<field name="amount" eval="2.6"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_26"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_26_invest_incl">
|
||||
<field name="name">2.6% on invest. and others expenses (incl.)</field>
|
||||
<field name="description">2.6% invest. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="2.6"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_26"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_sale_38">
|
||||
<field name="name">3.8% Sales</field>
|
||||
<field name="description">3.8%</field>
|
||||
<field name="amount" eval="3.8"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_38"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_343a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_343b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_343a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_343b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_sale_38_incl">
|
||||
<field name="name">3.8% Sales (incl.)</field>
|
||||
<field name="description">3.8% Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="3.8"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_38"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_343a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_343b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_343a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_343b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_38">
|
||||
<field name="name">3.8% on goods and services</field>
|
||||
<field name="description">3.8% purch.</field>
|
||||
<field name="amount" eval="3.8"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_38"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_38_incl">
|
||||
<field name="name">3.8% on goods and services (incl.)</field>
|
||||
<field name="description">3.8% purch. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="3.8"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_38"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_38_invest">
|
||||
<field name="name">3.8% on invest. and others expenses</field>
|
||||
<field name="description">3.8% invest</field>
|
||||
<field name="amount" eval="3.8"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_38"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_38_invest_incl">
|
||||
<field name="name">3.8% on invest. and others expenses (incl.)</field>
|
||||
<field name="description">3.8% invest Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="3.8"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_38"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_sale_81">
|
||||
<field name="name">8.1% Sales</field>
|
||||
<field name="description">8.1%</field>
|
||||
<field name="amount" eval="8.1"/>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_81"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_303a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_303b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_303a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_303b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_sale_81_incl">
|
||||
<field name="name">8.1% Sales (incl.)</field>
|
||||
<field name="description">8.1% Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="8.1"/>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_81"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_303a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_303b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_303a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_303b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_81">
|
||||
<field name="name">8.1% on goods and services</field>
|
||||
<field name="description">8.1% purch.</field>
|
||||
<field name="amount" eval="8.1"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_81"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_81_incl">
|
||||
<field name="name">8.1% on goods and services (incl.)</field>
|
||||
<field name="description">8.1% purch. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="8.1"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_81"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_81_invest">
|
||||
<field name="name">8.1% on invest. and others expenses</field>
|
||||
<field name="description">8.1% invest.</field>
|
||||
<field name="amount" eval="8.1"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_81"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_81_invest_incl">
|
||||
<field name="name">8.1% on invest. and others expenses (incl.)</field>
|
||||
<field name="description">8.1% invest. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="8.1"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_81"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<record model="account.tax.template" id="vat_purchase_81_return">
|
||||
<field name="name">8.1% Purchase (reverse)</field>
|
||||
<field name="description">8.1% purch. (reverse)</field>
|
||||
<field name="amount" eval="-8.1"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_383a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_383b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_383a_tag')],
|
||||
}),
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_383b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
<!--# for reverse charge or VAT on Acquisition (group of taxes)-->
|
||||
<record model="account.tax.template" id="vat_purchase_81_reverse">
|
||||
<field name="name">8.1% on purchase of service abroad (reverse charge)</field>
|
||||
<field name="description">8.1% rev</field>
|
||||
<field name="amount_type">group</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_vat_81"/>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="children_tax_ids" eval="[(6, 0, [ref('vat_purchase_81'), ref('vat_purchase_81_return')])]"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,777 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- # TVA - Taxe sur la Valeur Ajoutée (pre-2024 rates change) -->
|
||||
<record model="account.tax.template" id="vat_25">
|
||||
<field name="name">2.5% Sales</field>
|
||||
<field name="description">2.50%</field>
|
||||
<field name="amount" eval="2.5"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_25"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_312a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_312b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_312a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_312b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_25_incl">
|
||||
<field name="name">2.5% Sales (incl.)</field>
|
||||
<field name="description">2.5% Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="2.5"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_25"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_312a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_312b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_312a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_312b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_25_purchase">
|
||||
<field name="name">2.5% on goods and services</field>
|
||||
<field name="description">2.5% purch.</field>
|
||||
<field name="amount" eval="2.5"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_25"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_25_purchase_incl">
|
||||
<field name="name">2.5% on goods and services (incl.)</field>
|
||||
<field name="description">2.5% purch. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="2.5"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_25"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_25_invest">
|
||||
<field name="name">2.5% on invest. and others expenses</field>
|
||||
<field name="description">2.5% invest.</field>
|
||||
<field name="amount" eval="2.5"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_25"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_25_invest_incl">
|
||||
<field name="name">2.5% on invest. and others expenses (incl.)</field>
|
||||
<field name="description">2.5% invest. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="2.5"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_25"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_37">
|
||||
<field name="name">3.7% Sales</field>
|
||||
<field name="description">3.70%</field>
|
||||
<field name="amount" eval="3.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_37"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_342a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_342b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_342a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_342b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_37_incl">
|
||||
<field name="name">3.7% Sales (incl.)</field>
|
||||
<field name="description">3.7% Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="3.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_37"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_342a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_342b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_342a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_342b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_37_purchase">
|
||||
<field name="name">3.7% on goods and services</field>
|
||||
<field name="description">3.7% purch.</field>
|
||||
<field name="amount" eval="3.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_37"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_37_purchase_incl">
|
||||
<field name="name">3.7% on goods and services (incl.)</field>
|
||||
<field name="description">3.7% purch. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="3.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_37"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_37_invest">
|
||||
<field name="name">3.7% on invest. and others expenses</field>
|
||||
<field name="description">3.7% invest</field>
|
||||
<field name="amount" eval="3.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_37"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_37_invest_incl">
|
||||
<field name="name">3.7% on invest. and others expenses (incl.)</field>
|
||||
<field name="description">3.7% invest Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="3.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_37"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_77">
|
||||
<field name="name">7.7% Sales</field>
|
||||
<field name="description">7.70%</field>
|
||||
<field name="amount" eval="7.7"/>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_302a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_302b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_302a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_302b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_77_incl">
|
||||
<field name="name">7.7% Sales (incl.)</field>
|
||||
<field name="description">7.7% Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="7.7"/>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_302a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_302b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_302a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_2200'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_302b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_77_purchase_incl">
|
||||
<field name="name">7.7% on goods and services (incl.)</field>
|
||||
<field name="description">7.7% purch. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="7.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_77_invest">
|
||||
<field name="name">7.7% on invest. and others expenses</field>
|
||||
<field name="description">7.7% invest.</field>
|
||||
<field name="amount" eval="7.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_77_invest_incl">
|
||||
<field name="name">7.7% on invest. and others expenses (incl.)</field>
|
||||
<field name="description">7.7% invest. Incl.</field>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="amount" eval="7.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_XO">
|
||||
<field name="name">0% Export</field>
|
||||
<field name="amount" eval="0.00"/>
|
||||
<field name="description">0%</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_0"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_220_289_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_220_289_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_O_exclude">
|
||||
<field name="name">0% Excluded</field>
|
||||
<field name="description">0% excl.</field>
|
||||
<field name="amount" eval="0.00"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_0"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_230_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_230_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_O_import">
|
||||
<field name="name">0% Import</field>
|
||||
<field name="description">0% import.</field>
|
||||
<field name="amount" eval="0.00"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_0"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_100_import">
|
||||
<field name="name">Customs VAT on goods and services</field>
|
||||
<field name="description">100% imp.</field>
|
||||
<field name="amount" eval="100"/>
|
||||
<field name="amount_type">division</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_100"/>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_100_import_invest">
|
||||
<field name="name">Customs VAT on invest. and others expenses</field>
|
||||
<field name="description">100% imp.invest.</field>
|
||||
<field name="amount" eval="100"/>
|
||||
<field name="amount_type">division</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_100"/>
|
||||
<field name="price_include" eval="1"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1171'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_405_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_77_purchase_return">
|
||||
<field name="name">7.7% Purchase (reverse)</field>
|
||||
<field name="description">7.7% purch. (return)</field>
|
||||
<field name="amount" eval="-7.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="type_tax_use">none</field>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_382a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_382b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_382a_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_382b_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_77_purchase">
|
||||
<field name="name">7.7% on goods and services</field>
|
||||
<field name="description">7.7% purch.</field>
|
||||
<field name="amount" eval="7.7"/>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {'repartition_type': 'base'}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': ref('ch_coa_1170'),
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_400_tag')],
|
||||
}),
|
||||
]"/>
|
||||
</record>
|
||||
<!--# for reverse charge or VAT on Acquisition (group of taxes)-->
|
||||
<record model="account.tax.template" id="vat_77_purchase_reverse">
|
||||
<field name="description">7.7% rev.</field>
|
||||
<field name="name">7.7% on purchase of service abroad (reverse charge)</field>
|
||||
<field name="amount_type">group</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="tax_group_id" ref="tax_group_tva_77"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="children_tax_ids" eval="[(6, 0, [ref('vat_77_purchase_return'), ref('vat_77_purchase')])]"/>
|
||||
</record>
|
||||
<!-- Taxes for other movements -->
|
||||
<record model="account.tax.template" id="vat_other_movements_900">
|
||||
<field name="name">0% - Subsidies, tourist taxes</field>
|
||||
<field name="amount" eval="0.00"/>
|
||||
<field name="description">0% subventions</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_0"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_900_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_900_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
</record>
|
||||
<record model="account.tax.template" id="vat_other_movements_910">
|
||||
<field name="name">0% - Donations, dividends, compensation</field>
|
||||
<field name="amount" eval="0.00"/>
|
||||
<field name="description">0% dons</field>
|
||||
<field name="amount_type">percent</field>
|
||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="tax_group_id" ref="tax_group_tva_0"/>
|
||||
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'plus_report_expression_ids': [ref('account_tax_report_line_chtax_910_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
'minus_report_expression_ids': [ref('account_tax_report_line_chtax_910_tag')],
|
||||
}),
|
||||
|
||||
(0,0, {'repartition_type': 'tax'}),
|
||||
]"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- Account Tags -->
|
||||
<record id="l10nch_chart_template" model="account.chart.template">
|
||||
<field name="name">Plan comptable 2015 (Suisse)</field>
|
||||
<field name="code_digits">4</field>
|
||||
<field name="bank_account_code_prefix">102</field>
|
||||
<field name="cash_account_code_prefix">100</field>
|
||||
<field name="transfer_account_code_prefix">1090</field>
|
||||
<field name="currency_id" ref="base.CHF"/>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
<field name="spoken_languages" eval="'it_IT;de_DE;de_CH;fr_FR;fr_CH'"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="l10nch_chart_template" model="account.chart.template">
|
||||
<field name="property_account_receivable_id" ref="ch_coa_1100"/>
|
||||
<field name="property_account_payable_id" ref="ch_coa_2000"/>
|
||||
<field name="property_account_expense_categ_id" ref="ch_coa_4200"/>
|
||||
<field name="property_account_income_categ_id" ref="ch_coa_3200"/>
|
||||
<field name="income_currency_exchange_account_id" ref="ch_coa_3806"/>
|
||||
<field name="expense_currency_exchange_account_id" ref="ch_coa_4906"/>
|
||||
<field name="default_pos_receivable_account_id" ref="ch_coa_1101" />
|
||||
<field name="account_journal_early_pay_discount_loss_account_id" ref="ch_coa_4901"/>
|
||||
<field name="account_journal_early_pay_discount_gain_account_id" ref="ch_coa_3801"/>
|
||||
<field name="property_tax_payable_account_id" ref="ch_coa_2201"/>
|
||||
<field name="property_tax_receivable_account_id" ref="ch_coa_1176"/>
|
||||
<field name="default_cash_difference_expense_account_id" ref="ch_coa_4991"/>
|
||||
<field name="default_cash_difference_income_account_id" ref="ch_coa_4992"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="cash_rounding_5_centime" model="account.cash.rounding">
|
||||
<field name="name">Coinage 0.05</field>
|
||||
<field name="rounding">0.05</field>
|
||||
<field name="strategy">add_invoice_line</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
40
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/demo/demo_company.xml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="partner_demo_company_ch" model="res.partner">
|
||||
<field name="name">CH Company</field>
|
||||
<field name="vat">CHE-530781296TVA</field>
|
||||
<field name="street">14 Meierskappelerstrasse</field>
|
||||
<field name="city">Risch-Rotkreuz</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
|
||||
<field name="zip">6343</field>
|
||||
<field name="phone">+41 78 123 45 67</field>
|
||||
<field name="email">info@company.chexample.com</field>
|
||||
<field name="website">www.chexample.com</field>
|
||||
</record>
|
||||
|
||||
<record id="partner_demo_company_bank_account" model="res.partner.bank">
|
||||
<field name="acc_type">iban</field>
|
||||
<field name="acc_number">CH4431999123000889012</field>
|
||||
<field name="partner_id" ref="l10n_ch.partner_demo_company_ch"/>
|
||||
</record>
|
||||
|
||||
<record id="demo_company_ch" model="res.company">
|
||||
<field name="name">CH Company</field>
|
||||
<field name="partner_id" ref="partner_demo_company_ch"/>
|
||||
</record>
|
||||
|
||||
<function model="res.company" name="_onchange_country_id">
|
||||
<value eval="[ref('demo_company_ch')]"/>
|
||||
</function>
|
||||
|
||||
<function model="res.users" name="write">
|
||||
<value eval="[ref('base.user_root'), ref('base.user_admin'), ref('base.user_demo')]"/>
|
||||
<value eval="{'company_ids': [(4, ref('l10n_ch.demo_company_ch'))]}"/>
|
||||
</function>
|
||||
|
||||
<function model="account.chart.template" name="try_loading">
|
||||
<value eval="[ref('l10n_ch.l10nch_chart_template')]"/>
|
||||
<value model="res.company" eval="obj().env.ref('l10n_ch.demo_company_ch')"/>
|
||||
</function>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="res_partner_ch_qr" model="res.partner">
|
||||
<field name="name">Easy Clean Lausanne</field>
|
||||
<field eval="[Command.set([ref('base.res_partner_category_11')])]" name="category_id"/>
|
||||
<field name="is_company">1</field>
|
||||
<field name="city">Lausanne</field>
|
||||
<field name="zip">1004</field>
|
||||
<field name="country_id" ref="base.ch"/>
|
||||
<field name="street">Rte de Prilly 18, 1004 Lausanne, Suisse</field>
|
||||
<field name="email">info@easycleanlausanne.ch</field>
|
||||
<field name="phone">+41 21 796 73 24</field>
|
||||
<field name="website">http://www.easycleanlausanne.ch</field>
|
||||
<field name='vat'>CHE-123.456.788 TVA</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_iban_main_partner_ch" model="res.partner.bank">
|
||||
<field name="acc_type">iban</field>
|
||||
<field name="acc_number">CH11 3000 5228 1308 3501 F</field>
|
||||
<field name="partner_id" ref="l10n_ch.res_partner_ch_qr"/>
|
||||
</record>
|
||||
</odoo>
|
||||
2623
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/ar.po
Normal file
2683
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/de.po
Normal file
2664
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/fr.po
Normal file
2664
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/fr_BE.po
Normal file
2661
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/it.po
Normal file
2621
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/l10n_ch.pot
Normal file
2623
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/nl.po
Normal file
2621
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/i18n/zh_CN.po
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
""" From 12.0, to saas-13.3, l10n_ch_swissqr_template
|
||||
used to inherit from another template. This isn't the case
|
||||
anymore since https://github.com/odoo/odoo/commit/719f087b1b5be5f1f276a0f87670830d073f6ef4
|
||||
(made in 12.0, and forward-ported). The module will not be updatable if we
|
||||
don't manually clean inherit_id.
|
||||
"""
|
||||
cr.execute("""
|
||||
update ir_ui_view v
|
||||
set inherit_id = NULL, mode='primary'
|
||||
from ir_model_data mdata
|
||||
where
|
||||
v.id = mdata.res_id
|
||||
and mdata.model= 'ir.ui.view'
|
||||
and mdata.name = 'l10n_ch_swissqr_template'
|
||||
and mdata.module='l10n_ch';
|
||||
""")
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo import api, SUPERUSER_ID
|
||||
from odoo.addons.account.models.chart_template import update_taxes_from_templates
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
# We had corrupted data, handle the correction so the tax update can proceed.
|
||||
# See https://github.com/odoo/odoo/commit/7b07df873535446f97abc1de9176b9332de5cb07
|
||||
for company in env.companies:
|
||||
taxes_to_check = (f'{company.id}_vat_purchase_81_reverse', f'{company.id}_vat_77_purchase_reverse')
|
||||
tax_ids = env['ir.model.data'].search([
|
||||
('name', 'in', taxes_to_check),
|
||||
('model', '=', 'account.tax'),
|
||||
]).mapped('res_id')
|
||||
for tax in env['account.tax'].browse(tax_ids).with_context(active_test=False):
|
||||
for child in tax.children_tax_ids:
|
||||
if child.type_tax_use not in ('none', tax.type_tax_use):
|
||||
# set the child to it's parent's value
|
||||
child.type_tax_use = tax.type_tax_use
|
||||
|
||||
# Update taxes
|
||||
update_taxes_from_templates(cr, 'l10n_ch.l10nch_chart_template')
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
cr.execute("SELECT res_id FROM ir_model_data WHERE module = 'l10n_ch' AND name='account_tax_report_line_chtax_solde_formula'")
|
||||
|
||||
expression_id = cr.fetchone()
|
||||
|
||||
if expression_id:
|
||||
cr.execute(
|
||||
"DELETE FROM account_report_external_value WHERE target_report_expression_id = %s",
|
||||
[expression_id[0]]
|
||||
)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import odoo
|
||||
|
||||
def migrate(cr, version):
|
||||
registry = odoo.registry(cr.dbname)
|
||||
from odoo.addons.account.models.chart_template import migrate_set_tags_and_taxes_updatable
|
||||
migrate_set_tags_and_taxes_updatable(cr, registry, 'l10n_ch')
|
||||
|
||||
11
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/models/__init__.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import res_config_settings
|
||||
from . import account_invoice
|
||||
from . import account_journal
|
||||
from . import res_bank
|
||||
from . import res_company
|
||||
from . import account_bank_statement
|
||||
from . import ir_actions_report
|
||||
from . import chart_template
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.addons.l10n_ch.models.res_bank import _is_l10n_ch_postal
|
||||
from odoo.tools.misc import str2bool
|
||||
|
||||
|
||||
class AccountBankStatementLine(models.Model):
|
||||
|
||||
_inherit = "account.bank.statement.line"
|
||||
|
||||
def _find_or_create_bank_account(self):
|
||||
if self.company_id.account_fiscal_country_id.code in ('CH', 'LI') and _is_l10n_ch_postal(self.account_number):
|
||||
bank_account = self.env['res.partner.bank'].search(
|
||||
[('company_id', '=', self.company_id.id),
|
||||
('sanitized_acc_number', 'like', self.account_number + '%'),
|
||||
('partner_id', '=', self.partner_id.id)])
|
||||
if not bank_account and not str2bool(
|
||||
self.env['ir.config_parameter'].sudo().get_param("account.skip_create_bank_account_on_reconcile")
|
||||
):
|
||||
bank_account = self.env['res.partner.bank'].create({
|
||||
'company_id': self.company_id.id,
|
||||
'acc_number': self.account_number + " " + self.partner_id.name,
|
||||
'partner_id': self.partner_id.id
|
||||
})
|
||||
return bank_account
|
||||
else:
|
||||
return super()._find_or_create_bank_account()
|
||||
391
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/models/account_invoice.py
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import re
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools.float_utils import float_split_str
|
||||
from odoo.tools.misc import mod10r
|
||||
|
||||
l10n_ch_ISR_NUMBER_LENGTH = 27
|
||||
l10n_ch_ISR_ID_NUM_LENGTH = 6
|
||||
|
||||
class AccountMove(models.Model):
|
||||
# NOTE
|
||||
# The ISR system is kept and taken into account up to September 2022.
|
||||
# After that, the transition to the QR system will be completed and the ISR system won't exist anymore.
|
||||
# This means that Odoo v16 shouldn't support the ISR system and all the references to it should be cleaned up by then.
|
||||
# In the versions leading to that change,
|
||||
# although the functions related to the ISR are still taken into account and still exist,
|
||||
# the QR billing is always preferred.
|
||||
|
||||
_inherit = 'account.move'
|
||||
|
||||
l10n_ch_isr_subscription = fields.Char(compute='_compute_l10n_ch_isr_subscription', help='ISR subscription number identifying your company or your bank to generate ISR.')
|
||||
l10n_ch_isr_subscription_formatted = fields.Char(compute='_compute_l10n_ch_isr_subscription', help="ISR subscription number your company or your bank, formated with '-' and without the padding zeros, to generate ISR report.")
|
||||
|
||||
l10n_ch_isr_number = fields.Char(compute='_compute_l10n_ch_isr_number', store=True, help='The reference number associated with this invoice')
|
||||
l10n_ch_isr_number_spaced = fields.Char(compute='_compute_l10n_ch_isr_number_spaced', help="ISR number split in blocks of 5 characters (right-justified), to generate ISR report.")
|
||||
|
||||
l10n_ch_isr_optical_line = fields.Char(compute="_compute_l10n_ch_isr_optical_line", help='Optical reading line, as it will be printed on ISR')
|
||||
|
||||
l10n_ch_isr_valid = fields.Boolean(compute='_compute_l10n_ch_isr_valid', help='Boolean value. True iff all the data required to generate the ISR are present')
|
||||
|
||||
l10n_ch_isr_sent = fields.Boolean(default=False, help="Boolean value telling whether or not the ISR corresponding to this invoice has already been printed or sent by mail.")
|
||||
l10n_ch_currency_name = fields.Char(related='currency_id.name', readonly=True, string="Currency Name", help="The name of this invoice's currency") #This field is used in the "invisible" condition field of the 'Print ISR' button.
|
||||
l10n_ch_isr_needs_fixing = fields.Boolean(compute="_compute_l10n_ch_isr_needs_fixing", help="Used to show a warning banner when the vendor bill needs a correct ISR payment reference. ")
|
||||
|
||||
l10n_ch_is_qr_valid = fields.Boolean(compute='_compute_l10n_ch_qr_is_valid', help="Determines whether an invoice can be printed as a QR or not")
|
||||
|
||||
@api.depends('partner_id', 'currency_id')
|
||||
def _compute_l10n_ch_qr_is_valid(self):
|
||||
for move in self:
|
||||
company_eligible = True
|
||||
|
||||
if(move.company_id.account_fiscal_country_id.code != 'CH'):
|
||||
company_eligible = False
|
||||
|
||||
if move.partner_bank_id.acc_number and move.partner_bank_id.acc_type == 'iban':
|
||||
iban = move.partner_bank_id.acc_number.replace(' ', '')
|
||||
if iban.startswith('CH') and len(iban) >= 9:
|
||||
bank_code = iban[4:9]
|
||||
if bank_code.isdigit() and 30000 <= int(bank_code) <= 31999:
|
||||
company_eligible = True
|
||||
|
||||
move.l10n_ch_is_qr_valid = (
|
||||
move.move_type == 'out_invoice'
|
||||
and move.partner_bank_id._eligible_for_qr_code('ch_qr', move.partner_id, move.currency_id, raises_error=False)
|
||||
and company_eligible
|
||||
)
|
||||
|
||||
@api.depends('partner_bank_id.l10n_ch_isr_subscription_eur', 'partner_bank_id.l10n_ch_isr_subscription_chf')
|
||||
def _compute_l10n_ch_isr_subscription(self):
|
||||
""" Computes the ISR subscription identifying your company or the bank that allows to generate ISR. And formats it accordingly"""
|
||||
def _format_isr_subscription(isr_subscription):
|
||||
#format the isr as per specifications
|
||||
currency_code = isr_subscription[:2]
|
||||
middle_part = isr_subscription[2:-1]
|
||||
trailing_cipher = isr_subscription[-1]
|
||||
middle_part = re.sub('^0*', '', middle_part)
|
||||
return currency_code + '-' + middle_part + '-' + trailing_cipher
|
||||
|
||||
def _format_isr_subscription_scanline(isr_subscription):
|
||||
# format the isr for scanline
|
||||
return isr_subscription[:2] + isr_subscription[2:-1].rjust(6, '0') + isr_subscription[-1:]
|
||||
|
||||
for record in self:
|
||||
record.l10n_ch_isr_subscription = False
|
||||
record.l10n_ch_isr_subscription_formatted = False
|
||||
if record.partner_bank_id:
|
||||
if record.currency_id.name == 'EUR':
|
||||
isr_subscription = record.partner_bank_id.l10n_ch_isr_subscription_eur
|
||||
elif record.currency_id.name == 'CHF':
|
||||
isr_subscription = record.partner_bank_id.l10n_ch_isr_subscription_chf
|
||||
else:
|
||||
#we don't format if in another currency as EUR or CHF
|
||||
continue
|
||||
|
||||
if isr_subscription:
|
||||
isr_subscription = isr_subscription.replace("-", "") # In case the user put the -
|
||||
record.l10n_ch_isr_subscription = _format_isr_subscription_scanline(isr_subscription)
|
||||
record.l10n_ch_isr_subscription_formatted = _format_isr_subscription(isr_subscription)
|
||||
|
||||
def _get_isrb_id_number(self):
|
||||
"""Hook to fix the lack of proper field for ISR-B Customer ID"""
|
||||
# FIXME
|
||||
# replace l10n_ch_postal by an other field to not mix ISR-B
|
||||
# customer ID as it forbid the following validations on l10n_ch_postal
|
||||
# number for Vendor bank accounts:
|
||||
# - validation of format xx-yyyyy-c
|
||||
# - validation of checksum
|
||||
return self.partner_bank_id.l10n_ch_postal or ''
|
||||
|
||||
@api.depends('name', 'partner_bank_id.l10n_ch_postal')
|
||||
def _compute_l10n_ch_isr_number(self):
|
||||
for record in self:
|
||||
if (record.partner_bank_id.l10n_ch_qr_iban or record.l10n_ch_isr_subscription) and record.name:
|
||||
invoice_ref = re.sub(r'\D', '', record.name)
|
||||
record.l10n_ch_isr_number = record._compute_isr_number(invoice_ref)
|
||||
else:
|
||||
record.l10n_ch_isr_number = False
|
||||
|
||||
@api.model
|
||||
def _compute_isr_number(self, invoice_ref):
|
||||
r"""Generates the ISR or QRR reference
|
||||
|
||||
An ISR references are 27 characters long.
|
||||
QRR is a recycling of ISR for QR-bills. Thus works the same.
|
||||
|
||||
The invoice sequence number is used, removing each of its non-digit characters,
|
||||
and pad the unused spaces on the left of this number with zeros.
|
||||
The last digit is a checksum (mod10r).
|
||||
|
||||
There are 2 types of references:
|
||||
|
||||
* ISR (Postfinance)
|
||||
|
||||
The reference is free but for the last
|
||||
digit which is a checksum.
|
||||
If shorter than 27 digits, it is filled with zeros on the left.
|
||||
|
||||
e.g.
|
||||
|
||||
120000000000234478943216899
|
||||
\________________________/|
|
||||
1 2
|
||||
(1) 12000000000023447894321689 | reference
|
||||
(2) 9: control digit for identification number and reference
|
||||
|
||||
* ISR-B (Indirect through a bank, requires a customer ID)
|
||||
|
||||
In case of ISR-B The firsts digits (usually 6), contain the customer ID
|
||||
at the Bank of this ISR's issuer.
|
||||
The rest (usually 20 digits) is reserved for the reference plus the
|
||||
control digit.
|
||||
If the [customer ID] + [the reference] + [the control digit] is shorter
|
||||
than 27 digits, it is filled with zeros between the customer ID till
|
||||
the start of the reference.
|
||||
|
||||
e.g.
|
||||
|
||||
150001123456789012345678901
|
||||
\____/\__________________/|
|
||||
1 2 3
|
||||
(1) 150001 | id number of the customer (size may vary)
|
||||
(2) 12345678901234567890 | reference
|
||||
(3) 1: control digit for identification number and reference
|
||||
"""
|
||||
id_number = self._get_isrb_id_number()
|
||||
if id_number:
|
||||
id_number = id_number.zfill(l10n_ch_ISR_ID_NUM_LENGTH)
|
||||
# keep only the last digits if it exceed boundaries
|
||||
full_len = len(id_number) + len(invoice_ref)
|
||||
ref_payload_len = l10n_ch_ISR_NUMBER_LENGTH - 1
|
||||
extra = full_len - ref_payload_len
|
||||
if extra > 0:
|
||||
invoice_ref = invoice_ref[extra:]
|
||||
internal_ref = invoice_ref.zfill(ref_payload_len - len(id_number))
|
||||
|
||||
return mod10r(id_number + internal_ref)
|
||||
|
||||
@api.depends('l10n_ch_isr_number')
|
||||
def _compute_l10n_ch_isr_number_spaced(self):
|
||||
def _space_isr_number(isr_number):
|
||||
to_treat = isr_number
|
||||
res = ''
|
||||
while to_treat:
|
||||
res = to_treat[-5:] + res
|
||||
to_treat = to_treat[:-5]
|
||||
if to_treat:
|
||||
res = ' ' + res
|
||||
return res
|
||||
|
||||
for record in self:
|
||||
if record.l10n_ch_isr_number:
|
||||
record.l10n_ch_isr_number_spaced = _space_isr_number(record.l10n_ch_isr_number)
|
||||
else:
|
||||
record.l10n_ch_isr_number_spaced = False
|
||||
|
||||
def _get_l10n_ch_isr_optical_amount(self):
|
||||
"""Prepare amount string for ISR optical line"""
|
||||
self.ensure_one()
|
||||
currency_code = None
|
||||
if self.currency_id.name == 'CHF':
|
||||
currency_code = '01'
|
||||
elif self.currency_id.name == 'EUR':
|
||||
currency_code = '03'
|
||||
units, cents = float_split_str(self.amount_residual, 2)
|
||||
amount_to_display = units + cents
|
||||
amount_ref = amount_to_display.zfill(10)
|
||||
optical_amount = currency_code + amount_ref
|
||||
optical_amount = mod10r(optical_amount)
|
||||
return optical_amount
|
||||
|
||||
@api.depends(
|
||||
'currency_id.name', 'amount_residual', 'name',
|
||||
'partner_bank_id.l10n_ch_isr_subscription_eur',
|
||||
'partner_bank_id.l10n_ch_isr_subscription_chf')
|
||||
def _compute_l10n_ch_isr_optical_line(self):
|
||||
r""" Compute the optical line to print on the bottom of the ISR.
|
||||
|
||||
This line is read by an OCR.
|
||||
It's format is:
|
||||
|
||||
amount>reference+ creditor>
|
||||
|
||||
Where:
|
||||
|
||||
- amount: currency and invoice amount
|
||||
- reference: ISR structured reference number
|
||||
- in case of ISR-B contains the Customer ID number
|
||||
- it can also contains a partner reference (of the debitor)
|
||||
- creditor: Subscription number of the creditor
|
||||
|
||||
An optical line can have the 2 following formats:
|
||||
|
||||
* ISR (Postfinance)
|
||||
|
||||
0100003949753>120000000000234478943216899+ 010001628>
|
||||
|/\________/| \________________________/| \_______/
|
||||
1 2 3 4 5 6
|
||||
|
||||
(1) 01 | currency
|
||||
(2) 0000394975 | amount 3949.75
|
||||
(3) 4 | control digit for amount
|
||||
(5) 12000000000023447894321689 | reference
|
||||
(6) 9: control digit for identification number and reference
|
||||
(7) 010001628: subscription number (01-162-8)
|
||||
|
||||
* ISR-B (Indirect through a bank, requires a customer ID)
|
||||
|
||||
0100000494004>150001123456789012345678901+ 010234567>
|
||||
|/\________/| \____/\__________________/| \_______/
|
||||
1 2 3 4 5 6 7
|
||||
|
||||
(1) 01 | currency
|
||||
(2) 0000049400 | amount 494.00
|
||||
(3) 4 | control digit for amount
|
||||
(4) 150001 | id number of the customer (size may vary, usually 6 chars)
|
||||
(5) 12345678901234567890 | reference
|
||||
(6) 1: control digit for identification number and reference
|
||||
(7) 010234567: subscription number (01-23456-7)
|
||||
"""
|
||||
for record in self:
|
||||
record.l10n_ch_isr_optical_line = ''
|
||||
if record.l10n_ch_isr_number and record.l10n_ch_isr_subscription and record.currency_id.name:
|
||||
# Final assembly (the space after the '+' is no typo, it stands in the specs.)
|
||||
record.l10n_ch_isr_optical_line = '{amount}>{reference}+ {creditor}>'.format(
|
||||
amount=record._get_l10n_ch_isr_optical_amount(),
|
||||
reference=record.l10n_ch_isr_number,
|
||||
creditor=record.l10n_ch_isr_subscription,
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
'move_type', 'name', 'currency_id.name',
|
||||
'partner_bank_id.l10n_ch_isr_subscription_eur',
|
||||
'partner_bank_id.l10n_ch_isr_subscription_chf')
|
||||
def _compute_l10n_ch_isr_valid(self):
|
||||
"""Returns True if all the data required to generate the ISR are present"""
|
||||
for record in self:
|
||||
record.l10n_ch_isr_valid = record.move_type == 'out_invoice' and\
|
||||
record.name and \
|
||||
record.l10n_ch_isr_subscription and \
|
||||
record.l10n_ch_currency_name in ['EUR', 'CHF']
|
||||
|
||||
@api.depends('move_type', 'partner_bank_id', 'payment_reference')
|
||||
def _compute_l10n_ch_isr_needs_fixing(self):
|
||||
for inv in self:
|
||||
if inv.move_type == 'in_invoice' and inv.company_id.account_fiscal_country_id.code in ('CH', 'LI'):
|
||||
partner_bank = inv.partner_bank_id
|
||||
needs_isr_ref = partner_bank.l10n_ch_qr_iban or partner_bank._is_isr_issuer()
|
||||
if needs_isr_ref and not inv._has_isr_ref():
|
||||
inv.l10n_ch_isr_needs_fixing = True
|
||||
continue
|
||||
inv.l10n_ch_isr_needs_fixing = False
|
||||
|
||||
def _has_isr_ref(self):
|
||||
"""Check if this invoice has a valid ISR reference (for Switzerland)
|
||||
e.g.
|
||||
12371
|
||||
000000000000000000000012371
|
||||
210000000003139471430009017
|
||||
21 00000 00003 13947 14300 09017
|
||||
"""
|
||||
self.ensure_one()
|
||||
ref = self.payment_reference or self.ref
|
||||
if not ref:
|
||||
return False
|
||||
ref = ref.replace(' ', '')
|
||||
if re.match(r'^(\d{2,27})$', ref):
|
||||
return ref == mod10r(ref[:-1])
|
||||
return False
|
||||
|
||||
def split_total_amount(self):
|
||||
""" Splits the total amount of this invoice in two parts, using the dot as
|
||||
a separator, and taking two precision digits (always displayed).
|
||||
These two parts are returned as the two elements of a tuple, as strings
|
||||
to print in the report.
|
||||
|
||||
This function is needed on the model, as it must be called in the report
|
||||
template, which cannot reference static functions
|
||||
"""
|
||||
return float_split_str(self.amount_residual, 2)
|
||||
|
||||
def action_invoice_sent(self):
|
||||
# OVERRIDE
|
||||
rslt = super(AccountMove, self).action_invoice_sent()
|
||||
if self.l10n_ch_isr_valid or self.l10n_ch_is_qr_valid:
|
||||
rslt['context']['l10n_ch_mark_isr_as_sent'] = True
|
||||
return rslt
|
||||
|
||||
@api.returns('mail.message', lambda value: value.id)
|
||||
def message_post(self, **kwargs):
|
||||
if self.env.context.get('l10n_ch_mark_isr_as_sent'):
|
||||
self.filtered(lambda inv: not inv.l10n_ch_isr_sent).write({'l10n_ch_isr_sent': True})
|
||||
return super(AccountMove, self.with_context(mail_post_autofollow=self.env.context.get('mail_post_autofollow', True))).message_post(**kwargs)
|
||||
|
||||
def _get_invoice_reference_ch_invoice(self):
|
||||
""" This sets ISR 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
|
||||
"""
|
||||
self.ensure_one()
|
||||
# l10n_ch_isr_number is not always computed at this stage, and could change value when the invoice is posted.
|
||||
# We manually compute here it to avoid this conflict.
|
||||
self._compute_l10n_ch_isr_number()
|
||||
return self.l10n_ch_isr_number
|
||||
|
||||
def _get_invoice_reference_ch_partner(self):
|
||||
""" This sets ISR 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
|
||||
"""
|
||||
self.ensure_one()
|
||||
return self.l10n_ch_isr_number
|
||||
|
||||
@api.model
|
||||
def space_qrr_reference(self, qrr_ref):
|
||||
""" Makes the provided QRR reference human-friendly, spacing its elements
|
||||
by blocks of 5 from right to left.
|
||||
"""
|
||||
spaced_qrr_ref = ''
|
||||
i = len(qrr_ref) # i is the index after the last index to consider in substrings
|
||||
while i > 0:
|
||||
spaced_qrr_ref = qrr_ref[max(i-5, 0) : i] + ' ' + spaced_qrr_ref
|
||||
i -= 5
|
||||
return spaced_qrr_ref
|
||||
|
||||
@api.model
|
||||
def space_scor_reference(self, iso11649_ref):
|
||||
""" Makes the provided SCOR reference human-friendly, spacing its elements
|
||||
by blocks of 5 from right to left.
|
||||
"""
|
||||
|
||||
return ' '.join(iso11649_ref[i:i + 4] for i in range(0, len(iso11649_ref), 4))
|
||||
|
||||
def l10n_ch_action_print_qr(self):
|
||||
'''
|
||||
Checks that all invoices can be printed in the QR format.
|
||||
If so, launches the printing action.
|
||||
Else, triggers the l10n_ch wizard that will display the informations.
|
||||
'''
|
||||
if any(x.move_type != 'out_invoice' for x in self):
|
||||
raise UserError(_("Only customers invoices can be QR-printed."))
|
||||
if False in self.mapped('l10n_ch_is_qr_valid'):
|
||||
return {
|
||||
'name': (_("Some invoices could not be printed in the QR format")),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'l10n_ch.qr_invoice.wizard',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'target': 'new',
|
||||
'context': {'active_ids': self.ids},
|
||||
}
|
||||
return self.env.ref('account.account_invoices').report_action(self)
|
||||
|
||||
def _l10n_ch_dispatch_invoices_to_print(self):
|
||||
qr_invs = self.filtered('l10n_ch_is_qr_valid')
|
||||
isr_invs = self.filtered('l10n_ch_isr_valid')
|
||||
return {
|
||||
'qr': qr_invs,
|
||||
'isr': isr_invs,
|
||||
'classic': self - qr_invs - isr_invs,
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
from odoo.addons.base_iban.models.res_partner_bank import validate_iban
|
||||
from odoo.addons.base.models.res_bank import sanitize_account_number
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
_inherit = 'account.journal'
|
||||
|
||||
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 ISR
|
||||
'''
|
||||
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_isr_number(invoice_ref)
|
||||
return order_reference
|
||||
return super()._process_reference_for_sale_order(order_reference)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountChartTemplate(models.Model):
|
||||
_inherit = 'account.chart.template'
|
||||
|
||||
# Write paperformat and report template used on company
|
||||
def _load(self, company):
|
||||
res = super(AccountChartTemplate, self)._load(company)
|
||||
if self == self.env.ref('l10n_ch.l10nch_chart_template'):
|
||||
company.write({
|
||||
'external_report_layout_id': self.env.ref('l10n_din5008.external_layout_din5008').id,
|
||||
'paperformat_id': self.env.ref('l10n_din5008.paperformat_euro_din').id
|
||||
})
|
||||
return res
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import io
|
||||
from odoo import api, models
|
||||
from odoo.tools.pdf import OdooPdfFileReader, OdooPdfFileWriter
|
||||
from pathlib import Path
|
||||
from reportlab.graphics.shapes import Drawing as ReportLabDrawing, Image as ReportLabImage
|
||||
from reportlab.lib.units import mm
|
||||
|
||||
CH_QR_CROSS_SIZE_RATIO = 0.1522 # Ratio between the side length of the Swiss QR-code cross image and the QR-code's
|
||||
CH_QR_CROSS_FILE = Path('../static/src/img/CH-Cross_7mm.png') # Image file containing the Swiss QR-code cross to add on top of the QR-code
|
||||
|
||||
class IrActionsReport(models.Model):
|
||||
_inherit = 'ir.actions.report'
|
||||
|
||||
@api.model
|
||||
def get_available_barcode_masks(self):
|
||||
rslt = super(IrActionsReport, self).get_available_barcode_masks()
|
||||
rslt['ch_cross'] = self.apply_qr_code_ch_cross_mask
|
||||
return rslt
|
||||
|
||||
@api.model
|
||||
def apply_qr_code_ch_cross_mask(self, width, height, barcode_drawing):
|
||||
assert isinstance(barcode_drawing, ReportLabDrawing)
|
||||
zoom_x = barcode_drawing.transform[0]
|
||||
zoom_y = barcode_drawing.transform[3]
|
||||
cross_width = CH_QR_CROSS_SIZE_RATIO * width
|
||||
cross_height = CH_QR_CROSS_SIZE_RATIO * height
|
||||
cross_path = Path(__file__).absolute().parent / CH_QR_CROSS_FILE
|
||||
qr_cross = ReportLabImage((width/2 - cross_width/2) / zoom_x, (height/2 - cross_height/2) / zoom_y, cross_width / zoom_x, cross_height / zoom_y, cross_path.as_posix())
|
||||
barcode_drawing.add(qr_cross)
|
||||
|
||||
def _render_qweb_pdf_prepare_streams(self, report_ref, data, res_ids=None):
|
||||
# OVERRIDE
|
||||
res = super()._render_qweb_pdf_prepare_streams(report_ref, data, res_ids)
|
||||
if not res_ids:
|
||||
return res
|
||||
report = self._get_report(report_ref)
|
||||
if self._is_invoice_report(report_ref):
|
||||
invoices = self.env[report.model].browse(res_ids)
|
||||
# Determine which invoices need a QR/ISR.
|
||||
qr_inv_ids = []
|
||||
isr_inv_ids = []
|
||||
for invoice in invoices:
|
||||
# avoid duplicating existing streams
|
||||
if report.attachment_use and report.retrieve_attachment(invoice):
|
||||
continue
|
||||
if invoice.l10n_ch_is_qr_valid:
|
||||
qr_inv_ids.append(invoice.id)
|
||||
elif invoice.company_id.country_code == 'CH' and invoice.l10n_ch_isr_valid:
|
||||
isr_inv_ids.append(invoice.id)
|
||||
# Render the additional reports.
|
||||
streams_to_append = {}
|
||||
if qr_inv_ids:
|
||||
qr_res = self._render_qweb_pdf_prepare_streams(
|
||||
'l10n_ch.l10n_ch_qr_report',
|
||||
{
|
||||
**data,
|
||||
'skip_headers': False,
|
||||
},
|
||||
res_ids=qr_inv_ids,
|
||||
)
|
||||
header = self.env.ref('l10n_ch.l10n_ch_qr_header', raise_if_not_found=False)
|
||||
if header:
|
||||
# Make a separated rendering to get the a page containing the company header. Then, merge the qr bill with it.
|
||||
|
||||
header_res = self._render_qweb_pdf_prepare_streams(
|
||||
'l10n_ch.l10n_ch_qr_header',
|
||||
{
|
||||
**data,
|
||||
'skip_headers': True,
|
||||
},
|
||||
res_ids=qr_inv_ids,
|
||||
)
|
||||
|
||||
for invoice_id, stream in qr_res.items():
|
||||
qr_pdf = OdooPdfFileReader(stream['stream'], strict=False)
|
||||
header_pdf = OdooPdfFileReader(header_res[invoice_id]['stream'], strict=False)
|
||||
|
||||
page = header_pdf.getPage(0)
|
||||
page.mergePage(qr_pdf.getPage(0))
|
||||
|
||||
output_pdf = OdooPdfFileWriter()
|
||||
output_pdf.addPage(page)
|
||||
new_pdf_stream = io.BytesIO()
|
||||
output_pdf.write(new_pdf_stream)
|
||||
streams_to_append[invoice_id] = {'stream': new_pdf_stream}
|
||||
else:
|
||||
for invoice_id, stream in qr_res.items():
|
||||
streams_to_append[invoice_id] = stream
|
||||
|
||||
if isr_inv_ids:
|
||||
isr_res = self._render_qweb_pdf_prepare_streams('l10n_ch.l10n_ch_isr_report', data, res_ids=isr_inv_ids)
|
||||
for invoice_id, stream in isr_res.items():
|
||||
streams_to_append[invoice_id] = stream
|
||||
|
||||
# Add to results
|
||||
for invoice_id, additional_stream in streams_to_append.items():
|
||||
invoice_stream = res[invoice_id]['stream']
|
||||
writer = OdooPdfFileWriter()
|
||||
writer.appendPagesFromReader(OdooPdfFileReader(invoice_stream, strict=False))
|
||||
writer.appendPagesFromReader(OdooPdfFileReader(additional_stream['stream'], strict=False))
|
||||
new_pdf_stream = io.BytesIO()
|
||||
writer.write(new_pdf_stream)
|
||||
res[invoice_id]['stream'] = new_pdf_stream
|
||||
invoice_stream.close()
|
||||
additional_stream['stream'].close()
|
||||
return res
|
||||
|
||||
def get_paperformat(self):
|
||||
if self.env.context.get('snailmail_layout'):
|
||||
if self.report_name == 'l10n_ch.qr_report_main':
|
||||
return self.env.ref('l10n_ch.paperformat_euro_no_margin')
|
||||
if self.report_name == 'l10n_ch.qr_report_header':
|
||||
return self.env.ref('l10n_din5008.paperformat_euro_din')
|
||||
return super(IrActionsReport, self).get_paperformat()
|
||||
388
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/models/res_bank.py
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import re
|
||||
from stdnum.util import clean
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.addons.base.models.res_bank import sanitize_account_number
|
||||
from odoo.addons.base_iban.models.res_partner_bank import normalize_iban, pretty_iban, validate_iban
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
from odoo.tools.misc import mod10r
|
||||
|
||||
ISR_SUBSCRIPTION_CODE = {'CHF': '01', 'EUR': '03'}
|
||||
CLEARING = "09000"
|
||||
_re_postal = re.compile('^[0-9]{2}-[0-9]{1,6}-[0-9]$')
|
||||
|
||||
|
||||
def _is_l10n_ch_postal(account_ref):
|
||||
""" Returns True if the string account_ref is a valid postal account number,
|
||||
i.e. it only contains ciphers and is last cipher is the result of a recursive
|
||||
modulo 10 operation ran over the rest of it. Shorten form with - is also accepted.
|
||||
"""
|
||||
if _re_postal.match(account_ref or ''):
|
||||
ref_subparts = account_ref.split('-')
|
||||
account_ref = ref_subparts[0] + ref_subparts[1].rjust(6, '0') + ref_subparts[2]
|
||||
|
||||
if re.match(r'\d+$', account_ref or ''):
|
||||
account_ref_without_check = account_ref[:-1]
|
||||
return mod10r(account_ref_without_check) == account_ref
|
||||
return False
|
||||
|
||||
def _is_l10n_ch_isr_issuer(account_ref, currency_code):
|
||||
""" Returns True if the string account_ref is a valid a valid ISR issuer
|
||||
An ISR issuer is postal account number that starts by 01 (CHF) or 03 (EUR),
|
||||
"""
|
||||
if (account_ref or '').startswith(ISR_SUBSCRIPTION_CODE[currency_code]):
|
||||
return _is_l10n_ch_postal(account_ref)
|
||||
return False
|
||||
|
||||
def validate_qr_iban(qr_iban):
|
||||
# Check first if it's a valid IBAN.
|
||||
validate_iban(qr_iban)
|
||||
|
||||
# We sanitize first so that _check_qr_iban_range() can extract correct IID from IBAN to validate it.
|
||||
sanitized_qr_iban = sanitize_account_number(qr_iban)
|
||||
|
||||
if sanitized_qr_iban[:2] not in ['CH', 'LI']:
|
||||
raise ValidationError(_("QR-IBAN numbers are only available in Switzerland."))
|
||||
|
||||
# Now, check if it's valid QR-IBAN (based on its IID).
|
||||
if not check_qr_iban_range(sanitized_qr_iban):
|
||||
raise ValidationError(_("QR-IBAN '%s' is invalid.") % qr_iban)
|
||||
|
||||
return True
|
||||
|
||||
def check_qr_iban_range(iban):
|
||||
if not iban or len(iban) < 9:
|
||||
return False
|
||||
iid_start_index = 4
|
||||
iid_end_index = 8
|
||||
iid = iban[iid_start_index : iid_end_index+1]
|
||||
return re.match(r'\d+', iid) and 30000 <= int(iid) <= 31999 # Those values for iid are reserved for QR-IBANs only
|
||||
|
||||
|
||||
class ResPartnerBank(models.Model):
|
||||
_inherit = 'res.partner.bank'
|
||||
|
||||
l10n_ch_postal = fields.Char(
|
||||
string="Swiss Postal Account",
|
||||
readonly=False, store=True,
|
||||
compute='_compute_l10n_ch_postal',
|
||||
help="This field is used for the Swiss postal account number on a vendor account and for the client number on "
|
||||
"your own account. The client number is mostly 6 numbers without -, while the postal account number can "
|
||||
"be e.g. 01-162-8")
|
||||
|
||||
l10n_ch_qr_iban = fields.Char(string='QR-IBAN',
|
||||
compute='_compute_l10n_ch_qr_iban',
|
||||
store=True,
|
||||
readonly=False,
|
||||
help="Put the QR-IBAN here for your own bank accounts. That way, you can "
|
||||
"still use the main IBAN in the Account Number while you will see the "
|
||||
"QR-IBAN for the barcode. ")
|
||||
|
||||
# fields to configure ISR payment slip generation
|
||||
l10n_ch_isr_subscription_chf = fields.Char(string='CHF ISR Subscription Number', help='The subscription number provided by the bank or Postfinance to identify the bank, used to generate ISR in CHF. eg. 01-162-8')
|
||||
l10n_ch_isr_subscription_eur = fields.Char(string='EUR ISR Subscription Number', help='The subscription number provided by the bank or Postfinance to identify the bank, used to generate ISR in EUR. eg. 03-162-5')
|
||||
l10n_ch_show_subscription = fields.Boolean(compute='_compute_l10n_ch_show_subscription', default=lambda self: self.env.company.account_fiscal_country_id.code == 'CH')
|
||||
|
||||
def _is_isr_issuer(self):
|
||||
return (_is_l10n_ch_isr_issuer(self.l10n_ch_postal, 'CHF')
|
||||
or _is_l10n_ch_isr_issuer(self.l10n_ch_postal, 'EUR'))
|
||||
|
||||
@api.constrains("l10n_ch_postal", "partner_id")
|
||||
def _check_postal_num(self):
|
||||
"""Validate postal number format"""
|
||||
for rec in self:
|
||||
if rec.l10n_ch_postal and not _is_l10n_ch_postal(rec.l10n_ch_postal):
|
||||
# l10n_ch_postal is used for the purpose of Client Number on your own accounts, so don't do the check there
|
||||
if rec.partner_id and not rec.partner_id.ref_company_ids:
|
||||
raise ValidationError(
|
||||
_("The postal number {} is not valid.\n"
|
||||
"It must be a valid postal number format. eg. 10-8060-7").format(rec.l10n_ch_postal))
|
||||
return True
|
||||
|
||||
@api.constrains("l10n_ch_isr_subscription_chf", "l10n_ch_isr_subscription_eur")
|
||||
def _check_subscription_num(self):
|
||||
"""Validate ISR subscription number format
|
||||
Subscription number can only starts with 01 or 03
|
||||
"""
|
||||
for rec in self:
|
||||
for currency in ["CHF", "EUR"]:
|
||||
subscrip = rec.l10n_ch_isr_subscription_chf if currency == "CHF" else rec.l10n_ch_isr_subscription_eur
|
||||
if subscrip and not _is_l10n_ch_isr_issuer(subscrip, currency):
|
||||
example = "01-162-8" if currency == "CHF" else "03-162-5"
|
||||
raise ValidationError(
|
||||
_("The ISR subcription {} for {} number is not valid.\n"
|
||||
"It must starts with {} and we a valid postal number format. eg. {}"
|
||||
).format(subscrip, currency, ISR_SUBSCRIPTION_CODE[currency], example))
|
||||
return True
|
||||
|
||||
@api.depends('partner_id', 'company_id')
|
||||
def _compute_l10n_ch_show_subscription(self):
|
||||
for bank in self:
|
||||
if bank.partner_id:
|
||||
bank.l10n_ch_show_subscription = bank.partner_id.ref_company_ids.country_id.code in ('CH', 'LI')
|
||||
elif bank.company_id:
|
||||
bank.l10n_ch_show_subscription = bank.company_id.account_fiscal_country_id.code in ('CH', 'LI')
|
||||
else:
|
||||
bank.l10n_ch_show_subscription = self.env.company.account_fiscal_country_id.code in ('CH', 'LI')
|
||||
|
||||
@api.depends('acc_number', 'acc_type')
|
||||
def _compute_sanitized_acc_number(self):
|
||||
#Only remove spaces in case it is not postal
|
||||
postal_banks = self.filtered(lambda b: b.acc_type == "postal")
|
||||
for bank in postal_banks:
|
||||
bank.sanitized_acc_number = bank.acc_number
|
||||
super(ResPartnerBank, self - postal_banks)._compute_sanitized_acc_number()
|
||||
|
||||
@api.depends('acc_number')
|
||||
def _compute_l10n_ch_qr_iban(self):
|
||||
for record in self:
|
||||
try:
|
||||
validate_qr_iban(record.acc_number)
|
||||
valid_qr_iban = True
|
||||
except ValidationError:
|
||||
valid_qr_iban = False
|
||||
|
||||
if valid_qr_iban:
|
||||
record.l10n_ch_qr_iban = record.sanitized_acc_number
|
||||
else:
|
||||
record.l10n_ch_qr_iban = None
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('l10n_ch_qr_iban'):
|
||||
validate_qr_iban(vals['l10n_ch_qr_iban'])
|
||||
vals['l10n_ch_qr_iban'] = pretty_iban(normalize_iban(vals['l10n_ch_qr_iban']))
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('l10n_ch_qr_iban'):
|
||||
validate_qr_iban(vals['l10n_ch_qr_iban'])
|
||||
vals['l10n_ch_qr_iban'] = pretty_iban(normalize_iban(vals['l10n_ch_qr_iban']))
|
||||
return super().write(vals)
|
||||
|
||||
@api.model
|
||||
def _get_supported_account_types(self):
|
||||
rslt = super(ResPartnerBank, self)._get_supported_account_types()
|
||||
rslt.append(('postal', _('Postal')))
|
||||
return rslt
|
||||
|
||||
@api.model
|
||||
def retrieve_acc_type(self, acc_number):
|
||||
""" Overridden method enabling the recognition of swiss postal bank
|
||||
account numbers.
|
||||
"""
|
||||
acc_number_split = ""
|
||||
# acc_number_split is needed to continue to recognize the account
|
||||
# as a postal account even if the difference
|
||||
if acc_number and " " in acc_number:
|
||||
acc_number_split = acc_number.split(" ")[0]
|
||||
if _is_l10n_ch_postal(acc_number) or (acc_number_split and _is_l10n_ch_postal(acc_number_split)):
|
||||
return 'postal'
|
||||
else:
|
||||
return super(ResPartnerBank, self).retrieve_acc_type(acc_number)
|
||||
|
||||
@api.depends('acc_number', 'partner_id', 'acc_type')
|
||||
def _compute_l10n_ch_postal(self):
|
||||
for record in self:
|
||||
if record.acc_type == 'iban':
|
||||
record.l10n_ch_postal = self._retrieve_l10n_ch_postal(record.sanitized_acc_number)
|
||||
elif record.acc_type == 'postal':
|
||||
if record.acc_number and " " in record.acc_number:
|
||||
record.l10n_ch_postal = record.acc_number.split(" ")[0]
|
||||
else:
|
||||
record.l10n_ch_postal = record.acc_number
|
||||
# In case of ISR issuer, this number is not
|
||||
# unique and we fill acc_number with partner
|
||||
# name to give proper information to the user
|
||||
if record.partner_id and record.acc_number[:2] in ["01", "03"]:
|
||||
record.acc_number = ("{} {}").format(record.acc_number, record.partner_id.name)
|
||||
|
||||
@api.model
|
||||
def _is_postfinance_iban(self, iban):
|
||||
"""Postfinance IBAN have format
|
||||
CHXX 0900 0XXX XXXX XXXX K
|
||||
Where 09000 is the clearing number
|
||||
"""
|
||||
return iban.startswith(('CH', 'LI')) and iban[4:9] == CLEARING
|
||||
|
||||
@api.model
|
||||
def _pretty_postal_num(self, number):
|
||||
"""format a postal account number or an ISR subscription number
|
||||
as per specifications with '-' separators.
|
||||
eg. 010001628 -> 01-162-8
|
||||
"""
|
||||
if re.match('^[0-9]{2}-[0-9]{1,6}-[0-9]$', number or ''):
|
||||
return number
|
||||
currency_code = number[:2]
|
||||
middle_part = number[2:-1]
|
||||
trailing_cipher = number[-1]
|
||||
middle_part = middle_part.lstrip("0")
|
||||
return currency_code + '-' + middle_part + '-' + trailing_cipher
|
||||
|
||||
@api.model
|
||||
def _retrieve_l10n_ch_postal(self, iban):
|
||||
"""Reads a swiss postal account number from a an IBAN and returns it as
|
||||
a string. Returns None if no valid postal account number was found, or
|
||||
the given iban was not from Swiss Postfinance.
|
||||
|
||||
CH09 0900 0000 1000 8060 7 -> 10-8060-7
|
||||
"""
|
||||
if self._is_postfinance_iban(iban):
|
||||
# the IBAN corresponds to a swiss account
|
||||
return self._pretty_postal_num(iban[-9:])
|
||||
return None
|
||||
|
||||
def _l10n_ch_get_qr_vals(self, amount, currency, debtor_partner, free_communication, structured_communication):
|
||||
comment = ""
|
||||
if free_communication:
|
||||
comment = (free_communication[:137] + '...') if len(free_communication) > 140 else free_communication
|
||||
|
||||
creditor_addr_1, creditor_addr_2 = self._get_partner_address_lines(self.partner_id)
|
||||
debtor_addr_1, debtor_addr_2 = self._get_partner_address_lines(debtor_partner)
|
||||
|
||||
# Compute reference type (empty by default, only mandatory for QR-IBAN,
|
||||
# and must then be 27 characters-long, with mod10r check digit as the 27th one,
|
||||
# just like ISR number for invoices)
|
||||
reference_type = 'NON'
|
||||
reference = ''
|
||||
acc_number = self.sanitized_acc_number
|
||||
|
||||
if self.l10n_ch_qr_iban:
|
||||
# _check_for_qr_code_errors ensures we can't have a QR-IBAN without a QR-reference here
|
||||
reference_type = 'QRR'
|
||||
reference = structured_communication
|
||||
acc_number = sanitize_account_number(self.l10n_ch_qr_iban)
|
||||
elif self._is_iso11649_reference(structured_communication):
|
||||
reference_type = 'SCOR'
|
||||
reference = structured_communication.replace(' ', '')
|
||||
|
||||
currency = currency or self.currency_id or self.company_id.currency_id
|
||||
|
||||
return [
|
||||
'SPC', # QR Type
|
||||
'0200', # Version
|
||||
'1', # Coding Type
|
||||
acc_number, # IBAN / QR-IBAN
|
||||
'K', # Creditor Address Type
|
||||
(self.acc_holder_name or self.partner_id.name)[:70], # Creditor Name
|
||||
creditor_addr_1, # Creditor Address Line 1
|
||||
creditor_addr_2, # Creditor Address Line 2
|
||||
'', # Creditor Postal Code (empty, since we're using combined addres elements)
|
||||
'', # Creditor Town (empty, since we're using combined addres elements)
|
||||
self.partner_id.country_id.code, # Creditor Country
|
||||
'', # Ultimate Creditor Address Type
|
||||
'', # Name
|
||||
'', # Ultimate Creditor Address Line 1
|
||||
'', # Ultimate Creditor Address Line 2
|
||||
'', # Ultimate Creditor Postal Code
|
||||
'', # Ultimate Creditor Town
|
||||
'', # Ultimate Creditor Country
|
||||
'{:.2f}'.format(amount), # Amount
|
||||
currency.name, # Currency
|
||||
'K', # Ultimate Debtor Address Type
|
||||
debtor_partner.commercial_partner_id.name[:70], # Ultimate Debtor Name
|
||||
debtor_addr_1, # Ultimate Debtor Address Line 1
|
||||
debtor_addr_2, # Ultimate Debtor Address Line 2
|
||||
'', # Ultimate Debtor Postal Code (not to be provided for address type K)
|
||||
'', # Ultimate Debtor Postal City (not to be provided for address type K)
|
||||
debtor_partner.country_id.code, # Ultimate Debtor Postal Country
|
||||
reference_type, # Reference Type
|
||||
reference, # Reference
|
||||
comment, # Unstructured Message
|
||||
'EPD', # Mandatory trailer part
|
||||
]
|
||||
|
||||
def _get_qr_vals(self, qr_method, amount, currency, debtor_partner, free_communication, structured_communication):
|
||||
if qr_method == 'ch_qr':
|
||||
return self._l10n_ch_get_qr_vals(amount, currency, debtor_partner, free_communication, structured_communication)
|
||||
return super()._get_qr_vals(qr_method, amount, currency, debtor_partner, free_communication, structured_communication)
|
||||
|
||||
def _get_qr_code_generation_params(self, qr_method, amount, currency, debtor_partner, free_communication, structured_communication):
|
||||
if qr_method == 'ch_qr':
|
||||
return {
|
||||
'barcode_type': 'QR',
|
||||
'width': 256,
|
||||
'height': 256,
|
||||
'quiet': 1,
|
||||
'mask': 'ch_cross',
|
||||
'value': '\n'.join(self._get_qr_vals(qr_method, amount, currency, debtor_partner, free_communication, structured_communication)),
|
||||
# Swiss QR code requires Error Correction Level = 'M' by specification
|
||||
'barLevel': 'M',
|
||||
}
|
||||
return super()._get_qr_code_generation_params(qr_method, amount, currency, debtor_partner, free_communication, structured_communication)
|
||||
|
||||
def _get_partner_address_lines(self, partner):
|
||||
""" Returns a tuple of two elements containing the address lines to use
|
||||
for this partner. Line 1 contains the street and number, line 2 contains
|
||||
zip and city. Those two lines are limited to 70 characters
|
||||
"""
|
||||
streets = [partner.street, partner.street2]
|
||||
line_1 = ' '.join(filter(None, streets))
|
||||
line_2 = partner.zip + ' ' + partner.city
|
||||
return line_1[:70], line_2[:70]
|
||||
|
||||
@api.model
|
||||
def _is_qr_reference(self, reference):
|
||||
""" Checks whether the given reference is a QR-reference, i.e. it is
|
||||
made of 27 digits, the 27th being a mod10r check on the 26 previous ones.
|
||||
"""
|
||||
return reference \
|
||||
and len(reference) == 27 \
|
||||
and re.match(r'\d+$', reference) \
|
||||
and reference == mod10r(reference[:-1])
|
||||
|
||||
@api.model
|
||||
def _is_iso11649_reference(self, reference):
|
||||
""" Checks whether the given reference is a ISO11649 (SCOR) reference.
|
||||
"""
|
||||
return reference \
|
||||
and len(reference) >= 5 \
|
||||
and len(reference) <= 25 \
|
||||
and reference.startswith('RF') \
|
||||
and int(''.join(str(int(x, 36)) for x in clean(reference[4:] + reference[:4], ' -.,/:').upper().strip())) % 97 == 1
|
||||
# see https://github.com/arthurdejong/python-stdnum/blob/master/stdnum/iso11649.py
|
||||
|
||||
def _eligible_for_qr_code(self, qr_method, debtor_partner, currency, raises_error=True):
|
||||
if qr_method == 'ch_qr':
|
||||
error_messages = [_("The QR code could not be generated for the following reason(s):")]
|
||||
if self.acc_type != 'iban':
|
||||
error_messages.append(_("The account type isn't QR-IBAN or IBAN."))
|
||||
if not debtor_partner or debtor_partner.country_id.code not in ('CH', 'LI'):
|
||||
error_messages.append(_("The debtor partner's address isn't located in Switzerland."))
|
||||
if currency.id not in (self.env.ref('base.EUR').id, self.env.ref('base.CHF').id):
|
||||
error_messages.append(_("The currency isn't EUR nor CHF. \r\n"))
|
||||
if len(error_messages) != 1:
|
||||
if raises_error:
|
||||
raise UserError(' '.join(error_messages))
|
||||
return False
|
||||
return True
|
||||
return super()._eligible_for_qr_code(qr_method, debtor_partner, currency, raises_error)
|
||||
|
||||
def _check_for_qr_code_errors(self, qr_method, amount, currency, debtor_partner, free_communication, structured_communication):
|
||||
def _partner_fields_set(partner):
|
||||
return partner.zip and \
|
||||
partner.city and \
|
||||
partner.country_id.code and \
|
||||
(partner.street or partner.street2)
|
||||
|
||||
if qr_method == 'ch_qr':
|
||||
if not _partner_fields_set(self.partner_id):
|
||||
return _("The partner set on the bank account meant to receive the payment (%s) must have a complete postal address (street, zip, city and country).", self.acc_number)
|
||||
|
||||
if debtor_partner and not _partner_fields_set(debtor_partner):
|
||||
return _("The partner must have a complete postal address (street, zip, city and country).")
|
||||
|
||||
if self.l10n_ch_qr_iban and not self._is_qr_reference(structured_communication):
|
||||
return _("When using a QR-IBAN as the destination account of a QR-code, the payment reference must be a QR-reference.")
|
||||
|
||||
return super()._check_for_qr_code_errors(qr_method, amount, currency, debtor_partner, free_communication, structured_communication)
|
||||
|
||||
@api.model
|
||||
def _get_available_qr_methods(self):
|
||||
rslt = super()._get_available_qr_methods()
|
||||
rslt.append(('ch_qr', _("Swiss QR bill"), 10))
|
||||
return rslt
|
||||
29
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/models/res_company.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
class Company(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
l10n_ch_isr_preprinted_account = fields.Boolean(string='Preprinted account', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr')
|
||||
l10n_ch_isr_preprinted_bank = fields.Boolean(string='Preprinted bank', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr')
|
||||
l10n_ch_isr_print_bank_location = fields.Boolean(string='Print bank location', default=False, help='Boolean option field indicating whether or not the alternate layout (the one printing bank name and address) must be used when generating an ISR.')
|
||||
l10n_ch_isr_scan_line_left = fields.Float(string='Scan line horizontal offset (mm)', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr')
|
||||
l10n_ch_isr_scan_line_top = fields.Float(string='Scan line vertical offset (mm)', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr')
|
||||
|
||||
def _compute_l10n_ch_isr(self):
|
||||
get_param = self.env['ir.config_parameter'].sudo().get_param
|
||||
for company in self:
|
||||
company.l10n_ch_isr_preprinted_account = bool(get_param('l10n_ch.isr_preprinted_account', default=False))
|
||||
company.l10n_ch_isr_preprinted_bank = bool(get_param('l10n_ch.isr_preprinted_bank', default=False))
|
||||
company.l10n_ch_isr_scan_line_top = float(get_param('l10n_ch.isr_scan_line_top', default=0))
|
||||
company.l10n_ch_isr_scan_line_left = float(get_param('l10n_ch.isr_scan_line_left', default=0))
|
||||
|
||||
def _set_l10n_ch_isr(self):
|
||||
set_param = self.env['ir.config_parameter'].sudo().set_param
|
||||
for company in self:
|
||||
set_param("l10n_ch.isr_preprinted_account", company.l10n_ch_isr_preprinted_account)
|
||||
set_param("l10n_ch.isr_preprinted_bank", company.l10n_ch_isr_preprinted_bank)
|
||||
set_param("l10n_ch.isr_scan_line_top", company.l10n_ch_isr_scan_line_top)
|
||||
set_param("l10n_ch.isr_scan_line_left", company.l10n_ch_isr_scan_line_left)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
l10n_ch_isr_preprinted_account = fields.Boolean(string='Preprinted account',
|
||||
related="company_id.l10n_ch_isr_preprinted_account", readonly=False)
|
||||
l10n_ch_isr_preprinted_bank = fields.Boolean(string='Preprinted bank',
|
||||
related="company_id.l10n_ch_isr_preprinted_bank", readonly=False)
|
||||
l10n_ch_isr_print_bank_location = fields.Boolean(string="Print bank on ISR",
|
||||
related="company_id.l10n_ch_isr_print_bank_location", readonly=False,
|
||||
required=True)
|
||||
l10n_ch_isr_scan_line_left = fields.Float(string='Horizontal offset',
|
||||
related="company_id.l10n_ch_isr_scan_line_left", readonly=False)
|
||||
l10n_ch_isr_scan_line_top = fields.Float(string='Vertical offset',
|
||||
related="company_id.l10n_ch_isr_scan_line_top", readonly=False)
|
||||
3
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/report/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
|
||||
from . import swissqr_report
|
||||
157
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/report/isr_report.xml
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="paperformat_euro_no_margin" model="report.paperformat">
|
||||
<field name="name">European A4 without borders</field>
|
||||
<field name="default" eval="False" />
|
||||
<field name="format">A4</field>
|
||||
<field name="orientation">Portrait</field>
|
||||
<field name="margin_top">0</field>
|
||||
<field name="margin_bottom">0</field>
|
||||
<field name="margin_left">0</field>
|
||||
<field name="margin_right">0</field>
|
||||
<field name="header_line" eval="False" />
|
||||
<field name="header_spacing">0</field>
|
||||
</record>
|
||||
|
||||
<!--Report containing an ISR corrresponding to an invoice.-->
|
||||
<record id="l10n_ch_isr_report" model="ir.actions.report">
|
||||
<field name="name">ISR</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">l10n_ch.isr_report_main</field>
|
||||
<field name="report_file">l10n_ch.isr_report_main</field>
|
||||
<field name="print_report_name">'ISR-%s' % object.name</field>
|
||||
<field name="paperformat_id" ref="paperformat_euro_no_margin"/>
|
||||
<field name="attachment">'ISR-' + object.name + '.pdf'</field>
|
||||
<field name="attachment_use">True</field>
|
||||
</record>
|
||||
<!--No additional condition in report name on invoice state or type as this
|
||||
report is only available to be printed for out invoices after
|
||||
'draft' state, if the fields required by the ISR have been set.-->
|
||||
|
||||
<template id="l10n_ch_isr_report_template">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-set="split_total_amount" t-value="invoice.split_total_amount()"/>
|
||||
<t t-set="print_bank" t-value="invoice.company_id.l10n_ch_isr_print_bank_location"/>
|
||||
|
||||
<!-- add class to body tag -->
|
||||
<script>document.body.className += " l10n_ch_isr";</script>
|
||||
|
||||
<!-- since the body content take the whole page we need a way to add margin
|
||||
back on content outside the ISR so it does not overlap with the header -->
|
||||
<div id="content_outside_isr">
|
||||
<h1>ISR for invoice <t t-esc="invoice.name"/></h1>
|
||||
</div>
|
||||
|
||||
<div id="isr" t-att-class="'isr-print-bank' if print_bank else None">
|
||||
|
||||
<!--Voucher, left part of the ISR.-->
|
||||
<div id="voucher">
|
||||
<!--Einzahlung für/Versement pour/Versamento per-->
|
||||
|
||||
<!--If we use the alternate ISR layout, displaying name
|
||||
and location of the bank.-->
|
||||
<t t-if="print_bank">
|
||||
<div id="voucher-for-bank">
|
||||
<p t-if="not invoice.company_id.l10n_ch_isr_preprinted_bank">
|
||||
<t t-esc="invoice.partner_bank_id.bank_id.name"/><br />
|
||||
<t t-esc="invoice.partner_bank_id.bank_id.zip"/>
|
||||
<t t-esc="invoice.partner_bank_id.bank_id.city"/>
|
||||
</p>
|
||||
</div>
|
||||
<!--Zugunsten von/En faveur de/A favore di-->
|
||||
</t>
|
||||
<div id="voucher-for-contact">
|
||||
<p id="voucher-for_name" t-field="invoice.company_id.display_name"/>
|
||||
<p id="voucher-for_address1" t-field="invoice.company_id.street"/>
|
||||
<p id="voucher-for_address2" t-field="invoice.company_id.street2"/>
|
||||
<p id="voucher-for_address3">
|
||||
<t t-esc="invoice.company_id.zip"/>
|
||||
<t t-esc="invoice.company_id.city"/>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="voucher-bank" t-if="not print_bank or not invoice.company_id.l10n_ch_isr_preprinted_account">
|
||||
<!--Konto/Compte/Conto-->
|
||||
<p id="voucher-bank_ref" t-field="invoice.l10n_ch_isr_subscription_formatted"/>
|
||||
</div>
|
||||
|
||||
<p id="voucher-amount_units" t-esc="split_total_amount[0]"/>
|
||||
<p id="voucher-amount_cents" t-esc="split_total_amount[1]"/>
|
||||
|
||||
<div id="voucher-by">
|
||||
<!--Einbezahlt von/Versé par/Versato da-->
|
||||
<p id="voucher-by_reference_number" t-field="invoice.l10n_ch_isr_number"/>
|
||||
<address id="voucher-by_customer_address" t-field="invoice.partner_id" t-options='{"widget": "contact", "fields": ["address","name"], "no_marker": True}' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Slip, right part of the ISR.-->
|
||||
<div id="slip">
|
||||
<!--Einzahlung für/Versement pour/Versamento per-->
|
||||
|
||||
<!--If we use the alternate ISR layout, displaying name
|
||||
and location of the bank.-->
|
||||
<t t-if="print_bank">
|
||||
<div id="slip-for-bank">
|
||||
<p t-if="not invoice.company_id.l10n_ch_isr_preprinted_bank">
|
||||
<t t-esc="invoice.partner_bank_id.bank_id.name"/><br />
|
||||
<t t-esc="invoice.partner_bank_id.bank_id.zip"/>
|
||||
<t t-esc="invoice.partner_bank_id.bank_id.city"/>
|
||||
</p>
|
||||
</div>
|
||||
<!--Zugunsten von/En faveur de/A favore di-->
|
||||
</t>
|
||||
|
||||
<div id="slip-for-contact">
|
||||
<p id="slip-for_name" t-field="invoice.company_id.display_name"/>
|
||||
<p id="slip-for_address1" t-field="invoice.company_id.street"/>
|
||||
<p id="slip-for_address2" t-field="invoice.company_id.street2"/>
|
||||
<p id="slip-for_address3">
|
||||
<t t-esc="invoice.company_id.zip"/>
|
||||
<t t-esc="invoice.company_id.city"/>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="slip-bank" t-if="not print_bank or not invoice.company_id.l10n_ch_isr_preprinted_account">
|
||||
<!--Konto/Compte/Conto-->
|
||||
<!--aka ISR Subscriber number provided by the financial institution-->
|
||||
<p id="slip-bank_ref" t-field="invoice.l10n_ch_isr_subscription_formatted"/>
|
||||
</div>
|
||||
|
||||
<p id="slip-amount_units" t-esc="split_total_amount[0]"/>
|
||||
<p id="slip-amount_cents" t-esc="split_total_amount[1]"/>
|
||||
|
||||
<div id="slip-reference">
|
||||
<!--Referenz-Nr./N°de référence/N°di riferimento-->
|
||||
<p id="slip-reference_number" t-field="invoice.l10n_ch_isr_number_spaced"/>
|
||||
</div>
|
||||
|
||||
<div id="slip-by">
|
||||
<!--Einbezahlt von/Versé par/Versato da-->
|
||||
<address id="slip-by_customer_address" t-field="invoice.partner_id" t-options='{"widget": "contact", "fields": ["address","name"], "no_marker": True}' />
|
||||
</div>
|
||||
|
||||
<div id="slip-optical-line">
|
||||
<!--Optical reference-->
|
||||
<div t-attf-style="top: {{ invoice.company_id.l10n_ch_isr_scan_line_top }}mm; left: {{ invoice.company_id.l10n_ch_isr_scan_line_left }}mm;">
|
||||
<div t-foreach="invoice.l10n_ch_isr_optical_line" t-as="char" t-esc="char" t-attf-style="right: {{ round((char_size - char_index - 1) * 0.1, 1) }}in"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="l10n_ch.isr_report_main">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="invoice">
|
||||
<t t-set="o" t-value="invoice"/>
|
||||
<t t-call="l10n_ch.l10n_ch_isr_report_template"/>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from odoo import api, models
|
||||
|
||||
class ReportSwissQR(models.AbstractModel):
|
||||
_name = 'report.l10n_ch.qr_report_main'
|
||||
_description = 'Swiss QR-bill report'
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
docs = self.env['account.move'].browse(docids)
|
||||
|
||||
qr_code_urls = {}
|
||||
for invoice in docs:
|
||||
qr_code_urls[invoice.id] = invoice.partner_bank_id.build_qr_code_base64(invoice.amount_residual, invoice.ref or invoice.name, invoice.payment_reference, invoice.currency_id, invoice.partner_id, qr_method='ch_qr', silent_errors=False)
|
||||
|
||||
return {
|
||||
'doc_ids': docids,
|
||||
'doc_model': 'account.move',
|
||||
'docs': docs,
|
||||
'qr_code_urls': qr_code_urls,
|
||||
}
|
||||
251
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/report/swissqr_report.xml
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="l10n_ch_qr_report" model="ir.actions.report">
|
||||
<field name="name">QR-bill</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">l10n_ch.qr_report_main</field>
|
||||
<field name="report_file">l10n_ch.qr_report_main</field>
|
||||
<field name="print_report_name">'QR-bill-%s' % object.name</field>
|
||||
<field name="paperformat_id" ref="l10n_ch.paperformat_euro_no_margin"/>
|
||||
</record>
|
||||
|
||||
<record id="l10n_ch_qr_header" model="ir.actions.report">
|
||||
<field name="name">QR-bill Header</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">l10n_ch.qr_report_header</field>
|
||||
<field name="report_file">l10n_ch.qr_report_header</field>
|
||||
</record>
|
||||
|
||||
<template id="l10n_ch_header_template">
|
||||
<t t-call="web.external_layout">
|
||||
<!--The following elements are necessary for the header to be displayed correctly.-->
|
||||
<br/>
|
||||
<p>&nbsp;</p>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="l10n_ch_swissqr_template">
|
||||
<div class="article" t-att-data-oe-model="o._name" t-att-data-oe-id="o.id">
|
||||
<t t-set="o" t-value="o.with_context(lang=lang)"/>
|
||||
<t t-set="company" t-value="o.company_id"/>
|
||||
<t t-set="formated_amount" t-value="'{:,.2f}'.format(o.amount_residual).replace(',','\xa0')"/>
|
||||
|
||||
<t t-set="is_qrr" t-value="o.partner_bank_id.l10n_ch_qr_iban"/>
|
||||
<t t-set="is_scor" t-value="o.partner_bank_id._is_iso11649_reference(o.payment_reference)"/>
|
||||
|
||||
<div class="swissqr_content_v2">
|
||||
|
||||
<div class="swissqr_receipt">
|
||||
|
||||
<img src="/l10n_ch/static/src/img/scissors_h.png" class="scissors horizontal_scissors"/>
|
||||
|
||||
<div id="receipt_title_zone" class="swissqr_section_title">
|
||||
<span>Receipt</span>
|
||||
</div>
|
||||
|
||||
<div id="receipt_indication_zone" class="receipt_indication_zone">
|
||||
|
||||
<div class="swissqr_text title">
|
||||
<span>Account / Payable to</span>
|
||||
</div>
|
||||
<div class="swissqr_text content">
|
||||
<span t-field="o.partner_bank_id.acc_number" t-if="not o.partner_bank_id.l10n_ch_qr_iban"/>
|
||||
<span t-field="o.partner_bank_id.l10n_ch_qr_iban" t-if="o.partner_bank_id.l10n_ch_qr_iban"/>
|
||||
<br/>
|
||||
<span t-esc="o.partner_bank_id.acc_holder_name or o.company_id.name"/><br/>
|
||||
<span t-field="o.company_id.street"/><br/>
|
||||
<span t-field="o.company_id.country_id.code"/>
|
||||
<span t-field="o.company_id.zip"/>
|
||||
<span t-field="o.company_id.city"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<t t-if="is_qrr or is_scor">
|
||||
<div class="swissqr_text title">
|
||||
<span>Reference</span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="is_qrr">
|
||||
<div class="swissqr_text content">
|
||||
<span t-esc="o.space_qrr_reference(o.payment_reference)"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="is_scor">
|
||||
<div class="swissqr_text content">
|
||||
<span t-esc="o.space_scor_reference(o.payment_reference)"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="swissqr_text title">
|
||||
<span>Payable by</span>
|
||||
</div>
|
||||
<div class="swissqr_text content">
|
||||
<span t-field="o.partner_id.commercial_partner_id.name"/><br/>
|
||||
<span t-field="o.partner_id.street"/>
|
||||
<span t-field="o.partner_id.street2"/><br/>
|
||||
<span t-field="o.partner_id.country_id.code"/>
|
||||
<span t-field="o.partner_id.zip"/>
|
||||
<span t-field="o.partner_id.city"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="receipt_amount_zone" class="swissqr_column_left receipt_amount_zone">
|
||||
<div class="swissqr_text">
|
||||
<div class="column">
|
||||
<div class="title">
|
||||
<span>Currency</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<span t-field="o.currency_id.name"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="title">
|
||||
<span>Amount</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<span t-esc="formated_amount"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="receipt_acceptance_point_zone" class="receipt_acceptance_point_zone">
|
||||
<div class="swissqr_text content">
|
||||
<span class="title">Acceptance point</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="swissqr_body">
|
||||
|
||||
<img src="/l10n_ch/static/src/img/scissors_v.png" class="scissors vertical_scissors"/>
|
||||
|
||||
<div class="swissqr_column_left">
|
||||
|
||||
<div class="swissqr_section_title">
|
||||
<span>Payment part</span>
|
||||
</div>
|
||||
|
||||
<img class="swissqr" t-att-src="qr_code_urls[o.id]"/>
|
||||
|
||||
<div id="amount_zone" class="amount_zone">
|
||||
<div class="swissqr_text">
|
||||
<div class="column">
|
||||
<div class="title">
|
||||
<span>Currency</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<span t-field="o.currency_id.name"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="title">
|
||||
<span>Amount</span><br/>
|
||||
</div>
|
||||
<div class="content">
|
||||
<span t-esc="formated_amount"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="indications_zone" class="swissqr_column_right">
|
||||
<div class="swissqr_text title">
|
||||
<span>Account / Payable to</span><br/>
|
||||
</div>
|
||||
<div class="swissqr_text content">
|
||||
<span t-field="o.partner_bank_id.acc_number" t-if="not o.partner_bank_id.l10n_ch_qr_iban"/>
|
||||
<span t-field="o.partner_bank_id.l10n_ch_qr_iban" t-if="o.partner_bank_id.l10n_ch_qr_iban"/>
|
||||
<br/>
|
||||
<span t-esc="o.partner_bank_id.acc_holder_name or o.company_id.name"/><br/>
|
||||
<span t-field="o.company_id.street"/><br/>
|
||||
<span t-field="o.company_id.country_id.code"/>
|
||||
<span t-field="o.company_id.zip"/>
|
||||
<span t-field="o.company_id.city"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<t t-if="is_qrr or is_scor">
|
||||
<div class="swissqr_text title">
|
||||
<span class="title">Reference</span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="is_qrr">
|
||||
<div class="swissqr_text content">
|
||||
<span t-esc="o.space_qrr_reference(o.payment_reference)"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="is_scor">
|
||||
<div class="swissqr_text content">
|
||||
<span t-esc="o.space_scor_reference(o.payment_reference)"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-set="additional_info" t-value="(o.ref or o.name if is_qrr or is_scor else o.payment_reference or o.ref or o.name)"/>
|
||||
<t t-if="additional_info">
|
||||
<div class="swissqr_text title">
|
||||
<span>Additional information</span>
|
||||
</div>
|
||||
<div class="swissqr_text content">
|
||||
<span t-esc="additional_info"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="swissqr_text title">
|
||||
<span>Payable by</span>
|
||||
</div>
|
||||
<div class="swissqr_text content">
|
||||
<span t-field="o.partner_id.commercial_partner_id.name"/><br/>
|
||||
<span t-field="o.partner_id.street"> </span>
|
||||
<span t-field="o.partner_id.street2"/><br/>
|
||||
<span t-field="o.partner_id.country_id.code"/>
|
||||
<span t-field="o.partner_id.zip"/>
|
||||
<span t-field="o.partner_id.city"/><br/>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="l10n_ch.qr_report_main">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<t t-set="lang" t-value="o.partner_id.lang"/>
|
||||
<t t-call="l10n_ch.l10n_ch_swissqr_template" t-lang="lang"/>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="l10n_ch.qr_report_header">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="invoice">
|
||||
<t t-set="o" t-value="invoice"/>
|
||||
<t t-set="lang" t-value="o.partner_id.lang"/>
|
||||
<t t-call="l10n_ch.l10n_ch_header_template" t-lang="lang"/>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="minimal_layout_with_report_attribute" inherit_id="web.minimal_layout">
|
||||
<body position="attributes">
|
||||
<attribute name="t-att-data-report-id">report_xml_id</attribute>
|
||||
</body>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_l10n_ch_qr_invoice_wizard,l10n_ch.qr_invoice.wizard,model_l10n_ch_qr_invoice_wizard,account.group_account_invoice,1,1,1,0
|
||||
|
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
|
@ -0,0 +1,102 @@
|
|||
Digitized data copyright (c) 2010 Google Corporation
|
||||
with Reserved Font Arimo, Tinos and Cousine.
|
||||
Copyright (c) 2012 Red Hat, Inc.
|
||||
with Reserved Font Name Liberation.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
|
||||
PREAMBLE The goals of the Open Font License (OFL) are to stimulate
|
||||
worldwide development of collaborative font projects, to support the font
|
||||
creation efforts of academic and linguistic communities, and to provide
|
||||
a free and open framework in which fonts may be shared and improved in
|
||||
partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves.
|
||||
The fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply to
|
||||
any document created using the fonts or their derivatives.
|
||||
|
||||
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such.
|
||||
This may include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components
|
||||
as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting ? in part or in whole ?
|
||||
any of the components of the Original Version, by changing formats or
|
||||
by porting the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical writer
|
||||
or other person who contributed to the Font Software.
|
||||
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,in
|
||||
Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the
|
||||
corresponding Copyright Holder. This restriction only applies to the
|
||||
primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole, must
|
||||
be distributed entirely under this license, and must not be distributed
|
||||
under any other license. The requirement for fonts to remain under
|
||||
this license does not apply to any document created using the Font
|
||||
Software.
|
||||
|
||||
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are not met.
|
||||
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||
DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Files: ocrb.otf
|
||||
Copyright: 2012 Matthew Skala
|
||||
License: public-domain
|
||||
This file is released to the public domain by its author, Matthew Skala.
|
||||
BIN
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/static/src/font/ocrb.otf
Normal file
BIN
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/static/src/img/CH-Cross_7mm.png
Executable file
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
|
@ -0,0 +1,208 @@
|
|||
@font-face {
|
||||
font-family: ocrb;
|
||||
src: url('../font/ocrb.otf') format('opentype');
|
||||
}
|
||||
|
||||
.l10n_ch_isr {
|
||||
/*
|
||||
all elements are positionned for A4 format (210 x 297mm) but the viewport
|
||||
is bigger than this, hence we zoom the whole page to be bigger than the viewport
|
||||
which will then be resized down by wkhtmltopdf to get back to an A4 format
|
||||
*/
|
||||
zoom: 1.25;
|
||||
|
||||
&.o_in_iframe {
|
||||
zoom: 1;
|
||||
|
||||
/* display dummy check bacground in html rendering to help see the end result */
|
||||
#isr {
|
||||
background: url(../img/background_virgin_isr.png) bottom no-repeat;
|
||||
background-size: 100%;
|
||||
|
||||
&.isr-print-bank {
|
||||
background-image: url(../img/background_virgin_isr_bank.png);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* content outside isr needs margins to not overlap header */
|
||||
#content_outside_isr {
|
||||
padding: 15px;
|
||||
padding-top: 150px;
|
||||
}
|
||||
|
||||
/* ISR is intended for pre-printed paper, we don't want stylistic background */
|
||||
.o_report_layout_striped {
|
||||
background: none;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
#isr {
|
||||
height: 106mm;
|
||||
width: 210mm;
|
||||
|
||||
position: absolute;
|
||||
/* position bvr at bottom of page */
|
||||
top: 297 - 106mm;
|
||||
left: 0;
|
||||
|
||||
overflow: hidden;
|
||||
font-family: ocrb;
|
||||
line-height: 0.16in;
|
||||
font-size: 10pt;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#voucher {
|
||||
height: 4in;
|
||||
width: 2.4in;
|
||||
|
||||
position: absolute;
|
||||
/* header title of BVR section */
|
||||
top: 0.167in;
|
||||
/* right of voucher corresponds to left of slip */
|
||||
right: 5.9in;
|
||||
}
|
||||
|
||||
#voucher > * {
|
||||
position: absolute;
|
||||
/* default left margin for fields content */
|
||||
left: 0.15in;
|
||||
|
||||
&#voucher-for-contact {
|
||||
top: 0.25in;
|
||||
}
|
||||
|
||||
&#voucher-for-bank {
|
||||
top: 0.18in;
|
||||
}
|
||||
|
||||
&#voucher-for-bank + #voucher-for-contact {
|
||||
top: 0.68in;
|
||||
}
|
||||
|
||||
&#voucher-bank {
|
||||
top: 1.51in;
|
||||
left: 1.1in;
|
||||
}
|
||||
|
||||
&#voucher-amount_units {
|
||||
width: 1.62in;
|
||||
top: 1.87in;
|
||||
|
||||
text-align: right;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.095in;
|
||||
}
|
||||
|
||||
&#voucher-amount_cents {
|
||||
width: 0.4in;
|
||||
top: 1.87in;
|
||||
left: 1.96in;
|
||||
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.095in;
|
||||
}
|
||||
|
||||
&#voucher-by {
|
||||
top: 2.22in;
|
||||
font-size: 9pt;
|
||||
max-width: 2in;
|
||||
|
||||
#voucher-by_reference_number {
|
||||
font-size: 7.5pt;
|
||||
margin-bottom: 0.05in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#slip {
|
||||
height: 4in;
|
||||
width: 5.9in;
|
||||
|
||||
position: absolute;
|
||||
/* header title of BVR section */
|
||||
top: 0.167in;
|
||||
/* right of slip corresponds to right of slip */
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#slip > * {
|
||||
position: absolute;
|
||||
/* default left margin for fields content */
|
||||
left: 0.15in;
|
||||
|
||||
&#slip-for-contact {
|
||||
top: 0.25in;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&#slip-for-bank {
|
||||
top: 0.18in;
|
||||
}
|
||||
|
||||
&#slip-for-bank + #slip-for-contact {
|
||||
top: 0.68in;
|
||||
}
|
||||
|
||||
&#slip-bank {
|
||||
top: 1.51in;
|
||||
left: 1.1in;
|
||||
}
|
||||
|
||||
&#slip-amount_units {
|
||||
width: 1.62in;
|
||||
top: 1.87in;
|
||||
|
||||
text-align: right;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.095in;
|
||||
}
|
||||
|
||||
&#slip-amount_cents {
|
||||
width: 0.4in;
|
||||
top: 1.87in;
|
||||
left: 1.96in;
|
||||
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.095in;
|
||||
}
|
||||
|
||||
&#slip-reference {
|
||||
width: 3.3in;
|
||||
top: 1.2in;
|
||||
left: 2.5in;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&#slip-by {
|
||||
top: 1.85in;
|
||||
left: 2.55in;
|
||||
}
|
||||
|
||||
&#slip-optical-line {
|
||||
right: 0.32in;
|
||||
bottom: 0.667in;
|
||||
|
||||
/* Positioning is set for OCRB of Tsukurimashou Font Family */
|
||||
font-family: ocrb;
|
||||
font-size: 10pt;
|
||||
line-height: 0.1in;
|
||||
|
||||
> div {
|
||||
position: relative;
|
||||
|
||||
> div {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
@font-face {
|
||||
font-family: LiberationSans;
|
||||
src: url('../font/LiberationSans-Bold.woff') format('woff');
|
||||
font-weight: bold;
|
||||
}
|
||||
@font-face {
|
||||
font-family: LiberationSans;
|
||||
src: url('../font/LiberationSans-Regular.woff') format('woff');
|
||||
}
|
||||
|
||||
$l10n-ch-qr-ratio: 1.25;
|
||||
|
||||
body.l10n_ch_qr{
|
||||
padding: 0;
|
||||
span{
|
||||
padding-left: 10mm;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Disable custom bakground */
|
||||
.o_report_layout_striped {
|
||||
background-color: white;
|
||||
min-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.swissqr_page_title {
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
height: 7mm * $l10n-ch-qr-ratio;
|
||||
padding: 15px;
|
||||
padding-top: 150px;
|
||||
h1{
|
||||
padding-left:20mm;
|
||||
white-space:nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.swissqr_content_v2 {
|
||||
|
||||
$receipt_width: 52mm * $l10n-ch-qr-ratio;
|
||||
$left_col_width: 46mm * $l10n-ch-qr-ratio;
|
||||
$right_col_width: 87mm * $l10n-ch-qr-ratio;
|
||||
$rounding_offset: 0.25mm;
|
||||
|
||||
@mixin font {
|
||||
font-family: LiberationSans;
|
||||
color: black;
|
||||
}
|
||||
@mixin title {
|
||||
@include font;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* New QR Bill code */
|
||||
background-color: white !important;
|
||||
|
||||
/* Disable custom font-family */
|
||||
.o_company_2_layout {
|
||||
font-family: revert;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include title;
|
||||
}
|
||||
|
||||
.swissqr_text {
|
||||
@include font;
|
||||
}
|
||||
|
||||
.swissqr_section_title {
|
||||
@include title;
|
||||
width: $receipt_width;
|
||||
height: 7mm * $l10n-ch-qr-ratio;
|
||||
font-size: 11pt * $l10n-ch-qr-ratio;
|
||||
line-height: 9pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
|
||||
.swissqr_receipt {
|
||||
background-color: white !important;
|
||||
position: absolute;
|
||||
left: 0mm;
|
||||
top: 192mm * $l10n-ch-qr-ratio;
|
||||
width: 62mm * $l10n-ch-qr-ratio;
|
||||
height: 105mm * $l10n-ch-qr-ratio - $rounding_offset;
|
||||
border-top: 0.75pt * $l10n-ch-qr-ratio dashed black;
|
||||
padding: 5mm * $l10n-ch-qr-ratio;
|
||||
.title {
|
||||
font-size: 6pt * $l10n-ch-qr-ratio;
|
||||
line-height: 9pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.content {
|
||||
font-size: 8pt * $l10n-ch-qr-ratio;
|
||||
line-height: 9pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.receipt_indication_zone {
|
||||
width: $receipt_width;
|
||||
height: 56mm * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.receipt_amount_zone {
|
||||
width: $receipt_width;
|
||||
height: 14mm * $l10n-ch-qr-ratio;
|
||||
.column {
|
||||
float: left;
|
||||
margin-right: 5mm;
|
||||
}
|
||||
.content {
|
||||
font-size: 8pt * $l10n-ch-qr-ratio;
|
||||
line-height: 11pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
}
|
||||
.receipt_acceptance_point_zone {
|
||||
width: $receipt_width;
|
||||
height: 18mm * $l10n-ch-qr-ratio;
|
||||
.content {
|
||||
float: right;
|
||||
padding-right: 2mm * $l10n-ch-qr-ratio;
|
||||
font-size: 6pt * $l10n-ch-qr-ratio;
|
||||
line-height: 8pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swissqr_body {
|
||||
background-color: white !important;
|
||||
position: absolute;
|
||||
top: 192mm * $l10n-ch-qr-ratio;
|
||||
left: 62mm * $l10n-ch-qr-ratio;
|
||||
width: 148mm * $l10n-ch-qr-ratio;
|
||||
height: 105mm * $l10n-ch-qr-ratio - $rounding_offset;
|
||||
border: 0.75pt * $l10n-ch-qr-ratio dashed black;
|
||||
border-bottom: none;
|
||||
border-right: none;
|
||||
padding: 5mm * $l10n-ch-qr-ratio;
|
||||
.title {
|
||||
font-size: 8pt * $l10n-ch-qr-ratio;
|
||||
line-height: 11pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.content {
|
||||
font-size: 10pt * $l10n-ch-qr-ratio;
|
||||
line-height: 11pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.swissqr_column_left {
|
||||
float: left;
|
||||
width: $left_col_width;
|
||||
.swissqr_section_title{
|
||||
height: 7mm * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.swissqr {
|
||||
margin-top: 5mm * $l10n-ch-qr-ratio;
|
||||
margin-bottom: 5mm * $l10n-ch-qr-ratio;
|
||||
height: 46mm * $l10n-ch-qr-ratio;
|
||||
width: 46mm * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.amount_zone {
|
||||
width: $left_col_width;
|
||||
height: 22mm * $l10n-ch-qr-ratio;
|
||||
.column {
|
||||
margin-right: 3mm;
|
||||
float: left;
|
||||
}
|
||||
.title {
|
||||
font-size: 8pt * $l10n-ch-qr-ratio;
|
||||
line-height: 11pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.content {
|
||||
font-size: 10pt * $l10n-ch-qr-ratio;
|
||||
line-height: 13pt * $l10n-ch-qr-ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
.swissqr_column_right {
|
||||
float: right;
|
||||
width: $right_col_width;
|
||||
}
|
||||
}
|
||||
|
||||
.scissors {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.vertical_scissors {
|
||||
position: absolute;
|
||||
top: 5mm * $l10n-ch-qr-ratio;
|
||||
left: -1.8mm * $l10n-ch-qr-ratio;
|
||||
}
|
||||
.horizontal_scissors {
|
||||
position: absolute;
|
||||
top: -2mm * $l10n-ch-qr-ratio;
|
||||
left: 6mm * $l10n-ch-qr-ratio;
|
||||
}
|
||||
|
||||
}
|
||||
10
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/tests/__init__.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_ch_qr_code
|
||||
from . import test_swissqr
|
||||
from . import test_l10n_ch_isr_print
|
||||
from . import test_l10n_ch_qr_print
|
||||
from . import test_vendor_bill_isr
|
||||
from . import test_onchange_l10n_ch_postal
|
||||
from . import test_gen_isr_reference
|
||||
113
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/tests/test_ch_qr_code.py
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
|
||||
from reportlab.graphics.barcode import createBarcodeDrawing
|
||||
|
||||
from odoo import Command
|
||||
from odoo.tests import tagged
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class TestSwissQRCode(AccountTestInvoicingCommon):
|
||||
""" Tests the generation of Swiss QR-codes on invoices
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref='l10n_ch.l10nch_chart_template'):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.company_data['company'].qr_code = True
|
||||
cls.company_data['company'].country_id = None
|
||||
|
||||
cls.swiss_iban = cls.env['res.partner.bank'].create({
|
||||
'acc_number': 'CH15 3881 5158 3845 3843 7',
|
||||
'partner_id': cls.company_data['company'].partner_id.id,
|
||||
})
|
||||
|
||||
cls.swiss_qr_iban = cls.env['res.partner.bank'].create({
|
||||
'acc_number': 'CH21 3080 8001 2345 6782 7',
|
||||
'partner_id': cls.company_data['company'].partner_id.id,
|
||||
})
|
||||
|
||||
cls.ch_qr_invoice = cls.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': cls.partner_a.id,
|
||||
'currency_id': cls.env.ref('base.CHF').id,
|
||||
'partner_bank_id': cls.swiss_iban.id,
|
||||
'company_id': cls.company_data['company'].id,
|
||||
'payment_reference': "Papa a vu le fifi de lolo",
|
||||
'invoice_line_ids': [
|
||||
Command.create({
|
||||
'quantity': 1,
|
||||
'price_unit': 100,
|
||||
'tax_ids': [],
|
||||
})
|
||||
],
|
||||
})
|
||||
|
||||
def _assign_partner_address(self, partner):
|
||||
partner.write({
|
||||
'country_id': self.env.ref('base.ch').id,
|
||||
'street': "Crab street, 11",
|
||||
'city': "Crab City",
|
||||
'zip': "4242",
|
||||
})
|
||||
|
||||
def test_swiss_qr_code_generation(self):
|
||||
""" Check different cases of Swiss QR-code generation, when qr_method is
|
||||
specified beforehand.
|
||||
"""
|
||||
self.ch_qr_invoice.qr_code_method = 'ch_qr'
|
||||
|
||||
# First check with a regular IBAN
|
||||
with self.assertRaises(UserError, msg="It shouldn't be possible to generate a Swiss QR-code for partners without a complete Swiss address."):
|
||||
self.ch_qr_invoice._generate_qr_code()
|
||||
|
||||
# Setting the address should make it work
|
||||
self._assign_partner_address(self.ch_qr_invoice.company_id.partner_id)
|
||||
self._assign_partner_address(self.ch_qr_invoice.partner_id)
|
||||
|
||||
self.ch_qr_invoice._generate_qr_code()
|
||||
|
||||
# Now, check with a QR-IBAN as the payment account
|
||||
self.ch_qr_invoice.partner_bank_id = self.swiss_qr_iban
|
||||
|
||||
with self.assertRaises(UserError, msg="It shouldn't be possible to generate a Swiss QR-cde for a QR-IBAN without giving it a valid QR-reference as payment reference."):
|
||||
self.ch_qr_invoice._generate_qr_code()
|
||||
|
||||
# Assigning a QR reference should fix it
|
||||
self.ch_qr_invoice.payment_reference = '210000000003139471430009017'
|
||||
|
||||
# even if the invoice is not issued from Switzerland we want to generate the code
|
||||
self.ch_qr_invoice.company_id.partner_id.country_id = self.env.ref('base.fr')
|
||||
self.ch_qr_invoice._generate_qr_code()
|
||||
|
||||
def test_ch_qr_code_detection(self):
|
||||
""" Checks Swiss QR-code auto-detection when no specific QR-method
|
||||
is given to the invoice.
|
||||
"""
|
||||
self._assign_partner_address(self.ch_qr_invoice.company_id.partner_id)
|
||||
self._assign_partner_address(self.ch_qr_invoice.partner_id)
|
||||
self.ch_qr_invoice._generate_qr_code()
|
||||
self.assertEqual(self.ch_qr_invoice.qr_code_method, 'ch_qr', "Swiss QR-code generator should have been chosen for this invoice.")
|
||||
|
||||
def test_ch_qr_code_cross_mask(self):
|
||||
for width, height in ((64, 128), (128, 128), (256, 256), (512, 512)):
|
||||
barcode = createBarcodeDrawing('QR', value='', format='png', width=width, height=height)
|
||||
mask_to_apply = self.env['ir.actions.report'].get_available_barcode_masks()['ch_cross']
|
||||
mask_to_apply(width, height, barcode)
|
||||
zoom_x = width / (32 * (72 / 25.4))
|
||||
zoom_y = height / (32 * (72 / 25.4))
|
||||
self.assertEqual(
|
||||
[zoom_x, 0, 0, zoom_y, 0, 0],
|
||||
barcode.transform,
|
||||
)
|
||||
self.assertEqual(
|
||||
(0, 0, 90.70866141732284, 90.70866141732284),
|
||||
barcode.contents[0].getBounds(),
|
||||
)
|
||||
self.assertEqual(
|
||||
(38.45140157480315, 38.45140157480315, 52.25725984251969, 52.25725984251969),
|
||||
barcode.contents[1].getBounds(),
|
||||
)
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
from odoo.tests import tagged
|
||||
|
||||
QR_IBAN = 'CH21 3080 8001 2345 6782 7'
|
||||
ISR_SUBS_NUMBER = "01-162-8"
|
||||
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class TestGenISRReference(AccountTestInvoicingCommon):
|
||||
"""Check condition of generation of and content of the structured ref"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref="l10n_ch.l10nch_chart_template"):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||
cls.bank = cls.env["res.bank"].create(
|
||||
{
|
||||
"name": "Alternative Bank Schweiz AG",
|
||||
"bic": "ALSWCH21XXX",
|
||||
}
|
||||
)
|
||||
cls.bank_acc_isr = cls.env["res.partner.bank"].create(
|
||||
{
|
||||
"acc_number": "ISR",
|
||||
"l10n_ch_isr_subscription_chf": "01-162-8",
|
||||
"bank_id": cls.bank.id,
|
||||
"partner_id": cls.partner_a.id,
|
||||
}
|
||||
)
|
||||
cls.bank_acc_qriban = cls.env["res.partner.bank"].create(
|
||||
{
|
||||
"acc_number": QR_IBAN,
|
||||
"bank_id": cls.bank.id,
|
||||
"partner_id": cls.partner_a.id,
|
||||
}
|
||||
)
|
||||
cls.product_a.taxes_id = cls.product_b.taxes_id = None
|
||||
cls.invoice = cls.init_invoice("out_invoice", products=cls.product_a+cls.product_b)
|
||||
|
||||
def test_isr(self):
|
||||
|
||||
self.invoice.partner_bank_id = self.bank_acc_isr
|
||||
self.invoice.name = "INV/01234567890"
|
||||
# Post invoice to have the expected amount due (amount_residual)
|
||||
self.invoice.action_post()
|
||||
|
||||
expected_isr = "000000000000000012345678903"
|
||||
expected_isr_spaced = "00 00000 00000 00001 23456 78903"
|
||||
expected_optical_line = "0100001297203>000000000000000012345678903+ 010001628>"
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_number, expected_isr)
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_number_spaced, expected_isr_spaced)
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_optical_line, expected_optical_line)
|
||||
|
||||
def test_qrr(self):
|
||||
self.invoice.partner_bank_id = self.bank_acc_qriban
|
||||
|
||||
self.invoice.name = "INV/01234567890"
|
||||
|
||||
expected_isr = "000000000000000012345678903"
|
||||
expected_isr_spaced = "00 00000 00000 00001 23456 78903"
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_number, expected_isr)
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_number_spaced, expected_isr_spaced)
|
||||
# No need to check optical line, we have no use for it with QR-bill
|
||||
|
||||
def test_isr_long_reference(self):
|
||||
self.invoice.partner_bank_id = self.bank_acc_isr
|
||||
|
||||
self.invoice.name = "INV/123456789012345678901234567890"
|
||||
# Post invoice to have the expected amount due (amount_residual)
|
||||
self.invoice.action_post()
|
||||
|
||||
expected_isr = "567890123456789012345678901"
|
||||
expected_isr_spaced = "56 78901 23456 78901 23456 78901"
|
||||
expected_optical_line = "0100001297203>567890123456789012345678901+ 010001628>"
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_number, expected_isr)
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_number_spaced, expected_isr_spaced)
|
||||
self.assertEqual(self.invoice.l10n_ch_isr_optical_line, expected_optical_line)
|
||||
|
||||
def test_missing_isr_subscription_num(self):
|
||||
self.bank_acc_isr.l10n_ch_isr_subscription_chf = False
|
||||
|
||||
self.invoice.partner_bank_id = self.bank_acc_isr
|
||||
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number_spaced)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_optical_line)
|
||||
|
||||
def test_missing_isr_subscription_num_in_wrong_field(self):
|
||||
self.bank_acc_isr.l10n_ch_isr_subscription_chf = False
|
||||
self.bank_acc_isr.l10n_ch_postal = ISR_SUBS_NUMBER
|
||||
|
||||
self.invoice.partner_bank_id = self.bank_acc_isr
|
||||
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number_spaced)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_optical_line)
|
||||
|
||||
def test_no_bank_account(self):
|
||||
self.invoice.partner_bank_id = False
|
||||
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number_spaced)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_optical_line)
|
||||
|
||||
def test_wrong_currency(self):
|
||||
self.invoice.partner_bank_id = self.bank_acc_isr
|
||||
self.invoice.currency_id = self.env.ref("base.BTN")
|
||||
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_number_spaced)
|
||||
self.assertFalse(self.invoice.l10n_ch_isr_optical_line)
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
from odoo.tests import tagged
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class ISRTest(AccountTestInvoicingCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref='l10n_ch.l10nch_chart_template'):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
def print_isr(self, invoice):
|
||||
try:
|
||||
invoice.action_invoice_sent()
|
||||
return True
|
||||
except ValidationError:
|
||||
return False
|
||||
|
||||
def test_l10n_ch_postals(self):
|
||||
|
||||
def assertBankAccountValid(account_number, expected_account_type, expected_postal=None):
|
||||
partner_bank = self.env['res.partner.bank'].create({
|
||||
'acc_number': account_number,
|
||||
'partner_id': self.partner_a.id,
|
||||
})
|
||||
expected_vals = {'acc_type': expected_account_type}
|
||||
if expected_postal is not None:
|
||||
expected_vals['l10n_ch_postal'] = expected_postal
|
||||
|
||||
self.assertRecordValues(partner_bank, [expected_vals])
|
||||
|
||||
assertBankAccountValid('010391391', 'postal', expected_postal='010391391')
|
||||
assertBankAccountValid('CH6309000000250097798', 'iban', expected_postal='25-9779-8')
|
||||
assertBankAccountValid('GR1601101250000000012300695', 'iban', expected_postal=False)
|
||||
|
||||
partner_bank = self.env['res.partner.bank'].create({
|
||||
'acc_number': '010391394',
|
||||
'partner_id': self.partner_a.id,
|
||||
})
|
||||
self.assertNotEqual(partner_bank.acc_type, 'postal')
|
||||
|
||||
def test_isr(self):
|
||||
isr_bank_account = self.env['res.partner.bank'].create({
|
||||
'acc_number': "ISR {} number",
|
||||
'partner_id': self.env.company.partner_id.id,
|
||||
'l10n_ch_isr_subscription_chf': '01-39139-1',
|
||||
})
|
||||
|
||||
invoice_chf = self.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_bank_id': isr_bank_account.id,
|
||||
'currency_id': self.env.ref('base.CHF').id,
|
||||
'invoice_date': '2019-01-01',
|
||||
'invoice_line_ids': [(0, 0, {'product_id': self.product_a.id})],
|
||||
})
|
||||
invoice_chf.action_post()
|
||||
self.assertTrue(self.print_isr(invoice_chf))
|
||||
self.env.ref('base.EUR').active = True
|
||||
invoice_eur = self.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_bank_id': isr_bank_account.id,
|
||||
'currency_id': self.env.ref('base.EUR').id,
|
||||
'invoice_date': '2019-01-01',
|
||||
'invoice_line_ids': [(0, 0, {'product_id': self.product_a.id})],
|
||||
})
|
||||
invoice_eur.action_post()
|
||||
#a normal invoice will still get printed
|
||||
self.assertTrue(self.print_isr(invoice_eur))
|
||||
# However, a isr bill can't be printed with those infos
|
||||
self.assertFalse(invoice_eur.l10n_ch_isr_valid)
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import logging
|
||||
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import tagged
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class QRPrintTest(AccountTestInvoicingCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref='l10n_ch.l10nch_chart_template'):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
# the partner must be located in Switzerland.
|
||||
cls.partner = cls.env['res.partner'].create({
|
||||
'name': 'Bobby',
|
||||
'country_id': cls.env.ref('base.ch').id,
|
||||
})
|
||||
# The bank account must be QR-compatible
|
||||
cls.qr_bank_account = cls.env['res.partner.bank'].create({
|
||||
'acc_number': "CH4431999123000889012",
|
||||
'partner_id': cls.env.company.partner_id.id,
|
||||
'l10n_ch_isr_subscription_chf': '01-39139-1',
|
||||
})
|
||||
cls.correct_invoice_chf = cls.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': cls.partner.id,
|
||||
'partner_bank_id': cls.qr_bank_account.id,
|
||||
'currency_id': cls.env.ref('base.CHF').id,
|
||||
'invoice_date': '2019-01-01',
|
||||
'invoice_line_ids': [(0, 0, {'product_id': cls.product_a.id})],
|
||||
})
|
||||
|
||||
cls.correct_invoice_eur = cls.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': cls.partner.id,
|
||||
'partner_bank_id': cls.qr_bank_account.id,
|
||||
'currency_id': cls.env.ref('base.EUR').id,
|
||||
'invoice_date': '2019-01-01',
|
||||
'invoice_line_ids': [(0, 0, {'product_id': cls.product_a.id})],
|
||||
})
|
||||
|
||||
cls.wrong_partner_invoice = cls.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_bank_id': cls.qr_bank_account.id,
|
||||
'currency_id': cls.env.ref('base.EUR').id,
|
||||
'invoice_date': '2019-01-01',
|
||||
'invoice_line_ids': [(0, 0, {'product_id': cls.product_a.id})],
|
||||
})
|
||||
|
||||
def print_qr_bill(self, invoice):
|
||||
try:
|
||||
invoice.action_invoice_sent()
|
||||
return True
|
||||
except UserError as e:
|
||||
_logger.warning(e.name)
|
||||
return False
|
||||
|
||||
def test_print_qr(self):
|
||||
self.correct_invoice_chf.action_post()
|
||||
self.assertTrue(self.print_qr_bill(self.correct_invoice_chf))
|
||||
|
||||
#The QR can also be printed if the currency is EUR
|
||||
self.env.ref('base.EUR').active = True
|
||||
self.correct_invoice_eur.action_post()
|
||||
self.assertTrue(self.print_qr_bill(self.correct_invoice_eur))
|
||||
|
||||
#A normal invoice will be printed if the partner is not from Switzerland
|
||||
self.wrong_partner_invoice.action_post()
|
||||
self.assertTrue(self.print_qr_bill(self.wrong_partner_invoice))
|
||||
|
||||
#However, a qr bill can't be printed with those infos
|
||||
self.assertFalse(self.wrong_partner_invoice.l10n_ch_is_qr_valid)
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import Form, TransactionCase
|
||||
|
||||
|
||||
CH_ISR_ISSUER = '01-162-8'
|
||||
CH_IBAN = 'CH15 3881 5158 3845 3843 7'
|
||||
FR_IBAN = 'FR83 8723 4133 8709 9079 4002 530'
|
||||
CH_POST_IBAN = 'CH09 0900 0000 1000 8060 7'
|
||||
CH_POSTAL_ACC = '10-8060-7'
|
||||
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class TestOnchangePostal(TransactionCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||
|
||||
cls.partner = cls.env['res.partner'].create({
|
||||
'name': 'Swiss Company',
|
||||
'street': 'Route de Berne 41',
|
||||
'zip': '1000',
|
||||
'city': 'Lausanne',
|
||||
'is_company': 1,
|
||||
'country_id': cls.env.ref('base.ch').id,
|
||||
})
|
||||
cls.ch_bank = cls.env['res.bank'].create({
|
||||
'name': 'Alternative Bank Schweiz AG',
|
||||
'bic': 'ALSWCH21XXX',
|
||||
})
|
||||
cls.post_bank = cls.env['res.bank'].search(
|
||||
[('bic', '=', 'POFICHBEXXX')])
|
||||
if not cls.post_bank:
|
||||
cls.post_bank = cls.env['res.bank'].create({
|
||||
'name': 'PostFinance AG',
|
||||
'bic': 'POFICHBEXXX',
|
||||
})
|
||||
|
||||
def new_partner_bank_form(self):
|
||||
form = Form(
|
||||
self.env['res.partner.bank'],
|
||||
view="l10n_ch.isr_partner_bank_form",
|
||||
)
|
||||
form.partner_id = self.partner
|
||||
return form
|
||||
|
||||
def test_onchange_acc_number_isr_issuer(self):
|
||||
"""The user entered ISR issuer number into acc_number
|
||||
|
||||
We detect and move it to l10n_ch_postal.
|
||||
It must be moved as it is not unique.
|
||||
"""
|
||||
bank_acc = self.new_partner_bank_form()
|
||||
bank_acc.acc_number = CH_ISR_ISSUER
|
||||
account = bank_acc.save()
|
||||
|
||||
self.assertEqual(
|
||||
account.acc_number,
|
||||
"{} {}".format(CH_ISR_ISSUER, self.partner.name)
|
||||
)
|
||||
self.assertEqual(account.l10n_ch_postal, CH_ISR_ISSUER)
|
||||
self.assertEqual(account.acc_type, 'postal')
|
||||
|
||||
def test_onchange_acc_number_postal(self):
|
||||
"""The user entered postal number into acc_number
|
||||
|
||||
We detect and copy it to l10n_ch_postal.
|
||||
"""
|
||||
bank_acc = self.new_partner_bank_form()
|
||||
bank_acc.acc_number = CH_POSTAL_ACC
|
||||
account = bank_acc.save()
|
||||
|
||||
self.assertEqual(account.acc_number, CH_POSTAL_ACC)
|
||||
self.assertEqual(account.l10n_ch_postal, CH_POSTAL_ACC)
|
||||
self.assertEqual(account.acc_type, 'postal')
|
||||
|
||||
def test_onchange_acc_number_iban_ch(self):
|
||||
bank_acc = self.new_partner_bank_form()
|
||||
bank_acc.acc_number = CH_IBAN
|
||||
account = bank_acc.save()
|
||||
|
||||
self.assertEqual(account.acc_number, CH_IBAN)
|
||||
self.assertFalse(account.l10n_ch_postal)
|
||||
self.assertEqual(account.acc_type, 'iban')
|
||||
|
||||
def test_onchange_acc_number_iban_ch_postfinance(self):
|
||||
"""The user enter a postal IBAN, postal number can be deduced"""
|
||||
bank_acc = self.new_partner_bank_form()
|
||||
bank_acc.acc_number = CH_POST_IBAN
|
||||
account = bank_acc.save()
|
||||
|
||||
self.assertEqual(account.acc_number, CH_POST_IBAN)
|
||||
self.assertEqual(account.l10n_ch_postal, CH_POSTAL_ACC)
|
||||
self.assertEqual(account.acc_type, 'iban')
|
||||
|
||||
def test_onchange_acc_number_iban_foreign(self):
|
||||
"""Check IBAN still works changed"""
|
||||
bank_acc = self.new_partner_bank_form()
|
||||
bank_acc.acc_number = FR_IBAN
|
||||
account = bank_acc.save()
|
||||
|
||||
self.assertEqual(account.acc_number, FR_IBAN)
|
||||
self.assertFalse(account.l10n_ch_postal)
|
||||
self.assertEqual(account.acc_type, 'iban')
|
||||
|
||||
def test_onchange_acc_number_none(self):
|
||||
"""Check misc format still works"""
|
||||
bank_acc = self.new_partner_bank_form()
|
||||
bank_acc.acc_number = 'anything'
|
||||
account = bank_acc.save()
|
||||
|
||||
self.assertEqual(account.acc_number, 'anything')
|
||||
self.assertFalse(account.l10n_ch_postal)
|
||||
self.assertEqual(account.acc_type, 'bank')
|
||||
223
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/tests/test_swissqr.py
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
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'
|
||||
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class TestSwissQR(AccountTestInvoicingCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref='l10n_ch.l10nch_chart_template'):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
def setUp(self):
|
||||
super(TestSwissQR, self).setUp()
|
||||
# Activate SwissQR in Swiss invoices
|
||||
self.env['ir.config_parameter'].create(
|
||||
{'key': 'l10n_ch.print_qrcode', 'value': '1'}
|
||||
)
|
||||
self.customer = self.env['res.partner'].create(
|
||||
{
|
||||
"name": "Partner",
|
||||
"street": "Route de Berne 41",
|
||||
"street2": "",
|
||||
"zip": "1000",
|
||||
"city": "Lausanne",
|
||||
"country_id": self.env.ref("base.ch").id,
|
||||
}
|
||||
)
|
||||
self.env.user.company_id.partner_id.write(
|
||||
{
|
||||
"street": "Route de Berne 88",
|
||||
"street2": "",
|
||||
"zip": "2000",
|
||||
"city": "Neuchâtel",
|
||||
"country_id": self.env.ref('base.ch').id,
|
||||
}
|
||||
)
|
||||
self.product = self.env['product.product'].create({
|
||||
'name': 'Customizable Desk',
|
||||
})
|
||||
self.invoice1 = self.create_invoice('base.CHF')
|
||||
sale_journal = self.env['account.journal'].search([("type", "=", "sale")])
|
||||
sale_journal.invoice_reference_model = "ch"
|
||||
|
||||
def create_invoice(self, currency_to_use='base.CHF'):
|
||||
""" Generates a test invoice """
|
||||
|
||||
account = self.env['account.account'].search(
|
||||
[('account_type', '=', 'asset_current')], limit=1
|
||||
)
|
||||
invoice = (
|
||||
self.env['account.move']
|
||||
.create(
|
||||
{
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': self.customer.id,
|
||||
'currency_id': self.env.ref(currency_to_use).id,
|
||||
'date': time.strftime('%Y') + '-12-22',
|
||||
'invoice_line_ids': [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'account_id': account.id,
|
||||
'quantity': 1,
|
||||
'price_unit': 42.0,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
return invoice
|
||||
|
||||
def create_account(self, number):
|
||||
""" Generates a test res.partner.bank. """
|
||||
return self.env['res.partner.bank'].create(
|
||||
{
|
||||
'acc_number': number,
|
||||
'partner_id': self.env.user.company_id.partner_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
def swissqr_not_generated(self, invoice):
|
||||
""" Prints the given invoice and tests that no Swiss QR generation is triggered. """
|
||||
self.assertFalse(
|
||||
invoice.partner_bank_id._eligible_for_qr_code('ch_qr', invoice.partner_id, invoice.currency_id),
|
||||
'No Swiss QR should be generated for this invoice',
|
||||
)
|
||||
|
||||
def swissqr_generated(self, invoice, ref_type='NON'):
|
||||
""" Ensure correct params for Swiss QR generation. """
|
||||
|
||||
self.assertTrue(
|
||||
invoice.partner_bank_id._eligible_for_qr_code('ch_qr', invoice.partner_id, invoice.currency_id), 'A Swiss QR can be generated'
|
||||
)
|
||||
|
||||
if ref_type == 'QRR':
|
||||
self.assertTrue(invoice.payment_reference)
|
||||
struct_ref = invoice.payment_reference
|
||||
unstr_msg = invoice.ref or invoice.name or ''
|
||||
else:
|
||||
struct_ref = ''
|
||||
unstr_msg = invoice.payment_reference or invoice.ref or invoice.name or ''
|
||||
unstr_msg = unstr_msg or invoice.number
|
||||
|
||||
payload = (
|
||||
"SPC\n"
|
||||
"0200\n"
|
||||
"1\n"
|
||||
"{iban}\n"
|
||||
"K\n"
|
||||
"company_1_data\n"
|
||||
"Route de Berne 88\n"
|
||||
"2000 Neuchâtel\n"
|
||||
"\n\n"
|
||||
"CH\n"
|
||||
"\n\n\n\n\n\n\n"
|
||||
"42.00\n"
|
||||
"CHF\n"
|
||||
"K\n"
|
||||
"Partner\n"
|
||||
"Route de Berne 41\n"
|
||||
"1000 Lausanne\n"
|
||||
"\n\n"
|
||||
"CH\n"
|
||||
"{ref_type}\n"
|
||||
"{struct_ref}\n"
|
||||
"{unstr_msg}\n"
|
||||
"EPD"
|
||||
).format(
|
||||
iban=invoice.partner_bank_id.sanitized_acc_number,
|
||||
ref_type=ref_type,
|
||||
struct_ref=struct_ref or '',
|
||||
unstr_msg=unstr_msg,
|
||||
)
|
||||
|
||||
expected_params = {
|
||||
'barcode_type': 'QR',
|
||||
'barLevel': 'M',
|
||||
'width': 256,
|
||||
'height': 256,
|
||||
'quiet': 1,
|
||||
'mask': 'ch_cross',
|
||||
'value': payload,
|
||||
}
|
||||
|
||||
params = invoice.partner_bank_id._get_qr_code_generation_params(
|
||||
'ch_qr', 42.0, invoice.currency_id, invoice.partner_id, unstr_msg, struct_ref
|
||||
)
|
||||
|
||||
self.assertEqual(params, expected_params)
|
||||
|
||||
def test_swissQR_missing_bank(self):
|
||||
# Let us test the generation of a SwissQR for an invoice, first by showing an
|
||||
# QR is included in the invoice is only generated when Odoo has all the data it needs.
|
||||
with self.assertRaises(UserError), self.cr.savepoint():
|
||||
self.invoice1.action_post()
|
||||
self.swissqr_not_generated(self.invoice1)
|
||||
|
||||
def test_swissQR_iban(self):
|
||||
# Now we add an account for payment to our invoice
|
||||
# Here we don't use a structured reference
|
||||
iban_account = self.create_account(CH_IBAN)
|
||||
self.invoice1.partner_bank_id = iban_account
|
||||
self.invoice1.action_post()
|
||||
self.swissqr_generated(self.invoice1, ref_type="NON")
|
||||
|
||||
def test_swissQR_qriban(self):
|
||||
# Now use a proper QR-IBAN, we are good to print a QR Bill
|
||||
qriban_account = self.create_account(QR_IBAN)
|
||||
self.assertTrue(qriban_account.l10n_ch_qr_iban)
|
||||
self.invoice1.partner_bank_id = qriban_account
|
||||
self.invoice1.action_post()
|
||||
self.swissqr_generated(self.invoice1, ref_type="QRR")
|
||||
|
||||
def test_swiss_order_reference_isr_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]))
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo.tests import Form, common, tagged
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
CH_ISR_SUBSCRIPTION = "01-162-8"
|
||||
CH_POSTAL = "10-8060-7"
|
||||
CH_IBAN = "CH15 3881 5158 3845 3843 7"
|
||||
ISR_REFERENCE_GOOD = "16 00011 23456 78901 23456 78901"
|
||||
ISR_REFERENCE_ZEROS = "00 00000 00000 00001 23456 78903"
|
||||
ISR_REFERENCE_NO_ZEROS = "1 23456 78903"
|
||||
ISR_REFERENCE_BAD = "11 11111 11111 11111 11111 11111"
|
||||
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class TestVendorBillISR(common.TransactionCase):
|
||||
"""Check we can encode Vendor bills with ISR references
|
||||
|
||||
The ISR is a structured reference with a checksum.
|
||||
User are guided to ensure they don't encode wrong ISR references.
|
||||
Only vendors with ISR issuer accounts send ISR references.
|
||||
|
||||
ISR references can be received at least till 2022.
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestVendorBillISR, cls).setUpClass()
|
||||
cls.abs_bank = cls.env["res.bank"].create(
|
||||
{"name": "Alternative Bank Schweiz", "bic": "ABSOCH22XXX"}
|
||||
)
|
||||
cls.supplier1 = cls.env["res.partner"].create({"name": "Supplier ISR"})
|
||||
cls.supplier2 = cls.env["res.partner"].create({"name": "Supplier postal"})
|
||||
cls.supplier3 = cls.env["res.partner"].create({"name": "Supplier IBAN"})
|
||||
|
||||
cls.bank_acc_isr = cls.env['res.partner.bank'].create({
|
||||
"acc_number": "ISR 01-162-8 Supplier ISR",
|
||||
"partner_id": cls.supplier1.id,
|
||||
"l10n_ch_postal": CH_ISR_SUBSCRIPTION,
|
||||
})
|
||||
cls.bank_acc_postal = cls.env['res.partner.bank'].create({
|
||||
"acc_number": CH_POSTAL,
|
||||
"partner_id": cls.supplier2.id,
|
||||
"l10n_ch_postal": CH_POSTAL,
|
||||
})
|
||||
cls.bank_acc_iban = cls.env['res.partner.bank'].create({
|
||||
"acc_number": CH_IBAN,
|
||||
"partner_id": cls.supplier2.id,
|
||||
"l10n_ch_postal": False,
|
||||
})
|
||||
|
||||
def test_isr_ref(self):
|
||||
"""Enter ISR reference with ISR subscription account number
|
||||
|
||||
The vendor bill can be saved.
|
||||
"""
|
||||
self.env.company.country_id = self.env.ref('base.ch')
|
||||
self.env.company.account_fiscal_country_id = self.env.company.country_id
|
||||
form = Form(self.env["account.move"].with_context(
|
||||
default_move_type="in_invoice"), view="l10n_ch.isr_invoice_form")
|
||||
form.partner_id = self.supplier1
|
||||
form.partner_bank_id = self.bank_acc_isr
|
||||
|
||||
form.payment_reference = ISR_REFERENCE_GOOD
|
||||
invoice = form.save()
|
||||
|
||||
self.assertFalse(invoice.l10n_ch_isr_needs_fixing)
|
||||
|
||||
def test_isr_ref_with_zeros(self):
|
||||
"""Enter ISR reference with ISR subscription account number
|
||||
|
||||
An ISR Reference can have lots of zeros on the left.
|
||||
|
||||
The vendor bill can be saved.
|
||||
"""
|
||||
self.env.company.country_id = self.env.ref('base.ch')
|
||||
self.env.company.account_fiscal_country_id = self.env.company.country_id
|
||||
form = Form(self.env["account.move"].with_context(
|
||||
default_move_type="in_invoice"), view="l10n_ch.isr_invoice_form")
|
||||
form.partner_id = self.supplier1
|
||||
form.partner_bank_id = self.bank_acc_isr
|
||||
|
||||
form.payment_reference = ISR_REFERENCE_ZEROS
|
||||
invoice = form.save()
|
||||
|
||||
self.assertFalse(invoice.l10n_ch_isr_needs_fixing)
|
||||
|
||||
def test_isr_ref_no_zeros(self):
|
||||
"""Enter ISR reference with ISR subscription account number
|
||||
|
||||
An ISR Reference full of zeros can be entered starting by the
|
||||
first non zero digit.
|
||||
|
||||
The vendor bill can be saved.
|
||||
"""
|
||||
self.env.company.country_id = self.env.ref('base.ch')
|
||||
self.env.company.account_fiscal_country_id = self.env.company.country_id
|
||||
form = Form(self.env["account.move"].with_context(
|
||||
default_move_type="in_invoice"), view="l10n_ch.isr_invoice_form")
|
||||
form.partner_id = self.supplier1
|
||||
form.partner_bank_id = self.bank_acc_isr
|
||||
|
||||
form.payment_reference = ISR_REFERENCE_NO_ZEROS
|
||||
invoice = form.save()
|
||||
|
||||
self.assertFalse(invoice.l10n_ch_isr_needs_fixing)
|
||||
|
||||
def test_isr_wrong_ref(self):
|
||||
"""Mistype ISR reference with ISR subscription account number
|
||||
Check it will show the warning
|
||||
"""
|
||||
self.env.company.country_id = self.env.ref('base.ch')
|
||||
self.env.company.account_fiscal_country_id = self.env.company.country_id
|
||||
form = Form(self.env["account.move"].with_context(
|
||||
default_move_type="in_invoice"), view="l10n_ch.isr_invoice_form")
|
||||
form.partner_id = self.supplier1
|
||||
form.partner_bank_id = self.bank_acc_isr
|
||||
|
||||
form.payment_reference = ISR_REFERENCE_BAD
|
||||
invoice = form.save()
|
||||
|
||||
self.assertTrue(invoice.l10n_ch_isr_needs_fixing)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<template id="l10n_ch_report_invoice_document" inherit_id="account.report_invoice_document">
|
||||
<xpath expr="//div[@id='qrcode']" position="attributes">
|
||||
<attribute name="t-if" add="and o.qr_code_method != 'ch_qr'" separator=" "/>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="isr_invoice_form" model="ir.ui.view">
|
||||
<field name="name">l10n_ch.account.invoice.form</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='is_move_sent']" position="after">
|
||||
<field name="l10n_ch_isr_sent" invisible="1"/>
|
||||
<field name="l10n_ch_currency_name" invisible="1" readonly="1"/>
|
||||
<field name="l10n_ch_is_qr_valid" invisible="1"/>
|
||||
</xpath>
|
||||
<header position="after">
|
||||
<field name="l10n_ch_isr_needs_fixing" invisible="1"/>
|
||||
<div groups="account.group_account_invoice" class="alert alert-warning" role="alert" style="margin-bottom:0px;" attrs="{'invisible': [('l10n_ch_isr_needs_fixing', '=', False)]}">
|
||||
Please fill in a correct ISR reference in the payment reference. The banks will refuse your payment file otherwise.
|
||||
</div>
|
||||
</header>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="isr_invoice_search_view" model="ir.ui.view">
|
||||
<field name="name">l10n_ch.invoice.select</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//search" position="inside">
|
||||
<field name="l10n_ch_isr_number" string="ISR reference number"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!--Overridden action (and primary child view), so the filter are only
|
||||
available for customer invoices-->
|
||||
<record id="account.action_move_out_invoice_type" model="ir.actions.act_window">
|
||||
<field name="name">Customer Invoices</field>
|
||||
<field name="res_model">account.move</field>
|
||||
<field name="search_view_id" ref="isr_invoice_search_view"/>
|
||||
</record>
|
||||
|
||||
<record id="l10n_ch_qr_server_action" model="ir.actions.server">
|
||||
<field name="name">Print QR Invoices</field>
|
||||
<field name="model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_view_types">list</field>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
if records:
|
||||
action = records.l10n_ch_action_print_qr()
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="l10n_ch_qr_invoice_wizard_form" model="ir.ui.view">
|
||||
<field name="name">l10n_ch.qr_invoice.wizard.form</field>
|
||||
<field name="model">l10n_ch.qr_invoice.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="QR printing encountered a problem">
|
||||
<field name='nb_qr_inv' invisible="1"/>
|
||||
<field name="nb_classic_inv" invisible="1"/>
|
||||
<field name="nb_isr_inv" invisible="1"/>
|
||||
<p>
|
||||
<field name="qr_inv_text"/>
|
||||
<field name="isr_inv_text"/>
|
||||
<field name="classic_inv_text"/>
|
||||
</p>
|
||||
<p>
|
||||
To be able to print all invoices in the QR format, you might need to : <br/>
|
||||
- check the account is a valid QR-IBAN<br/>
|
||||
- or check your company and the partners are located in Switzerland.<br/>
|
||||
Press Check Invalid Invoices to see a list of the invoices that were printed without an ISR or a QR.
|
||||
</p>
|
||||
<footer>
|
||||
<button name="print_all_invoices" string="Print All" type="object" class="btn-primary"/>
|
||||
<button name="action_view_faulty_invoices" string="Check invalid invoices" type="object"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="l10n_ch_qr_invoice_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Qr Batch error Wizard</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">l10n_ch.qr_invoice.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="l10n_ch_qr_invoice_wizard_form"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="isr_partner_bank_form" model="ir.ui.view">
|
||||
<field name="name">l10n_ch.res.partner.bank.form</field>
|
||||
<field name="model">res.partner.bank</field>
|
||||
<field name="inherit_id" ref="base.view_partner_bank_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='acc_number']" position="after">
|
||||
<field name="l10n_ch_qr_iban" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
<label for="l10n_ch_postal" string="ISR Client Identification Number" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
<field name="l10n_ch_postal" nolabel="1" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
<field name="l10n_ch_postal" attrs="{'invisible': [('l10n_ch_show_subscription', '=', True)]}"/>
|
||||
<field name="l10n_ch_show_subscription" invisible="1"/>
|
||||
<field name="l10n_ch_isr_subscription_chf" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
<field name="l10n_ch_isr_subscription_eur" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="isr_partner_bank_tree" model="ir.ui.view">
|
||||
<field name="name">l10n_ch.res.partner.bank.tree</field>
|
||||
<field name="model">res.partner.bank</field>
|
||||
<field name="inherit_id" ref="base.view_partner_bank_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='acc_number']" position="after">
|
||||
<field name="l10n_ch_postal" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="isr_partner_property_bank_tree" model="ir.ui.view">
|
||||
<field name="name">l10n_ch.res.partner.property.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="account.view_partner_property_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='acc_number']" position="after">
|
||||
<field name="l10n_ch_postal" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.l10n.ch</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="account.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='invoicing_settings']" position="inside">
|
||||
<div class="col-12 col-lg-6 o_setting_box" id="l10n_ch-isr_print_bank" attrs="{'invisible': [('country_code', '!=', 'CH')]}">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="l10n_ch_isr_print_bank_location"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="l10n_ch_isr_print_bank_location"/>
|
||||
<div class="text-muted">
|
||||
Print the coordinates of your bank under the 'Payment for' title of the ISR.
|
||||
Your address will be moved to the 'in favour of' section.
|
||||
</div>
|
||||
<div class="content-group" attrs="{'invisible': [('l10n_ch_isr_print_bank_location', '=', False)]}">
|
||||
<div class="row mt16">
|
||||
<label for="l10n_ch_isr_preprinted_bank" class="col-lg-4 o_light_label"/>
|
||||
<field name="l10n_ch_isr_preprinted_bank"/>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="l10n_ch_isr_preprinted_account" class="col-lg-4 o_light_label"/>
|
||||
<field name="l10n_ch_isr_preprinted_account"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 o_setting_box" id="l10n_ch-isr_print_scanline_offset" attrs="{'invisible': [('country_code', '!=', 'CH')]}">
|
||||
<div class="o_setting_left_pane"/>
|
||||
<div class="o_setting_right_pane">
|
||||
<span class="o_form_label">ISR scan line offset</span>
|
||||
<div class="text-muted">
|
||||
Offset to move the scan line in mm
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<div class="row mt16">
|
||||
<label for="l10n_ch_isr_scan_line_top" class="col-lg-4 o_light_label"/>
|
||||
<field name="l10n_ch_isr_scan_line_top"/>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="l10n_ch_isr_scan_line_left" class="col-lg-4 o_light_label"/>
|
||||
<field name="l10n_ch_isr_scan_line_left"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="setup_bank_account_wizard_inherit" model="ir.ui.view">
|
||||
<field name="name">account.setup.bank.manual.config.form.ch.inherit</field>
|
||||
<field name="model">account.setup.bank.manual.config</field>
|
||||
<field name="inherit_id" ref="account.setup_bank_account_wizard"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="bank_bic" position="after">
|
||||
<field name="l10n_ch_show_subscription" invisible="1"/>
|
||||
<field name="l10n_ch_isr_subscription_chf" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
<label for="l10n_ch_postal" string="ISR Client Identification Number" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
<field name="l10n_ch_postal" nolabel="1" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
<field name="l10n_ch_qr_iban" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
4
odoo-bringout-oca-ocb-l10n_ch/l10n_ch/wizard/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import setup_wizards
|
||||
from . import qr_invoice_wizard
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class QrInvoiceWizard(models.TransientModel):
|
||||
'''
|
||||
Wizard :
|
||||
When multiple invoices are selected to be printed in the QR-Iban format,
|
||||
this wizard will appear if one or more invoice(s) could not be QR-printed (wrong format...)
|
||||
The user will then be able to print the invoices (in the format available, priority : QR --> ISR --> normal)
|
||||
or to see a list of the non-QR/ISR invoices.
|
||||
The non-QR/ISR invoices will have a note logged in their chatter, detailing the reason of the failure.
|
||||
'''
|
||||
_name = 'l10n_ch.qr_invoice.wizard'
|
||||
_description = 'Handles problems occurring while creating multiple QR-invoices at once'
|
||||
|
||||
nb_qr_inv = fields.Integer(readonly=True)
|
||||
nb_isr_inv = fields.Integer(readonly=True)
|
||||
nb_classic_inv = fields.Integer(readonly=True)
|
||||
qr_inv_text = fields.Text(readonly=True)
|
||||
isr_inv_text = fields.Text(readonly=True)
|
||||
classic_inv_text = fields.Text(readonly=True)
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
# Extends 'base'.
|
||||
|
||||
def determine_invoices_text(nb_inv, inv_format):
|
||||
'''
|
||||
Creates a sentence explaining nb_inv invoices could be printed in the inv_format format.
|
||||
'''
|
||||
if nb_inv == 0:
|
||||
return _("No invoice could be printed in the %s format.", inv_format)
|
||||
if nb_inv == 1:
|
||||
return _("One invoice could be printed in the %s format.", inv_format)
|
||||
return _("%s invoices could be printed in the %s format.", nb_inv, inv_format)
|
||||
|
||||
if not self._context.get('active_ids'):
|
||||
raise UserError(_("No invoice was found to be printed."))
|
||||
|
||||
invoices = self.env['account.move'].browse(self._context['active_ids'])
|
||||
companies = invoices.company_id
|
||||
if len(companies) != 1 or companies[0].country_code != 'CH':
|
||||
raise UserError(_("All selected invoices must belong to the same Switzerland company"))
|
||||
|
||||
results = super().default_get(fields)
|
||||
dispatched_invoices = invoices._l10n_ch_dispatch_invoices_to_print()
|
||||
results.update({
|
||||
'nb_qr_inv': len(dispatched_invoices['qr']),
|
||||
'nb_isr_inv': len(dispatched_invoices['isr']),
|
||||
'nb_classic_inv': len(dispatched_invoices['classic']),
|
||||
'qr_inv_text': determine_invoices_text(nb_inv=len(dispatched_invoices['qr']), inv_format="QR"),
|
||||
'isr_inv_text': determine_invoices_text(nb_inv=len(dispatched_invoices['isr']), inv_format="ISR"),
|
||||
'classic_inv_text': determine_invoices_text(nb_inv=len(dispatched_invoices['classic']),
|
||||
inv_format="classic"),
|
||||
})
|
||||
return results
|
||||
|
||||
def print_all_invoices(self):
|
||||
'''
|
||||
Triggered by the Print All button
|
||||
'''
|
||||
all_invoices_ids = self.env.context.get('inv_ids')
|
||||
return self.env.ref('account.account_invoices').report_action(all_invoices_ids)
|
||||
|
||||
def action_view_faulty_invoices(self):
|
||||
'''
|
||||
Open a list view of all the invoices that could not be printed in the QR nor the ISR format.
|
||||
'''
|
||||
# Prints the error stopping the invoice from being QR-printed in the invoice's chatter.
|
||||
invoices = self.env['account.move'].browse(self._context['active_ids'])
|
||||
dispatched_invoices = invoices._l10n_ch_dispatch_invoices_to_print()
|
||||
faulty_invoices = dispatched_invoices['classic']
|
||||
|
||||
# Log a message inside the chatter explaining why the invoice is faulty.
|
||||
for inv in faulty_invoices:
|
||||
try:
|
||||
# The error potentially raised in the following function helps create the wizard's message.
|
||||
inv.partner_bank_id._eligible_for_qr_code('ch_qr', inv.partner_id, inv.currency_id, raises_error=True)
|
||||
except UserError as e:
|
||||
inv.message_post(body=e.name, message_type="comment")
|
||||
|
||||
action_vals = {
|
||||
'name': _("Invalid Invoices"),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'account.move',
|
||||
'context': {'create': False},
|
||||
}
|
||||
if len(faulty_invoices) == 1:
|
||||
action_vals.update({
|
||||
'view_mode': 'form',
|
||||
'res_id': faulty_invoices.id,
|
||||
})
|
||||
else:
|
||||
action_vals.update({
|
||||
'view_mode': 'tree',
|
||||
'domain': [('id', 'in', faulty_invoices.ids)],
|
||||
})
|
||||
return action_vals
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class SwissSetupBarBankConfigWizard(models.TransientModel):
|
||||
_inherit = 'account.setup.bank.manual.config'
|
||||
|
||||
@api.onchange('acc_number')
|
||||
def _onchange_recompute_qr_iban(self):
|
||||
# Needed because ORM doesn't properly call the compute in 'new' mode, due to inherits, and
|
||||
# we want this field to be displayed in the wizard. We need to manually set acc_number
|
||||
# on the inherits m2o before calling the compute function manually.
|
||||
self.res_partner_bank_id.acc_number = self.acc_number
|
||||
self.res_partner_bank_id._compute_l10n_ch_qr_iban()
|
||||
self.l10n_ch_qr_iban = self.res_partner_bank_id.l10n_ch_qr_iban
|
||||
45
odoo-bringout-oca-ocb-l10n_ch/pyproject.toml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
[project]
|
||||
name = "odoo-bringout-oca-ocb-l10n_ch"
|
||||
version = "16.0.0"
|
||||
description = "Switzerland - Accounting - Odoo addon"
|
||||
authors = [
|
||||
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
|
||||
]
|
||||
dependencies = [
|
||||
"odoo-bringout-oca-ocb-account>=16.0.0",
|
||||
"odoo-bringout-oca-ocb-l10n_multilang>=16.0.0",
|
||||
"odoo-bringout-oca-ocb-base_iban>=16.0.0",
|
||||
"odoo-bringout-oca-ocb-l10n_din5008>=16.0.0",
|
||||
"requests>=2.25.1"
|
||||
]
|
||||
readme = "README.md"
|
||||
requires-python = ">= 3.11"
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Office/Business",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
homepage = "https://github.com/bringout/0"
|
||||
repository = "https://github.com/bringout/0"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.metadata]
|
||||
allow-direct-references = true
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["l10n_ch"]
|
||||
|
||||
[tool.rye]
|
||||
managed = true
|
||||
dev-dependencies = [
|
||||
"pytest>=8.4.1",
|
||||
]
|
||||