Portal Module
The Portal module provides a customer/vendor self-service interface where external users can view their documents (invoices, orders, etc.) without needing backend access.
Overview
Section titled “Overview”The portal system consists of:
- PortalAction - Configuration records that define which models are accessible in the portal
- Portal Views -
PortalListandPortalDetailview types for displaying documents - WebBlocks - Jinja templates for rendering portal pages
- Theme Integration - Inherits styling from website theme when installed
Making a Model Available in Portal
Section titled “Making a Model Available in Portal”To expose a model in the customer portal, create a PortalAction record:
- data_type: PortalAction identifier: portal_invoices name: Invoices model: FinancialDocument module: invoicing icon: bi-receipt sequence: 20 contact_field: contact global_filter: "Q(type__in=['Customer Invoice', 'Credit Note'])" list_view: invoice_portal_list detail_view: invoice_portal_detail active: truePortalAction Fields
Section titled “PortalAction Fields”| Field | Type | Description |
|---|---|---|
identifier | string | Unique identifier (used in URL: /portal/{identifier}) |
name | string | Display name in navigation sidebar |
model | string | Target model name |
module | string | Module that owns this portal action |
icon | string | Bootstrap icon class (e.g., bi-receipt) |
sequence | integer | Order in navigation (lower = first) |
contact_field | string | Field linking records to portal user’s contact |
global_filter | string | Q expression to filter records (e.g., only show certain types) |
list_view | string | Identifier of PortalList view |
detail_view | string | Identifier of PortalDetail view |
active | boolean | Whether this portal action is enabled |
Portal Views
Section titled “Portal Views”Portal views use the same UiView system as backend views but with types PortalList and PortalDetail.
PortalList View
Section titled “PortalList View”Displays a table of records with search, sorting, and pagination.
- data_type: UiView name: invoice_portal_list identifier: invoice_portal_list type: PortalList model: FinancialDocument arch: - content: - type: field name: number properties: widget: Text label: Number fw: 600 - type: field name: date properties: widget: Date label: Date - type: field name: state properties: widget: Badge label: Status colors: Draft: gray Posted: green Cancelled: red - type: field name: total_amount properties: widget: Monetary label: Total fw: 600Sortable Columns
Section titled “Sortable Columns”The following field names are automatically sortable: name, date, state, total, number, created_date.
PortalDetail View
Section titled “PortalDetail View”Displays a single document with structured layout. The architecture supports:
- Info Panel Fields - Displayed in the left sidebar
- Action Buttons - Displayed in the left sidebar
- Document Content - Rows, columns, cards, and fields
- data_type: UiView name: invoice_portal_detail identifier: invoice_portal_detail type: PortalDetail model: FinancialDocument arch: # Info panel fields (sidebar) - type: field name: total_amount properties: display_mode: info_panel label: Total Amount widget: Monetary
# Action buttons (sidebar) - type: actionButton properties: label: Download PDF icon: bi-download report: financial_document_print variant: secondary
# Document header - type: row content: - type: column span: 8 content: - type: field name: number properties: widget: Text size: xl fw: 700 noLabel: true - type: column span: 4 properties: style: "text-align: right;" content: - type: field name: state properties: widget: Badge noLabel: true
# Content cards - type: card title: Invoice Details icon: bi-info-circle content: - type: row content: - type: column span: 3 content: - type: field name: date properties: widget: Date label: Invoice Date
# Lines with totals - type: field name: lines properties: widget: List view: invoice_line_portal_list title: Invoice Lines icon: bi-receipt totals: - name: subtotal label: Subtotal widget: Monetary - name: total_amount label: Total widget: Monetary fw: 600
# Messages section - type: messagesArchitecture Elements
Section titled “Architecture Elements”Layout Elements
Section titled “Layout Elements”| Element | Description |
|---|---|
row | Horizontal container (12-column grid) |
column | Vertical container with span (1-12) |
card | Card container with title and optional icon |
divider | Visual separator |
Column Properties
Section titled “Column Properties”Columns support generic style and class properties for flexibility:
- type: column span: 4 properties: style: "text-align: right;" class: "custom-class" content: - type: field name: stateField Elements
Section titled “Field Elements”| Element | Description |
|---|---|
field | Data field with widget |
actionButton | Button for actions (download, sign, etc.) |
messages | Chatter/messaging section |
Special Field Properties
Section titled “Special Field Properties”| Property | Description |
|---|---|
display_mode: info_panel | Show field in sidebar info panel |
noLabel: true | Hide field label |
visible: Q(...) | Conditional visibility using Q expressions |
fw: 600 | Font weight (400, 500, 600, 700) |
size: xl | Text size (sm, md, lg, xl) |
Widgets
Section titled “Widgets”Portal views support these widgets:
| Widget | Description |
|---|---|
Text | Plain text display |
Date | Formatted date |
Badge | Status badge with colors |
Monetary | Currency-formatted amount |
Number | Numeric value |
Html | HTML content |
List | Embedded list (for lines) |
Badge Widget
Section titled “Badge Widget”- type: field name: state properties: widget: Badge colors: Draft: gray Posted: green Paid: teal Cancelled: redList Widget with Totals
Section titled “List Widget with Totals”For order/invoice lines, use the List widget with embedded totals:
- type: field name: lines properties: widget: List view: sale_order_line_portal_list title: Order Lines icon: bi-box-seam totals: - name: subtotal label: Subtotal widget: Monetary - name: total_tax label: Tax widget: Monetary - name: total label: Total widget: Monetary fw: 600Info Panel (Sidebar)
Section titled “Info Panel (Sidebar)”Fields marked with display_mode: info_panel appear in the left sidebar:
- type: field name: total_amount properties: display_mode: info_panel label: Total Amount widget: MonetaryMonetary fields display prominently. Other field types display as label/value pairs.
Action Buttons
Section titled “Action Buttons”Action buttons appear in the sidebar and can trigger:
Report Download
Section titled “Report Download”- type: actionButton properties: label: Download PDF icon: bi-download report: sale_order_print variant: secondaryMethod Call
Section titled “Method Call”- type: actionButton properties: label: Confirm Order icon: bi-check method: action_confirm variant: primary confirm: "Are you sure you want to confirm?"Signature Modal
Section titled “Signature Modal”- type: actionButton properties: label: Accept & Sign icon: bi-pen method: action_confirm modal: signature variant: primary visible: Q(state__eq='Draft')Button Variants
Section titled “Button Variants”| Variant | Description |
|---|---|
primary | Prominent action (dark background) |
secondary | Standard action (outlined) |
success | Positive action (green) |
Conditional Visibility
Section titled “Conditional Visibility”Use Q expressions for conditional visibility on fields, cards, and actions:
# Show only when state is Draftvisible: Q(state__eq='Draft')
# Show only when field has valuevisible: Q(terms_conditions__isnull=False) & Q(terms_conditions__neq='')
# Show for Posted invoicesvisible: Q(state__eq='Posted')Messages Section
Section titled “Messages Section”Add a messaging/chatter section to allow portal users to communicate:
- type: messagesThis renders the document’s message history and allows adding new messages.
Conditional Cards
Section titled “Conditional Cards”Cards can have visibility conditions:
- type: card title: Terms & Conditions icon: bi-file-text properties: visible: Q(terms_conditions__isnull=False) & Q(terms_conditions__neq='') content: - type: field name: terms_conditions properties: widget: Html noLabel: trueTheme Integration
Section titled “Theme Integration”The portal automatically integrates with the website theme when installed:
- Uses theme CSS variables (
--theme-primary,--theme-background, etc.) - Inherits navigation header and footer
- Falls back to standalone portal header when website module is not installed
CSS Variables
Section titled “CSS Variables”Portal styles use these CSS variables with theme fallbacks:
:root { --portal-accent: var(--theme-primary, #1a1a1a); --portal-background: var(--theme-background, #fafafa); --portal-surface: var(--theme-surface, #ffffff); --portal-border: var(--theme-border, #dee2e6); --portal-text: var(--theme-text, #212529); --portal-text-muted: var(--theme-text_muted, #6c757d);}Complete Example
Section titled “Complete Example”Here’s a complete portal configuration for a Sales Order:
Portal Action
Section titled “Portal Action”- depends: portal_views data_type: PortalAction identifier: portal_orders name: Orders model: SaleOrder module: sales icon: bi-cart sequence: 10 contact_field: contact list_view: sale_order_portal_list detail_view: sale_order_portal_detail active: trueList View
Section titled “List View”- data_type: UiView name: sale_order_portal_list identifier: sale_order_portal_list type: PortalList model: SaleOrder arch: - content: - type: field name: name properties: widget: Text label: Number fw: 600 - type: field name: date properties: widget: Date label: Date - type: field name: state properties: widget: Badge label: Status colors: Draft: gray Confirmed: green Done: teal Cancelled: red - type: field name: total properties: widget: Monetary label: Total fw: 600Detail View
Section titled “Detail View”- data_type: UiView name: sale_order_portal_detail identifier: sale_order_portal_detail type: PortalDetail model: SaleOrder arch: # Sidebar: Info panel - type: field name: user properties: display_mode: info_panel label: Your Contact - type: field name: total properties: display_mode: info_panel label: Total Amount widget: Monetary
# Sidebar: Actions - type: actionButton properties: label: Download PDF icon: bi-download report: sale_order_print variant: secondary - type: actionButton properties: label: Accept & Sign icon: bi-pen method: action_confirm modal: signature variant: primary visible: Q(state__eq='Draft')
# Header row - type: row content: - type: column span: 8 content: - type: field name: name properties: widget: Text size: xl fw: 700 noLabel: true - type: column span: 4 properties: style: "text-align: right;" content: - type: field name: state properties: widget: Badge noLabel: true colors: Draft: gray Confirmed: green Done: teal Cancelled: red
# Order details card - type: card title: Order Details icon: bi-info-circle content: - type: row content: - type: column span: 3 content: - type: field name: date properties: widget: Date label: Order Date - type: column span: 3 content: - type: field name: validity_date properties: widget: Date label: Valid Until visible: Q(state__eq='Draft') - type: column span: 3 content: - type: field name: commitment_date properties: widget: Date label: Delivery Date - type: column span: 3 content: - type: field name: payment_terms properties: widget: Text label: Payment Terms
# Order lines with totals - type: field name: lines properties: widget: List view: sale_order_line_portal_list title: Order Lines icon: bi-box-seam totals: - name: subtotal label: Subtotal widget: Monetary - name: total_tax label: Tax widget: Monetary - name: total label: Total widget: Monetary fw: 600
# Terms & Conditions (conditional) - type: card title: Terms & Conditions icon: bi-file-text properties: visible: Q(terms_conditions__isnull=False) & Q(terms_conditions__neq='') content: - type: field name: terms_conditions properties: widget: Html noLabel: true
# Messages - type: messagesLines View
Section titled “Lines View”- data_type: UiView name: sale_order_line_portal_list identifier: sale_order_line_portal_list type: PortalList model: SaleOrderLine arch: - content: - type: field name: description properties: widget: Text label: Item - type: field name: quantity properties: widget: Number label: Qty - type: field name: unit_price properties: widget: Monetary label: Unit Price - type: field name: subtotal properties: widget: Monetary label: AmountURL Structure
Section titled “URL Structure”Portal URLs follow this pattern:
| URL | Description |
|---|---|
/portal | Portal home page |
/portal/{identifier} | Document list |
/portal/{identifier}/{id} | Document detail |
/portal/{identifier}/{id}/report/{report_id} | PDF report download |
/portal/{identifier}/{id}/action/{method} | Execute action |
Security
Section titled “Security”Portal access is controlled by:
- Authentication - Users must be logged in with portal access
- Contact Filtering - Records are filtered by
contact_fieldto show only the user’s documents - Global Filter - Additional Q expression filtering (e.g., only show customer invoices, not vendor bills)
- Model Collaboration - The model should have
_collaborate = Trueand_collaborate_contactconfigured