Scheduler de pagos
El objetivo principal es gestionar comandos automáticos de programación de FDP (Future-Dated Payment) bajo demanda (crear, actualizar, eliminar). Esos comandos están relacionados con el propio scheduler, NO con pagos, y se basan en Domain Functions externas de MPS. Además, este concepto utiliza el Persistent Scheduler para almacenarlo en la base de datos.
El esquema general se representa aquí:
Función de programación (Schedule)
Esta función sirve para la creación del scheduler y, en MPS, la solicitud se ve de la siguiente manera:
| Nombre | Descripción | Datos de negocio | Respuestas |
|---|---|---|---|
|
Programar FDP con el tiempo de antelación adecuado para activar correctamente la transferencia de crédito en la fecha de ejecución. |
Hora programada |
Nombre: Schedule Response Descripción: Respuesta a la solicitud Datos de negocio: ninguno Códigos de respuesta: AcceptOrReject Códigos de motivo: <no reasonCodeSet> Completa: true |
Dentro del flujo de MPS, esta es la parte donde sucede:
Ahora, veamos el código. La primera parte es un action port de MPS generado, que debe implementarse:
public interface PaymentSchedulerActionPort {
CompletionStage<Void> execute(ScheduleRequestAction scheduleRequest);
}
La implementación es una parte clave aquí:
@Slf4j
@AllArgsConstructor
public class SamplePaymentSchedulerAdapter implements PaymentSchedulerActionPort {
SchedulingModuleInterface schedulingModuleInterface;
@Override
public CompletionStage<Void> execute(ScheduleRequestAction scheduleRequest) {
var cron = CronExpressionHelper.calendarToCron(scheduleRequest.getScheduledTime());
var jobSpecification = JobSpecificationDto.builder()
.jobSpecificationKey(new JobSpecificationKeyDto("DEBTOR_CT_JOB_ID"))
.schedulingSpecification(cron)
.jobRequestor(scheduleRequest.getId())
.triggerCommand(new PaymentSchedulerCommand(scheduleRequest.getId()))
.triggerIdentifier("triggerIdentifier")
.build();
return schedulingModuleInterface.scheduleJob(jobSpecification);
}
}
Puedes notar que hemos instanciado nuestro comando dentro del parámetro triggerCommand. Ese comando se presenta a continuación:
@Data
@AllArgsConstructor
public class PaymentSchedulerCommand implements SchedulingCommand {
private String id;
}
Parece bastante básico; como podemos ver, solo contiene un parámetro ID. Implementa la interfaz SchedulingCommand de la biblioteca shared-scheduling. Hablando de esa biblioteca, hay otra interfaz que debe usarse para que funcione:
public interface SchedulingHelper {
CompletionStage<Void> execute(String id, final SchedulingCommand request);
boolean supports(SchedulingCommand request);
}
Nuestra implementación está aquí:
@Slf4j
@RequiredArgsConstructor
public class PaymentSchedulerHelper implements SchedulingHelper {
@Override
public CompletionStage<Void> execute(String s, SchedulingCommand schedulingCommand) {
PaymentSchedulerCommand paymentSchedulerCommand = (PaymentSchedulerCommand) schedulingCommand;
return CredittransferDomain.paymentScheduler()
.handle(new ScheduleResponseInput.Builder(paymentSchedulerCommand.getId(), AcceptOrRejectCodes.Accepted).build())
.thenAccept(it -> log.debug("Scheduled"));
}
@Override
public boolean supports(SchedulingCommand schedulingCommand) {
return schedulingCommand instanceof PaymentSchedulerCommand;
}
}
Por último, pero no menos importante, debemos definir un bean que devuelva una instancia de nuestro SchedulingHelper implementado:
@Bean
public PaymentSchedulerHelper paymentSchedulerHelper() {
return new PaymentSchedulerHelper();
}