Initial commit

This commit is contained in:
gsinghpal
2026-02-22 01:22:18 -05:00
commit 5200d5baf0
2394 changed files with 386834 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Cheque Layout Settings Form View -->
<record id="view_cheque_layout_settings_form" model="ir.ui.view">
<field name="name">cheque.layout.settings.form</field>
<field name="model">cheque.layout.settings</field>
<field name="arch" type="xml">
<form string="Cheque Layout Settings">
<header>
<button name="action_open_preview" type="object" string="Visual Preview" class="btn-primary" icon="fa-eye"/>
<button name="action_set_as_default" type="object" string="Set as Default" invisible="is_default"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_open_preview" type="object" class="oe_stat_button" icon="fa-image">
<span>Preview</span>
</button>
</div>
<widget name="web_ribbon" title="Default" bg_color="text-bg-success" invisible="not is_default"/>
<div class="oe_title">
<h1>
<field name="name" placeholder="Layout Name"/>
</h1>
</div>
<group>
<group>
<field name="company_id" groups="base.group_multi_company"/>
<field name="is_default" readonly="1"/>
<field name="active"/>
</group>
<group>
<field name="cheque_image" widget="image" options="{'size': [200, 260]}"/>
<field name="cheque_image_filename" invisible="1"/>
</group>
</group>
<notebook>
<!-- Page Settings -->
<page string="Page &amp; Sections" name="page_settings">
<group>
<group string="Page Size">
<field name="page_width"/>
<field name="page_height"/>
</group>
</group>
<group>
<group string="Section 1: Cheque (Top)">
<field name="section1_height"/>
</group>
<group string="Section 2: Stub 1 (Middle)">
<field name="section2_start"/>
<field name="section2_height"/>
</group>
</group>
<group>
<group string="Section 3: Stub 2 (Bottom)">
<field name="section3_start"/>
<field name="section3_height"/>
</group>
</group>
</page>
<!-- Cheque Section Positions -->
<page string="Cheque Positions" name="cheque_positions">
<group>
<group string="Date Position">
<field name="date_x" string="X Position (inches)"/>
<field name="date_y" string="Y Position (inches)"/>
<field name="date_font_size"/>
</group>
<group string="Amount Position">
<field name="amount_x" string="X Position (inches)"/>
<field name="amount_y" string="Y Position (inches)"/>
<field name="amount_font_size"/>
</group>
</group>
<group>
<group string="Amount in Words Position">
<field name="amount_words_x" string="X Position (inches)"/>
<field name="amount_words_y" string="Y Position (inches)"/>
<field name="amount_words_font_size"/>
</group>
<group string="Payee Name Position">
<field name="payee_x" string="X Position (inches)"/>
<field name="payee_y" string="Y Position (inches)"/>
<field name="payee_font_size"/>
</group>
</group>
<group>
<group string="Payee Address Position">
<field name="payee_address_x" string="X Position (inches)"/>
<field name="payee_address_y" string="Y Position (inches)"/>
<field name="payee_address_font_size"/>
</group>
<group string="Pay Period Position">
<field name="cheque_pay_period_x" string="X Position (inches)"/>
<field name="cheque_pay_period_y" string="Y Position (inches)"/>
</group>
<group string="Memo Position">
<field name="memo_x" string="X Position (inches)"/>
<field name="memo_y" string="Y Position (inches)"/>
<field name="memo_font_size"/>
</group>
</group>
</page>
<!-- Stub Section Settings -->
<page string="Stub Settings" name="stub_settings">
<group>
<group string="Layout Options">
<field name="stub_full_width"/>
<field name="stub_center_data"/>
<field name="stub_content_margin" invisible="not stub_center_data"/>
</group>
<group string="Stub Padding (inches)">
<field name="stub_padding_top"/>
<field name="stub_padding_left"/>
<field name="stub_padding_right"/>
<field name="stub_padding_bottom"/>
</group>
</group>
<group>
<group string="Column Widths (%)">
<field name="col1_width" string="Employee Info"/>
<field name="col2_width" string="PAY/Benefits"/>
<field name="col3_width" string="Taxes/Deductions"/>
<field name="col4_width" string="Summary"/>
</group>
<group string="Font Sizes (pt)">
<field name="stub_title_font_size"/>
<field name="stub_content_font_size"/>
<field name="stub_header_font_size"/>
</group>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Cheque Layout Settings List View -->
<record id="view_cheque_layout_settings_tree" model="ir.ui.view">
<field name="name">cheque.layout.settings.list</field>
<field name="model">cheque.layout.settings</field>
<field name="arch" type="xml">
<list string="Cheque Layout Settings">
<field name="name"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="is_default"/>
<field name="active"/>
</list>
</field>
</record>
<!-- Cheque Layout Settings Action -->
<record id="action_cheque_layout_settings" model="ir.actions.act_window">
<field name="name">Cheque Layout Settings</field>
<field name="res_model">cheque.layout.settings</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Configure cheque print layout
</p>
<p>
Set up the exact X/Y positions for all fields on your pre-printed cheque stock.
Upload an image of your cheque for visual alignment preview.
</p>
</field>
</record>
<!-- Preview Wizard Form View -->
<record id="view_cheque_layout_preview_wizard_form" model="ir.ui.view">
<field name="name">cheque.layout.preview.wizard.form</field>
<field name="model">cheque.layout.preview.wizard</field>
<field name="arch" type="xml">
<form string="Cheque Layout Preview">
<sheet>
<group>
<group string="Upload Cheque Image">
<field name="cheque_image" widget="image" options="{'size': [300, 400]}"/>
</group>
</group>
<notebook>
<page string="Section Dividers" name="sections">
<group>
<group>
<field name="section1_height" string="Cheque End (in)"/>
<field name="section2_start" string="Stub 1 Start (in)"/>
<field name="section3_start" string="Stub 2 Start (in)"/>
</group>
</group>
</page>
<page string="Cheque Fields" name="cheque_fields">
<group>
<group string="Date">
<field name="date_x" string="X (in)"/>
<field name="date_y" string="Y (in)"/>
</group>
<group string="Amount">
<field name="amount_x" string="X (in)"/>
<field name="amount_y" string="Y (in)"/>
</group>
</group>
<group>
<group string="Amount in Words">
<field name="amount_words_x" string="X (in)"/>
<field name="amount_words_y" string="Y (in)"/>
</group>
<group string="Payee Name">
<field name="payee_x" string="X (in)"/>
<field name="payee_y" string="Y (in)"/>
</group>
</group>
<group>
<group string="Payee Address">
<field name="payee_address_x" string="X (in)"/>
<field name="payee_address_y" string="Y (in)"/>
</group>
<group string="Pay Period">
<field name="cheque_pay_period_x" string="X (in)"/>
<field name="cheque_pay_period_y" string="Y (in)"/>
</group>
<group string="Memo">
<field name="memo_x" string="X (in)"/>
<field name="memo_y" string="Y (in)"/>
</group>
</group>
</page>
<page string="Stub Padding" name="stub_padding">
<group>
<group>
<field name="stub_padding_top" string="Top Padding (in)"/>
<field name="stub_padding_left" string="Left Padding (in)"/>
</group>
</group>
</page>
</notebook>
<separator string="Live Preview"/>
<group>
<field name="preview_html" nolabel="1" colspan="2"/>
</group>
</sheet>
<footer>
<button name="action_save_and_close" type="object" string="Save &amp; Close" class="btn-primary"/>
<button name="action_print_test" type="object" string="Print Test" class="btn-secondary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- Menu Item -->
<!-- Menu will be added in fusion_payroll_menus.xml after parent is defined -->
</odoo>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="cheque_number_wizard_form" model="ir.ui.view">
<field name="name">payroll.cheque.number.wizard.form</field>
<field name="model">payroll.cheque.number.wizard</field>
<field name="arch" type="xml">
<form string="Set Cheque Number">
<group>
<group>
<field name="employee_name" readonly="1"/>
<field name="amount" widget="monetary" readonly="1"/>
<field name="currency_id" invisible="1"/>
</group>
</group>
<group>
<field name="cheque_number" placeholder="Enter cheque number (e.g., 000123)" required="1"/>
</group>
<footer>
<button name="action_confirm" type="object" string="Print Cheque" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,528 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- FUSION PAYROLL DASHBOARD ACTION -->
<!-- ============================================================ -->
<record id="action_fusion_payroll_dashboard" model="ir.actions.client">
<field name="name">Fusion Payroll Dashboard</field>
<field name="tag">fusion_payroll_dashboard</field>
</record>
<!-- Dashboard Action - Direct window action -->
<record id="action_fusion_dashboard_employees" model="ir.actions.act_window">
<field name="name">Fusion Payroll</field>
<field name="res_model">fusion.payroll.dashboard</field>
<field name="view_mode">form</field>
<field name="target">current</field>
<field name="context">{'create': False, 'edit': False, 'delete': False}</field>
<field name="view_id" ref="fusion_payroll_dashboard_form"/>
</record>
<!-- ============================================================ -->
<!-- RUN PAYROLL ACTIONS -->
<!-- ============================================================ -->
<record id="action_fusion_run_payroll" model="ir.actions.act_window">
<field name="name">Run Payroll</field>
<field name="res_model">hr.payslip.run</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new payroll batch
</p>
<p>Process payroll for your employees with automatic CPP, CPP2, EI, and tax calculations.</p>
</field>
</record>
<record id="action_fusion_payslips" model="ir.actions.act_window">
<field name="name">Payslips</field>
<field name="res_model">hr.payslip</field>
<field name="view_mode">list,form</field>
</record>
<!-- ============================================================ -->
<!-- EMPLOYEES ACTIONS -->
<!-- ============================================================ -->
<record id="action_fusion_employees" model="ir.actions.act_window">
<field name="name">Employees</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">kanban,list,form</field>
<field name="context">{'search_default_active_employees': 1}</field>
</record>
<record id="action_fusion_employees_active" model="ir.actions.act_window">
<field name="name">Active Employees</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">kanban,list,form</field>
<field name="domain">[('employment_status', '=', 'active')]</field>
</record>
<record id="action_fusion_employees_on_leave" model="ir.actions.act_window">
<field name="name">On Leave</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">kanban,list,form</field>
<field name="domain">[('employment_status', '=', 'on_leave')]</field>
</record>
<record id="action_fusion_employees_terminated" model="ir.actions.act_window">
<field name="name">Terminated Employees</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">list,form</field>
<field name="domain">[('employment_status', '=', 'terminated')]</field>
</record>
<!-- ============================================================ -->
<!-- PAYROLL TAX ACTIONS -->
<!-- ============================================================ -->
<record id="action_fusion_tax_remittances" model="ir.actions.act_window">
<field name="name">Tax Remittances</field>
<field name="res_model">hr.tax.remittance</field>
<field name="view_mode">list,kanban,form</field>
</record>
<!-- ============================================================ -->
<!-- ROE ACTIONS -->
<!-- ============================================================ -->
<record id="action_fusion_roe" model="ir.actions.act_window">
<field name="name">Records of Employment</field>
<field name="res_model">hr.roe</field>
<field name="view_mode">list,form</field>
</record>
<record id="action_fusion_roe_pending" model="ir.actions.act_window">
<field name="name">Pending ROE</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">list,form</field>
<field name="domain">[('employment_status', '=', 'terminated'), ('roe_issued', '=', False)]</field>
</record>
<!-- ============================================================ -->
<!-- COMPLIANCE ACTIONS -->
<!-- ============================================================ -->
<record id="action_fusion_t4_summary" model="ir.actions.act_window">
<field name="name">T4 Summary</field>
<field name="res_model">hr.t4.summary</field>
<field name="view_mode">list,form</field>
</record>
<record id="action_fusion_t4_slips" model="ir.actions.act_window">
<field name="name">T4 Slips</field>
<field name="res_model">hr.t4.slip</field>
<field name="view_mode">list,form</field>
</record>
<!-- ============================================================ -->
<!-- CONFIGURATION ACTIONS -->
<!-- ============================================================ -->
<record id="action_fusion_salary_rules" model="ir.actions.act_window">
<field name="name">Salary Rules</field>
<field name="res_model">hr.salary.rule</field>
<field name="view_mode">list,form</field>
<field name="domain">[('struct_id.name', 'ilike', 'canada')]</field>
</record>
<record id="action_fusion_rule_parameters" model="ir.actions.act_window">
<field name="name">Tax Rate Parameters</field>
<field name="res_model">hr.rule.parameter</field>
<field name="view_mode">list,form</field>
<field name="domain">[('code', 'like', 'ca_%')]</field>
</record>
<record id="action_fusion_payroll_structure" model="ir.actions.act_window">
<field name="name">Payroll Structure</field>
<field name="res_model">hr.payroll.structure</field>
<field name="view_mode">list,form</field>
<field name="domain">[('name', 'ilike', 'canada')]</field>
</record>
<record id="action_fusion_input_types" model="ir.actions.act_window">
<field name="name">Input Types</field>
<field name="res_model">hr.payslip.input.type</field>
<field name="view_mode">list,form</field>
<field name="domain">[('country_id.code', '=', 'CA')]</field>
</record>
<record id="action_fusion_yearly_rates" model="ir.actions.act_window">
<field name="name">Yearly Rates (Legacy)</field>
<field name="res_model">tax.yearly.rates</field>
<field name="view_mode">list,form</field>
</record>
<!-- ============================================================ -->
<!-- MAIN MENU: FUSION PAYROLL -->
<!-- ============================================================ -->
<!-- Root Menu under Payroll App -->
<menuitem id="menu_fusion_payroll_root"
name="Fusion Payroll"
parent="hr_work_entry_enterprise.menu_hr_payroll_root"
sequence="5"/>
<!-- ============================================================ -->
<!-- SUBMENU: DASHBOARD -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_dashboard"
name="Dashboard"
parent="menu_fusion_payroll_root"
action="action_fusion_dashboard_employees"
sequence="1"/>
<!-- ============================================================ -->
<!-- SUBMENU: RUN PAYROLL -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_run_payroll"
name="Run Payroll"
parent="menu_fusion_payroll_root"
sequence="10"/>
<menuitem id="menu_fusion_run_payroll_wizard"
name="Run Payroll"
parent="menu_fusion_run_payroll"
action="action_open_run_payroll"
sequence="5"/>
<menuitem id="menu_fusion_payroll_batches"
name="Payroll Batches"
parent="menu_fusion_run_payroll"
action="action_fusion_run_payroll"
sequence="10"/>
<menuitem id="menu_fusion_payslips"
name="All Payslips"
parent="menu_fusion_run_payroll"
action="action_fusion_payslips"
sequence="20"/>
<menuitem id="menu_fusion_pay_periods"
name="Pay Periods"
parent="menu_fusion_run_payroll"
action="action_payroll_pay_period"
sequence="25"/>
<!-- ============================================================ -->
<!-- SUBMENU: EMPLOYEES -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_employees"
name="Employees"
parent="menu_fusion_payroll_root"
sequence="20"/>
<menuitem id="menu_fusion_employees_all"
name="All Employees"
parent="menu_fusion_employees"
action="action_fusion_employees"
sequence="10"/>
<menuitem id="menu_fusion_employees_active"
name="Active"
parent="menu_fusion_employees"
action="action_fusion_employees_active"
sequence="20"/>
<menuitem id="menu_fusion_employees_on_leave"
name="On Leave"
parent="menu_fusion_employees"
action="action_fusion_employees_on_leave"
sequence="30"/>
<menuitem id="menu_fusion_employees_terminated"
name="Terminated"
parent="menu_fusion_employees"
action="action_fusion_employees_terminated"
sequence="40"/>
<!-- ============================================================ -->
<!-- SUBMENU: TAX COMPLIANCE (Combined) -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_payroll_tax"
name="Tax &amp; Compliance"
parent="menu_fusion_payroll_root"
sequence="30"/>
<menuitem id="menu_fusion_tax_remittances"
name="CRA Remittances"
parent="menu_fusion_payroll_tax"
action="action_fusion_tax_remittances"
sequence="10"/>
<menuitem id="menu_fusion_t4_summary"
name="T4 Summary"
parent="menu_fusion_payroll_tax"
action="action_fusion_t4_summary"
sequence="20"/>
<menuitem id="menu_fusion_t4_slips"
name="T4 Slips"
parent="menu_fusion_payroll_tax"
action="action_fusion_t4_slips"
sequence="30"/>
<record id="action_fusion_t4a_summary" model="ir.actions.act_window">
<field name="name">T4A Summary</field>
<field name="res_model">hr.t4a.summary</field>
<field name="view_mode">list,form</field>
</record>
<record id="action_fusion_t4a_slips" model="ir.actions.act_window">
<field name="name">T4A Slips</field>
<field name="res_model">hr.t4a.slip</field>
<field name="view_mode">list,form</field>
</record>
<menuitem id="menu_fusion_t4a_summary"
name="T4A Summary"
parent="menu_fusion_payroll_tax"
action="action_fusion_t4a_summary"
sequence="40"/>
<menuitem id="menu_fusion_t4a_slips"
name="T4A Slips"
parent="menu_fusion_payroll_tax"
action="action_fusion_t4a_slips"
sequence="50"/>
<!-- ============================================================ -->
<!-- SUBMENU: ROE (RECORD OF EMPLOYMENT) -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_roe"
name="Record of Employment"
parent="menu_fusion_payroll_root"
sequence="40"/>
<menuitem id="menu_fusion_roe_all"
name="All ROEs"
parent="menu_fusion_roe"
action="action_fusion_roe"
sequence="10"/>
<menuitem id="menu_fusion_roe_pending"
name="Pending ROE"
parent="menu_fusion_roe"
action="action_fusion_roe_pending"
sequence="20"/>
<!-- ============================================================ -->
<!-- REPORTS ACTIONS -->
<!-- ============================================================ -->
<!-- Report Hub Action - Shows all reports in a grid -->
<record id="action_fusion_report_hub_page" model="ir.actions.client">
<field name="name">Payroll Reports</field>
<field name="tag">fusion_payroll.report_hub</field>
</record>
<!-- Paycheque/Payslip Reports -->
<record id="action_report_paycheque_history" model="ir.actions.act_window">
<field name="name">Paycheque History</field>
<field name="res_model">hr.payslip</field>
<field name="view_mode">list,form</field>
<field name="domain">[('state', '=', 'done')]</field>
<field name="context">{'search_default_group_employee': 1}</field>
</record>
<record id="action_report_payroll_deductions" model="ir.actions.act_window">
<field name="name">Payroll Deductions/Contributions</field>
<field name="res_model">hr.payslip.line</field>
<field name="view_mode">list,pivot,graph</field>
<field name="domain">[('category_id.code', 'in', ['DED', 'COMP'])]</field>
<field name="context">{'search_default_group_category': 1}</field>
</record>
<record id="action_report_payroll_summary_employee" model="ir.actions.act_window">
<field name="name">Payroll Summary by Employee</field>
<field name="res_model">hr.payslip</field>
<field name="view_mode">pivot,list,graph</field>
<field name="context">{'search_default_group_employee': 1}</field>
</record>
<!-- Employee Reports -->
<record id="action_report_employee_directory" model="ir.actions.act_window">
<field name="name">Employee Directory</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">list,kanban,form</field>
<field name="domain">[('employment_status', '=', 'active')]</field>
</record>
<record id="action_report_employee_details" model="ir.actions.act_window">
<field name="name">Employee Details</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">list,form</field>
</record>
<record id="action_report_multiple_worksites" model="ir.actions.act_window">
<field name="name">Multiple Worksites</field>
<field name="res_model">hr.employee</field>
<field name="view_mode">list,form</field>
<field name="context">{'search_default_group_department': 1}</field>
</record>
<!-- Payroll Details Reports -->
<record id="action_report_payroll_details" model="ir.actions.act_window">
<field name="name">Payroll Details</field>
<field name="res_model">hr.payslip.line</field>
<field name="view_mode">list,pivot,graph</field>
</record>
<record id="action_report_payroll_item_list" model="ir.actions.act_window">
<field name="name">Payroll Item List</field>
<field name="res_model">hr.salary.rule</field>
<field name="view_mode">list,form</field>
</record>
<record id="action_report_payroll_summary" model="ir.actions.act_window">
<field name="name">Payroll Summary</field>
<field name="res_model">hr.payslip.run</field>
<field name="view_mode">list,pivot,form</field>
</record>
<record id="action_report_vacation_sick" model="ir.actions.act_window">
<field name="name">Vacation and Sick Leave</field>
<field name="res_model">hr.leave</field>
<field name="view_mode">list,calendar,pivot</field>
</record>
<!-- Tax Reports -->
<record id="action_report_retirement_plans" model="ir.actions.act_window">
<field name="name">Retirement Plans</field>
<field name="res_model">hr.payslip.line</field>
<field name="view_mode">list,pivot</field>
<field name="domain">[('salary_rule_id.code', 'ilike', 'rrsp')]</field>
</record>
<record id="action_report_tax_liability" model="ir.actions.act_window">
<field name="name">Payroll Tax Liability</field>
<field name="res_model">hr.tax.remittance</field>
<field name="view_mode">list,pivot,graph</field>
</record>
<record id="action_report_tax_payments" model="ir.actions.act_window">
<field name="name">Payroll Tax Payments</field>
<field name="res_model">hr.tax.remittance</field>
<field name="view_mode">list,form</field>
<field name="domain">[('state', '=', 'paid')]</field>
</record>
<record id="action_report_total_payroll_cost" model="ir.actions.act_window">
<field name="name">Total Payroll Cost</field>
<field name="res_model">hr.payslip.run</field>
<field name="view_mode">pivot,graph,list</field>
</record>
<record id="action_report_total_pay" model="ir.actions.act_window">
<field name="name">Total Pay</field>
<field name="res_model">hr.payslip</field>
<field name="view_mode">pivot,graph,list</field>
<field name="domain">[('state', '=', 'done')]</field>
</record>
<record id="action_report_tax_wage_summary" model="ir.actions.act_window">
<field name="name">Payroll Tax and Wage Summary</field>
<field name="res_model">hr.payslip</field>
<field name="view_mode">pivot,graph,list</field>
</record>
<record id="action_report_workers_comp" model="ir.actions.act_window">
<field name="name">Workers' Compensation</field>
<field name="res_model">hr.payslip.line</field>
<field name="view_mode">list,pivot</field>
<field name="domain">[('salary_rule_id.code', 'ilike', 'wsib')]</field>
</record>
<!-- Time Activities -->
<record id="action_report_time_activities" model="ir.actions.act_window">
<field name="name">Recent/Edited Time Activities</field>
<field name="res_model">hr.work.entry</field>
<field name="view_mode">list,calendar</field>
<field name="context">{'search_default_filter_today': 1}</field>
</record>
<record id="action_report_time_by_employee" model="ir.actions.act_window">
<field name="name">Time Activities by Employee Detail</field>
<field name="res_model">hr.work.entry</field>
<field name="view_mode">list,pivot,calendar</field>
<field name="context">{'search_default_group_employee': 1}</field>
</record>
<!-- ============================================================ -->
<!-- SUBMENU: REPORTS (single menu linking to reports page) -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_reports"
name="Reports"
parent="menu_fusion_payroll_root"
action="action_fusion_report_hub_page"
sequence="90"/>
<!-- ============================================================ -->
<!-- SUBMENU: SETTINGS (Company-level payroll settings) -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_payroll_settings"
name="Settings"
parent="menu_fusion_payroll_root"
action="action_payroll_config_settings"
sequence="95"/>
<!-- ============================================================ -->
<!-- SUBMENU: CONFIGURATION (Technical config for admins) -->
<!-- ============================================================ -->
<menuitem id="menu_fusion_config"
name="Configuration"
parent="menu_fusion_payroll_root"
sequence="100"
groups="base.group_system"/>
<menuitem id="menu_fusion_config_rules"
name="Salary Rules"
parent="menu_fusion_config"
action="action_fusion_salary_rules"
sequence="10"/>
<menuitem id="menu_fusion_config_params"
name="Tax Rate Parameters"
parent="menu_fusion_config"
action="action_fusion_rule_parameters"
sequence="20"/>
<menuitem id="menu_fusion_config_structure"
name="Payroll Structure"
parent="menu_fusion_config"
action="action_fusion_payroll_structure"
sequence="30"/>
<menuitem id="menu_fusion_config_inputs"
name="Input Types"
parent="menu_fusion_config"
action="action_fusion_input_types"
sequence="40"/>
<menuitem id="menu_fusion_config_yearly"
name="Yearly Rates (Legacy)"
parent="menu_fusion_config"
action="action_fusion_yearly_rates"
sequence="50"/>
<menuitem id="menu_fusion_work_locations"
name="Work Locations"
parent="menu_fusion_config"
action="action_payroll_work_location"
sequence="60"/>
<record id="action_pdf_field_position" model="ir.actions.act_window">
<field name="name">PDF Field Positions</field>
<field name="res_model">pdf.field.position</field>
<field name="view_mode">list,form</field>
<field name="context">{'search_default_active': 1}</field>
</record>
<menuitem id="menu_fusion_pdf_field_positions"
name="PDF Field Positions"
parent="menu_fusion_config"
action="action_pdf_field_position"
sequence="70"/>
<menuitem id="menu_cheque_layout_settings"
name="Cheque Layout"
parent="menu_fusion_config"
action="action_cheque_layout_settings"
sequence="75"/>
</odoo>

