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:
Response:
SMS Modal¶
The SMS functionality is accessed via a modal that can be opened from:
- Job detail page
- Lead detail page
- Customer detail page
Modal Features¶
- From Line Selector: Choose JustCall phone line
- To Number: Pre-filled from record, editable
- Template Selector: Quick-fill message from template
- Message Body: Text area for message content
- Conversation History: View past messages with customer
- 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.configrecord - 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...
}