What does the standard Odoo portal already give a B2B customer?
More than most teams realise before they scope a build. Out of the box, a portal user linked to a customer can sign in and see that customer’s quotations, sales orders, invoices, and delivery information, download documents, and communicate through the portal. For a straightforward B2B relationship — one customer account, a handful of buyers, standard pricing — that is frequently enough, and the honest scoping answer is “turn it on and configure it.”
Our illustrative supplier sells industrial components to a few hundred trade accounts. Their portal ambitions sound simple: buyers should see approved quotes and order history, check what is outstanding, and stop phoning the sales office for copies of documents. The standard portal covers the document part on day one. The scoping work is in the two words “approved” and “buyers” — because their accounts are not simple.
Where does the standard portal stop being enough?
Three requirements push this supplier past configuration, and they are the three that push most B2B portal projects into custom development:
- Buyer hierarchy. A trade account has a head-office buyer who may see all branches’ orders, branch buyers who may see only their branch, and a finance contact who sees invoices but not pricing discussions. The standard portal’s rule — a portal user sees their partner’s records — has no concept of branch-level subsets within one customer.
- Approval before visibility. Internally, sales reps draft quotations that go through margin review. The customer must only ever see a quotation after it is approved; a draft that leaks into the portal is a pricing incident. The standard portal keys visibility off the quotation’s state in ways that do not map neatly onto this supplier’s internal review states.
- Negotiated catalogue. Each account has contract pricing and, for some, a restricted product range. The portal ordering experience has to show the account’s products at the account’s prices — and must not accidentally surface another account’s contract range through search or direct links.
Each of these is an access-logic requirement. That is the signal: when the scoping conversation keeps returning to who may see what, the project is a security-sensitive custom module, and it should be planned like one.
Architecture: what a custom portal module actually contains
A custom B2B portal module in Odoo typically has four layers, and it is worth naming them because each carries a different kind of risk:
- Models. Usually extensions rather than new tables: fields on the partner or a small link model expressing the buyer hierarchy (which portal users belong to which branch of which account), plus flags that mark a quotation as portal-approved.
- Controllers. The HTTP routes behind the portal pages. Custom controllers replace or extend the standard ones wherever the visibility logic differs — the buyer’s order list, the quotation detail page, the catalogue view. Every controller is a door; each one must check who is knocking.
- Access rules. Access control lists (which models a portal user may read at all) and record rules (which rows within those models). This layer is the real security boundary — the controller decides what to render, but the record rules are what stop a manipulated URL from returning another branch’s order.
- Templates. The QWeb views. Lowest risk, highest visibility — and the layer teams over-invest in while under-investing in the two above it.
The scoping mistake to avoid is budgeting this as a “website project.” It is an access-control project with a website attached.
The audit a developer must run before go-live
Because the portal’s promise is “a buyer sees only their own company’s data,” the pre-launch audit is not optional polish. A developer should be able to produce evidence for each of these:
- ACL review: every model the portal touches has an explicit access entry for the portal group — no model is reachable by accident, and nothing internal (costs, margins, internal notes) is readable by portal users.
- Record-rule tests: scripted checks with two buyer accounts from different branches of the same customer, and two from different customers, attempting to read each other’s quotations and orders by direct URL and by search — all must fail.
- Cross-company isolation: if the database runs multiple companies, portal users of company A must get nothing from company B, including via attachments and document downloads.
- State leakage: quotations in every internal state (draft, under review, rejected) are requested through the portal to confirm only approved states render.
- Attachment sweep: files attached to visible records are checked — a record can be correctly hidden while its attachment stays downloadable if attachment rules were not scoped with the same care.
Threat checklist for scoping conversations
Use this checklist in the scoping workshop. Any row the team cannot answer is a design task, not a detail to leave for later:
| Threat | Question to answer | Where it is handled |
|---|---|---|
| Buyer opens another branch’s order by guessing its URL | Do record rules scope portal reads to the buyer’s branch? | Record rules + controller checks |
| Unapproved quotation becomes visible | Which states are portal-visible, and who can set them? | Model flag + workflow design |
| Contract pricing leaks via search results | Does catalogue search filter by the account’s agreed range? | Controller + catalogue rules |
| Attachment from a hidden record downloads directly | Are attachment access rules aligned with record rules? | ACL / ir.attachment rules |
| Deactivated buyer keeps access after leaving the customer | What is the offboarding step, and who owns it? | Process + user administration |
| Multi-company data crosses over | Are portal rules company-scoped and tested? | Record rules with company conditions |
Standard portal vs custom module: a feature comparison
| Capability | Standard portal | Custom portal module |
|---|---|---|
| Customer sees own quotes, orders, invoices | Yes, out of the box | Yes |
| Document downloads and portal messaging | Yes | Yes |
| Branch-level visibility within one account | No | Yes, with hierarchy modelling |
| Visibility gated on internal approval states | Limited | Yes, designed per workflow |
| Account-specific catalogue and contract range | Pricelists only | Yes, with filtered search |
| Buyer roles (purchasing vs finance views) | Single portal view | Yes, role-based controllers |
| Security audit surface | Odoo’s tested defaults | Your team’s responsibility |
That last row is the honest trade-off. The standard portal inherits years of hardening. A custom module gives you the access logic your B2B relationships actually need — at the price of owning the audit yourself.
Frequently asked questions
Can we start standard and customise later?
Yes, and it is often the right sequence: launch the standard portal for document access, watch what customers actually ask for, and scope the custom module against real demand. The one caution: do not promise branch-level visibility dates until the access design exists.
Does a custom portal need its own user licences?
Portal users are external users in Odoo’s model and are generally treated differently from internal users, but licensing terms vary by edition and contract. Confirm the position for your edition during scoping rather than assuming.
How do we handle a buyer who works for two of our customers?
As two separate portal identities or one identity with carefully designed rules — a real scoping decision, because the record rules must keep both relationships’ data separated while the human experiences one login. Raise it early; it is much harder to retrofit.
What is the single most common portal security mistake?
Hiding a link in the interface and calling it security. If the record rule allows the read, the record is accessible — the missing menu item only hides it from honest users.
Next step
Scope the access logic before the screens: the buyer hierarchy, the approval states, and the audit evidence you will demand at go-live. Scope a GitHub-ready B2B portal module with Module Builder — where the controllers, models, and access rules are generated as reviewable code your team can test, rather than as promises in a slide deck.



