Some checks are pending
CI Pipeline / changes (push) Waiting to run
CI Pipeline / core (push) Blocked by required conditions
CI Pipeline / trading-backend (push) Blocked by required conditions
CI Pipeline / trading-data-service (push) Blocked by required conditions
CI Pipeline / trading-frontend (push) Blocked by required conditions
CI Pipeline / erp-core (push) Blocked by required conditions
CI Pipeline / erp-mecanicas (push) Blocked by required conditions
CI Pipeline / gamilit-backend (push) Blocked by required conditions
CI Pipeline / gamilit-frontend (push) Blocked by required conditions
Core: - Add catalog reference implementations (auth, payments, notifications, websocket, etc.) - New agent profiles: Database Auditor, Integration Validator, LLM Agent, Policy Auditor, Trading Strategist - Update SIMCO directives and add escalation/git guidelines - Add deployment inventory and audit execution reports Projects: - erp-suite: DevOps configs, Dockerfiles, shared libs, vertical enhancements - gamilit: Test structure, admin controllers, service refactoring, husky/commitlint - trading-platform: MT4 gateway, auth controllers, admin frontend, deployment scripts - platform_marketing_content: Full DevOps setup, tests, Docker configs - betting-analytics/inmobiliaria-analytics: Initial app structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
764 lines
20 KiB
Markdown
764 lines
20 KiB
Markdown
# Vertical Development Guide
|
|
|
|
## Overview
|
|
|
|
Este documento explica cómo crear una **nueva vertical** de negocio que extiende el **erp-core** genérico. El patrón sigue el modelo de Odoo ERP: core reutilizable + extensiones especializadas por industria.
|
|
|
|
**Verticales Existentes:**
|
|
- Construcción (INFONAVIT) - 35% completado
|
|
- Vidrio Templado - 0%
|
|
- Mecánicas Diesel - 30%
|
|
- Retail (POS) - 0%
|
|
- Clínicas - 0%
|
|
|
|
## Architecture Pattern
|
|
|
|
### Core + Vertical Model
|
|
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ ERP CORE (60-70%) │
|
|
│ Generic modules: auth, inventory, │
|
|
│ sales, purchases, financial, etc. │
|
|
└────────────┬────────────────────────┘
|
|
│ extends
|
|
▼
|
|
┌─────────────────────────────────────┐
|
|
│ VERTICAL (30-40%) │
|
|
│ Industry-specific extensions │
|
|
│ - Override methods │
|
|
│ - Add new modules │
|
|
│ - Extend database schemas │
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
### Key Principles
|
|
|
|
1. **Don't modify core** - Core stays generic and reusable
|
|
2. **Extend, don't replace** - Vertical extends core modules
|
|
3. **Inheritance over duplication** - Use TypeScript class inheritance
|
|
4. **Additive database changes** - Add schemas, don't modify core schemas
|
|
5. **Separate documentation** - Each vertical has its own docs/
|
|
|
|
## Step-by-Step: Create New Vertical
|
|
|
|
### 1. Project Structure
|
|
|
|
```bash
|
|
# Create vertical directory
|
|
mkdir -p apps/verticales/my-vertical
|
|
|
|
cd apps/verticales/my-vertical
|
|
|
|
# Create standard structure
|
|
mkdir -p backend/src/{modules,shared}
|
|
mkdir -p frontend/src/{modules,shared}
|
|
mkdir -p database/ddl/schemas
|
|
mkdir -p docs
|
|
mkdir -p orchestration/{00-guidelines,trazas,estados}
|
|
```
|
|
|
|
**Result:**
|
|
```
|
|
apps/verticales/my-vertical/
|
|
├── backend/
|
|
│ └── src/
|
|
│ ├── modules/ # Industry-specific modules
|
|
│ ├── shared/ # Shared utilities
|
|
│ ├── routes/ # API routes
|
|
│ └── index.ts # Entry point
|
|
├── frontend/
|
|
│ └── src/
|
|
│ ├── modules/ # UI modules
|
|
│ └── shared/ # Shared components
|
|
├── database/
|
|
│ ├── ddl/
|
|
│ │ └── schemas/ # Vertical schemas
|
|
│ ├── migrations/ # Database migrations
|
|
│ └── seeds/ # Test data
|
|
├── docs/ # Vertical documentation
|
|
└── orchestration/ # Agent orchestration
|
|
├── 00-guidelines/
|
|
│ └── CONTEXTO-PROYECTO.md
|
|
├── trazas/
|
|
├── estados/
|
|
└── PROXIMA-ACCION.md
|
|
```
|
|
|
|
### 2. Define Vertical Context
|
|
|
|
Create `orchestration/00-guidelines/CONTEXTO-PROYECTO.md`:
|
|
|
|
```markdown
|
|
# Contexto del Proyecto: [Vertical Name]
|
|
|
|
## Descripción
|
|
[What is this vertical? What industry problem does it solve?]
|
|
|
|
## Módulos Específicos
|
|
1. [Module 1] - [Description]
|
|
2. [Module 2] - [Description]
|
|
|
|
## Dependencias del Core
|
|
- auth: Authentication & authorization
|
|
- inventory: Product management (extended)
|
|
- sales: Sales management (extended)
|
|
- [List core modules used]
|
|
|
|
## Schemas de Base de Datos
|
|
1. [schema_name] - [Purpose]
|
|
2. [schema_name] - [Purpose]
|
|
|
|
## Estado Actual
|
|
[Current development status]
|
|
```
|
|
|
|
### 3. Database Schema Design
|
|
|
|
#### Create Vertical Schema
|
|
|
|
```bash
|
|
# Create schema DDL
|
|
touch database/ddl/schemas/my_vertical_management/schema.sql
|
|
```
|
|
|
|
**Example:** `database/ddl/schemas/my_vertical_management/schema.sql`
|
|
|
|
```sql
|
|
-- ============================================
|
|
-- SCHEMA: my_vertical_management
|
|
-- PURPOSE: Industry-specific data for my vertical
|
|
-- DEPENDS ON: auth, core, inventory (from erp-core)
|
|
-- ============================================
|
|
|
|
CREATE SCHEMA IF NOT EXISTS my_vertical_management;
|
|
|
|
-- ============================================
|
|
-- TABLE: my_vertical_management.custom_entities
|
|
-- ============================================
|
|
CREATE TABLE my_vertical_management.custom_entities (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
|
|
|
|
-- Link to core entities
|
|
product_id UUID REFERENCES products.products(id),
|
|
partner_id UUID REFERENCES core.partners(id),
|
|
|
|
-- Vertical-specific fields
|
|
industry_code VARCHAR(50) NOT NULL,
|
|
certification_date DATE,
|
|
compliance_status VARCHAR(20),
|
|
|
|
-- Standard audit fields
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_custom_entities_tenant_id
|
|
ON my_vertical_management.custom_entities(tenant_id);
|
|
|
|
CREATE INDEX idx_custom_entities_industry_code
|
|
ON my_vertical_management.custom_entities(tenant_id, industry_code)
|
|
WHERE deleted_at IS NULL;
|
|
|
|
-- RLS Policy
|
|
ALTER TABLE my_vertical_management.custom_entities ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation ON my_vertical_management.custom_entities
|
|
USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
|
|
|
|
-- Permissions
|
|
GRANT SELECT, INSERT, UPDATE, DELETE
|
|
ON my_vertical_management.custom_entities TO erp_app_user;
|
|
|
|
-- Comments
|
|
COMMENT ON TABLE my_vertical_management.custom_entities IS
|
|
'Stores industry-specific entity data for my vertical';
|
|
```
|
|
|
|
### 4. Backend Module Structure
|
|
|
|
#### Extend Core Module
|
|
|
|
**Example:** Extending Projects module
|
|
|
|
```typescript
|
|
// backend/src/modules/projects/vertical-project.service.ts
|
|
import { ProjectService } from '@erp-core/modules/projects/project.service';
|
|
import { CreateProjectDto } from '@erp-core/modules/projects/dto';
|
|
|
|
interface CreateVerticalProjectDto extends CreateProjectDto {
|
|
// Add vertical-specific fields
|
|
industryCode: string;
|
|
certificationDate?: Date;
|
|
complianceStatus: string;
|
|
}
|
|
|
|
export class VerticalProjectService extends ProjectService {
|
|
/**
|
|
* Override create method to add vertical logic
|
|
*/
|
|
async create(
|
|
data: CreateVerticalProjectDto,
|
|
tenantId: string,
|
|
userId: string
|
|
): Promise<Project> {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
await client.query('BEGIN');
|
|
|
|
// 1. Call parent method (creates core project)
|
|
const project = await super.create(data, tenantId, userId);
|
|
|
|
// 2. Create vertical-specific data
|
|
await client.query(`
|
|
INSERT INTO my_vertical_management.custom_entities (
|
|
tenant_id, product_id, industry_code,
|
|
certification_date, compliance_status,
|
|
created_by
|
|
) VALUES ($1, $2, $3, $4, $5, $6)
|
|
`, [
|
|
tenantId,
|
|
project.id,
|
|
data.industryCode,
|
|
data.certificationDate,
|
|
data.complianceStatus,
|
|
userId
|
|
]);
|
|
|
|
await client.query('COMMIT');
|
|
return project;
|
|
|
|
} catch (error) {
|
|
await client.query('ROLLBACK');
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add vertical-specific method
|
|
*/
|
|
async findByCertificationDate(
|
|
tenantId: string,
|
|
startDate: Date,
|
|
endDate: Date
|
|
): Promise<any[]> {
|
|
const query = `
|
|
SELECT p.*, ce.industry_code, ce.certification_date
|
|
FROM projects.projects p
|
|
INNER JOIN my_vertical_management.custom_entities ce
|
|
ON p.id = ce.product_id
|
|
WHERE p.tenant_id = $1
|
|
AND ce.certification_date BETWEEN $2 AND $3
|
|
AND p.deleted_at IS NULL
|
|
`;
|
|
|
|
const result = await this.pool.query(query, [tenantId, startDate, endDate]);
|
|
return result.rows;
|
|
}
|
|
|
|
/**
|
|
* Override validation
|
|
*/
|
|
protected async validateProjectData(data: CreateVerticalProjectDto): Promise<void> {
|
|
// Call parent validation
|
|
await super.validateProjectData(data);
|
|
|
|
// Add vertical-specific validation
|
|
if (!data.industryCode) {
|
|
throw new Error('Industry code is required for this vertical');
|
|
}
|
|
|
|
if (data.complianceStatus && !['pending', 'approved', 'rejected'].includes(data.complianceStatus)) {
|
|
throw new Error('Invalid compliance status');
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Create New Module
|
|
|
|
**Example:** Vertical-specific module
|
|
|
|
```typescript
|
|
// backend/src/modules/certifications/certification.service.ts
|
|
import { BaseService } from '@erp-core/shared/services/base.service';
|
|
|
|
interface Certification {
|
|
id: string;
|
|
tenantId: string;
|
|
entityId: string;
|
|
certificationNumber: string;
|
|
issueDate: Date;
|
|
expiryDate: Date;
|
|
status: string;
|
|
}
|
|
|
|
interface CreateCertificationDto {
|
|
entityId: string;
|
|
certificationNumber: string;
|
|
issueDate: Date;
|
|
expiryDate: Date;
|
|
}
|
|
|
|
export class CertificationService extends BaseService<
|
|
Certification,
|
|
CreateCertificationDto,
|
|
Partial<CreateCertificationDto>
|
|
> {
|
|
constructor() {
|
|
super('certifications', 'my_vertical_management');
|
|
}
|
|
|
|
/**
|
|
* Find certifications expiring soon
|
|
*/
|
|
async findExpiringSoon(
|
|
tenantId: string,
|
|
daysAhead: number = 30
|
|
): Promise<Certification[]> {
|
|
const query = `
|
|
SELECT *
|
|
FROM my_vertical_management.certifications
|
|
WHERE tenant_id = $1
|
|
AND expiry_date <= NOW() + INTERVAL '${daysAhead} days'
|
|
AND expiry_date >= NOW()
|
|
AND deleted_at IS NULL
|
|
ORDER BY expiry_date ASC
|
|
`;
|
|
|
|
const result = await this.pool.query(query, [tenantId]);
|
|
return result.rows;
|
|
}
|
|
|
|
/**
|
|
* Renew certification
|
|
*/
|
|
async renew(
|
|
certificationId: string,
|
|
tenantId: string,
|
|
userId: string,
|
|
newExpiryDate: Date
|
|
): Promise<Certification> {
|
|
const query = `
|
|
UPDATE my_vertical_management.certifications
|
|
SET
|
|
expiry_date = $1,
|
|
status = 'active',
|
|
updated_by = $2,
|
|
updated_at = NOW()
|
|
WHERE id = $3 AND tenant_id = $4
|
|
RETURNING *
|
|
`;
|
|
|
|
const result = await this.pool.query(query, [
|
|
newExpiryDate,
|
|
userId,
|
|
certificationId,
|
|
tenantId
|
|
]);
|
|
|
|
return result.rows[0];
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. API Routes
|
|
|
|
```typescript
|
|
// backend/src/routes/index.ts
|
|
import express from 'express';
|
|
import { VerticalProjectService } from '../modules/projects/vertical-project.service';
|
|
import { CertificationService } from '../modules/certifications/certification.service';
|
|
import { authenticateJWT } from '@erp-core/middleware/auth.middleware';
|
|
|
|
const router = express.Router();
|
|
|
|
const projectService = new VerticalProjectService();
|
|
const certificationService = new CertificationService();
|
|
|
|
// Extend core projects endpoint
|
|
router.post('/projects', authenticateJWT, async (req, res) => {
|
|
try {
|
|
const project = await projectService.create(
|
|
req.body,
|
|
req.user.tenantId,
|
|
req.user.id
|
|
);
|
|
res.status(201).json(project);
|
|
} catch (error) {
|
|
res.status(400).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
// Vertical-specific endpoint
|
|
router.get('/certifications/expiring', authenticateJWT, async (req, res) => {
|
|
try {
|
|
const daysAhead = parseInt(req.query.days as string) || 30;
|
|
const certs = await certificationService.findExpiringSoon(
|
|
req.user.tenantId,
|
|
daysAhead
|
|
);
|
|
res.json(certs);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
export default router;
|
|
```
|
|
|
|
### 6. Frontend Module
|
|
|
|
```tsx
|
|
// frontend/src/modules/certifications/CertificationList.tsx
|
|
import React, { useEffect, useState } from 'react';
|
|
import { api } from '../../shared/utils/api';
|
|
|
|
interface Certification {
|
|
id: string;
|
|
certificationNumber: string;
|
|
issueDate: string;
|
|
expiryDate: string;
|
|
status: string;
|
|
}
|
|
|
|
export const CertificationList: React.FC = () => {
|
|
const [certifications, setCertifications] = useState<Certification[]>([]);
|
|
|
|
useEffect(() => {
|
|
fetchCertifications();
|
|
}, []);
|
|
|
|
const fetchCertifications = async () => {
|
|
const response = await api.get('/certifications/expiring?days=30');
|
|
setCertifications(response.data);
|
|
};
|
|
|
|
return (
|
|
<div className="p-4">
|
|
<h2 className="text-2xl font-bold mb-4">Certifications Expiring Soon</h2>
|
|
|
|
<table className="w-full border-collapse border">
|
|
<thead>
|
|
<tr className="bg-gray-100">
|
|
<th className="border p-2">Certification Number</th>
|
|
<th className="border p-2">Issue Date</th>
|
|
<th className="border p-2">Expiry Date</th>
|
|
<th className="border p-2">Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{certifications.map((cert) => (
|
|
<tr key={cert.id}>
|
|
<td className="border p-2">{cert.certificationNumber}</td>
|
|
<td className="border p-2">{new Date(cert.issueDate).toLocaleDateString()}</td>
|
|
<td className="border p-2">{new Date(cert.expiryDate).toLocaleDateString()}</td>
|
|
<td className="border p-2">
|
|
<span className={`px-2 py-1 rounded ${
|
|
cert.status === 'active' ? 'bg-green-200' : 'bg-red-200'
|
|
}`}>
|
|
{cert.status}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
};
|
|
```
|
|
|
|
### 7. Documentation
|
|
|
|
Create documentation for your vertical:
|
|
|
|
#### Required Docs
|
|
|
|
1. **CONTEXTO-PROYECTO.md** - Project overview
|
|
2. **REQUERIMIENTOS.md** - Functional requirements
|
|
3. **MODELO-DATOS.md** - Database schema documentation
|
|
4. **API.md** - API endpoints
|
|
5. **GUIA-USUARIO.md** - User guide
|
|
|
|
#### Example: MODELO-DATOS.md
|
|
|
|
```markdown
|
|
# Modelo de Datos: [Vertical Name]
|
|
|
|
## Schemas
|
|
|
|
### my_vertical_management
|
|
|
|
#### Tablas
|
|
|
|
##### custom_entities
|
|
**Propósito:** Almacena datos específicos de la industria
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| id | UUID | Primary key |
|
|
| tenant_id | UUID | Tenant isolation |
|
|
| product_id | UUID | Link to core product |
|
|
| industry_code | VARCHAR(50) | Industry classification code |
|
|
| certification_date | DATE | Date of certification |
|
|
| compliance_status | VARCHAR(20) | Compliance status |
|
|
|
|
**Índices:**
|
|
- `idx_custom_entities_tenant_id` - Performance
|
|
- `idx_custom_entities_industry_code` - Queries by code
|
|
|
|
**RLS:** Enabled (tenant_isolation policy)
|
|
```
|
|
|
|
### 8. Integration with Core
|
|
|
|
#### Import Core Modules
|
|
|
|
```typescript
|
|
// backend/src/modules/projects/vertical-project.service.ts
|
|
|
|
// Option 1: Direct import (if monorepo)
|
|
import { ProjectService } from '../../../erp-core/backend/src/modules/projects/project.service';
|
|
|
|
// Option 2: Package import (if separate packages)
|
|
import { ProjectService } from '@erp-core/modules/projects';
|
|
```
|
|
|
|
#### Share Types
|
|
|
|
```typescript
|
|
// shared-libs/core/types/index.ts
|
|
export interface BaseEntity {
|
|
id: string;
|
|
tenantId: string;
|
|
createdBy: string;
|
|
updatedBy?: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
deletedAt?: Date;
|
|
}
|
|
|
|
export interface Project extends BaseEntity {
|
|
name: string;
|
|
description?: string;
|
|
status: 'draft' | 'active' | 'completed';
|
|
}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Follow Naming Conventions
|
|
|
|
**Schemas:**
|
|
```
|
|
{vertical}_management
|
|
example: construction_management, clinic_management
|
|
```
|
|
|
|
**Tables:**
|
|
```
|
|
{vertical}_management.{entity_plural}
|
|
example: construction_management.phases
|
|
```
|
|
|
|
**Services:**
|
|
```
|
|
{Vertical}{Entity}Service
|
|
example: ConstructionProjectService
|
|
```
|
|
|
|
### 2. Always Use Multi-Tenancy
|
|
|
|
```sql
|
|
-- ✅ Good
|
|
CREATE TABLE my_vertical_management.entities (
|
|
id UUID PRIMARY KEY,
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
|
|
-- ...
|
|
);
|
|
|
|
-- ❌ Bad (missing tenant_id)
|
|
CREATE TABLE my_vertical_management.entities (
|
|
id UUID PRIMARY KEY,
|
|
-- missing tenant_id!
|
|
);
|
|
```
|
|
|
|
### 3. Extend, Don't Duplicate
|
|
|
|
```typescript
|
|
// ✅ Good - Extend core service
|
|
class VerticalProjectService extends ProjectService {
|
|
async create(...) {
|
|
const project = await super.create(...);
|
|
// Add vertical logic
|
|
return project;
|
|
}
|
|
}
|
|
|
|
// ❌ Bad - Duplicate core logic
|
|
class VerticalProjectService {
|
|
async create(...) {
|
|
// Copy-pasted from ProjectService
|
|
// Now you have duplicated code!
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4. Document Dependencies
|
|
|
|
```markdown
|
|
## Dependencias del Core
|
|
|
|
Este vertical extiende los siguientes módulos del core:
|
|
|
|
- **projects** - Gestión de proyectos (override create, findAll)
|
|
- **inventory** - Productos (agrega campos custom)
|
|
- **sales** - Ventas (validación adicional)
|
|
- **financial** - Contabilidad (reportes específicos)
|
|
```
|
|
|
|
### 5. Use Transactions
|
|
|
|
```typescript
|
|
async create(data: any, tenantId: string, userId: string) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
await client.query('BEGIN');
|
|
|
|
// 1. Core operation
|
|
const entity = await super.create(data, tenantId, userId);
|
|
|
|
// 2. Vertical operation
|
|
await this.createVerticalData(client, entity.id, data);
|
|
|
|
await client.query('COMMIT');
|
|
return entity;
|
|
|
|
} catch (error) {
|
|
await client.query('ROLLBACK');
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
```
|
|
|
|
## Testing Your Vertical
|
|
|
|
### Unit Tests
|
|
|
|
```typescript
|
|
// __tests__/vertical-project.service.test.ts
|
|
import { VerticalProjectService } from '../modules/projects/vertical-project.service';
|
|
|
|
describe('VerticalProjectService', () => {
|
|
let service: VerticalProjectService;
|
|
|
|
beforeEach(() => {
|
|
service = new VerticalProjectService();
|
|
});
|
|
|
|
it('should create project with vertical data', async () => {
|
|
const data = {
|
|
name: 'Test Project',
|
|
industryCode: 'IND-001',
|
|
complianceStatus: 'pending'
|
|
};
|
|
|
|
const project = await service.create(data, 'tenant-id', 'user-id');
|
|
|
|
expect(project).toBeDefined();
|
|
expect(project.name).toBe('Test Project');
|
|
// Verify vertical data was created
|
|
});
|
|
});
|
|
```
|
|
|
|
### Integration Tests
|
|
|
|
Test interaction with core modules and database.
|
|
|
|
## Deployment
|
|
|
|
### Database Migration
|
|
|
|
```bash
|
|
# Run core migrations first
|
|
cd apps/erp-core/database
|
|
psql -U erp_user -d erp_db -f ddl/schemas/auth/schema.sql
|
|
psql -U erp_user -d erp_db -f ddl/schemas/core/schema.sql
|
|
# ... all core schemas
|
|
|
|
# Then run vertical migrations
|
|
cd apps/verticales/my-vertical/database
|
|
psql -U erp_user -d erp_db -f ddl/schemas/my_vertical_management/schema.sql
|
|
```
|
|
|
|
### Environment Variables
|
|
|
|
```bash
|
|
# .env for vertical
|
|
CORE_API_URL=http://localhost:3000
|
|
VERTICAL_NAME=my-vertical
|
|
VERTICAL_DB_SCHEMA=my_vertical_management
|
|
```
|
|
|
|
## Examples from Existing Verticals
|
|
|
|
### Construcción Vertical
|
|
|
|
**Extends:**
|
|
- Projects → Construction Projects (adds phases, developments)
|
|
- Partners → Derechohabientes (adds INFONAVIT data)
|
|
- Financial → Presupuestos (construction budgets)
|
|
|
|
**New Modules:**
|
|
- Quality Management
|
|
- INFONAVIT Integration
|
|
- Construction Control
|
|
|
|
### Mecánicas Diesel Vertical
|
|
|
|
**Extends:**
|
|
- Inventory → Vehicle Parts (adds vehicle compatibility)
|
|
- Sales → Work Orders (service orders)
|
|
- Partners → Vehicle Owners
|
|
|
|
**New Modules:**
|
|
- Diagnostics
|
|
- Maintenance Schedules
|
|
- Vehicle Registry
|
|
|
|
## Checklist: Create New Vertical
|
|
|
|
- [ ] Create directory structure
|
|
- [ ] Write CONTEXTO-PROYECTO.md
|
|
- [ ] Design database schemas
|
|
- [ ] Create DDL files with RLS
|
|
- [ ] Identify core modules to extend
|
|
- [ ] Create service classes (extend BaseService)
|
|
- [ ] Implement API routes
|
|
- [ ] Create frontend modules
|
|
- [ ] Write documentation
|
|
- [ ] Write unit tests
|
|
- [ ] Integration testing
|
|
- [ ] Deploy database schemas
|
|
|
|
## References
|
|
|
|
- [Architecture Documentation](./ARCHITECTURE.md)
|
|
- [Multi-Tenancy Guide](./MULTI-TENANCY.md)
|
|
- [Core Modules Documentation](../apps/erp-core/docs/)
|
|
- [Odoo Development Patterns](../../../workspace/core/knowledge-base/patterns/PATRON-CORE-ODOO.md)
|