Account Setup (Quick Setup + Finish Setup): Build Brief
Overview
This lives in a new Odoo app, Account Setup, delivered as the module menmd_account_setup on menmd_digital_account_setup.
Area | Status |
|---|---|
Quick Setup form on the booth iPad (kiosk), in two steps: Details, then Agreement | Built, tested locally |
Signup Links: per-rep shareable links and QR codes, no PIN | Built, tested locally |
Drop-off tracking: Signup Funnel and Abandoned Signups reports | Built, tested locally |
Matching, duplicate handling, and review queue | Built, tested locally |
Territory routing by stateua and ZIP | Built, tested locally |
Signed agreement PDF, portal user, welcome email | Built, tested locally |
CRM opportunity and salesperson notification | Built |
Brands (menMD, Evitalin) applied to kiosk, email, and PDF | Built, tested locally |
Per-show opportunity tags, conference-attendee setting, and How Did You Hear value | Built |
Card capture through Authorize.net | Built; card entry needs HTTPS, so tested on UAT |
Minimal Finish Setup page (add a card) | Built; card entry tested on UAT |
Reporting by show, rep, and first order | Built |
First-vial code (Ticket 2) | Not started; waiting on business definition |
For the business team
A practice can now open an account at the booth in about 3 minutes on an iPad, with no DEA or license numbers needed. Those come later through Finish Setup.
At the booth
- The rep unlocks the iPad with the show PIN, picks the show, and picks their own name. The tablet remembers both for every signup that day.
- Details: the prospect fills in practice and address, primary prescriber and NPI, contact email and phone, and who pays (Practice Pay, Patient Pay, or Hybrid), then taps Next: Review agreement. Everything is checked before moving on.
- Agreement: the full agreement on its own screen, two checkboxes, and a finger signature. Back returns to the details with everything still filled in.
- Payment: the card step. Patient Pay can skip it; Practice Pay and Hybrid can also skip, and get a link to add the card later.
- A confirmation screen shows, then the iPad resets to a blank form. It also resets after 2 minutes of no activity, so the next person never sees prior answers.
A progress bar at the top shows Details > Agreement > Payment.
What happens automatically
- The practice, prescriber, and (if staff signed up) the office staff contact are created, or matched to existing records so nothing is duplicated.
- The account is assigned to the territory salesperson by state and ZIP; the booth rep gets credit as Sales Rep.
- The show is recorded as the account source and lead source. For trade shows, contacts are also tagged as attendees of that conference; field-signup shows can turn this off.
- A CRM opportunity is opened for the territory salesperson, tagged as set on the show (e.g. Conference for A4M, a field tag for in-field signups). If the practice already has an open opportunity, that one is used.
- The territory salesperson gets a to-do on the practice with the signup details, the same way portal self-registrations notify the team.
- A signed agreement PDF is attached to the practice, and also appears in their portal under Signatures.
- A welcome email goes out right away with a set-password link, catalog and first-order links, and a Finish Setup link.
When a rep needs to step in
If a signup looks inconsistent (for example, the NPI belongs to someone with a different name, or matches a different practice), it is marked Needs Review. The rep gets a to-do, and the welcome email, portal access, opportunity, and salesperson notification are held until the rep checks the records and clicks Approve and Send Welcome.
Branding
Each show is set to a brand. A menMD show is all menMD (kiosk, email, and PDF); an Evitalin show is all Evitalin. This gives us the ability to create "shows" based on the company. We will have the ability to choose menMD, Evitalin, or even create one for PharmaLabs if we decided to go to any shows as PharmaLabs in the future.
Signup links (outside the booth)
Reps can send the same signup form to prospects by email, text, or QR code. Each rep creates their own link under Account Setup > Signup Links, tied to a show (usually a field-signup show). The prospect opens it on their own device: no PIN or rep picker, the same Details > Agreement > Payment flow, and the signup is credited to the link's rep. Links can expire, be archived, or be given a new URL.
Seeing where people drop off
Every signup attempt is tracked from the first keystroke to the confirmation screen, so we can see how many people start, finish their details, reach the agreement, submit, and complete, and where the rest stop. Attempts idle for 30 minutes without finishing are marked Abandoned. Only progress is recorded: no names, emails, or anything typed into the form.
For admins: setting it up
Everything is configured in the Account Setup app. Configuration menus are visible to Account Setup Managers only.
What | Where | Notes |
|---|---|---|
Roles | Settings > Users > Account Setup | User: sees setups, approves reviews, manages their own signup links. Manager: also manages shows, brands, territories, and everyone's links |
Brands | Configuration > Brands | Name, logo, primary color, sender email, website, footer address and phone |
Territory Assignments | Configuration > Territory Assignments | One row per state; split a state with ZIP prefixes plus one blank-prefix row as the state default |
Shows | Shows | Name, code (e.g. A4M-2026), dates, brand, kiosk PIN, payment provider (PharmaLabs), fallback salesperson, reps, agreement text, welcome email links |
Show: Opportunity Tags | Shows > Setup | The exact CRM tags set on each new opportunity (same list as the opportunity's Tags field) |
Show: How Did You Hear About Us | Shows > Setup | Set on new contacts. Conference for trade shows, Representative for field signups |
Show: Tag Contacts as Conference Attendees | Shows > Setup | On for trade shows; off for field-signup shows so contacts aren't listed as conference attendees |
Signup Links | Signup Links | Label, show, rep credited, optional expiry. After saving: the link with a copy button, a QR code, and Opens, Started, Signups, and Abandoned counts |
Drop-off reports | Reporting > Signup Funnel, Abandoned Signups | Steps reached by show, rep, channel, and link; where abandoned attempts stopped |
Welcome email copy | Settings > Technical > Email Templates > "Account Setup: Welcome Email" | Edits made here survive module updates |
How routing picks a salesperson: the longest ZIP prefix match in the practice's state, then that state's default row, then the show's fallback salesperson. Existing accounts keep their salesperson.
Field signups: for reps signing up practices outside a show, create one long-running show per brand (e.g. "Evitalin Field Signups", end date 12/31/2099) with its own opportunity tag, How Did You Hear set to Representative, and Tag Contacts as Conference Attendees turned off. Reps then create Signup Links on that show. No PIN or reps list is needed for links.
After a show: archive it so it no longer appears on the kiosk; its setups stay linked for reporting.
Technical summary
One new Odoo 17 module, menmd_account_setup, installed as the Account Setup app. It reuses existing code by calling it and makes no changes to other modules, including the payment modules.
Dependencies: mail, contacts, crm, website, portal, auth_signup, sign, payment, bista_menmd_customization, bista_menmd_website.
Models
Model | Purpose |
|---|---|
account.setup.event | Show config: code, dates, brand, hashed kiosk PIN, payment provider, fallback salesperson, reps, opportunity tags, How Did You Hear value, conference-attendee toggle, agreement text, email links |
account.setup.submission | One record per signup: every answer, signature and audit data (IP, device, time), match result, card status, channel (kiosk or link), signup link, linked opportunity, Finish Setup token, idempotency key |
account.setup.link | Signup link: show, rep credited, random token, optional expiry, URL, QR code, open count |
account.setup.attempt | Drop-off tracking: show, rep, channel, link, furthest step and the time of each step, status (in progress, completed, abandoned). No personal details |
account.setup.brand | Logo, color, sender email, website, footer details |
account.setup.rep.mapping | Territory assignments by state and ZIP prefix |
res.partner (extended) | Treatment center fields: pay model, setup show, setup rep, setup status and date, first order flag; Account Setup tab |
Fields written on existing models
Record | Fields |
|---|---|
Treatment center | z_contact_record_type = treatment_center, is_company, user_id (territory), sales_rep (booth rep), z_account_source_custom (account.source = show code), pay model and setup fields |
Provider | parent_id, z_npi_number, z_healthcare_provider_type = new_menmd_provider, z_how_did_you_hear_about_menMD = the show's setting, sales_rep, z_lead_source_custom (lead.source = show code), z_conference_attendee_tags (bs.conference = show code, added only when the show's toggle is on), terms fields |
Support staff | Same as provider, with z_contact_record_type and z_healthcare_provider_type = support_staff |
CRM opportunity (crm.lead) | Name "[Practice] - [show code]", partner_id = treatment center, user_id = territory salesperson, tag_ids = the show's Opportunity Tags, signup summary in the description |
Matched records only get blank fields filled (a Sales Rep of "Public user" counts as blank); conference tags are added (never replaced) when the show's toggle is on. Source and conference records are created from the show code if they don't exist.
Public routes
Route | Purpose |
|---|---|
/account-setup/kiosk, /kiosk/rep, /kiosk/lock | PIN unlock (5 tries, then a 5-minute lockout), rep picker, lock |
/account-setup, /submit, /done | Quick Setup form (two steps), submission, confirmation |
/account-setup/join/<token> | Signup link: the same form with no PIN; credit goes to the link's rep; unavailable-link page if archived or expired |
/account-setup/track | Progress pings from the form (step reached only, no form data) |
/account-setup/card, /card/skip, /card/return | Card step (kiosk and links) |
/account-setup/finish/<id>?access_token= | Finish Setup from the welcome email (token checked in constant time) |
/my/finish-setup, /my/account-agreements/<id> | Portal entry to Finish Setup; agreement download (treatment center members only) |
Processing on submit: validate (NPI check digit, ZIP, required fields), match prescriber by NPI then email then phone, match treatment center via the prescriber or by email, flag inconsistent matches for review, create or update records, route the salesperson, render the agreement PDF. For clean matches (or after a rep approves a review): create the portal user without Odoo's standard invitation, send the welcome email immediately (force_send), open or link the CRM opportunity, and schedule a weekday to-do for the territory salesperson on the treatment center. All in one savepoint, so a validation error creates nothing.
Payments: the card step and Finish Setup render Odoo's standard payment form in validation mode, limited to the show's provider (PharmaLabs Authorize.net) and to cards. Card data goes from the browser to Authorize.net (Accept.js); Odoo stores only the token on the treatment center. Accept.js requires HTTPS, so card entry cannot be tested on plain-HTTP local environments.
Security: Account Setup User and Manager groups; record rules so reps see only their own signup links and attempts; public pages run behind the kiosk session, a signup link token, or a per-submission token; honeypot field and idempotency key on the form; signup links capped at 10 submissions per hour per connection; welcome email template is noupdate.
Drop-off tracking: an attempt is created on the first keystroke (not on page load, so kiosk resets and email scanners don't count) and moves forward as steps are reached. A scheduled action runs every 15 minutes and marks attempts idle for 30 minutes as abandoned.
How to test
UAT setup
- Give testers the Account Setup Manager role
- Create brands: Evitalin and menMD
- Add territory assignments, including the Florida split and a Florida default row
- Create a test show: brand, today inside its dates, PIN, reps, PharmaLabs provider, fallback salesperson, sample agreement text
- Create a field-signup show (How Did You Hear = Representative, conference toggle off, a field opportunity tag) and a Signup Link on it
Test data
- Valid test NPIs: 1000000012, 1182736458, 1428571420, 1564738296, 2020202026 (each creates a new prescriber the first time)
- Invalid NPI: 1234567890
- Sandbox card: Visa 4111 1111 1111 1111, any future expiry, any CVV; a billing ZIP of 46282 triggers a decline
Test script
To test directly in browser from the user facing form, use the following slug: /account-setup/kiosk for the kiosk, or the URL on a Signup Link for the remote form. Use a private window so you aren't logged in.
# | Test | Pass when |
|---|---|---|
1 | Kiosk: wrong PIN, right PIN, pick rep, Change rep, Lock | Wrong PIN rejected; Change rep asks for the PIN again; Lock returns to the PIN screen |
2 | New Practice Pay signup with the sandbox card | Card Status = Captured; token on the treatment center; confirmation shows; iPad resets |
3 | Signup, skip the card, then add it from the welcome email's Finish Setup link | Card Status changes from Pending to Captured; note on the submission |
4 | Declined card (billing ZIP 46282) | Account still saves; Card Status stays Pending |
5 | Patient Pay signup, Skip for now | Card Status = Not Required |
6 | Same NPI and practice again | Matched Existing; no duplicate records or opportunities; conference tag not duplicated |
7 | Same NPI, different last name or practice | Needs Review; no portal user, email, opportunity, or to-do until Approve and Send Welcome |
8 | Office staff signup ("No, I'm office staff") | Support staff contact under the treatment center |
9 | Form validation: empty fields, bad NPI, 4-digit ZIP on step 1; unchecked boxes and no signature on step 2 | Clear message under the Next or Create account button; nothing created |
10 | Two steps: sign, go Back, return without changes; then go Back and change a name | Signature kept the first time; cleared after a change |
11 | Routing: ZIPs in each Florida region and an unmapped state | Correct salesperson; fallback used with a note |
12 | CRM follow-up on a new signup | Opportunity owned by the territory salesperson with exactly the show's tags; to-do for that salesperson on the treatment center |
13 | Field-signup show (conference toggle off, field tag) | Contacts get no conference attendee tag; How Did You Hear = Representative; opportunity carries the field tag |
14 | Signup Link in a private window | No PIN; full signup works; Signed Up Through = Signup Link; credited to the link's rep; link's Signups count goes up |
15 | Archived or expired Signup Link | "This signup link isn't available" page |
16 | Drop-off: start a link signup, stop at the agreement, close the tab | Attempt shows Agreement Reached; after 30 minutes it appears in Abandoned Signups |
17 | Kiosk left idle through a few resets without typing | No signup attempts recorded |
18 | Welcome email through SES | Arrives within 5 minutes; brand logo, links, and password link work |
19 | Portal as the new user | Agreement listed on /my/signatures; /my/finish-setup opens their setup |
20 | Full flow on an MDM-enrolled iPad over cellular | Under 3 minutes; signature pad works; no AutoFill suggestions; idle reset after 2 minutes |
21 | Brand switch: same flow on a menMD show | Kiosk, email, and PDF all show menMD |
22 | Reporting > Setups Analysis and Signup Funnel | Setups by show, by rep, and first order; funnel counts per step by show, rep, and channel |
All of these except the card entry itself (tests 2 to 4) can also be run locally.
Open items before the Dec 1 freeze
Only the first-vial code blocks an acceptance criterion; the rest is content and small decisions.
- First-vial code (Ticket 2): what it gives, what it applies to, how long it lasts, single use or not, and who gets one. The welcome email hides the code section until it exists.
- Agreement text: final wording from legal, plus sign-off on the e-sign consent wording