In iLeben, a Proyecto (Project) represents a real estate development — a building or complex with its own location, etapa (construction stage), advisors, and payment configuration. A Planta (Plant) is an individual unit within a project: a departamento, estacionamiento, bodega, or local. Both entities are Salesforce-sourced; Salesforce is the system of record, and the local database is kept in sync automatically. The Filament admin panel gives operators a rich interface to view, filter, and override selected local attributes without losing their values on the next sync.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.
Projects (Proyectos)
CRUD and Navigation
Projects are managed under the Real Estate navigation group viaProyectoResource. Both admin and marketing users can view the list, but only admin can create, edit, or delete records. The table shows a navigation badge with the total project count.
Each project row exposes three inline record actions: Edit, Toggle Active/Inactive, and Ver en Salesforce (opens the Salesforce record directly in a new tab, visible only when salesforce_id is filled).
Key Fields
| Field | Type | Notes |
|---|---|---|
name | text | Read-only, sourced from Salesforce |
salesforce_id | text | Salesforce Proyecto__c ID |
slug | text | Auto-generated from name on create/update |
tipo | multiselect (array) | Values: best, broker, home, icon, invest |
etapa | select | Normalized construction stage (see below) |
descripcion | text | Read-only, sourced from Salesforce |
direccion | text | Read-only, sourced from Salesforce |
comuna / provincia / region | text | Read-only, sourced from Salesforce |
is_active | boolean | Controls visibility in public catalog |
entrega_inmediata | boolean | Flags immediate-delivery units |
transbank_commerce_code | select | Per-project Transbank Mall commerce code |
descuento_defecto_cotizacion_web | decimal | Default web discount %, sourced from Salesforce |
descuento_maximo_unidad | decimal | Max unit discount %, sourced from Salesforce |
valor_reserva_exigido_defecto_peso | decimal | Default reservation amount in CLP |
valor_reserva_exigido_min_peso | decimal | Minimum reservation amount in CLP |
project_image_id | FK → Media | Manual Curator image override for project card |
manual_payment_instructions | text | Per-project deposit instructions |
manual_payment_bank_accounts | array | Per-project bank account list for manual payments |
manual_payment_link | text | Per-project manual payment URL |
Etapa Normalization
Theetapa field is automatically normalized on read and write using Proyecto::normalizeEtapa(). Legacy Salesforce values and encoding variations are mapped to canonical keys:
Filters
The projects table ships four sidebar filters:- Etapa — multi-select from all normalized options
- Región — multi-select populated dynamically from the database
- Tipo — multi-select (
best,broker,home,icon,invest) - Entrega Inmediata — boolean yes/no
Advisors (Asesores)
Each project can be associated with multipleAsesor records through the asesor_proyecto pivot table (BelongsToMany). The project form renders a searchable multi-select that lists advisors by full name and email. Advisors are also synced from Salesforce automatically when running php artisan test:sync-projects.
Transbank Mall Commerce Code
Thetransbank_commerce_code field maps this project to a specific Transbank commerce code. The admin form populates the select options from the payments.gateways.transbank.commerce_codes config key (sourced from TRANSBANK_STORE_CODES in .env). If no value is stored in the DB, the attribute accessor falls back to the config-level mapping by project slug.
Pricing Fields
descuento_defecto_cotizacion_web and descuento_maximo_unidad are synced from Salesforce and displayed as read-only in the admin form. They feed the Plant::resolveFinalPrice() calculation:
Plants (Plantas)
CRUD and Navigation
Plants live under the same Real Estate group viaPlantResource. Like projects, both roles can view them, but only admin may create, edit, or delete. The badge shows the total plant count.
Key Fields
| Field | Type | Notes |
|---|---|---|
salesforce_product_id | text | Salesforce Product2 ID (read-only) |
salesforce_proyecto_id | text | FK to Proyecto.salesforce_id (read-only) |
name | text | Unit name |
product_code | text | Internal product code |
tipo_producto | text | DEPARTAMENTO, ESTACIONAMIENTO, BODEGA, LOCAL |
is_active | boolean | Controls catalog visibility |
unidad_sale | boolean | Marks unit as part of a sale event |
precio_base | decimal | Base price in UF |
precio_lista | decimal | List price in UF (read-only, from Salesforce) |
porcentaje_maximo_unidad | decimal | Max unit discount % |
descuento_defecto_cotizacion_web | decimal | Per-plant web discount % synced from Salesforce |
asesor_id | FK → Asesor | Optional per-plant advisor override |
contact_link | text | Optional direct contact URL for this unit |
cover_image_id | FK → Media | Cover image via Curator picker |
interior_image_id | FK → Media | Interior image via Curator picker |
salesforce_interior_image_url | text | Fallback interior URL synced from Salesforce |
piso | text | Floor number |
orientacion | text | Unit orientation |
programa | text | Program name (e.g., layout type) |
programa2 | text | Secondary program name |
superficie_total_principal | decimal | Total principal area in m² |
superficie_interior | decimal | Interior area in m² |
superficie_util | decimal | Usable area in m² |
superficie_terraza | decimal | Terrace area in m² |
last_synced_at | datetime | Timestamp of last Salesforce sync |
Images via Curator
Cover and interior images are selected usingCuratorPicker fields in the plant form. They resolve to Media records in the curator table. The table view shows a circular thumbnail for the cover image. If no Curator image is set for the interior, the frontend falls back to salesforce_interior_image_url.
Table Filters
| Filter | Options |
|---|---|
| Estado (is_active) | Activo / Inactivo |
| Unidad Sale | Sí / No |
| Tipo de planta | DEPARTAMENTO, ESTACIONAMIENTO, BODEGA, LOCAL (defaults to DEPARTAMENTO) |
| Proyecto | Relationship search |
| Programa | Dynamic list from DB |
Inline Record Actions
Each plant row in the table exposes four actions:- Toggle Active/Inactive — flips
is_activein-place - Toggle Unidad Sale — flips
unidad_salein-place - Ver en Salesforce — opens the
Product2record (only whensalesforce_product_idis filled) - Edit — opens the full edit form
Export
The plants table includes anExportAction powered by PlantExporter. Exports run asynchronously on the database queue, and a persistent Filament notification appears in the panel when the file is ready.
Exports require the queue worker to be running. On cPanel, make sure both the
schedule:run cron and the queue:work cron are active. See the cPanel queue setup in the README for the exact commands.Bulk Actions
From the toolbar, admins can select multiple plants and:- Activar / Desactivar seleccionadas — bulk toggle
is_active - Activar en sale / Desactivar en sale — bulk toggle
unidad_sale - Eliminar — bulk delete (requires confirmation)
Availability Logic
A plant is considered unavailable when either of these conditions is true:- Reserved — an active
PlantReservationexists withstatus = ACTIVEandexpires_atin the future. - Paid — a
PlantReservationwithstatus = COMPLETEDexists, or aPaymentrecord withstatus IN (COMPLETED, AUTHORIZED)exists for the plant.
Plant::isReserved() and Plant::isPaid(). The scheduler runs php artisan reservations:expire every minute to transition expired-but-still-active reservations to EXPIRED status, freeing units automatically.
PlantReservation Model
| Field | Type | Notes |
|---|---|---|
plant_id | FK | The reserved plant |
user_id | FK | Buyer who initiated the reservation |
session_token | string | Anonymous session identifier |
status | enum | ACTIVE, EXPIRED, COMPLETED, RELEASED |
expires_at | datetime | Configurable via gateway_reservation_timeout_minutes in SiteSettings |
completed_at | datetime | Set when the payment succeeds |
released_at / released_by | datetime / string | Set when manually or automatically released |
metadata | array | Supports manual_lock flag to prevent auto-release |
Salesforce Sync
Both projects and plants are synced from Salesforce using dedicated Artisan commands. Salesforce is the source of truth for all fields listed inProyecto::syncableFields() and Plant::syncableFields(). The sync logic deliberately skips overwriting local-only attributes (like cover_image_id, interior_image_id, transbank_commerce_code) to preserve changes made in the admin panel.
Run
php artisan sync:plants to manually trigger a plant sync. For projects, use php artisan test:sync-projects. The scheduler automatically runs sync:plants every 5 minutes via a queued job.You can also configure which fields are excluded from sync in SiteSettings → Sincronización Salesforce → Campos excluidos.SyncSalesforceOpportunitiesJob every 60 minutes and salesforce:sync-broker-metrics every 15 minutes for broker metric snapshots.