diff --git a/fusion_clock/wizard/__init__.py b/fusion_clock/wizard/__init__.py
index d4fa3d08..22793f09 100644
--- a/fusion_clock/wizard/__init__.py
+++ b/fusion_clock/wizard/__init__.py
@@ -3,3 +3,4 @@
# License OPL-1 (Odoo Proprietary License v1.0)
from . import clock_nfc_enrollment_wizard
+from . import clock_period_picker_wizard
diff --git a/fusion_clock/wizard/clock_period_picker_views.xml b/fusion_clock/wizard/clock_period_picker_views.xml
new file mode 100644
index 00000000..a26d0c18
--- /dev/null
+++ b/fusion_clock/wizard/clock_period_picker_views.xml
@@ -0,0 +1,36 @@
+
+
+
+
+ fusion.clock.period.picker.form
+ fusion.clock.period.picker
+
+
+
+
+
+
+ Bi-Weekly Period
+ fusion.clock.period.picker
+ form
+
+ new
+
+
+
diff --git a/fusion_clock/wizard/clock_period_picker_wizard.py b/fusion_clock/wizard/clock_period_picker_wizard.py
new file mode 100644
index 00000000..651702f7
--- /dev/null
+++ b/fusion_clock/wizard/clock_period_picker_wizard.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+# Copyright 2026 Nexa Systems Inc.
+# License OPL-1 (Odoo Proprietary License v1.0)
+
+from datetime import timedelta
+from odoo import models, fields, api, _
+from odoo.exceptions import ValidationError
+from ..models.pay_period import compute_pay_period, period_length_days, current_prev_next
+from ..models.tz_utils import get_local_today, get_local_day_boundaries
+
+
+class FusionClockPeriodPicker(models.TransientModel):
+ """Pick a pay-period window and open the attendance list filtered to it.
+
+ Defaults to the current pay period. Changing the start auto-fills the end
+ to one pay period later (two weeks by default); the end stays editable so a
+ fully custom range can be entered too.
+ """
+ _name = 'fusion.clock.period.picker'
+ _description = 'Bi-Weekly Period Picker'
+
+ date_start = fields.Date(string='Period Start', required=True,
+ default=lambda self: self._fclk_default_window()[0])
+ date_end = fields.Date(string='Period End', required=True,
+ default=lambda self: self._fclk_default_window()[1])
+
+ def _fclk_config(self):
+ ICP = self.env['ir.config_parameter'].sudo()
+ return (ICP.get_param('fusion_clock.pay_period_type', 'biweekly'),
+ ICP.get_param('fusion_clock.pay_period_start', ''))
+
+ def _fclk_default_window(self):
+ frequency, anchor = self._fclk_config()
+ return current_prev_next(frequency, anchor, get_local_today(self.env))['current']
+
+ @api.onchange('date_start')
+ def _onchange_date_start(self):
+ if not self.date_start:
+ return
+ frequency, anchor = self._fclk_config()
+ length = period_length_days(frequency)
+ if length:
+ self.date_end = self.date_start + timedelta(days=length - 1)
+ else:
+ self.date_end = compute_pay_period(frequency, anchor, self.date_start)[1]
+
+ @api.constrains('date_start', 'date_end')
+ def _check_dates(self):
+ for rec in self:
+ if rec.date_start and rec.date_end and rec.date_end < rec.date_start:
+ raise ValidationError(_("Period end cannot be before period start."))
+
+ def action_apply(self):
+ self.ensure_one()
+ start_utc, _dummy = get_local_day_boundaries(self.env, self.date_start)
+ _dummy2, end_excl_utc = get_local_day_boundaries(self.env, self.date_end)
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': _("Attendances ยท %s โ %s") % (self.date_start, self.date_end),
+ 'res_model': 'hr.attendance',
+ 'view_mode': 'list,form',
+ 'domain': ['&',
+ ('check_in', '>=', fields.Datetime.to_string(start_utc)),
+ ('check_in', '<', fields.Datetime.to_string(end_excl_utc))],
+ 'target': 'current',
+ }