feat(fusion_clock): default clock-in/out times as 12-hour AM/PM dropdowns
People aren't good with 24h. Default Clock-In/Out are now AM/PM dropdowns (15-min grid) instead of 24h float_time inputs. Stored value stays the float-string (e.g. '9.0'), so all downstream float(get_param(...)) reads are unchanged; persisted manually with get-snap for any off-grid value. Bump 19.0.4.0.3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Fusion Clock',
|
'name': 'Fusion Clock',
|
||||||
'version': '19.0.4.0.2',
|
'version': '19.0.4.0.3',
|
||||||
'category': 'Human Resources/Attendances',
|
'category': 'Human Resources/Attendances',
|
||||||
'summary': 'Complete Employee T&A with Geofencing, Shifts, Penalties, Overtime, Kiosk, Dashboard & Payroll Export',
|
'summary': 'Complete Employee T&A with Geofencing, Shifts, Penalties, Overtime, Kiosk, Dashboard & Payroll Export',
|
||||||
'description': """
|
'description': """
|
||||||
|
|||||||
@@ -9,17 +9,21 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
_inherit = 'res.config.settings'
|
_inherit = 'res.config.settings'
|
||||||
|
|
||||||
# ── Work Schedule ──────────────────────────────────────────────────
|
# ── Work Schedule ──────────────────────────────────────────────────
|
||||||
fclk_default_clock_in_time = fields.Float(
|
# 12-hour AM/PM dropdowns (people aren't good with 24h). The selection VALUE
|
||||||
|
# is the float-as-string the backend stores (e.g. '9.0', '17.5'), so all
|
||||||
|
# downstream float(get_param(...)) reads are unchanged. Persisted manually in
|
||||||
|
# get_values/set_values (a 15-min grid; get snaps any off-grid stored value).
|
||||||
|
fclk_default_clock_in_time = fields.Selection(
|
||||||
|
selection='_fclk_time_selection',
|
||||||
string='Default Clock-In Time',
|
string='Default Clock-In Time',
|
||||||
config_parameter='fusion_clock.default_clock_in_time',
|
default='9.0',
|
||||||
default=9.0,
|
help="Default scheduled clock-in time, used when no shift is assigned.",
|
||||||
help="Default scheduled clock-in time (24h format, e.g. 9.0 = 9:00 AM).",
|
|
||||||
)
|
)
|
||||||
fclk_default_clock_out_time = fields.Float(
|
fclk_default_clock_out_time = fields.Selection(
|
||||||
|
selection='_fclk_time_selection',
|
||||||
string='Default Clock-Out Time',
|
string='Default Clock-Out Time',
|
||||||
config_parameter='fusion_clock.default_clock_out_time',
|
default='17.0',
|
||||||
default=17.0,
|
help="Default scheduled clock-out time, used when no shift is assigned.",
|
||||||
help="Default scheduled clock-out time (24h format, e.g. 17.0 = 5:00 PM).",
|
|
||||||
)
|
)
|
||||||
fclk_auto_deduct_break = fields.Boolean(
|
fclk_auto_deduct_break = fields.Boolean(
|
||||||
string='Auto-Deduct Break',
|
string='Auto-Deduct Break',
|
||||||
@@ -280,11 +284,40 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
('fclk_nfc_kiosk_debug', 'fusion_clock.nfc_kiosk_debug', False),
|
('fclk_nfc_kiosk_debug', 'fusion_clock.nfc_kiosk_debug', False),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _fclk_time_selection(self):
|
||||||
|
"""15-minute grid of 12-hour clock times. Each option's VALUE is the
|
||||||
|
float-as-string the backend stores (e.g. '9.0', '17.5'); the LABEL is
|
||||||
|
the friendly 12-hour form (e.g. '9:00 AM')."""
|
||||||
|
opts = []
|
||||||
|
for i in range(96):
|
||||||
|
f = i * 0.25
|
||||||
|
h24 = int(f)
|
||||||
|
mm = int(round((f - h24) * 60))
|
||||||
|
ap = 'AM' if h24 < 12 else 'PM'
|
||||||
|
h12 = h24 % 12 or 12
|
||||||
|
opts.append((str(f), '%d:%02d %s' % (h12, mm, ap)))
|
||||||
|
return opts
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _fclk_snap_time(value, default_float):
|
||||||
|
"""Snap a stored float-ish time to the nearest 15-min grid key string."""
|
||||||
|
try:
|
||||||
|
f = float(value)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
f = default_float
|
||||||
|
f = round(f * 4) / 4
|
||||||
|
if f < 0 or f >= 24:
|
||||||
|
f = default_float
|
||||||
|
return str(f)
|
||||||
|
|
||||||
def set_values(self):
|
def set_values(self):
|
||||||
super().set_values()
|
super().set_values()
|
||||||
ICP = self.env['ir.config_parameter'].sudo()
|
ICP = self.env['ir.config_parameter'].sudo()
|
||||||
for fname, key, _default in self._FCLK_BOOL_PARAMS:
|
for fname, key, _default in self._FCLK_BOOL_PARAMS:
|
||||||
ICP.set_param(key, 'True' if self[fname] else 'False')
|
ICP.set_param(key, 'True' if self[fname] else 'False')
|
||||||
|
ICP.set_param('fusion_clock.default_clock_in_time', self.fclk_default_clock_in_time or '9.0')
|
||||||
|
ICP.set_param('fusion_clock.default_clock_out_time', self.fclk_default_clock_out_time or '17.0')
|
||||||
if self.fclk_office_user_id:
|
if self.fclk_office_user_id:
|
||||||
ICP.set_param('fusion_clock.office_user_id', str(self.fclk_office_user_id.id))
|
ICP.set_param('fusion_clock.office_user_id', str(self.fclk_office_user_id.id))
|
||||||
else:
|
else:
|
||||||
@@ -323,4 +356,8 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
res['fclk_pay_period_start'] = fields.Date.to_date(anchor_str[:10])
|
res['fclk_pay_period_start'] = fields.Date.to_date(anchor_str[:10])
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
res['fclk_default_clock_in_time'] = self._fclk_snap_time(
|
||||||
|
ICP.get_param('fusion_clock.default_clock_in_time', '9.0'), 9.0)
|
||||||
|
res['fclk_default_clock_out_time'] = self._fclk_snap_time(
|
||||||
|
ICP.get_param('fusion_clock.default_clock_out_time', '17.0'), 17.0)
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
<div class="content-group">
|
<div class="content-group">
|
||||||
<div class="row mt16">
|
<div class="row mt16">
|
||||||
<label for="fclk_default_clock_in_time" string="Clock-In" class="col-lg-5 o_light_label"/>
|
<label for="fclk_default_clock_in_time" string="Clock-In" class="col-lg-5 o_light_label"/>
|
||||||
<field name="fclk_default_clock_in_time" widget="float_time"/>
|
<field name="fclk_default_clock_in_time"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt8">
|
<div class="row mt8">
|
||||||
<label for="fclk_default_clock_out_time" string="Clock-Out" class="col-lg-5 o_light_label"/>
|
<label for="fclk_default_clock_out_time" string="Clock-Out" class="col-lg-5 o_light_label"/>
|
||||||
<field name="fclk_default_clock_out_time" widget="float_time"/>
|
<field name="fclk_default_clock_out_time"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</setting>
|
</setting>
|
||||||
|
|||||||
Reference in New Issue
Block a user