class ApplicationFundingServiceImpl extends BaseTransactionalService implements ApplicationFundingService {

    @Override
    @Transactional
    public ServiceResult<Void> notifyApplicantsOfFundingDecisions(FundingNotificationResource fundingNotificationResource) {

        List<Application> applications = getFundingApplications(fundingNotificationResource.getFundingDecisions());
        setApplicationState(fundingNotificationResource.getFundingDecisions(), applications);

        List<ServiceResult<Pair<Long, NotificationTarget>>> fundingNotificationTargets = getApplicantNotificationTargets(fundingNotificationResource.calculateApplicationIds());
        ServiceResult<List<Pair<Long, NotificationTarget>>> aggregatedFundingTargets = aggregate(fundingNotificationTargets);

        return aggregatedFundingTargets.handleSuccessOrFailure(
                failure -> serviceFailure(NOTIFICATIONS_UNABLE_TO_DETERMINE_NOTIFICATION_TARGETS),
                success -> {

                    Notification fundingNotification = createFundingDecisionNotification(applications, fundingNotificationResource, aggregatedFundingTargets.getSuccess());
                    ServiceResult<Void> fundedEmailSendResult = notificationService.sendNotificationWithFlush(fundingNotification, EMAIL);

                    ServiceResult<Void> setEmailDateTimeResult = fundedEmailSendResult.andOnSuccess(() ->
                            aggregate(simpleMap(
                                    applications, application ->
                                            applicationService.setApplicationFundingEmailDateTime(application.getId(), ZonedDateTime.now()))))
                            .andOnSuccessReturnVoid();
                    return setEmailDateTimeResult.andOnSuccess(() -> {
                        if (!applications.isEmpty()) {
                            return competitionService.manageInformState(
                                    applications.get(0)
                                            .getCompetition()
                                            .getId());
                        }
                        return serviceSuccess();
                    });
                });
    }

}