changes
This commit is contained in:
@@ -4,6 +4,7 @@ import base64
|
||||
import os
|
||||
import io
|
||||
from datetime import date
|
||||
from lxml import etree
|
||||
from odoo import models, fields, api
|
||||
from odoo.exceptions import UserError
|
||||
from odoo import tools
|
||||
@@ -128,6 +129,15 @@ class HrT4ASummary(models.Model):
|
||||
string='Telephone',
|
||||
)
|
||||
|
||||
# === Transmitter Information ===
|
||||
transmitter_bn = fields.Char(string='Business Number (BN)')
|
||||
transmitter_name = fields.Char(string='Transmitter Name')
|
||||
contact_email = fields.Char(string='Contact Email')
|
||||
|
||||
# === XML Export ===
|
||||
xml_file = fields.Binary(string='XML File', attachment=True)
|
||||
xml_filename = fields.Char(string='XML Filename')
|
||||
|
||||
# === Filing Information ===
|
||||
filing_date = fields.Date(
|
||||
string='Filing Date',
|
||||
@@ -158,6 +168,123 @@ class HrT4ASummary(models.Model):
|
||||
'filing_date': date.today(),
|
||||
})
|
||||
|
||||
def action_export_xml(self):
|
||||
"""Generate CRA T4A XML file (T619 format) for electronic filing"""
|
||||
self.ensure_one()
|
||||
nsmap = {
|
||||
None: 'http://www.cra-arc.gc.ca/enov/ol/interfaces/efile/partnership/t4a'
|
||||
}
|
||||
root = etree.Element('Submission', nsmap=nsmap)
|
||||
|
||||
t619 = etree.SubElement(root, 'T619')
|
||||
self._add_xml_element(t619, 'sbmt_ref_id', 'T4A-%s-%s' % (self.tax_year, self.id))
|
||||
self._add_xml_element(t619, 'rpt_tcd', 'O')
|
||||
bn = self.transmitter_bn or self.cra_business_number or ''
|
||||
self._add_xml_element(t619, 'trnmtr_nbr', 'MM' + bn[:7].ljust(7, '0') if bn else 'MM0000000')
|
||||
self._add_xml_element(t619, 'trnmtr_tcd', '4')
|
||||
self._add_xml_element(t619, 'summ_cnt', '1')
|
||||
self._add_xml_element(t619, 'lang_cd', 'E')
|
||||
|
||||
trnmtr_nm = etree.SubElement(t619, 'TRNMTR_NM')
|
||||
self._add_xml_element(trnmtr_nm, 'l1_nm', self.transmitter_name or self.company_id.name or '')
|
||||
|
||||
company = self.company_id
|
||||
trnmtr_addr = etree.SubElement(t619, 'TRNMTR_ADDR')
|
||||
if company.street:
|
||||
self._add_xml_element(trnmtr_addr, 'addr_l1_txt', company.street)
|
||||
if company.city:
|
||||
self._add_xml_element(trnmtr_addr, 'cty_nm', company.city)
|
||||
if company.state_id:
|
||||
self._add_xml_element(trnmtr_addr, 'prov_cd', company.state_id.code)
|
||||
if company.zip:
|
||||
self._add_xml_element(trnmtr_addr, 'pstl_cd', company.zip)
|
||||
self._add_xml_element(trnmtr_addr, 'cntry_cd', 'CAN')
|
||||
|
||||
if self.contact_name or self.contact_phone or self.contact_email:
|
||||
cntc = etree.SubElement(t619, 'CNTC')
|
||||
self._add_xml_element(cntc, 'cntc_nm', self.contact_name)
|
||||
if self.contact_phone:
|
||||
phone = ''.join(filter(str.isdigit, self.contact_phone))
|
||||
if len(phone) >= 10:
|
||||
self._add_xml_element(cntc, 'cntc_area_cd', phone[:3])
|
||||
self._add_xml_element(cntc, 'cntc_phn_nbr', phone[3:10])
|
||||
self._add_xml_element(cntc, 'cntc_email_area', self.contact_email)
|
||||
|
||||
t4a_return = etree.SubElement(root, 'T4AReturn')
|
||||
|
||||
t4a_summary = etree.SubElement(t4a_return, 'T4ASummary')
|
||||
bn15 = (self.transmitter_bn or self.cra_business_number or '')[:15]
|
||||
self._add_xml_element(t4a_summary, 'bn', bn15)
|
||||
self._add_xml_element(t4a_summary, 'tx_yr', str(self.tax_year))
|
||||
self._add_xml_element(t4a_summary, 'slp_cnt', str(self.slip_count))
|
||||
|
||||
payr_nm = etree.SubElement(t4a_summary, 'PAYR_NM')
|
||||
self._add_xml_element(payr_nm, 'l1_nm', company.name or '')
|
||||
|
||||
payr_addr = etree.SubElement(t4a_summary, 'PAYR_ADDR')
|
||||
if company.street:
|
||||
self._add_xml_element(payr_addr, 'addr_l1_txt', company.street)
|
||||
if company.city:
|
||||
self._add_xml_element(payr_addr, 'cty_nm', company.city)
|
||||
if company.state_id:
|
||||
self._add_xml_element(payr_addr, 'prov_cd', company.state_id.code)
|
||||
if company.zip:
|
||||
self._add_xml_element(payr_addr, 'pstl_cd', company.zip)
|
||||
self._add_xml_element(payr_addr, 'cntry_cd', 'CAN')
|
||||
|
||||
t4a_tamt = etree.SubElement(t4a_summary, 'T4A_TAMT')
|
||||
self._add_xml_amount(t4a_tamt, 'tot_pens_spran_amt', self.total_box_016)
|
||||
self._add_xml_amount(t4a_tamt, 'tot_lsp_amt', self.total_box_018)
|
||||
self._add_xml_amount(t4a_tamt, 'tot_self_empl_cmsn_amt', self.total_box_020)
|
||||
self._add_xml_amount(t4a_tamt, 'tot_annty_amt', self.total_box_024)
|
||||
|
||||
for t4a in self.slip_ids:
|
||||
slip_elem = etree.SubElement(t4a_return, 'T4ASlip')
|
||||
self._add_xml_element(slip_elem, 'rcpnt_nm', t4a.recipient_name or '')
|
||||
self._add_xml_element(slip_elem, 'sin', (t4a.recipient_sin or '').replace('-', '').replace(' ', ''))
|
||||
if t4a.recipient_account_number:
|
||||
self._add_xml_element(slip_elem, 'rcpnt_bn', t4a.recipient_account_number)
|
||||
|
||||
t4a_amt = etree.SubElement(slip_elem, 'T4A_AMT')
|
||||
self._add_xml_amount(t4a_amt, 'pens_spran_amt', t4a.box_016_pension)
|
||||
self._add_xml_amount(t4a_amt, 'lsp_amt', t4a.box_018_lump_sum)
|
||||
self._add_xml_amount(t4a_amt, 'self_empl_cmsn_amt', t4a.box_020_commissions)
|
||||
self._add_xml_amount(t4a_amt, 'annty_amt', t4a.box_024_annuities)
|
||||
self._add_xml_amount(t4a_amt, 'fees_svc_amt', t4a.box_048_fees)
|
||||
|
||||
xml_bytes = etree.tostring(root, xml_declaration=True, encoding='UTF-8', pretty_print=True)
|
||||
filename = 'T4A_%s_%s.xml' % (self.tax_year, (company.name or 'Company').replace(' ', '_'))
|
||||
|
||||
self.write({
|
||||
'xml_file': base64.b64encode(xml_bytes),
|
||||
'xml_filename': filename,
|
||||
})
|
||||
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'name': filename,
|
||||
'type': 'binary',
|
||||
'datas': base64.b64encode(xml_bytes),
|
||||
'res_model': self._name,
|
||||
'res_id': self.id,
|
||||
'mimetype': 'application/xml',
|
||||
})
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': '/web/content/%s?download=true' % attachment.id,
|
||||
'target': 'self',
|
||||
}
|
||||
|
||||
def _add_xml_element(self, parent, tag, value):
|
||||
if value:
|
||||
elem = etree.SubElement(parent, tag)
|
||||
elem.text = str(value)
|
||||
|
||||
def _add_xml_amount(self, parent, tag, amount):
|
||||
if amount:
|
||||
elem = etree.SubElement(parent, tag)
|
||||
elem.text = '%.2f' % amount
|
||||
|
||||
|
||||
class HrT4ASlip(models.Model):
|
||||
"""T4A Slip - One per recipient per tax year"""
|
||||
@@ -486,16 +613,17 @@ class HrT4ASlip(models.Model):
|
||||
})
|
||||
|
||||
# Post to chatter
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'name': filename,
|
||||
'type': 'binary',
|
||||
'datas': pdf_data,
|
||||
'res_model': self._name,
|
||||
'res_id': self.id,
|
||||
'mimetype': 'application/pdf',
|
||||
})
|
||||
self.message_post(
|
||||
body=f'T4A PDF generated: <strong>{filename}</strong>',
|
||||
attachment_ids=[(0, 0, {
|
||||
'name': filename,
|
||||
'type': 'binary',
|
||||
'datas': pdf_data,
|
||||
'res_model': self._name,
|
||||
'res_id': self.id,
|
||||
'mimetype': 'application/pdf',
|
||||
})],
|
||||
attachment_ids=[attachment.id],
|
||||
)
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user