View File

@@ -0,0 +1,321 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- SIN View/Edit Wizard Form -->
<record id="hr_employee_sin_wizard_form" model="ir.ui.view">
<field name="name">hr.employee.sin.wizard.form</field>
<field name="model">hr.employee.sin.wizard</field>
<field name="arch" type="xml">
<form string="View/Edit Social Insurance Number">
<div class="alert alert-info mb-3" role="alert">
<i class="fa fa-lock me-2"/>
<strong>Restricted Access:</strong> This information is only visible to HR Managers and Accountants.
</div>
<group>
<group>
<field name="employee_id" readonly="1"/>
</group>
<group>
<label for="sin_number"/>
<div class="o_row">
<field name="sin_number" nolabel="1" placeholder="XXX-XXX-XXX"/>
</div>
<field name="sin_number_formatted" readonly="1" invisible="1"/>
</group>
</group>
<div class="text-muted small mt-2">
<i class="fa fa-info-circle me-1"/>
Enter the 9-digit SIN number. Format: XXX-XXX-XXX
</div>
<footer>
<button name="action_save" string="Save" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- Employee Termination Wizard Form -->
<record id="hr_employee_terminate_wizard_form" model="ir.ui.view">
<field name="name">hr.employee.terminate.wizard.form</field>
<field name="model">hr.employee.terminate.wizard</field>
<field name="arch" type="xml">
<form string="Terminate Employee">
<div class="alert alert-warning mb-3" role="alert">
<i class="fa fa-warning me-2"/>
<strong>Important:</strong> Make sure you send a Record of Employment (ROE) to Service Canada within 5 days of the interruption in earnings.
</div>
<group>
<group string="Employee">
<field name="employee_id" readonly="1"/>
<field name="last_day_of_work" required="1"/>
</group>
<group string="Reason">
<field name="roe_reason_code" required="1"/>
</group>
</group>
<group>
<group string="Options">
<field name="show_in_employee_lists_only"/>
<field name="issue_roe_now"/>
</group>
</group>
<group>
<field name="notes" placeholder="Optional termination notes..."/>
</group>
<footer>
<button name="action_terminate" string="Terminate Employee" type="object" class="btn-danger"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- Extend Employee Form View -->
<record id="hr_employee_view_form_inherit_payroll_canada" model="ir.ui.view">
<field name="name">hr.employee.form.inherit.payroll.canada</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="priority">50</field>
<field name="arch" type="xml">
<!-- Add Terminate button in header -->
<xpath expr="//header" position="inside">
<button name="action_terminate_employee"
string="Terminate"
type="object"
class="btn-secondary"
invisible="employment_status == 'terminated'"/>
<button name="action_issue_roe"
string="Issue ROE"
type="object"
class="btn-secondary"
invisible="employment_status != 'terminated' or roe_issued"/>
</xpath>
<!-- Add Employment Status badge after name -->
<xpath expr="//div[hasclass('oe_title')]" position="inside">
<div class="d-flex gap-2 mt-2">
<span class="badge rounded-pill text-bg-success"
invisible="employment_status != 'active'">Active</span>
<span class="badge rounded-pill text-bg-warning"
invisible="employment_status != 'on_leave'">On Leave</span>
<span class="badge rounded-pill text-bg-danger"
invisible="employment_status != 'terminated'">Terminated</span>
</div>
</xpath>
<!-- Add Fusion Payroll Tab -->
<xpath expr="//notebook" position="inside">
<page string="Fusion Payroll" name="fusion_payroll">
<!-- Employment Details Section -->
<group string="Employment Details">
<group>
<field name="employment_status"/>
<field name="hire_date"/>
<field name="pay_schedule"/>
</group>
<group>
<field name="work_location_ids" widget="many2many_tags"
options="{'color_field': 'status'}"
placeholder="Select work locations..."/>
<field name="department_id"/>
<field name="employee_number"/>
</group>
</group>
<group invisible="employment_status != 'terminated'">
<group>
<field name="last_day_of_work" required="employment_status == 'terminated'"/>
<field name="roe_reason_code" required="employment_status == 'terminated'"/>
<field name="show_in_employee_lists_only"/>
</group>
</group>
<!-- Personal Info Section -->
<group string="Personal Info">
<group>
<field name="preferred_name" placeholder="Preferred First Name"/>
<field name="private_email" widget="email"/>
<field name="private_phone" widget="phone"/>
</group>
<group>
<field name="birthday"/>
<field name="gender_identity"/>
<!-- SIN with masking -->
<label for="sin_number_display"/>
<div class="o_row">
<field name="sin_number_display" readonly="1" nolabel="1"/>
<button name="action_view_sin" type="object"
string="View/Edit" class="btn-link"
groups="hr.group_hr_manager,account.group_account_manager"/>
</div>
</group>
</group>
<group string="Home Address">
<group>
<field name="home_street" placeholder="Street Address"/>
<field name="home_street2" placeholder="Apt, Suite, Unit"/>
<field name="home_city"/>
</group>
<group>
<field name="home_province"/>
<field name="home_postal_code" placeholder="A1A 1A1"/>
</group>
</group>
<group string="Mailing Address">
<group>
<field name="mailing_same_as_home"/>
</group>
<group invisible="mailing_same_as_home">
<field name="mailing_street"/>
<field name="mailing_city"/>
<field name="mailing_province"/>
<field name="mailing_postal_code"/>
</group>
</group>
<!-- Tax Withholdings Section -->
<group string="Tax Withholdings">
<group>
<field name="federal_td1_amount" widget="monetary"/>
<field name="federal_additional_tax" widget="monetary"/>
</group>
<group>
<field name="provincial_claim_amount" widget="monetary"/>
</group>
</group>
<group string="Tax Exemptions">
<group>
<field name="exempt_cpp"/>
<field name="exempt_ei"/>
<field name="exempt_federal_tax"/>
</group>
</group>
<!-- Payment Method Section -->
<group string="Payment Method">
<group>
<field name="payment_method" widget="radio"/>
</group>
</group>
<!-- Base Pay Section -->
<field name="currency_id" invisible="1"/>
<group string="Base Pay">
<group>
<field name="pay_type" widget="radio"/>
<field name="hourly_rate" widget="monetary"
invisible="pay_type != 'hourly'"/>
<field name="salary_amount" widget="monetary"
invisible="pay_type != 'salary'"/>
</group>
<group>
<field name="default_hours_per_day"/>
<field name="default_days_per_week"/>
<field name="default_hours_per_week" readonly="1"/>
<field name="base_pay_effective_date"/>
</group>
</group>
<!-- Time Off / Vacation Section -->
<group string="Time Off">
<group>
<field name="vacation_policy"/>
<field name="vacation_rate"
invisible="vacation_policy not in ['percent_4', 'percent_6']"/>
</group>
</group>
<!-- Deductions and Contributions -->
<group string="Deductions and Contributions">
<group>
<field name="t4_dental_code"/>
</group>
</group>
<!-- Billing Section -->
<group string="Billing">
<group>
<field name="billing_rate" widget="monetary"/>
<field name="billable_by_default"/>
</group>
</group>
<!-- Emergency Contact Section -->
<group string="Emergency Contact">
<group>
<field name="emergency_first_name"/>
<field name="emergency_last_name"/>
<field name="emergency_relationship"/>
</group>
<group>
<field name="emergency_phone" widget="phone"/>
<field name="emergency_email" widget="email"/>
</group>
</group>
<!-- ROE Tracking Section (visible only for terminated) -->
<group string="Record of Employment (ROE)"
invisible="employment_status != 'terminated'">
<group>
<field name="roe_issued"/>
<field name="roe_issued_date" invisible="not roe_issued"/>
</group>
<group>
<field name="roe_serial_number" invisible="not roe_issued"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
<!-- Employee Tree View - Add Status Column -->
<record id="hr_employee_view_tree_inherit_payroll_canada" model="ir.ui.view">
<field name="name">hr.employee.tree.inherit.payroll.canada</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='department_id']" position="after">
<field name="employment_status"
decoration-success="employment_status == 'active'"
decoration-warning="employment_status == 'on_leave'"
decoration-danger="employment_status == 'terminated'"/>
<field name="hire_date"/>
</xpath>
</field>
</record>
<!-- Employee Search View - Add Filters -->
<record id="hr_employee_view_search_inherit_payroll_canada" model="ir.ui.view">
<field name="name">hr.employee.search.inherit.payroll.canada</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_filter"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='my_team']" position="after">
<separator/>
<filter name="active_employees" string="Active"
domain="[('employment_status', '=', 'active')]"/>
<filter name="on_leave_employees" string="On Leave"
domain="[('employment_status', '=', 'on_leave')]"/>
<filter name="terminated_employees" string="Terminated"
domain="[('employment_status', '=', 'terminated')]"/>
<filter name="pending_roe" string="Pending ROE"
domain="[('employment_status', '=', 'terminated'), ('roe_issued', '=', False)]"/>
</xpath>
<xpath expr="//group" position="inside">
<filter name="group_by_status" string="Employment Status"
context="{'group_by': 'employment_status'}"/>
<filter name="group_by_pay_schedule" string="Pay Schedule"
context="{'group_by': 'pay_schedule'}"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,277 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- EXTEND PAYSLIP FORM - QuickBooks-style Canadian Payroll -->
<!-- ============================================================ -->
<record id="view_hr_payslip_form_inherit_canada" model="ir.ui.view">
<field name="name">hr.payslip.form.inherit.canada</field>
<field name="model">hr.payslip</field>
<field name="inherit_id" ref="hr_payroll.view_hr_payslip_form"/>
<field name="priority">50</field>
<field name="arch" type="xml">
<!-- Add Print Cheque button in header -->
<xpath expr="//button[@name='action_payslip_done']" position="after">
<button name="action_print_cheque"
type="object"
string="Print Cheque"
class="btn-secondary"
icon="fa-print"
invisible="paid_by != 'cheque'"/>
</xpath>
<!-- Add ribbon-style cheque status using Odoo's built-in web_ribbon widget -->
<xpath expr="//sheet" position="inside">
<field name="cheque_state" invisible="1"/>
<field name="cheque_id" invisible="1"/>
<widget name="web_ribbon" title="PRINTED" bg_color="text-bg-success"
invisible="paid_by != 'cheque' or cheque_state != 'printed'"/>
<widget name="web_ribbon" title="DRAFT" bg_color="text-bg-info"
invisible="paid_by != 'cheque' or cheque_state != 'draft'"/>
<widget name="web_ribbon" title="VOIDED" bg_color="text-bg-danger"
invisible="paid_by != 'cheque' or cheque_state != 'voided'"/>
<widget name="web_ribbon" title="CASHED" bg_color="text-bg-warning"
invisible="paid_by != 'cheque' or cheque_state != 'cashed'"/>
</xpath>
<!-- Reorganize header: hide the standalone avatar, move payment info to main group -->
<xpath expr="//field[@name='employee_id']/.." position="attributes">
<attribute name="class">oe_title d-flex align-items-center</attribute>
</xpath>
<!-- Add Payment/Cheque info in the main info group with other fields -->
<xpath expr="//group[field[@name='payslip_run_id']]" position="before">
<group string="Payment Information" invisible="paid_by == False">
<field name="paid_by" string="Payment Method"/>
<field name="cheque_number" string="Cheque #" invisible="paid_by != 'cheque'" readonly="1"/>
</group>
</xpath>
<!-- Add Canadian Summary Tab after Salary Computation -->
<xpath expr="//notebook" position="inside">
<page string="Paycheque Entry" name="paycheque_entry">
<!-- Header with Net Pay -->
<div class="row mb-4">
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h6 class="card-subtitle mb-2 text-muted">PAY TO</h6>
<h4><field name="employee_id" readonly="1" class="fw-bold"/></h4>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h6 class="card-subtitle mb-2 text-muted">PAY PERIOD</h6>
<div class="row">
<div class="col-6">
<small class="text-muted">From</small><br/>
<field name="date_from" readonly="1"/>
</div>
<div class="col-6">
<small class="text-muted">To</small><br/>
<field name="date_to" readonly="1"/>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card bg-success text-white">
<div class="card-body text-end">
<h6 class="card-subtitle mb-2 text-white-50">NET PAY</h6>
<h2 class="mb-0">
<field name="net_wage" widget="monetary"/>
</h2>
<div invisible="paid_by != 'cheque'">
<small>Cheque #: <field name="cheque_number" readonly="1"/></small>
</div>
</div>
</div>
</div>
</div>
<!-- Pay Section (Earnings) -->
<div class="card mb-3">
<div class="card-header bg-primary text-white">
<i class="fa fa-money me-2"/>Pay (Earnings)
</div>
<div class="card-body p-0">
<field name="line_ids" mode="list" readonly="state == 'done'"
context="{'default_slip_id': id}"
domain="[('category_id.code', 'in', ['BASIC', 'ALW', 'GROSS'])]">
<list string="Earnings" create="0" delete="0"
decoration-bf="category_id.code == 'GROSS'">
<field name="name" string="Type"/>
<field name="code" column_invisible="1"/>
<field name="quantity" string="Hours"/>
<field name="rate" string="Rate"/>
<field name="amount" string="Current"/>
<field name="total" string="Total" sum="Total Earnings"/>
<field name="category_id" column_invisible="1"/>
</list>
</field>
</div>
<div class="card-footer text-end">
<strong>Total Earnings: </strong>
<field name="gross_wage" widget="monetary" class="fw-bold"/>
<span class="text-muted ms-3">YTD: </span>
<field name="ytd_gross" widget="monetary"/>
</div>
</div>
<!-- Employee Taxes Section -->
<div class="card mb-3">
<div class="card-header bg-warning">
<i class="fa fa-calculator me-2"/>Employee Taxes
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm mb-0">
<thead>
<tr>
<th>Type</th>
<th class="text-end">Current</th>
<th class="text-end">YTD</th>
</tr>
</thead>
<tbody>
<tr>
<td>Income Tax</td>
<td class="text-end"><field name="employee_income_tax" widget="monetary"/></td>
<td class="text-end text-muted"><field name="ytd_income_tax" widget="monetary"/></td>
</tr>
<tr>
<td>Employment Insurance (EI)</td>
<td class="text-end"><field name="employee_ei" widget="monetary"/></td>
<td class="text-end text-muted"><field name="ytd_ei" widget="monetary"/></td>
</tr>
<tr>
<td>Canada Pension Plan (CPP)</td>
<td class="text-end"><field name="employee_cpp" widget="monetary"/></td>
<td class="text-end text-muted"><field name="ytd_cpp" widget="monetary"/></td>
</tr>
<tr>
<td>Second Canada Pension Plan (CPP2)</td>
<td class="text-end"><field name="employee_cpp2" widget="monetary"/></td>
<td class="text-end text-muted"><field name="ytd_cpp2" widget="monetary"/></td>
</tr>
</tbody>
<tfoot>
<tr class="fw-bold">
<td>Total</td>
<td class="text-end"><field name="total_employee_deductions" widget="monetary"/></td>
<td></td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<!-- Employer Taxes Section -->
<div class="card mb-3">
<div class="card-header bg-info text-white">
<i class="fa fa-building me-2"/>Employer Taxes (Company Cost)
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm mb-0">
<thead>
<tr>
<th>Type</th>
<th class="text-end">Current</th>
</tr>
</thead>
<tbody>
<tr>
<td>Employment Insurance Employer (1.4x)</td>
<td class="text-end"><field name="employer_ei" widget="monetary"/></td>
</tr>
<tr>
<td>Canada Pension Plan Employer</td>
<td class="text-end"><field name="employer_cpp" widget="monetary"/></td>
</tr>
<tr>
<td>Second CPP Employer</td>
<td class="text-end"><field name="employer_cpp2" widget="monetary"/></td>
</tr>
</tbody>
<tfoot>
<tr class="fw-bold">
<td>Total Employer Cost</td>
<td class="text-end"><field name="total_employer_cost" widget="monetary"/></td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<!-- Summary Section -->
<div class="card mb-3">
<div class="card-header bg-dark text-white">
<i class="fa fa-list-alt me-2"/>Summary
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<table class="table table-sm">
<tr>
<td>Total Pay</td>
<td class="text-end"><field name="gross_wage" widget="monetary"/></td>
<td class="text-end text-muted"><field name="ytd_gross" widget="monetary"/></td>
</tr>
<tr>
<td>Total Taxes</td>
<td class="text-end text-danger">-<field name="total_employee_deductions" widget="monetary"/></td>
<td></td>
</tr>
<tr class="fw-bold fs-5">
<td>Net Pay</td>
<td class="text-end text-success"><field name="net_wage" widget="monetary"/></td>
<td class="text-end text-muted"><field name="ytd_net" widget="monetary"/></td>
</tr>
</table>
</div>
</div>
</div>
</div>
<!-- Memo -->
<div class="card">
<div class="card-header">
<i class="fa fa-sticky-note me-2"/>Memo
</div>
<div class="card-body">
<field name="memo" placeholder="Add internal notes for this paycheque..."/>
</div>
</div>
</page>
</xpath>
</field>
</record>
<!-- ============================================================ -->
<!-- PAYSLIP LIST VIEW - Add Canadian fields -->
<!-- ============================================================ -->
<record id="view_hr_payslip_tree_inherit_canada" model="ir.ui.view">
<field name="name">hr.payslip.tree.inherit.canada</field>
<field name="model">hr.payslip</field>
<field name="inherit_id" ref="hr_payroll.view_hr_payslip_tree"/>
<field name="priority">50</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='employee_id']" position="after">
<field name="paid_by" optional="hide"/>
<field name="cheque_number" optional="hide"/>
<field name="net_wage" string="Net Pay" widget="monetary" optional="show"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ROE Form View -->
<record id="hr_roe_view_form" model="ir.ui.view">
<field name="name">hr.roe.form</field>
<field name="model">hr.roe</field>
<field name="arch" type="xml">
<form string="Record of Employment">
<header>
<button name="action_calculate_earnings"
string="Calculate Earnings"
type="object"
class="btn-secondary"
invisible="state in ['submitted', 'archived']"/>
<button name="action_generate_blk"
string="Generate BLK File"
type="object"
class="btn-primary"
invisible="state in ['submitted', 'archived']"/>
<button name="action_mark_submitted"
string="Mark as Submitted"
type="object"
class="btn-success"
invisible="state in ['draft', 'submitted', 'archived']"/>
<button name="action_print_roe"
string="Print ROE"
type="object"
class="btn-secondary"
icon="fa-print"/>
<field name="state" widget="statusbar" statusbar_visible="draft,ready,submitted,archived"/>
</header>
<sheet>
<!-- Deadline Warning Ribbon -->
<widget name="web_ribbon" title="Deadline Approaching" bg_color="text-bg-warning"
invisible="state != 'ready'"/>
<widget name="web_ribbon" title="Submitted" bg_color="text-bg-success"
invisible="state != 'submitted'"/>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<group>
<group string="Employee Information">
<field name="employee_id"/>
<field name="sin_number"/>
<field name="occupation"/>
<field name="pay_period_type"/>
</group>
<group string="Employer Information">
<field name="company_id"/>
<field name="cra_business_number"/>
</group>
</group>
<group>
<group string="Employment Dates">
<field name="first_day_worked"/>
<field name="last_day_paid"/>
<field name="final_pay_period_end"/>
<field name="expected_recall_date"/>
</group>
<group string="Reason">
<field name="reason_code"/>
<field name="communication_language"/>
</group>
</group>
<notebook>
<page string="Insurable Earnings" name="earnings">
<group>
<group>
<field name="total_insurable_hours"/>
</group>
<group>
<field name="total_insurable_earnings"/>
</group>
</group>
<field name="pay_period_earnings_ids">
<list editable="bottom">
<field name="sequence"/>
<field name="amount"/>
<field name="payslip_id"/>
</list>
</field>
</page>
<page string="Additional Information" name="additional">
<group>
<group string="Other Payments">
<field name="other_payments"/>
</group>
<group string="Comments">
<field name="comments"/>
</group>
</group>
</page>
<page string="Contact" name="contact">
<group>
<group string="Contact Person">
<field name="contact_name"/>
<field name="contact_phone"/>
</group>
<group string="Submission Status">
<field name="submission_date"/>
<field name="submission_deadline"/>
<field name="service_canada_serial"/>
</group>
</group>
<group string="Files">
<group>
<field name="blk_file" filename="blk_filename"/>
<field name="blk_filename" invisible="1"/>
</group>
<group>
<field name="pdf_file" filename="pdf_filename"/>
<field name="pdf_filename" invisible="1"/>
</group>
</group>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ROE List View -->
<record id="hr_roe_view_tree" model="ir.ui.view">
<field name="name">hr.roe.list</field>
<field name="model">hr.roe</field>
<field name="arch" type="xml">
<list string="Records of Employment">
<field name="name"/>
<field name="employee_id"/>
<field name="reason_code"/>
<field name="last_day_paid"/>
<field name="submission_deadline"/>
<field name="total_insurable_earnings"/>
<field name="state"/>
</list>
</field>
</record>
<!-- ROE Search View -->
<record id="hr_roe_view_search" model="ir.ui.view">
<field name="name">hr.roe.search</field>
<field name="model">hr.roe</field>
<field name="arch" type="xml">
<search string="Search ROE">
<field name="name"/>
<field name="employee_id"/>
</search>
</field>
</record>
<!-- ROE Sequence (menus moved to fusion_payroll_menus.xml) -->
<record id="sequence_hr_roe" model="ir.sequence">
<field name="name">ROE Sequence</field>
<field name="code">hr.roe</field>
<field name="prefix">ROE-</field>
<field name="padding">5</field>
<field name="company_id" eval="False"/>
</record>
</odoo>

