Overview
Satélite API follows a clean layered architecture pattern that separates concerns and promotes maintainability. The architecture consists of four primary layers:
Architectural Layers
GraphQL Schema Layer
Location : Schema/Query/ and Schema/Mutation/This layer handles GraphQL requests and responses. It defines the API contract and delegates business logic to services. public class Query
{
private readonly UsuarioRepository _userRepository ;
public Query ( UsuarioRepository userRepository )
{
_userRepository = userRepository ;
}
[ Authorize ]
public async Task < IEnumerable < UsuarioDTO >> GetUsuarios ()
{
return await _userRepository . GetAll ();
}
}
Service Layer
Location : Services/Services contain business logic and orchestrate operations across multiple repositories. They handle complex workflows and business rules. Example services:
PlanComercialService
AuthenticationService
BitacoraCumplimientoService
DonacionService
Repository Layer
Location : Repository/ and inline with ServicesRepositories provide data access abstraction and encapsulate database operations. public class UsuarioRepository
{
private readonly IDbContextFactory < SateliteDBContext > _contextFactory ;
public async Task < IEnumerable < UsuarioDTO >> GetAll ()
{
await using var context = await _contextFactory . CreateDbContextAsync ();
return await context . Usuarios . ToListAsync ();
}
}
Data Layer
Location : Services/*DBContext.csEntity Framework Core DbContexts manage database connections and entity mappings. See Database Contexts for details.
Dependency Injection
The application uses ASP.NET Core’s built-in dependency injection. All services and repositories are registered in Program.cs.
Repository Registration
// Repository registrations
builder . Services . AddScoped < UsuarioRepository >();
builder . Services . AddScoped < RolesRepository >();
builder . Services . AddScoped < PermisosRepository >();
builder . Services . AddScoped < ProductoRepository >();
builder . Services . AddScoped < ClientesRepository >();
builder . Services . AddScoped < PlanComercialRepository >();
builder . Services . AddScoped < BitCuResponsabilidadRepository >();
builder . Services . AddScoped < DonacionesRepository >();
// BitacoraCumplimiento Repositories
builder . Services . AddScoped < BitCuResponsabilidadRepository >();
builder . Services . AddScoped < BitCuProcesoRepository >();
builder . Services . AddScoped < BitCuLocalidadRepository >();
builder . Services . AddScoped < BitCuAuditoriaRepository >();
// Catalog repositories
builder . Services . AddScoped < SateliteAprobadoresRepository >();
builder . Services . AddScoped < CatalogoUnidadManejoRepository >();
builder . Services . AddScoped < CatalogoMaterialesHomologadosRepository >();
Service Registration
// Registro Consumo Services
builder . Services . AddScoped < TipoConsumoService >();
builder . Services . AddScoped < CategoriaConsumoService >();
builder . Services . AddScoped < UnidadConsumoService >();
builder . Services . AddScoped < RegistroConsumoService >();
// Donaciones Services
builder . Services . AddScoped < CatInstitucionService >();
builder . Services . AddScoped < CatContactoService >();
builder . Services . AddScoped < CatTransporteService >();
builder . Services . AddScoped < DonacionService >();
// Memoria de Sostenibilidad Services
builder . Services . AddScoped < CatMemoriaSostenibilidadProcesosService >();
builder . Services . AddScoped < MemoriaSostenibilidadService >();
// Databricks Services
builder . Services . AddScoped < ScadaHomologacionService >();
builder . Services . AddScoped < RutaDistanciaService >();
Extension Methods for Service Registration
The application uses extension methods to organize service registration:
builder . Services . AddPlanComercialServices ();
builder . Services . AddNotaCreditoServices ();
builder . Services . AddCatalogosServices ();
builder . Services . AddServiceCollection ( builder . Configuration );
builder . Services . AddSapServices ( builder . Configuration );
builder . Services . AddUsuarioServiceCollection ();
builder . Services . AddEquifaxServices ( builder . Configuration );
builder . Services . AddCatalogoMaestroServices ();
builder . Services . AddAprobacionServiceCollection ();
builder . Services . AddNotaCreditoJobs ();
Extension methods keep the Program.cs clean and organize related service registrations into logical groups.
Scheduled Jobs with Quartz
Satélite API uses Quartz.NET for scheduled background jobs. Jobs are configured in Program.cs:193-265.
Job Configuration
builder . Services . AddQuartz ( q =>
{
q . UseMicrosoftDependencyInjectionJobFactory ();
// Anticipo Job - Daily at 9:00 AM
var anticipoKey = new JobKey ( "AnticipoJob" );
q . AddJob < TaskAnticipo >( opts => opts . WithIdentity ( anticipoKey ));
q . AddTrigger ( opts => opts
. ForJob ( anticipoKey )
. WithIdentity ( "AnticipoJob-trigger" )
. WithCronSchedule ( "0 0 9 * * ?" ));
// Reembolso Job - Daily at 9:00 AM
var reembolsoKey = new JobKey ( "ReembolsoJob" );
q . AddJob < TaskReembolso >( opts => opts . WithIdentity ( reembolsoKey ));
q . AddTrigger ( opts => opts
. ForJob ( reembolsoKey )
. WithIdentity ( "ReembolsoJob-trigger" )
. WithCronSchedule ( "0 0 9 * * ?" ));
// Bitacora Caducidad Job - Daily at 8:00 AM
var bitacoraCaducidadKey = new JobKey ( "BitacoraCaducidadJob" );
q . AddJob < TaskBitacoraCaducidad >( opts =>
opts . WithIdentity ( bitacoraCaducidadKey ));
q . AddTrigger ( opts => opts
. ForJob ( bitacoraCaducidadKey )
. WithIdentity ( "BitacoraCaducidadJob-trigger" )
. WithCronSchedule ( "0 0 8 * * ?" ));
// Activos Job - Daily at 9:00 AM
var activosKey = new JobKey ( "ActivosJob" );
q . AddJob < TaskActivos >( opts => opts . WithIdentity ( activosKey ));
q . AddTrigger ( opts => opts
. ForJob ( activosKey )
. WithIdentity ( "ActivosJob-trigger" )
. WithCronSchedule ( "0 0 9 * * ?" ));
// Procurement Job - Daily at 9:00 AM
var procurmentKey = new JobKey ( "ProcurmentJob" );
q . AddJob < TaskProcurment >( opts => opts . WithIdentity ( procurmentKey ));
q . AddTrigger ( opts => opts
. ForJob ( procurmentKey )
. WithIdentity ( "ProcurmentJob-trigger" )
. WithCronSchedule ( "0 0 9 * * ?" ));
// Tracking Job - Daily at 9:00 AM
var trackingKey = new JobKey ( "TrackingJob" );
q . AddJob < TaskProcurmentSeguimiento >( opts =>
opts . WithIdentity ( trackingKey ));
q . AddTrigger ( opts => opts
. ForJob ( trackingKey )
. WithIdentity ( "TrackingJob-trigger" )
. WithCronSchedule ( "0 0 9 * * ?" ));
// Procurement Seguimiento Sin Correo - Every hour
q . AddJob < TaskProcurmentSeguimientoSinCorreo >( opts =>
opts . WithIdentity ( "TaskProcurmentSeguimientoSinCorreo" ));
q . AddTrigger ( opts => opts
. ForJob ( "TaskProcurmentSeguimientoSinCorreo" )
. WithIdentity ( "TaskProcurmentSeguimientoSinCorreo-trigger" )
. WithCronSchedule ( "0 0 * * * ?" ));
// Gestor Job - Daily at 6:00 AM
var gestorKey = new JobKey ( "GestorJob" );
q . AddJob < TaskGestor >( opts => opts . WithIdentity ( gestorKey ));
q . AddTrigger ( opts => opts
. ForJob ( gestorKey )
. WithIdentity ( "GestorJob-trigger" )
. WithCronSchedule ( "0 0 6 * * ?" ));
});
builder . Services . AddQuartzHostedService ( q =>
q . WaitForJobsToComplete = true );
Scheduled Jobs Overview
TaskAnticipo Schedule : Daily at 9:00 AMProcesses advance payment requests
TaskReembolso Schedule : Daily at 9:00 AMProcesses reimbursement requests
TaskBitacoraCaducidad Schedule : Daily at 8:00 AMChecks and updates expiration dates
TaskActivos Schedule : Daily at 9:00 AMSynchronizes fixed assets data
TaskProcurment Schedule : Daily at 9:00 AMProcesses procurement requests
TaskProcurmentSeguimiento Schedule : Daily at 9:00 AMTracks procurement with email notifications
TaskProcurmentSeguimientoSinCorreo Schedule : Every hourTracks procurement without emails
TaskGestor Schedule : Daily at 6:00 AMDocument management tasks
All scheduled times use server timezone (UTC-5). Cron expressions follow standard Quartz syntax:
0 0 9 * * ? = Daily at 9:00 AM
0 0 * * * ? = Every hour
Data Flow Example
Here’s how a typical request flows through the architecture:
Configuration Management
Configuration is managed through appsettings.json and environment variables:
// Configure external API settings
builder . Services . Configure < ApiCofaseSettings >(
builder . Configuration . GetSection ( "ApiCofase" ));
builder . Services . Configure < ApiEquifaxSettings >(
builder . Configuration . GetSection ( "ApiEquifax" ));
builder . Services . Configure < DatabricksConfig >(
builder . Configuration . GetSection ( "DatabricksConfig" ));
Next Steps
Database Contexts Explore the multiple database contexts
Error Handling Learn error handling patterns