No description
  • Python 44.6%
  • JavaScript 31.8%
  • SCSS 23.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
treesloth b1620f0883 Keep the backend readable when the backdrop image is missing
Two more spots where Liquid Glass leaves white on white.

The backend is only legible because one background-image sits behind it:
every glass surface in the theme is a white overlay and every label on it
is white. iOS drops a fixed, cover-sized background image, so the PWA on
an iPhone renders the whole backend white on near-white - Discuss worst
of all, since it is mostly text straight on the backdrop. Put a dark
colour and a gradient on the root element for the image to cover, so the
failure mode cannot happen; the theme's own rule is untouched.

The other spot is the mail composer: "Send by Email", "Cancel Sales
Order" and the rest render an email template into an html field, where
the theme whitens every div, span and p over the template's own light
wrapper. Same paper-and-ink treatment as the chatter, scoped to dialogs
and the composer's field and guarded by the same :has() test so ordinary
html fields keep the glass look.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VS29zEeXj2sgcuU3KWoEkz
2026-09-17 10:46:25 -04:00
team_hub Stop apprentices completing or closing out a job 2026-09-16 23:30:55 -04:00
theme_glass_readability Keep the backend readable when the backdrop image is missing 2026-09-17 10:46:25 -04:00
tools Schedule jobs per date, check crew conflicts, text every assignment change 2026-09-11 15:28:07 -04:00
web_pwa_customize_ios Add web_pwa_customize_ios: use the PWA icon on iOS home screens 2026-09-10 20:59:22 -04:00
.gitignore Fix XMLSyntaxError in shift record rule; add README and .gitignore 2026-06-07 16:22:06 -04:00
INVENTORY_DATA.md Apprenticeship hour tracking: work processes, split-at-clock-out, sign-off, progress 2026-06-28 02:32:22 -04:00
QA_CHECKLIST.md Stop apprentices completing or closing out a job 2026-09-16 23:30:55 -04:00
README.md Schedule jobs per date, check crew conflicts, text every assignment change 2026-09-11 15:28:07 -04:00
TEST_DATA.md Apprenticeship hour tracking: work processes, split-at-clock-out, sign-off, progress 2026-06-28 02:32:22 -04:00

Team Hub

A Connecteam-style, mobile-first Team Portal for frontline / deskless employees, built as a full-screen OWL client action inside the Odoo 18 Community web client.

Clean cards, big touch targets, a bottom navigation bar, and fast access to the daily tools your staff actually use — clock in/out, jobs, checklists, and chat — without the clutter of the standard backend.

Features

