diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientTest.java index 3351cd230..843f75db2 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientTest.java @@ -65,5 +65,71 @@ public class ClientTest { ClientStatusChecker.verifyClientWithdrawn(clientStatusHashMap); } + + @Test + public void testClientAsPersonStatus() { + + this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); + final Integer clientId = ClientHelper.createClientAsPerson(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientId); + + HashMap status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); + ClientStatusChecker.verifyClientIsActive(status); + + HashMap clientStatusHashMap = this.clientHelper.closeClient(clientId); + ClientStatusChecker.verifyClientClosed(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.reactivateClient(clientId); + ClientStatusChecker.verifyClientPending(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.rejectClient(clientId); + ClientStatusChecker.verifyClientRejected(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.activateClient(clientId); + ClientStatusChecker.verifyClientActiavted(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.closeClient(clientId); + ClientStatusChecker.verifyClientClosed(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.reactivateClient(clientId); + ClientStatusChecker.verifyClientPending(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.withdrawClient(clientId); + ClientStatusChecker.verifyClientWithdrawn(clientStatusHashMap); + + } + + @Test + public void testClientAsEntityStatus() { + + this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); + final Integer clientId = ClientHelper.createClientAsEntity(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientId); + + HashMap status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); + ClientStatusChecker.verifyClientIsActive(status); + + HashMap clientStatusHashMap = this.clientHelper.closeClient(clientId); + ClientStatusChecker.verifyClientClosed(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.reactivateClient(clientId); + ClientStatusChecker.verifyClientPending(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.rejectClient(clientId); + ClientStatusChecker.verifyClientRejected(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.activateClient(clientId); + ClientStatusChecker.verifyClientActiavted(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.closeClient(clientId); + ClientStatusChecker.verifyClientClosed(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.reactivateClient(clientId); + ClientStatusChecker.verifyClientPending(clientStatusHashMap); + + clientStatusHashMap = this.clientHelper.withdrawClient(clientId); + ClientStatusChecker.verifyClientWithdrawn(clientStatusHashMap); + + } } diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java index b5bccd7dd..e57b745e6 100755 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ClientHelper.java @@ -9,6 +9,7 @@ import static org.junit.Assert.assertEquals; import java.util.HashMap; +import org.mifosplatform.infrastructure.codes.domain.CodeValue; import org.mifosplatform.integrationtests.common.system.CodeHelper; import com.google.gson.Gson; @@ -55,6 +56,43 @@ public class ClientHelper { return Utils.performServerPost(requestSpec, responseSpec, CREATE_CLIENT_URL, getTestClientAsJSON(activationDate, officeId), "clientId"); } + + public static Integer createClientAsPerson(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + return createClientAsPerson(requestSpec, responseSpec, "04 March 2011"); + } + + public static Integer createClientAsPerson(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String activationDate) { + return createClientAsPerson(requestSpec, responseSpec, activationDate, "1"); + } + + public static Integer createClientAsPerson(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String activationDate, final String officeId) { + + System.out.println("---------------------------------CREATING A CLIENT NON PERSON(ORGANISATION)---------------------------------------------"); + return Utils.performServerPost(requestSpec, responseSpec, CREATE_CLIENT_URL, getTestPersonClientAsJSON(activationDate, officeId), + "clientId"); + } + + public static Integer createClientAsEntity(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + return createClientAsEntity(requestSpec, responseSpec, "04 March 2011"); + } + + public static Integer createClientAsEntity(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String activationDate) { + return createClientAsEntity(requestSpec, responseSpec, activationDate, "1"); + } + + public static Integer createClientAsEntity(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String activationDate, final String officeId) { + + Integer constitutionCodeId = (Integer) CodeHelper.getCodeByName(requestSpec, responseSpec, "Constitution").get("id"); + Integer soleProprietorCodeValueId = (Integer) CodeHelper.retrieveOrCreateCodeValue(constitutionCodeId, requestSpec, responseSpec).get("id"); + + System.out.println("---------------------------------CREATING A CLIENT NON PERSON(ORGANISATION)---------------------------------------------"); + return Utils.performServerPost(requestSpec, responseSpec, CREATE_CLIENT_URL, getTestEntityClientAsJSON(activationDate, officeId, soleProprietorCodeValueId), + "clientId"); + } public static Integer createClientForAccountPreference(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer clientType, String jsonAttributeToGetBack) { @@ -93,6 +131,40 @@ public class ClientHelper { System.out.println("map : " + map); return new Gson().toJson(map); } + + public static String getTestPersonClientAsJSON(final String dateOfJoining, final String officeId) { + final HashMap map = new HashMap<>(); + map.put("officeId", officeId); + map.put("fullname", Utils.randomNameGenerator("Client_FullName_", 5)); + map.put("externalId", randomIDGenerator("ID_", 7)); + map.put("dateFormat", DATE_FORMAT); + map.put("locale", "en"); + map.put("active", "true"); + map.put("activationDate", dateOfJoining); + map.put("legalFormId", 1); + + System.out.println("map : " + map); + return new Gson().toJson(map); + } + + public static String getTestEntityClientAsJSON(final String dateOfJoining, final String officeId, final Integer soleProprietorCodeValueId) { + final HashMap map = new HashMap<>(); + map.put("officeId", officeId); + map.put("fullname", Utils.randomNameGenerator("Client_FullName_", 5)); + map.put("externalId", randomIDGenerator("ID_", 7)); + map.put("dateFormat", DATE_FORMAT); + map.put("locale", "en"); + map.put("active", "true"); + map.put("activationDate", dateOfJoining); + map.put("legalFormId", 2); + + final HashMap clientNonPersonMap = new HashMap<>(); + clientNonPersonMap.put("constitutionId", soleProprietorCodeValueId); + map.put("clientNonPersonDetails", clientNonPersonMap); + + System.out.println("map : " + map); + return new Gson().toJson(map); + } public static String getTestClientWithClientTypeAsJSON(final String dateOfJoining, final String officeId, final String clientType) { final HashMap map = new HashMap<>(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java index 01f68f974..078f0a02f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java @@ -39,6 +39,10 @@ public class Code extends AbstractPersistable { final String name = command.stringValueOfParameterNamed("name"); return new Code(name); } + + public static Code createNew(final String name) { + return new Code(name); + } protected Code() { this.systemDefined = false; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java index 6541a2fae..212d09222 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientApiConstants.java @@ -48,9 +48,15 @@ public class ClientApiConstants { public static final String GENDER = "Gender"; public static final String CLIENT_TYPE = "ClientType"; public static final String CLIENT_CLASSIFICATION = "ClientClassification"; + + public static final String CLIENT_NON_PERSON_CONSTITUTION = "Constitution"; + public static final String CLIENT_NON_PERSON_MAIN_BUSINESS_LINE = "Main Business Line"; + // general public static final String localeParamName = "locale"; public static final String dateFormatParamName = "dateFormat"; + + public static final String CLIENT_TYPE_INDIVIDUAL = "Individual"; // request parameters public static final String idParamName = "id"; @@ -62,6 +68,7 @@ public class ClientApiConstants { public static final String middlenameParamName = "middlename"; public static final String lastnameParamName = "lastname"; public static final String fullnameParamName = "fullname"; + public static final String displaynameParamName = "displayname"; public static final String officeIdParamName = "officeId"; public static final String transferOfficeIdParamName = "transferOfficeIdParamName"; public static final String activeParamName = "active"; @@ -86,6 +93,8 @@ public class ClientApiConstants { public static final String clientTypeParamName = "clientType"; public static final String clientClassificationIdParamName = "clientClassificationId"; public static final String clientClassificationParamName = "clientClassification"; + public static final String legalFormIdParamName = "legalFormId"; + public static final String legalFormParamName = "legalForm"; // request parameters for payment details public static final String paymentTypeIdParamName = "paymentTypeId"; public static final String transactionAccountNumberParamName = "accountNumber"; @@ -93,6 +102,15 @@ public class ClientApiConstants { public static final String routingCodeParamName = "routingCode"; public static final String receiptNumberParamName = "receiptNumber"; public static final String bankNumberParamName = "bankNumber"; + + //request parameters for client non person + public static final String clientNonPersonDetailsParamName = "clientNonPersonDetails"; + public static final String incorpNumberParamName = "incorpNumber"; + public static final String remarksParamName = "remarks"; + public static final String incorpValidityTillParamName = "incorpValidityTillDate"; + public static final String constitutionIdParamName = "constitutionId"; + public static final String mainBusinessLineIdParamName = "mainBusinessLineId"; + // response parameters public static final String statusParamName = "status"; @@ -147,13 +165,23 @@ public class ClientApiConstants { Arrays.asList(localeParamName, dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName, mobileNoParamName, firstnameParamName, middlenameParamName, lastnameParamName, fullnameParamName, officeIdParamName, activeParamName, activationDateParamName, staffIdParamName, submittedOnDateParamName, savingsProductIdParamName, - dateOfBirthParamName, genderIdParamName, clientTypeIdParamName, clientClassificationIdParamName)); + dateOfBirthParamName, genderIdParamName, clientTypeIdParamName, clientClassificationIdParamName, + clientNonPersonDetailsParamName, displaynameParamName, legalFormIdParamName)); + + public static final Set CLIENT_NON_PERSON_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>( + Arrays.asList(localeParamName, dateFormatParamName, incorpNumberParamName, remarksParamName, incorpValidityTillParamName, + constitutionIdParamName, mainBusinessLineIdParamName)); public static final Set CLIENT_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, dateFormatParamName, accountNoParamName, externalIdParamName, mobileNoParamName, firstnameParamName, middlenameParamName, lastnameParamName, fullnameParamName, activeParamName, activationDateParamName, staffIdParamName, savingsProductIdParamName, - dateOfBirthParamName, genderIdParamName, clientTypeIdParamName, clientClassificationIdParamName, submittedOnDateParamName)); + dateOfBirthParamName, genderIdParamName, clientTypeIdParamName, clientClassificationIdParamName, submittedOnDateParamName, + clientNonPersonDetailsParamName, displaynameParamName, legalFormIdParamName)); + + public static final Set CLIENT_NON_PERSON_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, + dateFormatParamName, incorpNumberParamName, remarksParamName, incorpValidityTillParamName, + constitutionIdParamName, mainBusinessLineIdParamName)); /** * These parameters will match the class level parameters of @@ -165,7 +193,8 @@ public class ClientApiConstants { lastnameParamName, fullnameParamName, displayNameParamName, mobileNoParamName, officeIdParamName, officeNameParamName, transferToOfficeIdParamName, transferToOfficeNameParamName, hierarchyParamName, imageIdParamName, imagePresentParamName, staffIdParamName, staffNameParamName, timelineParamName, groupsParamName, officeOptionsParamName, staffOptionsParamName, - dateOfBirthParamName, genderParamName, clientTypeParamName, clientClassificationParamName)); + dateOfBirthParamName, genderParamName, clientTypeParamName, clientClassificationParamName, legalFormParamName, + clientNonPersonDetailsParamName)); public static final Set ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<>( Arrays.asList(localeParamName, dateFormatParamName, activationDateParamName)); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java index 3777276bf..06dab2395 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientData.java @@ -6,6 +6,7 @@ package org.mifosplatform.portfolio.client.data; import java.util.Collection; +import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.CompareToBuilder; @@ -62,6 +63,7 @@ final public class ClientData implements Comparable { private final String savingsProductName; private final Long savingsAccountId; + private final EnumOptionData legalForm; // associations private final Collection groups; @@ -74,12 +76,19 @@ final public class ClientData implements Comparable { private final Collection savingAccountOptions; private final Collection genderOptions; private final Collection clientTypeOptions; - private final Collection clientClassificationOptions; + private final Collection clientClassificationOptions; + private final Collection clientNonPersonConstitutionOptions; + private final Collection clientNonPersonMainBusinessLineOptions; + private final List clientLegalFormOptions; + + private final ClientNonPersonData clientNonPersonDetails; public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection officeOptions, final Collection staffOptions, final Collection narrations, final Collection genderOptions, final Collection savingProductOptions, - final Collection clientTypeOptions, final Collection clientClassificationOptions) { + final Collection clientTypeOptions, final Collection clientClassificationOptions, + final Collection clientNonPersonConstitutionOptions, final Collection clientNonPersonMainBusinessLineOptions, + final List clientLegalFormOptions) { final String accountNo = null; final EnumOptionData status = null; final CodeValueData subStatus = null; @@ -107,11 +116,14 @@ final public class ClientData implements Comparable { final Collection savingAccountOptions = null; final CodeValueData clientType = null; final CodeValueData clientClassification = null; + final EnumOptionData legalForm = null; + final ClientNonPersonData clientNonPersonDetails = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, joinedDate, imageId, staffId, staffName, officeOptions, groups, staffOptions, narrations, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, - clientTypeOptions, clientClassificationOptions); + clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, + clientNonPersonDetails, clientLegalFormOptions, legalForm); } @@ -124,7 +136,9 @@ final public class ClientData implements Comparable { clientData.staffName, templateData.officeOptions, clientData.groups, templateData.staffOptions, templateData.narrations, templateData.genderOptions, clientData.timeline, templateData.savingProductOptions, clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, clientData.savingAccountOptions, clientData.clientType, - clientData.clientClassification, templateData.clientTypeOptions, templateData.clientClassificationOptions); + clientData.clientClassification, templateData.clientTypeOptions, templateData.clientClassificationOptions, + templateData.clientNonPersonConstitutionOptions, templateData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, + templateData.clientLegalFormOptions, clientData.legalForm); } @@ -138,7 +152,9 @@ final public class ClientData implements Comparable { clientData.staffName, clientData.officeOptions, clientData.groups, clientData.staffOptions, clientData.narrations, clientData.genderOptions, clientData.timeline, clientData.savingProductOptions, clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, savingAccountOptions, clientData.clientType, - clientData.clientClassification, clientData.clientTypeOptions, clientData.clientClassificationOptions); + clientData.clientClassification, clientData.clientTypeOptions, clientData.clientClassificationOptions, + clientData.clientNonPersonConstitutionOptions, clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, + clientData.clientLegalFormOptions, clientData.legalForm); } @@ -150,7 +166,8 @@ final public class ClientData implements Comparable { clientData.staffName, clientData.officeOptions, parentGroups, clientData.staffOptions, null, null, clientData.timeline, clientData.savingProductOptions, clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, clientData.savingAccountOptions, clientData.clientType, clientData.clientClassification, clientData.clientTypeOptions, - clientData.clientClassificationOptions); + clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions, clientData.clientNonPersonMainBusinessLineOptions, + clientData.clientNonPersonDetails, clientData.clientLegalFormOptions, clientData.legalForm); } @@ -182,13 +199,19 @@ final public class ClientData implements Comparable { final CodeValueData clientClassification = null; final Collection clientTypeOptions = null; final Collection clientClassificationOptions = null; + final Collection clientNonPersonConstitutionOptions = null; + final Collection clientNonPersonMainBusinessLineOptions = null; + final List clientLegalFormOptions = null; final EnumOptionData status = null; final CodeValueData subStatus = null; + final EnumOptionData legalForm = null; + final ClientNonPersonData clientNonPerson = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, activationDate, imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, - clientTypeOptions, clientClassificationOptions); + clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, + clientNonPerson, clientLegalFormOptions, legalForm); } public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) { @@ -224,11 +247,17 @@ final public class ClientData implements Comparable { final CodeValueData clientClassification = null; final Collection clientTypeOptions = null; final Collection clientClassificationOptions = null; + final Collection clientNonPersonConstitutionOptions = null; + final Collection clientNonPersonMainBusinessLineOptions = null; + final List clientLegalFormOptions = null; + final EnumOptionData legalForm = null; + final ClientNonPersonData clientNonPerson = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, activationDate, imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, - clientTypeOptions, clientClassificationOptions); + clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, + clientNonPerson, clientLegalFormOptions, legalForm); } @@ -238,7 +267,7 @@ final public class ClientData implements Comparable { final String externalId, final String mobileNo, final LocalDate dateOfBirth, final CodeValueData gender, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName, final ClientTimelineData timeline, final Long savingsProductId, final String savingsProductName, final Long savingsAccountId, - final CodeValueData clientType, final CodeValueData clientClassification) { + final CodeValueData clientType, final CodeValueData clientClassification, final EnumOptionData legalForm, final ClientNonPersonData clientNonPerson) { final Collection allowedOffices = null; final Collection groups = null; @@ -248,11 +277,15 @@ final public class ClientData implements Comparable { final Collection savingProductOptions = null; final Collection clientTypeOptions = null; final Collection clientClassificationOptions = null; + final Collection clientNonPersonConstitutionOptions = null; + final Collection clientNonPersonMainBusinessLineOptions = null; + final List clientLegalFormOptions = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, activationDate, imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, null, clientType, clientClassification, clientTypeOptions, - clientClassificationOptions); + clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientNonPerson, + clientLegalFormOptions, legalForm); } @@ -267,7 +300,9 @@ final public class ClientData implements Comparable { final Collection savingProductOptions, final Long savingsProductId, final String savingsProductName, final Long savingsAccountId, final Collection savingAccountOptions, final CodeValueData clientType, final CodeValueData clientClassification, final Collection clientTypeOptions, - final Collection clientClassificationOptions) { + final Collection clientClassificationOptions, final Collection clientNonPersonConstitutionOptions, + final Collection clientNonPersonMainBusinessLineOptions, final ClientNonPersonData clientNonPerson, + final List clientLegalFormOptions, final EnumOptionData legalForm) { this.accountNo = accountNo; this.status = status; if (status != null) { @@ -313,6 +348,10 @@ final public class ClientData implements Comparable { this.genderOptions = genderOptions; this.clientClassificationOptions = clientClassificationOptions; this.clientTypeOptions = clientTypeOptions; + + this.clientNonPersonConstitutionOptions = clientNonPersonConstitutionOptions; + this.clientNonPersonMainBusinessLineOptions = clientNonPersonMainBusinessLineOptions; + this.clientLegalFormOptions = clientLegalFormOptions; this.timeline = timeline; this.savingProductOptions = savingProductOptions; @@ -320,6 +359,8 @@ final public class ClientData implements Comparable { this.savingsProductName = savingsProductName; this.savingsAccountId = savingsAccountId; this.savingAccountOptions = savingAccountOptions; + this.legalForm = legalForm; + this.clientNonPersonDetails = clientNonPerson; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java index b44ef65f4..862c7c815 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java @@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.client.data; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -46,7 +47,13 @@ public final class ClientDataValidator { final Type typeOfMap = new TypeToken>() {}.getType(); this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_CREATE_REQUEST_DATA_PARAMETERS); final JsonElement element = this.fromApiJsonHelper.parse(json); - + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.clientNonPersonDetailsParamName, element)) { + final String clientNonPersonJson = this.fromApiJsonHelper.toJson(element.getAsJsonObject().get(ClientApiConstants.clientNonPersonDetailsParamName)); + if(clientNonPersonJson != null) + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, clientNonPersonJson, ClientApiConstants.CLIENT_NON_PERSON_CREATE_REQUEST_DATA_PARAMETERS); + } + final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) @@ -168,8 +175,57 @@ public final class ClientDataValidator { baseDataValidator.reset().parameter(ClientApiConstants.clientClassificationIdParamName).value(clientClassification) .integerGreaterThanZero(); } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.legalFormIdParamName, element)) { + final Integer legalFormId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.legalFormIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.legalFormIdParamName).value(legalFormId).ignoreIfNull().inMinMaxRange(1, 2); + } + + List dataValidationErrorsForClientNonPerson = getDataValidationErrorsForCreateOnClientNonPerson(element.getAsJsonObject().get(ClientApiConstants.clientNonPersonDetailsParamName)); + dataValidationErrors.addAll(dataValidationErrorsForClientNonPerson); + throwExceptionIfValidationWarningsExist(dataValidationErrors); } + + List getDataValidationErrorsForCreateOnClientNonPerson(JsonElement element) + { + + final List dataValidationErrors = new ArrayList<>(); + + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource(ClientApiConstants.CLIENT_RESOURCE_NAME); + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.incorpNumberParamName, element)) { + final String incorpNumber = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.incorpNumberParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.incorpNumberParamName).value(incorpNumber).ignoreIfNull() + .notExceedingLengthOf(50); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.remarksParamName, element)) { + final String remarks = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.remarksParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.remarksParamName).value(remarks).ignoreIfNull() + .notExceedingLengthOf(150); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.incorpValidityTillParamName, element)) { + final LocalDate incorpValidityTill = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.incorpValidityTillParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.incorpValidityTillParamName).value(incorpValidityTill).ignoreIfNull(); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.constitutionIdParamName, element)) { + final Integer constitution = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.constitutionIdParamName, + element); + baseDataValidator.reset().parameter(ClientApiConstants.constitutionIdParamName).value(constitution).notNull().integerGreaterThanZero(); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.mainBusinessLineIdParamName, element)) { + final Integer mainBusinessLine = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.mainBusinessLineIdParamName, + element); + baseDataValidator.reset().parameter(ClientApiConstants.mainBusinessLineIdParamName).value(mainBusinessLine).integerGreaterThanZero(); + } + + return dataValidationErrors; + } private void validateIndividualNamePartsCannotBeUsedWithFullname(final JsonElement element, final DataValidatorBuilder baseDataValidator) { final String firstnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element); @@ -243,7 +299,13 @@ public final class ClientDataValidator { final Type typeOfMap = new TypeToken>() {}.getType(); this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_UPDATE_REQUEST_DATA_PARAMETERS); final JsonElement element = this.fromApiJsonHelper.parse(json); - + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.clientNonPersonDetailsParamName, element)) { + final String clientNonPersonJson = this.fromApiJsonHelper.toJson(element.getAsJsonObject().get(ClientApiConstants.clientNonPersonDetailsParamName)); + if(clientNonPersonJson != null) + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, clientNonPersonJson, ClientApiConstants.CLIENT_NON_PERSON_UPDATE_REQUEST_DATA_PARAMETERS); + } + final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) @@ -379,14 +441,73 @@ public final class ClientDataValidator { baseDataValidator.reset().parameter(ClientApiConstants.submittedOnDateParamName).value(submittedDate).notNull(); } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.legalFormIdParamName, element)) { + atLeastOneParameterPassedForUpdate = true; + final Integer legalFormId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.legalFormIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.legalFormIdParamName).value(legalFormId).ignoreIfNull().inMinMaxRange(1, 2); + } - if (!atLeastOneParameterPassedForUpdate) { + Map parameterUpdateStatusDetails = getParameterUpdateStatusAndDataValidationErrorsForUpdateOnClientNonPerson(element.getAsJsonObject().get(ClientApiConstants.clientNonPersonDetailsParamName)); + boolean atLeastOneParameterPassedForClientNonPersonUpdate = (boolean) parameterUpdateStatusDetails.get("parameterUpdateStatus"); + + if (!atLeastOneParameterPassedForUpdate && !atLeastOneParameterPassedForClientNonPersonUpdate) { final Object forceError = null; baseDataValidator.reset().anyOfNotNull(forceError); } - + + @SuppressWarnings("unchecked") + List dataValidationErrorsForClientNonPerson = (List) parameterUpdateStatusDetails.get("dataValidationErrors"); + dataValidationErrors.addAll(dataValidationErrorsForClientNonPerson); + throwExceptionIfValidationWarningsExist(dataValidationErrors); } + + Map getParameterUpdateStatusAndDataValidationErrorsForUpdateOnClientNonPerson(JsonElement element) + { + boolean atLeastOneParameterPassedForUpdate = false; + final List dataValidationErrors = new ArrayList<>(); + + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource(ClientApiConstants.CLIENT_RESOURCE_NAME); + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.incorpNumberParamName, element)) { + atLeastOneParameterPassedForUpdate = true; + final String incorpNo = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.incorpNumberParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.incorpNumberParamName).value(incorpNo).ignoreIfNull().notExceedingLengthOf(50); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.remarksParamName, element)) { + atLeastOneParameterPassedForUpdate = true; + final String remarks = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.remarksParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.remarksParamName).value(remarks).notExceedingLengthOf(150); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.incorpValidityTillParamName, element)) { + atLeastOneParameterPassedForUpdate = true; + final LocalDate incorpValidityTill = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.incorpValidityTillParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.incorpValidityTillParamName).value(incorpValidityTill); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.constitutionIdParamName, element)) { + atLeastOneParameterPassedForUpdate = true; + final Integer constitutionId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.constitutionIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.constitutionIdParamName).value(constitutionId).notNull().integerGreaterThanZero(); + } + + if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.mainBusinessLineIdParamName, element)) { + atLeastOneParameterPassedForUpdate = true; + final Integer mainBusinessLineId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.mainBusinessLineIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.mainBusinessLineIdParamName).value(mainBusinessLineId).integerGreaterThanZero(); + } + + Map parameterUpdateStatusDetails = new HashMap<>(); + parameterUpdateStatusDetails.put("parameterUpdateStatus", atLeastOneParameterPassedForUpdate); + parameterUpdateStatusDetails.put("dataValidationErrors", dataValidationErrors); + + return parameterUpdateStatusDetails; + + } public void validateActivation(final JsonCommand command) { final String json = command.json(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientNonPersonData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientNonPersonData.java new file mode 100644 index 000000000..28398b558 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientNonPersonData.java @@ -0,0 +1,33 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.data; + +import org.joda.time.LocalDate; +import org.mifosplatform.infrastructure.codes.data.CodeValueData; + +/** + * Immutable data object representing the ClientNonPerson + */ +@SuppressWarnings("unused") +public class ClientNonPersonData { + + private final CodeValueData constitution; + private final String incorpNumber; + private final LocalDate incorpValidityTillDate; + private final CodeValueData mainBusinessLine; + private final String remarks; + + public ClientNonPersonData(CodeValueData constitution, String incorpNo, LocalDate incorpValidityTillDate, + CodeValueData mainBusinessLine, String remarks) { + super(); + this.constitution = constitution; + this.incorpNumber = incorpNo; + this.incorpValidityTillDate = incorpValidityTillDate; + this.mainBusinessLine = mainBusinessLine; + this.remarks = remarks; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java index 146752e51..13223e4fc 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java @@ -88,16 +88,16 @@ public final class Client extends AbstractPersistable { @Temporal(TemporalType.DATE) private Date officeJoiningDate; - @Column(name = "firstname", length = 50) + @Column(name = "firstname", length = 50, nullable = true) private String firstname; - @Column(name = "middlename", length = 50) + @Column(name = "middlename", length = 50, nullable = true) private String middlename; - @Column(name = "lastname", length = 50) + @Column(name = "lastname", length = 50, nullable = true) private String lastname; - @Column(name = "fullname", length = 100) + @Column(name = "fullname", length = 100, nullable = true) private String fullname; @Column(name = "display_name", length = 100, nullable = false) @@ -208,10 +208,13 @@ public final class Client extends AbstractPersistable { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "client_classification_cv_id", nullable = true) private CodeValue clientClassification; + + @Column(name = "legal_form_enum", nullable = true) + private Integer legalForm; public static Client createNew(final AppUser currentUser, final Office clientOffice, final Group clientParentGroup, final Staff staff, final SavingsProduct savingsProduct, final CodeValue gender, final CodeValue clientType, final CodeValue clientClassification, - final JsonCommand command) { + final Integer legalForm, final JsonCommand command) { final String accountNo = command.stringValueOfParameterNamed(ClientApiConstants.accountNoParamName); final String externalId = command.stringValueOfParameterNamed(ClientApiConstants.externalIdParamName); @@ -248,18 +251,18 @@ public final class Client extends AbstractPersistable { final SavingsAccount account = null; return new Client(currentUser, status, clientOffice, clientParentGroup, accountNo, firstname, middlename, lastname, fullname, activationDate, officeJoiningDate, externalId, mobileNo, staff, submittedOnDate, savingsProduct, account, dataOfBirth, - gender, clientType, clientClassification); + gender, clientType, clientClassification, legalForm); } protected Client() { - // + this.setLegalForm(null); } private Client(final AppUser currentUser, final ClientStatus status, final Office office, final Group clientParentGroup, final String accountNo, final String firstname, final String middlename, final String lastname, final String fullname, final LocalDate activationDate, final LocalDate officeJoiningDate, final String externalId, final String mobileNo, final Staff staff, final LocalDate submittedOnDate, final SavingsProduct savingsProduct, final SavingsAccount savingsAccount, - final LocalDate dateOfBirth, final CodeValue gender, final CodeValue clientType, final CodeValue clientClassification) { + final LocalDate dateOfBirth, final CodeValue gender, final CodeValue clientType, final CodeValue clientClassification, final Integer legalForm) { if (StringUtils.isBlank(accountNo)) { this.accountNumber = new RandomPasswordGenerator(19).generate(); @@ -333,6 +336,7 @@ public final class Client extends AbstractPersistable { } this.clientType = clientType; this.clientClassification = clientClassification; + this.setLegalForm(legalForm); deriveDisplayName(); validate(); @@ -346,6 +350,16 @@ public final class Client extends AbstractPersistable { if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } + + private void validateUpdate() { + final List dataValidationErrors = new ArrayList<>(); + //Not validating name parts while update request as firstname/lastname can be along with fullname + //when we change clientType from Individual to Organisation or vice-cersa + validateActivationDate(dataValidationErrors); + + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } + + } public boolean isAccountNumberRequiresAutoGeneration() { return this.accountNumberRequiresAutoGeneration; @@ -506,6 +520,29 @@ public final class Client extends AbstractPersistable { final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.clientClassificationIdParamName); actualChanges.put(ClientApiConstants.clientClassificationIdParamName, newValue); } + + if (command.isChangeInIntegerParameterNamed(ClientApiConstants.legalFormIdParamName, this.getLegalForm())) { + final Integer newValue = command.integerValueOfParameterNamed(ClientApiConstants.legalFormIdParamName); + if(newValue != null) + { + LegalForm legalForm = LegalForm.fromInt(newValue); + if(legalForm != null) + { + actualChanges.put(ClientApiConstants.legalFormIdParamName, ClientEnumerations.legalForm(newValue)); + this.setLegalForm(legalForm.getValue()); + } + else + { + actualChanges.put(ClientApiConstants.legalFormIdParamName, null); + this.setLegalForm(null); + } + } + else + { + actualChanges.put(ClientApiConstants.legalFormIdParamName, null); + this.setLegalForm(null); + } + } final String dateFormatAsInput = command.dateFormat(); final String localeAsInput = command.locale(); @@ -541,7 +578,7 @@ public final class Client extends AbstractPersistable { this.submittedOnDate = newValue.toDate(); } - validate(); + validateUpdate(); deriveDisplayName(); @@ -615,22 +652,28 @@ public final class Client extends AbstractPersistable { private void deriveDisplayName() { StringBuilder nameBuilder = new StringBuilder(); - if (StringUtils.isNotBlank(this.firstname)) { - nameBuilder.append(this.firstname).append(' '); - } + Integer legalForm = this.getLegalForm(); + if(legalForm == null || LegalForm.fromInt(legalForm).isPerson()) + { + if (StringUtils.isNotBlank(this.firstname)) { + nameBuilder.append(this.firstname).append(' '); + } - if (StringUtils.isNotBlank(this.middlename)) { - nameBuilder.append(this.middlename).append(' '); - } + if (StringUtils.isNotBlank(this.middlename)) { + nameBuilder.append(this.middlename).append(' '); + } - if (StringUtils.isNotBlank(this.lastname)) { - nameBuilder.append(this.lastname); + if (StringUtils.isNotBlank(this.lastname)) { + nameBuilder.append(this.lastname); + } } - - if (StringUtils.isNotBlank(this.fullname)) { - nameBuilder = new StringBuilder(this.fullname); + else if(LegalForm.fromInt(legalForm).isEntity()) + { + if (StringUtils.isNotBlank(this.fullname)) { + nameBuilder = new StringBuilder(this.fullname); + } } - + this.displayName = nameBuilder.toString(); } @@ -896,4 +939,12 @@ public final class Client extends AbstractPersistable { this.status = ClientStatus.PENDING.getValue(); } + + public Integer getLegalForm() { + return legalForm; + } + + public void setLegalForm(Integer legalForm) { + this.legalForm = legalForm; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java index ea7b52448..5442598a7 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientEnumerations.java @@ -53,6 +53,24 @@ public class ClientEnumerations { return optionData; } + + public static EnumOptionData legalForm(final Integer statusId) { + return legalForm(LegalForm.fromInt(statusId)); + } + + public static EnumOptionData legalForm(final LegalForm legalForm) { + final EnumOptionData optionData = new EnumOptionData(legalForm.getValue().longValue(), legalForm.getCode(), + legalForm.toString()); + return optionData; + } + + public static List legalForm(final LegalForm[] legalForms) { + final List optionDatas = new ArrayList<>(); + for (final LegalForm legalForm : legalForms) { + optionDatas.add(legalForm(legalForm)); + } + return optionDatas; + } public static EnumOptionData clientTransactionType(final int id) { return clientTransactionType(ClientTransactionType.fromInt(id)); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPerson.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPerson.java new file mode 100644 index 000000000..f23a53fb2 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPerson.java @@ -0,0 +1,195 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.domain; + +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.LocalDate; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.mifosplatform.infrastructure.codes.domain.CodeValue; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; +import org.mifosplatform.portfolio.client.api.ClientApiConstants; +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_client_non_person") +public class ClientNonPerson extends AbstractPersistable { + + @OneToOne(optional = false) + @JoinColumn(name = "client_id", referencedColumnName = "id", nullable = false, unique = true) + private Client client; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "constitution_cv_id", nullable = false) + private CodeValue constitution; + + @Column(name = "incorp_no", length = 50, nullable = true) + private String incorpNumber; + + @Column(name = "incorp_validity_till", nullable = true) + @Temporal(TemporalType.DATE) + private Date incorpValidityTill; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "main_business_line_cv_id", nullable = true) + private CodeValue mainBusinessLine; + + @Column(name = "remarks", length = 150, nullable = true) + private String remarks; + + + public static ClientNonPerson createNew(final Client client, final CodeValue constitution, final CodeValue mainBusinessLine, String incorpNumber, LocalDate incorpValidityTill, String remarks) + { + return new ClientNonPerson(client, constitution, mainBusinessLine, incorpNumber, incorpValidityTill, remarks); + } + + protected ClientNonPerson() { + // + } + + private ClientNonPerson(final Client client, final CodeValue constitution, final CodeValue mainBusinessLine, final String incorpNumber, final LocalDate incorpValidityTill, final String remarks) + { + if(client != null) + this.client = client; + + if(constitution != null) + this.constitution = constitution; + + if(mainBusinessLine != null) + this.mainBusinessLine = mainBusinessLine; + + if (StringUtils.isNotBlank(incorpNumber)) { + this.incorpNumber = incorpNumber.trim(); + } else { + this.incorpNumber = null; + } + + if (incorpValidityTill != null) { + this.incorpValidityTill = incorpValidityTill.toDateTimeAtStartOfDay().toDate(); + } + + if (StringUtils.isNotBlank(remarks)) { + this.remarks = remarks.trim(); + } else { + this.remarks = null; + } + + validate(client); + } + + private void validate(final Client client) { + final List dataValidationErrors = new ArrayList<>(); + validateIncorpValidityTillDate(client, dataValidationErrors); + + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } + + } + + private void validateIncorpValidityTillDate(final Client client, final List dataValidationErrors) { + if (getIncorpValidityTillLocalDate() != null && client.dateOfBirthLocalDate() != null && client.dateOfBirthLocalDate().isAfter(getIncorpValidityTillLocalDate())) { + + final String defaultUserMessage = "incorpvaliditytill date cannot be after the incorporation date"; + final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.incorpValidityTill.after.incorp.date", + defaultUserMessage, ClientApiConstants.incorpValidityTillParamName, this.incorpValidityTill); + + dataValidationErrors.add(error); + } + } + + public LocalDate getIncorpValidityTillLocalDate() { + LocalDate incorpValidityTillLocalDate = null; + if (this.incorpValidityTill != null) { + incorpValidityTillLocalDate = LocalDate.fromDateFields(this.incorpValidityTill); + } + return incorpValidityTillLocalDate; + } + + public Long constitutionId() { + Long constitutionId = null; + if (this.constitution != null) { + constitutionId = this.constitution.getId(); + } + return constitutionId; + } + + public Long mainBusinessLineId() { + Long mainBusinessLineId = null; + if (this.mainBusinessLine != null) { + mainBusinessLineId = this.mainBusinessLine.getId(); + } + return mainBusinessLineId; + } + + public void updateConstitution(CodeValue constitution) { + this.constitution = constitution; + } + + public void updateMainBusinessLine(CodeValue mainBusinessLine) { + this.mainBusinessLine = mainBusinessLine; + } + + public Map update(final JsonCommand command) { + + final Map actualChanges = new LinkedHashMap<>(9); + + if (command.isChangeInStringParameterNamed(ClientApiConstants.incorpNumberParamName, this.incorpNumber)) { + final String newValue = command.stringValueOfParameterNamed(ClientApiConstants.incorpNumberParamName); + actualChanges.put(ClientApiConstants.incorpNumberParamName, newValue); + this.incorpNumber = StringUtils.defaultIfEmpty(newValue, null); + } + + if (command.isChangeInStringParameterNamed(ClientApiConstants.remarksParamName, this.remarks)) { + final String newValue = command.stringValueOfParameterNamed(ClientApiConstants.remarksParamName); + actualChanges.put(ClientApiConstants.remarksParamName, newValue); + this.remarks = StringUtils.defaultIfEmpty(newValue, null); + } + + final String dateFormatAsInput = command.dateFormat(); + final String localeAsInput = command.locale(); + + if (command.isChangeInLocalDateParameterNamed(ClientApiConstants.incorpValidityTillParamName, getIncorpValidityTillLocalDate())) { + final String valueAsInput = command.stringValueOfParameterNamed(ClientApiConstants.incorpValidityTillParamName); + actualChanges.put(ClientApiConstants.incorpValidityTillParamName, valueAsInput); + actualChanges.put(ClientApiConstants.dateFormatParamName, dateFormatAsInput); + actualChanges.put(ClientApiConstants.localeParamName, localeAsInput); + + final LocalDate newValue = command.localDateValueOfParameterNamed(ClientApiConstants.incorpValidityTillParamName); + this.incorpValidityTill = newValue.toDate(); + } + + if (command.isChangeInLongParameterNamed(ClientApiConstants.constitutionIdParamName, constitutionId())) { + final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.constitutionIdParamName); + actualChanges.put(ClientApiConstants.constitutionIdParamName, newValue); + } + + if (command.isChangeInLongParameterNamed(ClientApiConstants.mainBusinessLineIdParamName, mainBusinessLineId())) { + final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.mainBusinessLineIdParamName); + actualChanges.put(ClientApiConstants.mainBusinessLineIdParamName, newValue); + } + + //validate(); + + return actualChanges; + + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPersonRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPersonRepository.java new file mode 100644 index 000000000..4f6ece9a5 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPersonRepository.java @@ -0,0 +1,17 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface ClientNonPersonRepository extends JpaRepository, JpaSpecificationExecutor{ + + @Query("from ClientNonPerson clientNonPerson where clientNonPerson.client.id = :clientId") + ClientNonPerson findByClientId(@Param("clientId") Long clientId); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPersonRepositoryWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPersonRepositoryWrapper.java new file mode 100644 index 000000000..01a3dae78 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientNonPersonRepositoryWrapper.java @@ -0,0 +1,60 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.domain; + +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.portfolio.client.exception.ClientNonPersonNotFoundByClientIdException; +import org.mifosplatform.portfolio.client.exception.ClientNonPersonNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +/** + *

+ * Wrapper for {@link ClientNonPersonRepository} that adds NULL checking and Error + * handling capabilities + *

+ */ +@Service +public class ClientNonPersonRepositoryWrapper { + + private final ClientNonPersonRepository repository; + private final PlatformSecurityContext context; + + @Autowired + public ClientNonPersonRepositoryWrapper(final ClientNonPersonRepository repository, final PlatformSecurityContext context) { + this.repository = repository; + this.context = context; + } + + public ClientNonPerson findOneWithNotFoundDetection(final Long id) { + final ClientNonPerson clientNonPerson = this.repository.findOne(id); + if (clientNonPerson == null) { throw new ClientNonPersonNotFoundException(id); } + return clientNonPerson; + } + + public ClientNonPerson findOneByClientId(final Long clientId) { + return this.repository.findByClientId(clientId); + } + + public ClientNonPerson findOneByClientIdWithNotFoundDetection(final Long clientId) { + final ClientNonPerson clientNonPerson = this.repository.findByClientId(clientId); + if (clientNonPerson == null) { throw new ClientNonPersonNotFoundByClientIdException(clientId); } + return clientNonPerson; + } + + public void save(final ClientNonPerson clientNonPerson) { + this.repository.save(clientNonPerson); + } + + public void saveAndFlush(final ClientNonPerson clientNonPerson) { + this.repository.saveAndFlush(clientNonPerson); + } + + public void delete(final ClientNonPerson clientNonPerson) { + this.repository.delete(clientNonPerson); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/LegalForm.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/LegalForm.java new file mode 100644 index 000000000..7ed621ae4 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/LegalForm.java @@ -0,0 +1,54 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.domain; + +/** + * Type used to differentiate the type of client + */ +public enum LegalForm { + + PERSON(1, "legalFormType.person"), + + ENTITY(2, "legalFormType.entity"); + + private final Integer value; + private final String code; + + private LegalForm(final Integer value, final String code) { + this.value = value; + this.code = code; + } + + public Integer getValue() { + return this.value; + } + + public String getCode() { + return this.code; + } + + public static LegalForm fromInt(final Integer type) { + + LegalForm legalForm = null; + switch (type) { + case 1: + legalForm = LegalForm.PERSON; + break; + case 2: + legalForm = LegalForm.ENTITY; + break; + } + return legalForm; + } + + public boolean isPerson() { + return this.value.equals(LegalForm.PERSON.getValue()); + } + + public boolean isEntity() { + return this.value.equals(LegalForm.ENTITY.getValue()); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/exception/ClientNonPersonNotFoundByClientIdException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/exception/ClientNonPersonNotFoundByClientIdException.java new file mode 100644 index 000000000..9b3423289 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/exception/ClientNonPersonNotFoundByClientIdException.java @@ -0,0 +1,18 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.exception; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +/** + * A {@link RuntimeException} thrown when clientNonPerson resources are not found. + */ +public class ClientNonPersonNotFoundByClientIdException extends AbstractPlatformResourceNotFoundException { + + public ClientNonPersonNotFoundByClientIdException(final Long id) { + super("error.msg.clientnonperson.id.invalid", "ClientNonPerson with client identifier " + id + " does not exist", id); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/exception/ClientNonPersonNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/exception/ClientNonPersonNotFoundException.java new file mode 100644 index 000000000..8c1e52d26 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/exception/ClientNonPersonNotFoundException.java @@ -0,0 +1,19 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.client.exception; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +/** + * A {@link RuntimeException} thrown when clientNonPerson resources are not found. + */ +public class ClientNonPersonNotFoundException extends AbstractPlatformResourceNotFoundException { + + public ClientNonPersonNotFoundException(final Long id) { + super("error.msg.clientnonperson.id.invalid", "ClientNonPerson with identifier " + id + " does not exist", id); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java index 0acd25052..82672f91d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientReadPlatformServiceImpl.java @@ -29,9 +29,11 @@ import org.mifosplatform.organisation.staff.data.StaffData; import org.mifosplatform.organisation.staff.service.StaffReadPlatformService; import org.mifosplatform.portfolio.client.api.ClientApiConstants; import org.mifosplatform.portfolio.client.data.ClientData; +import org.mifosplatform.portfolio.client.data.ClientNonPersonData; import org.mifosplatform.portfolio.client.data.ClientTimelineData; import org.mifosplatform.portfolio.client.domain.ClientEnumerations; import org.mifosplatform.portfolio.client.domain.ClientStatus; +import org.mifosplatform.portfolio.client.domain.LegalForm; import org.mifosplatform.portfolio.client.exception.ClientNotFoundException; import org.mifosplatform.portfolio.group.data.GroupGeneralData; import org.mifosplatform.portfolio.savings.data.SavingsProductData; @@ -103,9 +105,18 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final List clientClassificationOptions = new ArrayList<>( this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_CLASSIFICATION)); + + final List clientNonPersonConstitutionOptions = new ArrayList<>( + this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_NON_PERSON_CONSTITUTION)); + + final List clientNonPersonMainBusinessLineOptions = new ArrayList<>( + this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_NON_PERSON_MAIN_BUSINESS_LINE)); + + final List clientLegalFormOptions = ClientEnumerations.legalForm(LegalForm.values()); return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions, null, genderOptions, savingsProductDatas, - clientTypeOptions, clientClassificationOptions); + clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, + clientLegalFormOptions); } @Override @@ -302,6 +313,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService sqlBuilder.append("cvclienttype.code_value as clienttypeValue, "); sqlBuilder.append("c.client_classification_cv_id as classificationId, "); sqlBuilder.append("cvclassification.code_value as classificationValue, "); + sqlBuilder.append("c.legal_form_enum as legalFormEnum, "); sqlBuilder.append("c.activation_date as activationDate, c.image_id as imageId, "); sqlBuilder.append("c.staff_id as staffId, s.display_name as staffName,"); sqlBuilder.append("c.default_savings_product as savingsProductId, sp.name as savingsProductName, "); @@ -319,10 +331,19 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService sqlBuilder.append("acu.username as activatedByUsername, "); sqlBuilder.append("acu.firstname as activatedByFirstname, "); - sqlBuilder.append("acu.lastname as activatedByLastname "); + sqlBuilder.append("acu.lastname as activatedByLastname, "); + + sqlBuilder.append("cnp.constitution_cv_id as constitutionId, "); + sqlBuilder.append("cvConstitution.code_value as constitutionValue, "); + sqlBuilder.append("cnp.incorp_no as incorpNo, "); + sqlBuilder.append("cnp.incorp_validity_till as incorpValidityTill, "); + sqlBuilder.append("cnp.main_business_line_cv_id as mainBusinessLineId, "); + sqlBuilder.append("cvMainBusinessLine.code_value as mainBusinessLineValue, "); + sqlBuilder.append("cnp.remarks as remarks "); sqlBuilder.append("from m_client c "); sqlBuilder.append("join m_office o on o.id = c.office_id "); + sqlBuilder.append("left join m_client_non_person cnp on cnp.client_id = c.id "); sqlBuilder.append("join m_group_client pgc on pgc.client_id = c.id "); sqlBuilder.append("left join m_staff s on s.id = c.staff_id "); sqlBuilder.append("left join m_savings_product sp on sp.id = c.default_savings_product "); @@ -335,6 +356,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService sqlBuilder.append("left join m_code_value cvclienttype on cvclienttype.id = c.client_type_cv_id "); sqlBuilder.append("left join m_code_value cvclassification on cvclassification.id = c.client_classification_cv_id "); sqlBuilder.append("left join m_code_value cvSubStatus on cvSubStatus.id = c.sub_status "); + sqlBuilder.append("left join m_code_value cvConstitution on cvConstitution.id = cnp.constitution_cv_id "); + sqlBuilder.append("left join m_code_value cvMainBusinessLine on cvMainBusinessLine.id = cnp.main_business_line_cv_id "); this.schema = sqlBuilder.toString(); } @@ -407,6 +430,23 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final String activatedByUsername = rs.getString("activatedByUsername"); final String activatedByFirstname = rs.getString("activatedByFirstname"); final String activatedByLastname = rs.getString("activatedByLastname"); + + final Integer legalFormEnum = JdbcSupport.getInteger(rs, "legalFormEnum"); + EnumOptionData legalForm = null; + if(legalFormEnum != null) + legalForm = ClientEnumerations.legalForm(legalFormEnum); + + final Long constitutionId = JdbcSupport.getLong(rs, "constitutionId"); + final String constitutionValue = rs.getString("constitutionValue"); + final CodeValueData constitution = CodeValueData.instance(constitutionId, constitutionValue); + final String incorpNo = rs.getString("incorpNo"); + final LocalDate incorpValidityTill = JdbcSupport.getLocalDate(rs, "incorpValidityTill"); + final Long mainBusinessLineId = JdbcSupport.getLong(rs, "mainBusinessLineId"); + final String mainBusinessLineValue = rs.getString("mainBusinessLineValue"); + final CodeValueData mainBusinessLine = CodeValueData.instance(mainBusinessLineId, mainBusinessLineValue); + final String remarks = rs.getString("remarks"); + + final ClientNonPersonData clientNonPerson = new ClientNonPersonData(constitution, incorpNo, incorpValidityTill, mainBusinessLine, remarks); final ClientTimelineData timeline = new ClientTimelineData(submittedOnDate, submittedByUsername, submittedByFirstname, submittedByLastname, activationDate, activatedByUsername, activatedByFirstname, activatedByLastname, closedOnDate, @@ -415,7 +455,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService return ClientData.instance(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, activationDate, imageId, staffId, staffName, timeline, savingsProductId, savingsProductName, savingsAccountId, clienttype, - classification); + classification, legalForm, clientNonPerson); } } @@ -455,6 +495,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService builder.append("cvclienttype.code_value as clienttypeValue, "); builder.append("c.client_classification_cv_id as classificationId, "); builder.append("cvclassification.code_value as classificationValue, "); + builder.append("c.legal_form_enum as legalFormEnum, "); builder.append("c.submittedon_date as submittedOnDate, "); builder.append("sbu.username as submittedByUsername, "); @@ -470,6 +511,14 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService builder.append("acu.username as activatedByUsername, "); builder.append("acu.firstname as activatedByFirstname, "); builder.append("acu.lastname as activatedByLastname, "); + + builder.append("cnp.constitution_cv_id as constitutionId, "); + builder.append("cvConstitution.code_value as constitutionValue, "); + builder.append("cnp.incorp_no as incorpNo, "); + builder.append("cnp.incorp_validity_till as incorpValidityTill, "); + builder.append("cnp.main_business_line_cv_id as mainBusinessLineId, "); + builder.append("cvMainBusinessLine.code_value as mainBusinessLineValue, "); + builder.append("cnp.remarks as remarks, "); builder.append("c.activation_date as activationDate, c.image_id as imageId, "); builder.append("c.staff_id as staffId, s.display_name as staffName, "); @@ -477,6 +526,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService builder.append("c.default_savings_account as savingsAccountId "); builder.append("from m_client c "); builder.append("join m_office o on o.id = c.office_id "); + builder.append("left join m_client_non_person cnp on cnp.client_id = c.id "); builder.append("left join m_staff s on s.id = c.staff_id "); builder.append("left join m_savings_product sp on sp.id = c.default_savings_product "); builder.append("left join m_office transferToOffice on transferToOffice.id = c.transfer_to_office_id "); @@ -487,6 +537,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService builder.append("left join m_code_value cvclienttype on cvclienttype.id = c.client_type_cv_id "); builder.append("left join m_code_value cvclassification on cvclassification.id = c.client_classification_cv_id "); builder.append("left join m_code_value cvSubStatus on cvSubStatus.id = c.sub_status "); + builder.append("left join m_code_value cvConstitution on cvConstitution.id = cnp.constitution_cv_id "); + builder.append("left join m_code_value cvMainBusinessLine on cvMainBusinessLine.id = cnp.main_business_line_cv_id "); this.schema = builder.toString(); } @@ -558,6 +610,23 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final String activatedByUsername = rs.getString("activatedByUsername"); final String activatedByFirstname = rs.getString("activatedByFirstname"); final String activatedByLastname = rs.getString("activatedByLastname"); + + final Integer legalFormEnum = JdbcSupport.getInteger(rs, "legalFormEnum"); + EnumOptionData legalForm = null; + if(legalFormEnum != null) + legalForm = ClientEnumerations.legalForm(legalFormEnum); + + final Long constitutionId = JdbcSupport.getLong(rs, "constitutionId"); + final String constitutionValue = rs.getString("constitutionValue"); + final CodeValueData constitution = CodeValueData.instance(constitutionId, constitutionValue); + final String incorpNo = rs.getString("incorpNo"); + final LocalDate incorpValidityTill = JdbcSupport.getLocalDate(rs, "incorpValidityTill"); + final Long mainBusinessLineId = JdbcSupport.getLong(rs, "mainBusinessLineId"); + final String mainBusinessLineValue = rs.getString("mainBusinessLineValue"); + final CodeValueData mainBusinessLine = CodeValueData.instance(mainBusinessLineId, mainBusinessLineValue); + final String remarks = rs.getString("remarks"); + + final ClientNonPersonData clientNonPerson = new ClientNonPersonData(constitution, incorpNo, incorpValidityTill, mainBusinessLine, remarks); final ClientTimelineData timeline = new ClientTimelineData(submittedOnDate, submittedByUsername, submittedByFirstname, submittedByLastname, activationDate, activatedByUsername, activatedByFirstname, activatedByLastname, closedOnDate, @@ -566,7 +635,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService return ClientData.instance(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, activationDate, imageId, staffId, staffName, timeline, savingsProductId, savingsProductName, savingsAccountId, clienttype, - classification); + classification, legalForm, clientNonPerson); } } @@ -674,7 +743,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final List narrations = new ArrayList<>(this.codeValueReadPlatformService.retrieveCodeValuesByCode(clientNarrations)); final Collection clientTypeOptions = null; final Collection clientClassificationOptions = null; - return ClientData.template(null, null, null, null, narrations, null, null, clientTypeOptions, clientClassificationOptions); + final Collection clientNonPersonConstitutionOptions = null; + final Collection clientNonPersonMainBusinessLineOptions = null; + final List clientLegalFormOptions = null; + return ClientData.template(null, null, null, null, narrations, null, null, clientTypeOptions, clientClassificationOptions, + clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientLegalFormOptions); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 37e490530..00c64cee0 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -11,6 +11,7 @@ */ package org.mifosplatform.portfolio.client.service; + import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -32,6 +33,7 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.organisation.office.domain.Office; import org.mifosplatform.organisation.office.domain.OfficeRepository; @@ -42,8 +44,11 @@ import org.mifosplatform.portfolio.client.api.ClientApiConstants; import org.mifosplatform.portfolio.client.data.ClientDataValidator; import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator; import org.mifosplatform.portfolio.client.domain.Client; +import org.mifosplatform.portfolio.client.domain.ClientNonPerson; +import org.mifosplatform.portfolio.client.domain.ClientNonPersonRepositoryWrapper; import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper; import org.mifosplatform.portfolio.client.domain.ClientStatus; +import org.mifosplatform.portfolio.client.domain.LegalForm; import org.mifosplatform.portfolio.client.exception.ClientActiveForUpdateException; import org.mifosplatform.portfolio.client.exception.ClientHasNoStaffException; import org.mifosplatform.portfolio.client.exception.ClientMustBePendingToBeDeletedException; @@ -73,6 +78,8 @@ import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.google.gson.JsonElement; + @Service public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWritePlatformService { @@ -80,6 +87,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP private final PlatformSecurityContext context; private final ClientRepositoryWrapper clientRepository; + private final ClientNonPersonRepositoryWrapper clientNonPersonRepository; private final OfficeRepository officeRepository; private final NoteRepository noteRepository; private final GroupRepository groupRepository; @@ -94,19 +102,21 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP private final CommandProcessingService commandProcessingService; private final ConfigurationDomainService configurationDomainService; private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository; + private final FromJsonHelper fromApiJsonHelper; @Autowired public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, - final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository, final NoteRepository noteRepository, + final ClientRepositoryWrapper clientRepository, final ClientNonPersonRepositoryWrapper clientNonPersonRepository, final OfficeRepository officeRepository, final NoteRepository noteRepository, final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGenerator accountNumberGenerator, final GroupRepository groupRepository, final StaffRepositoryWrapper staffRepository, final CodeValueRepositoryWrapper codeValueRepository, final LoanRepository loanRepository, final SavingsAccountRepository savingsRepository, final SavingsProductRepository savingsProductRepository, final SavingsApplicationProcessWritePlatformService savingsApplicationProcessWritePlatformService, final CommandProcessingService commandProcessingService, final ConfigurationDomainService configurationDomainService, - final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository) { + final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final FromJsonHelper fromApiJsonHelper) { this.context = context; this.clientRepository = clientRepository; + this.clientNonPersonRepository = clientNonPersonRepository; this.officeRepository = officeRepository; this.noteRepository = noteRepository; this.fromApiJsonDeserializer = fromApiJsonDeserializer; @@ -121,6 +131,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP this.commandProcessingService = commandProcessingService; this.configurationDomainService = configurationDomainService; this.accountNumberFormatRepository = accountNumberFormatRepository; + this.fromApiJsonHelper = fromApiJsonHelper; } @Transactional @@ -134,6 +145,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP final List relatedNotes = this.noteRepository.findByClientId(clientId); this.noteRepository.deleteInBatch(relatedNotes); + final ClientNonPerson clientNonPerson = this.clientNonPersonRepository.findOneByClientId(clientId); + if(clientNonPerson != null) + this.clientNonPersonRepository.delete(clientNonPerson); + this.clientRepository.delete(client); return new CommandProcessingResultBuilder() // @@ -225,9 +240,22 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (savingsProduct == null) { throw new SavingsProductNotFoundException(savingsProductId); } } - + + final Integer legalFormParamValue = command.integerValueOfParameterNamed(ClientApiConstants.legalFormIdParamName); + boolean isEntity = false; + Integer legalFormValue = null; + if(legalFormParamValue != null) + { + LegalForm legalForm = LegalForm.fromInt(legalFormParamValue); + if(legalForm != null) + { + legalFormValue = legalForm.getValue(); + isEntity = legalForm.isEntity(); + } + } + final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProduct, gender, - clientType, clientClassification, command); + clientType, clientClassification, legalFormValue, command); boolean rollbackTransaction = false; if (newClient.isActive()) { validateParentGroupRulesBeforeClientActivation(newClient); @@ -242,13 +270,16 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP newClient.updateAccountNo(accountNumberGenerator.generate(newClient, accountNumberFormat)); this.clientRepository.save(newClient); } - + final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); CommandProcessingResult result = openSavingsAccount(newClient, fmt); if (result.getSavingsId() != null) { this.clientRepository.save(newClient); } + + if(isEntity) + extractAndCreateClientNonPerson(newClient, command); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // @@ -265,6 +296,42 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP return CommandProcessingResult.empty(); } } + + /** + * This method extracts ClientNonPerson details from Client command and creates a new ClientNonPerson record + * @param client + * @param command + */ + public void extractAndCreateClientNonPerson(Client client, JsonCommand command) + { + final JsonElement clientNonPersonElement = this.fromApiJsonHelper.parse(command.jsonFragment(ClientApiConstants.clientNonPersonDetailsParamName)); + + if(clientNonPersonElement != null) + { + final String incorpNumber = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.incorpNumberParamName, clientNonPersonElement); + final String remarks = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.remarksParamName, clientNonPersonElement); + final LocalDate incorpValidityTill = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.incorpValidityTillParamName, clientNonPersonElement); + + //JsonCommand clientNonPersonCommand = JsonCommand.fromExistingCommand(command, command.arrayOfParameterNamed(ClientApiConstants.clientNonPersonDetailsParamName).getAsJsonObject()); + CodeValue clientNonPersonConstitution = null; + final Long clientNonPersonConstitutionId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.constitutionIdParamName, clientNonPersonElement); + if (clientNonPersonConstitutionId != null) { + clientNonPersonConstitution = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.CLIENT_NON_PERSON_CONSTITUTION, + clientNonPersonConstitutionId); + } + + CodeValue clientNonPersonMainBusinessLine = null; + final Long clientNonPersonMainBusinessLineId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.mainBusinessLineIdParamName, clientNonPersonElement); + if (clientNonPersonMainBusinessLineId != null) { + clientNonPersonMainBusinessLine = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.CLIENT_NON_PERSON_MAIN_BUSINESS_LINE, + clientNonPersonMainBusinessLineId); + } + + final ClientNonPerson newClientNonPerson = ClientNonPerson.createNew(client, clientNonPersonConstitution, clientNonPersonMainBusinessLine, incorpNumber, incorpValidityTill, remarks); + + this.clientNonPersonRepository.save(newClientNonPerson); + } + } @Transactional @Override @@ -345,6 +412,61 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (!changes.isEmpty()) { this.clientRepository.saveAndFlush(clientForUpdate); } + + if (changes.containsKey(ClientApiConstants.legalFormIdParamName)) { + Integer legalFormValue = clientForUpdate.getLegalForm(); + boolean isChangedToEntity = false; + if(legalFormValue != null) + { + LegalForm legalForm = LegalForm.fromInt(legalFormValue); + if(legalForm != null) + isChangedToEntity = legalForm.isEntity(); + } + + if(isChangedToEntity) + { + extractAndCreateClientNonPerson(clientForUpdate, command); + } + else + { + final ClientNonPerson clientNonPerson = this.clientNonPersonRepository.findOneByClientId(clientForUpdate.getId()); + if(clientNonPerson != null) + this.clientNonPersonRepository.delete(clientNonPerson); + } + } + + final ClientNonPerson clientNonPersonForUpdate = this.clientNonPersonRepository.findOneByClientId(clientId); + if(clientNonPersonForUpdate != null) + { + final JsonElement clientNonPersonElement = this.fromApiJsonHelper.parse(command.jsonFragment(ClientApiConstants.clientNonPersonDetailsParamName)); + final Map clientNonPersonChanges = clientNonPersonForUpdate.update(JsonCommand.fromExistingCommand(command, clientNonPersonElement)); + + if (clientNonPersonChanges.containsKey(ClientApiConstants.constitutionIdParamName)) { + + final Long newValue = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.constitutionIdParamName, clientNonPersonElement); + CodeValue constitution = null; + if (newValue != null) { + constitution = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.CLIENT_NON_PERSON_CONSTITUTION, newValue); + } + clientNonPersonForUpdate.updateConstitution(constitution); + } + + if (clientNonPersonChanges.containsKey(ClientApiConstants.mainBusinessLineIdParamName)) { + + final Long newValue = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.mainBusinessLineIdParamName, clientNonPersonElement); + CodeValue mainBusinessLine = null; + if (newValue != null) { + mainBusinessLine = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.CLIENT_NON_PERSON_MAIN_BUSINESS_LINE, newValue); + } + clientNonPersonForUpdate.updateMainBusinessLine(mainBusinessLine); + } + + if (!clientNonPersonChanges.isEmpty()) { + this.clientNonPersonRepository.saveAndFlush(clientNonPersonForUpdate); + } + + changes.putAll(clientNonPersonChanges); + } return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/mifosng-provider/src/main/resources/sql/migrations/core_db/V289__client_non_person.sql b/mifosng-provider/src/main/resources/sql/migrations/core_db/V289__client_non_person.sql new file mode 100644 index 000000000..1393860e6 --- /dev/null +++ b/mifosng-provider/src/main/resources/sql/migrations/core_db/V289__client_non_person.sql @@ -0,0 +1,22 @@ + +INSERT INTO `m_code` (`code_name`, `is_system_defined`) values + ("Constitution", true); + +INSERT INTO `m_code` (`code_name`, `is_system_defined`) values + ("Main Business Line", true); + +ALTER TABLE `m_client` ADD `legal_form_enum` INT(5); + +CREATE TABLE `m_client_non_person` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `client_id` BIGINT(20) NOT NULL UNIQUE, + `constitution_cv_id` INT(11) NOT NULL, + `incorp_no` varchar(50), + `incorp_validity_till` DATETIME, + `main_business_line_cv_id` INT(11), + `remarks` varchar(150), + PRIMARY KEY (`id`), + INDEX `FK_client_id` (`client_id`), + CONSTRAINT `FK_client_id` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) +); +