- Python 44.6%
- JavaScript 31.8%
- SCSS 23.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
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 |
||
| team_hub | ||
| theme_glass_readability | ||
| tools | ||
| web_pwa_customize_ios | ||
| .gitignore | ||
| INVENTORY_DATA.md | ||
| QA_CHECKLIST.md | ||
| README.md | ||
| TEST_DATA.md | ||
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.shiftmodel. Since 18.0.1.4.0 a job's days live inteam_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:
- creates a Project (the client/site) linked to the lead's Contact,
- drops a ready-to-schedule job into the Dispatch Console backlog, with the contact's address pre-filled as the job location, and
- 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 start–finish 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 hrCommunity core hr_attendanceCommunity core hr_timesheetCommunity core projectCommunity core crmCommunity core mailCommunity core smsCommunity core (sending needs IAP SMS credits)
Installation
-
Place the module on your addons path. Clone or copy the
team_hub/directory into a folder that is listed in your Odooaddons_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_hubThe
addons_pathmust point at the directory containingteam_hub(i.e..../Odoo-Team-Catalyst), not atteam_hubitself. -
Restart Odoo so it picks up the new path:
sudo systemctl restart odoo # or however you run your instance -
Update the apps list. In Odoo: enable Developer Mode (Settings → Developer Tools → Activate the developer mode), then go to Apps → ⋮ → Update Apps List.
-
Install. Search Apps for "Team Hub" and click Install.
-
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 onhr.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:
- Open your Odoo instance over HTTPS on the phone's browser (Chrome/Edge on Android, Safari on iOS).
- Use the browser's Install app / Add to Home Screen option.
- 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