Skip to main content

Overview

Core Projects is a construction management SaaS platform built on a modern, full-stack architecture that combines Laravel’s robust backend capabilities with Vue.js’s reactive frontend, seamlessly connected through Inertia.js.

Technology Stack

Backend Layer

Laravel Framework

MVC architecture with Eloquent ORM for database operations

MySQL Database

Relational database for structured project and sales data

Service Layer

Business logic encapsulation through dedicated service classes

Middleware

Role-based access control and request handling

Frontend Layer

Vue 3

Component-based reactive user interface

Inertia.js

SPA-like experience without building an API

Tailwind CSS

Utility-first CSS framework for styling

Vite

Fast build tool and development server

Directory Structure

core-projects/
├── app/
│   ├── Http/
│   │   ├── Controllers/      # Request handlers
│   │   │   ├── Admin/       # Admin-specific controllers
│   │   │   ├── Ventas/      # Sales module controllers
│   │   │   ├── Gerencia/    # Management controllers
│   │   │   └── Contabilidad/ # Accounting controllers
│   │   └── Middleware/       # Request/response filters
│   ├── Models/               # Eloquent ORM models
│   └── Services/             # Business logic layer
│       ├── VentaService.php
│       ├── ProyectoPricingService.php
│       └── PriceEngine.php
├── database/
│   └── migrations/           # Database schema definitions
├── resources/
│   └── js/
│       ├── Pages/           # Inertia.js page components
│       │   ├── Admin/
│       │   ├── Ventas/
│       │   ├── Gerencia/
│       │   └── Contabilidad/
│       ├── Components/       # Reusable Vue components
│       └── Layouts/          # Page layout templates
└── routes/
    └── web.php              # Application routes

Database Schema Overview

Core Projects uses a normalized relational database structure organized into logical domains:

Core Entities

Key Tables

  • proyectos - Construction projects
  • torres - Towers within projects
  • pisos_torre - Floors in towers
  • ubicaciones - Geographic locations
  • estados - Project states
  • apartamentos - Apartment units
  • locales - Commercial spaces
  • parqueaderos - Parking spots
  • zonas_sociales - Social areas
  • tipos_apartamento - Apartment types
  • estados_inmueble - Property availability states
  • ventas - Sales and separations
  • clientes - Customer information
  • pagos - Payment transactions
  • plan_amortizacion_venta - Amortization plans
  • plan_amortizacion_cuota - Payment installments
  • formas_pago - Payment methods
  • politicas_precio_proyecto - Dynamic pricing policies
  • politicas_comision - Commission structures
  • proyectos_metas_comerciales - Sales targets
  • empleados - Employee accounts
  • cargos - Job positions/roles
  • dependencias - Departments
  • login_logs - Authentication audit trail

Design Patterns

Model-View-Controller (MVC)

Core Projects follows Laravel’s MVC pattern: Models - Eloquent ORM classes representing database entities:
app/Models/Proyecto.php
class Proyecto extends Model
{
    protected $table = 'proyectos';
    protected $primaryKey = 'id_proyecto';

    // Relationships
    public function torres()
    {
        return $this->hasMany(Torre::class, 'id_proyecto', 'id_proyecto');
    }

    public function politicaVigente()
    {
        return $this->hasOne(PoliticaPrecioProyecto::class, 'id_proyecto', 'id_proyecto')
            ->where('estado', true)
            ->where(function ($query) {
                $query->whereNull('aplica_desde')
                    ->orWhere('aplica_desde', '<=', now());
            })
            ->latest('aplica_desde');
    }
}
Controllers - Handle HTTP requests and return Inertia responses:
app/Http/Controllers/Admin/ProyectoController.php
public function index()
{
    $proyectos = Proyecto::with(['estado_proyecto', 'ubicacion', 'torres'])
        ->paginate(10);

    return Inertia::render('Admin/Proyectos/Index', [
        'proyectos' => $proyectos
    ]);
}
Views - Vue 3 components rendered by Inertia:
resources/js/Pages/Admin/Proyectos/Index.vue
<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  proyectos: Object
});
</script>

<template>
  <div class="container">
    <!-- Project list UI -->
  </div>
</template>

Service Layer Pattern

Complex business logic is encapsulated in service classes to keep controllers thin:
app/Services/VentaService.php
class VentaService
{
    public function crearOperacion(array $data): Venta
    {
        return DB::transaction(function () use ($data) {
            // 1. Lock and verify property availability
            // 2. Validate business rules
            // 3. Calculate pricing
            // 4. Create sale record
            // 5. Update property state
            // 6. Generate payment plan
            // 7. Recalculate project pricing
        });
    }
}
Service classes handle multi-step operations that span multiple models, ensuring data consistency through database transactions.

Repository Pattern (Eloquent)

Eloquent acts as an implementation of the Repository pattern:
// Query scopes for reusable queries
public function scopeActivos($query)
{
    return $query->where('activo', true);
}

// Usage in controllers
$proyectos = Proyecto::activos()->get();

Middleware Pattern

Request filtering and authentication through middleware:
app/Http/Middleware/CheckCargo.php
class CheckCargo
{
    public function handle(Request $request, Closure $next, ...$cargosPermitidos)
    {
        $empleado = Auth::guard('web')->user();

        if (!$empleado || 
            !$empleado->cargo || 
            !in_array($empleado->cargo->nombre, $cargosPermitidos)) {
            abort(403, 'No tienes permiso para acceder a esta sección.');
        }

        return $next($request);
    }
}

Request Flow

The typical request lifecycle in Core Projects:

Inertia.js Integration

Inertia.js creates a seamless SPA experience without building a REST API:

Server-Side

// Return Inertia response with props
return Inertia::render('Ventas/Index', [
    'ventas' => $ventas,
    'filters' => $filters
]);

Client-Side

<script setup>
import { router } from '@inertiajs/vue3';

const props = defineProps({
  ventas: Object,
  filters: Object
});

// Navigate without full page reload
const editVenta = (id) => {
  router.visit(`/ventas/${id}/edit`);
};
</script>
Inertia automatically handles form submissions, validation errors, and preserves scroll position without writing API endpoints.

Authentication & Authorization

Core Projects uses Laravel’s authentication with custom employee model:
app/Models/Empleado.php
class Empleado extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    protected $table = 'empleados';
    protected $guard = 'web';

    public function cargo()
    {
        return $this->belongsTo(Cargo::class, 'id_cargo', 'id_cargo');
    }
}

Route Protection

routes/web.php
// Admin and Manager routes
Route::middleware(['auth', 'check.cargo:Gerente,Administrador'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::resource('proyectos', ProyectoController::class);
});

// Sales team routes
Route::middleware(['auth', 'check.cargo:Directora Comercial,Asesora Comercial,Gerente,Administrador'])
    ->group(function () {
        Route::resource('ventas', VentaWebController::class);
        Route::get('/catalogo', [CatalogoWebController::class, 'index']);
    });

Performance Considerations

Eager Loading

Prevent N+1 queries with relationship eager loading:
$proyectos = Proyecto::with([
    'torres.apartamentos.estadoInmueble',
    'politicaVigente',
    'ubicacion'
])->get();

Database Transactions

Ensure data consistency for complex operations:
DB::transaction(function () {
    // All operations succeed or all fail
});

Pessimistic Locking

Prevent race conditions in concurrent sales:
$inmueble = Apartamento::where('id_apartamento', $id)
    ->lockForUpdate()
    ->firstOrFail();

User Roles

Learn about role-based access control

Projects

Understanding project structure

Properties

Property types and management

Sales Workflow

Sales process and operations

Build docs developers (and LLMs) love