View File

@@ -0,0 +1,293 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- T4 ACTIONS - Must be defined before views that reference them -->
<!-- ============================================================ -->
<record id="action_hr_t4_summary" model="ir.actions.act_window">
<field name="name">T4 Summary</field>
<field name="res_model">hr.t4.summary</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your T4 Summary
</p>
<p>
Generate T4 slips for all employees for the tax year.
</p>
</field>
</record>
<record id="action_hr_t4_slip" model="ir.actions.act_window">
<field name="name">T4 Slips</field>
<field name="res_model">hr.t4.slip</field>
<field name="view_mode">list,form</field>
</record>
<!-- ============================================================ -->
<!-- T4 SUMMARY FORM VIEW -->
<!-- ============================================================ -->
<record id="hr_t4_summary_view_form" model="ir.ui.view">
<field name="name">hr.t4.summary.form</field>
<field name="model">hr.t4.summary</field>
<field name="arch" type="xml">
<form string="T4 Summary">
<header>
<button name="action_generate_slips"
string="Generate T4 Slips"
type="object"
class="btn-primary"/>
<button name="action_fill_pdf"
string="Fill PDF"
type="object"
class="btn-primary"/>
<button name="action_download_pdf"
string="Download PDF"
type="object"
class="btn-secondary"
invisible="not filled_pdf"/>
<button name="action_extract_pdf_fields"
string="Extract PDF Fields"
type="object"
class="btn-info"
help="Extract and display PDF form field names (for debugging)"/>
<button name="action_mark_filed"
string="Mark as Filed"
type="object"
class="btn-success"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button type="action" class="oe_stat_button"
name="%(fusion_payroll.action_hr_t4_slip)d"
icon="fa-file-text-o">
<field name="slip_count" widget="statinfo" string="T4 Slips"/>
</button>
</div>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<group>
<group string="Tax Year">
<field name="company_id"/>
<field name="tax_year"/>
<field name="cra_business_number"/>
</group>
<group string="Contact">
<field name="contact_name"/>
<field name="contact_phone"/>
<field name="proprietor_sin"/>
<field name="filing_date"/>
</group>
</group>
<group string="PDF" invisible="not filled_pdf">
<field name="filled_pdf_filename" readonly="1"/>
</group>
<notebook>
<page string="Summary Totals" name="totals">
<group string="Employee Contributions">
<group>
<field name="total_employment_income"
string="Box 14: Employment Income"/>
<field name="total_cpp_employee"
string="Box 16: Employees' CPP"/>
<field name="total_cpp2_employee"
string="Box 16A: Employees' CPP2"/>
</group>
<group>
<field name="total_ei_employee"
string="Box 18: Employees' EI"/>
<field name="total_income_tax"
string="Box 22: Income Tax"/>
</group>
</group>
<group string="Employer Contributions">
<group>
<field name="total_cpp_employer"
string="Box 27: Employer's CPP"/>
<field name="total_cpp2_employer"
string="Box 27A: Employer's CPP2"/>
</group>
<group>
<field name="total_ei_employer"
string="Box 19: Employer's EI"/>
</group>
</group>
<group string="Remittance Summary">
<group>
<field name="total_deductions"
string="Box 80: Total Deductions"/>
<field name="total_remittances"
string="Box 82: Remittances"/>
</group>
<group>
<field name="balance_due"
string="Box 86: Balance Due"/>
<field name="overpayment"
string="Box 84: Overpayment"/>
</group>
</group>
</page>
<page string="T4 Slips" name="slips">
<field name="slip_ids">
<list>
<field name="employee_id"/>
<field name="employment_income" sum="Total"/>
<field name="cpp_employee" sum="Total"/>
<field name="ei_employee" sum="Total"/>
<field name="income_tax" sum="Total"/>
<field name="t4_dental_code"/>
</list>
</field>
</page>
</notebook>
<field name="currency_id" invisible="1"/>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ============================================================ -->
<!-- T4 SUMMARY LIST VIEW -->
<!-- ============================================================ -->
<record id="hr_t4_summary_view_list" model="ir.ui.view">
<field name="name">hr.t4.summary.list</field>
<field name="model">hr.t4.summary</field>
<field name="arch" type="xml">
<list string="T4 Summaries">
<field name="tax_year"/>
<field name="company_id"/>
<field name="slip_count"/>
<field name="total_employment_income"/>
<field name="total_deductions"/>
<field name="state"/>
<field name="currency_id" column_invisible="1"/>
</list>
</field>
</record>
<!-- ============================================================ -->
<!-- T4 SLIP FORM VIEW -->
<!-- ============================================================ -->
<record id="hr_t4_slip_view_form" model="ir.ui.view">
<field name="name">hr.t4.slip.form</field>
<field name="model">hr.t4.slip</field>
<field name="arch" type="xml">
<form string="T4 Slip">
<header>
<button name="action_fill_pdf"
string="Fill PDF"
type="object"
class="btn-primary"/>
<button name="action_download_pdf"
string="Download PDF"
type="object"
class="btn-secondary"
invisible="not filled_pdf"/>
<button name="action_extract_pdf_fields"
string="Extract PDF Fields"
type="object"
class="btn-info"
help="Extract and display PDF form field names (for debugging)"/>
</header>
<sheet>
<group>
<group string="Employee">
<field name="employee_id"/>
<field name="sin_number"/>
<field name="tax_year"/>
</group>
<group string="Reference">
<field name="summary_id"/>
<field name="t4_dental_code"/>
</group>
</group>
<group string="Amounts">
<group>
<field name="employment_income"
string="Box 14: Employment Income"/>
<field name="cpp_employee"
string="Box 16: CPP"/>
<field name="cpp2_employee"
string="Box 16A: CPP2"/>
</group>
<group>
<field name="ei_employee"
string="Box 18: EI"/>
<field name="income_tax"
string="Box 22: Income Tax"/>
</group>
</group>
<group string="Earnings and Deductions">
<group>
<field name="ei_insurable_earnings"
string="Box 24: EI Insurable Earnings"/>
<field name="cpp_pensionable_earnings"
string="Box 26: CPP Pensionable Earnings"/>
</group>
<group>
<field name="box_40_taxable_benefits"
string="Box 40: Other Taxable Allowances/Benefits"/>
<field name="box_42_commissions"
string="Box 42: Employment Commissions"/>
<field name="box_44_union_dues"
string="Box 44: Union Dues"/>
</group>
</group>
<group string="PDF" invisible="not filled_pdf">
<field name="filled_pdf_filename" readonly="1"/>
</group>
<field name="currency_id" invisible="1"/>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ============================================================ -->
<!-- T4 SLIP LIST VIEW -->
<!-- ============================================================ -->
<record id="hr_t4_slip_view_list" model="ir.ui.view">
<field name="name">hr.t4.slip.list</field>
<field name="model">hr.t4.slip</field>
<field name="arch" type="xml">
<list string="T4 Slips">
<field name="employee_id"/>
<field name="tax_year"/>
<field name="employment_income" sum="Total"/>
<field name="ei_insurable_earnings" sum="Total" optional="hide"/>
<field name="cpp_pensionable_earnings" sum="Total" optional="hide"/>
<field name="cpp_employee" sum="Total"/>
<field name="cpp2_employee" sum="Total"/>
<field name="ei_employee" sum="Total"/>
<field name="income_tax" sum="Total"/>
<field name="box_40_taxable_benefits" sum="Total" optional="hide"/>
<field name="box_42_commissions" sum="Total" optional="hide"/>
<field name="box_44_union_dues" sum="Total" optional="hide"/>
<field name="t4_dental_code"/>
<field name="currency_id" column_invisible="1"/>
</list>
</field>
</record>
<!-- Menus moved to fusion_payroll_menus.xml -->
</odoo>

