BFBambooForge Labs

Helpdesk & Ticket Management for Community

A helpdesk for Odoo Community: tickets by mail and portal, targets counted in working hours, escalation with a name on it, and safe merges.

Buy on the Odoo Apps StoreOpen the live demoExtra Tools€290Community & Enterprise

Available for Odoo 16.0, Odoo 17.0, Odoo 18.0, Odoo 19.0. Technical name bambooforge_helpdesk.

Odoo 16.0Odoo 17.0Odoo 18.0Odoo 19.0
Full walkthrough on a live Odoo 19.0 database, with subtitles. It ends with what this app deliberately does not do.

Helpdesk & Ticket Management for Community

Odoo Community has no helpdesk. This is one. It is built around the three things that decide whether a support desk is trusted rather than merely installed: the clock, the mailbox, and who can read what.

The clock

Working hours, not wall-clock hours

Every service target is a number of working hours on the team's own calendar. Four hours promised at 16:00 on a Friday is 11:00 on Monday - one hour left on the Friday, three on the Monday morning - and public holidays on that calendar are skipped like any other closed day. A desk that measures in wall-clock hours reports itself late every weekend and stops being believed within a month.

The team falls back to the company calendar when it has none of its own, so a fresh install already counts correctly.

The clock stops while you are waiting on the customer

Mark a stage Waiting on Customer and every running target on a ticket in that stage is paused. When the customer answers, the time spent waiting is measured in working hours and given back: each deadline moves forward by exactly that much. How long a ticket was paused is on the ticket, in hours, so the number can be argued with rather than believed.

The escalation cron knows about the pause too: a paused ticket past its deadline is not reported as late, because you are not late for somebody else's silence.

What counts as an answer

The first-reply target is met by a message the customer can read, written by somebody on our side. An internal note is not an answer. Moving the ticket to another column is not an answer. The customer writing again is not an answer.

This is the single most commonly faked number in helpdesk software, and the one a customer can check against their own inbox.

Missing a target has a name on it

When a deadline passes, the target is marked missed once, with how many working hours it went over, and an activity is created for the escalation user of that policy - or the team leader if the policy names nobody. Not a red colour on a list nobody opens. Running the cron again does not pile up a second activity.

Reopening starts a new clock, and keeps the old one

A reopened ticket gets a new resolution target, counted from the reopening, recorded as attempt 2. The rows from attempt 1 are left exactly as they were: last month's report does not change because somebody reopened a ticket in March.

The first-reply target is not re-issued. It was promised once and met once; re-issuing it would let a reopen quietly rewrite the number.

Reclassification

Raise a ticket to Urgent and the urgent policy attaches counted from now, not backdated to a creation time when nobody had promised anything. A note goes in the chatter saying so. Targets already running are never withdrawn by editing a tag: a promise made is a promise kept.

The mailbox

Each team has an alias. Mail to it opens a ticket in that team; replies land on the ticket they belong to, because the desk answers through the chatter and the mail headers do the rest.

An unknown sender never silently creates a contact. The name and the address are kept on the ticket, and a human decides whether that is a customer. A helpdesk that creates a partner per inbound mail turns a contact database into a spam trap within a quarter.

A known address is matched to its contact, and the customer is added as a follower so the answer reaches them.

Who can read what

Agents and managers

An Agent works tickets: reads, answers, moves and closes them. An agent cannot delete a ticket and cannot change teams, stages or targets. A Manager does all that, plus configuration, plus deleting - which is refused on a closed ticket unless it is a manager doing it, because a closed ticket is history.

Teams that are nobody else's business

A team is readable by every agent by default, which is how most desks actually run. Set it to its own agents and a team handling payroll, legal or staff complaints becomes invisible to the rest of the desk - a record rule, not a hidden menu.

The customer portal

A customer sees their tickets at /my/tickets: the conversation, not the back office. Internal notes are filtered on the server, by message subtype, before anything is rendered - not hidden by a widget that a future version might render differently.

A customer can add a message, close their own ticket, and open a new one. A customer cannot set the priority: letting them would let anybody buy themselves a one-hour target. Writing back on a ticket that was waiting on the customer moves it out of that stage automatically, so the desk sees it again and the clock restarts.

By default a portal user sees the tickets of their whole company, which is what a customer's operations team expects. Tick Private to the contact and a ticket stays with the person named on it - a complaint about a colleague is not for the whole company's portal.

There is a plain rate limit on new tickets from the portal: ten in an hour from one contact, after which the form says so.

Merging

Two reports of the same fault are merged from either ticket. The messages, the files and the followers move onto the ticket you keep; the others are closed with the reason Merged into another ticket and carry a link to the winner. Nothing is deleted.

Tickets from two companies are refused: their documents and their books are separate, and a merge would move one company's messages into the other's. Different customers are allowed but warned about in the wizard, in as many words, because sometimes they really are the same fault.

Housekeeping

Two scheduled jobs, both opt-in, both isolating failures per record so one bad ticket cannot stop the run:

  • Close tickets nobody answered. Set a number of days on the team. Tickets sitting in a Waiting on Customer stage with no word back for that long are closed with the reason No answer from the customer. Tickets the desk still owes an answer are never touched.

  • Delete closed tickets past retention. Set a number of months in Settings, per company. Closed tickets older than that are removed with their messages and files. Zero - the default - keeps everything for ever, which is the right default for anybody who has not thought about it yet.

What it needs

base, mail, portal, resource and base_setup. All Community. No Enterprise module is required, and none is used.

Screens

Pipeline - bambooforge_helpdesk
Pipeline
Portal - bambooforge_helpdesk
Portal
Targets - bambooforge_helpdesk
Targets
Ticket - bambooforge_helpdesk
Ticket