diff --git a/mifosng-db/patches/patch-0013-loan_officer_reassignment_history.sql b/mifosng-db/patches/patch-0012-loan_officer_reassignment_history.sql similarity index 100% rename from mifosng-db/patches/patch-0013-loan_officer_reassignment_history.sql rename to mifosng-db/patches/patch-0012-loan_officer_reassignment_history.sql diff --git a/mifosng-db/patches/patch-0013-maker-checker.sql b/mifosng-db/patches/patch-0013-maker-checker.sql new file mode 100644 index 000000000..80a9b58ec --- /dev/null +++ b/mifosng-db/patches/patch-0013-maker-checker.sql @@ -0,0 +1,15 @@ +drop table `m_maker_checker`; +CREATE TABLE `m_maker_checker` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `task_name` varchar(100) NOT NULL, + `task_json` varchar(1000) NOT NULL, + `maker_id` bigint(20) NOT NULL, + `made_on_date` date NOT NULL, + `checker_id` bigint(20) DEFAULT NULL, + `checked_on_date` date DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `FK_m_maker_m_appuser` (`maker_id`), + KEY `FK_m_checker_m_appuser` (`checker_id`), + CONSTRAINT `FK_m_maker_m_appuser` FOREIGN KEY (`maker_id`) REFERENCES `m_appuser` (`id`), + CONSTRAINT `FK_m_checker_m_appuser` FOREIGN KEY (`checker_id`) REFERENCES `m_appuser` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java index df41163e8..3b18edc30 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientsApiResource.java @@ -40,6 +40,7 @@ import org.mifosng.platform.common.FileUtils; import org.mifosng.platform.exceptions.ClientNotFoundException; import org.mifosng.platform.exceptions.ImageNotFoundException; import org.mifosng.platform.infrastructure.api.ApiParameterHelper; +import org.mifosng.platform.makerchecker.service.PortfolioMakerCheckerService; import org.mifosng.platform.organisation.service.OfficeReadPlatformService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,6 +68,9 @@ public class ClientsApiResource { @Autowired private PortfolioApiDataConversionService apiDataConversionService; + + @Autowired + private PortfolioMakerCheckerService portfolioMakerCheckerService; @Autowired private OfficeReadPlatformService officeReadPlatformService; @@ -192,37 +196,47 @@ public class ClientsApiResource { @POST @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response enrollClient(final String jsonRequestBody) { - - ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, jsonRequestBody); + public String enrollClient(final String jsonRequestBody) { - Long clientId = this.clientWritePlatformService.enrollClient(command); - - return Response.ok().entity(new EntityIdentifier(clientId)).build(); + String jsonResult = ""; + // hardcode to false before checking in until configuration for enabling is done. + final boolean makerCheckerEnabledForTask = false; + if (makerCheckerEnabledForTask) { + final Long makerCheckerId = this.portfolioMakerCheckerService.logNewEntry("CREATE_CLIENT", jsonRequestBody); + jsonResult = this.apiJsonSerializerService.serializeEntityIdentifier(EntityIdentifier.makerChecker(makerCheckerId)); + } else { + final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, jsonRequestBody); + + final Long clientId = this.clientWritePlatformService.enrollClient(command); + + jsonResult = this.apiJsonSerializerService.serializeEntityIdentifier(new EntityIdentifier(clientId)); + } + + return jsonResult; } @PUT @Path("{clientId}") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response updateClient(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { + public String updateClient(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { - ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(clientId, jsonRequestBody); + final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(clientId, jsonRequestBody); - EntityIdentifier identifier = this.clientWritePlatformService.updateClientDetails(command); + final EntityIdentifier identifier = this.clientWritePlatformService.updateClientDetails(command); - return Response.ok().entity(identifier).build(); + return this.apiJsonSerializerService.serializeEntityIdentifier(identifier); } @DELETE @Path("{clientId}") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response deleteClient(@PathParam("clientId") final Long clientId) { + public String deleteClient(@PathParam("clientId") final Long clientId) { this.clientWritePlatformService.deleteClient(clientId); - return Response.ok(new EntityIdentifier(clientId)).build(); + return this.apiJsonSerializerService.serializeEntityIdentifier(new EntityIdentifier(clientId)); } @GET diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java index 911b3f1ab..f3f2018b0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ClientData.java @@ -150,8 +150,4 @@ public class ClientData { public void setImagePresent(boolean imagePresent) { this.imagePresent = imagePresent; } - - - - } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/EntityIdentifier.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/EntityIdentifier.java index 1a00a820a..e1f74e41c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/EntityIdentifier.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/EntityIdentifier.java @@ -1,10 +1,18 @@ package org.mifosng.platform.api.data; - +/** + * Represents the successful result of an REST API call. + */ public class EntityIdentifier { private Long entityId; + @SuppressWarnings("unused") + private Long makerCheckerId; + public static EntityIdentifier makerChecker(final Long makerCheckerId) { + return new EntityIdentifier(null, makerCheckerId); + } + public EntityIdentifier() { // } @@ -12,6 +20,11 @@ public class EntityIdentifier { public EntityIdentifier(final Long entityId) { this.entityId = entityId; } + + private EntityIdentifier(final Long entityId, final Long makerCheckerId) { + this.entityId = entityId; + this.makerCheckerId = makerCheckerId; + } public Long getEntityId() { return this.entityId; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerChecker.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerChecker.java new file mode 100644 index 000000000..c727555e6 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerChecker.java @@ -0,0 +1,67 @@ +package org.mifosng.platform.makerchecker.domain; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.LocalDate; +import org.mifosng.platform.user.domain.AppUser; +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_maker_checker") +public class MakerChecker extends AbstractPersistable { + + @Column(name = "task_name", length = 100) + private String taskName; + + @Column(name = "task_json", length = 1000) + private String taskJson; + + // should maker and checker be a staff member as opposed to just any application user? + @ManyToOne + @JoinColumn(name = "maker_id", nullable = false) + private AppUser maker; + + @Column(name = "made_on_date", nullable = false) + @Temporal(TemporalType.DATE) + private Date madeOnDate; + + @ManyToOne + @JoinColumn(name = "checker_id", nullable = true) + private AppUser checker; + + @Column(name = "checked_on_date", nullable = false) + @Temporal(TemporalType.DATE) + private Date checkedOnDate; + + public static MakerChecker makerEntry( + final String taskName, + final String jsonRequestBody, + final AppUser maker, + final LocalDate madeOnDate) { + return new MakerChecker(taskName, jsonRequestBody, maker, madeOnDate); + } + + protected MakerChecker() { + // + } + + private MakerChecker( + final String taskName, + final String taskJson, + final AppUser maker, + final LocalDate madeOnDate) { + this.taskName = StringUtils.defaultIfEmpty(taskName, null); + this.taskJson = StringUtils.defaultIfEmpty(taskJson, null); + this.maker = maker; + this.madeOnDate = madeOnDate.toDate(); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerCheckerRepository.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerCheckerRepository.java new file mode 100644 index 000000000..e8a59475e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/domain/MakerCheckerRepository.java @@ -0,0 +1,10 @@ +package org.mifosng.platform.makerchecker.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface MakerCheckerRepository extends + JpaRepository, + JpaSpecificationExecutor { + // no added behaviour +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerService.java new file mode 100644 index 000000000..24c203b7c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerService.java @@ -0,0 +1,7 @@ +package org.mifosng.platform.makerchecker.service; + +public interface PortfolioMakerCheckerService { + + Long logNewEntry(String taskName, String taskJson); + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerServiceImpl.java new file mode 100644 index 000000000..81ab185a8 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/makerchecker/service/PortfolioMakerCheckerServiceImpl.java @@ -0,0 +1,37 @@ +package org.mifosng.platform.makerchecker.service; + +import org.joda.time.LocalDate; +import org.mifosng.platform.makerchecker.domain.MakerChecker; +import org.mifosng.platform.makerchecker.domain.MakerCheckerRepository; +import org.mifosng.platform.security.PlatformSecurityContext; +import org.mifosng.platform.user.domain.AppUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + */ +@Service +public class PortfolioMakerCheckerServiceImpl implements PortfolioMakerCheckerService { + + private final PlatformSecurityContext context; + private final MakerCheckerRepository makerCheckerRepository; + + @Autowired + public PortfolioMakerCheckerServiceImpl(final PlatformSecurityContext context, final MakerCheckerRepository makerCheckerRepository) { + this.context = context; + this.makerCheckerRepository = makerCheckerRepository; + } + + @Override + public Long logNewEntry(final String taskName, final String taskJson) { + + final AppUser maker = context.authenticatedUser(); + + final MakerChecker entity = MakerChecker.makerEntry(taskName, taskJson, maker, new LocalDate()); + + makerCheckerRepository.save(entity); + + return entity.getId(); + } +} \ No newline at end of file