Area Status Notes
Home dashboard Phase 1 Greeting, one-tap clock in/out, today's scheduled jobs, checklists, announcements
Time Clock GPS-aware payroll clock in/out, reuses Odoo Attendance. Crew closeout moved to the job checkout, where the work actually happens
Job lifecycle Confirm assignment → check in to site (GPS + job timer) → crew closeout (status, note, blockers, materials, files) → check out. Recorded per visit in team_hub.job_visit
CRM activity log Every job action posts a timestamped OdooBot log note to the customer's opportunity, with photos and files attached — the invoicing trail
Work-order numbers WO/00001 sequence on every job, quoted in log notes and on the crew's phones
Files Photos, receipts and documents upload from the phone to the work order and the CRM card, typed so the office can filter receipts
Foreman crew view Crew tab: who's on the clock, who's on site, their jobs, statuses, hours, photos and last known location — scoped to the reporting line
Location breadcrumbs ⚙️ Opt-in Off by default. GPS at every clock and job event, plus a foreground heartbeat. See the honest limitations below
Jobs A tech's work as dispatched Projects/Tasks — each job has a client/site, one or more scheduled dates (each with its own times and crew), a location, tags, and an optional checklist. The Jobs tab shows the tech's own dates one week at a time
Multi-date scheduling Pick any days on a calendar; each date keeps its own start, finish, hours and crew (team_hub.job_schedule), so one day can change without touching the rest
Scheduling conflicts Saving in the console checks for crew double-booked across jobs and saves nothing until the manager changes the schedule or clicks Save anyway (logged)
CRM intake → Jobs Moving a CRM lead into your Approved stage auto-creates a client/site Project (from the lead's contact + address) and a ready-to-schedule job in the dispatch backlog — tags carry over
Labor by tag Job timers log analytic lines carrying the job's tags, so hours report by tag. Payroll time (attendance) and job time (timesheets) never double-count
Checklists & Forms Phase 3 Digital checklists (checkbox/text/number items, progress, submit) on the Checklists tab. Job tasks, with their assignees, show on the job sheet
Chat / Announcements Phase 4 Company announcements feed + one-tap into Odoo Discuss
Mobile / installable Phase 5 Photo capture on clock; installs as an app via Odoo's built-in PWA (see below)
Dispatch Console Desktop command center for managers/dispatchers: multi-date job scheduling, date-by-date crew, task assignments, job tagging, checklist assignment, attendance corrections, announcement management, and a Configuration tab for who counts as field crew
Clickable links Web addresses in job details, closeout notes, blockers, materials, additional work, sub-task names and checklist instructions open in a new tab, in Team Hub and the console
Field Service Guide Manager-only educational screen: electrical-contractor workflow, what Odoo automates vs what you do manually, step-by-step how-tos, and crew-phone preview

Jobs vs. shifts. A field tech's day is modelled as Projects/Tasks, not fixed shifts: a Project is a client/site and each Task is a job (with start/end time and location). This replaces the earlier team_hub.shift model. Since 18.0.1.4.0 a job's days live in team_hub.job_schedule (one row per date, with its own times and crew); the task's start/end are computed from those rows, and its assignees are everyone on any date.

Employees consume everything through the simplified mobile portal; managers get two front doors onto the same data: the standard Odoo backend views (under the Employees app) for detailed editing, and the Dispatch Console — a full-screen, desktop-first OWL command center — for at-a-glance crew status and quick actions.

Dispatch Console

A separate app tile (Dispatch Console), visible only to users in the Team Hub → Team Manager group. Built for a wide screen, it has three views in the top bar — Schedule (timeline), Jobs (list) and Configuration — plus a Back to Odoo button. Every action opens an in-console dialog and refreshes the whole board in one round-trip:

  • On the clock — every crew member with a live in/out dot, time worked so far, and a map-pin link to their clock-in GPS / a camera flag if they captured a site photo. Managers can clock a member in/out or correct clock-in/out times right here.
  • Jobs & scheduling — the day's scheduled dates plus a Backlog · needs scheduling list (jobs with no dates). The job dialog's Schedule section is a month calendar: click any days to add them, click a chosen day again to remove it. Each date is its own row with Start, Finish, Hours (defaults to finish minus start; override it for an unpaid lunch) and Crew. New dates start with sets the default times and crew copied into newly added dates; Apply to every date overwrites all rows. Editing one date never changes another.
  • Scheduled dates — every timeline block is one date. Clicking it (or the calendar icon on a Jobs-list row) opens a Scheduled date dialog to change that date's date/times/hours, add or remove crew for that date only, remove the date, or jump to Edit whole job. Dragging a block along its row changes its time; dropping it on another person's row swaps that person in for that date only; dropping a backlog card on a crew row creates one date (2-hour default). The Jobs list shows one row per date, with Assign… / + Crew… adding someone to that date only.
  • Conflict alerts — saving a job dialog, a scheduled-date dialog or a drag checks whether any crew member would overlap another scheduled date (other jobs, drafts included; cancelled/archived jobs ignored; new dates in the same save checked against each other). If so, nothing is saved and a panel lists each clash (employee, job with work-order #, date, overlapping times). Change the schedule, or click Save anyway; overrides are logged as "Scheduling conflict overridden" on the CRM card (or job chatter). An already-accepted clash is not raised again unless that date's time or crew changes. Backend edits (Job Schedule menu, task form) are not checked.
  • Task assignments — each task row in the job dialog assigns the task to one employee (active field crew with a Team Hub login; people scheduled on the job listed first). The dialog warns when that person isn't on any of the job's dates, because they won't see the job until they are. Team Hub shows each task's assignee on the job sheet.
  • Job checklists — every open field checklist with a completion bar, assignee, and due date. Assign a new checklist (with checkbox/text/number items) to a tech and optionally attach it to a job.
  • Announcements — compose + (optionally pin) a broadcast, and edit / pin / delete existing announcements. Bodies render as formatted HTML on every crew member's portal.
  • Configuration — every active employee with a Field crew on/off switch, search, and All / Field crew / Hidden filters. Switching someone off hides them from the crew sidebar and timeline, every crew picker (job dialog, scheduled-date dialog, checklist Assign to) and the scheduling views. It only sets hr.employee.team_hub_field_crew — the employee, user, attendance and history are untouched, and they can be switched back any time. Rows flag No login and show a count of upcoming dates; a hidden person still on upcoming dates gets a warning, because hiding doesn't take them off those dates. The same flag is on the employee form's Team Hub tab (which also holds the apprenticeship fields) and in Employees → Team Hub → Crew Structure. Everyone is on by default. Apprentice progress in the console ignores the flag.

URLs in job details, the crew closeout (note, blockers, materials, additional work), sub-task names and checklist instructions are shown as links that open in a new tab — in the job dialog (a Links row under Details), on each Jobs-list row, and in the scheduled-date dialog. Links made in the backend HTML editor keep their address in Team Hub ("label (https://…)").

Scheduled dates can also be managed in the backend: Employees → Team Hub → Job Schedule (calendar / list / form, Upcoming filter) and the Scheduled Dates list on the task form's Team Hub tab.

Every Console RPC re-checks the manager group server-side, so the panel is safe even if the menu is reached directly.

Field Service Guide

A third manager-only app tile (Field Service Guide) — a scrollable, visual training screen for dispatchers and operational managers who may not be comfortable with computers. No backend configuration required; content ships with the module.

  • The big picture — end-to-end workflow from customer inquiry to job complete, with AUTO vs YOU labels on each step
  • What Odoo does automatically — CRM Approved/Won → backlog job, tag snapshots on clock-in, timesheet logging on clock-out, checklist gate on job completion, apprentice hour splitting, and more
  • Your tools in Odoo — when to use CRM, Dispatch Console, Projects, Team Hub, and backend settings
  • Step-by-step guides — schedule a job, assign checklists, fix missed clock-ins, sign off apprentice hours, and other daily tasks in plain language
  • What your crew sees — a phone mock of the Team Hub portal so managers know what techs experience after you publish a job
  • Quick reference — daily dispatcher checklist, glossary, and FAQ

CRM intake → Projects & jobs

The client's sales pipeline feeds dispatch directly. Tick Create Team Hub project on a CRM stage (CRM → Configuration → Stages — pre-set on your Approved stage at install), and the moment a lead lands in that column Team Hub automatically:

  1. creates a Project (the client/site) linked to the lead's Contact,
  2. drops a ready-to-schedule job into the Dispatch Console backlog, with the contact's address pre-filled as the job location, and
  3. carries the lead's tags over onto the job (CRM tags are mirrored to project tags by name, reusing existing ones).

The dispatcher just sets the crew + time and publishes. Conversion is idempotent — a lead remembers the project it created (team_hub_project_id), so moving it in and out of the stage won't make duplicates. Clear that link on the lead to allow a fresh conversion.

Crew text messages (SMS)

Crew get texts through Odoo's built-in SMS (IAP), so the database needs SMS credits.

Texts are worked out once per save — at most one text per person per job — and cover:

  • New assignment — their first date on a published job.
  • Dates added to a job they're already on.
  • Schedule change — the new time, with "was …".
  • Removed from a date, or from the job.
  • Job cancelled — cancelled, deleted or archived.
  • Taken off your schedule — the job was pulled back to draft.

Each text carries the company name, a header, the job name with work-order #, the site address, and the date(s) with startfinish time in Central Time ("CT"). Assignments and changes add an Open: link, https://<odoo>/team_hub/job/<id>?date=YYYY-MM-DD, which opens Team Hub on that job and week (signed-out users log in first).

  • Only published jobs text. A draft texts nobody; publishing texts everyone on its upcoming dates. Past dates and jobs marked done never text.
  • No duplicates. The last state each person was told is remembered per date, so re-saving an unchanged schedule sends nothing.
  • Number used: the employee's Private Phone (Employees → person → Private Information → Private Contact). Work Mobile and the job's customer are never texted. Crew with no Private Phone are skipped and named in a "Crew text not sent" note on the CRM card (or the work order).
  • Every text is posted on the work order's chatter with its delivery status. Texts go out through the SMS: SMS Queue Manager scheduled action shortly after the save commits.

Tags & labor reporting

Jobs carry standard project tags. Assign them in the Console job dialog (toggle colored chips, or create a tag inline); chips show on the board and on the tech's job cards. To track labor by category, a tech clocks in against a job from the Time Clock — the attendance is linked to that job and snapshots its tags, and on clock-out the worked hours are logged as a timesheet on the job's task (carrying the same tags). Attendance and timesheet records can then be filtered / grouped by tag.

Requirements

  • Odoo 18 Community (or Enterprise — only Community modules are used).
  • All dependencies ship with Odoo core, so there is nothing extra to download. They will be installed automatically when you install Team Hub:
    Module Ships with
    hr Community core
    hr_attendance Community core
    hr_timesheet Community core
    project Community core
    crm Community core
    mail Community core
    sms Community core (sending needs IAP SMS credits)

Installation

  1. Place the module on your addons path. Clone or copy the team_hub/ directory into a folder that is listed in your Odoo addons_path, e.g.:

    cd /opt/odoo/addons
    git clone <this-repo-url> Odoo-Team-Catalyst
    # team_hub then lives at /opt/odoo/addons/Odoo-Team-Catalyst/team_hub
    

    The addons_path must point at the directory containing team_hub (i.e. .../Odoo-Team-Catalyst), not at team_hub itself.

  2. Restart Odoo so it picks up the new path:

    sudo systemctl restart odoo      # or however you run your instance
    
  3. Update the apps list. In Odoo: enable Developer Mode (Settings → Developer Tools → Activate the developer mode), then go to Apps → ⋮ → Update Apps List.

  4. Install. Search Apps for "Team Hub" and click Install.

  5. Open the Team Hub app tile — the mobile portal loads full-screen with the bottom navigation and your dashboard.

Upgrading

After pulling new changes, restart with the module flagged for upgrade:

odoo -u team_hub -d <your-database>

…or use Apps → Team Hub → Upgrade from the UI.

18.0.1.4.0 needs -u team_hub (new team_hub.job_schedule model, fields, the Job Schedule menu and access rules). The migration:

  • creates one scheduled date per already-scheduled job from its old start, end and assignees (a job with a start but no end gets a 2-hour window),
  • marks those crews as already texted, so upgrading sends no SMS,
  • switches Field crew on for every employee.

Roles & security

  • Team Member (team_hub.group_team_member) — every internal user is one by default. No direct project.task ACL; sees and completes only their own dispatched jobs and checklists through guarded, sudo-backed server methods. Record rules restrict checklists to the assigned employee.
  • Team Foreman (team_hub.group_team_foreman) — a crew lead. Sees and works the jobs, photos, notes and checklists of everyone who reports to them, plus the Crew tab. This is derived entirely from the native Manager field on hr.employee (parent_id) and silently grants nothing until that is filled in — set it under Employees → Team Hub → Crew Structure. The Dispatch Console warns about foremen with no crew, and the Crew tab says so on screen rather than showing an empty list.
  • Team Manager (team_hub.group_team_manager) — runs the Dispatch Console (jobs, checklists, attendance, announcements) and the backend management views. Implies Foreman. Grant this to schedulers/supervisors via Settings → Users → (user) → Other → Team Hub.

Team Managers — exactly the users who can open the Dispatch Console — get a Back to Odoo button in the portal's top-right corner to return to the main apps screen. Foremen who aren't managers, and field techs, stay in the portal.

On the Jobs tab a member sees only their own scheduled dates for one week (foremen also see their crew's, with names), grouped by day. Unscheduled jobs and other people's jobs are not listed. The week starts on the day set by the user's language (Sunday for English (US)).

All portal actions re-resolve the acting employee from the logged-in user server-side — a client can never act on behalf of another employee.

Installing as a mobile app (PWA)

Team Hub runs inside Odoo's web client, which already is a Progressive Web App in Odoo 18 — it ships its own web manifest and service worker. Team Hub deliberately does not register a second service worker, because a service worker only controls pages under its own URL scope; to cover the /odoo backend ours would have to be root-scoped and would then collide with Odoo's, breaking the platform's offline support. Instead we ride on the built-in PWA:

  1. Open your Odoo instance over HTTPS on the phone's browser (Chrome/Edge on Android, Safari on iOS).
  2. Use the browser's Install app / Add to Home Screen option.
  3. Launch from the new home-screen icon, then open Team Hub — it runs full-screen with no browser chrome, like a native app.

Tip: set your installable app name/icon in Settings → General Settings → Progressive Web App. Offline caching of static assets is handled by Odoo's own service worker; live data (jobs, tasks, clock) still needs a connection.

Job photos, receipts and documents

Photos, receipts and documents upload from the job detail sheet and from the crew closeout — not from the day clock, which no longer collects anything. Each file is attached to the work order as a native ir.attachment (so it shows in the backend chatter), typed as photo / receipt / document, and mirrored onto the customer's CRM card with a log note. Files upload one at a time as they're picked, so a dropped connection mid-closeout never loses the ones already sent.

Camera capture and geolocation both require HTTPS (or localhost); without it the app still works, just without photos or coordinates.

Location breadcrumbs — what this can and cannot do

Breadcrumbs are off by default (Employees → Team Hub → Settings). Switch them on only after telling your crew: continuous employee location logging requires written notice or consent in several US states.

What you get:

  • A guaranteed reading at clock in, clock out, job check-in and job check-out.
  • A best-effort reading every N minutes (default 10) while the app is open in the foreground and the employee is clocked in.
  • Nothing at all while the employee is off the clock — enforced server-side, not just in the UI.
  • Coordinates plus a one-click Google Maps link. No reverse geocoding: there is no free service that survives per-reading rate limits, and a paid key is not worth the dependency.
  • Nightly pruning past the retention window (default 90 days).

What you do not get: a continuous track. A phone browser cannot read GPS once the tab is closed or the screen locks — no PWA can. Treat the trail as a set of confirmed sightings, and expect gaps. The Location Trail view is written to say so.

Notes

  • Geolocation on the Time Clock only works over HTTPS (or localhost). On plain HTTP the browser blocks it and the clock still works, just without coordinates.
  • The portal is a backend client action — it reuses Odoo's session, ORM, and security.

License

LGPL-3