Sistema de Contratos con Node.js y Vue.js

Desarrolla una solución completa para la gestión de contratos utilizando las tecnologías más modernas del desarrollo web.

Sistema de Contratos

Características del Sistema

Creación de Contratos

Interfaz intuitiva para crear contratos personalizados con plantillas predefinidas y campos dinámicos.

Búsqueda Avanzada

Encuentra contratos rápidamente utilizando filtros avanzados y búsqueda por palabras clave.

Gestión de Firmas

Sistema de firma digital con validación y seguimiento del estado de cada contrato.

Notificaciones

Sistema de alertas para recordatorios de vencimiento y acciones pendientes.

Reportes y Análisis

Genera reportes detallados y visualiza métricas importantes sobre tus contratos.

Seguridad

Protección de datos con encriptación, autenticación y control de acceso basado en roles.

Tecnologías Utilizadas

Backend con Node.js

Desarrollamos un servidor robusto y escalable utilizando Node.js y Express.js, con las siguientes características:

  • API RESTful para comunicación con el frontend
  • Autenticación JWT para seguridad
  • Conexión a base de datos MongoDB
  • Validación de datos con Joi
  • Subida y gestión de archivos
  • Envio de correos electrónicos

Frontend con Vue.js

Interfaz de usuario moderna y reactiva desarrollada con Vue.js y sus ecosistema:

  • Vue Router para navegación
  • Vuex para gestión de estado
  • Componentes reutilizables
  • Vuelidate para validación de formularios
  • Axios para comunicación con la API
Node.js
Node.js
Vue.js
Vue.js
Express.js
Express.js
MongoDB
MongoDB

Demo del Sistema

Proceso de Desarrollo

1. Planificación y Análisis

Definimos los requisitos del sistema, casos de uso y arquitectura general.

Node.js
Vue.js
MongoDB

2. Configuración del Backend

Configuramos el servidor Express, conexión a base de datos y modelos de datos.

// server.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');

const app = express();

// Middlewares
app.use(cors());
app.use(express.json());

// Conexión a MongoDB
mongoose.connect('mongodb://localhost:27017/contracts', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

// Rutas
app.use('/api/contracts', require('./routes/contracts'));
app.use('/api/auth', require('./routes/auth'));

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`Servidor ejecutándose en puerto ${PORT}`);
});

3. Desarrollo de la API

Implementamos endpoints para gestión de contratos, usuarios y autenticación.

// routes/contracts.js
const express = require('express');
const router = express.Router();
const Contract = require('../models/Contract');
const auth = require('../middleware/auth');

// Obtener todos los contratos
router.get('/', auth, async (req, res) => {
  try {
    const contracts = await Contract.find({ user: req.user.id });
    res.json(contracts);
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

// Crear nuevo contrato
router.post('/', auth, async (req, res) => {
  const contract = new Contract({
    title: req.body.title,
    description: req.body.description,
    parties: req.body.parties,
    terms: req.body.terms,
    user: req.user.id
  });

  try {
    const newContract = await contract.save();
    res.status(201).json(newContract);
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
});

4. Configuración del Frontend

Configuramos Vue.js, Vue Router y Vuex para la gestión del estado.

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App)
  .use(store)
  .use(router)
  .mount('#app')

// store/index.js
import { createStore } from 'vuex'

export default createStore({
  state: {
    user: null,
    contracts: [],
    loading: false
  },
  mutations: {
    SET_USER(state, user) {
      state.user = user
    },
    SET_CONTRACTS(state, contracts) {
      state.contracts = contracts
    }
  },
  actions: {
    async login({ commit }, credentials) {
      // Lógica de autenticación
    },
    async fetchContracts({ commit }) {
      // Obtener contratos desde la API
    }
  }
})

5. Componentes Vue

Desarrollamos componentes reutilizables para la interfaz de usuario.

<template>
  <div class="contract-list">
    <div class="header">
      <h2>Mis Contratos</h2>
      <button @click="showCreateModal = true" class="btn btn-primary">
        Nuevo Contrato
      </button>
    </div>
    
    <div class="filters">
      <input v-model="searchTerm" placeholder="Buscar contratos...">
      <select v-model="statusFilter">
        <option value="">Todos</option>
        <option value="active">Activos</option>
        <option value="pending">Pendientes</option>
        <option value="expired">Expirados</option>
      </select>
    </div>
    
    <div class="contracts-grid">
      <ContractCard 
        v-for="contract in filteredContracts" 
        :key="contract._id" 
        :contract="contract"
        @edit="editContract"
        @delete="deleteContract"
      />
    </div>
    
    <CreateContractModal 
      v-if="showCreateModal"
      @close="showCreateModal = false"
      @created="fetchContracts"
    />
  </div>
</template>

<script>
import { ref, computed, onMounted } from 'vue'
import { useStore } from 'vuex'
import ContractCard from '@/components/ContractCard.vue'
import CreateContractModal from '@/components/CreateContractModal.vue'

export default {
  name: 'ContractList',
  components: {
    ContractCard,
    CreateContractModal
  },
  setup() {
    const store = useStore()
    const searchTerm = ref('')
    const statusFilter = ref('')
    const showCreateModal = ref(false)
    
    const contracts = computed(() => store.state.contracts)
    
    const filteredContracts = computed(() => {
      return contracts.value.filter(contract => {
        const matchesSearch = contract.title.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
                            contract.description.toLowerCase().includes(searchTerm.value.toLowerCase())
        const matchesStatus = !statusFilter.value || contract.status === statusFilter.value
        return matchesSearch && matchesStatus
      })
    })
    
    const fetchContracts = async () => {
      await store.dispatch('fetchContracts')
    }
    
    onMounted(() => {
      fetchContracts()
    })
    
    return {
      searchTerm,
      statusFilter,
      showCreateModal,
      filteredContracts,
      fetchContracts
    }
  }
}
</script>

6. Integración y Pruebas

Conectamos frontend y backend, realizamos pruebas integrales y despliegue.

// services/api.js
import axios from 'axios'

const API_URL = process.env.VUE_APP_API_URL || 'http://localhost:5000/api'

const api = axios.create({
  baseURL: API_URL
})

// Interceptor para agregar token de autenticación
api.interceptors.request.use((config) => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

// Servicios para contratos
export const contractsService = {
  getAll: () => api.get('/contracts'),
  getById: (id) => api.get(`/contracts/${id}`),
  create: (data) => api.post('/contracts', data),
  update: (id, data) => api.put(`/contracts/${id}`, data),
  delete: (id) => api.delete(`/contracts/${id}`),
  sign: (id, signature) => api.post(`/contracts/${id}/sign`, { signature })
}

export default api

¿Interesado en el Proyecto?