FINERACT-2119: Address jobs by name
This commit is contained in:
committed by
Adam Saghy
parent
eef6a8da5e
commit
3aaa2ffe9c
+1
@@ -54,6 +54,7 @@ public final class SchedulerJobApiConstants {
|
||||
public static final String COMMAND_START_SCHEDULER = "start";
|
||||
public static final String COMMAND = "command";
|
||||
public static final String JOB_ID = "jobId";
|
||||
public static final String SHORT_NAME_PARAM = "short-name";
|
||||
public static final String JOB_RUN_HISTORY = "runhistory";
|
||||
public static final String SCHEDULER_STATUS_PATH = "scheduler";
|
||||
|
||||
|
||||
+106
-32
@@ -18,6 +18,11 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.jobs.api;
|
||||
|
||||
import static org.apache.fineract.infrastructure.jobs.api.SchedulerJobApiConstants.JOB_DETAIL_RESPONSE_DATA_PARAMETERS;
|
||||
import static org.apache.fineract.infrastructure.jobs.api.SchedulerJobApiConstants.JOB_HISTORY_RESPONSE_DATA_PARAMETERS;
|
||||
import static org.apache.fineract.infrastructure.jobs.api.SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME;
|
||||
import static org.apache.fineract.infrastructure.jobs.api.SchedulerJobApiConstants.SHORT_NAME_PARAM;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
@@ -27,6 +32,7 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
@@ -41,12 +47,14 @@ import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
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.IdTypeResolver;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
@@ -88,10 +96,10 @@ public class SchedulerJobApiResource {
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.GetJobsResponse.class)))) })
|
||||
public String retrieveAll(@Context final UriInfo uriInfo) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
|
||||
final List<JobDetailData> jobDetailDatas = this.schedulerJobRunnerReadService.findAllJobDeatils();
|
||||
this.context.authenticatedUser().validateHasReadPermission(SCHEDULER_RESOURCE_NAME);
|
||||
final List<JobDetailData> jobDetailDatas = this.schedulerJobRunnerReadService.findAllJobDetails();
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, jobDetailDatas, SchedulerJobApiConstants.JOB_DETAIL_RESPONSE_DATA_PARAMETERS);
|
||||
return this.toApiJsonSerializer.serialize(settings, jobDetailDatas, JOB_DETAIL_RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -101,10 +109,19 @@ public class SchedulerJobApiResource {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.GetJobsResponse.class))) })
|
||||
public String retrieveOne(@PathParam(SchedulerJobApiConstants.JOB_ID) @Parameter(description = "jobId") final Long jobId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
|
||||
final JobDetailData jobDetailData = this.schedulerJobRunnerReadService.retrieveOne(jobId);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, jobDetailData, SchedulerJobApiConstants.JOB_DETAIL_RESPONSE_DATA_PARAMETERS);
|
||||
return retrieveOne(IdTypeResolver.resolveDefault(), Objects.toString(jobId, null), uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path(SHORT_NAME_PARAM + "/{shortName}")
|
||||
@Operation(summary = "Retrieve a Job", description = "Returns the details of a Job bu shortName.\n" + "\n" + "Example Requests:\n"
|
||||
+ "\n" + "jobs/short-name/SA_PINT")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.GetJobsResponse.class))) })
|
||||
public String retrieveByShortName(
|
||||
@PathParam("shortName") @Parameter(required = true, description = SchedulerJobApiConstants.SHORT_NAME_PARAM) final String shortName,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveOne(IdTypeResolver.resolve(SHORT_NAME_PARAM), shortName, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -118,16 +135,22 @@ public class SchedulerJobApiResource {
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
|
||||
sqlValidator.validate(orderBy);
|
||||
sqlValidator.validate(sortOrder);
|
||||
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
|
||||
.sortOrder(sortOrder).build();
|
||||
final Page<JobDetailHistoryData> jobhistoryDetailData = this.schedulerJobRunnerReadService.retrieveJobHistory(jobId,
|
||||
searchParameters);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.jobHistoryToApiJsonSerializer.serialize(settings, jobhistoryDetailData,
|
||||
SchedulerJobApiConstants.JOB_HISTORY_RESPONSE_DATA_PARAMETERS);
|
||||
return retrieveHistory(IdTypeResolver.resolveDefault(), Objects.toString(jobId, null), offset, limit, orderBy, sortOrder, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path(SHORT_NAME_PARAM + "/{shortName}/" + SchedulerJobApiConstants.JOB_RUN_HISTORY)
|
||||
@Operation(summary = "Retrieve Job Run History", description = "Example Requests:\n" + "\n"
|
||||
+ "jobs/short-name/SA_PINT/runhistory?offset=0&limit=200")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.GetJobsJobIDJobRunHistoryResponse.class))) })
|
||||
public String retrieveHistoryByShortName(@Context final UriInfo uriInfo,
|
||||
@PathParam("shortName") @Parameter(required = true, description = SchedulerJobApiConstants.SHORT_NAME_PARAM) final String shortName,
|
||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
|
||||
return retrieveHistory(IdTypeResolver.resolve(SHORT_NAME_PARAM), shortName, offset, limit, orderBy, sortOrder, uriInfo);
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -138,17 +161,78 @@ public class SchedulerJobApiResource {
|
||||
public Response executeJob(@PathParam(SchedulerJobApiConstants.JOB_ID) @Parameter(description = "jobId") final Long jobId,
|
||||
@QueryParam(SchedulerJobApiConstants.COMMAND) @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
// check the logged in user have permissions to execute scheduler jobs
|
||||
return executeJob(IdTypeResolver.resolveDefault(), Objects.toString(jobId, null), commandParam, jsonRequestBody);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path(SHORT_NAME_PARAM + "/{shortName}")
|
||||
@Operation(summary = "Run a Job", description = "Manually Execute Specific Job.")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.ExecuteJobRequest.class)))
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "POST: jobs/short-name/SA_PINT?command=executeJob") })
|
||||
public Response executeJobByShortName(
|
||||
@PathParam("shortName") @Parameter(required = true, description = SchedulerJobApiConstants.SHORT_NAME_PARAM) final String shortName,
|
||||
@QueryParam(SchedulerJobApiConstants.COMMAND) @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
return executeJob(IdTypeResolver.resolve(SHORT_NAME_PARAM), shortName, commandParam, jsonRequestBody);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{" + SchedulerJobApiConstants.JOB_ID + "}")
|
||||
@Operation(summary = "Update a Job", description = "Updates the details of a job.")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.PutJobsJobIDRequest.class)))
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String updateJobDetail(@PathParam(SchedulerJobApiConstants.JOB_ID) @Parameter(description = "jobId") final Long jobId,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
return updateJobDetail(IdTypeResolver.resolveDefault(), Objects.toString(jobId, null), jsonRequestBody);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path(SHORT_NAME_PARAM + "/{shortName}")
|
||||
@Operation(summary = "Update a Job", description = "Updates the details of a job.")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.PutJobsJobIDRequest.class)))
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String updateJobDetailByShortName(
|
||||
@PathParam("shortName") @Parameter(required = true, description = SchedulerJobApiConstants.SHORT_NAME_PARAM) final String shortName,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
return updateJobDetail(IdTypeResolver.resolve(SHORT_NAME_PARAM), shortName, jsonRequestBody);
|
||||
}
|
||||
|
||||
private boolean is(final String commandParam, final String commandValue) {
|
||||
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
|
||||
}
|
||||
|
||||
private String retrieveOne(@NotNull IdTypeResolver.IdType idType, String identifier, UriInfo uriInfo) {
|
||||
context.authenticatedUser().validateHasReadPermission(SCHEDULER_RESOURCE_NAME);
|
||||
final JobDetailData jobDetailData = schedulerJobRunnerReadService.retrieveOne(idType, identifier);
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return toApiJsonSerializer.serialize(settings, jobDetailData, JOB_DETAIL_RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
private String retrieveHistory(@NotNull IdTypeResolver.IdType idType, String identifier, Integer offset, Integer limit, String orderBy,
|
||||
String sortOrder, UriInfo uriInfo) {
|
||||
context.authenticatedUser().validateHasReadPermission(SCHEDULER_RESOURCE_NAME);
|
||||
sqlValidator.validate(orderBy);
|
||||
sqlValidator.validate(sortOrder);
|
||||
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
|
||||
.sortOrder(sortOrder).build();
|
||||
final Page<JobDetailHistoryData> jobHistoryData = schedulerJobRunnerReadService.retrieveJobHistory(idType, identifier,
|
||||
searchParameters);
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return jobHistoryToApiJsonSerializer.serialize(settings, jobHistoryData, JOB_HISTORY_RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
private Response executeJob(@NotNull IdTypeResolver.IdType idType, String identifier, String commandParam, String jsonRequestBody) {
|
||||
// check the logged-in user have permissions to execute scheduler jobs
|
||||
Response response;
|
||||
if (fineractProperties.getMode().isBatchManagerEnabled()) {
|
||||
final boolean hasNotPermission = this.context.authenticatedUser().hasNotPermissionForAnyOf("ALL_FUNCTIONS",
|
||||
"EXECUTEJOB_SCHEDULER");
|
||||
final boolean hasNotPermission = context.authenticatedUser().hasNotPermissionForAnyOf("ALL_FUNCTIONS", "EXECUTEJOB_SCHEDULER");
|
||||
if (hasNotPermission) {
|
||||
final String authorizationMessage = "User has no authority to execute scheduler jobs";
|
||||
throw new NoAuthorizationException(authorizationMessage);
|
||||
}
|
||||
response = Response.status(400).build();
|
||||
if (is(commandParam, SchedulerJobApiConstants.COMMAND_EXECUTE_JOB)) {
|
||||
Long jobId = schedulerJobRunnerReadService.retrieveId(idType, identifier);
|
||||
jobRegisterService.executeJobWithParameters(jobId, jsonRequestBody);
|
||||
response = Response.status(202).build();
|
||||
} else {
|
||||
@@ -161,14 +245,8 @@ public class SchedulerJobApiResource {
|
||||
return response;
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{" + SchedulerJobApiConstants.JOB_ID + "}")
|
||||
@Operation(summary = "Update a Job", description = "Updates the details of a job.")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = SchedulerJobApiResourceSwagger.PutJobsJobIDRequest.class)))
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String updateJobDetail(@PathParam(SchedulerJobApiConstants.JOB_ID) @Parameter(description = "jobId") final Long jobId,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
|
||||
private String updateJobDetail(@NotNull IdTypeResolver.IdType idType, String identifier, String jsonRequestBody) {
|
||||
Long jobId = schedulerJobRunnerReadService.retrieveId(idType, identifier);
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
|
||||
.updateJobDetail(jobId) //
|
||||
.withJson(jsonRequestBody) //
|
||||
@@ -180,8 +258,4 @@ public class SchedulerJobApiResource {
|
||||
}
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
private boolean is(final String commandParam, final String commandValue) {
|
||||
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -44,6 +44,8 @@ final class SchedulerJobApiResourceSwagger {
|
||||
public Long jobId;
|
||||
@Schema(example = "Update loan Summary")
|
||||
public String displayName;
|
||||
@Schema(example = "LA_USUM")
|
||||
public String shortName;
|
||||
@Schema(example = "")
|
||||
public Date nextRunTime;
|
||||
@Schema(example = "")
|
||||
|
||||
+5
-1
@@ -23,6 +23,7 @@ import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -36,7 +37,7 @@ import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.jobs.api.SchedulerJobApiConstants;
|
||||
|
||||
@Entity
|
||||
@Table(name = "job")
|
||||
@Table(name = "job", uniqueConstraints = { @UniqueConstraint(columnNames = { "short_name" }, name = "job_short_name_key") })
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@@ -97,6 +98,9 @@ public class ScheduledJobDetail extends AbstractPersistableCustom<Long> {
|
||||
@Column(name = "is_misfired")
|
||||
private boolean triggerMisfired;
|
||||
|
||||
@Column(name = "short_name", nullable = false)
|
||||
private String shortName;
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||
|
||||
|
||||
+20
@@ -20,6 +20,8 @@ package org.apache.fineract.infrastructure.jobs.domain;
|
||||
|
||||
import jakarta.persistence.LockModeType;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.apache.fineract.infrastructure.jobs.data.JobDetailData;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Lock;
|
||||
@@ -47,4 +49,22 @@ public interface ScheduledJobDetailRepository
|
||||
|
||||
ScheduledJobDetail findByJobName(String jobName);
|
||||
|
||||
String GET_DATA = "select new org.apache.fineract.infrastructure.jobs.data.JobDetailData(j.id, j.jobDisplayName, j.shortName, j.nextRunTime, "
|
||||
+ "j.errorLog, j.cronExpression, j.activeSchedular, j.currentlyRunning, "
|
||||
+ "jh.version, jh.startTime, jh.endTime, jh.status, jh.errorMessage, jh.triggerType, jh.errorLog) "
|
||||
+ "from ScheduledJobDetail j left join ScheduledJobRunHistory jh on jh.scheduledJobDetail = j and j.previousRunStartTime = jh.startTime ";
|
||||
|
||||
@Query(GET_DATA + "where j.id = :jobId")
|
||||
JobDetailData getDataById(@Param("jobId") Long jobId);
|
||||
|
||||
@Query(GET_DATA + "where j.shortName = :shortName")
|
||||
JobDetailData getDataByShortName(@Param("shortName") String shortName);
|
||||
|
||||
@Query(GET_DATA + "order by j.id")
|
||||
List<JobDetailData> getAllData();
|
||||
|
||||
boolean existsByShortName(String shortName);
|
||||
|
||||
@Query("select j.id from ScheduledJobDetail j where j.shortName = :shortName")
|
||||
Optional<Long> findIdByShortName(@Param("shortName") String shortName);
|
||||
}
|
||||
|
||||
+5
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.jobs.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.IdTypeResolver;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
import org.springframework.batch.core.launch.NoSuchJobException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
@@ -31,6 +32,10 @@ public class JobNotFoundException extends AbstractPlatformResourceNotFoundExcept
|
||||
super("error.msg.sheduler.job.id.invalid", "Job with identifier " + identifier + " does not exist", identifier);
|
||||
}
|
||||
|
||||
public JobNotFoundException(IdTypeResolver.IdType idType, String jobId) {
|
||||
super("error.msg.sheduler.job.id.invalid", String.format("Job with %s: %s cannot be found", idType, jobId), idType, jobId);
|
||||
}
|
||||
|
||||
public JobNotFoundException(final String identifier, NoSuchJobException e) {
|
||||
super("error.msg.sheduler.job.id.invalid", "Job with identifier " + identifier + " does not exist", identifier, e);
|
||||
}
|
||||
|
||||
+63
-107
@@ -18,22 +18,24 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.jobs.service;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.api.IdTypeResolver;
|
||||
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.jobs.data.JobDetailData;
|
||||
import org.apache.fineract.infrastructure.jobs.data.JobDetailHistoryData;
|
||||
import org.apache.fineract.infrastructure.jobs.domain.ScheduledJobDetailRepository;
|
||||
import org.apache.fineract.infrastructure.jobs.exception.JobNotFoundException;
|
||||
import org.apache.fineract.infrastructure.jobs.exception.OperationNotAllowedException;
|
||||
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
|
||||
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;
|
||||
@@ -47,59 +49,62 @@ public class SchedulerJobRunnerReadServiceImpl implements SchedulerJobRunnerRead
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final ColumnValidator columnValidator;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
private final ScheduledJobDetailRepository jobDetailRepository;
|
||||
|
||||
private final PaginationHelper paginationHelper;
|
||||
|
||||
@Autowired
|
||||
public SchedulerJobRunnerReadServiceImpl(final JdbcTemplate jdbcTemplate, final ColumnValidator columnValidator,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) {
|
||||
DatabaseSpecificSQLGenerator sqlGenerator, ScheduledJobDetailRepository jobDetailRepository,
|
||||
PaginationHelper paginationHelper) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.columnValidator = columnValidator;
|
||||
this.sqlGenerator = sqlGenerator;
|
||||
this.jobDetailRepository = jobDetailRepository;
|
||||
this.paginationHelper = paginationHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JobDetailData> findAllJobDeatils() {
|
||||
final JobDetailMapper detailMapper = new JobDetailMapper(sqlGenerator);
|
||||
final String sql = detailMapper.schema();
|
||||
final List<JobDetailData> JobDeatils = this.jdbcTemplate.query(sql, detailMapper, new Object[] {});
|
||||
return JobDeatils;
|
||||
public List<JobDetailData> findAllJobDetails() {
|
||||
return jobDetailRepository.getAllData();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobDetailData retrieveOne(final Long jobId) {
|
||||
try {
|
||||
final JobDetailMapper detailMapper = new JobDetailMapper(sqlGenerator);
|
||||
final String sql = detailMapper.schema() + " where job.id=?";
|
||||
return this.jdbcTemplate.queryForObject(sql, detailMapper, new Object[] { jobId }); // NOSONAR
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new JobNotFoundException(String.valueOf(jobId), e);
|
||||
public JobDetailData retrieveOne(@NotNull IdTypeResolver.IdType idType, String identifier) {
|
||||
JobDetailData jobDetail = switch (idType) {
|
||||
case ID -> jobDetailRepository.getDataById(Long.valueOf(identifier));
|
||||
case SHORT_NAME -> jobDetailRepository.getDataByShortName(identifier);
|
||||
default -> null;
|
||||
};
|
||||
if (jobDetail == null) {
|
||||
throw new JobNotFoundException(idType, identifier);
|
||||
}
|
||||
return jobDetail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobDetailData retrieveOneByName(String jobName) {
|
||||
try {
|
||||
final JobDetailMapper detailMapper = new JobDetailMapper(sqlGenerator);
|
||||
final String sql = detailMapper.schema() + " where job.name=?";
|
||||
return this.jdbcTemplate.queryForObject(sql, detailMapper, new Object[] { jobName }); // NOSONAR
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new JobNotFoundException(jobName, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<JobDetailHistoryData> retrieveJobHistory(final Long jobId, final SearchParameters searchParameters) {
|
||||
if (!isJobExist(jobId)) {
|
||||
throw new JobNotFoundException(String.valueOf(jobId));
|
||||
public Page<JobDetailHistoryData> retrieveJobHistory(@NotNull IdTypeResolver.IdType idType, String identifier,
|
||||
SearchParameters searchParameters) {
|
||||
if (!isJobExist(idType, identifier)) {
|
||||
throw new JobNotFoundException(idType, identifier);
|
||||
}
|
||||
final JobHistoryMapper jobHistoryMapper = new JobHistoryMapper(sqlGenerator);
|
||||
final StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " ");
|
||||
sqlBuilder.append(jobHistoryMapper.schema());
|
||||
sqlBuilder.append(" where job.id=?");
|
||||
final StringBuilder sqlBuilder = new StringBuilder("select " + sqlGenerator.calcFoundRows() + " ").append(jobHistoryMapper.schema())
|
||||
.append(" where job.");
|
||||
Object idParam;
|
||||
switch (idType) {
|
||||
case ID -> {
|
||||
sqlBuilder.append("id");
|
||||
idParam = Long.valueOf(identifier);
|
||||
}
|
||||
case SHORT_NAME -> {
|
||||
sqlBuilder.append("short_name");
|
||||
idParam = identifier;
|
||||
}
|
||||
default -> throw new JobNotFoundException(idType, identifier);
|
||||
}
|
||||
sqlBuilder.append(" = ?");
|
||||
if (searchParameters.hasOrderBy()) {
|
||||
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
|
||||
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
|
||||
@@ -118,7 +123,18 @@ public class SchedulerJobRunnerReadServiceImpl implements SchedulerJobRunnerRead
|
||||
}
|
||||
}
|
||||
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlBuilder.toString(), new Object[] { jobId }, jobHistoryMapper);
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlBuilder.toString(), new Object[] { idParam }, jobHistoryMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Long retrieveId(@NotNull IdTypeResolver.IdType idType, String identifier) {
|
||||
return switch (idType) {
|
||||
case ID -> Long.valueOf(identifier);
|
||||
case SHORT_NAME ->
|
||||
jobDetailRepository.findIdByShortName(identifier).orElseThrow(() -> new JobNotFoundException(idType, identifier));
|
||||
default -> throw new JobNotFoundException(idType, identifier);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,84 +149,27 @@ public class SchedulerJobRunnerReadServiceImpl implements SchedulerJobRunnerRead
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isJobExist(final Long jobId) {
|
||||
boolean isJobPresent = false;
|
||||
try {
|
||||
final String sql = "select count(*) from job job where job.id= ?";
|
||||
final int count = this.jdbcTemplate.queryForObject(sql, Integer.class, new Object[] { jobId });
|
||||
if (count == 1) {
|
||||
isJobPresent = true;
|
||||
}
|
||||
return isJobPresent;
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
return isJobPresent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class JobDetailMapper implements RowMapper<JobDetailData> {
|
||||
|
||||
private final StringBuilder sqlBuilder;
|
||||
|
||||
JobDetailMapper(DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
sqlBuilder = new StringBuilder("select").append(
|
||||
" job.id,job.display_name as displayName,job.next_run_time as nextRunTime,job.initializing_errorlog as initializingError,job.cron_expression as cronExpression,job.is_active as active,job.currently_running as currentlyRunning,")
|
||||
.append(" runHistory.version,runHistory.start_time as lastRunStartTime,runHistory.end_time as lastRunEndTime,runHistory.")
|
||||
.append(sqlGenerator.escape("status"))
|
||||
.append(",runHistory.error_message as jobRunErrorMessage,runHistory.trigger_type as triggerType,runHistory.error_log as jobRunErrorLog ")
|
||||
.append(" from job job left join job_run_history runHistory ON job.id=runHistory.job_id and job.previous_run_start_time=runHistory.start_time ");
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.sqlBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobDetailData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = rs.getLong("id");
|
||||
final String displayName = rs.getString("displayName");
|
||||
final Date nextRunTime = rs.getTimestamp("nextRunTime");
|
||||
final String initializingError = rs.getString("initializingError");
|
||||
final String cronExpression = rs.getString("cronExpression");
|
||||
final boolean active = rs.getBoolean("active");
|
||||
final boolean currentlyRunning = rs.getBoolean("currentlyRunning");
|
||||
|
||||
final Long version = rs.getLong("version");
|
||||
final Date jobRunStartTime = rs.getTimestamp("lastRunStartTime");
|
||||
final Date jobRunEndTime = rs.getTimestamp("lastRunEndTime");
|
||||
final String status = rs.getString("status");
|
||||
final String jobRunErrorMessage = rs.getString("jobRunErrorMessage");
|
||||
final String triggerType = rs.getString("triggerType");
|
||||
final String jobRunErrorLog = rs.getString("jobRunErrorLog");
|
||||
|
||||
JobDetailHistoryData lastRunHistory = null;
|
||||
if (version > 0) {
|
||||
lastRunHistory = new JobDetailHistoryData().setVersion(version).setJobRunStartTime(jobRunStartTime)
|
||||
.setJobRunEndTime(jobRunEndTime).setStatus(status).setJobRunErrorMessage(jobRunErrorMessage)
|
||||
.setTriggerType(triggerType).setJobRunErrorLog(jobRunErrorLog);
|
||||
}
|
||||
final JobDetailData jobDetail = new JobDetailData().setJobId(id).setDisplayName(displayName).setNextRunTime(nextRunTime)
|
||||
.setInitializingError(initializingError).setCronExpression(cronExpression).setActive(active)
|
||||
.setCurrentlyRunning(currentlyRunning).setLastRunHistory(lastRunHistory);
|
||||
return jobDetail;
|
||||
}
|
||||
|
||||
private boolean isJobExist(@NotNull IdTypeResolver.IdType idType, @NotNull String jobId) {
|
||||
return switch (idType) {
|
||||
case ID -> jobDetailRepository.existsById(Long.valueOf(jobId));
|
||||
case SHORT_NAME -> jobDetailRepository.existsByShortName(jobId);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static final class JobHistoryMapper implements RowMapper<JobDetailHistoryData> {
|
||||
|
||||
private final StringBuilder sqlBuilder;
|
||||
private final String sql;
|
||||
|
||||
JobHistoryMapper(DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
sqlBuilder = new StringBuilder(200)
|
||||
.append(" runHistory.version,runHistory.start_time as runStartTime,runHistory.end_time as runEndTime,runHistory."
|
||||
+ sqlGenerator.escape("status")
|
||||
+ ",runHistory.error_message as jobRunErrorMessage,runHistory.trigger_type as triggerType,runHistory.error_log as jobRunErrorLog ")
|
||||
.append(" from job job join job_run_history runHistory ON job.id=runHistory.job_id");
|
||||
sql = " runHistory.version, runHistory.start_time as runStartTime, runHistory.end_time as runEndTime, " + "runHistory."
|
||||
+ sqlGenerator.escape("status")
|
||||
+ ", runHistory.error_message as jobRunErrorMessage, runHistory.trigger_type as triggerType, runHistory.error_log as jobRunErrorLog "
|
||||
+ "from job job join job_run_history runHistory ON job.id=runHistory.job_id";
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.sqlBuilder.toString();
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,12 +181,9 @@ public class SchedulerJobRunnerReadServiceImpl implements SchedulerJobRunnerRead
|
||||
final String jobRunErrorMessage = rs.getString("jobRunErrorMessage");
|
||||
final String triggerType = rs.getString("triggerType");
|
||||
final String jobRunErrorLog = rs.getString("jobRunErrorLog");
|
||||
final JobDetailHistoryData jobDetailHistory = new JobDetailHistoryData().setVersion(version).setJobRunStartTime(jobRunStartTime)
|
||||
.setJobRunEndTime(jobRunEndTime).setStatus(status).setJobRunErrorMessage(jobRunErrorMessage).setTriggerType(triggerType)
|
||||
return new JobDetailHistoryData().setVersion(version).setJobRunStartTime(jobRunStartTime).setJobRunEndTime(jobRunEndTime)
|
||||
.setStatus(status).setJobRunErrorMessage(jobRunErrorMessage).setTriggerType(triggerType)
|
||||
.setJobRunErrorLog(jobRunErrorLog);
|
||||
return jobDetailHistory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
<include file="tenant-store/changelog-tenant-store.xml" relativeToChangelogFile="true" context="tenant_store_db AND !initial_switch"/>
|
||||
<include file="tenant/initial-switch-changelog-tenant.xml" relativeToChangelogFile="true" context="tenant_db AND initial_switch"/>
|
||||
<include file="tenant/changelog-tenant.xml" relativeToChangelogFile="true" context="tenant_db AND !initial_switch"/>
|
||||
<includeAll path="db/changelog/tenant/module" errorIfMissingOrEmpty="false" context="tenant_db AND custom_changelog" filter="org.apache.fineract.infrastructure.core.service.migration.TenantModuleRootFilter" />
|
||||
<includeAll path="db/custom-changelog" errorIfMissingOrEmpty="false" context="tenant_db AND custom_changelog" />
|
||||
<!-- Add new module to the end of this modules list (to keep the existing auto-increment identifiers) -->
|
||||
<include file="db/changelog/tenant/module/loan/module-changelog-master.xml" context="tenant_db AND !initial_switch"/>
|
||||
<include file="db/changelog/tenant/module/investor/module-changelog-master.xml" context="tenant_db AND !initial_switch"/>
|
||||
<includeAll path="db/custom-changelog" errorIfMissingOrEmpty="false" context="tenant_db AND !initial_switch AND custom_changelog"/>
|
||||
<!-- Scripts to run after the modules were initialized -->
|
||||
<include file="tenant/final-changelog-tenant.xml" relativeToChangelogFile="true" context="tenant_db AND !initial_switch"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -164,4 +164,5 @@
|
||||
<include file="parts/0142_add_accrual_activity_transaction.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/0143_add_accrual_activity_posting_job.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/0144_transaction_summary_with_asset_owner_report_unc_allocation_fix.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/0145_job_short_name.xml" relativeToChangelogFile="true" />
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<include file="parts/0146_add_final_constraints.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1">
|
||||
<addColumn tableName="job">
|
||||
<column name="short_name" type="VARCHAR(8)">
|
||||
<constraints unique="true" nullable="true"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="2">
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_USUM"/>
|
||||
<where>name='Update loan Summary'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_ARAG"/>
|
||||
<where>name='Update Loan Arrears Ageing'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_PIAD"/>
|
||||
<where>name='Update Loan Paid In Advance'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_AHOL"/>
|
||||
<where>name='Apply Holidays To Loans'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_TFFS"/>
|
||||
<where>name='Transfer Fee For Loans From Savings'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_OPEN"/>
|
||||
<where>name='Apply penalty to overdue loans'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_UNPA"/>
|
||||
<where>name='Update Non Performing Assets'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_RINT"/>
|
||||
<where>name='Recalculate Interest For Loans'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_GLPR"/>
|
||||
<where>name='Generate Loan Loss Provisioning'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_AATR"/>
|
||||
<where>name='Add Accrual Transactions For Loans With Income Posted As Transactions'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_ECOB"/>
|
||||
<where>name='Loan COB'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="LA_DECL"/>
|
||||
<where>name='Loan Delinquency Classification'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SA_AANF"/>
|
||||
<where>name='Apply Annual Fee For Savings'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SA_PINT"/>
|
||||
<where>name='Post Interest For Savings'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SA_PDCH"/>
|
||||
<where>name='Pay Due Savings Charges'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SA_TINT"/>
|
||||
<where>name='Transfer Interest To Savings'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SA_MATD"/>
|
||||
<where>name='Update Deposit Accounts Maturity details'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SA_GSCH"/>
|
||||
<where>name='Generate Mandatory Savings Schedule'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SA_UDOR"/>
|
||||
<where>name='Update Savings Dormant Accounts'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SH_PDIV"/>
|
||||
<where>name='Post Dividends For Shares'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="ACC_RBAL"/>
|
||||
<where>name='Update Accounting Running Balances'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="ACC_AATR"/>
|
||||
<where>name='Add Accrual Transactions'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="ACC_APTR"/>
|
||||
<where>name='Add Periodic Accrual Transactions'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="STI_EXEC"/>
|
||||
<where>name='Execute Standing Instruction'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="RMJ_EXEC"/>
|
||||
<where>name='Execute Report Mailing Jobs'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="EM_EXEC"/>
|
||||
<where>name='Execute Email'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="EM_UOUT"/>
|
||||
<where>name='Update Email Outbound with campaign message'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SMS_UOUT"/>
|
||||
<where>name='Update SMS Outbound with Campaign Message'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SMS_SMSG"/>
|
||||
<where>name='Send Messages to SMS Gateway'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="SMS_DRPT"/>
|
||||
<where>name='Get Delivery Reports from SMS Gateway'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="ADH_GSCH"/>
|
||||
<where>name='Generate AdhocClient Schedule'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="TBL_UDET"/>
|
||||
<where>name='Update Trial Balance Details'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="JOB_EXEC"/>
|
||||
<where>name='Execute All Dirty Jobs'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="BDT_INC1"/>
|
||||
<where>name='Increase Business Date by 1 day'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="BDT_INC1"/>
|
||||
<where>name='Increase Business Date by 1 day'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="BDT_COB1"/>
|
||||
<where>name='Increase COB Date by 1 day'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="ASE_SEND"/>
|
||||
<where>name='Send Asynchronous Events'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="EXE_PURG"/>
|
||||
<where>name='Purge External Events'</where>
|
||||
</update>
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="COM_PURG"/>
|
||||
<where>name='Purge Processed Commands'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="3">
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="ACC_ACPO"/>
|
||||
<where>name='Accrual Activity Posting'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1" context="postgresql">
|
||||
<addNotNullConstraint tableName="job" columnName="short_name"/>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="2" context="mysql">
|
||||
<addNotNullConstraint tableName="job" columnName="short_name" columnDataType="VARCHAR(8)"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user