Files
Odoo-Modules/fusion_payroll/reports/payroll_cheque_report.xml
2026-02-22 01:22:18 -05:00

363 lines
24 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Paper Format for Cheque (Letter size - matches pre-printed cheque stock) -->
<record id="paperformat_cheque" model="report.paperformat">
<field name="name">Payroll Cheque</field>
<field name="default" eval="False"/>
<field name="format">Letter</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>
<field name="dpi">96</field>
</record>
<record id="action_report_payroll_cheque" model="ir.actions.report">
<field name="name">Payroll Cheque</field>
<field name="model">payroll.cheque</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">fusion_payroll.report_payroll_cheque</field>
<field name="report_file">fusion_payroll.report_payroll_cheque</field>
<field name="print_report_name">'Cheque-%s-%s' % (object.cheque_number or 'Draft', object.employee_id.name)</field>
<field name="binding_model_id" ref="model_payroll_cheque"/>
<field name="binding_type">report</field>
<field name="paperformat_id" ref="paperformat_cheque"/>
</record>
<!-- Main Cheque Report Template -->
<template id="report_payroll_cheque">
<t t-call="web.html_container">
<style>
/* Force full page width - override ALL Bootstrap container constraints */
body.container, body.container-fluid, .container, .container-fluid,
#wrapwrap, main {
max-width: 100% !important;
width: 100% !important;
padding-left: 0 !important;
padding-right: 0 !important;
margin: 0 !important;
}
</style>
<t t-foreach="docs" t-as="cheque">
<t t-set="layout" t-value="env['cheque.layout.settings'].sudo().get_default_settings()"/>
<t t-set="stub_data" t-value="cheque.get_pay_stub_data()"/>
<t t-call="fusion_payroll.report_payroll_cheque_page"/>
</t>
</t>
</template>
<!-- Cheque Page Layout -->
<template id="report_payroll_cheque_page">
<!-- Main page container - 8.5in wide, centered -->
<div style="font-family: Arial, sans-serif; width: 8.5in; height: 11in; position: relative; margin: 0 auto; padding: 0; box-sizing: border-box;">
<!-- ======================= SECTION 1: CHEQUE (Top 3.67 inches) ======================= -->
<div t-attf-style="position: absolute; top: 0; left: 0; width: 100%; height: #{layout.section1_height}in; box-sizing: border-box;">
<!-- Date - Single Line with Label -->
<div t-attf-style="position: absolute; right: 0.8in; top: #{layout.date_y}in; white-space: nowrap;">
<span t-attf-style="font-size: #{layout.date_font_size}pt; font-weight: bold; font-family: 'Courier New', monospace;">
DATE: <t t-esc="cheque.cheque_date.strftime('%b %d, %Y').upper() if cheque.cheque_date else ''"/>
</span>
</div>
<!-- Amount (numeric) -->
<div t-attf-style="position: absolute; right: 0.6in; top: #{layout.amount_y}in; white-space: nowrap;">
<span t-attf-style="font-size: #{layout.amount_font_size}pt; font-weight: bold; font-family: 'Courier New', monospace;">
**<t t-esc="'{:,.2f}'.format(cheque.amount)"/>
</span>
</div>
<!-- Amount in Words -->
<div t-attf-style="position: absolute; left: #{layout.amount_words_x}in; top: #{layout.amount_words_y}in; right: 2in; white-space: nowrap; overflow: hidden;">
<span t-attf-style="font-size: #{layout.amount_words_font_size}pt; font-family: 'Courier New', monospace;">
*****<t t-esc="cheque.amount_in_words"/>*****
</span>
</div>
<!-- Payee Name -->
<div t-attf-style="position: absolute; left: #{layout.payee_x}in; top: #{layout.payee_y}in; white-space: nowrap;">
<span t-attf-style="font-size: #{layout.payee_font_size}pt; font-weight: bold;">
<t t-esc="cheque.payee_name"/>
</span>
</div>
<!-- Payee Address -->
<div t-attf-style="position: absolute; left: #{layout.payee_address_x}in; top: #{layout.payee_address_y}in; width: 4in;">
<span t-attf-style="font-size: #{layout.payee_address_font_size}pt; color: #333;">
<t t-esc="(cheque.payee_address or '').replace(chr(10), ', ')"/>
</span>
</div>
<!-- Pay Period -->
<div t-attf-style="position: absolute; left: #{layout.cheque_pay_period_x}in; top: #{layout.cheque_pay_period_y}in; white-space: nowrap;">
<span style="font-size: 9pt;">
<b>Pay Period:</b> <t t-esc="cheque.pay_period_display"/>
</span>
</div>
<!-- Memo (if any) -->
<div t-if="cheque.memo" t-attf-style="position: absolute; left: #{layout.memo_x}in; top: #{layout.memo_y}in;">
<span t-attf-style="font-size: #{layout.memo_font_size}pt; color: #666;">
<t t-esc="cheque.memo"/>
</span>
</div>
</div>
<!-- ======================= SECTION 2: PAY STUB 1 (Middle) ======================= -->
<!-- Full width stub - uses layout settings for padding to control margins -->
<div t-attf-style="position: absolute; top: #{layout.section2_start}in; left: 0; width: 8.5in; height: #{layout.section2_height}in; overflow: hidden; padding-left: #{layout.stub_padding_left}in; padding-right: #{layout.stub_padding_right}in; padding-top: #{layout.stub_padding_top}in; box-sizing: border-box;">
<t t-call="fusion_payroll.report_cheque_stub_redesigned"/>
</div>
<!-- ======================= SECTION 3: PAY STUB 2 (Bottom) ======================= -->
<!-- Full width stub - uses layout settings for padding to control margins -->
<div t-attf-style="position: absolute; top: #{layout.section3_start}in; left: 0; width: 8.5in; height: #{layout.section3_height}in; overflow: hidden; padding-left: #{layout.stub_padding_left}in; padding-right: #{layout.stub_padding_right}in; padding-top: #{layout.stub_padding_top}in; box-sizing: border-box;">
<t t-call="fusion_payroll.report_cheque_stub_redesigned"/>
</div>
</div>
</template>
<!-- ======================= REDESIGNED PAY STUB CONTENT ======================= -->
<template id="report_cheque_stub_redesigned">
<!-- Main stub table - full width, reduced padding for maximum width usage -->
<table style="width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; table-layout: fixed;">
<tr>
<!-- LEFT COLUMN: Employee &amp; Company Info -->
<td style="width: 22%; vertical-align: top; padding: 0 8px 0 5px; border-right: 1px solid #ccc;">
<!-- Employee Name -->
<div style="font-weight: bold; font-size: 11pt; margin-bottom: 2px;">
<t t-esc="cheque.payee_name"/>
</div>
<div style="font-size: 8pt; color: #444; line-height: 1.2; margin-bottom: 6px;">
<t t-esc="cheque.payee_address or ''"/>
</div>
<!-- Company Info -->
<div style="font-weight: bold; font-size: 9pt; margin-top: 4px;">
<t t-esc="cheque.company_id.name"/>
</div>
<div style="font-size: 7pt; color: #555; line-height: 1.2;">
<t t-if="cheque.company_id.street"><t t-esc="cheque.company_id.street"/><br/></t>
<t t-esc="cheque.company_id.city or ''"/><t t-if="cheque.company_id.state_id">, <t t-esc="cheque.company_id.state_id.code"/></t>
<t t-if="cheque.company_id.zip"> <t t-esc="cheque.company_id.zip"/></t>
</div>
<!-- Pay Period -->
<div style="margin-top: 6px;">
<div style="font-size: 7pt; color: #888; font-weight: bold;">PAY PERIOD</div>
<div style="font-size: 8pt;"><t t-esc="cheque.pay_period_display"/></div>
</div>
<!-- Pay Date -->
<div style="margin-top: 3px;">
<div style="font-size: 7pt; color: #888; font-weight: bold;">PAY DATE</div>
<div style="font-size: 8pt;"><t t-esc="cheque.cheque_date.strftime('%m/%d/%Y') if cheque.cheque_date else ''"/></div>
</div>
<!-- Cheque Number -->
<div t-if="cheque.cheque_number" style="margin-top: 3px;">
<div style="font-size: 7pt; color: #888; font-weight: bold;">CHEQUE #</div>
<div style="font-size: 8pt; font-weight: bold;"><t t-esc="cheque.cheque_number"/></div>
</div>
</td>
<!-- MIDDLE COLUMN: PAY Details -->
<td style="width: 26%; vertical-align: top; padding: 0 12px; border-right: 1px solid #ccc;">
<!-- PAY Section -->
<div style="font-weight: bold; font-size: 9pt; border-bottom: 1.5px solid #333; padding-bottom: 3px; margin-bottom: 5px;">
PAY
</div>
<table style="width: 100%; font-size: 8pt; border-collapse: separate; border-spacing: 0 3px;">
<tr style="color: #666; font-size: 7pt;">
<td></td>
<td style="text-align: right; padding: 2px 4px;">Hrs</td>
<td style="text-align: right; padding: 2px 4px;">Rate</td>
<td style="text-align: right; padding: 2px 4px;">Current</td>
<td style="text-align: right; padding: 2px 4px;">YTD</td>
</tr>
<tr>
<td style="padding: 2px 0;">Regular</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:.2f}'.format(stub_data.get('pay',{}).get('regular_pay',{}).get('hours',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:.2f}'.format(stub_data.get('pay',{}).get('regular_pay',{}).get('rate',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('pay',{}).get('regular_pay',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('pay',{}).get('regular_pay',{}).get('ytd',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 0;">Vacation</td>
<td style="text-align: right; padding: 2px 4px;">-</td>
<td style="text-align: right; padding: 2px 4px;">-</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('pay',{}).get('vacation_pay',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('pay',{}).get('vacation_pay',{}).get('ytd',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 0;">Stat Holiday</td>
<td style="text-align: right; padding: 2px 4px;">-</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:.2f}'.format(stub_data.get('pay',{}).get('stat_holiday_pay',{}).get('rate',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('pay',{}).get('stat_holiday_pay',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('pay',{}).get('stat_holiday_pay',{}).get('ytd',0))"/></td>
</tr>
</table>
<!-- Gross Pay Total -->
<div style="text-align: right; font-size: 8pt; font-weight: bold; margin-top: 5px; padding-top: 4px; border-top: 1px solid #ccc;">
Gross: $<t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('total_pay',{}).get('current',0))"/>
</div>
<!-- OTHER PAY Section -->
<div style="font-weight: bold; font-size: 8pt; border-bottom: 1px solid #999; margin-top: 8px; padding-bottom: 2px; margin-bottom: 4px;">
OTHER PAY
</div>
<table style="width: 100%; font-size: 7pt; color: #666;">
<tr><td colspan="3" style="padding: 2px; text-align: center;">-</td></tr>
</table>
<!-- BENEFITS Section -->
<div style="font-weight: bold; font-size: 8pt; border-bottom: 1px solid #999; margin-top: 8px; padding-bottom: 2px; margin-bottom: 4px;">
BENEFITS
</div>
<table style="width: 100%; font-size: 7pt; border-collapse: separate; border-spacing: 0 2px;">
<tr style="color: #666; font-size: 6pt;">
<td></td>
<td style="text-align: right; padding: 2px 4px;">Accrued</td>
<td style="text-align: right; padding: 2px 4px;">Used</td>
<td style="text-align: right; padding: 2px 4px;">Avail</td>
</tr>
<tr>
<td style="padding: 2px 0;">Vacation</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:.2f}'.format(stub_data.get('benefits',{}).get('vacation',{}).get('accrued',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:.2f}'.format(stub_data.get('benefits',{}).get('vacation',{}).get('used',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:.2f}'.format(stub_data.get('benefits',{}).get('vacation',{}).get('available',0))"/></td>
</tr>
</table>
</td>
<!-- THIRD COLUMN: TAXES &amp; DEDUCTIONS -->
<td style="width: 26%; vertical-align: top; padding: 0 12px; border-right: 1px solid #ccc;">
<!-- TAXES Section -->
<div style="font-weight: bold; font-size: 9pt; border-bottom: 1.5px solid #333; padding-bottom: 3px; margin-bottom: 5px;">
TAXES
</div>
<table style="width: 100%; font-size: 8pt; border-collapse: separate; border-spacing: 0 3px;">
<tr style="color: #666; font-size: 7pt;">
<td></td>
<td style="text-align: right; padding: 2px 4px;">Current</td>
<td style="text-align: right; padding: 2px 4px;">YTD</td>
</tr>
<tr>
<td style="padding: 2px 0;">Income Tax</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('income_tax',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('income_tax',{}).get('ytd',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 0;">EI</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('ei',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('ei',{}).get('ytd',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 0;">CPP</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('cpp',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('cpp',{}).get('ytd',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 0;">CPP2</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('cpp2',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('taxes',{}).get('cpp2',{}).get('ytd',0))"/></td>
</tr>
</table>
<!-- Total Taxes -->
<div style="text-align: right; font-size: 8pt; font-weight: bold; margin-top: 5px; padding-top: 4px; border-top: 1px solid #ccc;">
Total: $<t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('taxes',{}).get('current',0))"/>
</div>
<!-- DEDUCTIONS Section -->
<div style="font-weight: bold; font-size: 8pt; border-bottom: 1px solid #999; margin-top: 8px; padding-bottom: 2px; margin-bottom: 4px;">
DEDUCTIONS
</div>
<table style="width: 100%; font-size: 7pt; color: #666;">
<tr><td colspan="3" style="padding: 2px; text-align: center;">-</td></tr>
</table>
<!-- EMPLOYER CONTRIBUTIONS Section -->
<div style="font-weight: bold; font-size: 8pt; border-bottom: 1px solid #999; margin-top: 8px; padding-bottom: 2px; margin-bottom: 4px; color: #0066cc;">
EMPLOYER CONTRIBUTIONS
</div>
<table style="width: 100%; font-size: 7pt; border-collapse: separate; border-spacing: 0 2px;">
<tr>
<td style="padding: 2px 0;">EI (1.4x)</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('employer',{}).get('ei',{}).get('current',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 0;">CPP</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('employer',{}).get('cpp',{}).get('current',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 0;">CPP2</td>
<td style="text-align: right; padding: 2px 4px;"><t t-esc="'{:,.2f}'.format(stub_data.get('employer',{}).get('cpp2',{}).get('current',0))"/></td>
</tr>
</table>
</td>
<!-- RIGHT COLUMN: SUMMARY -->
<td style="width: 26%; vertical-align: top; padding: 0 5px 0 8px;">
<!-- Summary Box -->
<table style="width: 100%; border: 2px solid #333; border-collapse: collapse; font-size: 8pt;">
<tr style="background: #f0f0f0; border-bottom: 1px solid #333;">
<td style="padding: 3px 5px; font-weight: bold; font-size: 9pt;">SUMMARY</td>
<td style="text-align: right; padding: 3px; font-size: 7pt; color: #666;">Current</td>
<td style="text-align: right; padding: 3px; font-size: 7pt; color: #666;">YTD</td>
</tr>
<tr>
<td style="padding: 2px 5px;">Total Pay</td>
<td style="text-align: right; padding: 2px;"><t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('total_pay',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px;"><t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('total_pay',{}).get('ytd',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 5px;">Taxes</td>
<td style="text-align: right; padding: 2px; color: #c00;">-<t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('taxes',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px;"><t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('taxes',{}).get('ytd',0))"/></td>
</tr>
<tr>
<td style="padding: 2px 5px;">Deductions</td>
<td style="text-align: right; padding: 2px;"><t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('deductions',{}).get('current',0))"/></td>
<td style="text-align: right; padding: 2px;"><t t-esc="'{:,.2f}'.format(stub_data.get('summary',{}).get('deductions',{}).get('ytd',0))"/></td>
</tr>
<tr style="border-top: 2px solid #333; background: #333; color: white;">
<td style="padding: 4px 5px; font-weight: bold; font-size: 10pt;">NET PAY</td>
<td colspan="2" style="text-align: right; padding: 4px 5px; font-weight: bold; font-size: 14pt;">
$<t t-esc="'{:,.2f}'.format(cheque.amount)"/>
</td>
</tr>
</table>
<!-- Additional Info -->
<div style="margin-top: 8px; font-size: 7pt; color: #666;">
<div style="margin-bottom: 3px;">
<span style="font-weight: bold;">Total Employer Cost:</span>
<span style="float: right;">$<t t-esc="'{:,.2f}'.format(
stub_data.get('employer',{}).get('ei',{}).get('current',0) +
stub_data.get('employer',{}).get('cpp',{}).get('current',0) +
stub_data.get('employer',{}).get('cpp2',{}).get('current',0)
)"/></span>
</div>
</div>
<!-- Memo if available -->
<div t-if="cheque.memo" style="margin-top: 6px; padding: 4px; background: #fffde7; border: 1px solid #fff59d; font-size: 7pt;">
<span style="font-weight: bold;">MEMO:</span>
<t t-esc="cheque.memo"/>
</div>
</td>
</tr>
</table>
</template>
</odoo>