iLeben keeps its local database in sync with Salesforce through a combination of scheduled Laravel jobs, on-demand Artisan commands, and a background Production Sync flow. The scheduler handles routine plant pulls (governed byDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/scooller/Leben-site/llms.txt
Use this file to discover all available pages before exploring further.
SalesforcePlantSyncSchedule::shouldRunAt()) and token refresh every 20 hours, while Artisan commands let operators trigger or diagnose syncs manually. All scheduled work runs on the database queue, which requires a queue worker process running alongside the Laravel scheduler.
Artisan Commands
| Command | Description |
|---|---|
php artisan test:sync-projects | Triggers SyncProjectsAction::execute() to pull projects from Salesforce and upsert them into the local proyectos table. Reports created/updated counts. |
php artisan sync:plants | Triggers SyncPlantsAction::execute() to pull Product2 units from Salesforce and sync them into the local plants table. Preserves configurable local-only fields. |
php artisan salesforce:sync-broker-metrics | Recalculates commercial broker metrics from local opportunity snapshots. Does not query Salesforce directly. |
php artisan salesforce:test-auth | Authenticates with Salesforce and runs a SELECT COUNT() FROM Lead SOQL query to verify end-to-end connectivity. |
php artisan salesforce:refresh-token | Proactively renews the OAuth access token. If the token is in cache, it synchronizes the DB backup. If no token is in cache, it attempts auto-reconnect from the encrypted DB backup. |
Example: test authentication
Example: sync projects
Scheduler Configuration
The Laravel scheduler is defined inroutes/console.php. The following entries are active:
| Schedule | Frequency | Notes |
|---|---|---|
reservations:expire | Every minute | Expires plant reservations that have passed their deadline. |
SyncPlantsJob | Every minute (with SalesforcePlantSyncSchedule::shouldRunAt() gate) | Dispatches SyncPlantsJob to the queue with withoutOverlapping(). The shouldRunAt() gate controls the effective cadence based on site settings. |
model:prune (FrontendPreviewLink) | Daily | Prunes expired frontend preview link records. |
salesforce:refresh-token | Every 20 hours (cron('0 */20 * * *')) | Proactively refreshes the OAuth access token or syncs the DB backup. |
routes/console.php:
Production Sync (RunProductionSyncJob)
iLeben supports a controlled sync-from-production flow for pre-production or staging environments. Rather than querying Salesforce directly, this flow fetches a data snapshot from a running production instance via a protected HTTP endpoint and applies it locally. The sync is dispatched as a background job (RunProductionSyncJob) and reports progress in real time through the Filament panel.
Trigger endpoint (production side):
PRODUCTION_SYNC_TOKEN. The staging instance polls it to download the snapshot, then applies projects, plants, and site configuration locally.
Required environment variables:
| Variable | Purpose |
|---|---|
PRODUCTION_SYNC_BASE_URL | Base URL of the production instance to pull the snapshot from |
PRODUCTION_SYNC_TOKEN | Bearer token used to authenticate against the production export endpoint |
PRODUCTION_SYNC_AUTHORIZED_URL | URL of the current (staging) instance, sent to production for validation |
PRODUCTION_SYNC_TIMEOUT | HTTP timeout in seconds for the snapshot download (default 120) |
SyncFromProductionAction) that dispatches RunProductionSyncJob and shows a live progress screen with step counts and log messages.
Data Preservation During Sync
The plants sync (SyncPlantsAction) uses a configurable list of excluded update fields to protect locally managed data from being overwritten by Salesforce. The list is stored in SiteSetting.extra_settings.salesforce_sync_plants_excluded_fields and can be configured from the admin panel.
The following plant fields are eligible for exclusion from updates:
| Field | Label |
|---|---|
salesforce_proyecto_id | Proyecto Salesforce |
name | Nombre |
tipo_producto | Tipo producto |
orientacion | Orientacion |
programa | Programa |
programa2 | Programa 2 |
piso | Piso |
precio_base | Precio base |
precio_lista | Precio lista |
porcentaje_maximo_unidad | Porcentaje maximo unidad |
superficie_total_principal | Superficie total principal |
superficie_interior | Superficie interior |
superficie_util | Superficie util |
superficie_terraza | Superficie terraza |
salesforce_interior_image_url | URL interior Salesforce |
product_code is never overwritten on existing plants — it is only set at creation time. This preserves any local corrections to product codes without requiring a Salesforce update.
SOQL Result Caching
All SOQL queries executed throughSalesforceService::query() are cached with Cache::remember using a default TTL of 900 seconds (15 minutes). This reduces the number of API calls to Salesforce and prevents hitting rate limits during high-frequency sync windows.
After running
cache:clear, the OAuth tokens stored in the Laravel cache are also cleared. The auto-reconnect mechanism will restore them from the encrypted DB backup on the next background job execution. No manual reconnect is needed as long as a token_cache_backup exists in SiteSetting.extra_settings. See OAuth Setup for the post-deploy reconnect requirement.cPanel Cron Setup
On cPanel-hosted servers,schedule:run does not consume the queue on its own. If QUEUE_CONNECTION=database, you need two separate cron entries: one for the Laravel scheduler and one for the queue worker.
Operational notes for cPanel cron
Operational notes for cPanel cron
- Do not add a leading
-to cron commands in the cPanel cron editor — it will break parsing. - Verify the real path of
flockon your server withwhich flock. It is typically/usr/bin/flock. - If jobs accumulate in the
jobstable withattempts=0andreserved_at=NULL, the queue worker is not running. - Monitor
storage/logs/queue-worker.logto confirm jobs are being processed. - You can rotate the queue worker log daily with an additional cron:
% must be escaped as \% in cron commands so date +\%F works correctly.