Initial commit
This commit is contained in:
131
fusion_payroll/models/payroll_tax_payment_schedule.py
Normal file
131
fusion_payroll/models/payroll_tax_payment_schedule.py
Normal file
@@ -0,0 +1,131 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
from datetime import date
|
||||
|
||||
|
||||
class PayrollTaxPaymentSchedule(models.Model):
|
||||
"""
|
||||
Tax Payment Schedule
|
||||
Date-effective payment schedules for provincial taxes.
|
||||
"""
|
||||
_name = 'payroll.tax.payment.schedule'
|
||||
_description = 'Tax Payment Schedule'
|
||||
_order = 'province, effective_date desc'
|
||||
|
||||
config_id = fields.Many2one(
|
||||
'payroll.config.settings',
|
||||
string='Payroll Settings',
|
||||
required=True,
|
||||
ondelete='cascade',
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
related='config_id.company_id',
|
||||
string='Company',
|
||||
store=True,
|
||||
)
|
||||
province = fields.Selection([
|
||||
('AB', 'Alberta'),
|
||||
('BC', 'British Columbia'),
|
||||
('MB', 'Manitoba'),
|
||||
('NB', 'New Brunswick'),
|
||||
('NL', 'Newfoundland and Labrador'),
|
||||
('NS', 'Nova Scotia'),
|
||||
('NT', 'Northwest Territories'),
|
||||
('NU', 'Nunavut'),
|
||||
('ON', 'Ontario'),
|
||||
('PE', 'Prince Edward Island'),
|
||||
('QC', 'Quebec'),
|
||||
('SK', 'Saskatchewan'),
|
||||
('YT', 'Yukon'),
|
||||
], string='Province', required=True)
|
||||
payment_frequency = fields.Selection([
|
||||
('monthly', 'Monthly'),
|
||||
('quarterly', 'Quarterly'),
|
||||
('annually', 'Annually'),
|
||||
], string='Payment Frequency', required=True, default='quarterly')
|
||||
effective_date = fields.Date(
|
||||
string='Effective Date',
|
||||
required=True,
|
||||
help='Date when this payment schedule becomes effective',
|
||||
)
|
||||
form_type = fields.Char(
|
||||
string='Form Type',
|
||||
help='Tax form type (e.g., Form PD7A)',
|
||||
)
|
||||
is_current = fields.Boolean(
|
||||
string='Current Schedule',
|
||||
compute='_compute_is_current',
|
||||
store=True,
|
||||
help='True if this is the currently active schedule',
|
||||
)
|
||||
display_name = fields.Char(
|
||||
string='Display Name',
|
||||
compute='_compute_display_name',
|
||||
)
|
||||
|
||||
@api.depends('payment_frequency', 'effective_date', 'is_current')
|
||||
def _compute_display_name(self):
|
||||
"""Compute display name for the schedule."""
|
||||
for schedule in self:
|
||||
freq_map = {
|
||||
'monthly': 'Monthly',
|
||||
'quarterly': 'Quarterly',
|
||||
'annually': 'Annually',
|
||||
}
|
||||
freq = freq_map.get(schedule.payment_frequency, schedule.payment_frequency)
|
||||
date_str = schedule.effective_date.strftime('%m/%d/%Y') if schedule.effective_date else ''
|
||||
current = ' (current schedule)' if schedule.is_current else ''
|
||||
schedule.display_name = f"{freq} since {date_str}{current}"
|
||||
|
||||
@api.depends('effective_date', 'province', 'config_id.provincial_tax_schedule_ids')
|
||||
def _compute_is_current(self):
|
||||
"""Determine if this is the current active schedule."""
|
||||
today = date.today()
|
||||
for schedule in self:
|
||||
# Get all schedules for this province, ordered by effective_date desc
|
||||
all_schedules = self.search([
|
||||
('config_id', '=', schedule.config_id.id),
|
||||
('province', '=', schedule.province),
|
||||
], order='effective_date desc')
|
||||
|
||||
# The current schedule is the one with the most recent effective_date <= today
|
||||
current_schedule = None
|
||||
for sched in all_schedules:
|
||||
if sched.effective_date <= today:
|
||||
current_schedule = sched
|
||||
break
|
||||
|
||||
schedule.is_current = (current_schedule and current_schedule.id == schedule.id)
|
||||
|
||||
@api.model
|
||||
def get_current_schedule(self, config_id, province, check_date=None):
|
||||
"""Get the current active schedule for a province."""
|
||||
if not check_date:
|
||||
check_date = date.today()
|
||||
|
||||
schedule = self.search([
|
||||
('config_id', '=', config_id),
|
||||
('province', '=', province),
|
||||
('effective_date', '<=', check_date),
|
||||
], order='effective_date desc', limit=1)
|
||||
|
||||
return schedule
|
||||
|
||||
@api.constrains('effective_date', 'province', 'config_id')
|
||||
def _check_overlapping_schedules(self):
|
||||
"""Warn if schedules overlap (but allow for historical changes)."""
|
||||
for schedule in self:
|
||||
# Allow multiple schedules, but warn if dates are very close
|
||||
overlapping = self.search([
|
||||
('config_id', '=', schedule.config_id.id),
|
||||
('province', '=', schedule.province),
|
||||
('id', '!=', schedule.id),
|
||||
('effective_date', '=', schedule.effective_date),
|
||||
])
|
||||
if overlapping:
|
||||
raise UserError(_(
|
||||
'A payment schedule for %s already exists with effective date %s. '
|
||||
'Please use a different date.'
|
||||
) % (schedule.province, schedule.effective_date.strftime('%m/%d/%Y')))
|
||||
Reference in New Issue
Block a user