feat(fusion_clock): Publish & Notify range + portal Schedule fold-in [A6-A7]

Generalise post_week into fclk_publish_range/fclk_email_posted_range +
planner Publish… panel + publish_range endpoint. Fold the /my/clock/schedule
controller+template+css from fusion_planning into fusion_clock (native
schedule only, role colour); inline Schedule nav across all portal pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-06-04 20:54:59 -04:00
parent 734b3b94fd
commit 3376a32143
14 changed files with 641 additions and 31 deletions

View File

@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
from datetime import date
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
@tagged('-at_install', 'post_install', 'fusion_clock')
class TestPublishRange(TransactionCase):
def setUp(self):
super().setUp()
self.Schedule = self.env['fusion.clock.schedule']
self.emp = self.env['hr.employee'].create({
'name': 'Pat', 'work_email': 'pat@example.com'})
def _draft(self, day):
return self.Schedule.create({
'employee_id': self.emp.id, 'schedule_date': day,
'start_time': 9.0, 'end_time': 17.0, 'state': 'draft'})
def test_publish_range_posts_drafts(self):
d1, d2 = date(2026, 6, 1), date(2026, 6, 3)
self._draft(d1)
self._draft(d2)
posted, _notified = self.Schedule.fclk_publish_range(self.emp, d1, d2)
self.assertEqual(posted, 2)
rows = self.Schedule.search([('employee_id', '=', self.emp.id)])
self.assertTrue(all(r.state == 'posted' for r in rows))
self.assertTrue(all(r.posted_date for r in rows))
def test_publish_range_skips_already_posted(self):
d = date(2026, 6, 1)
self.Schedule.create({
'employee_id': self.emp.id, 'schedule_date': d,
'start_time': 9.0, 'end_time': 17.0, 'state': 'posted'})
posted, _notified = self.Schedule.fclk_publish_range(self.emp, d, d)
self.assertEqual(posted, 0, "Already-posted rows are not re-posted")
def test_publish_range_respects_bounds(self):
inside = self._draft(date(2026, 6, 5))
outside = self._draft(date(2026, 6, 20))
posted, _notified = self.Schedule.fclk_publish_range(
self.emp, date(2026, 6, 1), date(2026, 6, 7))
self.assertEqual(posted, 1)
self.assertEqual(inside.state, 'posted')
self.assertEqual(outside.state, 'draft')
def test_email_posted_range_no_email_returns_false(self):
emp2 = self.env['hr.employee'].create({'name': 'NoEmail'})
self.assertFalse(
self.Schedule.fclk_email_posted_range(emp2, date(2026, 6, 1), date(2026, 6, 2)))