CRM

For: Agents Where to find it: Sidebar → CRM (seat-holders) · BillingAdd-Ons to switch it on

The CRM keeps every enquiry, client and trade agency in one place, moves each piece of business along a pipeline you can see at a glance, and turns a lead into a priced quote without anyone retyping the trip.

It sits on top of Quote to Book, which is what actually builds the quote — a lead becomes a priced quote, so the CRM requires it. Quote to Book in turn requires the Rates Engine. Selecting the CRM switches both on for you if you do not already have them.

What it does

  • A pipeline board. Every live lead as a card in a column, dragged (or moved from a menu on the card) between stages. Your pipeline starts with a sensible set of stages and you can rename, add or retire them.
  • Contacts and agencies. The person you correspond with, and the trade agency a booking came through, each with their own record and their full history. Contacts and agencies are archived rather than deleted, because leads and quotes point at them.
  • An enquiry inbox. Enquiries submitted against your published itineraries land here, ready to be turned into a lead in one action. See The enquiry inbox below — this is the surface you should work from.
  • A timeline per lead. Notes, calls, emails and tasks in one list, alongside the stage changes and quote events Tourium records for you. Tasks live in the same timeline, with a due date; you get an in-app notification for tasks due today.
  • Quotes linked to leads. Build a quote from a lead and the brand, agency, travel window, party size and client details are copied across. Sending, accepting or declining that quote writes back to the lead's timeline and moves it along the pipeline.
  • Lost reasons. Moving a lead into a losing stage asks why. That is the only field the board insists on, and it is the one that makes the pipeline worth reading later.

What it costs

The CRM is billed per seat, and the first seat costs more than each additional one:

Seats Monthly
First seat R499
Each additional seat R249

So 3 seats is R499 + R249 + R249 = R997/month, not 3 × the first-seat price. Prices are VAT-inclusive and may change — the Billing page always shows your actual total before you confirm anything.

This is on top of Quote to Book, which is billed per seat separately (R2,499 first seat / R999 additional), and the Rates Engine, which is billed on your inventory size. The CRM is priced as an attachment to the quoting module, not as a product of its own.

Seats are separate from your plan's ordinary team seats, which cover logging in and using the rest of Tourium.

Turning it on

  1. Go to Billing and find CRM in the Add-Ons list.
  2. Switch it on. A dialog asks you to choose the team members who should get a seat, and shows what your add-ons will come to per month before you commit.
  3. Confirm. CRM appears in the sidebar for seat-holders.

You can also enable it during signup. The agent guided setup has a CRM step where you pick the seat-holders — that is the only thing it asks. Your pipeline stages are created for you and are edited on the real Pipeline settings page afterwards, so there is only ever one place they live.

Switching the add-on off removes all seats immediately and stops its billing from your next cycle. Your leads, contacts and agencies are not deleted.

Who needs what

Two different questions decide who can do what: do you hold a seat, and which permission do you have.

To do this You need
Open the CRM and work leads, contacts and agencies A CRM seat, plus the crm.manage permission
Convert an enquiry into a lead The same: a CRM seat plus crm.manage
Edit the pipeline stages themselves A CRM seat plus crm.settings.manage — renaming or retiring a stage changes every consultant's board
Build a quote from a lead A Quote to Book seat and the quotes.manage permission, on top of your CRM access
Work the rate gaps worklist The rates.manage permission — no seat of either kind needed
Grant or revoke CRM seats Seat-management access (owners and admins have it by default)

The quote-seat line is the one worth reading twice. A CRM seat buys the pipeline; it does not buy quote-building. The "Build a quote" action on a lead demands a Quote to Book seat and quotes.manage in its own right, and the button is hidden from anyone without both. If the CRM alone let people build quotes it would simply be a cheaper way to buy the quoting module — so give the consultants who quote both seats.

The rate-gap split is deliberate for the opposite reason. Fixing a gap means editing a rate sheet, which is a rates job, usually done by somebody who holds no CRM or quote seat at all. Putting the worklist behind a seat would have hidden the work from the only people who can do it.

