# Fusion Authorizer & Sales Portal

**Version:** 19.0.1.0.0  
**License:** LGPL-3  
**Category:** Sales/Portal  
**Author:** Fusion Claims

## Table of Contents

1. [Overview](#overview)
2. [Features](#features)
3. [Installation](#installation)
4. [Configuration](#configuration)
5. [Models](#models)
6. [Controllers & Routes](#controllers--routes)
7. [Security](#security)
8. [Frontend Assets](#frontend-assets)
9. [Email Templates](#email-templates)
10. [User Guide](#user-guide)
11. [API Reference](#api-reference)
12. [Troubleshooting](#troubleshooting)
13. [Changelog](#changelog)

---

## Overview

The **Fusion Authorizer & Sales Portal** module extends Odoo's portal functionality to provide external access for two key user types:

- **Authorizers (Occupational Therapists/OTs):** Healthcare professionals who authorize ADP (Assistive Devices Program) claims
- **Sales Representatives:** Field sales staff who conduct client assessments and manage orders

This module integrates with the `fusion_claims` module to provide a seamless workflow for ADP claims management, from initial client assessment through to order completion.

### Target Platform
- **Odoo Enterprise v19**
- Requires: `base`, `sale`, `portal`, `website`, `mail`, `fusion_claims`

---

## Features

### Authorizer Portal
- View all assigned ADP cases with full details (excluding internal costs)
- Real-time search by client name, reference numbers, or claim number
- Upload ADP application documents with revision tracking
- Add comments/notes to cases
- Download submitted ADP applications
- Receive email notifications for new assignments and status changes

### Sales Rep Portal
- View sales cases linked to the logged-in user
- Start and manage client assessments
- Record detailed wheelchair specifications and measurements
- Capture digital signatures for ADP pages 11 & 12
- Track assessment progress through workflow states

### Assessment System
- Comprehensive client information collection
- Wheelchair specifications (seat width, depth, height, cushion type, etc.)
- Accessibility and mobility needs documentation
- Touch-friendly digital signature capture
- Automatic draft Sale Order creation upon completion
- Document distribution to authorizers, sales reps, and internal records
- Automated email notifications

---

## Installation

### Prerequisites
1. Odoo Enterprise v19 installed and running
2. The `fusion_claims` module installed and configured
3. Portal module enabled
4. Website module enabled
5. Mail module configured with outgoing email server

### Installation Steps

1. **Copy the module** to your Odoo addons directory:
   ```bash
   cp -r fusion_authorizer_portal /path/to/odoo/custom-addons/
   ```

2. **Update the apps list** in Odoo:
   - Go to Apps menu
   - Click "Update Apps List"
   - Search for "Fusion Authorizer"

3. **Install the module**:
   - Click Install on "Fusion Authorizer & Sales Portal"
   - Wait for installation to complete

4. **Restart Odoo** (recommended):
   ```bash
   docker restart odoo-app  # For Docker installations
   # OR
   sudo systemctl restart odoo    # For systemd installations
   ```

---

## Configuration

### Granting Portal Access to Users

1. Navigate to **Contacts** in Odoo backend
2. Open the contact record for the authorizer or sales rep
3. Go to the **Portal Access** tab
4. Check the appropriate role:
   - `Is Authorizer` - For Occupational Therapists
   - `Is Sales Rep (Portal)` - For Sales Representatives
5. Click the **Grant Portal Access** button
6. An invitation email will be sent to the contact's email address

### Setting Up Authorizers on Sales Orders

1. Open a Sales Order
2. In the order details, set the **Authorizer** field (`x_fc_authorizer_id`)
3. The authorizer will receive an email notification about the assignment
4. The case will appear in their portal dashboard

---

## Models

### New Models

#### `fusion.assessment`
**Wheelchair Assessment Record**

Captures comprehensive client assessment data including:

| Field Group | Fields |
|-------------|--------|
| **Client Info** | `client_name`, `client_first_name`, `client_last_name`, `client_street`, `client_city`, `client_state`, `client_postal_code`, `client_country_id`, `client_phone`, `client_mobile`, `client_email`, `client_dob`, `client_health_card`, `client_reference_1`, `client_reference_2` |
| **Participants** | `sales_rep_id` (res.users), `authorizer_id` (res.partner) |
| **Assessment Details** | `assessment_date`, `assessment_location`, `assessment_location_notes` |
| **Measurements** | `seat_width`, `seat_depth`, `seat_to_floor_height`, `back_height`, `armrest_height`, `footrest_length`, `overall_width`, `overall_length`, `overall_height`, `seat_angle`, `back_angle`, `client_weight`, `client_height` |
| **Product Types** | `cushion_type`, `cushion_notes`, `backrest_type`, `backrest_notes`, `frame_type`, `frame_notes`, `wheel_type`, `wheel_notes` |
| **Needs** | `mobility_notes`, `accessibility_notes`, `special_requirements`, `diagnosis` |
| **Signatures** | `signature_page_11`, `signature_page_11_name`, `signature_page_11_date`, `signature_page_12`, `signature_page_12_name`, `signature_page_12_date` |
| **Status** | `state` (draft, pending_signature, completed, cancelled) |
| **References** | `reference` (auto-generated ASM-XXXXX), `sale_order_id`, `partner_id` |

**Key Methods:**
- `action_complete()` - Completes assessment, creates draft Sale Order, sends notifications
- `_ensure_partner()` - Creates or links res.partner for the client
- `_create_draft_sale_order()` - Generates Sale Order with specifications
- `_generate_signed_documents()` - Creates document records for signatures
- `_send_completion_notifications()` - Sends emails to authorizer and client

---

#### `fusion.adp.document`
**ADP Document Management with Revision Tracking**

| Field | Type | Description |
|-------|------|-------------|
| `sale_order_id` | Many2one | Link to Sale Order |
| `assessment_id` | Many2one | Link to Assessment |
| `document_type` | Selection | full_application, page_11, page_12, pages_11_12, final_submission, other |
| `file` | Binary | Document file content |
| `filename` | Char | Original filename |
| `file_size` | Integer | File size in bytes |
| `mimetype` | Char | MIME type |
| `revision` | Integer | Revision number (auto-incremented) |
| `revision_note` | Text | Notes about this revision |
| `is_current` | Boolean | Whether this is the current version |
| `uploaded_by` | Many2one | User who uploaded |
| `upload_date` | Datetime | Upload timestamp |
| `source` | Selection | portal, internal, assessment |

**Key Methods:**
- `action_download()` - Download the document
- `get_documents_for_order()` - Get all documents for a sale order
- `get_revision_history()` - Get all revisions of a document type

---

#### `fusion.authorizer.comment`
**Portal Comments System**

| Field | Type | Description |
|-------|------|-------------|
| `sale_order_id` | Many2one | Link to Sale Order |
| `assessment_id` | Many2one | Link to Assessment |
| `author_id` | Many2one | res.partner who authored |
| `author_user_id` | Many2one | res.users who authored |
| `comment` | Text | Comment content |
| `comment_type` | Selection | general, question, update, approval |
| `is_internal` | Boolean | Internal-only comment |

---

### Extended Models

#### `res.partner` (Extended)

| New Field | Type | Description |
|-----------|------|-------------|
| `is_authorizer` | Boolean | Partner is an Authorizer/OT |
| `is_sales_rep_portal` | Boolean | Partner is a Sales Rep with portal access |
| `authorizer_portal_user_id` | Many2one | Linked portal user account |
| `assigned_case_count` | Integer | Computed count of assigned cases |
| `assessment_count` | Integer | Computed count of assessments |

**New Methods:**
- `action_grant_portal_access()` - Creates portal user and sends invitation
- `action_view_assigned_cases()` - Opens list of assigned Sale Orders
- `action_view_assessments()` - Opens list of assessments

---

#### `sale.order` (Extended)

| New Field | Type | Description |
|-----------|------|-------------|
| `portal_comment_ids` | One2many | Comments from portal users |
| `portal_comment_count` | Integer | Computed comment count |
| `portal_document_ids` | One2many | Documents uploaded via portal |
| `portal_document_count` | Integer | Computed document count |
| `assessment_id` | Many2one | Source assessment that created this order |
| `portal_authorizer_id` | Many2one | Authorizer reference (computed from x_fc_authorizer_id) |

**New Methods:**
- `_send_authorizer_assignment_notification()` - Email on authorizer assignment
- `_send_status_change_notification()` - Email on status change
- `get_portal_display_data()` - Safe data for portal display (excludes costs)
- `get_authorizer_portal_cases()` - Search cases for authorizer portal
- `get_sales_rep_portal_cases()` - Search cases for sales rep portal

---

## Controllers & Routes

### Authorizer Portal Routes

| Route | Method | Auth | Description |
|-------|--------|------|-------------|
| `/my/authorizer` | GET | user | Authorizer dashboard |
| `/my/authorizer/cases` | GET | user | List of assigned cases |
| `/my/authorizer/cases/search` | POST | user | AJAX search (jsonrpc) |
| `/my/authorizer/case/<id>` | GET | user | Case detail view |
| `/my/authorizer/case/<id>/comment` | POST | user | Add comment to case |
| `/my/authorizer/case/<id>/upload` | POST | user | Upload document |
| `/my/authorizer/document/<id>/download` | GET | user | Download document |

### Sales Rep Portal Routes

| Route | Method | Auth | Description |
|-------|--------|------|-------------|
| `/my/sales` | GET | user | Sales rep dashboard |
| `/my/sales/cases` | GET | user | List of sales cases |
| `/my/sales/cases/search` | POST | user | AJAX search (jsonrpc) |
| `/my/sales/case/<id>` | GET | user | Case detail view |

### Assessment Routes

| Route | Method | Auth | Description |
|-------|--------|------|-------------|
| `/my/assessments` | GET | user | List of assessments |
| `/my/assessment/new` | GET | user | New assessment form |
| `/my/assessment/<id>` | GET | user | View/edit assessment |
| `/my/assessment/save` | POST | user | Save assessment data |
| `/my/assessment/<id>/signatures` | GET | user | Signature capture page |
| `/my/assessment/<id>/save_signature` | POST | user | Save signature (jsonrpc) |
| `/my/assessment/<id>/complete` | POST | user | Complete assessment |

---

## Security

### Security Groups

| Group | XML ID | Description |
|-------|--------|-------------|
| Authorizer Portal | `group_authorizer_portal` | Access to authorizer portal features |
| Sales Rep Portal | `group_sales_rep_portal` | Access to sales rep portal features |

### Record Rules

| Model | Rule | Description |
|-------|------|-------------|
| `fusion.authorizer.comment` | Portal Read | Users can read non-internal comments on their cases |
| `fusion.authorizer.comment` | Portal Create | Users can create comments on their cases |
| `fusion.adp.document` | Portal Read | Users can read documents on their cases |
| `fusion.adp.document` | Portal Create | Users can upload documents to their cases |
| `fusion.assessment` | Portal Access | Users can access assessments they're linked to |
| `sale.order` | Portal Authorizer | Authorizers can view their assigned orders |

### Access Rights (ir.model.access.csv)

| Model | Group | Read | Write | Create | Unlink |
|-------|-------|------|-------|--------|--------|
| `fusion.authorizer.comment` | base.group_user | 1 | 1 | 1 | 1 |
| `fusion.authorizer.comment` | base.group_portal | 1 | 0 | 1 | 0 |
| `fusion.adp.document` | base.group_user | 1 | 1 | 1 | 1 |
| `fusion.adp.document` | base.group_portal | 1 | 0 | 1 | 0 |
| `fusion.assessment` | base.group_user | 1 | 1 | 1 | 1 |
| `fusion.assessment` | base.group_portal | 1 | 1 | 1 | 0 |

---

## Frontend Assets

### CSS (`static/src/css/portal_style.css`)

Custom portal styling with a dark blue and green color scheme:

- **Primary Color:** Dark blue (#1e3a5f)
- **Secondary Color:** Medium blue (#2c5282)
- **Accent Color:** Green (#38a169)
- **Background:** Light gray (#f7fafc)

Styled components:
- Portal cards with shadow effects
- Status badges with color coding
- Custom buttons with hover effects
- Responsive tables
- Form inputs with focus states

### JavaScript

#### `portal_search.js`
Real-time search functionality:
- Debounced input handling (300ms delay)
- AJAX calls to search endpoints
- Dynamic table updates
- Search result highlighting

#### `assessment_form.js`
Assessment form enhancements:
- Unsaved changes warning
- Auto-fill client name from first/last name
- Number input validation
- Form state tracking

#### `signature_pad.js`
Digital signature capture:
- HTML5 Canvas-based drawing
- Touch and mouse event support
- Clear signature functionality
- Export to base64 PNG
- AJAX save to server

---

## Email Templates

### Case Assignment (`mail_template_case_assigned`)
**Trigger:** Authorizer assigned to a Sale Order  
**Recipient:** Authorizer email  
**Content:** Case details, client information, link to portal

### Status Change (`mail_template_status_changed`)
**Trigger:** Sale Order state changes  
**Recipient:** Assigned authorizer  
**Content:** Previous and new status, case details

### Assessment Complete - Authorizer (`mail_template_assessment_complete_authorizer`)
**Trigger:** Assessment completed  
**Recipient:** Assigned authorizer  
**Content:** Assessment details, measurements, signed documents

### Assessment Complete - Client (`mail_template_assessment_complete_client`)
**Trigger:** Assessment completed  
**Recipient:** Client email  
**Content:** Confirmation, next steps, measurements summary

### Document Uploaded (`mail_template_document_uploaded`)
**Trigger:** Document uploaded via portal  
**Recipient:** Internal team  
**Content:** Document details, revision info, download link

---

## User Guide

### For Administrators

#### Granting Portal Access

1. Go to **Contacts** > Select the contact
2. Navigate to the **Portal Access** tab
3. Enable the appropriate role:
   - Check `Is Authorizer` for OTs/Therapists
   - Check `Is Sales Rep (Portal)` for Sales Reps
4. Click **Grant Portal Access**
5. The user receives an email with login instructions

#### Assigning Cases to Authorizers

1. Open a **Sale Order**
2. Set the **Authorizer** field to the appropriate contact
3. Save the order
4. The authorizer receives a notification email
5. The case appears in their portal dashboard

---

### For Authorizers

#### Accessing the Portal

1. Visit `https://your-domain.com/my`
2. Log in with your portal credentials
3. Click **Authorizer Portal** in the menu

#### Viewing Cases

1. From the dashboard, view recent cases and statistics
2. Click **View All Cases** or **My Cases** for the full list
3. Use the search bar to find specific cases by:
   - Client name
   - Client reference 1 or 2
   - Claim number

#### Adding Comments

1. Open a case detail view
2. Scroll to the Comments section
3. Enter your comment
4. Select comment type (General, Question, Update, Approval)
5. Click **Add Comment**

#### Uploading Documents

1. Open a case detail view
2. Go to the Documents section
3. Click **Upload Document**
4. Select document type (Full Application, Page 11, Page 12, etc.)
5. Choose the file and add revision notes
6. Click **Upload**

---

### For Sales Representatives

#### Starting a New Assessment

1. Log in to the portal
2. Click **New Assessment**
3. Fill in client information:
   - Name, address, contact details
   - Client references
4. Record wheelchair specifications:
   - Measurements (seat width, depth, height)
   - Product types (cushion, backrest, frame, wheels)
5. Document accessibility and mobility needs
6. Click **Save & Continue**

#### Capturing Signatures

1. After saving assessment data, click **Proceed to Signatures**
2. **Page 11 (Authorizer):**
   - Have the OT sign on the canvas
   - Enter their printed name
   - Click **Save Signature**
3. **Page 12 (Client):**
   - Have the client sign on the canvas
   - Enter their printed name
   - Click **Save Signature**

#### Completing the Assessment

1. Once both signatures are captured, click **Complete Assessment**
2. The system will:
   - Create a new customer record (if needed)
   - Generate a draft Sale Order
   - Attach signed documents
   - Send notification emails
3. The assessment moves to "Completed" status

---

## API Reference

### Assessment Model Methods

```python
# Complete an assessment and create Sale Order
assessment.action_complete()

# Get formatted specifications for order notes
specs = assessment._format_specifications_for_order()

# Ensure partner exists or create new
partner = assessment._ensure_partner()
```

### Sale Order Portal Methods

```python
# Get safe data for portal display (no costs)
data = order.get_portal_display_data()

# Search cases for authorizer
cases = SaleOrder.get_authorizer_portal_cases(
    partner_id=123,
    search_query='Smith',
    limit=50,
    offset=0
)

# Search cases for sales rep
cases = SaleOrder.get_sales_rep_portal_cases(
    user_id=456,
    search_query='wheelchair',
    limit=50,
    offset=0
)
```

### Partner Methods

```python
# Grant portal access programmatically
partner.action_grant_portal_access()

# Check if partner is an authorizer
if partner.is_authorizer:
    cases = partner.assigned_case_count
```

### Document Methods

```python
# Get all documents for an order
docs = ADPDocument.get_documents_for_order(sale_order_id)

# Get revision history
history = document.get_revision_history()
```

---

## Troubleshooting

### Common Errors

#### Error: `Invalid field 'in_portal' in 'portal.wizard.user'`

**Cause:** Odoo 19 changed the portal wizard API, removing the `in_portal` field.

**Solution:** The `action_grant_portal_access` method has been updated to:
1. First attempt using the standard portal wizard
2. If that fails, fall back to direct user creation with portal group assignment

```python
# The fallback code creates the user directly:
portal_group = self.env.ref('base.group_portal')
portal_user = self.env['res.users'].sudo().create({
    'name': self.name,
    'login': self.email,
    'email': self.email,
    'partner_id': self.id,
    'groups_id': [(6, 0, [portal_group.id])],
})
```

---

#### Error: `Invalid view type: 'tree'`

**Cause:** Odoo 19 renamed `<tree>` views to `<list>`.

**Solution:** Replace all `<tree>` tags with `<list>` in XML view definitions:
```xml
<!-- Old (Odoo 18 and earlier) -->
<tree>...</tree>

<!-- New (Odoo 19) -->
<list>...</list>
```

---

#### Error: `Invalid field 'category_id' in 'res.groups'`

**Cause:** Odoo 19 no longer supports `category_id` in `res.groups` XML definitions.

**Solution:** Remove the `<field name="category_id">` element from security group definitions:
```xml
<!-- Remove this line -->
<field name="category_id" ref="base.module_category_sales"/>
```

---

#### Error: `DeprecationWarning: @route(type='json') is deprecated`

**Cause:** Odoo 19 uses `type='jsonrpc'` instead of `type='json'`.

**Solution:** Update route decorators:
```python
# Old
@http.route('/my/endpoint', type='json', auth='user')

# New
@http.route('/my/endpoint', type='jsonrpc', auth='user')
```

---

### Portal Access Issues

#### User can't see cases in portal

1. Verify the partner has `is_authorizer` or `is_sales_rep_portal` checked
2. Verify the `authorizer_portal_user_id` is set
3. For authorizers, verify the Sale Order has `x_fc_authorizer_id` set to their partner ID
4. For sales reps, verify the Sale Order has `user_id` set to their user ID

#### Email notifications not sending

1. Check that the outgoing mail server is configured in Odoo
2. Verify the email templates exist and are active
3. Check the mail queue (Settings > Technical > Email > Emails)
4. Review the Odoo logs for mail errors

---

### Debug Logging

Enable debug logging for this module:

```python
import logging
_logger = logging.getLogger('fusion_authorizer_portal')
_logger.setLevel(logging.DEBUG)
```

Or in Odoo configuration:
```ini
[options]
log_handler = fusion_authorizer_portal:DEBUG
```

---

## Changelog

### Version 19.0.1.0.0 (Initial Release)

**New Features:**
- Authorizer Portal with case management
- Sales Rep Portal with assessment forms
- Wheelchair Assessment model with 50+ fields
- Digital signature capture (Pages 11 & 12)
- Document management with revision tracking
- Real-time search functionality
- Email notifications for key events
- Portal access management from partner form

**Technical:**
- Compatible with Odoo Enterprise v19
- Integrates with fusion_claims module
- Mobile-responsive portal design
- Touch-friendly signature pad
- AJAX-powered search

**Bug Fixes:**
- Fixed `in_portal` field error in Odoo 19 portal wizard
- Fixed `tree` to `list` view type for Odoo 19
- Fixed `category_id` error in security groups
- Fixed `type='json'` deprecation warning

---

## File Structure

```
fusion_authorizer_portal/
├── __init__.py
├── __manifest__.py
├── README.md
├── controllers/
│   ├── __init__.py
│   ├── portal_main.py          # Authorizer & Sales Rep portal routes
│   └── portal_assessment.py    # Assessment routes
├── data/
│   ├── mail_template_data.xml  # Email templates & sequences
│   └── portal_menu_data.xml    # Portal menu items
├── models/
│   ├── __init__.py
│   ├── adp_document.py         # Document management model
│   ├── assessment.py           # Assessment model
│   ├── authorizer_comment.py   # Comments model
│   ├── res_partner.py          # Partner extensions
│   └── sale_order.py           # Sale Order extensions
├── security/
│   ├── ir.model.access.csv     # Access rights
│   └── portal_security.xml     # Groups & record rules
├── static/
│   └── src/
│       ├── css/
│       │   └── portal_style.css    # Portal styling
│       └── js/
│           ├── assessment_form.js  # Form enhancements
│           ├── portal_search.js    # Real-time search
│           └── signature_pad.js    # Signature capture
└── views/
    ├── assessment_views.xml    # Assessment backend views
    ├── portal_templates.xml    # Portal QWeb templates
    ├── res_partner_views.xml   # Partner form extensions
    └── sale_order_views.xml    # Sale Order extensions
```

---

## Support

For support or feature requests, contact:

- **Email:** support@fusionclaims.com
- **Website:** https://fusionclaims.com

---

*Last Updated: January 2026*