View File

@@ -0,0 +1,235 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- T4A ACTIONS - Must be defined before views that reference them -->
<!-- ============================================================ -->
<record id="action_hr_t4a_summary" model="ir.actions.act_window">
<field name="name">T4A Summary</field>
<field name="res_model">hr.t4a.summary</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your T4A Summary
</p>
<p>
Generate T4A slips for all recipients for the tax year.
</p>
</field>
</record>
<record id="action_hr_t4a_slip" model="ir.actions.act_window">
<field name="name">T4A Slips</field>
<field name="res_model">hr.t4a.slip</field>
<field name="view_mode">list,form</field>
</record>
<!-- ============================================================ -->
<!-- T4A SUMMARY FORM VIEW -->
<!-- ============================================================ -->
<record id="hr_t4a_summary_view_form" model="ir.ui.view">
<field name="name">hr.t4a.summary.form</field>
<field name="model">hr.t4a.summary</field>
<field name="arch" type="xml">
<form string="T4A Summary">
<header>
<button name="action_mark_filed"
string="Mark as Filed"
type="object"
class="btn-success"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button type="action" class="oe_stat_button"
name="%(fusion_payroll.action_hr_t4a_slip)d"
icon="fa-file-text-o">
<field name="slip_count" widget="statinfo" string="T4A Slips"/>
</button>
</div>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<group>
<group string="Tax Year">
<field name="company_id"/>
<field name="tax_year"/>
<field name="cra_business_number"/>
</group>
<group string="Contact">
<field name="contact_name"/>
<field name="contact_phone"/>
<field name="filing_date"/>
</group>
</group>
<notebook>
<page string="Summary Totals" name="totals">
<group string="Income Totals">
<group>
<field name="total_box_016"
string="Box 016: Pension"/>
<field name="total_box_018"
string="Box 018: Lump-Sum"/>
<field name="total_box_020"
string="Box 020: Commissions"/>
</group>
<group>
<field name="total_box_024"
string="Box 024: Annuities"/>
<field name="total_box_048"
string="Box 048: Fees"/>
</group>
</group>
</page>
<page string="T4A Slips" name="slips">
<field name="slip_ids">
<list>
<field name="recipient_name"/>
<field name="box_016_pension" sum="Total"/>
<field name="box_018_lump_sum" sum="Total"/>
<field name="box_020_commissions" sum="Total"/>
<field name="box_024_annuities" sum="Total"/>
<field name="box_048_fees" sum="Total"/>
</list>
</field>
</page>
</notebook>
<field name="currency_id" invisible="1"/>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ============================================================ -->
<!-- T4A SUMMARY LIST VIEW -->
<!-- ============================================================ -->
<record id="hr_t4a_summary_view_list" model="ir.ui.view">
<field name="name">hr.t4a.summary.list</field>
<field name="model">hr.t4a.summary</field>
<field name="arch" type="xml">
<list string="T4A Summaries">
<field name="tax_year"/>
<field name="company_id"/>
<field name="slip_count"/>
<field name="total_box_016"/>
<field name="state"/>
<field name="currency_id" column_invisible="1"/>
</list>
</field>
</record>
<!-- ============================================================ -->
<!-- T4A SLIP FORM VIEW -->
<!-- ============================================================ -->
<record id="hr_t4a_slip_view_form" model="ir.ui.view">
<field name="name">hr.t4a.slip.form</field>
<field name="model">hr.t4a.slip</field>
<field name="arch" type="xml">
<form string="T4A Slip">
<header>
<button name="action_fill_pdf"
string="Fill PDF"
type="object"
class="btn-primary"/>
<button name="action_download_pdf"
string="Download PDF"
type="object"
class="btn-secondary"
invisible="not filled_pdf"/>
<button name="action_extract_pdf_fields"
string="Extract PDF Fields"
type="object"
class="btn-info"
help="Extract and display PDF form field names (for debugging)"/>
</header>
<sheet>
<group>
<group string="Recipient">
<field name="recipient_id"
options="{'no_create': True}"/>
<field name="recipient_name" required="1"/>
<field name="recipient_sin"
string="SIN (Box 12)"/>
<field name="recipient_account_number"
string="Account Number (Box 13)"/>
</group>
<group string="Reference">
<field name="summary_id"/>
<field name="tax_year"/>
</group>
</group>
<group string="Recipient Address">
<field name="recipient_address"
widget="text"
placeholder="Street address&#10;City, Province Postal Code"/>
</group>
<group string="Income Boxes">
<group>
<field name="box_016_pension"
string="Box 016: Pension or Superannuation"/>
<field name="box_018_lump_sum"
string="Box 018: Lump-Sum Payments"/>
<field name="box_020_commissions"
string="Box 020: Self-Employed Commissions"/>
</group>
<group>
<field name="box_024_annuities"
string="Box 024: Annuities"/>
<field name="box_048_fees"
string="Box 048: Fees for Services"/>
</group>
</group>
<group string="Other Information (Boxes 028-197)">
<field name="other_info_ids">
<list>
<field name="box_number" required="1"/>
<field name="amount" required="1"/>
<field name="description"/>
</list>
</field>
</group>
<group string="PDF" invisible="not filled_pdf">
<field name="filled_pdf_filename" readonly="1"/>
</group>
<field name="currency_id" invisible="1"/>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ============================================================ -->
<!-- T4A SLIP LIST VIEW -->
<!-- ============================================================ -->
<record id="hr_t4a_slip_view_list" model="ir.ui.view">
<field name="name">hr.t4a.slip.list</field>
<field name="model">hr.t4a.slip</field>
<field name="arch" type="xml">
<list string="T4A Slips">
<field name="recipient_name"/>
<field name="tax_year"/>
<field name="box_016_pension" sum="Total"/>
<field name="box_018_lump_sum" sum="Total"/>
<field name="box_020_commissions" sum="Total"/>
<field name="box_024_annuities" sum="Total"/>
<field name="box_048_fees" sum="Total"/>
<field name="filled_pdf_filename" optional="hide"/>
<field name="currency_id" column_invisible="1"/>
</list>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,253 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- TAX REMITTANCE FORM VIEW -->
<!-- ============================================================ -->
<record id="hr_tax_remittance_view_form" model="ir.ui.view">
<field name="name">hr.tax.remittance.form</field>
<field name="model">hr.tax.remittance</field>
<field name="arch" type="xml">
<form string="Tax Remittance">
<header>
<button name="action_calculate_amounts"
string="Calculate Amounts"
type="object"
class="btn-primary"
invisible="state == 'paid'"/>
<button name="action_mark_paid"
string="Mark as Paid"
type="object"
class="btn-success"
invisible="state == 'paid'"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,pending,due,paid"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button type="object" class="oe_stat_button"
name="action_view_payslips"
icon="fa-file-text-o"
invisible="payslip_count == 0">
<field name="payslip_count" widget="statinfo" string="Payslips"/>
</button>
</div>
<!-- Status Ribbons -->
<widget name="web_ribbon" title="Paid" bg_color="text-bg-success"
invisible="state != 'paid'"/>
<widget name="web_ribbon" title="Past Due" bg_color="text-bg-danger"
invisible="state != 'past_due'"/>
<widget name="web_ribbon" title="Due Soon" bg_color="text-bg-warning"
invisible="state != 'due'"/>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<!-- Period Info -->
<group>
<group string="Period">
<field name="company_id" readonly="state == 'paid'"/>
<field name="period_type"/>
<field name="period_start"/>
<field name="period_end"/>
<field name="due_date"/>
</group>
<group string="Payment">
<field name="payment_date"/>
<field name="payment_method"/>
<field name="payment_reference"/>
</group>
</group>
<notebook>
<page string="Remittance Details" name="details">
<!-- CPP Section -->
<group string="Canada Pension Plan (CPP)">
<group>
<field name="cpp_employee" widget="monetary"/>
<field name="cpp_employer" widget="monetary"/>
</group>
<group>
<field name="cpp2_employee" widget="monetary"/>
<field name="cpp2_employer" widget="monetary"/>
</group>
</group>
<!-- EI Section -->
<group string="Employment Insurance (EI)">
<group>
<field name="ei_employee" widget="monetary"/>
</group>
<group>
<field name="ei_employer" widget="monetary"/>
</group>
</group>
<!-- Tax Section -->
<group string="Income Tax">
<group>
<field name="income_tax" widget="monetary"/>
</group>
</group>
<group>
<group string="Total">
<field name="total" widget="monetary" class="fw-bold fs-4"/>
</group>
</group>
</page>
<page string="Payslips" name="payslips">
<field name="payslip_ids">
<list>
<field name="employee_id"/>
<field name="name"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="net_wage" widget="monetary"/>
<field name="state"/>
</list>
</field>
</page>
</notebook>
<field name="currency_id" invisible="1"/>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ============================================================ -->
<!-- TAX REMITTANCE LIST VIEW -->
<!-- ============================================================ -->
<record id="hr_tax_remittance_view_list" model="ir.ui.view">
<field name="name">hr.tax.remittance.list</field>
<field name="model">hr.tax.remittance</field>
<field name="arch" type="xml">
<list string="Tax Remittances"
decoration-danger="state == 'past_due'"
decoration-warning="state == 'due'"
decoration-success="state == 'paid'"
decoration-muted="state == 'draft'">
<field name="name"/>
<field name="period_start"/>
<field name="period_end"/>
<field name="due_date"/>
<field name="total" widget="monetary" sum="Total"/>
<field name="payment_date"/>
<field name="state" widget="badge"
decoration-danger="state == 'past_due'"
decoration-warning="state == 'due'"
decoration-success="state == 'paid'"/>
<field name="currency_id" column_invisible="1"/>
</list>
</field>
</record>
<!-- ============================================================ -->
<!-- TAX REMITTANCE KANBAN VIEW -->
<!-- ============================================================ -->
<record id="hr_tax_remittance_view_kanban" model="ir.ui.view">
<field name="name">hr.tax.remittance.kanban</field>
<field name="model">hr.tax.remittance</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile" default_group_by="state">
<field name="name"/>
<field name="period_start"/>
<field name="period_end"/>
<field name="due_date"/>
<field name="total"/>
<field name="state"/>
<field name="currency_id"/>
<templates>
<t t-name="card">
<div class="oe_kanban_content">
<div class="o_kanban_record_top mb-2">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong>
</div>
<field name="state" widget="label_selection"
options="{'classes': {'draft': 'secondary', 'pending': 'info', 'due': 'warning', 'past_due': 'danger', 'paid': 'success'}}"/>
</div>
<div class="o_kanban_record_body">
<div>
<span t-out="record.period_start.value"/> - <span t-out="record.period_end.value"/>
</div>
<div class="text-muted">
Due: <field name="due_date"/>
</div>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<strong class="fs-5">
<field name="total" widget="monetary"/>
</strong>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- ============================================================ -->
<!-- TAX REMITTANCE SEARCH VIEW -->
<!-- ============================================================ -->
<record id="hr_tax_remittance_view_search" model="ir.ui.view">
<field name="name">hr.tax.remittance.search</field>
<field name="model">hr.tax.remittance</field>
<field name="arch" type="xml">
<search string="Search Tax Remittances">
<field name="name"/>
<field name="period_start"/>
<field name="period_end"/>
<filter name="filter_paid" string="Paid" domain="[('state', '=', 'paid')]"/>
<filter name="filter_draft" string="Draft" domain="[('state', '=', 'draft')]"/>
<filter name="group_state" string="Status" context="{'group_by': 'state'}"/>
</search>
</field>
</record>
<!-- ============================================================ -->
<!-- TAX REMITTANCE ACTION -->
<!-- ============================================================ -->
<record id="hr_tax_remittance_action" model="ir.actions.act_window">
<field name="name">Tax Remittances</field>
<field name="res_model">hr.tax.remittance</field>
<field name="view_mode">kanban,list,form</field>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first tax remittance
</p>
<p>
Track CPP, EI, and income tax remittances to CRA.
The system can calculate amounts automatically from confirmed payslips.
</p>
</field>
</record>
<!-- Menus moved to fusion_payroll_menus.xml -->
<!-- ============================================================ -->
<!-- TAX REMITTANCE SEQUENCE -->
<!-- ============================================================ -->
<record id="sequence_hr_tax_remittance" model="ir.sequence">
<field name="name">Tax Remittance Sequence</field>
<field name="code">hr.tax.remittance</field>
<field name="prefix">REM-%(year)s-</field>
<field name="padding">4</field>
<field name="company_id" eval="False"/>
</record>
</odoo>

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Pay Period Tree View -->
<record id="payroll_pay_period_tree" model="ir.ui.view">
<field name="name">payroll.pay.period.tree</field>
<field name="model">payroll.pay.period</field>
<field name="arch" type="xml">
<list>
<field name="name" string="Period"/>
<field name="schedule_type"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="pay_date"/>
<field name="state" widget="badge"
decoration-info="state == 'draft'"
decoration-warning="state == 'in_progress'"
decoration-success="state == 'paid'"
decoration-muted="state == 'closed'"/>
<field name="payslip_run_id"/>
</list>
</field>
</record>
<!-- Pay Period Form View -->
<record id="payroll_pay_period_form" model="ir.ui.view">
<field name="name">payroll.pay.period.form</field>
<field name="model">payroll.pay.period</field>
<field name="arch" type="xml">
<form>
<header>
<field name="state" widget="statusbar" statusbar_visible="draft,in_progress,paid,closed"/>
</header>
<sheet>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<group>
<group>
<field name="company_id" groups="base.group_multi_company"/>
<field name="schedule_type"/>
</group>
<group>
<field name="date_start"/>
<field name="date_end"/>
<field name="pay_date"/>
</group>
</group>
<group>
<field name="payslip_run_id" readonly="1"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Pay Period Search View -->
<record id="payroll_pay_period_search" model="ir.ui.view">
<field name="name">payroll.pay.period.search</field>
<field name="model">payroll.pay.period</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="schedule_type"/>
</search>
</field>
</record>
<!-- Pay Period Settings Form View -->
<record id="payroll_pay_period_settings_form" model="ir.ui.view">
<field name="name">payroll.pay.period.settings.form</field>
<field name="model">payroll.pay.period.settings</field>
<field name="arch" type="xml">
<form>
<sheet>
<div class="oe_title mb-3">
<h1>Pay Period Configuration</h1>
</div>
<group>
<group string="Schedule Settings">
<field name="company_id" invisible="1"/>
<field name="schedule_type" widget="radio"/>
<field name="first_period_start"/>
<field name="pay_day_offset" help="Days after period end until pay date"/>
</group>
<group string="Auto-Generation">
<field name="auto_generate_periods"/>
<field name="periods_to_generate" invisible="not auto_generate_periods"/>
</group>
</group>
<div class="mt-4">
<button name="action_generate_periods"
type="object"
string="Generate Pay Periods"
class="btn-primary"
icon="fa-calendar-plus-o"/>
</div>
</sheet>
</form>
</field>
</record>
<!-- Pay Period Action -->
<record id="action_payroll_pay_period" model="ir.actions.act_window">
<field name="name">Pay Periods</field>
<field name="res_model">payroll.pay.period</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first pay period
</p>
<p>
Pay periods help you track payroll cycles. Configure your pay period settings
to automatically generate periods based on your schedule.
</p>
</field>
</record>
<!-- Pay Period Settings Action -->
<record id="action_payroll_pay_period_settings" model="ir.actions.act_window">
<field name="name">Pay Period Settings</field>
<field name="res_model">payroll.pay.period.settings</field>
<field name="view_mode">form</field>
<field name="target">current</field>
</record>
<!-- Server Action to Open Pay Period Settings (creates if not exists) -->
<record id="action_open_pay_period_settings" model="ir.actions.server">
<field name="name">Pay Period Settings</field>
<field name="model_id" ref="model_payroll_pay_period_settings"/>
<field name="state">code</field>
<field name="code">
settings = model.get_or_create_settings()
action = {
'type': 'ir.actions.act_window',
'name': 'Pay Period Settings',
'res_model': 'payroll.pay.period.settings',
'res_id': settings.id,
'view_mode': 'form',
'target': 'current',
}
</field>
</record>
</odoo>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- CHEQUE PRINT WIZARD VIEW -->
<!-- ============================================================ -->
<record id="payroll_cheque_print_wizard_form" model="ir.ui.view">
<field name="name">payroll.cheque.print.wizard.form</field>
<field name="model">payroll.cheque.print.wizard</field>
<field name="arch" type="xml">
<form string="Print Payroll Cheques">
<div class="alert alert-success mb-3" role="alert">
<i class="fa fa-check-circle me-2"/>
<strong>Payroll Submitted Successfully!</strong>
</div>
<group>
<group>
<field name="payslip_run_id" readonly="1"/>
<field name="cheque_count" readonly="1"/>
</group>
<group>
<field name="starting_cheque_number"
placeholder="Auto-generate"/>
</group>
</group>
<group string="Cheques to Print">
<field name="cheque_preview" nolabel="1" colspan="2"/>
</group>
<field name="cheque_ids" invisible="1"/>
<footer>
<button name="action_print_all" type="object"
string="Print Cheques" class="btn-primary"
icon="fa-print"/>
<button name="action_view_cheques" type="object"
string="View Cheques" class="btn-secondary"/>
<button name="action_skip_print" type="object"
string="Skip Printing" class="btn-link"/>
</footer>
</form>
</field>
</record>
<!-- Note: Payslip batch view extension moved to hr_payslip_views.xml -->
<!-- The cheque buttons can be added once the correct view ID is identified -->
<!-- ============================================================ -->
<!-- ADD CHEQUE MENU ITEMS -->
<!-- ============================================================ -->
<!-- Cheques menu under Fusion Payroll -->
<menuitem id="menu_fusion_cheques"
name="Cheques"
parent="menu_fusion_payroll_root"
action="action_payroll_cheque"
sequence="25"/>
<!-- Removed duplicate menu - use cheque_layout_settings_views.xml instead -->
</odoo>

