Workflow: SmartCRM — Bidirectional ERP Synchronization
Modules involved: SmartCRM · Leads · Clients · Invoices · Projects · Tickets · Products · Warehouse
Used by: Administrator · IT · Operations
Typical duration: Manual sync = minutes · Automatic sync = every 1/2/4/12/24 hours (configurable)
Overview
SmartCRM is a bidirectional connector between CRMConnect and an external ERP/CRM system (e.g.: a proprietary ERP or another CRM), not an AI or scoring tool. It synchronizes in both directions: imports data from the external system into CRM and exports CRM records to the external system.
Synchronized entities:
| Entity | Import (external → CRM) | Export (CRM → external) |
|---|---|---|
| Products + prices | ✓ | ✗ |
| Product groups | ✓ | ✗ |
| Clients + contacts | ✓ | ✓ |
| Orders / Proformas | ✓ (as Sales Orders) | ✗ |
| Stock per warehouse | ✓ | ✗ |
| Discounts per group | ✓ | ✗ |
| Leads | ✓ | ✓ |
| Projects | ✓ | ✓ |
| Tickets | ✓ | ✓ |
| Invoices | ✓ | ✓ |
Scoring module: the
scoringmodule is non-functional as shipped — the installation SQL and activation hooks are completely commented out in the code. Tables are not created on activation. There is no operational score calculation. It does not integrate with SmartCRM.
Flow diagram
[SETUP — admin, required before first sync]
│
├── SmartCRM → Settings:
│ ├── smartcrm_api_url (external system URL + /index.php/api/)
│ ├── smartcrm_auth_token (Bearer token for REST API)
│ ├── smartcrm_client_token (separate token for entity sync V2 — REQUIRED)
│ ├── smartcrm_currency_mapping (JSON mapping external currency ID → local)
│ └── Test Connection → connectivity check
│
├── Cron configuration (optional):
│ ├── smartcrm_cron = 'yes'
│ └── smartcrm_interval: 1/2/4/12/24 hours
│
└── Batch settings:
smartcrm_batch_size (default 50)
smartcrm_api_timeout (default 30s)
smartcrm_max_retries (default 3, with exponential backoff)
│
↓
════════════════════════════════════
IMPORT — DATA FROM EXTERNAL INTO CRM
════════════════════════════════════
│
├── Manual: SmartCRM → Sync → button per entity
├── Automatic (cron): all 5 main entities if interval has elapsed
│
├── Import flow per entity:
│ ├── GET /api/{entity} from the external system (with auth token)
│ ├── Deduplicate: checks external_id + external_channel='smartcrm'
│ ├── INSERT or UPDATE in CRM tables
│ └── Mark with external_id + external_channel='smartcrm'
│
├── Entities with advanced sync (sync_entity_v2 — requires smartcrm_client_token):
│ ├── Units of measure
│ ├── Product groups → tblitems_groups
│ ├── Products with prices per warehouse → tblitems
│ ├── Clients with county/locality mapping → tblclients
│ ├── Client groups → tbldiscount_groups
│ ├── Contacts → tblcontacts
│ ├── Orders/Proformas → tblcart + tblcart_detailt
│ ├── Currencies → tblcurrencies (requires currency_mapping)
│ ├── Warehouses → tblwarehouse
│ ├── Stock → tblinventory_manage
│ └── Discount grids → tblitem_client_group_discounts
│
└── Log: each operation → tbl_smartcrm_logs (level, entity, records_processed/success/failed)
│
↓
════════════════════════════════════
EXPORT — DATA FROM CRM TO EXTERNAL
════════════════════════════════════
│
├── Identify new records: WHERE external_channel IS NULL OR != 'smartcrm'
├── Format payload via format_{entity}_for_smartcrm()
├── POST /api/{entity} to the external system
├── On success: mark_as_exported_to_smartcrm() → external_id + external_channel='smartcrm'
└── On failure: retry with exponential backoff (2^n seconds, max smartcrm_max_retries)
│
↓
[MONITORING]
│
├── SmartCRM → Dashboard: sync statistics (inserted/updated/failed per entity per day)
├── SmartCRM → Logs: details per operation (level: DEBUG/INFO/WARNING/ERROR)
├── SmartCRM → Errors Overview: grouped errors
└── reset_statistics() / cleanup_logs() — manual cleanup
[SYNC COMPLETE ✓ · BIDIRECTIONAL DATA ✓]
Step by step
1. Initial setup (admin)
Where: /admin/smartcrm → Settings
1a. API credentials (required)
| Option | Description |
|---|---|
smartcrm_api_url |
Base URL of the external system (e.g.: https://erp.company.com/). The module automatically appends index.php/api/{entity} |
smartcrm_auth_token |
REST Bearer token for authentication at /api/leads, /api/clients, etc. |
smartcrm_client_token |
Separate token used by sync_entity_v2 for advanced entities (products, stock, groups). This token does not appear in the Settings UI — it must be set manually in tbloptions with name='smartcrm_client_token'. Without it, sync_entity_v2 fails with "Missing client token". |
Connectivity test: Test Connection button → checks URL accessibility + token validity.
1b. Currency mapping (required if synchronizing prices)
Where: Settings → Currency Mapping
JSON mapping external system currency IDs to local IDs:
{"1": 1, "2": 3, "5": 2}
(e.g.: ID 1 in external = ID 1 local = RON; ID 2 in external = ID 3 local = USD)
Without this mapping, price synchronization returns an error.
1c. Automatic cron configuration
| Option | Values | Description |
|---|---|---|
smartcrm_cron |
'yes' / 'no' |
Enable automatic sync |
smartcrm_interval |
1, 2, 4, 12, 24 |
Interval in hours between syncs |
On each CRM cron execution, sync_cron_smartcrm() checks if smartcrm_cron = 'yes' and if the interval has elapsed since smartcrm_last_update. If so, it synchronizes all 5 main entities.
1d. Performance settings
| Option | Default | Description |
|---|---|---|
smartcrm_batch_size |
50 | Records per request |
smartcrm_api_timeout |
30 | Request timeout in seconds |
smartcrm_max_retries |
3 | Retries on failure (backoff: 2^n sec) |
smartcrm_log_level |
INFO | DEBUG / INFO / WARNING / ERROR |
2. Manual sync per entity
Where: /admin/smartcrm → Sync tab
Separate buttons per entity:
- Sync Leads — import/export leads
- Sync Clients — import/export clients
- Sync Projects — import/export projects
- Sync Tickets — import/export tickets
- Sync Invoices — import/export invoices
- Sync Entity V2 (multiselect) — products, stock, groups, orders, etc. (requires
smartcrm_client_token) - Export → SmartCRM (per entity) — exports locally unmarked records
3. Deduplication mechanism
Synchronized records are marked with:
external_id— the ID from the external systemexternal_channel = 'smartcrm'— identifies the source
On re-sync, the system checks for the existence of external_id + external_channel before INSERT → performs UPDATE if exists, INSERT if not.
Records created locally (without external_channel) are eligible for export.
4. Monitoring and logs
Where: /admin/smartcrm/dashboard + /admin/smartcrm/errors_overview
Dashboard (tbl_smartcrm_sync_stats): per day per entity — total/inserted/updated/failed + status (SUCCESS/FAILED/PARTIAL).
Logs (tbl_smartcrm_logs): complete details per operation with records_processed, records_success, records_failed, execution_time.
Cleanup:
reset_statistics()— resets counters (requiressmartcrm → edit)cleanup_logs()— deletes logs (requiressmartcrm → delete)
Note on the Scoring module
The scoring module is installed but non-functional:
- The table creation SQL in
install.phpis completely commented out (/* ... */) - The activation hook (
scoring_module_activation_hook) is commented out - Menu and permissions are not registered
- The
save_scoring_lead()function is an empty stub - The required tables are not created when the module is activated
If you need operational lead scoring, this module requires manual intervention (manually create tables in DB + uncomment the code).
Required permissions
| Permission | Access |
|---|---|
smartcrm → view |
Access to dashboard, logs, statistics, sync buttons |
smartcrm → edit |
Reset statistics |
smartcrm → delete |
Cleanup logs |
| SmartCRM Settings | Available to staff with view (no additional admin check) |
Gotchas
| Problem | Cause | Solution |
|---|---|---|
| Sync entity V2 fails with "Missing client token" | smartcrm_client_token not set |
Insert manually into tbloptions: INSERT INTO tbloptions (name,value,autoload) VALUES ('smartcrm_client_token','TOKEN_VALUE',0) |
| Prices not synchronizing | smartcrm_currency_mapping missing or invalid JSON |
Configure the correct mapping in Settings |
| Duplicate records on re-sync | external_id missing from external response |
Verify that the external API returns a consistent ID field |
| Cron not syncing | smartcrm_cron != 'yes' or interval not elapsed |
Enable cron + check smartcrm_last_update in tbloptions |
| Slow retry loop | max_retries=3 + backoff 2^n = 1+2+4=7 extra seconds per failed entity |
Reduce smartcrm_max_retries to 1 for fast sync or increase api_timeout |
Module references
- Leads — synchronized leads
- Clients — synchronized clients
- Invoices — synchronized invoices
- Warehouse — synchronized stock
- Integrations — Merlin ERP — another available ERP connector
Run a manual sync for each entity type (leads, clients, invoices) and verify the results before enabling automatic scheduled sync — confirming field mappings work correctly on a small dataset prevents mass data propagation errors across both systems.
Bidirectional sync means a record changed in the ERP can overwrite a change made in CRMConnect. Decide which system is the master for each entity type before enabling sync — without a clear master system, conflicting changes create data that belongs in neither system.