Skip to main content

Documentation 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.

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 by 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

CommandDescription
php artisan test:sync-projectsTriggers SyncProjectsAction::execute() to pull projects from Salesforce and upsert them into the local proyectos table. Reports created/updated counts.
php artisan sync:plantsTriggers 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-metricsRecalculates commercial broker metrics from local opportunity snapshots. Does not query Salesforce directly.
php artisan salesforce:test-authAuthenticates with Salesforce and runs a SELECT COUNT() FROM Lead SOQL query to verify end-to-end connectivity.
php artisan salesforce:refresh-tokenProactively 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

php artisan salesforce:test-auth
Intentando autenticación con Salesforce...
✓ Token obtenido exitosamente
Haciendo una consulta SOQL de prueba...
✓ Consulta exitosa
Conexión con Salesforce funcionando correctamente

Example: sync projects

php artisan test:sync-projects
🔄 Sincronizando proyectos...
✅ Sincronización de proyectos completada.
Creados: 2, Actualizados: 5

Scheduler Configuration

The Laravel scheduler is defined in routes/console.php. The following entries are active:
ScheduleFrequencyNotes
reservations:expireEvery minuteExpires plant reservations that have passed their deadline.
SyncPlantsJobEvery 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)DailyPrunes expired frontend preview link records.
salesforce:refresh-tokenEvery 20 hours (cron('0 */20 * * *'))Proactively refreshes the OAuth access token or syncs the DB backup.
The scheduler config in routes/console.php:
Schedule::command('reservations:expire')->everyMinute();

Schedule::command('model:prune', [
    '--model' => [FrontendPreviewLink::class],
])->daily();

Schedule::job(new SyncPlantsJob)
    ->everyMinute()
    ->withoutOverlapping()
    ->when(static fn(): bool => SalesforcePlantSyncSchedule::shouldRunAt());

Schedule::command('salesforce:refresh-token')
    ->cron('0 */20 * * *')
    ->withoutOverlapping();

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):
GET /api/v1/production-sync/export
This endpoint requires authentication via PRODUCTION_SYNC_TOKEN. The staging instance polls it to download the snapshot, then applies projects, plants, and site configuration locally. Required environment variables:
VariablePurpose
PRODUCTION_SYNC_BASE_URLBase URL of the production instance to pull the snapshot from
PRODUCTION_SYNC_TOKENBearer token used to authenticate against the production export endpoint
PRODUCTION_SYNC_AUTHORIZED_URLURL of the current (staging) instance, sent to production for validation
PRODUCTION_SYNC_TIMEOUTHTTP timeout in seconds for the snapshot download (default 120)
PRODUCTION_SYNC_BASE_URL=https://prod.example.com
PRODUCTION_SYNC_TOKEN=your-secret-token
PRODUCTION_SYNC_AUTHORIZED_URL="${APP_URL}"
PRODUCTION_SYNC_TIMEOUT=120
The Filament panel includes a Sync desde Producción action (via 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:
FieldLabel
salesforce_proyecto_idProyecto Salesforce
nameNombre
tipo_productoTipo producto
orientacionOrientacion
programaPrograma
programa2Programa 2
pisoPiso
precio_basePrecio base
precio_listaPrecio lista
porcentaje_maximo_unidadPorcentaje maximo unidad
superficie_total_principalSuperficie total principal
superficie_interiorSuperficie interior
superficie_utilSuperficie util
superficie_terrazaSuperficie terraza
salesforce_interior_image_urlURL interior Salesforce
Note: 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 through SalesforceService::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.
protected int $defaultCacheTtl = 900; // 15 minutes
Cache keys are generated by MD5-hashing the SOQL string:
salesforce:soql:<md5_of_soql>
To force a fresh query, clear the application cache:
php artisan cache:clear
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.
# 1) Laravel Scheduler — every minute
* * * * * /usr/local/bin/php /home/adminmktleben/laravel/artisan schedule:run >> /dev/null 2>&1

# 2) Queue Worker with flock — every minute
* * * * * /usr/bin/flock -n /tmp/leben-queue.lock /usr/local/bin/php /home/adminmktleben/laravel/artisan queue:work database --queue=default --sleep=3 --tries=3 --backoff=5 --max-time=50 --stop-when-empty >> /home/adminmktleben/laravel/storage/logs/queue-worker.log 2>&1
  • Do not add a leading - to cron commands in the cPanel cron editor — it will break parsing.
  • Verify the real path of flock on your server with which flock. It is typically /usr/bin/flock.
  • If jobs accumulate in the jobs table with attempts=0 and reserved_at=NULL, the queue worker is not running.
  • Monitor storage/logs/queue-worker.log to confirm jobs are being processed.
  • You can rotate the queue worker log daily with an additional cron:
# Rotate log daily at midnight
0 0 * * * /bin/mv /home/adminmktleben/laravel/storage/logs/queue-worker.log /home/adminmktleben/laravel/storage/logs/queue-worker-$(date +\%F).log 2>/dev/null; /usr/bin/touch /home/adminmktleben/laravel/storage/logs/queue-worker.log

# Delete rotated logs older than 14 days
10 0 * * * /usr/bin/find /home/adminmktleben/laravel/storage/logs -name 'queue-worker-*.log' -type f -mtime +14 -delete
Note that % must be escaped as \% in cron commands so date +\%F works correctly.

Build docs developers (and LLMs) love