Skip to content

SMS Integration

JustCall SMS integration for sending messages and viewing conversation history.

Overview

The SMS module provides:

  • Send SMS from lead/job detail pages
  • View conversation history with customer
  • Use JustCall phone lines
  • Apply SMS templates
  • MMS support (view media)

API Endpoints

Get Phone Lines

GET /api/sms/lines

Get available JustCall phone lines for the "From" dropdown.

Response:

{
  "success": true,
  "lines": [
    {"id": 1, "name": "Main Line", "phone_display": "+1 (555) 123-4567", "is_default": true},
    {"id": 2, "name": "Sales Line", "phone_display": "+1 (555) 234-5678", "is_default": false}
  ]
}

Get Templates

GET /api/sms/templates

Get SMS templates for quick message composition.

Response:

{
  "success": true,
  "templates": [
    {"id": 1, "name": "Appointment Reminder", "body": "Hi {{name}}, this is a reminder about your appointment tomorrow.", "sequence": 1},
    {"id": 2, "name": "Quote Follow-up", "body": "Hi {{name}}, following up on your recent quote. Any questions?", "sequence": 2}
  ]
}

Get Conversation

GET /api/sms/conversation/{phone}

Get SMS conversation history for a phone number.

Response:

{
  "success": true,
  "messages": [
    {
      "id": 123,
      "contact_number": "+15551234567",
      "contact_name": "John Doe",
      "justcall_number": "+15559998888",
      "justcall_line_name": "Main Line",
      "direction": "Outgoing",
      "body": "Hello! Your order is ready for pickup.",
      "sms_date": "2024-03-15",
      "sms_time": "14:30:00",
      "delivery_status": "Delivered",
      "is_mms": false,
      "mms_urls": null,
      "agent_name": "Jane Smith",
      "datetime": "2024-03-15 14:30:00",
      "is_outgoing": true
    }
  ]
}

Send SMS

POST /api/sms/send

Send an SMS message via JustCall.

Request:

{
  "to": "+15551234567",
  "body": "Hello! Your order is ready for pickup.",
  "from": "+15559998888"
}

Response:

{
  "success": true,
  "result": {
    "sent": true,
    "message_id": 456
  }
}

SMS Modal

The SMS functionality is accessed via a modal that can be opened from:

  • Job detail page
  • Lead detail page
  • Customer detail page
  1. From Line Selector: Choose JustCall phone line
  2. To Number: Pre-filled from record, editable
  3. Template Selector: Quick-fill message from template
  4. Message Body: Text area for message content
  5. Conversation History: View past messages with customer
  6. Send Button: Submit message

SMS Flow

sequenceDiagram
    participant User
    participant PWA
    participant Odoo
    participant JustCall

    User->>PWA: Open SMS modal
    PWA->>Odoo: Get JustCall lines
    PWA->>Odoo: Get SMS templates
    Odoo-->>PWA: Lines and templates

    User->>PWA: Click phone number
    PWA->>Odoo: Get conversation
    Odoo-->>PWA: Message history

    User->>PWA: Compose and send
    PWA->>Odoo: Send SMS (via config)
    Odoo->>JustCall: API call
    JustCall-->>Odoo: Success
    Odoo-->>PWA: Result
    PWA-->>User: Success message

Message Storage

SMS messages are stored in Odoo's justcall.sms model:

Field Type Description
contact_number Char Recipient phone
contact_name Char Contact name (from Odoo)
justcall_number Char From phone number
justcall_line_name Char JustCall line name
direction Selection Incoming or Outgoing
body Text Message content
sms_date Date Date sent/received
sms_time Char Time sent/received
delivery_status Char JustCall delivery status
is_mms Boolean Whether MMS
mms_urls Text Media URLs for MMS
agent_name Char JustCall agent

Phone Number Matching

Conversation lookup uses last 10 digits for matching:

def get_sms_conversation(phone: str, limit: int = 100):
    # Clean phone number - get last 10 digits
    clean_phone = ''.join(c for c in phone if c.isdigit())[-10:]

    domain = [('contact_number', 'ilike', clean_phone)]
    # Returns messages ordered by date ascending (oldest first)

Sending SMS

SMS is sent through Odoo's JustCall integration:

def send_sms(to_number: str, body: str, from_number: str = None):
    # Get JustCall config
    config = self._jsonrpc_call('justcall.config', 'search_read',
        [[('active', '=', True)]],
        {'fields': ['id'], 'limit': 1}
    )

    config_id = config[0]['id']

    # Call send_sms method
    result = self._jsonrpc_call(
        'justcall.config',
        'send_sms',
        [[config_id], to_number, body],
        {'from_number': from_number} if from_number else {}
    )

    return {'sent': True, 'result': result}

MMS Support

For MMS messages, media URLs are displayed in the conversation:

{% if msg.is_mms and msg.mms_urls %}
    <div class="mms-media">
        {% for url in msg.mms_urls.split(',') %}
            <img src="{{ url }}" alt="MMS media" class="mms-image">
        {% endfor %}
    </div>
{% endif %}

Templates

SMS templates support placeholder variables:

Placeholder Description
{{name}} Contact name
{{company}} Company name
{{date}} Current date

Templates are managed in Odoo at justcall.sms.template.

Error Handling

SMS errors are displayed to the user:

@bp.route('/api/sms/send', methods=['POST'])
def send_sms():
    try:
        result = odoo_api.send_sms(to_number, body, from_number)
        return jsonify({'success': True, 'result': result})
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500

Common errors:

  • JustCall not configured: No active justcall.config record
  • Invalid phone number: JustCall API rejected the number
  • Rate limit exceeded: Too many messages sent
  • Insufficient credits: JustCall account needs credits

Frontend JavaScript

The SMS modal is controlled by static/js/sms.js:

// Open SMS modal
function openSmsModal(phone, name) {
    document.getElementById('smsTo').value = phone;
    document.getElementById('smsContactName').textContent = name;
    loadConversation(phone);
    new bootstrap.Modal('#smsModal').show();
}

// Load conversation history
async function loadConversation(phone) {
    const response = await fetch(`/api/sms/conversation/${encodeURIComponent(phone)}`);
    const data = await response.json();
    // Render messages...
}

// Send message
async function sendSms() {
    const response = await fetch('/api/sms/send', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({
            to: document.getElementById('smsTo').value,
            body: document.getElementById('smsBody').value,
            from: document.getElementById('smsFrom').value
        })
    });
    // Handle response...
}