View File

@@ -0,0 +1,301 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- PAYROLL CHEQUE VIEWS -->
<!-- ============================================================ -->
<!-- Cheque List View -->
<record id="payroll_cheque_view_list" model="ir.ui.view">
<field name="name">payroll.cheque.list</field>
<field name="model">payroll.cheque</field>
<field name="arch" type="xml">
<list string="Cheques" default_order="cheque_date desc, cheque_number desc">
<field name="cheque_number"/>
<field name="cheque_date"/>
<field name="employee_id"/>
<field name="amount" widget="monetary"/>
<field name="payslip_id" optional="show"/>
<field name="payslip_run_id" optional="show"/>
<field name="state" widget="badge"
decoration-info="state == 'draft'"
decoration-success="state == 'printed'"
decoration-warning="state == 'cashed'"
decoration-danger="state == 'voided'"/>
<field name="currency_id" column_invisible="1"/>
</list>
</field>
</record>
<!-- Cheque Form View -->
<record id="payroll_cheque_view_form" model="ir.ui.view">
<field name="name">payroll.cheque.form</field>
<field name="model">payroll.cheque</field>
<field name="arch" type="xml">
<form string="Cheque">
<header>
<button name="action_print_cheque" type="object" string="Print Cheque"
class="oe_highlight" invisible="state != 'draft'"/>
<button name="action_print_cheque" type="object" string="Reprint Cheque"
invisible="state not in ['printed', 'cashed']"/>
<button name="action_void" type="object" string="Void"
class="btn-secondary" invisible="state not in ['draft', 'printed']"/>
<button name="action_mark_cashed" type="object" string="Mark as Cashed"
invisible="state != 'printed'"/>
<button name="action_reset_to_draft" type="object" string="Reset to Draft"
invisible="state != 'voided'" groups="hr.group_hr_manager"/>
<field name="state" widget="statusbar" statusbar_visible="draft,printed,cashed"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_print_cheque" type="object" class="oe_stat_button" icon="fa-print">
<span>Print</span>
</button>
<button name="%(action_payroll_cheque)d" type="action" class="oe_stat_button" icon="fa-list">
<span>Cheques</span>
</button>
</div>
<!-- Status badge in top right -->
<div class="float-end" style="position: absolute; top: 10px; right: 20px; z-index: 10;">
<field name="state" widget="badge"
decoration-info="state == 'draft'"
decoration-success="state == 'printed'"
decoration-warning="state == 'cashed'"
decoration-danger="state == 'voided'"/>
</div>
<!-- Compact header with smaller text and spacing -->
<div style="margin-bottom: 16px;">
<div style="margin-bottom: 8px;">
<label for="employee_id" string="Employee" class="o_form_label" style="font-size: 12px; color: #666;"/>
<div style="margin-top: 4px;">
<field name="employee_id" readonly="1" style="font-size: 14px; font-weight: 500;"/>
</div>
</div>
<div style="display: flex; gap: 24px; margin-top: 12px;">
<div style="flex: 1;">
<label for="cheque_number" string="Cheque Number" class="o_form_label" style="font-size: 12px; color: #666;"/>
<div style="margin-top: 4px;">
<span invisible="not cheque_number" style="font-size: 12px; color: #999;">CHQ-</span>
<field name="cheque_number" placeholder="Draft" style="font-size: 14px; font-weight: 500;"/>
</div>
</div>
<div style="flex: 1;">
<label for="payment_method_display" string="Payment Method" class="o_form_label" style="font-size: 12px; color: #666;"/>
<div style="margin-top: 4px;">
<field name="payment_method_display" readonly="1" style="font-size: 14px; font-weight: 500;"/>
</div>
</div>
</div>
</div>
<group>
<group string="Cheque Details">
<field name="cheque_date"/>
<field name="employee_id"/>
<field name="amount" widget="monetary"/>
<field name="amount_in_words" readonly="1"/>
<field name="currency_id" invisible="1"/>
</group>
<group string="Payment Info">
<field name="payslip_id" readonly="1"/>
<field name="payslip_run_id" readonly="1"/>
<field name="bank_account_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
<group>
<group string="Payee Address">
<field name="payee_name"/>
<field name="payee_address"/>
</group>
<group string="Pay Period">
<field name="pay_period_start"/>
<field name="pay_period_end"/>
<field name="pay_period_display" readonly="1"/>
</group>
</group>
<group string="Memo">
<field name="memo" nolabel="1" colspan="2"/>
</group>
<group string="Void Information" invisible="state != 'voided'">
<field name="voided_date"/>
<field name="void_reason"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="activity_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
<!-- Cheque Search View -->
<record id="payroll_cheque_view_search" model="ir.ui.view">
<field name="name">payroll.cheque.search</field>
<field name="model">payroll.cheque</field>
<field name="arch" type="xml">
<search string="Search Cheques">
<field name="cheque_number"/>
<field name="employee_id"/>
<field name="payslip_id"/>
<field name="payslip_run_id"/>
<filter name="draft" string="Draft" domain="[('state', '=', 'draft')]"/>
<filter name="printed" string="Printed" domain="[('state', '=', 'printed')]"/>
<filter name="cashed" string="Cashed" domain="[('state', '=', 'cashed')]"/>
<filter name="voided" string="Voided" domain="[('state', '=', 'voided')]"/>
<filter name="group_employee" string="Employee" context="{'group_by': 'employee_id'}"/>
<filter name="group_batch" string="Payslip Batch" context="{'group_by': 'payslip_run_id'}"/>
<filter name="group_state" string="Status" context="{'group_by': 'state'}"/>
<filter name="group_date" string="Date" context="{'group_by': 'cheque_date:month'}"/>
</search>
</field>
</record>
<!-- Cheque Action -->
<record id="action_payroll_cheque" model="ir.actions.act_window">
<field name="name">Cheques</field>
<field name="res_model">payroll.cheque</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="payroll_cheque_view_search"/>
<field name="context">{'search_default_draft': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No cheques found
</p>
<p>
Cheques are created when you process payroll for employees with payment method set to "Cheque".
</p>
</field>
</record>
<!-- ============================================================ -->
<!-- CHEQUE VOID WIZARD VIEW -->
<!-- ============================================================ -->
<record id="payroll_cheque_void_wizard_form" model="ir.ui.view">
<field name="name">payroll.cheque.void.wizard.form</field>
<field name="model">payroll.cheque.void.wizard</field>
<field name="arch" type="xml">
<form string="Void Cheque">
<group>
<field name="cheque_id" readonly="1"/>
<field name="void_reason" placeholder="Enter reason for voiding this cheque..."/>
</group>
<footer>
<button name="action_void" type="object" string="Void Cheque" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- ============================================================ -->
<!-- CHEQUE LAYOUT VIEWS -->
<!-- ============================================================ -->
<record id="payroll_cheque_layout_view_form" model="ir.ui.view">
<field name="name">payroll.cheque.layout.form</field>
<field name="model">payroll.cheque.layout</field>
<field name="arch" type="xml">
<form string="Cheque Layout">
<sheet>
<group>
<group string="General">
<field name="name"/>
<field name="active"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group string="Page Settings">
<field name="page_width"/>
<field name="page_height"/>
<field name="cheque_height"/>
<field name="stub_height"/>
<field name="show_employer_copy"/>
</group>
</group>
<notebook>
<page string="Date Position">
<group>
<group>
<field name="date_x"/>
<field name="date_y"/>
</group>
<group>
<field name="date_format"/>
</group>
</group>
</page>
<page string="Amount Positions">
<group>
<group string="Numeric Amount">
<field name="amount_x"/>
<field name="amount_y"/>
</group>
<group string="Amount in Words">
<field name="amount_words_x"/>
<field name="amount_words_y"/>
</group>
</group>
</page>
<page string="Payee &amp; Memo">
<group>
<group string="Payee">
<field name="payee_x"/>
<field name="payee_y"/>
</group>
<group string="Memo">
<field name="memo_x"/>
<field name="memo_y"/>
</group>
</group>
<group>
<group string="Pay Period">
<field name="pay_period_x"/>
<field name="pay_period_y"/>
</group>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="payroll_cheque_layout_view_list" model="ir.ui.view">
<field name="name">payroll.cheque.layout.list</field>
<field name="model">payroll.cheque.layout</field>
<field name="arch" type="xml">
<list string="Cheque Layouts">
<field name="name"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="active"/>
</list>
</field>
</record>
<record id="action_payroll_cheque_layout" model="ir.actions.act_window">
<field name="name">Cheque Layouts</field>
<field name="res_model">payroll.cheque.layout</field>
<field name="view_mode">list,form</field>
</record>
<!-- ============================================================ -->
<!-- CHEQUE SEQUENCE -->
<!-- ============================================================ -->
<record id="seq_payroll_cheque" model="ir.sequence">
<field name="name">Payroll Cheque</field>
<field name="code">payroll.cheque</field>
<field name="prefix"></field>
<field name="padding">6</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
</record>
</odoo>

View File

@@ -0,0 +1,308 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Payroll Settings Form View -->
<record id="payroll_config_settings_view_form" model="ir.ui.view">
<field name="name">payroll.config.settings.form</field>
<field name="model">payroll.config.settings</field>
<field name="arch" type="xml">
<form string="Payroll Settings">
<sheet>
<div class="oe_button_box" name="button_box">
<field name="company_id" widget="res_company" options="{'no_create': True, 'no_open': True}"/>
</div>
<notebook>
<!-- General Tax Info -->
<page string="General Tax Info" name="general_tax">
<div class="alert alert-info" role="alert">
<p>Tell us about your business so we can report your payroll wages and taxes.
This is the info you used when you applied for a business number with the CRA.</p>
</div>
<group>
<group string="Company Legal Name">
<field name="company_legal_name" placeholder="e.g., Westin Healthcare Inc"/>
<div class="text-muted mt-2">
<small>This may be different than a trade or doing business as (DBA) name.</small>
</div>
</group>
</group>
<group string="Company Legal Address">
<group>
<field name="company_legal_street" placeholder="Street address"/>
<field name="company_legal_street2" placeholder="Apt, Suite, Unit (optional)"/>
<field name="company_legal_city" placeholder="City"/>
</group>
<group>
<field name="company_legal_country_id" placeholder="Country"/>
<field name="company_legal_state_id" placeholder="Province"/>
<field name="company_legal_zip" placeholder="Postal code"/>
</group>
</group>
</page>
<!-- Contact Information -->
<page string="Contact Information" name="contact_info">
<div class="alert alert-info" role="alert">
<p>Who's your payroll contact?</p>
<p>This information is required for payroll forms such as the Record of Employment (ROE) or the T4 Summary (T4SUM).
<a href="#" target="_blank">Learn more about different roles in payroll</a>.</p>
</div>
<group>
<group>
<field name="payroll_contact_first_name" placeholder="First name"/>
<field name="payroll_contact_last_name" placeholder="Last name"/>
</group>
<group>
<field name="payroll_contact_phone" placeholder="Business phone"/>
<field name="payroll_contact_email" placeholder="Email address"/>
</group>
</group>
</page>
<!-- Federal Tax Info -->
<page string="Federal Tax Info" name="federal_tax">
<div class="alert alert-info" role="alert">
<p>Once you have your tax info, you can correctly pay your federal taxes.
You can find what you need in letters and tax notices you have received from the CRA.</p>
</div>
<group string="CRA Payroll Number">
<group>
<label for="cra_business_number" string="CRA payroll number"/>
<div class="d-flex align-items-center gap-2">
<field name="cra_business_number" placeholder="Business Number"/>
<span class="text-muted">RP</span>
<field name="cra_reference_number" placeholder="Reference Number"/>
</div>
<div class="mt-2">
<a href="#" target="_blank">Don't have it?</a>
</div>
</group>
</group>
<group string="Social Insurance Numbers">
<group>
<field name="cra_owner1_sin" placeholder="SIN: Owner 1"/>
<field name="cra_owner2_sin" placeholder="SIN: Owner 2 (optional)"/>
<field name="cra_representative_rac" placeholder="Representative Identifier (RAC) - optional"/>
</group>
</group>
<group string="Tax Payment Frequency">
<group>
<label for="federal_tax_display" string="How often do you pay your taxes?"/>
<field name="federal_tax_display" readonly="1"/>
</group>
<group>
<field name="federal_tax_form_type" placeholder="e.g., Form PD7A"/>
<field name="federal_tax_payment_frequency"/>
<field name="federal_tax_effective_date"/>
</group>
</group>
</page>
<!-- Provincial Tax Info -->
<page string="Provincial Tax Info" name="provincial_tax">
<div class="alert alert-info" role="alert">
<p>We'll use this info to calculate and track your workers' compensation premiums based on where your employees work.
You can find it in the letters or emails you receive from the province.
<a href="#" target="_blank">Learn more</a>.</p>
</div>
<group>
<field name="provincial_tax_schedule_ids" nolabel="1" context="{'default_config_id': id}"/>
</group>
</page>
<!-- Work Locations -->
<page string="Work Locations" name="work_locations">
<group>
<field name="work_location_ids" nolabel="1"/>
</group>
</page>
<!-- Email Notifications -->
<page string="Email Notifications" name="email_notifications">
<group>
<group string="Primary Notification Recipients">
<field name="notification_email_primary_ids" widget="many2many_tags" options="{'no_create': True}"/>
</group>
</group>
<group string="Notification Preferences">
<group>
<field name="notification_setup_send_to" string="Setup notifications"/>
<field name="notification_form_filing_send_to" string="Form filing notifications"/>
<field name="notification_payday_send_to" string="Payday notifications"/>
</group>
<group>
<field name="notification_tax_send_to" string="Tax notifications"/>
<field name="notification_payday_reminders_send_to" string="Payday reminders"/>
<field name="notification_tax_setup_reminders_send_to" string="Tax setup reminders"/>
</group>
</group>
</page>
<!-- Bank Accounts -->
<page string="Bank Accounts" name="bank_accounts">
<group>
<group>
<field name="payroll_bank_account_id"
options="{'no_create': True, 'no_open': True}"
domain="[('company_id', '=', company_id)]"/>
<div class="mt-2">
<a href="#" target="_blank">Manage payroll principal officer information</a>
</div>
</group>
<group>
<field name="payroll_principal_officer_info" widget="text"/>
</group>
</group>
</page>
<!-- Printing -->
<page string="Printing" name="printing">
<div class="alert alert-info" role="alert">
<p>Choose your default printing preferences:</p>
</div>
<group>
<group>
<field name="print_preference" widget="radio"/>
<field name="paystub_layout"
invisible="print_preference != 'paycheques_and_stubs'"
widget="radio"/>
<div class="mt-2" invisible="print_preference != 'paycheques_and_stubs'">
<a href="#" target="_blank">Order cheques</a>
</div>
</group>
</group>
<group string="Vacation Display Options">
<group>
<field name="show_accrued_vacation_hours"/>
<field name="show_accrued_vacation_balance"/>
</group>
</group>
<div class="mt-3">
<button name="action_align_printer" string="Align my printer" type="object" class="btn-secondary"/>
</div>
<div class="mt-3">
<p>Need help? <a href="#" target="_blank">Check out guidance</a></p>
</div>
</page>
<!-- Direct Deposit -->
<page string="Direct Deposit" name="direct_deposit" invisible="1">
<group>
<group>
<field name="direct_deposit_funding_time" string="Funding time"/>
<field name="direct_deposit_funding_limit" string="Funding limit"/>
<field name="direct_deposit_funding_period_days" string="Funding period (days)"/>
</group>
</group>
</page>
<!-- Workers' Compensation -->
<page string="Workers' Compensation" name="workers_comp">
<div class="alert alert-info" role="alert">
<p>Add the details of your workers' comp insurance coverage.</p>
</div>
<group>
<group>
<field name="workers_comp_province"/>
<field name="workers_comp_class" placeholder="Workers' Comp Class"/>
<field name="workers_comp_account_number" placeholder="Account Number"/>
</group>
</group>
</page>
<!-- Accounting Preferences -->
<page string="Accounting" name="accounting" groups="account.group_account_readonly">
<div class="alert alert-info" role="alert">
<p>Choose how payroll transactions are mapped to your chart of accounts.</p>
</div>
<group>
<group string="Paycheque and Payroll Tax Payments">
<field name="account_bank_account_id"
options="{'no_create': True}"/>
<field name="account_wage_expense_id"
options="{'no_create': True}"/>
<field name="account_employer_tax_expense_id"
options="{'no_create': True}"
domain="[('account_type', 'in', ('expense', 'liability_current')), ('company_ids', 'parent_of', company_id)]"/>
</group>
<group string="Tax Liability Accounts">
<field name="account_federal_tax_liability_id"
options="{'no_create': True}"
domain="[('account_type', 'in', ('expense', 'liability_current')), ('company_ids', 'parent_of', company_id)]"/>
<field name="account_ontario_tax_liability_id"
options="{'no_create': True}"
domain="[('account_type', 'in', ('expense', 'liability_current')), ('company_ids', 'parent_of', company_id)]"/>
</group>
<group string="Other Liability and Assets">
<field name="account_vacation_pay_liability_id"
options="{'no_create': True}"
domain="[('account_type', 'in', ('expense', 'liability_current')), ('company_ids', 'parent_of', company_id)]"/>
</group>
</group>
<group string="Class Tracking">
<div class="alert alert-info" role="alert">
<p><strong>How do you want to track classes for payroll transactions in QuickBooks?</strong></p>
</div>
<field name="account_class_tracking" widget="radio" options="{'horizontal': true}"/>
</group>
<group string="Update Transactions" col="12">
<div class="alert alert-warning" role="alert" style="padding: 15px 20px; font-size: 14px; line-height: 1.5; width: 100%;">
<p style="margin: 0;">Update accounting preferences for past transactions according to current preference settings (we'll update all accounts except the Bank Account section).</p>
</div>
</group>
</page>
<!-- Auto Payroll -->
<page string="Auto Payroll" name="auto_payroll" invisible="1">
<div class="alert alert-warning" role="alert">
<p><strong>Currently ineligible.</strong></p>
<field name="auto_payroll_ineligibility_reason" readonly="1" nolabel="1"/>
<div class="mt-2">
<a href="#" target="_blank">Why am I ineligible?</a>
</div>
</div>
<group>
<field name="auto_payroll_enabled" readonly="1"/>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Payroll Settings List View -->
<record id="payroll_config_settings_view_tree" model="ir.ui.view">
<field name="name">payroll.config.settings.list</field>
<field name="model">payroll.config.settings</field>
<field name="arch" type="xml">
<list string="Payroll Settings">
<field name="company_id"/>
<field name="company_legal_name"/>
<field name="payroll_contact_email"/>
</list>
</field>
</record>
<!-- Payroll Settings Action - Server Action to get/create settings -->
<record id="action_payroll_config_settings" model="ir.actions.server">
<field name="name">Payroll Settings</field>
<field name="model_id" ref="model_payroll_config_settings"/>
<field name="state">code</field>
<field name="code">
settings = model.get_settings()
action = {
'type': 'ir.actions.act_window',
'name': 'Payroll Settings',
'res_model': 'payroll.config.settings',
'res_id': settings.id,
'view_mode': 'form',
'target': 'current',
}
</field>
</record>
</odoo>

View File

@@ -0,0 +1,254 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- FUSION PAYROLL DASHBOARD FORM VIEW -->
<!-- ============================================================ -->
<record id="fusion_payroll_dashboard_form" model="ir.ui.view">
<field name="name">fusion.payroll.dashboard.form</field>
<field name="model">fusion.payroll.dashboard</field>
<field name="arch" type="xml">
<form string="Fusion Payroll" create="0" edit="0" delete="0">
<field name="currency_id" invisible="1"/>
<field name="company_id" invisible="1"/>
<div class="o_fusion_payroll_dashboard">
<!-- ========== HEADER ========== -->
<div style="padding: 24px 32px; border-bottom: 1px solid var(--o-color-border);">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h1 style="margin: 0; font-size: 28px; font-weight: 600;">Fusion Payroll</h1>
<p style="margin: 4px 0 0 0; color: var(--o-color-text-muted);">Canadian Payroll Management</p>
</div>
<button name="action_run_payroll" type="object"
class="btn btn-primary btn-lg"
style="padding: 12px 32px; font-size: 16px;">
<i class="fa fa-play me-2"/> Run Payroll
</button>
</div>
</div>
<!-- ========== STATISTICS CARDS ========== -->
<div style="padding: 24px 32px;">
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 32px;">
<!-- Payroll This Month -->
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; padding: 24px; color: white;">
<div style="font-size: 13px; opacity: 0.9; text-transform: uppercase; letter-spacing: 1px;">Payroll This Month</div>
<div style="font-size: 32px; font-weight: 700; margin: 8px 0;">
<field name="payroll_this_month" widget="monetary" options="{'no_label': True}"/>
</div>
<div style="font-size: 13px; opacity: 0.8;">
<field name="payroll_count_this_month"/> payslips processed
</div>
</div>
<!-- Payroll YTD -->
<div style="background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%); border-radius: 12px; padding: 24px; color: white;">
<div style="font-size: 13px; opacity: 0.9; text-transform: uppercase; letter-spacing: 1px;">Payroll This Year</div>
<div style="font-size: 32px; font-weight: 700; margin: 8px 0;">
<field name="payroll_this_year" widget="monetary" options="{'no_label': True}"/>
</div>
<div style="font-size: 13px; opacity: 0.8;">
Year to date total
</div>
</div>
<!-- Active Employees -->
<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border-radius: 12px; padding: 24px; color: white;">
<div style="font-size: 13px; opacity: 0.9; text-transform: uppercase; letter-spacing: 1px;">Active Employees</div>
<div style="font-size: 32px; font-weight: 700; margin: 8px 0;">
<field name="active_employees"/>
</div>
<div style="font-size: 13px; opacity: 0.8;">
<field name="on_leave_employees"/> on leave
</div>
</div>
<!-- Average Pay -->
<div style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); border-radius: 12px; padding: 24px; color: white;">
<div style="font-size: 13px; opacity: 0.9; text-transform: uppercase; letter-spacing: 1px;">Avg Pay / Employee</div>
<div style="font-size: 32px; font-weight: 700; margin: 8px 0;">
<field name="avg_payroll_per_employee" widget="monetary" options="{'no_label': True}"/>
</div>
<div style="font-size: 13px; opacity: 0.8;">
This month
</div>
</div>
</div>
<!-- ========== QUICK ACTIONS ========== -->
<h3 style="margin: 0 0 16px 0; font-size: 18px; font-weight: 600;">Quick Actions</h3>
<div style="display: grid; grid-template-columns: repeat(6, 1fr); gap: 16px; margin-bottom: 32px;">
<!-- Run Payroll -->
<button name="action_run_payroll" type="object"
style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 20px; text-align: center; cursor: pointer; transition: all 0.2s;">
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;">
<i class="fa fa-play" style="font-size: 20px; color: white;"/>
</div>
<div style="font-weight: 600; font-size: 14px;">Run Payroll</div>
<div style="font-size: 12px; color: var(--o-color-text-muted); margin-top: 4px;">Process payments</div>
</button>
<!-- All Employees -->
<button name="action_view_employees" type="object"
style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 20px; text-align: center; cursor: pointer; transition: all 0.2s;">
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;">
<i class="fa fa-users" style="font-size: 20px; color: white;"/>
</div>
<div style="font-weight: 600; font-size: 14px;">Employees</div>
<div style="font-size: 12px; color: var(--o-color-text-muted); margin-top: 4px;"><field name="active_employees"/> active</div>
</button>
<!-- CRA Remittance -->
<button name="action_cra_remittance" type="object"
style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 20px; text-align: center; cursor: pointer; transition: all 0.2s;">
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;">
<i class="fa fa-bank" style="font-size: 20px; color: white;"/>
</div>
<div style="font-weight: 600; font-size: 14px;">CRA Remittance</div>
<div style="font-size: 12px; color: var(--o-color-text-muted); margin-top: 4px;">Tax payments</div>
</button>
<!-- T4 Slips -->
<button name="action_t4_slips" type="object"
style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 20px; text-align: center; cursor: pointer; transition: all 0.2s;">
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;">
<i class="fa fa-file-text-o" style="font-size: 20px; color: #333;"/>
</div>
<div style="font-weight: 600; font-size: 14px;">T4 Slips</div>
<div style="font-size: 12px; color: var(--o-color-text-muted); margin-top: 4px;">Tax statements</div>
</button>
<!-- ROE -->
<button name="action_roe" type="object"
style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 20px; text-align: center; cursor: pointer; transition: all 0.2s;">
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, #5ee7df 0%, #b490ca 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;">
<i class="fa fa-file-archive-o" style="font-size: 20px; color: white;"/>
</div>
<div style="font-weight: 600; font-size: 14px;">ROE</div>
<div style="font-size: 12px; color: var(--o-color-text-muted); margin-top: 4px;">Employment records</div>
</button>
<!-- Settings -->
<button name="action_settings" type="object"
style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 20px; text-align: center; cursor: pointer; transition: all 0.2s;">
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;">
<i class="fa fa-cog" style="font-size: 20px; color: white;"/>
</div>
<div style="font-weight: 600; font-size: 14px;">Settings</div>
<div style="font-size: 12px; color: var(--o-color-text-muted); margin-top: 4px;">Configuration</div>
</button>
</div>
<!-- ========== CHARTS SECTION ========== -->
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 24px;">
<!-- Payroll Trend Chart -->
<div style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 24px;">
<h4 style="margin: 0 0 16px 0; font-size: 16px; font-weight: 600;">Payroll Trend (Last 12 Months)</h4>
<div style="height: 300px;">
<!-- Embedded graph view -->
<field name="id" widget="fusion_payroll_chart" readonly="1"/>
</div>
</div>
<!-- Employee Distribution -->
<div style="background: var(--o-color-bg); border: 1px solid var(--o-color-border); border-radius: 12px; padding: 24px;">
<h4 style="margin: 0 0 16px 0; font-size: 16px; font-weight: 600;">Employee Status</h4>
<div style="display: flex; flex-direction: column; gap: 16px; padding-top: 16px;">
<!-- Active -->
<div style="display: flex; align-items: center; gap: 12px;">
<div style="width: 12px; height: 12px; border-radius: 50%; background: #22c55e;"/>
<div style="flex: 1;">Active</div>
<div style="font-weight: 600;"><field name="active_employees"/></div>
</div>
<!-- On Leave -->
<div style="display: flex; align-items: center; gap: 12px;">
<div style="width: 12px; height: 12px; border-radius: 50%; background: #f59e0b;"/>
<div style="flex: 1;">On Leave</div>
<div style="font-weight: 600;"><field name="on_leave_employees"/></div>
</div>
<!-- Terminated -->
<div style="display: flex; align-items: center; gap: 12px;">
<div style="width: 12px; height: 12px; border-radius: 50%; background: #ef4444;"/>
<div style="flex: 1;">Terminated</div>
<div style="font-weight: 600;"><field name="terminated_employees"/></div>
</div>
<div style="border-top: 1px solid var(--o-color-border); padding-top: 16px; margin-top: 8px;">
<div style="display: flex; align-items: center; gap: 12px;">
<div style="width: 12px; height: 12px; border-radius: 50%; background: #6366f1;"/>
<div style="flex: 1; font-weight: 600;">Total</div>
<div style="font-weight: 700; font-size: 18px;"><field name="total_employees"/></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</field>
</record>
<!-- ============================================================ -->
<!-- PAYROLL STATS GRAPH VIEW -->
<!-- ============================================================ -->
<record id="fusion_payroll_stats_graph" model="ir.ui.view">
<field name="name">fusion.payroll.stats.graph</field>
<field name="model">fusion.payroll.stats</field>
<field name="arch" type="xml">
<graph string="Payroll Trend" type="bar">
<field name="name" type="col"/>
<field name="total_payroll" type="measure"/>
</graph>
</field>
</record>
<record id="fusion_payroll_stats_pivot" model="ir.ui.view">
<field name="name">fusion.payroll.stats.pivot</field>
<field name="model">fusion.payroll.stats</field>
<field name="arch" type="xml">
<pivot string="Payroll Analysis">
<field name="year" type="row"/>
<field name="month_name" type="col"/>
<field name="total_payroll" type="measure"/>
<field name="employee_count" type="measure"/>
</pivot>
</field>
</record>
<!-- ============================================================ -->
<!-- DASHBOARD ACTION -->
<!-- ============================================================ -->
<record id="action_fusion_payroll_dashboard_new" model="ir.actions.server">
<field name="name">Fusion Payroll Dashboard</field>
<field name="model_id" ref="model_fusion_payroll_dashboard"/>
<field name="state">code</field>
<field name="code">
action = model.action_open_dashboard()
</field>
</record>
<!-- Stats Graph Action -->
<record id="action_payroll_stats_graph" model="ir.actions.act_window">
<field name="name">Payroll Trend</field>
<field name="res_model">fusion.payroll.stats</field>
<field name="view_mode">graph,pivot,list</field>
<field name="domain">[('company_id', '=', active_id)]</field>
</record>
</odoo>

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- PAYCHEQUE REPORTS -->
<!-- ============================================================ -->
<!-- Paycheque History Action -->
<record id="action_payroll_report_paycheque_history" model="ir.actions.client">
<field name="name">Paycheque History</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.paycheque.history'}</field>
</record>
<!-- Payroll Details Action -->
<record id="action_payroll_report_payroll_details" model="ir.actions.client">
<field name="name">Payroll Details</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.payroll.details'}</field>
</record>
<!-- ============================================================ -->
<!-- TAX REPORTS -->
<!-- ============================================================ -->
<!-- Payroll Tax Liability Action -->
<record id="action_payroll_report_tax_liability" model="ir.actions.client">
<field name="name">Payroll Tax Liability</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.tax.liability'}</field>
</record>
<!-- Payroll Tax Payments Action -->
<record id="action_payroll_report_tax_payments" model="ir.actions.client">
<field name="name">Payroll Tax Payments</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.tax.payments'}</field>
</record>
<!-- Payroll Tax and Wage Summary Action -->
<record id="action_payroll_report_tax_wage_summary" model="ir.actions.client">
<field name="name">Payroll Tax and Wage Summary</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.tax.wage.summary'}</field>
</record>
<!-- ============================================================ -->
<!-- SUMMARY REPORTS -->
<!-- ============================================================ -->
<!-- Payroll Summary Action -->
<record id="action_payroll_report_summary" model="ir.actions.client">
<field name="name">Payroll Summary</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.summary'}</field>
</record>
<!-- Payroll Summary by Employee Action -->
<record id="action_payroll_report_summary_employee" model="ir.actions.client">
<field name="name">Payroll Summary by Employee</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.summary.by.employee'}</field>
</record>
<!-- ============================================================ -->
<!-- EMPLOYEE REPORTS -->
<!-- ============================================================ -->
<!-- Employee Directory / Payroll Item List Action -->
<record id="action_payroll_report_employee_directory" model="ir.actions.client">
<field name="name">Payroll Item List</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.employee.directory'}</field>
</record>
<!-- Time Off Report Action -->
<record id="action_payroll_report_time_off" model="ir.actions.client">
<field name="name">Time Off</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.time.off'}</field>
</record>
<!-- ============================================================ -->
<!-- COST REPORTS -->
<!-- ============================================================ -->
<!-- Total Pay Action -->
<record id="action_payroll_report_total_pay" model="ir.actions.client">
<field name="name">Total Pay</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.total.pay'}</field>
</record>
<!-- Total Payroll Cost Action -->
<record id="action_payroll_report_total_cost" model="ir.actions.client">
<field name="name">Total Payroll Cost</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.total.cost'}</field>
</record>
<!-- Deductions and Contributions Action -->
<record id="action_payroll_report_deductions" model="ir.actions.client">
<field name="name">Deductions and Contributions</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.deductions'}</field>
</record>
<!-- ============================================================ -->
<!-- COMPLIANCE REPORTS -->
<!-- ============================================================ -->
<!-- Workers' Compensation Action -->
<record id="action_payroll_report_workers_comp" model="ir.actions.client">
<field name="name">Workers' Compensation</field>
<field name="tag">fusion_payroll.payroll_report_action</field>
<field name="context">{'report_model': 'payroll.report.workers.comp'}</field>
</record>
</odoo>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Tax Payment Schedule List View -->
<record id="payroll_tax_payment_schedule_view_list" model="ir.ui.view">
<field name="name">payroll.tax.payment.schedule.list</field>
<field name="model">payroll.tax.payment.schedule</field>
<field name="arch" type="xml">
<list string="Payment Schedules" editable="bottom">
<field name="province"/>
<field name="payment_frequency"/>
<field name="effective_date"/>
<field name="form_type"/>
<field name="is_current" readonly="1"/>
</list>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Work Location Form View -->
<record id="payroll_work_location_view_form" model="ir.ui.view">
<field name="name">payroll.work.location.form</field>
<field name="model">payroll.work.location</field>
<field name="arch" type="xml">
<form string="Work Location">
<header>
<field name="status" widget="statusbar" statusbar_visible="active,inactive"/>
</header>
<sheet>
<group>
<group>
<field name="name" placeholder="Location name"/>
<field name="company_id" invisible="1"/>
<field name="is_primary"/>
</group>
<group>
<field name="employee_count" readonly="1"/>
</group>
</group>
<group string="Address">
<group>
<field name="street" placeholder="Street address"/>
<field name="street2" placeholder="Apt, Suite, Unit (optional)"/>
<field name="city" placeholder="City"/>
</group>
<group>
<field name="state_id" placeholder="Province"/>
<field name="zip" placeholder="Postal code"/>
<field name="country_id" placeholder="Country"/>
</group>
</group>
<group string="Employees">
<field name="employee_ids" widget="many2many_tags"
options="{'color_field': 'employment_status'}"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Work Location List View -->
<record id="payroll_work_location_view_tree" model="ir.ui.view">
<field name="name">payroll.work.location.list</field>
<field name="model">payroll.work.location</field>
<field name="arch" type="xml">
<list string="Work Locations">
<field name="name"/>
<field name="street"/>
<field name="city"/>
<field name="state_id"/>
<field name="zip"/>
<field name="employee_count" string="Employees Assigned"/>
<field name="status"/>
<field name="is_primary" widget="boolean_toggle"/>
</list>
</field>
</record>
<!-- Work Location Kanban View -->
<record id="payroll_work_location_view_kanban" model="ir.ui.view">
<field name="name">payroll.work.location.kanban</field>
<field name="model">payroll.work.location</field>
<field name="arch" type="xml">
<kanban default_order="is_primary desc, name">
<field name="name"/>
<field name="is_primary"/>
<field name="employee_count"/>
<field name="status"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_card oe_kanban_global_click">
<div class="oe_kanban_content">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong>
<span class="badge badge-pill text-bg-primary"
t-if="record.is_primary.raw_value">PRIMARY</span>
</div>
</div>
<div class="o_kanban_record_body">
<div>
<field name="street"/>
<field name="city"/>
<field name="state_id"/>
<field name="zip"/>
</div>
<div class="mt-2">
<span><field name="employee_count"/> employees</span>
</div>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- Work Location Action -->
<record id="action_payroll_work_location" model="ir.actions.act_window">
<field name="name">Work Locations</field>
<field name="res_model">payroll.work.location</field>
<field name="view_mode">kanban,list,form</field>
<field name="context">{}</field>
</record>
</odoo>

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- PDF Field Position List View -->
<record id="pdf_field_position_view_tree" model="ir.ui.view">
<field name="name">pdf.field.position.list</field>
<field name="model">pdf.field.position</field>
<field name="arch" type="xml">
<list string="PDF Field Positions" default_order="template_type,sequence,field_name">
<field name="template_type"/>
<field name="field_name"/>
<field name="field_label"/>
<field name="x_position"/>
<field name="y_position"/>
<field name="font_size"/>
<field name="font_name"/>
<field name="active" widget="boolean_toggle"/>
<field name="sequence" widget="handle"/>
</list>
</field>
</record>
<!-- PDF Field Position Form View -->
<record id="pdf_field_position_view_form" model="ir.ui.view">
<field name="name">pdf.field.position.form</field>
<field name="model">pdf.field.position</field>
<field name="arch" type="xml">
<form string="PDF Field Position">
<header>
<field name="active" widget="boolean_toggle"/>
</header>
<sheet>
<group>
<group>
<field name="template_type" required="1"/>
<field name="field_name" required="1"
placeholder="e.g., EmployeeLastName, SIN, Box14"/>
<field name="field_label"
placeholder="Human-readable label (optional)"/>
</group>
<group>
<field name="sequence" widget="handle"/>
</group>
</group>
<group string="Position" col="4">
<group>
<field name="x_position" required="1"/>
<div class="text-muted mt-2">
<small>X coordinate in points (1 point = 1/72 inch)</small>
</div>
</group>
<group>
<field name="y_position" required="1"/>
<div class="text-muted mt-2">
<small>Y coordinate in points (origin at bottom-left)</small>
</div>
</group>
<group>
<field name="font_size" required="1"/>
<div class="text-muted mt-2">
<small>Font size in points (default: 10)</small>
</div>
</group>
<group>
<field name="font_name" required="1"/>
<div class="text-muted mt-2">
<small>Font family (e.g., Helvetica, Times-Roman)</small>
</div>
</group>
</group>
<div class="alert alert-info" role="alert">
<p><strong>Coordinate System:</strong></p>
<ul>
<li>Origin (0, 0) is at the <strong>bottom-left</strong> corner of the page</li>
<li>Units are in <strong>points</strong> (1 point = 1/72 inch)</li>
<li>Standard letter size: 612 x 792 points (8.5" x 11")</li>
<li>X increases to the right, Y increases upward</li>
</ul>
<p class="mt-2"><strong>Field Name:</strong> Must match the field identifier used in PDF field mapping (e.g., EmployeeLastName, SIN, Box14, PayerName)</p>
</div>
</sheet>
</form>
</field>
</record>
<!-- PDF Field Position Search View -->
<record id="pdf_field_position_view_search" model="ir.ui.view">
<field name="name">pdf.field.position.search</field>
<field name="model">pdf.field.position</field>
<field name="arch" type="xml">
<search>
<field name="template_type"/>
<field name="field_name"/>
</search>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,483 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Payroll Entry Edit Form (Edit Paycheque Dialog - Clean Table Layout) -->
<record id="payroll_entry_edit_form" model="ir.ui.view">
<field name="name">payroll.entry.edit.form</field>
<field name="model">payroll.entry</field>
<field name="arch" type="xml">
<form string="Edit Paycheque">
<field name="currency_id" invisible="1"/>
<field name="wizard_id" invisible="1"/>
<sheet>
<!-- HEADER -->
<div class="o_form_sheet_bg" style="margin: -24px; margin-bottom: 16px; padding: 24px; background: var(--o-view-background-color);">
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
<div>
<span class="text-muted" style="font-size: 12px;">PAY TO</span>
<h2 style="margin: 4px 0 0 0;"><field name="employee_id" readonly="1" options="{'no_open': True}"/></h2>
</div>
<div style="display: flex; gap: 48px;">
<div>
<div class="text-muted" style="font-size: 12px;">Pay Date</div>
<div><field name="pay_date" readonly="1"/></div>
<div class="text-muted mt-2" style="font-size: 12px;">Paid From</div>
<div><field name="paid_from" readonly="1"/></div>
</div>
<div>
<div class="text-muted" style="font-size: 12px;">Pay Period</div>
<div><field name="pay_period_display" readonly="1"/></div>
<div class="text-muted mt-2" style="font-size: 12px;">Paid By</div>
<div><field name="payment_method"/></div>
</div>
<div style="text-align: right;">
<div class="text-muted" style="font-size: 12px;">NET PAY</div>
<h1 style="color: #28a745; margin: 0;"><field name="net_pay" widget="monetary"/></h1>
</div>
</div>
</div>
</div>
<!-- PAY SECTION -->
<h4 style="border-bottom: 2px solid var(--o-color-border); padding-bottom: 8px; margin-top: 24px;">PAY</h4>
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 8px 0; font-weight: bold; border-bottom: 1px solid var(--o-color-border);">
<div>TYPE</div>
<div style="text-align: right;">Hours</div>
<div style="text-align: right;">Rate</div>
<div style="text-align: right;">Current</div>
<div style="text-align: right;">YTD</div>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Regular Pay</div>
<div style="text-align: right;"><field name="regular_hours"/></div>
<div style="text-align: right;"><field name="hourly_rate" readonly="1" widget="monetary"/></div>
<div style="text-align: right;"><field name="regular_pay" readonly="1" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="regular_pay" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Vacation Pay</div>
<div style="text-align: right; opacity: 0.6;">-</div>
<div style="text-align: right;"><field name="vacation_pay_percent" readonly="1"/> %</div>
<div style="text-align: right;"><field name="vacation_pay" readonly="1" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="vacation_pay" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Stat Holiday Pay</div>
<div style="text-align: right;"><field name="stat_holiday_hours"/></div>
<div style="text-align: right;"><field name="hourly_rate" readonly="1" widget="monetary"/></div>
<div style="text-align: right;"><field name="stat_holiday_pay" readonly="1" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="stat_holiday_pay" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Stat pay - average daily wage</div>
<div style="text-align: right; opacity: 0.6;">-</div>
<div style="text-align: right; opacity: 0.6;">-</div>
<div style="text-align: right;"><field name="stat_pay_avg_daily_wage" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;">$ 0.00</div>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center; font-weight: bold; border-top: 1px solid var(--o-color-border); margin-top: 8px;">
<div>Total</div>
<div style="text-align: right;"><field name="total_hours" readonly="1"/></div>
<div></div>
<div style="text-align: right;"><field name="gross_pay" readonly="1" widget="monetary"/></div>
<div style="text-align: right;"><field name="gross_pay" readonly="1" widget="monetary"/></div>
</div>
<!-- EMPLOYEE TAXES SECTION -->
<h4 style="border-bottom: 2px solid var(--o-color-border); padding-bottom: 8px; margin-top: 32px;">EMPLOYEE TAXES</h4>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 8px 0; font-weight: bold; border-bottom: 1px solid var(--o-color-border);">
<div>TYPE</div>
<div style="text-align: right;">Current</div>
<div style="text-align: right;">YTD</div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Income Tax</div>
<div style="text-align: right;"><field name="income_tax" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="income_tax" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Employment Insurance</div>
<div style="text-align: right;"><field name="employment_insurance" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="employment_insurance" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Canada Pension Plan</div>
<div style="text-align: right;"><field name="cpp" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="cpp" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Second Canada Pension Plan</div>
<div style="text-align: right;"><field name="cpp2" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="cpp2" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center; font-weight: bold; border-top: 1px solid var(--o-color-border); margin-top: 8px;">
<div>Total</div>
<div style="text-align: right;"><field name="total_employee_tax" readonly="1" widget="monetary"/></div>
<div style="text-align: right;"><field name="total_employee_tax" readonly="1" widget="monetary"/></div>
</div>
<!-- EMPLOYER TAXES SECTION -->
<h4 style="border-bottom: 2px solid var(--o-color-border); padding-bottom: 8px; margin-top: 32px;">EMPLOYER TAXES</h4>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 8px 0; font-weight: bold; border-bottom: 1px solid var(--o-color-border);">
<div>TYPE</div>
<div style="text-align: right;">Current</div>
<div style="text-align: right;">YTD</div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Employment Insurance Employer</div>
<div style="text-align: right;"><field name="employer_ei" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="employer_ei" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Canada Pension Plan Employer</div>
<div style="text-align: right;"><field name="employer_cpp" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="employer_cpp" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Second Canada Pension Plan Employer</div>
<div style="text-align: right;"><field name="employer_cpp2" widget="monetary"/></div>
<div style="text-align: right; opacity: 0.6;"><field name="employer_cpp2" readonly="1" widget="monetary"/></div>
</div>
<div style="display: grid; grid-template-columns: 3fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center; font-weight: bold; border-top: 1px solid var(--o-color-border); margin-top: 8px;">
<div>Total</div>
<div style="text-align: right;"><field name="total_employer_tax" readonly="1" widget="monetary"/></div>
<div style="text-align: right;"><field name="total_employer_tax" readonly="1" widget="monetary"/></div>
</div>
<!-- TIME OFF SECTION -->
<h4 style="border-bottom: 2px solid var(--o-color-border); padding-bottom: 8px; margin-top: 32px;">TIME OFF</h4>
<div style="display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 8px 0; font-weight: bold; border-bottom: 1px solid var(--o-color-border); font-size: 12px;">
<div></div>
<div style="text-align: right;">Hours accrued</div>
<div style="text-align: right;">Hours used</div>
<div style="text-align: right;">Hours available</div>
<div style="text-align: right;">Amount accrued</div>
<div style="text-align: right;">Amount used</div>
<div style="text-align: right;">Amount available</div>
</div>
<div style="display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 12px 0; align-items: center;">
<div>Vacation</div>
<div style="text-align: right;"><field name="vacation_hours_accrued"/></div>
<div style="text-align: right;"><field name="vacation_hours_used"/></div>
<div style="text-align: right;"><field name="vacation_hours_available" readonly="1"/></div>
<div style="text-align: right;"><field name="vacation_amount_accrued" readonly="1" widget="monetary"/></div>
<div style="text-align: right;"><field name="vacation_amount_used" widget="monetary"/></div>
<div style="text-align: right;"><field name="vacation_amount_available" readonly="1" widget="monetary"/></div>
</div>
<!-- MEMO -->
<h4 style="border-bottom: 2px solid var(--o-color-border); padding-bottom: 8px; margin-top: 32px;">MEMO</h4>
<field name="memo" placeholder="Add a memo..." style="width: 100%; min-height: 60px;"/>
</sheet>
<footer>
<button string="Save" type="object" name="action_save_entry" class="btn-primary"/>
<button string="Close" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- Run Payroll Wizard Form View (QuickBooks-like with Entry and Preview states) -->
<record id="run_payroll_wizard_view_form" model="ir.ui.view">
<field name="name">run.payroll.wizard.form</field>
<field name="model">run.payroll.wizard</field>
<field name="arch" type="xml">
<form string="Run Payroll" create="0" edit="1" delete="0">
<field name="state" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="pay_schedule" invisible="1"/>
<field name="currency_id" invisible="1"/>
<field name="payslip_run_id" invisible="1"/>
<field name="available_period_ids" invisible="1"/>
<field name="display_name" invisible="1"/>
<sheet>
<!-- Page Title -->
<div class="oe_title mb-4">
<h1>
<span invisible="state != 'entry'">Run Payroll</span>
<span invisible="state != 'preview'">Preview Payroll</span>
</h1>
</div>
<!-- ============ ENTRY STATE ============ -->
<div invisible="state != 'entry'">
<!-- Header: Pay Period and Pay Date -->
<div style="display: flex; gap: 32px; margin-bottom: 24px; align-items: flex-end;">
<div>
<div class="text-muted" style="font-size: 12px; margin-bottom: 4px;">Pay period</div>
<field name="pay_period_id"
options="{'no_create': True, 'no_open': True}"
placeholder="Select pay period..."
style="min-width: 200px;"/>
</div>
<div>
<div class="text-muted" style="font-size: 12px; margin-bottom: 4px;">Pay date</div>
<field name="pay_date"/>
</div>
<div style="flex: 1;"></div>
<button name="action_load_attendance"
type="object"
string="Load Attendance Hours"
class="btn btn-outline-secondary"
icon="fa-clock-o"/>
</div>
<!-- Add Employee Button -->
<div style="margin-bottom: 16px;">
<button name="action_add_employee"
type="object"
string="+ Add an employee"
class="btn btn-link"
style="padding-left: 0;"/>
</div>
<!-- Employee Payroll Grid -->
<field name="entry_ids" nolabel="1">
<list editable="bottom" decoration-muted="regular_hours == 0">
<field name="employee_id" readonly="1"/>
<field name="employee_type" readonly="1" string=""/>
<field name="has_previous_payroll" column_invisible="1"/>
<field name="previous_payroll_amount" column_invisible="1"/>
<field name="previous_payroll_date" column_invisible="1"/>
<field name="regular_hours" string="Regular pay"/>
<field name="vacation_pay_percent" string="Vacation pay" readonly="1"/>
<field name="stat_holiday_hours" string="Stat holiday pay"/>
<field name="stat_pay_avg_daily_wage" string="Stat pay - aver..."/>
<field name="total_hours" string="Total hrs" readonly="1"/>
<field name="gross_pay" string="Gross pay" readonly="1"/>
<field name="net_pay" string="Net pay" readonly="1"/>
<field name="memo"/>
<field name="payment_method" string="Pay method"/>
<button name="action_open_edit_paycheque"
type="object"
icon="fa-ellipsis-v"
title="Edit paycheque"/>
</list>
</field>
<!-- Summary Footer -->
<div style="display: flex; padding: 16px 0; margin-top: 16px; border-top: 1px solid var(--o-color-border); font-weight: bold;">
<div style="width: 120px;">Total</div>
<div style="flex: 1;"></div>
<div style="width: 100px; text-align: right;">
<field name="total_regular_hours" readonly="1"/> hrs
</div>
<div style="flex: 1;"></div>
<div style="width: 120px; text-align: right;">
<field name="total_gross_pay" widget="monetary" readonly="1"/>
</div>
</div>
<!-- Action Buttons for Entry State -->
<div style="display: flex; justify-content: flex-end; gap: 12px; padding: 24px 0; margin-top: 24px; border-top: 1px solid var(--o-color-border);">
<button string="Cancel" class="btn btn-link" special="cancel"/>
<button name="action_save_for_later"
string="Save for later"
type="object"
class="btn btn-secondary"/>
<button name="action_preview_payroll"
string="Preview payroll"
type="object"
class="btn btn-primary"/>
</div>
</div>
<!-- ============ PREVIEW STATE ============ -->
<div invisible="state != 'preview'">
<!-- TOTAL PAYROLL COST Summary Box -->
<div style="display: flex; gap: 48px; margin-bottom: 32px; padding: 24px; border: 1px solid var(--o-color-border); border-radius: 8px; background: var(--o-view-background-color);">
<!-- Left: Total Cost -->
<div style="min-width: 220px;">
<div class="text-muted" style="font-size: 12px; margin-bottom: 4px;">TOTAL PAYROLL COST</div>
<h1 style="margin: 0 0 8px 0;"><field name="total_payroll_cost" widget="monetary" readonly="1"/></h1>
<div style="font-size: 13px;">
<span class="text-success" invisible="change_from_last &lt;= 0">
<i class="fa fa-arrow-up"/> Up <field name="change_from_last" readonly="1"/>% compared to last time
</span>
<span class="text-danger" invisible="change_from_last &gt;= 0">
<i class="fa fa-arrow-down"/> Down <field name="change_from_last" readonly="1"/>% compared to last time
</span>
</div>
<div style="margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--o-color-border);">
<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
<span class="text-muted">Gross pay</span>
<field name="total_gross_pay" widget="monetary" readonly="1"/>
</div>
<div style="display: flex; justify-content: space-between;">
<span class="text-muted">Employer taxes &amp; contributions</span>
<field name="total_employer_taxes" widget="monetary" readonly="1"/>
</div>
</div>
</div>
<!-- Right: Account Selection & Pay Details -->
<div style="flex: 1;">
<div style="margin-bottom: 16px;">
<div class="text-muted" style="font-size: 12px; margin-bottom: 4px;">Funding account</div>
<field name="bank_account_id"
options="{'no_create': True}"
placeholder="Select bank account..."
style="min-width: 250px;"/>
</div>
<field name="date_start" invisible="1"/>
<field name="date_end" invisible="1"/>
<div style="display: flex; gap: 48px;">
<div>
<div class="text-muted" style="font-size: 12px;">Pay period:</div>
<div><field name="period_display" readonly="1"/></div>
</div>
<div>
<div class="text-muted" style="font-size: 12px;">Pay date:</div>
<div><field name="pay_date" readonly="1"/></div>
</div>
</div>
</div>
</div>
<!-- Preview Employee Summary Grid -->
<field name="entry_ids" nolabel="1" readonly="1">
<list decoration-muted="regular_hours == 0">
<field name="employee_id" string="Name"/>
<field name="employee_type" string="" column_invisible="1"/>
<field name="total_hours" string="Total hours"/>
<field name="gross_pay" string="Gross pay"/>
<field name="total_employee_tax" string="Employee taxes &amp; deductions"/>
<field name="net_pay" string="Net pay"/>
<field name="total_employer_tax" string="Employer taxes &amp; contributions"/>
<field name="change_from_last_payroll" string="Change in gross pay"/>
<field name="memo" string="Memo"/>
</list>
</field>
<!-- Totals Row -->
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 12px 0; font-weight: bold; border-top: 1px solid var(--o-color-border); margin-top: 8px;">
<div>Total</div>
<div style="text-align: right;"><field name="total_hours" readonly="1"/>h</div>
<div style="text-align: right;"><field name="total_gross_pay" widget="monetary" readonly="1"/></div>
<div style="text-align: right;"><field name="total_employee_taxes" widget="monetary" readonly="1"/></div>
<div style="text-align: right;"><field name="total_net_pay" widget="monetary" readonly="1"/></div>
<div style="text-align: right;"><field name="total_employer_taxes" widget="monetary" readonly="1"/></div>
<div></div>
<div></div>
</div>
<!-- Action Buttons for Preview State -->
<div style="display: flex; justify-content: space-between; gap: 12px; padding: 24px 0; margin-top: 24px; border-top: 1px solid var(--o-color-border);">
<button name="action_back_to_entry"
string="Back"
type="object"
class="btn btn-link"/>
<div style="display: flex; gap: 12px;">
<button name="action_submit_payroll"
string="Submit payroll"
type="object"
class="btn btn-primary"/>
</div>
</div>
</div>
</sheet>
</form>
</field>
</record>
<!-- Pay Period Tree View -->
<record id="payroll_pay_period_tree" model="ir.ui.view">
<field name="name">payroll.pay.period.tree</field>
<field name="model">payroll.pay.period</field>
<field name="arch" type="xml">
<list>
<field name="display_name"/>
<field name="schedule_type"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="pay_date"/>
<field name="state" widget="badge"
decoration-info="state == 'draft'"
decoration-warning="state == 'in_progress'"
decoration-success="state == 'paid'"/>
</list>
</field>
</record>
<!-- Pay Period Form View -->
<record id="payroll_pay_period_form" model="ir.ui.view">
<field name="name">payroll.pay.period.form</field>
<field name="model">payroll.pay.period</field>
<field name="arch" type="xml">
<form>
<header>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<group>
<group>
<field name="company_id"/>
<field name="schedule_type"/>
</group>
<group>
<field name="date_start"/>
<field name="date_end"/>
<field name="pay_date"/>
</group>
</group>
<group>
<field name="payslip_run_id"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Pay Period Settings Form View -->
<record id="payroll_pay_period_settings_form" model="ir.ui.view">
<field name="name">payroll.pay.period.settings.form</field>
<field name="model">payroll.pay.period.settings</field>
<field name="arch" type="xml">
<form>
<sheet>
<group string="Pay Period Configuration">
<group>
<field name="company_id" invisible="1"/>
<field name="schedule_type"/>
<field name="first_period_start"/>
</group>
<group>
<field name="pay_day_offset"/>
<field name="auto_generate_periods"/>
<field name="periods_to_generate" invisible="not auto_generate_periods"/>
</group>
</group>
<footer>
<button name="action_generate_periods"
type="object"
string="Generate Periods"
class="btn-primary"/>
</footer>
</sheet>
</form>
</field>
</record>
<!-- Run Payroll Wizard Action (opens in full page with breadcrumbs) -->
<record id="action_run_payroll_wizard" model="ir.actions.act_window">
<field name="name">Run Payroll</field>
<field name="res_model">run.payroll.wizard</field>
<field name="view_mode">form</field>
<field name="target">current</field>
<field name="context">{'form_view_ref': 'fusion_payroll.run_payroll_wizard_view_form'}</field>
</record>
<!-- Server Action to Open Run Payroll with Pre-loaded Data -->
<record id="action_open_run_payroll" model="ir.actions.server">
<field name="name">Run Payroll</field>
<field name="model_id" ref="model_run_payroll_wizard"/>
<field name="state">code</field>
<field name="code">
action = model.action_open_run_payroll()
</field>
</record>
</odoo>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Tax Yearly Rates Tree View -->
<record id="tax_rates_tree_view" model="ir.ui.view">
<field name="name">tax.rates.tree.view</field>
<field name="model">tax.yearly.rates</field>
<field name="priority">16</field>
<field name="arch" type="xml">
<list string="Tax Lines">
<field name="fiscal_year"/>
<field name="tax_type"/>
<field name="ded_type"/>
</list>
</field>
</record>
<!-- Tax Yearly Rates Form View -->
<record id="tax_rates_form_view" model="ir.ui.view">
<field name="name">tax.rates.form.view</field>
<field name="model">tax.yearly.rates</field>
<field name="priority">16</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="fiscal_year" required="1"/>
<!-- Canada Pension Plan Section -->
<group name="Canada Pension Plan">
<field name="ded_type" invisible="ded_type not in ['cpp']"/>
<group name="CPP" invisible="ded_type not in ['cpp']">
<separator string="Canadian Pension Plan"/>
<field name="emp_contribution_rate"/>
<field name="employer_contribution_rate"/>
<field name="exemption"/>
<field name="max_cpp"/>
</group>
</group>
<!-- Employment Insurance Section -->
<group name="ei">
<field name="ded_type" invisible="ded_type not in ['ei']"/>
<group name="emp_ins" invisible="ded_type not in ['ei']">
<separator string="Employment Insurance"/>
<field name="ei_earnings"/>
<field name="emp_ei_amount"/>
<field name="employer_ei_amount"/>
<field name="ei_rate"/>
</group>
</group>
<!-- Tax Brackets Section -->
<group name="test">
<group name="testing" invisible="not tax_type">
<separator string="Taxes"/>
<field name="tax_type"/>
<field name="tax_yearly_rate_ids">
<list editable="bottom">
<field name="tax_bracket" required="1"/>
<field name="tax_rate" required="1"/>
<field name="tax_constant" required="1"/>
</list>
</field>
<field name="canada_emp_amount" required="1"
invisible="tax_type not in ['federal'] and ded_type not in ['cpp','ei']"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- Actions and Menus moved to fusion_payroll_menus.xml -->
</odoo>