Initial commit for l10n_ca_pst_reports
This commit is contained in:
parent
b605f77e55
commit
b83fb948d4
5 changed files with 235 additions and 0 deletions
0
l10n_ca_pst_reports/__init__.py
Normal file
0
l10n_ca_pst_reports/__init__.py
Normal file
33
l10n_ca_pst_reports/__manifest__.py
Normal file
33
l10n_ca_pst_reports/__manifest__.py
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
'name': 'Canadian PST Numbers on Reports',
|
||||||
|
'author': 'Bemade Inc.',
|
||||||
|
'version': '1.0',
|
||||||
|
'category': 'Accounting/Localizations/Reports',
|
||||||
|
'summary': 'Add PST numbers alongside GST/VAT numbers on reports',
|
||||||
|
'description': '''
|
||||||
|
This module adds Provincial Sales Tax (PST) numbers to reports where GST/VAT numbers
|
||||||
|
are already displayed. Supports:
|
||||||
|
- Invoice reports
|
||||||
|
- Company documents
|
||||||
|
- Customer/Vendor forms
|
||||||
|
''',
|
||||||
|
'depends': [
|
||||||
|
'base',
|
||||||
|
'account',
|
||||||
|
'l10n_ca',
|
||||||
|
'web', # for external layouts
|
||||||
|
],
|
||||||
|
'data': [
|
||||||
|
'views/external_layout.xml',
|
||||||
|
],
|
||||||
|
'external_dependencies': {
|
||||||
|
'python': [],
|
||||||
|
},
|
||||||
|
'test_external_dependencies': {
|
||||||
|
'python': ['pdfminer.six'],
|
||||||
|
},
|
||||||
|
'installable': True,
|
||||||
|
'application': False,
|
||||||
|
'auto_install': False,
|
||||||
|
'license': 'LGPL-3',
|
||||||
|
}
|
||||||
1
l10n_ca_pst_reports/tests/__init__.py
Normal file
1
l10n_ca_pst_reports/tests/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
from . import test_report_tax_numbers
|
||||||
65
l10n_ca_pst_reports/tests/test_report_tax_numbers.py
Normal file
65
l10n_ca_pst_reports/tests/test_report_tax_numbers.py
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
from odoo.tests import TransactionCase, tagged
|
||||||
|
from pdfminer.high_level import extract_text
|
||||||
|
import base64
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
|
||||||
|
@tagged('post_install', '-at_install')
|
||||||
|
class TestReportTaxNumbers(TransactionCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
# Create a Canadian company with GST and PST numbers
|
||||||
|
self.company = self.env['res.company'].create({
|
||||||
|
'name': 'Test Canadian Company',
|
||||||
|
'country_id': self.env.ref('base.ca').id,
|
||||||
|
'vat': '123456789',
|
||||||
|
'l10n_ca_pst': 'PST12345',
|
||||||
|
})
|
||||||
|
self.env['account.chart.template'].try_loading('ca_2023', company=self.company)
|
||||||
|
|
||||||
|
# Create a partner
|
||||||
|
self.partner = self.env['res.partner'].create({
|
||||||
|
'name': 'Test Customer',
|
||||||
|
'country_id': self.env.ref('base.ca').id,
|
||||||
|
})
|
||||||
|
|
||||||
|
# Create an invoice to test with
|
||||||
|
self.invoice = self.env['account.move'].create({
|
||||||
|
'move_type': 'out_invoice',
|
||||||
|
'partner_id': self.partner.id,
|
||||||
|
'company_id': self.company.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
def _get_pdf_content(self, report_name, res_ids):
|
||||||
|
"""Generate PDF report and extract its text content."""
|
||||||
|
pdf_content, _ = self.env['ir.actions.report']._render_qweb_html(report_name, [res_ids])
|
||||||
|
|
||||||
|
return str(pdf_content)
|
||||||
|
|
||||||
|
def test_invoice_tax_numbers(self):
|
||||||
|
"""Test that GST and PST numbers appear on invoice report."""
|
||||||
|
# Generate invoice PDF and extract text
|
||||||
|
text = self._get_pdf_content('account.report_invoice', self.invoice.id)
|
||||||
|
|
||||||
|
# Check for GST and PST numbers
|
||||||
|
self.assertIn('GST: <span>123456789</span>', text, "GST number not found in invoice")
|
||||||
|
self.assertIn('PST: <span>PST12345</span>', text, "PST number not found in invoice")
|
||||||
|
|
||||||
|
def test_different_layouts(self):
|
||||||
|
"""Test tax numbers appear with different report layouts."""
|
||||||
|
layouts = ['standard', 'boxed', 'bold', 'striped', 'bubble', 'wave', 'folder']
|
||||||
|
|
||||||
|
for layout in layouts:
|
||||||
|
# Set company layout
|
||||||
|
layout_id = self.env.ref(f'web.external_layout_{layout}')
|
||||||
|
self.company.write({'external_report_layout_id': layout_id.id})
|
||||||
|
|
||||||
|
# Generate invoice PDF and extract text
|
||||||
|
text = self._get_pdf_content('account.report_invoice', self.invoice.id)
|
||||||
|
|
||||||
|
# Check for GST and PST numbers
|
||||||
|
self.assertIn('GST: <span>123456789</span>', text,
|
||||||
|
f"GST number not found in invoice with {layout} layout")
|
||||||
|
self.assertIn('PST: <span>PST12345</span>', text,
|
||||||
|
f"PST number not found in invoice with {layout} layout")
|
||||||
136
l10n_ca_pst_reports/views/external_layout.xml
Normal file
136
l10n_ca_pst_reports/views/external_layout.xml
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<template id="l10n_ca_pst_external_layout_standard" inherit_id="web.external_layout_standard">
|
||||||
|
<xpath expr="//li[@t-if='not forced_vat']" position="replace">
|
||||||
|
<li t-if="not forced_vat and o.company_id.country_id.code == 'CA'">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div t-if="o.company_id.vat">
|
||||||
|
GST: <span t-field="o.company_id.vat"/>
|
||||||
|
</div>
|
||||||
|
<div t-if="o.company_id.l10n_ca_pst">
|
||||||
|
PST: <span t-field="o.company_id.l10n_ca_pst"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li t-elif="not forced_vat and o.company_id.vat">
|
||||||
|
<t t-if="o.company_id.country_id.vat_label" t-out="o.company_id.country_id.vat_label" id="inv_tax_id_label"/>
|
||||||
|
<t t-else="">Tax ID</t>: <span t-field="o.company_id.vat"/>
|
||||||
|
</li>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Also inherit other layout styles to maintain consistency -->
|
||||||
|
<template id="l10n_ca_pst_external_layout_boxed" inherit_id="web.external_layout_boxed">
|
||||||
|
<xpath expr="//li[@t-if='not forced_vat']" position="replace">
|
||||||
|
<li t-if="not forced_vat and o.company_id.country_id.code == 'CA'">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div t-if="o.company_id.vat">
|
||||||
|
GST: <span t-field="o.company_id.vat"/>
|
||||||
|
</div>
|
||||||
|
<div t-if="o.company_id.l10n_ca_pst">
|
||||||
|
PST: <span t-field="o.company_id.l10n_ca_pst"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li t-elif="not forced_vat and o.company_id.vat">
|
||||||
|
<t t-if="o.company_id.country_id.vat_label" t-out="o.company_id.country_id.vat_label" id="inv_tax_id_label"/>
|
||||||
|
<t t-else="">Tax ID</t>: <span t-field="o.company_id.vat"/>
|
||||||
|
</li>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="l10n_ca_pst_external_layout_bold" inherit_id="web.external_layout_bold">
|
||||||
|
<xpath expr="//li[@t-if='not forced_vat']" position="replace">
|
||||||
|
<li t-if="not forced_vat and o.company_id.country_id.code == 'CA'">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div t-if="o.company_id.vat">
|
||||||
|
GST: <span t-field="o.company_id.vat"/>
|
||||||
|
</div>
|
||||||
|
<div t-if="o.company_id.l10n_ca_pst">
|
||||||
|
PST: <span t-field="o.company_id.l10n_ca_pst"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li t-elif="not forced_vat and o.company_id.vat">
|
||||||
|
<t t-if="o.company_id.country_id.vat_label" t-out="o.company_id.country_id.vat_label" id="inv_tax_id_label"/>
|
||||||
|
<t t-else="">Tax ID</t>: <span t-field="o.company_id.vat"/>
|
||||||
|
</li>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="l10n_ca_pst_external_layout_striped" inherit_id="web.external_layout_striped">
|
||||||
|
<xpath expr="//li[@t-if='not forced_vat']" position="replace">
|
||||||
|
<li t-if="not forced_vat and o.company_id.country_id.code == 'CA'">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div t-if="o.company_id.vat">
|
||||||
|
GST: <span t-field="o.company_id.vat"/>
|
||||||
|
</div>
|
||||||
|
<div t-if="o.company_id.l10n_ca_pst">
|
||||||
|
PST: <span t-field="o.company_id.l10n_ca_pst"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li t-elif="not forced_vat and o.company_id.vat">
|
||||||
|
<t t-if="o.company_id.country_id.vat_label" t-out="o.company_id.country_id.vat_label" id="inv_tax_id_label"/>
|
||||||
|
<t t-else="">Tax ID</t>: <span t-field="o.company_id.vat"/>
|
||||||
|
</li>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="l10n_ca_pst_external_layout_bubble" inherit_id="web.external_layout_bubble">
|
||||||
|
<xpath expr="//li[@t-if='not forced_vat']" position="replace">
|
||||||
|
<li t-if="not forced_vat and o.company_id.country_id.code == 'CA'">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div t-if="o.company_id.vat">
|
||||||
|
GST: <span t-field="o.company_id.vat"/>
|
||||||
|
</div>
|
||||||
|
<div t-if="o.company_id.l10n_ca_pst">
|
||||||
|
PST: <span t-field="o.company_id.l10n_ca_pst"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li t-elif="not forced_vat and o.company_id.vat">
|
||||||
|
<t t-if="o.company_id.country_id.vat_label" t-out="o.company_id.country_id.vat_label" id="inv_tax_id_label"/>
|
||||||
|
<t t-else="">Tax ID</t>: <span t-field="o.company_id.vat"/>
|
||||||
|
</li>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="l10n_ca_pst_external_layout_wave" inherit_id="web.external_layout_wave">
|
||||||
|
<xpath expr="//li[@t-if='not forced_vat']" position="replace">
|
||||||
|
<li t-if="not forced_vat and o.company_id.country_id.code == 'CA'">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div t-if="o.company_id.vat">
|
||||||
|
GST: <span t-field="o.company_id.vat"/>
|
||||||
|
</div>
|
||||||
|
<div t-if="o.company_id.l10n_ca_pst">
|
||||||
|
PST: <span t-field="o.company_id.l10n_ca_pst"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li t-elif="not forced_vat and o.company_id.vat">
|
||||||
|
<t t-if="o.company_id.country_id.vat_label" t-out="o.company_id.country_id.vat_label" id="inv_tax_id_label"/>
|
||||||
|
<t t-else="">Tax ID</t>: <span t-field="o.company_id.vat"/>
|
||||||
|
</li>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="l10n_ca_pst_external_layout_folder" inherit_id="web.external_layout_folder">
|
||||||
|
<xpath expr="//li[@t-if='not forced_vat']" position="replace">
|
||||||
|
<li t-if="not forced_vat and o.company_id.country_id.code == 'CA'">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div t-if="o.company_id.vat">
|
||||||
|
GST: <span t-field="o.company_id.vat"/>
|
||||||
|
</div>
|
||||||
|
<div t-if="o.company_id.l10n_ca_pst">
|
||||||
|
PST: <span t-field="o.company_id.l10n_ca_pst"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li t-elif="not forced_vat and o.company_id.vat">
|
||||||
|
<t t-if="o.company_id.country_id.vat_label" t-out="o.company_id.country_id.vat_label" id="inv_tax_id_label"/>
|
||||||
|
<t t-else="">Tax ID</t>: <span t-field="o.company_id.vat"/>
|
||||||
|
</li>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
</odoo>
|
||||||
Loading…
Reference in a new issue