FINERACT-2169: SMS API refactoring and clean up;

This commit is contained in:
viktorpavlenko
2025-02-26 12:55:02 +01:00
committed by Adam Saghy
parent dcde04d506
commit 191a35a940
38 changed files with 770 additions and 887 deletions
@@ -28,6 +28,9 @@ import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
*/
public class DateParam {
public static final String FROM_DATE_PARAM = "fromDate";
public static final String TO_DATE_PARAM = "toDate";
private final String dateAsString;
public DateParam(final String dateStr) {
@@ -48,18 +48,17 @@ public class SmsConfigUtils {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add(SmsCampaignConstants.FINERACT_PLATFORM_TENANT_ID, tenant.getTenantIdentifier());
headers.add(SmsCampaignConstants.FINERACT_TENANT_APP_KEY, messageGatewayConfigurationData.getTenantAppKey());
headers.add(SmsCampaignConstants.FINERACT_TENANT_APP_KEY, messageGatewayConfigurationData.tenantAppKey());
StringBuilder pathBuilder = new StringBuilder();
String endPoint = messageGatewayConfigurationData.getEndPoint() == null || messageGatewayConfigurationData.getEndPoint().equals("/")
? ""
: messageGatewayConfigurationData.getEndPoint();
pathBuilder = messageGatewayConfigurationData.getEndPoint() == null || messageGatewayConfigurationData.getEndPoint().equals("/")
String endPoint = messageGatewayConfigurationData.endPoint() == null || messageGatewayConfigurationData.endPoint().equals("/") ? ""
: messageGatewayConfigurationData.endPoint();
pathBuilder = messageGatewayConfigurationData.endPoint() == null || messageGatewayConfigurationData.endPoint().equals("/")
? pathBuilder.append("{apiEndPoint}")
: pathBuilder.append("{endPoint}/{apiEndPoint}");
// pathBuilder.append("{endPoint}/{apiEndPoint}") ;
UriBuilder builder = UriBuilder.fromPath(pathBuilder.toString()).host(messageGatewayConfigurationData.getHostName()).scheme("http")
.port(messageGatewayConfigurationData.getPortNumber());
URI uri = messageGatewayConfigurationData.getEndPoint() == null || messageGatewayConfigurationData.getEndPoint().equals("/")
UriBuilder builder = UriBuilder.fromPath(pathBuilder.toString()).host(messageGatewayConfigurationData.hostName()).scheme("http")
.port(messageGatewayConfigurationData.portNumber());
URI uri = messageGatewayConfigurationData.endPoint() == null || messageGatewayConfigurationData.endPoint().equals("/")
? builder.build(apiEndPoint)
: builder.build(endPoint, apiEndPoint);
HttpEntity<?> entity = null;
@@ -18,6 +18,10 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.api;
import static org.apache.fineract.infrastructure.campaigns.sms.data.dto.SmsCampaignHandlerDto.ACTIVATE_COMMAND;
import static org.apache.fineract.infrastructure.campaigns.sms.data.dto.SmsCampaignHandlerDto.CLOSE_COMMAND;
import static org.apache.fineract.infrastructure.campaigns.sms.data.dto.SmsCampaignHandlerDto.REACTIVATE_COMMAND;
import com.google.gson.JsonElement;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -34,10 +38,7 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.UriInfo;
import java.util.HashSet;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.commands.domain.CommandWrapper;
@@ -47,18 +48,19 @@ import org.apache.fineract.infrastructure.campaigns.constants.CampaignType;
import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignConstants;
import org.apache.fineract.infrastructure.campaigns.sms.data.CampaignPreviewData;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsCampaignData;
import org.apache.fineract.infrastructure.campaigns.sms.data.dto.SmsCampaignCreationDto;
import org.apache.fineract.infrastructure.campaigns.sms.data.dto.SmsCampaignHandlerDto;
import org.apache.fineract.infrastructure.campaigns.sms.data.dto.SmsCampaignPreviewDto;
import org.apache.fineract.infrastructure.campaigns.sms.data.dto.SmsCampaignUpdateDto;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignReadPlatformService;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignWritePlatformService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.api.JsonQuery;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.stereotype.Component;
@Path("/v1/smscampaigns")
@@ -68,14 +70,11 @@ public class SmsCampaignApiResource {
private final PlatformSecurityContext platformSecurityContext;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final DefaultToApiJsonSerializer<SmsCampaignData> toApiJsonSerializer;
private final SmsCampaignReadPlatformService smsCampaignReadPlatformService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final FromJsonHelper fromJsonHelper;
private final DefaultToApiJsonSerializer<CampaignPreviewData> previewCampaignMessageDefaultToApiJsonSerializer;
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
private final PlatformSecurityContext context;
private final SqlValidator sqlValidator;
private final DefaultToApiJsonSerializer<String> toApiJsonSerializer;
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "SMS_CAMPAIGN";
@@ -92,11 +91,9 @@ public class SmsCampaignApiResource {
smscampaigns/template""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SmsCampaignData.class)))
public String template(@Context final UriInfo uriInfo) {
public SmsCampaignData template() {
platformSecurityContext.authenticatedUser().validateHasReadPermission(SmsCampaignConstants.RESOURCE_NAME);
final SmsCampaignData smsCampaignData = smsCampaignReadPlatformService.retrieveTemplate(CampaignType.SMS.name());
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, smsCampaignData);
return smsCampaignReadPlatformService.retrieveTemplate(CampaignType.SMS.name());
}
@POST
@@ -110,11 +107,11 @@ public class SmsCampaignApiResource {
paramValue in json format""")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = CommandWrapper.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CommandProcessingResult.class)))
public String createCampaign(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
public CommandProcessingResult createCampaign(@Parameter(hidden = true) final SmsCampaignCreationDto smsCampaignCreationDto) {
platformSecurityContext.authenticatedUser();
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSmsCampaign().withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return toApiJsonSerializer.serialize(result);
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSmsCampaign()
.withJson(toApiJsonSerializer.serialize(smsCampaignCreationDto)).build();
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
@GET
@@ -126,12 +123,9 @@ public class SmsCampaignApiResource {
smscampaigns/1
""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SmsCampaignData.class)))
public String retrieveCampaign(@PathParam("resourceId") final Long resourceId, @Context final UriInfo uriInfo) {
public SmsCampaignData retrieveCampaign(@PathParam("resourceId") final Long resourceId) {
platformSecurityContext.authenticatedUser().validateHasReadPermission(SmsCampaignConstants.RESOURCE_NAME);
SmsCampaignData smsCampaignData = smsCampaignReadPlatformService.retrieveOne(resourceId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, smsCampaignData);
return smsCampaignReadPlatformService.retrieveOne(resourceId);
}
@GET
@@ -141,16 +135,12 @@ public class SmsCampaignApiResource {
smscampaigns""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SmsCampaignData.class)))
public String retrieveAllEmails(@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder, @Context final UriInfo uriInfo) {
public Page<SmsCampaignData> retrieveAllEmails(@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder) {
platformSecurityContext.authenticatedUser().validateHasReadPermission(SmsCampaignConstants.RESOURCE_NAME);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
Page<SmsCampaignData> smsCampaignDataCollection = smsCampaignReadPlatformService.retrieveAll(searchParameters);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, smsCampaignDataCollection);
return smsCampaignReadPlatformService.retrieveAll(searchParameters);
}
@PUT
@@ -160,12 +150,11 @@ public class SmsCampaignApiResource {
@Operation(summary = "Update a Campaign")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = CommandWrapper.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CommandProcessingResult.class)))
public String updateCampaign(@PathParam("campaignId") final Long campaignId,
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateSmsCampaign(campaignId).withJson(apiRequestBodyAsJson)
.build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return toApiJsonSerializer.serialize(result);
public CommandProcessingResult updateCampaign(@PathParam("campaignId") final Long campaignId,
@Parameter(hidden = true) final SmsCampaignUpdateDto smsCampaignUpdateDto) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateSmsCampaign(campaignId)
.withJson(toApiJsonSerializer.serialize(smsCampaignUpdateDto)).build();
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
@POST
@@ -174,51 +163,43 @@ public class SmsCampaignApiResource {
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "SMS Campaign", description = "Activates | Deactivates | Reactivates")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CommandProcessingResult.class)))
public String handleCommands(@PathParam("campaignId") final Long campaignId, @QueryParam("command") final String commandParam,
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
CommandProcessingResult result = null;
CommandWrapper commandRequest;
if (is(commandParam, "activate")) {
commandRequest = builder.activateSmsCampaign(campaignId).build();
result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, "close")) {
commandRequest = builder.closeSmsCampaign(campaignId).build();
result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, "reactivate")) {
commandRequest = builder.reactivateSmsCampaign(campaignId).build();
result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
return toApiJsonSerializer.serialize(result);
public CommandProcessingResult handleCommands(@PathParam("campaignId") final Long campaignId,
@QueryParam("command") final String commandParam, @Parameter(hidden = true) SmsCampaignHandlerDto campaignHandlerDto) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(toApiJsonSerializer.serialize(campaignHandlerDto));
return getCommandProcessingResult(commandParam, builder, campaignId);
}
@POST
@Path("preview")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String preview(final String apiRequestBodyAsJson, @Context final UriInfo uriInfo) {
public CampaignPreviewData preview(SmsCampaignPreviewDto previewDto) {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
CampaignPreviewData campaignMessage;
final JsonElement parsedQuery = fromJsonHelper.parse(apiRequestBodyAsJson);
final JsonQuery query = JsonQuery.from(apiRequestBodyAsJson, parsedQuery, fromJsonHelper);
campaignMessage = smsCampaignWritePlatformService.previewMessage(query);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return previewCampaignMessageDefaultToApiJsonSerializer.serialize(settings, campaignMessage, new HashSet<>());
final String strPreviewDtoJson = toApiJsonSerializer.serialize(previewDto);
final JsonElement parsedQuery = fromJsonHelper.parse(strPreviewDtoJson);
final JsonQuery query = JsonQuery.from(strPreviewDtoJson, parsedQuery, fromJsonHelper);
return smsCampaignWritePlatformService.previewMessage(query);
}
@DELETE
@Path("{campaignId}")
@Operation(summary = "Delete a SMS Campaign", description = "Note: Only closed SMS Campaigns can be deleted")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CommandProcessingResult.class)))
public String delete(@PathParam("campaignId") final Long campaignId) {
public CommandProcessingResult delete(@PathParam("campaignId") final Long campaignId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteSmsCampaign(campaignId).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return toApiJsonSerializer.serialize(result);
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
private CommandProcessingResult getCommandProcessingResult(String commandParam, CommandWrapperBuilder builder, Long campaignId) {
if (StringUtils.isBlank(commandParam)) {
return null;
}
return switch (commandParam.trim().toLowerCase()) {
case ACTIVATE_COMMAND -> commandsSourceWritePlatformService.logCommandSource(builder.activateSmsCampaign(campaignId).build());
case CLOSE_COMMAND -> commandsSourceWritePlatformService.logCommandSource(builder.closeSmsCampaign(campaignId).build());
case REACTIVATE_COMMAND ->
commandsSourceWritePlatformService.logCommandSource(builder.reactivateSmsCampaign(campaignId).build());
default -> null;
};
}
}
@@ -18,6 +18,9 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.constants;
import lombok.Getter;
@Getter
public enum SmsCampaignStatus {
INVALID(-1, "smsCampaignStatus.invalid"), //
@@ -34,38 +37,11 @@ public enum SmsCampaignStatus {
}
public static SmsCampaignStatus fromInt(final Integer statusValue) {
switch (statusValue) {
case 100:
return PENDING;
case 300:
return ACTIVE;
case 600:
return CLOSED;
default:
return INVALID;
}
}
public Integer getValue() {
return value;
}
public String getCode() {
return code;
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isActive() {
return this.equals(ACTIVE);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isPending() {
return this.equals(PENDING);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isClosed() {
return this.equals(CLOSED);
return switch (statusValue) {
case 100 -> PENDING;
case 300 -> ACTIVE;
case 600 -> CLOSED;
default -> INVALID;
};
}
}
@@ -18,8 +18,10 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.constants;
import lombok.Getter;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
@Getter
public enum SmsCampaignTriggerType {
INVALID(-1, "triggerType.invalid"), DIRECT(1, "triggerType.direct"), SCHEDULE(2, "triggerType.schedule"), TRIGGERED(3,
@@ -33,29 +35,17 @@ public enum SmsCampaignTriggerType {
this.code = code;
}
public Integer getValue() {
return value;
}
public String getCode() {
return code;
}
public static SmsCampaignTriggerType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
switch (v) {
case 1:
return DIRECT;
case 2:
return SCHEDULE;
case 3:
return TRIGGERED;
default:
return INVALID;
}
return switch (v) {
case 1 -> DIRECT;
case 2 -> SCHEDULE;
case 3 -> TRIGGERED;
default -> INVALID;
};
}
public static EnumOptionData triggerType(final Integer triggerTypeId) {
@@ -63,32 +53,12 @@ public enum SmsCampaignTriggerType {
}
public static EnumOptionData triggerType(final SmsCampaignTriggerType triggerType) {
switch (triggerType) {
case INVALID:
return new EnumOptionData(INVALID.getValue().longValue(), INVALID.getCode(), "Invalid");
case DIRECT:
return new EnumOptionData(DIRECT.getValue().longValue(), DIRECT.getCode(), "Direct");
case SCHEDULE:
return new EnumOptionData(SCHEDULE.getValue().longValue(), SCHEDULE.getCode(), "Schedule");
case TRIGGERED:
return new EnumOptionData(TRIGGERED.getValue().longValue(), TRIGGERED.getCode(), "Triggered");
default:
return new EnumOptionData(INVALID.getValue().longValue(), INVALID.getCode(), "Invalid");
}
return switch (triggerType) {
case DIRECT -> new EnumOptionData(DIRECT.getValue().longValue(), DIRECT.getCode(), "Direct");
case SCHEDULE -> new EnumOptionData(SCHEDULE.getValue().longValue(), SCHEDULE.getCode(), "Schedule");
case TRIGGERED -> new EnumOptionData(TRIGGERED.getValue().longValue(), TRIGGERED.getCode(), "Triggered");
default -> new EnumOptionData(INVALID.getValue().longValue(), INVALID.getCode(), "Invalid");
};
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isDirect() {
return this.equals(DIRECT);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isSchedule() {
return this.equals(SCHEDULE);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isTriggered() {
return this.equals(TRIGGERED);
}
}
@@ -18,22 +18,6 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.data;
public class CampaignPreviewData {
public record CampaignPreviewData(String campaignMessage, Integer totalNumberOfMessages) {
private final String campaignMessage;
private final Integer totalNumberOfMessages;
public CampaignPreviewData(String campaignMessage, Integer totalNumberOfMessages) {
this.campaignMessage = campaignMessage;
this.totalNumberOfMessages = totalNumberOfMessages;
}
public String getCampaignMessage() {
return campaignMessage;
}
public Integer getTotalNumberOfMessages() {
return totalNumberOfMessages;
}
}
@@ -18,64 +18,7 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.data;
public class MessageGatewayConfigurationData {
public record MessageGatewayConfigurationData(Long id, String connectionName, String hostName, int portNumber, String endPoint,
String userName, String password, boolean sslEnabled, String tenantAppKey) {
private final Long id;
private final String connectionName;
private final String hostName;
private final int portNumber;
private final String endPoint;
private final String userName;
private final String password;
private final boolean sslEnabled;
private final String tenantAppKey;
public MessageGatewayConfigurationData(final Long id, final String connectionName, final String hostName, final int portNumber,
final String endPoint, final String userName, final String password, final boolean sslEnabled, final String tenantAppKey) {
this.id = id;
this.connectionName = connectionName;
this.hostName = hostName;
this.portNumber = portNumber;
this.endPoint = endPoint;
this.userName = userName;
this.password = password;
this.sslEnabled = sslEnabled;
this.tenantAppKey = tenantAppKey;
}
public Long getId() {
return this.id;
}
public String getConnectionName() {
return this.connectionName;
}
public String getHostName() {
return this.hostName;
}
public int getPortNumber() {
return this.portNumber;
}
public String getEndPoint() {
return this.endPoint;
}
public String getUserName() {
return this.userName;
}
public String getPassword() {
return this.password;
}
public boolean isSslEnabled() {
return this.sslEnabled;
}
public String getTenantAppKey() {
return this.tenantAppKey;
}
}
@@ -20,59 +20,14 @@ package org.apache.fineract.infrastructure.campaigns.sms.data;
import java.util.Map;
public class SmsBusinessRulesData {
private final Long reportId;
private final String reportName;
private final String reportType;
private final String reportSubType;
private final String reportDescription;
private final Map<String, Object> reportParamName;
public SmsBusinessRulesData(final Long reportId, final String reportName, final String reportType, final String reportSubType,
final Map<String, Object> reportParamName, final String reportDescription) {
this.reportId = reportId;
this.reportName = reportName;
this.reportType = reportType;
this.reportSubType = reportSubType;
this.reportParamName = reportParamName;
this.reportDescription = reportDescription;
}
public record SmsBusinessRulesData(Long reportId, String reportName, String reportType, String reportSubType,
Map<String, Object> reportParamName, String reportDescription) {
public static SmsBusinessRulesData instance(final Long reportId, final String reportName, final String reportType,
final String reportSubType, final Map<String, Object> reportParamName, final String reportDescription) {
return new SmsBusinessRulesData(reportId, reportName, reportType, reportSubType, reportParamName, reportDescription);
}
public Map<String, Object> getReportParamName() {
return reportParamName;
}
public String getReportType() {
return reportType;
}
public String getReportSubType() {
return this.reportSubType;
}
public String getReportName() {
return reportName;
}
public Long getReportId() {
return reportId;
}
public String getReportDescription() {
return reportDescription;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -21,8 +21,12 @@ package org.apache.fineract.infrastructure.campaigns.sms.data;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.Collection;
import lombok.Builder;
import lombok.Getter;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
@Builder
@Getter
@SuppressWarnings("unused")
public final class SmsCampaignData {
@@ -44,82 +48,25 @@ public final class SmsCampaignData {
private final boolean isNotification;
private final Collection<SmsProviderData> smsProviderOptions;
private final Collection<EnumOptionData> campaignTypeOptions;
private final Collection<EnumOptionData> triggerTypeOptions;
private final Collection<SmsBusinessRulesData> businessRulesOptions;
private final Collection<EnumOptionData> months;
private final Collection<EnumOptionData> weekDays;
private final Collection<EnumOptionData> frequencyTypeOptions;
private final Collection<EnumOptionData> periodFrequencyOptions;
private SmsCampaignData(final Long id, final String campaignName, final EnumOptionData campaignType, final EnumOptionData triggerType,
final Long runReportId, final String reportName, final String paramValue, final EnumOptionData campaignStatus,
final String message, final ZonedDateTime nextTriggerDate, final LocalDate lastTriggerDate,
final SmsCampaignTimeLine smsCampaignTimeLine, final ZonedDateTime recurrenceStartDate, final String recurrence,
final Long providerId, final Collection<SmsBusinessRulesData> businessRulesOptions,
final Collection<SmsProviderData> smsProviderOptions, final Collection<EnumOptionData> campaignTypeOptions,
final Collection<EnumOptionData> triggerTypeOptions, final Collection<EnumOptionData> months,
final Collection<EnumOptionData> weekDays, final Collection<EnumOptionData> frequencyTypeOptions,
final Collection<EnumOptionData> periodFrequencyOptions, final boolean isNotification) {
this.id = id;
this.campaignName = campaignName;
this.campaignType = campaignType;
this.triggerType = triggerType;
this.runReportId = runReportId;
this.reportName = reportName;
this.paramValue = paramValue;
this.campaignStatus = campaignStatus;
this.campaignMessage = message;
if (nextTriggerDate != null) {
this.nextTriggerDate = nextTriggerDate;
} else {
this.nextTriggerDate = null;
}
if (lastTriggerDate != null) {
this.lastTriggerDate = lastTriggerDate;
} else {
this.lastTriggerDate = null;
}
this.isNotification = isNotification;
this.smsCampaignTimeLine = smsCampaignTimeLine;
this.recurrenceStartDate = recurrenceStartDate;
this.recurrence = recurrence;
this.providerId = providerId;
this.businessRulesOptions = businessRulesOptions;
this.smsProviderOptions = smsProviderOptions;
this.campaignTypeOptions = campaignTypeOptions;
this.triggerTypeOptions = triggerTypeOptions;
this.months = months;
this.weekDays = weekDays;
this.frequencyTypeOptions = frequencyTypeOptions;
this.periodFrequencyOptions = periodFrequencyOptions;
}
public static SmsCampaignData instance(final Long id, final String campaignName, final EnumOptionData campaignType,
final EnumOptionData triggerType, final Long runReportId, final String reportName, final String paramValue,
final EnumOptionData campaignStatus, final String message, final ZonedDateTime nextTriggerDate, final LocalDate lastTriggerDate,
final SmsCampaignTimeLine smsCampaignTimeLine, final ZonedDateTime recurrenceStartDate, final String recurrence,
final Long providerId, final boolean isNotification) {
final Collection<SmsBusinessRulesData> businessRulesOptions = null;
final Collection<SmsProviderData> smsProviderOptions = null;
final Collection<EnumOptionData> campaignTypeOptions = null;
final Collection<EnumOptionData> triggerTypeOptions = null;
final Collection<EnumOptionData> months = null;
final Collection<EnumOptionData> weekDays = null;
final Collection<EnumOptionData> frequencyTypeOptions = null;
final Collection<EnumOptionData> periodFrequencyOptions = null;
return new SmsCampaignData(id, campaignName, campaignType, triggerType, runReportId, reportName, paramValue, campaignStatus,
message, nextTriggerDate, lastTriggerDate, smsCampaignTimeLine, recurrenceStartDate, recurrence, providerId,
businessRulesOptions, smsProviderOptions, campaignTypeOptions, triggerTypeOptions, months, weekDays, frequencyTypeOptions,
periodFrequencyOptions, isNotification);
return SmsCampaignData.builder().id(id).campaignName(campaignName).campaignType(campaignType).triggerType(triggerType)
.runReportId(runReportId).reportName(reportName).paramValue(paramValue).campaignStatus(campaignStatus)
.campaignMessage(message).nextTriggerDate(nextTriggerDate).lastTriggerDate(lastTriggerDate)
.smsCampaignTimeLine(smsCampaignTimeLine).recurrenceStartDate(recurrenceStartDate).recurrence(recurrence)
.providerId(providerId).isNotification(isNotification).build();
}
public static SmsCampaignData template(final Collection<SmsProviderData> smsProviderOptions,
@@ -127,82 +74,9 @@ public final class SmsCampaignData {
final Collection<EnumOptionData> triggerTypeOptions, final Collection<EnumOptionData> months,
final Collection<EnumOptionData> weekDays, final Collection<EnumOptionData> frequencyTypeOptions,
final Collection<EnumOptionData> periodFrequencyOptions) {
final Long id = null;
final String campaignName = null;
final EnumOptionData campaignType = null;
final Long runReportId = null;
final String paramValue = null;
final EnumOptionData campaignStatus = null;
final String message = null;
final ZonedDateTime nextTriggerDate = null;
final LocalDate lastTriggerDate = null;
final SmsCampaignTimeLine smsCampaignTimeLine = null;
final ZonedDateTime recurrenceStartDate = null;
final String recurrence = null;
final EnumOptionData triggerType = null;
final String reportName = null;
final Long providerId = null;
final boolean isNotification = false;
return new SmsCampaignData(id, campaignName, campaignType, triggerType, runReportId, reportName, paramValue, campaignStatus,
message, nextTriggerDate, lastTriggerDate, smsCampaignTimeLine, recurrenceStartDate, recurrence, providerId,
businessRulesOptions, smsProviderOptions, campaignTypeOptions, triggerTypeOptions, months, weekDays, frequencyTypeOptions,
periodFrequencyOptions, isNotification);
}
public Long getId() {
return id;
}
public String getCampaignName() {
return this.campaignName;
}
public EnumOptionData getCampaignType() {
return this.campaignType;
}
public Long getRunReportId() {
return this.runReportId;
}
public String getParamValue() {
return this.paramValue;
}
public EnumOptionData getCampaignStatus() {
return this.campaignStatus;
}
public String getMessage() {
return this.campaignMessage;
}
public ZonedDateTime getNextTriggerDate() {
return this.nextTriggerDate;
}
public LocalDate getLastTriggerDate() {
return this.lastTriggerDate;
}
public String getRecurrence() {
return this.recurrence;
}
public ZonedDateTime getRecurrenceStartDate() {
return this.recurrenceStartDate;
}
public String getReportName() {
return this.reportName;
}
public Long providerId() {
return this.providerId;
}
public boolean isNotification() {
return this.isNotification;
return SmsCampaignData.builder().smsProviderOptions(smsProviderOptions).businessRulesOptions(businessRulesOptions)
.campaignTypeOptions(campaignTypeOptions).triggerTypeOptions(triggerTypeOptions).months(months).weekDays(weekDays)
.frequencyTypeOptions(frequencyTypeOptions).periodFrequencyOptions(periodFrequencyOptions).build();
}
}
@@ -21,24 +21,7 @@ package org.apache.fineract.infrastructure.campaigns.sms.data;
import java.time.LocalDate;
@SuppressWarnings("unused")
public class SmsCampaignTimeLine {
public record SmsCampaignTimeLine(LocalDate submittedOnDate, String submittedByUsername, LocalDate activatedOnDate,
String activatedByUsername, LocalDate closedOnDate, String closedByUsername) {
private final LocalDate submittedOnDate;
private final String submittedByUsername;
private final LocalDate activatedOnDate;
private final String activatedByUsername;
private final LocalDate closedOnDate;
private final String closedByUsername;
public SmsCampaignTimeLine(final LocalDate submittedOnDate, final String submittedByUsername, final LocalDate activatedOnDate,
final String activatedByUsername, final LocalDate closedOnDate, final String closedByUsername) {
this.submittedOnDate = submittedOnDate;
this.submittedByUsername = submittedByUsername;
this.activatedOnDate = activatedOnDate;
this.activatedByUsername = activatedByUsername;
this.closedOnDate = closedOnDate;
this.closedByUsername = closedByUsername;
}
}
@@ -18,55 +18,20 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.data;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class SmsProviderData {
private Long id;
private String tenantId;
private String phoneNo;
private String providerAppKey;
private String providerName;
private String providerDescription;
public SmsProviderData(final Long id, final String providerAppKey, final String providerName, final String providerDescription,
final String tenantId, final String phoneNo) {
this.id = id;
this.providerAppKey = providerAppKey;
this.providerName = providerName;
this.providerDescription = providerDescription;
this.tenantId = tenantId;
this.phoneNo = phoneNo;
}
public SmsProviderData() {
}
public Long getId() {
return this.id;
}
public String getProviderAppKey() {
return this.providerAppKey;
}
public String getProviderName() {
return this.providerName;
}
public String getProviderDescription() {
return this.providerDescription;
}
public String getTenantId() {
return this.tenantId;
}
public String getPhoneNo() {
return this.phoneNo;
}
}
@@ -0,0 +1,36 @@
/**
* 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.campaigns.sms.data.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SmsCampaignCreationDto extends SmsCampaignDto {
private Long providerId;
private String frequency;
private String interval;
private String repeatsOnDay;
}
@@ -0,0 +1,49 @@
/**
* 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.campaigns.sms.data.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serial;
import java.io.Serializable;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public abstract class SmsCampaignDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String campaignName;
private Long campaignType;
private Long triggerType;
private Long runReportId;
private String message;
private SmsCampaignParamReq paramValue;
private String recurrenceStartDate;
private String submittedOnDate;
private Boolean isNotification;
private String locale;
private String dateFormat;
private String dateTimeFormat;
}
@@ -0,0 +1,48 @@
/**
* 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.campaigns.sms.data.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serial;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SmsCampaignHandlerDto implements Serializable {
public static final String ACTIVATE_COMMAND = "activate";
public static final String CLOSE_COMMAND = "close";
public static final String REACTIVATE_COMMAND = "reactivate";
@Serial
private static final long serialVersionUID = 1L;
private String locale;
private String dateFormat;
private String activationDate;
private String closureDate;
}
@@ -0,0 +1,39 @@
/**
* 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.campaigns.sms.data.dto;
import java.io.Serial;
import java.io.Serializable;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class SmsCampaignParamReq implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Integer officeId;
private Integer loanOfficerId;
private Integer transactionId;
private String reportName;
}
@@ -0,0 +1,28 @@
/**
* 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.campaigns.sms.data.dto;
import java.io.Serial;
import java.io.Serializable;
public record SmsCampaignPreviewDto(SmsCampaignParamReq paramValue, String message) implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
}
@@ -0,0 +1,33 @@
/**
* 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.campaigns.sms.data.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SmsCampaignUpdateDto extends SmsCampaignDto {
private String recurrence;
}
@@ -18,6 +18,13 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.domain;
import static org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignStatus.ACTIVE;
import static org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignStatus.CLOSED;
import static org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignStatus.PENDING;
import static org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType.DIRECT;
import static org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType.SCHEDULE;
import static org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType.TRIGGERED;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
@@ -159,7 +166,7 @@ public class SmsCampaign extends AbstractPersistableCustom<Long> {
String recurrence = null;
LocalDateTime recurrenceStartDate = null;
if (SmsCampaignTriggerType.fromInt(triggerType.intValue()).isSchedule()) {
if (SCHEDULE.getValue().equals(triggerType.intValue())) {
final Locale locale = command.extractLocale();
String dateTimeFormat;
recurrenceStartDate = DateUtils.getLocalDateTimeOfTenant();
@@ -228,7 +235,7 @@ public class SmsCampaign extends AbstractPersistableCustom<Long> {
actualChanges.put(SmsCampaignValidator.isNotificationParamName, newValue);
}
if (SmsCampaignTriggerType.fromInt(this.triggerType).isSchedule()) {
if (isSchedule()) {
final String dateFormatAsInput = command.dateFormat();
final String dateTimeFormatAsInput = command.stringValueOfParameterNamed(SmsCampaignValidator.dateTimeFormat);
final String localeAsInput = command.locale();
@@ -260,7 +267,7 @@ public class SmsCampaign extends AbstractPersistableCustom<Long> {
}
this.approvedOnDate = activationLocalDate;
this.approvedBy = currentUser;
this.status = SmsCampaignStatus.ACTIVE.getValue();
this.status = ACTIVE.getValue();
validate();
}
@@ -301,7 +308,7 @@ public class SmsCampaign extends AbstractPersistableCustom<Long> {
}
this.approvedOnDate = reactivateLocalDate;
this.status = SmsCampaignStatus.ACTIVE.getValue();
this.status = ACTIVE.getValue();
this.approvedBy = currentUser;
this.closureDate = null;
this.isVisible = true;
@@ -326,27 +333,27 @@ public class SmsCampaign extends AbstractPersistableCustom<Long> {
}
public boolean isActive() {
return SmsCampaignStatus.fromInt(this.status).isActive();
return SmsCampaignStatus.fromInt(this.status).equals(ACTIVE);
}
public boolean isPending() {
return SmsCampaignStatus.fromInt(this.status).isPending();
return SmsCampaignStatus.fromInt(this.status).equals(PENDING);
}
public boolean isClosed() {
return SmsCampaignStatus.fromInt(this.status).isClosed();
return SmsCampaignStatus.fromInt(this.status).equals(CLOSED);
}
public boolean isDirect() {
return SmsCampaignTriggerType.fromInt(this.triggerType).isDirect();
return SmsCampaignTriggerType.fromInt(this.triggerType).equals(DIRECT);
}
public boolean isSchedule() {
return SmsCampaignTriggerType.fromInt(this.triggerType).isSchedule();
return SmsCampaignTriggerType.fromInt(this.triggerType).equals(SCHEDULE);
}
public boolean isTriggered() {
return SmsCampaignTriggerType.fromInt(this.triggerType).isTriggered();
return SmsCampaignTriggerType.fromInt(this.triggerType).equals(TRIGGERED);
}
private void validate() {
@@ -32,28 +32,17 @@ public final class SmsCampaignStatusEnumerations {
}
public static EnumOptionData status(final SmsCampaignStatus status) {
EnumOptionData optionData = new EnumOptionData(SmsCampaignStatus.INVALID.getValue().longValue(),
SmsCampaignStatus.INVALID.getCode(), "Invalid");
switch (status) {
case INVALID:
optionData = new EnumOptionData(SmsCampaignStatus.INVALID.getValue().longValue(), SmsCampaignStatus.INVALID.getCode(),
"Invalid");
break;
case PENDING:
optionData = new EnumOptionData(SmsCampaignStatus.PENDING.getValue().longValue(), SmsCampaignStatus.PENDING.getCode(),
"Pending");
break;
case ACTIVE:
optionData = new EnumOptionData(SmsCampaignStatus.ACTIVE.getValue().longValue(), SmsCampaignStatus.ACTIVE.getCode(),
"active");
break;
case CLOSED:
optionData = new EnumOptionData(SmsCampaignStatus.CLOSED.getValue().longValue(), SmsCampaignStatus.CLOSED.getCode(),
"closed");
break;
new EnumOptionData(SmsCampaignStatus.INVALID.getValue().longValue(), SmsCampaignStatus.INVALID.getCode(), "Invalid");
}
return optionData;
return switch (status) {
case INVALID ->
new EnumOptionData(SmsCampaignStatus.INVALID.getValue().longValue(), SmsCampaignStatus.INVALID.getCode(), "Invalid");
case PENDING ->
new EnumOptionData(SmsCampaignStatus.PENDING.getValue().longValue(), SmsCampaignStatus.PENDING.getCode(), "Pending");
case ACTIVE ->
new EnumOptionData(SmsCampaignStatus.ACTIVE.getValue().longValue(), SmsCampaignStatus.ACTIVE.getCode(), "active");
case CLOSED ->
new EnumOptionData(SmsCampaignStatus.CLOSED.getValue().longValue(), SmsCampaignStatus.CLOSED.getCode(), "closed");
};
}
}
@@ -18,25 +18,21 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.handler;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignWritePlatformService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SMSCAMPAIGN", action = "ACTIVATE")
@RequiredArgsConstructor
public class ActivateSmsCampaignCommandHandler implements NewCommandSourceHandler {
private SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Autowired
public ActivateSmsCampaignCommandHandler(final SmsCampaignWritePlatformService smsCampaignWritePlatformService) {
this.smsCampaignWritePlatformService = smsCampaignWritePlatformService;
}
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Transactional
@Override
@@ -18,25 +18,21 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.handler;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignWritePlatformService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@CommandType(entity = "SMSCAMPAIGN", action = "CLOSE")
@RequiredArgsConstructor
public class CloseSmsCampaignCommandHandler implements NewCommandSourceHandler {
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Autowired
public CloseSmsCampaignCommandHandler(final SmsCampaignWritePlatformService smsCampaignWritePlatformService) {
this.smsCampaignWritePlatformService = smsCampaignWritePlatformService;
}
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.smsCampaignWritePlatformService.closeSmsCampaign(command.entityId(), command);
@@ -18,25 +18,21 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.handler;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignWritePlatformService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SMSCAMPAIGN", action = "CREATE")
@RequiredArgsConstructor
public class CreateSmsCampaignCommandHandler implements NewCommandSourceHandler {
private SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Autowired
public CreateSmsCampaignCommandHandler(final SmsCampaignWritePlatformService smsCampaignWritePlatformService) {
this.smsCampaignWritePlatformService = smsCampaignWritePlatformService;
}
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Transactional
@Override
@@ -18,26 +18,22 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.handler;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignWritePlatformService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SMSCAMPAIGN", action = "DELETE")
@RequiredArgsConstructor
public class DeleteSmsCampaignCommandHandler implements NewCommandSourceHandler {
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Autowired
public DeleteSmsCampaignCommandHandler(SmsCampaignWritePlatformService smsCampaignWritePlatformService) {
this.smsCampaignWritePlatformService = smsCampaignWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
@@ -18,26 +18,22 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.handler;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignWritePlatformService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SMSCAMPAIGN", action = "REACTIVATE")
@RequiredArgsConstructor
public class ReactivateSmsCampaignCommandHandler implements NewCommandSourceHandler {
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Autowired
public ReactivateSmsCampaignCommandHandler(SmsCampaignWritePlatformService smsCampaignWritePlatformService) {
this.smsCampaignWritePlatformService = smsCampaignWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
@@ -18,25 +18,21 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.handler;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignWritePlatformService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SMSCAMPAIGN", action = "UPDATE")
@RequiredArgsConstructor
public class UpdateSmsCampaignCommandHandler implements NewCommandSourceHandler {
private SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Autowired
public UpdateSmsCampaignCommandHandler(final SmsCampaignWritePlatformService smsCampaignWritePlatformService) {
this.smsCampaignWritePlatformService = smsCampaignWritePlatformService;
}
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
@Transactional
@Override
@@ -0,0 +1,103 @@
/**
* 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.campaigns.sms.mapper;
import jakarta.annotation.PostConstruct;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsBusinessRulesData;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class BusinessRuleMapper implements ResultSetExtractor<List<SmsBusinessRulesData>> {
private String schema;
private final DatabaseSpecificSQLGenerator sqlGenerator;
@PostConstruct
public void init() {
final StringBuilder sql = new StringBuilder(300);
sql.append("sr.id as id, ");
sql.append("sr.report_name as reportName, ");
sql.append("sr.report_type as reportType, ");
sql.append("sr.report_subtype as reportSubType, ");
sql.append("sr.description as description, ");
sql.append("sp.parameter_variable as params, ");
sql.append("sp." + sqlGenerator.escape("parameter_FormatType") + " as paramType, ");
sql.append("sp.parameter_label as paramLabel, ");
sql.append("sp.parameter_name as paramName ");
sql.append("from stretchy_report sr ");
sql.append("left join stretchy_report_parameter as srp on srp.report_id = sr.id ");
sql.append("left join stretchy_parameter as sp on sp.id = srp.parameter_id ");
this.schema = sql.toString();
}
public String schema() {
return this.schema;
}
@Override
public List<SmsBusinessRulesData> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<SmsBusinessRulesData> smsBusinessRulesDataList = new ArrayList<>();
SmsBusinessRulesData smsBusinessRulesData = null;
Map<Long, SmsBusinessRulesData> mapOfSameObjects = new HashMap<>();
while (rs.next()) {
final Long id = rs.getLong("id");
smsBusinessRulesData = mapOfSameObjects.get(id);
if (smsBusinessRulesData == null) {
final String reportName = rs.getString("reportName");
final String reportType = rs.getString("reportType");
final String reportSubType = rs.getString("reportSubType");
final String paramName = rs.getString("paramName");
final String paramLabel = rs.getString("paramLabel");
final String description = rs.getString("description");
Map<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put(paramLabel, paramName);
smsBusinessRulesData = SmsBusinessRulesData.instance(id, reportName, reportType, reportSubType, hashMap, description);
mapOfSameObjects.put(id, smsBusinessRulesData);
// add to the list
smsBusinessRulesDataList.add(smsBusinessRulesData);
}
// add new paramType to the existing object
Map<String, Object> hashMap = new HashMap<String, Object>();
final String paramName = rs.getString("paramName");
final String paramLabel = rs.getString("paramLabel");
hashMap.put(paramLabel, paramName);
// get existing map and add new items to it
smsBusinessRulesData.reportParamName().putAll(hashMap);
}
return smsBusinessRulesDataList;
}
}
@@ -0,0 +1,118 @@
/**
* 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.campaigns.sms.mapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import lombok.Setter;
import org.apache.fineract.infrastructure.campaigns.constants.CampaignType;
import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsCampaignData;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsCampaignTimeLine;
import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaignStatusEnumerations;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
@Setter
@Component
public class SmsCampaignMapper implements RowMapper<SmsCampaignData> {
private String schema;
public SmsCampaignMapper() {
setSchema(buildCampaignColumn());
}
public String schema() {
return this.schema;
}
private String buildCampaignColumn() {
final StringBuilder sql = new StringBuilder(400);
sql.append("sc.id as id, ");
sql.append("sc.campaign_name as campaignName, ");
sql.append("sc.campaign_type as campaignType, ");
sql.append("sc.campaign_trigger_type as triggerType, ");
sql.append("sc.report_id as runReportId, ");
sql.append("sc.message as message, ");
sql.append("sc.param_value as paramValue, ");
sql.append("sc.status_enum as status, ");
sql.append("sc.recurrence as recurrence, ");
sql.append("sc.recurrence_start_date as recurrenceStartDate, ");
sql.append("sc.next_trigger_date as nextTriggerDate, ");
sql.append("sc.last_trigger_date as lastTriggerDate, ");
sql.append("sc.submittedon_date as submittedOnDate, ");
sql.append("sbu.username as submittedByUsername, ");
sql.append("sc.closedon_date as closedOnDate, ");
sql.append("clu.username as closedByUsername, ");
sql.append("acu.username as activatedByUsername, ");
sql.append("sc.approvedon_date as activatedOnDate, ");
sql.append("sr.report_name as reportName, ");
sql.append("provider_id as providerId, ");
sql.append("sc.is_notification as isNotification ");
sql.append("from sms_campaign sc ");
sql.append("left join m_appuser sbu on sbu.id = sc.submittedon_userid ");
sql.append("left join m_appuser acu on acu.id = sc.approvedon_userid ");
sql.append("left join m_appuser clu on clu.id = sc.closedon_userid ");
sql.append("left join stretchy_report sr on sr.id = sc.report_id ");
return sql.toString();
}
@Override
public SmsCampaignData mapRow(ResultSet rs, int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String campaignName = rs.getString("campaignName");
final Integer campaignType = JdbcSupport.getInteger(rs, "campaignType");
final EnumOptionData campaignTypeEnum = CampaignType.campaignType(campaignType);
final Long runReportId = JdbcSupport.getLong(rs, "runReportId");
final String paramValue = rs.getString("paramValue");
final String message = rs.getString("message");
final Integer statusId = JdbcSupport.getInteger(rs, "status");
final EnumOptionData status = SmsCampaignStatusEnumerations.status(statusId);
final Integer triggerType = JdbcSupport.getInteger(rs, "triggerType");
final EnumOptionData triggerTypeEnum = SmsCampaignTriggerType.triggerType(triggerType);
final ZonedDateTime nextTriggerDate = JdbcSupport.getDateTime(rs, "nextTriggerDate");
final LocalDate lastTriggerDate = JdbcSupport.getLocalDate(rs, "lastTriggerDate");
final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate");
final String closedByUsername = rs.getString("closedByUsername");
final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
final String submittedByUsername = rs.getString("submittedByUsername");
final LocalDate activatedOnDate = JdbcSupport.getLocalDate(rs, "activatedOnDate");
final String activatedByUsername = rs.getString("activatedByUsername");
final String recurrence = rs.getString("recurrence");
final ZonedDateTime recurrenceStartDate = JdbcSupport.getDateTime(rs, "recurrenceStartDate");
final SmsCampaignTimeLine smsCampaignTimeLine = new SmsCampaignTimeLine(submittedOnDate, submittedByUsername, activatedOnDate,
activatedByUsername, closedOnDate, closedByUsername);
final String reportName = rs.getString("reportName");
final Long providerId = rs.getLong("providerId");
final boolean isNotification = rs.getBoolean("isNotification");
return SmsCampaignData.instance(id, campaignName, campaignTypeEnum, triggerTypeEnum, runReportId, reportName, paramValue, status,
message, nextTriggerDate, lastTriggerDate, smsCampaignTimeLine, recurrenceStartDate, recurrence, providerId,
isNotification);
}
}
@@ -104,7 +104,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void notifyRejectedLoanOwner(Loan loan) {
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns("Loan Rejected");
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign campaign : smsCampaigns) {
if (campaign.isActive()) {
SmsCampaignDomainServiceImpl.this.smsCampaignWritePlatformCommandHandler.insertDirectCampaignIntoSmsOutboundTable(loan,
@@ -116,7 +116,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void notifyAcceptedLoanOwner(Loan loan) {
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns("Loan Approved");
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign campaign : smsCampaigns) {
this.smsCampaignWritePlatformCommandHandler.insertDirectCampaignIntoSmsOutboundTable(loan, campaign);
}
@@ -125,7 +125,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void notifyClientActivated(final Client client) {
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns("Client Activated");
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign campaign : smsCampaigns) {
this.smsCampaignWritePlatformCommandHandler.insertDirectCampaignIntoSmsOutboundTable(client, campaign);
}
@@ -135,7 +135,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void notifyClientRejected(final Client client) {
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns("Client Rejected");
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign campaign : smsCampaigns) {
this.smsCampaignWritePlatformCommandHandler.insertDirectCampaignIntoSmsOutboundTable(client, campaign);
}
@@ -145,7 +145,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void notifySavingsAccountActivated(final SavingsAccount savingsAccount) {
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns("Savings Activated");
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign campaign : smsCampaigns) {
this.smsCampaignWritePlatformCommandHandler.insertDirectCampaignIntoSmsOutboundTable(savingsAccount, campaign);
}
@@ -155,7 +155,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void notifySavingsAccountRejected(final SavingsAccount savingsAccount) {
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns("Savings Rejected");
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign campaign : smsCampaigns) {
this.smsCampaignWritePlatformCommandHandler.insertDirectCampaignIntoSmsOutboundTable(savingsAccount, campaign);
}
@@ -165,7 +165,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void sendSmsForLoanRepayment(LoanTransaction loanTransaction) {
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns("Loan Repayment");
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign smsCampaign : smsCampaigns) {
try {
Loan loan = loanTransaction.getLoan();
@@ -236,7 +236,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
private void sendSmsForSavingsTransaction(final SavingsAccountTransaction savingsTransaction, boolean isDeposit) {
String campaignName = isDeposit ? "Savings Deposit" : "Savings Withdrawal";
List<SmsCampaign> smsCampaigns = retrieveSmsCampaigns(campaignName);
if (smsCampaigns.size() > 0) {
if (!smsCampaigns.isEmpty()) {
for (SmsCampaign smsCampaign : smsCampaigns) {
try {
final SavingsAccount savingsAccount = savingsTransaction.getSavingsAccount();
@@ -293,9 +293,7 @@ public class SmsCampaignDomainServiceImpl implements SmsCampaignDomainService {
}
private List<SmsCampaign> retrieveSmsCampaigns(String paramValue) {
List<SmsCampaign> smsCampaigns = smsCampaignRepository.findActiveSmsCampaigns("%" + paramValue + "%",
SmsCampaignTriggerType.TRIGGERED.getValue());
return smsCampaigns;
return smsCampaignRepository.findActiveSmsCampaigns("%" + paramValue + "%", SmsCampaignTriggerType.TRIGGERED.getValue());
}
private HashMap<String, Object> processRepaymentDataForSms(final LoanTransaction loanTransaction, Client groupClient) {
@@ -18,7 +18,6 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.service;
import java.util.Collection;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsCampaignData;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
@@ -30,7 +29,4 @@ public interface SmsCampaignReadPlatformService {
Page<SmsCampaignData> retrieveAll(SearchParameters searchParameters);
SmsCampaignData retrieveTemplate(String reportType);
Collection<SmsCampaignData> retrieveAllScheduleActiveCampaign();
}
@@ -18,69 +18,42 @@
*/
package org.apache.fineract.infrastructure.campaigns.sms.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.campaigns.constants.CampaignType;
import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsBusinessRulesData;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsCampaignData;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsCampaignTimeLine;
import org.apache.fineract.infrastructure.campaigns.sms.data.SmsProviderData;
import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaignStatusEnumerations;
import org.apache.fineract.infrastructure.campaigns.sms.exception.SmsCampaignNotFound;
import org.apache.fineract.infrastructure.campaigns.sms.mapper.BusinessRuleMapper;
import org.apache.fineract.infrastructure.campaigns.sms.mapper.SmsCampaignMapper;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.portfolio.calendar.service.CalendarDropdownReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class SmsCampaignReadPlatformServiceImpl implements SmsCampaignReadPlatformService {
private final BusinessRuleMapper businessRuleMapper;
private final JdbcTemplate jdbcTemplate;
private final DatabaseSpecificSQLGenerator sqlGenerator;
private final SmsCampaignDropdownReadPlatformService smsCampaignDropdownReadPlatformService;
private final SmsCampaignMapper smsCampaignMapper;
private final CalendarDropdownReadPlatformService calendarDropdownReadPlatformService;
private final PaginationHelper paginationHelper;
@Autowired
public SmsCampaignReadPlatformServiceImpl(final JdbcTemplate jdbcTemplate,
SmsCampaignDropdownReadPlatformService smsCampaignDropdownReadPlatformService,
final CalendarDropdownReadPlatformService calendarDropdownReadPlatformService, DatabaseSpecificSQLGenerator sqlGenerator,
PaginationHelper paginationHelper) {
this.jdbcTemplate = jdbcTemplate;
this.sqlGenerator = sqlGenerator;
this.businessRuleMapper = new BusinessRuleMapper(sqlGenerator);
this.smsCampaignDropdownReadPlatformService = smsCampaignDropdownReadPlatformService;
this.smsCampaignMapper = new SmsCampaignMapper();
this.calendarDropdownReadPlatformService = calendarDropdownReadPlatformService;
this.paginationHelper = paginationHelper;
}
private final BusinessRuleMapper businessRuleMapper;
private final SmsCampaignMapper smsCampaignMapper;
@Override
public SmsCampaignData retrieveOne(Long campaignId) {
final boolean isVisible = true;
try {
final String sql = "select " + this.smsCampaignMapper.schema + " where sc.id = ? and sc.is_visible = ?";
final String sql = "select " + this.smsCampaignMapper.schema() + " where sc.id = ? and sc.is_visible = ?";
return this.jdbcTemplate.queryForObject(sql, this.smsCampaignMapper, campaignId, isVisible); // NOSONAR
} catch (final EmptyResultDataAccessException e) {
throw new SmsCampaignNotFound(campaignId, e);
@@ -90,9 +63,9 @@ public class SmsCampaignReadPlatformServiceImpl implements SmsCampaignReadPlatfo
@Override
public Page<SmsCampaignData> retrieveAll(final SearchParameters searchParameters) {
final boolean visible = true;
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " ");
sqlBuilder.append(this.smsCampaignMapper.schema() + " where sc.is_visible = ? ");
final StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("select ").append(sqlGenerator.calcFoundRows()).append(" ").append(this.smsCampaignMapper.schema())
.append(" where sc.is_visible = ? ");
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
@@ -107,11 +80,13 @@ public class SmsCampaignReadPlatformServiceImpl implements SmsCampaignReadPlatfo
@Override
public SmsCampaignData retrieveTemplate(final String reportType) {
String sql = "select " + this.businessRuleMapper.schema();
if (!StringUtils.isEmpty(reportType)) {
sql = sql + " where sr.report_type = ?";
final StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("select ").append(this.businessRuleMapper.schema());
if (StringUtils.isNotBlank(reportType)) {
sqlBuilder.append(" where sr.report_type = ?");
}
final Collection<SmsBusinessRulesData> businessRulesOptions = this.jdbcTemplate.query(sql, this.businessRuleMapper, // NOSONAR
final Collection<SmsBusinessRulesData> businessRulesOptions = this.jdbcTemplate.query(sqlBuilder.toString(),
this.businessRuleMapper, // NOSONAR
reportType);
final Collection<SmsProviderData> smsProviderOptions = this.smsCampaignDropdownReadPlatformService.retrieveSmsProviders();
final Collection<EnumOptionData> campaignTypeOptions = this.smsCampaignDropdownReadPlatformService.retrieveCampaignTypes();
@@ -122,161 +97,7 @@ public class SmsCampaignReadPlatformServiceImpl implements SmsCampaignReadPlatfo
final Collection<EnumOptionData> frequencyTypeOptions = this.calendarDropdownReadPlatformService
.retrieveCalendarFrequencyTypeOptions();
final Collection<EnumOptionData> periodFrequencyOptions = this.smsCampaignDropdownReadPlatformService.retrivePeriodFrequencyTypes();
// final Collection<TriggerTypeWithSubTypesData>
// triggerTypeSubTypeOptions =
// this.smsCampaignDropdownReadPlatformService.getTriggerTypeAndSubTypes();
return SmsCampaignData.template(smsProviderOptions, campaignTypeOptions, businessRulesOptions, campaignTriggerTypeOptions, months,
weekDays, frequencyTypeOptions, periodFrequencyOptions);
}
@Override
public Collection<SmsCampaignData> retrieveAllScheduleActiveCampaign() {
return null;
}
private static final class BusinessRuleMapper implements ResultSetExtractor<List<SmsBusinessRulesData>> {
final String schema;
private BusinessRuleMapper(DatabaseSpecificSQLGenerator sqlGenerator) {
final StringBuilder sql = new StringBuilder(300);
sql.append("sr.id as id, ");
sql.append("sr.report_name as reportName, ");
sql.append("sr.report_type as reportType, ");
sql.append("sr.report_subtype as reportSubType, ");
sql.append("sr.description as description, ");
sql.append("sp.parameter_variable as params, ");
sql.append("sp." + sqlGenerator.escape("parameter_FormatType") + " as paramType, ");
sql.append("sp.parameter_label as paramLabel, ");
sql.append("sp.parameter_name as paramName ");
sql.append("from stretchy_report sr ");
sql.append("left join stretchy_report_parameter as srp on srp.report_id = sr.id ");
sql.append("left join stretchy_parameter as sp on sp.id = srp.parameter_id ");
this.schema = sql.toString();
}
public String schema() {
return this.schema;
}
@Override
public List<SmsBusinessRulesData> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<SmsBusinessRulesData> smsBusinessRulesDataList = new ArrayList<SmsBusinessRulesData>();
SmsBusinessRulesData smsBusinessRulesData = null;
Map<Long, SmsBusinessRulesData> mapOfSameObjects = new HashMap<Long, SmsBusinessRulesData>();
while (rs.next()) {
final Long id = rs.getLong("id");
smsBusinessRulesData = mapOfSameObjects.get(id);
if (smsBusinessRulesData == null) {
final String reportName = rs.getString("reportName");
final String reportType = rs.getString("reportType");
final String reportSubType = rs.getString("reportSubType");
final String paramName = rs.getString("paramName");
final String paramLabel = rs.getString("paramLabel");
final String description = rs.getString("description");
Map<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put(paramLabel, paramName);
smsBusinessRulesData = SmsBusinessRulesData.instance(id, reportName, reportType, reportSubType, hashMap, description);
mapOfSameObjects.put(id, smsBusinessRulesData);
// add to the list
smsBusinessRulesDataList.add(smsBusinessRulesData);
}
// add new paramType to the existing object
Map<String, Object> hashMap = new HashMap<String, Object>();
final String paramName = rs.getString("paramName");
final String paramLabel = rs.getString("paramLabel");
hashMap.put(paramLabel, paramName);
// get existing map and add new items to it
smsBusinessRulesData.getReportParamName().putAll(hashMap);
}
return smsBusinessRulesDataList;
}
}
private static final class SmsCampaignMapper implements RowMapper<SmsCampaignData> {
final String schema;
private SmsCampaignMapper() {
final StringBuilder sql = new StringBuilder(400);
sql.append("sc.id as id, ");
sql.append("sc.campaign_name as campaignName, ");
sql.append("sc.campaign_type as campaignType, ");
sql.append("sc.campaign_trigger_type as triggerType, ");
sql.append("sc.report_id as runReportId, ");
sql.append("sc.message as message, ");
sql.append("sc.param_value as paramValue, ");
sql.append("sc.status_enum as status, ");
sql.append("sc.recurrence as recurrence, ");
sql.append("sc.recurrence_start_date as recurrenceStartDate, ");
sql.append("sc.next_trigger_date as nextTriggerDate, ");
sql.append("sc.last_trigger_date as lastTriggerDate, ");
sql.append("sc.submittedon_date as submittedOnDate, ");
sql.append("sbu.username as submittedByUsername, ");
sql.append("sc.closedon_date as closedOnDate, ");
sql.append("clu.username as closedByUsername, ");
sql.append("acu.username as activatedByUsername, ");
sql.append("sc.approvedon_date as activatedOnDate, ");
sql.append("sr.report_name as reportName, ");
sql.append("provider_id as providerId, ");
sql.append("sc.is_notification as isNotification ");
sql.append("from sms_campaign sc ");
sql.append("left join m_appuser sbu on sbu.id = sc.submittedon_userid ");
sql.append("left join m_appuser acu on acu.id = sc.approvedon_userid ");
sql.append("left join m_appuser clu on clu.id = sc.closedon_userid ");
sql.append("left join stretchy_report sr on sr.id = sc.report_id ");
this.schema = sql.toString();
}
public String schema() {
return this.schema;
}
@Override
public SmsCampaignData mapRow(ResultSet rs, int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String campaignName = rs.getString("campaignName");
final Integer campaignType = JdbcSupport.getInteger(rs, "campaignType");
final EnumOptionData campaignTypeEnum = CampaignType.campaignType(campaignType);
final Long runReportId = JdbcSupport.getLong(rs, "runReportId");
final String paramValue = rs.getString("paramValue");
final String message = rs.getString("message");
final Integer statusId = JdbcSupport.getInteger(rs, "status");
final EnumOptionData status = SmsCampaignStatusEnumerations.status(statusId);
final Integer triggerType = JdbcSupport.getInteger(rs, "triggerType");
final EnumOptionData triggerTypeEnum = SmsCampaignTriggerType.triggerType(triggerType);
final ZonedDateTime nextTriggerDate = JdbcSupport.getDateTime(rs, "nextTriggerDate");
final LocalDate lastTriggerDate = JdbcSupport.getLocalDate(rs, "lastTriggerDate");
final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate");
final String closedByUsername = rs.getString("closedByUsername");
final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
final String submittedByUsername = rs.getString("submittedByUsername");
final LocalDate activatedOnDate = JdbcSupport.getLocalDate(rs, "activatedOnDate");
final String activatedByUsername = rs.getString("activatedByUsername");
final String recurrence = rs.getString("recurrence");
final ZonedDateTime recurrenceStartDate = JdbcSupport.getDateTime(rs, "recurrenceStartDate");
final SmsCampaignTimeLine smsCampaignTimeLine = new SmsCampaignTimeLine(submittedOnDate, submittedByUsername, activatedOnDate,
activatedByUsername, closedOnDate, closedByUsername);
final String reportName = rs.getString("reportName");
final Long providerId = rs.getLong("providerId");
final Boolean isNotification = rs.getBoolean("isNotification");
return SmsCampaignData.instance(id, campaignName, campaignTypeEnum, triggerTypeEnum, runReportId, reportName, paramValue,
status, message, nextTriggerDate, lastTriggerDate, smsCampaignTimeLine, recurrenceStartDate, recurrence, providerId,
isNotification);
}
}
}
@@ -472,20 +472,14 @@ public class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP
CampaignPreviewData campaignMessage = null;
this.context.authenticatedUser();
this.smsCampaignValidator.validatePreviewMessage(query.json());
// final String smsParams =
// this.fromJsonHelper.extractJsonObjectNamed("paramValue",
// query.parsedJson()).getAsString();
final JsonElement smsParamsElement = this.fromJsonHelper.extractJsonObjectNamed(SmsCampaignValidator.paramValue,
query.parsedJson());
String smsParams = smsParamsElement.toString();
final String textMessageTemplate = this.fromJsonHelper.extractStringNamed("message", query.parsedJson());
try {
HashMap<String, String> campaignParams = new ObjectMapper().readValue(smsParams,
new TypeReference<HashMap<String, String>>() {});
HashMap<String, String> queryParamForRunReport = new ObjectMapper().readValue(smsParams,
new TypeReference<HashMap<String, String>>() {});
HashMap<String, String> campaignParams = new ObjectMapper().readValue(smsParams, new TypeReference<>() {});
HashMap<String, String> queryParamForRunReport = new ObjectMapper().readValue(smsParams, new TypeReference<>() {});
List<HashMap<String, Object>> runReportObject = this.getRunReportByServiceImpl(campaignParams.get("reportName"),
queryParamForRunReport);
@@ -25,8 +25,12 @@ import static org.apache.fineract.infrastructure.hooks.api.HookApiConstants.smsP
import static org.apache.fineract.infrastructure.hooks.api.HookApiConstants.smsProviderTokenIdName;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
import org.apache.fineract.infrastructure.hooks.domain.HookConfiguration;
@Getter
@Setter
public class SmsProviderData {
private String url;
@@ -60,52 +64,4 @@ public class SmsProviderData {
}
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPhoneNumber() {
return phoneNo;
}
public String getSmsProvider() {
return smsProvider;
}
public String getSmsProviderAccountId() {
return smsProviderAccountId;
}
public String getSmsProviderTokenId() {
return smsProviderToken;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
public String getMifosToken() {
return mifosToken;
}
public void setMifosToken(String mifosToken) {
this.mifosToken = mifosToken;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
}
@@ -18,7 +18,11 @@
*/
package org.apache.fineract.infrastructure.sms.api;
import static org.apache.fineract.infrastructure.core.api.DateParam.FROM_DATE_PARAM;
import static org.apache.fineract.infrastructure.core.api.DateParam.TO_DATE_PARAM;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.BeanParam;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
@@ -27,28 +31,24 @@ import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.UriInfo;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.api.DateParam;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.DateFormat;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.sms.data.SmsData;
import org.apache.fineract.infrastructure.sms.data.request.SmsCreationRequest;
import org.apache.fineract.infrastructure.sms.data.request.SmsUpdateRequest;
import org.apache.fineract.infrastructure.sms.param.SmsRequestParam;
import org.apache.fineract.infrastructure.sms.service.SmsReadPlatformService;
import org.springframework.stereotype.Component;
@@ -64,79 +64,57 @@ public class SmsApiResource {
private final PlatformSecurityContext context;
private final SmsReadPlatformService readPlatformService;
private final DefaultToApiJsonSerializer<SmsData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final SqlValidator sqlValidator;
private final DefaultToApiJsonSerializer<String> apiJsonSerializer;
@GET
public String retrieveAll(@Context final UriInfo uriInfo) {
public List<SmsData> retrieveAll() {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final Collection<SmsData> smsMessages = readPlatformService.retrieveAll();
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, smsMessages);
return readPlatformService.retrieveAll();
}
@POST
public String create(final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSms().withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return toApiJsonSerializer.serialize(result);
public CommandProcessingResult create(final SmsCreationRequest smsCreationRequest) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSms()
.withJson(apiJsonSerializer.serialize(smsCreationRequest)).build();
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
@GET
@Path("{resourceId}")
public String retrieveOne(@PathParam("resourceId") final Long resourceId, @Context final UriInfo uriInfo) {
final SmsData smsMessage = readPlatformService.retrieveOne(resourceId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, smsMessage);
public SmsData retrieveOne(@PathParam("resourceId") final Long resourceId) {
return readPlatformService.retrieveOne(resourceId);
}
@GET
@Path("{campaignId}/messageByStatus")
public String retrieveAllSmsByStatus(@PathParam("campaignId") final Long campaignId, @Context final UriInfo uriInfo,
@QueryParam("status") final Long status, @QueryParam("fromDate") final DateParam fromDateParam,
@QueryParam("toDate") final DateParam toDateParam, @QueryParam("locale") final String locale,
@QueryParam("dateFormat") final String rawDateFormat, @QueryParam("offset") final Integer offset,
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
@QueryParam("sortOrder") final String sortOrder) {
public Page<SmsData> retrieveAllSmsByStatus(@PathParam("campaignId") final Long campaignId,
@BeanParam SmsRequestParam smsRequestParam) {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
final SearchParameters searchParameters = SearchParameters.builder().limit(smsRequestParam.limit()).offset(smsRequestParam.offset())
.orderBy(smsRequestParam.orderBy()).sortOrder(smsRequestParam.sortOrder()).build();
final DateFormat dateFormat = StringUtils.isBlank(rawDateFormat) ? null : new DateFormat(rawDateFormat);
final DateFormat dateFormat = Optional.ofNullable(smsRequestParam.rawDateFormat()).map(DateFormat::new).orElse(null);
final LocalDate fromDate = Optional.ofNullable(smsRequestParam.fromDate())
.map(fromDateParam -> fromDateParam.getDate(FROM_DATE_PARAM, dateFormat, smsRequestParam.locale())).orElse(null);
final LocalDate toDate = Optional.ofNullable(smsRequestParam.toDate())
.map(toDateParam -> toDateParam.getDate(TO_DATE_PARAM, dateFormat, smsRequestParam.locale())).orElse(null);
LocalDate fromDate = null;
if (fromDateParam != null) {
fromDate = fromDateParam.getDate("fromDate", dateFormat, locale);
}
LocalDate toDate = null;
if (toDateParam != null) {
toDate = toDateParam.getDate("toDate", dateFormat, locale);
}
final Page<SmsData> smsMessages = readPlatformService.retrieveSmsByStatus(campaignId, searchParameters, status.intValue(), fromDate,
toDate);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, smsMessages);
return readPlatformService.retrieveSmsByStatus(campaignId, searchParameters, smsRequestParam.status().intValue(), fromDate, toDate);
}
@PUT
@Path("{resourceId}")
public String update(@PathParam("resourceId") final Long resourceId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateSms(resourceId).withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return toApiJsonSerializer.serialize(result);
public CommandProcessingResult update(@PathParam("resourceId") final Long resourceId, final SmsUpdateRequest smsUpdateRequest) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateSms(resourceId)
.withJson(apiJsonSerializer.serialize(smsUpdateRequest)).build();
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
@DELETE
@Path("{resourceId}")
public String delete(@PathParam("resourceId") final Long resourceId) {
public CommandProcessingResult delete(@PathParam("resourceId") final Long resourceId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteSms(resourceId).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return toApiJsonSerializer.serialize(result);
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
}
@@ -0,0 +1,28 @@
/**
* 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.sms.data.request;
import java.io.Serial;
import java.io.Serializable;
public record SmsCreationRequest(Long groupId, Long clientId, Long staffId, String message, Long campaignId) implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
}
@@ -0,0 +1,28 @@
/**
* 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.sms.data.request;
import java.io.Serial;
import java.io.Serializable;
public record SmsUpdateRequest(String message) implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
}
@@ -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.sms.param;
import org.apache.fineract.infrastructure.core.api.DateParam;
public record SmsRequestParam(Long status, DateParam fromDate, DateParam toDate, String locale, String rawDateFormat, Integer offset,
Integer limit, String orderBy, String sortOrder) {
}
@@ -19,7 +19,6 @@
package org.apache.fineract.infrastructure.sms.service;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
@@ -27,17 +26,17 @@ import org.apache.fineract.infrastructure.sms.data.SmsData;
public interface SmsReadPlatformService {
Collection<SmsData> retrieveAll();
List<SmsData> retrieveAll();
SmsData retrieveOne(Long resourceId);
Collection<SmsData> retrieveAllPending(Long campaignId, Integer limit);
List<SmsData> retrieveAllPending(Long campaignId, Integer limit);
Collection<SmsData> retrieveAllSent(Integer limit);
List<SmsData> retrieveAllSent(Integer limit);
Collection<SmsData> retrieveAllDelivered(Integer limit);
List<SmsData> retrieveAllDelivered(Integer limit);
Collection<SmsData> retrieveAllFailed(Integer limit);
List<SmsData> retrieveAllFailed(Integer limit);
Page<SmsData> retrieveSmsByStatus(Long campaignId, SearchParameters searchParameters, Integer status, LocalDate dateFrom,
LocalDate dateTo);
@@ -18,12 +18,13 @@
*/
package org.apache.fineract.infrastructure.sms.service;
import jakarta.annotation.PostConstruct;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -31,34 +32,31 @@ import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.infrastructure.sms.data.SmsData;
import org.apache.fineract.infrastructure.sms.domain.SmsMessageEnumerations;
import org.apache.fineract.infrastructure.sms.domain.SmsMessageStatusType;
import org.apache.fineract.infrastructure.sms.exception.SmsNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final DatabaseSpecificSQLGenerator sqlGenerator;
private final SmsMapper smsRowMapper;
private final PaginationHelper paginationHelper;
private final ColumnValidator columnValidator;
private final SqlValidator sqlValidator;
private SmsMapper smsRowMapper;
@Autowired
public SmsReadPlatformServiceImpl(final JdbcTemplate jdbcTemplate, final ColumnValidator columnValidator,
DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) {
this.jdbcTemplate = jdbcTemplate;
this.sqlGenerator = sqlGenerator;
@PostConstruct
public void init() {
this.smsRowMapper = new SmsMapper();
this.columnValidator = columnValidator;
this.paginationHelper = paginationHelper;
}
private static final class SmsMapper implements RowMapper<SmsData> {
@@ -113,7 +111,7 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
}
@Override
public Collection<SmsData> retrieveAll() {
public List<SmsData> retrieveAll() {
final String sql = "select " + this.smsRowMapper.schema();
@@ -131,7 +129,7 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
}
@Override
public Collection<SmsData> retrieveAllPending(final Long campaignId, final Integer limit) {
public List<SmsData> retrieveAllPending(final Long campaignId, final Integer limit) {
final String sqlPlusLimit = limit > 0 ? " " + sqlGenerator.limit(limit) : "";
String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum = " + SmsMessageStatusType.PENDING.getValue();
if (campaignId != null) {
@@ -144,7 +142,7 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
}
@Override
public Collection<SmsData> retrieveAllSent(final Integer limit) {
public List<SmsData> retrieveAllSent(final Integer limit) {
final String sqlPlusLimit = limit > 0 ? " " + sqlGenerator.limit(limit) : "";
final String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum IN ("
+ SmsMessageStatusType.WAITING_FOR_DELIVERY_REPORT.getValue() + "," + SmsMessageStatusType.SENT.getValue() + ")"
@@ -180,7 +178,7 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
}
@Override
public Collection<SmsData> retrieveAllDelivered(final Integer limit) {
public List<SmsData> retrieveAllDelivered(final Integer limit) {
final String sqlPlusLimit = limit > 0 ? " " + sqlGenerator.limit(limit) : "";
final String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum = " + SmsMessageStatusType.DELIVERED.getValue()
+ sqlPlusLimit;
@@ -189,7 +187,7 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
}
@Override
public Collection<SmsData> retrieveAllFailed(final Integer limit) {
public List<SmsData> retrieveAllFailed(final Integer limit) {
final String sqlPlusLimit = limit > 0 ? " " + sqlGenerator.limit(limit) : "";
final String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum = " + SmsMessageStatusType.FAILED.getValue()
+ sqlPlusLimit;
@@ -200,6 +198,9 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
@Override
public Page<SmsData> retrieveSmsByStatus(final Long campaignId, final SearchParameters searchParameters, final Integer status,
final LocalDate dateFrom, final LocalDate dateTo) {
sqlValidator.validate(searchParameters.getOrderBy());
sqlValidator.validate(searchParameters.getSortOrder());
final StringBuilder sqlBuilder = new StringBuilder(200);
final Object[] objectArray = new Object[10];
int arrayPos = 0;