commit 9bfb78c65034061b625a439e03e6145e6210ce46 Author: Scorpion Callejas Date: Fri Dec 26 21:43:42 2025 -0600 Initial commit - estructura completa del proyecto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9cb63aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.env +*.log +__pycache__/ +venv/ +node_modules/ +vendor/ +.idea/ +.vscode/ diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..d9d11ff --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,21 @@ +FROM python:3.11-slim + +WORKDIR /app + +# Instalar dependencias del sistema +RUN apt-get update && apt-get install -y \ + gcc \ + libpq-dev \ + postgresql-client \ + && rm -rf /var/lib/apt/lists/* + +# Copiar requirements e instalar dependencias Python +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copiar el proyecto +COPY . . + +EXPOSE 8000 + +CMD ["sh", "-c", "sleep 5 && python manage.py migrate && python manage.py runserver 0.0.0.0:8000"] diff --git a/backend/inventario/__init__.py b/backend/inventario/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/inventario/admin.py b/backend/inventario/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/backend/inventario/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/inventario/apps.py b/backend/inventario/apps.py new file mode 100644 index 0000000..0478bb5 --- /dev/null +++ b/backend/inventario/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class InventarioConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'inventario' diff --git a/backend/inventario/migrations/__init__.py b/backend/inventario/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/inventario/models.py b/backend/inventario/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/backend/inventario/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/backend/inventario/tests.py b/backend/inventario/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/backend/inventario/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/inventario/views.py b/backend/inventario/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/backend/inventario/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/backend/manage.py b/backend/manage.py new file mode 100755 index 0000000..9784925 --- /dev/null +++ b/backend/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pycore_db.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/backend/pycore/__init__.py b/backend/pycore/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/pycore/asgi.py b/backend/pycore/asgi.py new file mode 100644 index 0000000..8872402 --- /dev/null +++ b/backend/pycore/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for pycore project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pycore_db.settings') + +application = get_asgi_application() diff --git a/backend/pycore/settings.py b/backend/pycore/settings.py new file mode 100644 index 0000000..5d690d9 --- /dev/null +++ b/backend/pycore/settings.py @@ -0,0 +1,102 @@ +import os +from pathlib import Path + +import sys +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) + +BASE_DIR = Path(__file__).resolve().parent.parent + +SECRET_KEY = os.environ.get('SECRET_KEY', 'clave-temporal-cambiar') + +DEBUG = os.environ.get('DEBUG', 'False') == 'True' + +ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'backend', '0.0.0.0'] + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', + 'corsheaders', + 'inventario', + 'ventas', + 'sucursales', +] + +MIDDLEWARE = [ + 'corsheaders.middleware.CorsMiddleware', + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'pycore.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'pycore.wsgi.application' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'pycore_db', + 'USER': 'Scorpion', + 'PASSWORD': 'CyCoT256', + 'HOST': 'db', + 'PORT': '5432', + } +} + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +LANGUAGE_CODE = 'es-mx' +TIME_ZONE = 'America/Mexico_City' +USE_I18N = True +USE_TZ = True + +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +REST_FRAMEWORK = { + 'DEFAULT_PERMISSION_CLASSES': [ + 'rest_framework.permissions.AllowAny', + ] +} + +CORS_ALLOW_ALL_ORIGINS = True diff --git a/backend/pycore/urls.py b/backend/pycore/urls.py new file mode 100644 index 0000000..280b532 --- /dev/null +++ b/backend/pycore/urls.py @@ -0,0 +1,22 @@ +""" +URL configuration for pycore project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] diff --git a/backend/pycore/wsgi.py b/backend/pycore/wsgi.py new file mode 100644 index 0000000..8168255 --- /dev/null +++ b/backend/pycore/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for pycore project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pycore.settings') + +application = get_wsgi_application() diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..385c0fe --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,7 @@ +Django==4.2.7 +djangorestframework==3.14.0 +django-cors-headers==4.3.1 +psycopg2-binary==2.9.7 +python-decouple==3.8 +Pillow==10.0.1 +gunicorn==21.2.0 diff --git a/backend/sucursales/__init__.py b/backend/sucursales/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/sucursales/admin.py b/backend/sucursales/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/backend/sucursales/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/sucursales/apps.py b/backend/sucursales/apps.py new file mode 100644 index 0000000..abe9cc9 --- /dev/null +++ b/backend/sucursales/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class SucursalesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'sucursales' diff --git a/backend/sucursales/migrations/__init__.py b/backend/sucursales/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/sucursales/models.py b/backend/sucursales/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/backend/sucursales/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/backend/sucursales/tests.py b/backend/sucursales/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/backend/sucursales/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/sucursales/views.py b/backend/sucursales/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/backend/sucursales/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/backend/ventas/__init__.py b/backend/ventas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/ventas/admin.py b/backend/ventas/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/backend/ventas/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/ventas/apps.py b/backend/ventas/apps.py new file mode 100644 index 0000000..568755f --- /dev/null +++ b/backend/ventas/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class VentasConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'ventas' diff --git a/backend/ventas/migrations/__init__.py b/backend/ventas/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/ventas/models.py b/backend/ventas/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/backend/ventas/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/backend/ventas/tests.py b/backend/ventas/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/backend/ventas/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/ventas/views.py b/backend/ventas/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/backend/ventas/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/backend/wait-for-db.sh b/backend/wait-for-db.sh new file mode 100755 index 0000000..1abd3ca --- /dev/null +++ b/backend/wait-for-db.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# wait-for-db.sh + +set -e + +host="$1" +shift +cmd="$@" + +until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "Scorpion" -d "pycore_db" -c '\q'; do + >&2 echo "PostgreSQL no está disponible - esperando..." + sleep 1 +done + +>&2 echo "PostgreSQL está listo - ejecutando comando" +exec $cmd diff --git a/check-status.sh b/check-status.sh new file mode 100755 index 0000000..5a77128 --- /dev/null +++ b/check-status.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +echo "🔍 Verificando estado de pycore ..." + +echo "📊 Contenedores:" +docker-compose ps + +echo "" +echo "🌐 Verificando servicios:" + +# Esperar un poco para que todo esté listo +sleep 5 + +# Verificar backend +echo -n "Backend (8000): " +if curl -s http://localhost:8000 > /dev/null; then + echo "✅ OK" +else + echo "❌ Falló" +fi + +# Verificar frontend +echo -n "Frontend (3000): " +if curl -s http://localhost:3000 > /dev/null; then + echo "✅ OK" +else + echo "❌ Falló" +fi + +# Verificar pgadmin +echo -n "PgAdmin (5050): " +if curl -s http://localhost:5050 > /dev/null; then + echo "✅ OK" +else + echo "❌ Falló" +fi + +# Verificar base de datos +echo -n "Base de datos: " +if docker-compose exec db pg_isready -U Scorpion -d pycore_db; then + echo "✅ OK" +else + echo "❌ Falló" +fi + +echo "" +echo "📝 Logs recientes del backend:" +docker-compose logs backend --tail=5 diff --git a/clean.sh b/clean.sh new file mode 100755 index 0000000..fda532c --- /dev/null +++ b/clean.sh @@ -0,0 +1,5 @@ +#!/bin/bash +echo "🧹 Limpiando todo..." +docker-compose down -v +docker system prune -f +echo "✅ Limpieza completada" diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..5b57087 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,12 @@ +version: '3.8' + +services: + backend: + command: > + sh -c "until pg_isready -h db -p 5432; do + echo 'Esperando a la base de datos...'; + sleep 2; + done; + echo 'BD lista!'; + python manage.py migrate; + python manage.py runserver 0.0.0.0:8000" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b96a212 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,83 @@ +version: '3.8' + +services: + # Base de datos PostgreSQL + db: + image: postgres:15 + container_name: pycore_db + environment: + POSTGRES_DB: pycore_db + POSTGRES_USER: Scorpion + POSTGRES_PASSWORD: CyCoT256 + volumes: + - postgres_data:/var/lib/postgresql/data + - ./postgres/init:/docker-entrypoint-initdb.d + ports: + - "5432:5432" + networks: + - pycore_network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U Scorpion -d pycore_db"] + interval: 5s + timeout: 5s + retries: 5 + + # PgAdmin + pgadmin: + image: dpage/pgadmin4 + container_name: pycore_pgadmin + environment: + PGADMIN_DEFAULT_EMAIL: admin@pycore.com + PGADMIN_DEFAULT_PASSWORD: CyCoT256 + ports: + - "5050:80" + depends_on: + - db + networks: + - pycore_network + + # Backend Django + backend: + build: ./backend + container_name: pycore_backend + volumes: + - ./backend:/app + ports: + - "8000:8000" + depends_on: + db: + condition: service_healthy + environment: + DATABASE_URL: postgresql://Scorpion:CyCoT256@db:5432/pycore_db + DEBUG: "True" + SECRET_KEY: "clave-secreta-temporal-2024" + networks: + - pycore_network + command: > + sh -c "echo 'Esperando a que la base de datos esté lista...' && + sleep 10 && + python manage.py migrate && + python manage.py runserver 0.0.0.0:8000" + + # Frontend React + frontend: + build: ./frontend + container_name: pycore_frontend + volumes: + - ./frontend:/app + - /app/node_modules + ports: + - "3000:3000" + depends_on: + - backend + environment: + VITE_API_URL: http://localhost:8000/api + networks: + - pycore_network + +networks: + pycore_network: + driver: bridge + +volumes: + postgres_data: diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..3c5ac0c --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,12 @@ +FROM node:18-alpine + +WORKDIR /app + +COPY package.json ./ +RUN npm install + +COPY . . + +EXPOSE 3000 + +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..850b02a --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,12 @@ + + + + + + pycore + + +
+ + + diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..d11c5f7 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,23 @@ +{ + "name": "pycore-frontend", + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.16.0", + "axios": "^1.5.0" + }, + "devDependencies": { + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@vitejs/plugin-react": "^4.0.3", + "typescript": "^5.0.2", + "vite": "^4.4.5" + } +} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 0000000..b1dd4eb --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,21 @@ +import React from 'react'; + +const App: React.FC = () => { + return ( +
+

🚀 pycore - ERP

+

El sistema está funcionando correctamente.

+
+

Servicios disponibles:

+
    +
  • 🌐 Frontend: http://localhost:3000
  • +
  • 🔧 Backend API: http://localhost:8000
  • +
  • 📊 PgAdmin: http://localhost:5050
  • +
  • 🗄️ PostgreSQL: localhost:5432
  • +
+
+
+ ); +}; + +export default App; diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 0000000..c4c5b6d --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,9 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..8d6e2e6 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + server: { + host: '0.0.0.0', + port: 3000 + } +}) diff --git a/postgres/init/01-init.sql b/postgres/init/01-init.sql new file mode 100644 index 0000000..fe65d6b --- /dev/null +++ b/postgres/init/01-init.sql @@ -0,0 +1,174 @@ +-- Script de inicialización para pycore +-- Verificar si la base de datos ya existe y solo crear tablas si no existen + +-- Crear tipos ENUM personalizados si no existen +DO $$ BEGIN + CREATE TYPE tipo_producto_enum AS ENUM ('insumo', 'terminado'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- 1️⃣ Sucursales +CREATE TABLE IF NOT EXISTS Sucursales ( + id_sucursal SERIAL PRIMARY KEY, + nombre VARCHAR(100) NOT NULL, + direccion VARCHAR(255), + telefono VARCHAR(20), + fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 2️⃣ Inventario +CREATE TABLE IF NOT EXISTS Inventario ( + id_producto SERIAL PRIMARY KEY, + nombre_producto VARCHAR(100) NOT NULL, + tipo_producto tipo_producto_enum NOT NULL, + precio_unitario DECIMAL(10,2) NOT NULL, + stock INT DEFAULT 0, + id_sucursal INT, + fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (id_sucursal) REFERENCES Sucursales(id_sucursal) +); + +-- 3️⃣ Compras +CREATE TABLE IF NOT EXISTS Compras ( + id_compra SERIAL PRIMARY KEY, + id_sucursal INT NOT NULL, + fecha_compra DATE NOT NULL, + total DECIMAL(10,2) NOT NULL, + FOREIGN KEY (id_sucursal) REFERENCES Sucursales(id_sucursal) +); + +-- 4️⃣ Detalle_compras +CREATE TABLE IF NOT EXISTS Detalle_compras ( + id_detalle SERIAL PRIMARY KEY, + id_compra INT NOT NULL, + id_producto INT NOT NULL, + cantidad INT NOT NULL, + precio_unitario DECIMAL(10,2) NOT NULL, + FOREIGN KEY (id_compra) REFERENCES Compras(id_compra), + FOREIGN KEY (id_producto) REFERENCES Inventario(id_producto) +); + +-- 5️⃣ Promociones +CREATE TABLE IF NOT EXISTS Promociones ( + id_promocion SERIAL PRIMARY KEY, + nombre_promocion VARCHAR(100) NOT NULL, + descripcion TEXT, + descuento DECIMAL(5,2), -- Porcentaje + fecha_inicio DATE, + fecha_fin DATE +); + +-- 6️⃣ Colaboradores +CREATE TABLE IF NOT EXISTS Colaboradores ( + id_colaborador SERIAL PRIMARY KEY, + id_sucursal INT NOT NULL, + nombre VARCHAR(100) NOT NULL, + puesto VARCHAR(50), + salario DECIMAL(10,2), + fecha_ingreso DATE, + FOREIGN KEY (id_sucursal) REFERENCES Sucursales(id_sucursal) +); + +-- 7️⃣ Gastos_sucursal +CREATE TABLE IF NOT EXISTS Gastos_sucursal ( + id_gasto SERIAL PRIMARY KEY, + id_sucursal INT NOT NULL, + concepto VARCHAR(255) NOT NULL, + monto DECIMAL(10,2) NOT NULL, + fecha_gasto DATE NOT NULL, + FOREIGN KEY (id_sucursal) REFERENCES Sucursales(id_sucursal) +); + +-- 8️⃣ Ventas +CREATE TABLE IF NOT EXISTS Ventas ( + id_venta SERIAL PRIMARY KEY, + id_sucursal INT NOT NULL, + fecha_venta TIMESTAMP NOT NULL, + total DECIMAL(10,2) NOT NULL, + id_promocion INT, + FOREIGN KEY (id_sucursal) REFERENCES Sucursales(id_sucursal), + FOREIGN KEY (id_promocion) REFERENCES Promociones(id_promocion) +); + +-- 9️⃣ Detalle_ventas +CREATE TABLE IF NOT EXISTS Detalle_ventas ( + id_detalle SERIAL PRIMARY KEY, + id_venta INT NOT NULL, + id_producto INT NOT NULL, + cantidad INT NOT NULL, + precio_unitario DECIMAL(10,2) NOT NULL, + FOREIGN KEY (id_venta) REFERENCES Ventas(id_venta), + FOREIGN KEY (id_producto) REFERENCES Inventario(id_producto) +); + +-- ========================== +-- ÍNDICES PARA MEJOR PERFORMANCE +-- ========================== + +DO $$ BEGIN + CREATE INDEX IF NOT EXISTS idx_inventario_sucursal ON Inventario(id_sucursal); + CREATE INDEX IF NOT EXISTS idx_ventas_fecha ON Ventas(fecha_venta); + CREATE INDEX IF NOT EXISTS idx_ventas_sucursal ON Ventas(id_sucursal); + CREATE INDEX IF NOT EXISTS idx_compras_fecha ON Compras(fecha_compra); + CREATE INDEX IF NOT EXISTS idx_detalle_ventas_producto ON Detalle_ventas(id_producto); + CREATE INDEX IF NOT EXISTS idx_detalle_compras_producto ON Detalle_compras(id_producto); + CREATE INDEX IF NOT EXISTS idx_colaboradores_sucursal ON Colaboradores(id_sucursal); +EXCEPTION + WHEN duplicate_table THEN null; +END $$; + +-- ========================== +-- DATOS DE EJEMPLO +-- ========================== + +-- Insertar sucursal principal si no existen +INSERT INTO Sucursales (id_sucursal, nombre, direccion, telefono) VALUES +(1, 'Alitas Downtown', 'Av. Principal 123, Ciudad', '+52-55-1234-5678'), +(2, 'Alitas Norte', 'Plaza Norte 456, Zona Norte', '+52-55-8765-4321') +ON CONFLICT (id_sucursal) DO UPDATE SET +nombre = EXCLUDED.nombre, +direccion = EXCLUDED.direccion, +telefono = EXCLUDED.telefono; + +-- Insertar productos típicos de alitas +INSERT INTO Inventario (id_producto, nombre_producto, tipo_producto, precio_unitario, stock, id_sucursal) VALUES +(1, 'Alitas de pollo', 'insumo', 45.50, 200, 1), +(2, 'Salsa BBQ', 'insumo', 25.00, 50, 1), +(3, 'Salsa Buffalo', 'insumo', 28.00, 40, 1), +(4, 'Papas para freír', 'insumo', 18.00, 100, 1), +(5, 'Harina para empanizar', 'insumo', 12.50, 30, 1), +(6, 'Orden de alitas (6 pzas)', 'terminado', 120.00, 0, 1), +(7, 'Orden de alitas (12 pzas)', 'terminado', 220.00, 0, 1), +(8, 'Papas a la francesa', 'terminado', 45.00, 0, 1), +(9, 'Aros de cebolla', 'terminado', 55.00, 0, 1) +ON CONFLICT (id_producto) DO UPDATE SET +nombre_producto = EXCLUDED.nombre_producto, +tipo_producto = EXCLUDED.tipo_producto, +precio_unitario = EXCLUDED.precio_unitario, +stock = EXCLUDED.stock, +id_sucursal = EXCLUDED.id_sucursal; + +-- Insertar promociones +INSERT INTO Promociones (id_promocion, nombre_promocion, descripcion, descuento, fecha_inicio, fecha_fin) VALUES +(1, 'Martes de Alitas', '2x1 en órdenes de alitas todos los martes', 50.00, '2024-01-01', '2024-12-31'), +(2, 'Happy Hour', '20% de descuento en bebidas de 4pm a 7pm', 20.00, '2024-01-01', '2024-12-31'), +(3, 'Combo Familiar', 'Descuento especial en combos familiares', 15.00, '2024-03-01', '2024-03-31') +ON CONFLICT (id_promocion) DO UPDATE SET +nombre_promocion = EXCLUDED.nombre_promocion, +descripcion = EXCLUDED.descripcion, +descuento = EXCLUDED.descuento, +fecha_inicio = EXCLUDED.fecha_inicio, +fecha_fin = EXCLUDED.fecha_fin; + +-- Insertar colaboradores +INSERT INTO Colaboradores (id_colaborador, id_sucursal, nombre, puesto, salario, fecha_ingreso) VALUES +(1, 1, 'Juan Pérez García', 'Gerente', 15000.00, '2023-01-15'), +(2, 1, 'María Hernández López', 'Cocinero', 8000.00, '2023-03-20'), +(3, 1, 'Carlos Rodríguez Silva', 'Mesero', 6000.00, '2023-05-10') +ON CONFLICT (id_colaborador) DO UPDATE SET +id_sucursal = EXCLUDED.id_sucursal, +nombre = EXCLUDED.nombre, +puesto = EXCLUDED.puesto, +salario = EXCLUDED.salario, +fecha_ingreso = EXCLUDED.fecha_ingreso; diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..cb1b72a --- /dev/null +++ b/start.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +echo "🚀 Iniciando pycore ..." + +# Verificar Docker +if ! command -v docker &> /dev/null; then + echo "❌ Docker no está instalado" + exit 1 +fi + +# Construir y levantar +echo "📦 Construyendo contenedores..." +docker-compose up --build -d + +echo "⏳ Esperando inicialización..." +sleep 15 + +echo "✅ Servicios iniciados:" +echo " 🌐 Frontend: http://localhost:3000" +echo " 🔧 Backend: http://localhost:8000" +echo " 📊 PgAdmin: http://localhost:5050" +echo " 🗄️ PostgreSQL: localhost:5432" +echo "" +echo "🔑 PgAdmin: admin@pycore.com / CyCoT256" diff --git a/stop.sh b/stop.sh new file mode 100755 index 0000000..f06fa4c --- /dev/null +++ b/stop.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo "🛑 Deteniendo pycore ..." +docker-compose down +echo "✅ Servicios detenidos"