Files
planilla/worker/sync-empleados.js
google-labs-jules[bot] 242dc66983 Refactor: Centralize Prisma schema and restrict DB access
This commit refactors the project to use a shared Prisma schema and restricts direct database access to the API service.

Key changes:

- Created a new shared package `core/prisma` containing the Prisma schema, generated client, and types.
- Configured the monorepo to use NPM workspaces, including `core/prisma` and all services.
- Updated all services (`api`, `ui`, `mcp`, `agent`, and the background processing service) to depend on `@empresa/prisma-schema`.
- The API service now imports `PrismaClient` from `@empresa/prisma-schema/client`.
- Other services import only types from `@empresa/prisma-schema`.
- Removed redundant Prisma configurations from `api` and the background processing service.
- Updated the background processing service's `sync-empleados.js` to fetch data via an API call instead of direct database access.
- Updated TypeScript configurations (`tsconfig.base.json` and service-specific ones) to support the new structure and path aliases.
- Updated `README.md` to reflect the new architecture and added convenience scripts for Prisma operations.

This change promotes a single source of truth for data models, reduces code duplication, and improves the overall architecture by centralizing database operations within the API service.
2025-05-30 23:40:00 +00:00

164 lines
8.9 KiB
JavaScript

// This script is responsible for synchronizing employee data from the local
// Prisma database to an external database. It is designed to be run as a scheduled task.
// --- External Database Configuration (PLACEHOLDERS - User MUST Configure via environment variables) ---
// IMPORTANT: These variables define the connection to your external database.
// You MUST configure these, ideally through environment variables, for the script to work.
// The script provides a template for different database types, but you'll need to:
// 1. Install the appropriate database client library (e.g., `npm install pg` or `npm install mysql2`).
// 2. Implement the actual database connection and query logic in the designated section.
const EXTERNAL_DB_TYPE = process.env.EXTERNAL_DB_TYPE || 'your_db_type_here'; // e.g., 'postgres', 'mysql'. User must set this.
const EXTERNAL_DB_HOST = process.env.EXTERNAL_DB_HOST || 'YOUR_EXTERNAL_DB_HOST'; // User must set this.
const EXTERNAL_DB_PORT = process.env.EXTERNAL_DB_PORT || 5432; // Adjust default port if needed. User must set this.
const EXTERNAL_DB_USER = process.env.EXTERNAL_DB_USER || 'YOUR_EXTERNAL_DB_USER'; // User must set this.
const EXTERNAL_DB_PASSWORD = process.env.EXTERNAL_DB_PASSWORD || 'YOUR_EXTERNAL_DB_PASSWORD'; // User must set this.
const EXTERNAL_DB_NAME = process.env.EXTERNAL_DB_NAME || 'YOUR_EXTERNAL_DB_NAME'; // User must set this.
const EXTERNAL_DB_EMPLEADOS_TABLE = process.env.EXTERNAL_DB_EMPLEADOS_TABLE || 'empleados_externos'; // User must set this.
// --- End of External Database Configuration ---
// Import types from the shared Prisma package.
// We are not importing PrismaClient here as the worker will fetch data from the API.
import type { Cliente } from '@empresa/prisma-schema'; // Assuming Cliente is the relevant type for employees
// Define a type for the employee data we expect from the API.
// This might be identical to Cliente or a subset, depending on the API endpoint.
type EmployeeDataFromAPI = Pick<Cliente, 'id' | 'name' | 'cedula' | 'ubicacion' | 'telefono'>;
async function syncEmpleadosToExternalDB() {
console.log('[SyncEmpleados] Starting synchronization process...');
try {
// TODO: Fetch employee data from the API (e.g., GET /api/empleados)
// This is a placeholder for the API call logic.
console.log('[SyncEmpleados] Fetching employee data from API...');
const response = await fetch('http://localhost:4000/api/empleados'); // Replace with your actual API endpoint
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const localEmpleados: EmployeeDataFromAPI[] = await response.json();
if (!localEmpleados || !localEmpleados.length) {
console.log('[SyncEmpleados] No employees found from API. Nothing to sync.');
return;
}
console.log(`[SyncEmpleados] Found ${localEmpleados.length} employees from API to sync.`);
// --- External DB Connection Logic (User to implement based on EXTERNAL_DB_TYPE) ---
// User must implement the actual database connection logic here based on EXTERNAL_DB_TYPE
// and install the required database client library (e.g., 'pg' for PostgreSQL, 'mysql2' for MySQL).
// The following are conceptual examples.
// Example for PostgreSQL using 'pg' library (user would need to install it: npm install pg)
/*
if (EXTERNAL_DB_TYPE === 'postgres') {
// const { Client } = require('pg'); // User would uncomment and install
// const externalDbClient = new Client({
// host: EXTERNAL_DB_HOST,
// port: EXTERNAL_DB_PORT,
// user: EXTERNAL_DB_USER,
// password: EXTERNAL_DB_PASSWORD,
// database: EXTERNAL_DB_NAME,
// });
// await externalDbClient.connect();
// console.log('[SyncEmpleados] Connected to external PostgreSQL database.');
// ... (sync logic using externalDbClient) ...
// await externalDbClient.end();
// console.log('[SyncEmpleados] Disconnected from external PostgreSQL database.');
} else if (EXTERNAL_DB_TYPE === 'mysql') {
// const mysql = require('mysql2/promise'); // User would uncomment and install
// const connection = await mysql.createConnection({
// host: EXTERNAL_DB_HOST,
// user: EXTERNAL_DB_USER,
// password: EXTERNAL_DB_PASSWORD,
// database: EXTERNAL_DB_NAME,
// port: EXTERNAL_DB_PORT,
// });
// console.log('[SyncEmpleados] Connected to external MySQL database.');
// ... (sync logic using connection) ...
// await connection.end();
// console.log('[SyncEmpleados] Disconnected from external MySQL database.');
} else {
console.error(`[SyncEmpleados] Unsupported EXTERNAL_DB_TYPE: ${EXTERNAL_DB_TYPE}. User needs to implement connection logic.`);
// For now, we will just log the data that would be synced
}
*/
// --- End of External DB Connection Logic ---
console.log('[SyncEmpleados] --- Data to be Synced (Conceptual) ---');
for (const emp of localEmpleados) {
console.log(`[SyncEmpleados] Processing employee: ID=${emp.id}, Cedula=${emp.cedula}, Name=${emp.name}`);
// Conceptual Upsert Logic: The following section outlines where you would implement the upsert (update or insert) operation.
// You'll need to use your chosen external database client to first check if an employee
// with a matching unique identifier (e.g., emp.cedula) exists in the ${EXTERNAL_DB_EMPLEADOS_TABLE}.
// If it exists, execute an UPDATE statement. If not, execute an INSERT statement.
// Ensure you map fields from 'emp' (local employee) to the corresponding columns in your external table.
// Example of data to be inserted/updated:
const externalData = {
// Assuming external table has these columns. User must map accordingly.
// Ensure data types are compatible between local and external databases.
cedula: emp.cedula, // Primary key for matching in the external table (assumed)
nombre: emp.name,
telefono: emp.telefono,
ubicacion: emp.ubicacion,
// local_id: emp.id, // Optional: store local ID for reference
// ... map other fields ...
};
console.log(`[SyncEmpleados] Data for external table: ${JSON.stringify(externalData)}`);
}
console.log('[SyncEmpleados] --- End of Data to be Synced ---');
} catch (error) {
// Catch any errors that occur during the synchronization process.
console.error('[SyncEmpleados] Error during synchronization:', error);
} finally {
// No Prisma client to disconnect as we are using API.
}
console.log('[SyncEmpleados] Synchronization process finished.');
}
export { syncEmpleadosToExternalDB };
// --- Testing Considerations ---
// 1. **Configuration is Key:** This script requires the `EXTERNAL_DB_...` variables to be correctly
// configured with your actual external database credentials and details before any meaningful
// end-to-end testing can be performed.
//
// 2. **Manual Testing:**
// * Once configured, you can test the script by running it directly: `node worker/sync-empleados.js`
// * Observe the console logs for any errors or successful completion messages.
// * Verify that data fetched from the API appears correctly (or is logged as intended for now)
// if you have implemented the external DB sync part.
// * The cron job in `worker/cron-worker.js` is scheduled to run this script.
// You can monitor logs after this time to see its execution.
//
// 3. **Automated Testing (Recommendations for future development):**
// * **Unit Tests:**
// - Mock the API call (`fetch`) to return predefined employee data.
// - Mock the external database client (e.g., `pg`, `mysql2`) to simulate connection,
// query execution (select, insert, update), and disconnections. This allows testing
// the sync logic without actual API or database dependencies.
// * **Integration Tests:**
// - If possible, set up a dedicated test instance of your external database.
// - Write tests that populate the local Prisma test database with sample employee data,
// run the sync script, and then query the external test database to assert that
// the data was synchronized correctly. This provides more comprehensive testing
// but requires more setup.
//
// 4. **Logging:** Pay close attention to the console output. The script includes logging for various
// stages, which will be crucial for diagnosing issues during testing and operation.
// --- End of Testing Considerations ---
// Optional: For direct execution of this script, e.g., `node worker/sync-empleados.js`
if (require.main === module) {
console.log('[SyncEmpleados] Running synchronization script directly.');
syncEmpleadosToExternalDB()
.then(() => console.log('[SyncEmpleados] Direct execution completed.'))
.catch(err => console.error('[SyncEmpleados] Direct execution failed:', err));
}