Managerial roles bypass the permission checks, so an owner always sees everything. A seat, on the other hand, is billing — managerial roles can reach the CRM screens without one, but ordinary team members cannot.

The enquiry inbox

When somebody enquires through one of your published itineraries, two things happen: the enquiry is recorded, and the consultant on that itinerary gets an email.

Work from the inbox, not from the email. The consultant notification is deliberately rate-limited to five per link per hour — a protection against a single popular itinerary flooding an inbox. That limit means a burst of enquiries in one hour produces a handful of emails and nothing more. Every enquiry, emailed or not, appears in CRM → Enquiries. The inbox is the complete record; the email is a convenience.

From the inbox you can:

  • Convert an enquiry into a lead. Tourium matches the enquiry's email against your existing contacts and tells you, before you commit, whether it will reuse a contact you already have or create a new one. Converting twice — a double-click, two people acting at once — cannot create two leads; the second attempt simply shows you the lead that already exists.
  • Dismiss an enquiry that is spam or a duplicate, and restore it later if you were wrong.

Good to know

  • Contacts are one per email address, per brand. A couple sharing one mailbox is one contact — the person you correspond with. The travellers themselves are recorded as the party size on the lead. If somebody genuinely has a second address, put it in the alternative-email field.
  • Moving a card back where it came from does nothing, on purpose. It does not restart the stage clock or write a history entry.
  • A won or lost stage cannot be retired, and neither can a stage still holding open leads, or the last stage standing.
  • Renaming a stage is safe. The automatic moves Tourium makes when a quote is sent or accepted follow the stage's underlying identity, not its label.
  • Accepting a quote moves the lead to provisional and stops there. Bookings, supplier confirmations and client money are a later phase; the "Convert to booking" button on a lead is a placeholder for it.
  • Seat charges appear on the Billing page as an add-on line item, and one-off prorated charges show under On-demand charges on the Invoices page.

Appendix — loading data at onboarding (Tourium operators)

Not a self-serve feature. Importing a client list is part of the white-glove onboarding a Tourium engineer runs against a tenant's database; there is no upload screen, and there is deliberately no --all-tenants mode, because a CSV is one organisation's data and a mistyped sweep would be a data-protection incident.

Three commands, in this order:

php artisan crm:import-agencies --tenant={tenant} --dry-run  path/to/agencies.csv
php artisan crm:import-contacts --tenant={tenant} --dry-run  path/to/contacts.csv
php artisan crm:link-quotes-to-contacts --tenant={tenant} --dry-run

Agencies first, always. A contact row naming an agency is resolved against the agencies already in that brand and is rejected if the name is not there. It never creates a stub agency (a misspelling would become a permanent duplicate that looks real in every picker) and never silently nulls the link (the contact would look like a direct traveller forever).

Dry-run first, then the fix loop. Run with --dry-run to see what would happen without writing anything. Then run for real with --report=rejected.csv: rejected rows are written back out verbatim, in the delimiter they arrived in, with a reason column. Correct that file and re-run it. A run with any rejection exits non-zero even though its accepted rows were written — a pilot reported as "loaded" while forty rows sit in a scrollback buffer is the failure this prevents.

Re-running a file is safe, with one exception. Rows are matched against the database's own unique indexes (lower(name) for agencies, lower(email) for contacts, both brand-scoped) and matched rows are updated in place, so an interrupted import can simply be run again. A contact row with no email has no natural key: it is imported, with a loud warning naming the count, and re-running that file will create those rows a second time. Do not re-run a file containing keyless rows — either give those rows an email and re-run only them, or accept the import as final.

crm:link-quotes-to-contacts is the one-off historical backfill: it matches quotes created before the CRM existed to contacts by email address. It is not required for the CRM to work — the contact page also matches on email at read time, so a direct-created quote shows up against its contact before any backfill has run.

The import commands deliberately do not check that the tenant holds the CRM module. Loading a prospect's client list is part of the pitch, and happens before anything is bought; the module gate is a UI and route concern and is fully applied there.