FINERACT-1694-Event-Configuration-Database-Storage

This commit is contained in:
Ruchi Dhamankar
2022-10-17 15:15:52 +02:00
committed by Arnold Gálovics
parent 55b1baeacb
commit c9d5742836
25 changed files with 1146 additions and 8 deletions
@@ -24,6 +24,7 @@ import org.apache.fineract.cob.COBBusinessStepService;
import org.apache.fineract.cob.COBBusinessStepServiceImpl;
import org.apache.fineract.cob.domain.BatchBusinessStepRepository;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -38,10 +39,15 @@ public class TestDefaultConfiguration {
return mock(BatchBusinessStepRepository.class);
}
@Bean
public BusinessEventNotifierService businessEventNotifierService() {
return mock(BusinessEventNotifierService.class);
}
@Bean
public COBBusinessStepService cobBusinessStepService(BatchBusinessStepRepository batchBusinessStepRepository,
ApplicationContext context, ListableBeanFactory beanFactory) {
return new COBBusinessStepServiceImpl(batchBusinessStepRepository, context, beanFactory);
ApplicationContext context, ListableBeanFactory beanFactory, BusinessEventNotifierService businessEventNotifierService) {
return new COBBusinessStepServiceImpl(batchBusinessStepRepository, context, beanFactory, businessEventNotifierService);
}
@Bean
@@ -30,6 +30,7 @@ import org.apache.fineract.cob.exceptions.BusinessStepException;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.ApplicationContext;
@@ -43,12 +44,14 @@ public class COBBusinessStepServiceImpl implements COBBusinessStepService {
private final BatchBusinessStepRepository batchBusinessStepRepository;
private final ApplicationContext applicationContext;
private final ListableBeanFactory beanFactory;
private final BusinessEventNotifierService businessEventNotifierService;
@Override
public <T extends COBBusinessStep<S>, S extends AbstractPersistableCustom> S run(TreeMap<Long, String> executionMap, S item) {
if (executionMap == null || executionMap.isEmpty()) {
throw new BusinessStepException("Execution map is empty! COB Business step execution skipped!");
}
businessEventNotifierService.startExternalEventRecording();
for (String businessStep : executionMap.values()) {
try {
COBBusinessStep<S> businessStepBean = (COBBusinessStep<S>) applicationContext.getBean(businessStep);
@@ -60,6 +63,7 @@ public class COBBusinessStepServiceImpl implements COBBusinessStepService {
ThreadLocalContextUtil.setActionContext(ActionContext.COB);
}
}
businessEventNotifierService.stopExternalEventRecording();
return item;
}
@@ -28,6 +28,7 @@ import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository;
import org.apache.fineract.infrastructure.event.external.service.ExternalEventService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@@ -45,6 +46,7 @@ public class BusinessEventNotifierServiceImpl implements BusinessEventNotifierSe
private final ThreadLocal<List<BusinessEvent<?>>> recordedEvents = ThreadLocal.withInitial(ArrayList::new);
private final ExternalEventService externalEventService;
private final ExternalEventConfigurationRepository eventConfigurationRepository;
private final FineractProperties fineractProperties;
@Override
@@ -88,10 +90,12 @@ public class BusinessEventNotifierServiceImpl implements BusinessEventNotifierSe
}
if (isExternalEventPostingEnabled()) {
// we only want to create external events for operations that were successful, hence the post listener
if (isExternalEventRecordingEnabled()) {
recordedEvents.get().add(businessEvent);
} else {
externalEventService.postEvent(businessEvent);
if (isExternalEventConfiguredForPosting(businessEvent.getType())) {
if (isExternalEventRecordingEnabled()) {
recordedEvents.get().add(businessEvent);
} else {
externalEventService.postEvent(businessEvent);
}
}
}
}
@@ -114,6 +118,10 @@ public class BusinessEventNotifierServiceImpl implements BusinessEventNotifierSe
return fineractProperties.getEvents().getExternal().isEnabled();
}
private boolean isExternalEventConfiguredForPosting(String eventType) {
return eventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(eventType).isEnabled();
}
private void throwExceptionIfBulkEvent(BusinessEvent<?> businessEvent) {
if (businessEvent instanceof BulkBusinessEvent) {
throw new IllegalArgumentException("BulkBusinessEvent cannot be raised directly");
@@ -0,0 +1,30 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.command;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class ExternalEventConfigurationCommand {
private final Map<String, Boolean> externalEventConfigurations;
}
@@ -0,0 +1,30 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.data;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class ExternalEventConfigurationData {
private List<ExternalEventConfigurationItemData> externalEventConfiguration;
}
@@ -0,0 +1,32 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.data;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExternalEventConfigurationItemData {
private String type;
private boolean enabled;
}
@@ -0,0 +1,26 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.exception;
public class ExternalEventConfigurationNotFoundException extends RuntimeException {
public ExternalEventConfigurationNotFoundException(final String externalEventType) {
super("Configuration not found for external event " + externalEventType);
}
}
@@ -0,0 +1,26 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.repository;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
public interface CustomExternalEventConfigurationRepository {
ExternalEventConfiguration findExternalEventConfigurationByTypeWithNotFoundDetection(String externalEventType);
}
@@ -0,0 +1,43 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.event.external.exception.ExternalEventConfigurationNotFoundException;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class CustomExternalEventConfigurationRepositoryImpl implements CustomExternalEventConfigurationRepository {
@PersistenceContext
private final EntityManager entityManager;
@Override
public ExternalEventConfiguration findExternalEventConfigurationByTypeWithNotFoundDetection(String externalEventType) {
final ExternalEventConfiguration configuration = entityManager.find(ExternalEventConfiguration.class, externalEventType);
if (configuration == null) {
throw new ExternalEventConfigurationNotFoundException(externalEventType);
}
return configuration;
}
}
@@ -0,0 +1,25 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.repository;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ExternalEventConfigurationRepository
extends JpaRepository<ExternalEventConfiguration, String>, CustomExternalEventConfigurationRepository {}
@@ -0,0 +1,46 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.repository.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "m_external_event_configuration")
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ExternalEventConfiguration {
@Id
@Column(name = "type", nullable = false)
private String type;
@Column(name = "enabled", nullable = false)
private boolean enabled = false;
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
@@ -0,0 +1,55 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.serialization;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
import org.apache.fineract.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.event.external.command.ExternalEventConfigurationCommand;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class ExternalEventConfigurationCommandFromApiJsonDeserializer
extends AbstractFromApiJsonDeserializer<ExternalEventConfigurationCommand> {
private static final String EXTERNAL_EVENT_CONFIGURATIONS = "externalEventConfigurations";
private final Set<String> supportedParameters = new HashSet<>(Arrays.asList(EXTERNAL_EVENT_CONFIGURATIONS));
private final FromJsonHelper fromApiJsonHelper;
@Override
public ExternalEventConfigurationCommand commandFromApiJson(String json) {
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
return fromApiJsonHelper.fromJson(json, ExternalEventConfigurationCommand.class);
}
}
@@ -0,0 +1,26 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import org.apache.fineract.infrastructure.event.external.data.ExternalEventConfigurationData;
public interface ExternalEventConfigurationReadPlatformService {
ExternalEventConfigurationData findAllExternalEventConfigurations();
}
@@ -0,0 +1,43 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.event.external.data.ExternalEventConfigurationData;
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class ExternalEventConfigurationReadPlatformServiceImpl implements ExternalEventConfigurationReadPlatformService {
private final ExternalEventConfigurationRepository repository;
private final ExternalEventsConfigurationMapper mapper;
@Override
public ExternalEventConfigurationData findAllExternalEventConfigurations() {
ExternalEventConfigurationData configurationData = new ExternalEventConfigurationData();
List<ExternalEventConfiguration> eventConfigurations = repository.findAll();
configurationData.setExternalEventConfiguration(mapper.map(eventConfigurations));
return configurationData;
}
}
@@ -0,0 +1,27 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
public interface ExternalEventConfigurationWritePlatformService {
CommandProcessingResult updateConfigurations(JsonCommand command);
}
@@ -0,0 +1,69 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.event.external.command.ExternalEventConfigurationCommand;
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.apache.fineract.infrastructure.event.external.serialization.ExternalEventConfigurationCommandFromApiJsonDeserializer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@AllArgsConstructor
public class ExternalEventConfigurationWritePlatformServiceImpl implements ExternalEventConfigurationWritePlatformService {
private final ExternalEventConfigurationRepository repository;
private final ExternalEventConfigurationCommandFromApiJsonDeserializer fromApiJsonDeserializer;
@Transactional
@Override
public CommandProcessingResult updateConfigurations(final JsonCommand command) {
final ExternalEventConfigurationCommand configurationCommand = fromApiJsonDeserializer.commandFromApiJson(command.json());
final Map<String, Boolean> commandConfigurations = configurationCommand.getExternalEventConfigurations();
final Map<String, Object> changes = new HashMap<>();
final Map<String, Boolean> changedConfigurations = new HashMap<>();
final List<ExternalEventConfiguration> modifiedConfigurations = new ArrayList<>();
for (final String eventType : commandConfigurations.keySet()) {
final ExternalEventConfiguration configuration = repository
.findExternalEventConfigurationByTypeWithNotFoundDetection(eventType);
final boolean canEnable = commandConfigurations.get(eventType).booleanValue();
configuration.setEnabled(canEnable);
changedConfigurations.put(eventType, canEnable);
modifiedConfigurations.add(configuration);
}
if (!modifiedConfigurations.isEmpty()) {
this.repository.saveAll(modifiedConfigurations);
}
if (!changedConfigurations.isEmpty()) {
changes.put("externalEventConfigurations", changedConfigurations);
}
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).with(changes).build();
}
}
@@ -0,0 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import java.util.List;
import org.apache.fineract.infrastructure.event.external.data.ExternalEventConfigurationItemData;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.apache.fineract.infrastructure.event.external.service.support.ExternalEventMapperConfig;
import org.mapstruct.Mapper;
@Mapper(config = ExternalEventMapperConfig.class)
public interface ExternalEventsConfigurationMapper {
List<ExternalEventConfigurationItemData> map(List<ExternalEventConfiguration> source);
}
@@ -0,0 +1,27 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service.support;
import org.mapstruct.Builder;
import org.mapstruct.MapperConfig;
import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy;
@MapperConfig(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.ERROR, builder = @Builder(disableBuilder = true))
public class ExternalEventMapperConfig {}
@@ -75,4 +75,5 @@
<include file="parts/0053_add_external_events_purge_job.xml" relativeToChangelogFile="true"/>
<include file="parts/0054_additional_fields_loan_repayment_schedule.xml" relativeToChangelogFile="true"/>
<include file="parts/0055_add_submitted_on_date_to_loan_charge.xml" relativeToChangelogFile="true"/>
<include file="parts/0056_add_external_event_default_configuration.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,324 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet author="fineract" id="1">
<insert tableName="m_external_event_configuration">
<column name="type" value="ClientActivateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="ClientCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="ClientRejectBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="FixedDepositAccountCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="RecurringDepositAccountCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="CentersCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="GroupsCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanAddChargeBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanDeleteChargeBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanUpdateChargeBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanWaiveChargeBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanWaiveChargeUndoBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanProductCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanChargePaymentPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanChargePaymentPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanChargeRefundBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanCreditBalanceRefundPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanCreditBalanceRefundPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanDisbursalTransactionBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanForeClosurePostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanForeClosurePreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanRefundPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanRefundPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionGoodwillCreditPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionGoodwillCreditPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionMakeRepaymentPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionMakeRepaymentPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionMerchantIssuedRefundPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionMerchantIssuedRefundPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionPayoutRefundPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionPayoutRefundPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionRecoveryPaymentPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionRecoveryPaymentPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanUndoWrittenOffBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanWaiveInterestBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanWrittenOffPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanWrittenOffPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanAcceptTransferBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanAdjustTransactionBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanApplyOverdueChargeBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanApprovedBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanBalanceChangedBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanChargebackTransactionBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanCloseAsRescheduleBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanCloseBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanCreatedBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanDisbursalBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanInitiateTransferBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanInterestRecalculationBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanReassignOfficerBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanRejectedBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanRejectTransferBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanRemoveOfficerBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanRescheduledDueCalendarChangeBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanRescheduledDueHolidayBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanScheduleVariationsAddedBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanScheduleVariationsDeletedBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanStatusChangedBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanUndoApprovalBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanUndoDisbursalBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanUndoLastDisbursalBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanUpdateDisbursementDataBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanWithdrawTransferBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsDepositBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsWithdrawalBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsActivateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsApproveBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsCloseBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsPostInterestBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="SavingsRejectBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="ShareAccountApproveBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="ShareAccountCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="ShareProductDividentsCreateBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -37,6 +37,7 @@ import org.apache.fineract.cob.loan.LoanCOBBusinessStep;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.mix.data.MixTaxonomyData;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.ListableBeanFactory;
@@ -47,8 +48,9 @@ public class COBBusinessStepServiceStepDefinitions implements En {
private ApplicationContext applicationContext = mock(ApplicationContext.class);
private ListableBeanFactory beanFactory = mock(ListableBeanFactory.class);
private BatchBusinessStepRepository batchBusinessStepRepository = mock(BatchBusinessStepRepository.class);
private BusinessEventNotifierService businessEventNotifierService = mock(BusinessEventNotifierService.class);
private final COBBusinessStepService businessStepService = new COBBusinessStepServiceImpl(batchBusinessStepRepository,
applicationContext, beanFactory);
applicationContext, beanFactory, businessEventNotifierService);
private COBBusinessStep cobBusinessStep = mock(COBBusinessStep.class);
private COBBusinessStep notRegistereCobBusinessStep = mock(COBBusinessStep.class);
private TreeMap<Long, String> executionMap;
@@ -23,17 +23,21 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.apache.fineract.infrastructure.event.external.service.ExternalEventService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@@ -45,6 +49,10 @@ class BusinessEventNotifierServiceImplTest {
@Mock
private ExternalEventService externalEventService;
@Mock
private ExternalEventConfigurationRepository externalEventConfigurationRepository;
@Mock
private FineractProperties fineractProperties;
@@ -74,6 +82,9 @@ class BusinessEventNotifierServiceImplTest {
MockBusinessEvent event = new MockBusinessEvent();
BusinessEventListener<MockBusinessEvent> postListener = mockListener();
underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener);
when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any()))
.thenReturn(new ExternalEventConfiguration("aType", true));
// when
underTest.notifyPostBusinessEvent(event);
// then
@@ -85,7 +96,8 @@ class BusinessEventNotifierServiceImplTest {
public void testNotifyPostBusinessEventShouldNotifyPostListenersAndPostAnBulkExternalEventWhenRecordingEnabled() {
// given
configureExternalEventsProperties(true);
when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any()))
.thenReturn(new ExternalEventConfiguration("aType", true));
MockBusinessEvent event = new MockBusinessEvent();
BusinessEventListener<MockBusinessEvent> postListener = mockListener();
underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener);
@@ -133,6 +145,22 @@ class BusinessEventNotifierServiceImplTest {
verifyNoInteractions(externalEventService);
}
@Test
public void testNotifyPostBusinessEventShouldNotifyPostListenersAndShouldNotPostAnExternalEventIfNotConfiguredForPosting() {
// given
configureExternalEventsProperties(true);
when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any()))
.thenReturn(new ExternalEventConfiguration("aType", false));
MockBusinessEvent event = new MockBusinessEvent();
BusinessEventListener<MockBusinessEvent> postListener = mockListener();
underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener);
// when
underTest.notifyPostBusinessEvent(event);
// then
verify(postListener).onBusinessEvent(event);
verifyNoInteractions(externalEventService);
}
private void configureExternalEventsProperties(boolean isExternalEventsEnabled) {
FineractProperties.FineractEventsProperties eventsProperties = new FineractProperties.FineractEventsProperties();
FineractProperties.FineractExternalEventsProperties externalProperties = new FineractProperties.FineractExternalEventsProperties();
@@ -0,0 +1,71 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;
import javax.persistence.EntityManager;
import org.apache.fineract.infrastructure.event.external.exception.ExternalEventConfigurationNotFoundException;
import org.apache.fineract.infrastructure.event.external.repository.CustomExternalEventConfigurationRepositoryImpl;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class CustomExternalEventConfigurationRepositoryImplTest {
@Mock
private EntityManager entityManager;
private CustomExternalEventConfigurationRepositoryImpl underTest;
@BeforeEach
public void setUp() {
underTest = new CustomExternalEventConfigurationRepositoryImpl(entityManager);
}
@Test
public void givenConfigurationExistsThenReturnConfiguration() {
// given
ExternalEventConfiguration configuration = new ExternalEventConfiguration("aType", true);
when(entityManager.find(Mockito.any(), Mockito.anyString())).thenReturn(configuration);
// when
ExternalEventConfiguration actualConfiguration = underTest.findExternalEventConfigurationByTypeWithNotFoundDetection("aType");
// then
assertThat(actualConfiguration.getType(), equalTo(configuration.getType()));
assertThat(actualConfiguration.isEnabled(), equalTo(configuration.isEnabled()));
}
@Test
public void givenConfigurationDoesNotExistsThenThrowExternalEventConfigurationNotFoundException() {
// given
when(entityManager.find(Mockito.any(), Mockito.anyString())).thenReturn(null);
// then
assertThrows(ExternalEventConfigurationNotFoundException.class,
() -> underTest.findExternalEventConfigurationByTypeWithNotFoundDetection("aType"));
}
}
@@ -0,0 +1,87 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.any;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.fineract.infrastructure.event.external.data.ExternalEventConfigurationData;
import org.apache.fineract.infrastructure.event.external.data.ExternalEventConfigurationItemData;
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class ExternalEventConfigurationReadPlatformServiceTest {
@Mock
private ExternalEventConfigurationRepository repository;
@Mock
private ExternalEventsConfigurationMapper mapper;
private ExternalEventConfigurationReadPlatformServiceImpl underTest;
@BeforeEach
public void setUp() {
underTest = new ExternalEventConfigurationReadPlatformServiceImpl(repository, mapper);
}
@Test
public void givenConfigurationsThenReturnConfigurationData() {
// given
List<ExternalEventConfiguration> configurations = Arrays.asList(new ExternalEventConfiguration("aType", true),
new ExternalEventConfiguration("bType", false));
List<ExternalEventConfigurationItemData> configurationDataItems = Arrays
.asList(new ExternalEventConfigurationItemData("aType", true), new ExternalEventConfigurationItemData("bType", false));
when(repository.findAll()).thenReturn(configurations);
when(mapper.map(Mockito.anyList())).thenReturn(configurationDataItems);
// when
ExternalEventConfigurationData actualConfiguration = underTest.findAllExternalEventConfigurations();
// then
assertThat(actualConfiguration.getExternalEventConfiguration(), hasSize(2));
assertThat(actualConfiguration.getExternalEventConfiguration().get(0), any(ExternalEventConfigurationItemData.class));
assertThat(actualConfiguration.getExternalEventConfiguration().get(0).getType(), equalTo("aType"));
assertThat(actualConfiguration.getExternalEventConfiguration().get(0).isEnabled(), equalTo(true));
}
@Test
public void givenNoConfigurationsThenReturnEmptyConfigurationData() {
// given
List<ExternalEventConfiguration> emptyConfiguration = new ArrayList<>();
when(repository.findAll()).thenReturn(emptyConfiguration);
// when
ExternalEventConfigurationData actualConfiguration = underTest.findAllExternalEventConfigurations();
// then
assertThat(actualConfiguration.getExternalEventConfiguration(), hasSize(0));
}
}
@@ -0,0 +1,71 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.event.external.service;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.event.external.command.ExternalEventConfigurationCommand;
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository;
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration;
import org.apache.fineract.infrastructure.event.external.serialization.ExternalEventConfigurationCommandFromApiJsonDeserializer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class ExternalEventConfigurationWritePlatformServiceTest {
@Mock
private ExternalEventConfigurationRepository repository;
@Mock
private ExternalEventConfigurationCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private ExternalEventConfigurationWritePlatformServiceImpl underTest;
@BeforeEach
public void setUp() {
underTest = new ExternalEventConfigurationWritePlatformServiceImpl(repository, fromApiJsonDeserializer);
}
@Test
public void givenExternalEventConfigurationsWithChangeWhenUpdateConfigurationThenConfigurationIsUpdated() {
// given
final JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
Map<String, Boolean> mapOfConfigurationsForUpdate = new HashMap<>();
mapOfConfigurationsForUpdate.put("aType", Boolean.TRUE);
ExternalEventConfigurationCommand command = new ExternalEventConfigurationCommand(mapOfConfigurationsForUpdate);
when(jsonCommand.json()).thenReturn("");
when(fromApiJsonDeserializer.commandFromApiJson(Mockito.anyString())).thenReturn(command);
when(repository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.anyString()))
.thenReturn(new ExternalEventConfiguration("aType", false));
// when
underTest.updateConfigurations(jsonCommand);
// then
verify(repository, times(1)).saveAll(Mockito.anyCollection());
}
}