MIFOSX-1252 Squashing all previous commits.Savings Officer changes

This commit is contained in:
Chandrika
2014-09-24 17:39:11 -04:00
parent 114f17e300
commit 253c444a45
20 changed files with 466 additions and 113 deletions
+19 -13
View File
@@ -427,7 +427,7 @@
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td>savingsaccounts/{accountId}?command=assignFieldOfficer</td> <td>savingsaccounts/{accountId}?command=assignSavingsOfficer</td>
<td><a href="#savingsaccounts_assignSavingsOfficer">Assign Savings Officer</a></td> <td><a href="#savingsaccounts_assignSavingsOfficer">Assign Savings Officer</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -435,7 +435,7 @@
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td>savingsaccounts/{accountId}?command=unassignFieldOfficer</td> <td>savingsaccounts/{accountId}?command=unassignSavingsOfficer</td>
<td><a href="#savingsaccounts_unassignSavingsOfficer">Unassign Savings Officer</a></td> <td><a href="#savingsaccounts_unassignSavingsOfficer">Unassign Savings Officer</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -19167,20 +19167,24 @@ Request Body:
<p>Allows you to assign <i>Savings Officer</i> for existing Savings Account.</p> <p>Allows you to assign <i>Savings Officer</i> for existing Savings Account.</p>
</div> </div>
<div class="method-example"> <div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=assignFieldOfficer</code> <code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=assignSavingsOfficer</code>
<code class="method-request">POST savingsaccounts/1?command=assignFieldOfficer <code class="method-request">POST savingsaccounts/1?command=assignSavingsOfficer
Content-Type: application/json Content-Type: application/json
Request Body: Request Body:
{ {
"staffId":1 assignmentDate : "04 September 2014"
dateFormat : "dd MMMM yyyy"
fromSavingsOfficerId : ""
locale : "en"
toSavingsOfficerId : 2
} }
</code> </code>
<code class="method-response"> <code class="method-response">
{ {
"officeId":2, "officeId":2,
"clientId":8, "savingsId":8,
"resourceId":8, "resourceId":8,
"changes":{"staffId":1} "changes":{"savingsOfficerId":2}
} }
</code> </code>
</div> </div>
@@ -19193,12 +19197,14 @@ Request Body:
<p>Allows you to unassign the <i>Savings Officer</i>.</p> <p>Allows you to unassign the <i>Savings Officer</i>.</p>
</div> </div>
<div class="method-example"> <div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=unassignFieldOfficer</code> <code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=unassignSavingsOfficer</code>
<code class="method-request">POST savingsaccounts/1?command=unassignFieldOfficer <code class="method-request">POST savingsaccounts/1?command=unassignSavingsOfficer
Content-Type: application/json Content-Type: application/json
Request Body: Request Body:
{ {
"staffId":1 dateFormat : "dd MMMM yyyy"
locale : "en"
unassignedDate : "05 September 2014"
} }
</code> </code>
<code class="method-response"> <code class="method-response">
@@ -19206,7 +19212,7 @@ Request Body:
"officeId":2, "officeId":2,
"clientId":8, "clientId":8,
"resourceId":8, "resourceId":8,
"changes":{"staffId":1} "changes":{}
} }
</code> </code>
</div> </div>
@@ -33777,7 +33783,7 @@ No Request Body:
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td>savingsaccounts/{accountId}?command=assignFieldOfficer</td> <td>savingsaccounts/{accountId}?command=assignSavingsOfficer</td>
<td><a href="#savingsaccounts_assignSavingsOfficer">Assign Savings Officer</a></td> <td><a href="#savingsaccounts_assignSavingsOfficer">Assign Savings Officer</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -33785,7 +33791,7 @@ No Request Body:
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td>savingsaccounts/{accountId}?command=unassignFieldOfficer</td> <td>savingsaccounts/{accountId}?command=unassignSavingsOfficer</td>
<td><a href="#savingsaccounts_unassignSavingsOfficer">Unassign Savings Officer</a></td> <td><a href="#savingsaccounts_unassignSavingsOfficer">Unassign Savings Officer</a></td>
<td></td> <td></td>
<td></td> <td></td>
@@ -0,0 +1,20 @@
CREATE TABLE `m_savings_officer_assignment_history` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`account_id` bigint(20) NOT NULL,
`savings_officer_id` bigint(20) DEFAULT NULL,
`start_date` date NOT NULL,
`end_date` date DEFAULT NULL,
`createdby_id` bigint(20) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`lastmodified_date` datetime DEFAULT NULL,
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_m_savings_officer_assignment_history_0001` (`account_id`),
KEY `fk_m_savings_officer_assignment_history_0002` (`savings_officer_id`),
CONSTRAINT `fk_m_savings_officer_assignment_history_0001` FOREIGN KEY (`account_id`) REFERENCES `m_savings_account` (`id`),
CONSTRAINT `fk_m_savings_officer_assignment_history_0002` FOREIGN KEY (`savings_officer_id`) REFERENCES `m_staff` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into m_permission (grouping,code,entity_name,action_name) values ('portfolio','REMOVESAVINGSOFFICER_SAVINGSACCOUNT','SAVINGSACCOUNT','REMOVESAVINGSOFFICER');
insert into m_permission (grouping,code,entity_name,action_name) values ('portfolio','UPDATESAVINGSOFFICER_SAVINGSACCOUNT','SAVINGSACCOUNT','UPDATESAVINGSOFFICER');
@@ -589,12 +589,12 @@ public class CommandWrapper {
return this.actionName.equalsIgnoreCase("ADJUSTTRANSACTION") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT"); return this.actionName.equalsIgnoreCase("ADJUSTTRANSACTION") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
} }
public boolean isAssignStaffSavingsAccount(){ public boolean isUpdateSavingsOfficer(){
return this.actionName.equalsIgnoreCase("ASSIGNFIELDOFFICER") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT"); return this.actionName.equalsIgnoreCase("UPDATESAVINGSOFFICER") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
} }
public boolean isUnAssignStaffSavingsAccount(){ public boolean isRemoveSavingsOfficer(){
return this.actionName.equalsIgnoreCase("UNASSIGNFIELDOFFICER") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT"); return this.actionName.equalsIgnoreCase("REMOVESAVINGSOFFICER") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
} }
public boolean isSavingsAccountChargeResource() { public boolean isSavingsAccountChargeResource() {
@@ -2073,19 +2073,19 @@ public class CommandWrapperBuilder {
this.entityId = entityId; this.entityId = entityId;
return this; return this;
} }
public CommandWrapperBuilder assignFieldOfficer(final Long accountId) { public CommandWrapperBuilder assignSavingsOfficer(final Long accountId) {
this.actionName = "ASSIGNFIELDOFFICER"; this.actionName = "UPDATESAVINGSOFFICER";
this.entityName = "SAVINGSACCOUNT"; this.entityName = "SAVINGSACCOUNT";
this.entityId = accountId; this.entityId = accountId;
this.href = "/savingsaccounts/" + accountId + "?command=assignFieldOfficer"; this.href = "/savingsaccounts/" + accountId + "?command=assignSavingsOfficer";
return this; return this;
} }
public CommandWrapperBuilder unassignFieldOfficer(final Long accountId) { public CommandWrapperBuilder unassignSavingsOfficer(final Long accountId) {
this.actionName = "UNASSIGNFIELDOFFICER"; this.actionName = "REMOVESAVINGSOFFICER";
this.entityName = "SAVINGSACCOUNT"; this.entityName = "SAVINGSACCOUNT";
this.entityId = accountId; this.entityId = accountId;
this.href = "/savingsaccounts/" + accountId + "?command=unassignFieldOfficer"; this.href = "/savingsaccounts/" + accountId + "?commad=unassignSavingsOfficer";
return this; return this;
} }
@@ -512,10 +512,10 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = this.applicationContext.getBean("savingsTransactionAdjustmentCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("savingsTransactionAdjustmentCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSavingsAccountClose()) { } else if (wrapper.isSavingsAccountClose()) {
handler = this.applicationContext.getBean("closeSavingsAccountCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("closeSavingsAccountCommandHandler", NewCommandSourceHandler.class);
}else if(wrapper.isAssignStaffSavingsAccount()) { }else if(wrapper.isUpdateSavingsOfficer()) {
handler = this.applicationContext.getBean("assignFieldOfficerSavingsAccountCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("updateSavingsOfficerCommandHandler", NewCommandSourceHandler.class);
}else if(wrapper.isUnAssignStaffSavingsAccount()) { }else if(wrapper.isRemoveSavingsOfficer()) {
handler = this.applicationContext.getBean("unassignFieldOfficerSavingsAccountCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("removeSavingsOfficerCommandHandler", NewCommandSourceHandler.class);
} }
else { else {
throw new UnsupportedCommandException(wrapper.commandName()); throw new UnsupportedCommandException(wrapper.commandName());
@@ -13,7 +13,7 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN
public class StaffRoleException extends AbstractPlatformResourceNotFoundException { public class StaffRoleException extends AbstractPlatformResourceNotFoundException {
public static enum STAFF_ROLE { public static enum STAFF_ROLE {
LOAN_OFFICER, BRANCH_MANAGER; LOAN_OFFICER, BRANCH_MANAGER,SAVINGS_OFFICER;
@Override @Override
public String toString() { public String toString() {
@@ -48,7 +48,7 @@ public class SavingsApiConstants {
public static final String localeParamName = "locale"; public static final String localeParamName = "locale";
public static final String dateFormatParamName = "dateFormat"; public static final String dateFormatParamName = "dateFormat";
public static final String monthDayFormatParamName = "monthDayFormat"; public static final String monthDayFormatParamName = "monthDayFormat";
public static final String staffIdParamName = "staffId"; public static final String staffIdParamName = "savingsOfficerId";
// savings product and account parameters // savings product and account parameters
public static final String idParamName = "id"; public static final String idParamName = "id";
@@ -248,12 +248,12 @@ public class SavingsAccountsApiResource {
} else if (is(commandParam, "close")) { } else if (is(commandParam, "close")) {
final CommandWrapper commandRequest = builder.closeSavingsAccountApplication(accountId).build(); final CommandWrapper commandRequest = builder.closeSavingsAccountApplication(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, "assignFieldOfficer")) { } else if (is(commandParam, "assignSavingsOfficer")) {
final CommandWrapper commandRequest = builder.assignFieldOfficer(accountId).build(); final CommandWrapper commandRequest = builder.assignSavingsOfficer(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result); return this.toApiJsonSerializer.serialize(result);
} else if (is(commandParam, "unassignFieldOfficer")) { } else if (is(commandParam, "unassignSavingsOfficer")) {
final CommandWrapper commandRequest = builder.unassignFieldOfficer(accountId).build(); final CommandWrapper commandRequest = builder.unassignSavingsOfficer(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result); return this.toApiJsonSerializer.serialize(result);
} }
@@ -262,7 +262,7 @@ public class SavingsAccountsApiResource {
// //
throw new UnrecognizedQueryParamException("command", commandParam, throw new UnrecognizedQueryParamException("command", commandParam,
new Object[] { "reject", "withdrawnByApplicant", "approve", "undoapproval", "activate", "calculateInterest", new Object[] { "reject", "withdrawnByApplicant", "approve", "undoapproval", "activate", "calculateInterest",
"postInterest", "close", "assignFieldOfficer", "unassignFieldOfficer" }); "postInterest", "close", "assignSavingsOfficer", "unassignSavingsOfficer" });
} }
return this.toApiJsonSerializer.serialize(result); return this.toApiJsonSerializer.serialize(result);
@@ -391,50 +391,56 @@ public class SavingsAccountDataValidator {
} }
public void validateForAssignFieldOfficer(final String json) { public void validateForAssignSavingsOfficer(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("fromSavingsOfficerId","toSavingsOfficerId","assignmentDate","locale","dateFormat"));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType(); final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final Set<String> supportedParametersUnassignStaff = new HashSet<>(Arrays.asList(SavingsApiConstants.staffIdParamName));
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParametersUnassignStaff);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) final JsonElement element = this.fromApiJsonHelper.parse(json);
.resource(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
final String staffIdParameterName = SavingsApiConstants.staffIdParamName; final Long toSavingsOfficerId = this.fromApiJsonHelper.extractLongNamed("toSavingsOfficerId", element);
final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParameterName, element); baseDataValidator.reset().parameter("toSavingsOfficerId").value(toSavingsOfficerId).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter(staffIdParameterName).value(staffId).notNull().longGreaterThanZero();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } final String assignmentDateStr = this.fromApiJsonHelper.extractStringNamed("assignmentDate", element);
baseDataValidator.reset().parameter("assignmentDate").value(assignmentDateStr).notBlank();
if (!StringUtils.isBlank(assignmentDateStr)) {
final LocalDate assignmentDate = this.fromApiJsonHelper.extractLocalDateNamed("assignmentDate", element);
baseDataValidator.reset().parameter("assignmentDate").value(assignmentDate).notNull();
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
} }
public void validateForUnAssignFieldOfficer(final String json) { public void validateForUnAssignSavingsOfficer(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("unassignedDate","locale","dateFormat"));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType(); final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final Set<String> supportedParametersUnassignStaff = new HashSet<>(Arrays.asList(SavingsApiConstants.staffIdParamName));
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParametersUnassignStaff);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) final JsonElement element = this.fromApiJsonHelper.parse(json);
.resource(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
final String staffIdParameterName = SavingsApiConstants.staffIdParamName; final String unassignedDateStr = this.fromApiJsonHelper.extractStringNamed("unassignedDate", element);
final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParameterName, element); baseDataValidator.reset().parameter("unassignedDate").value(unassignedDateStr).notBlank();
baseDataValidator.reset().parameter(staffIdParameterName).value(staffId).notNull().longGreaterThanZero();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } if (!StringUtils.isBlank(unassignedDateStr)) {
final LocalDate unassignedDate = this.fromApiJsonHelper.extractLocalDateNamed("unassignedDate", element);
} baseDataValidator.reset().parameter("unassignedDate").value(unassignedDate).notNull();
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
} }
@@ -728,7 +728,7 @@ public class FixedDepositAccount extends SavingsAccount {
final boolean withdrawalFeeApplicableForTransfer = false; final boolean withdrawalFeeApplicableForTransfer = false;
final String accountNumber = null; final String accountNumber = null;
final FixedDepositAccount reInvestedAccount = FixedDepositAccount final FixedDepositAccount reInvestedAccount = FixedDepositAccount
.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNumber, externalId, accountType, .createNewApplicationForSubmittal(client, group, product, savingsOfficer, accountNumber, externalId, accountType,
getClosedOnDate(), closedBy, interestRate, compoundingPeriodType, postingPeriodType, interestCalculationType, getClosedOnDate(), closedBy, interestRate, compoundingPeriodType, postingPeriodType, interestCalculationType,
daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure, newChart); withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure, newChart);
@@ -1006,7 +1006,7 @@ public class RecurringDepositAccount extends SavingsAccount {
newAccountTermAndPreClosure.updateExpectedFirstDepositDate(now); newAccountTermAndPreClosure.updateExpectedFirstDepositDate(now);
RecurringDepositAccount rdAccount = RecurringDepositAccount.createNewActivatedAccount(client, group, product, fieldOfficer, RecurringDepositAccount rdAccount = RecurringDepositAccount.createNewActivatedAccount(client, group, product, savingsOfficer,
accountNumber, externalId, accountType, getClosedOnDate(), closedBy, interestRate, compoundingPeriodType, accountNumber, externalId, accountType, getClosedOnDate(), closedBy, interestRate, compoundingPeriodType,
postingPeriodType, interestCalculationType, daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, postingPeriodType, interestCalculationType, daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure,
@@ -75,6 +75,8 @@ import org.mifosplatform.portfolio.charge.exception.SavingsAccountChargeNotFound
import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.group.domain.Group; import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.savings.exception.SavingsOfficerAssignmentDateException;
import org.mifosplatform.portfolio.savings.domain.SavingsOfficerAssignmentHistory;
import org.mifosplatform.portfolio.savings.DepositAccountType; import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.SavingsApiConstants; import org.mifosplatform.portfolio.savings.SavingsApiConstants;
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType; import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
@@ -87,6 +89,7 @@ import org.mifosplatform.portfolio.savings.domain.interest.PostingPeriod;
import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException; import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException;
import org.mifosplatform.portfolio.savings.exception.SavingsAccountTransactionNotFoundException; import org.mifosplatform.portfolio.savings.exception.SavingsAccountTransactionNotFoundException;
import org.mifosplatform.portfolio.savings.exception.SavingsActivityPriorToClientTransferException; import org.mifosplatform.portfolio.savings.exception.SavingsActivityPriorToClientTransferException;
import org.mifosplatform.portfolio.savings.exception.SavingsOfficerUnassignmentDateException;
import org.mifosplatform.portfolio.savings.exception.SavingsTransferTransactionsCannotBeUndoneException; import org.mifosplatform.portfolio.savings.exception.SavingsTransferTransactionsCannotBeUndoneException;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations; import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
@@ -123,7 +126,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
@ManyToOne @ManyToOne
@JoinColumn(name = "field_officer_id", nullable = true) @JoinColumn(name = "field_officer_id", nullable = true)
protected Staff fieldOfficer; protected Staff savingsOfficer;
@Column(name = "status_enum", nullable = false) @Column(name = "status_enum", nullable = false)
protected Integer status; protected Integer status;
@@ -263,6 +266,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true) @OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true)
protected Set<SavingsAccountCharge> charges = new HashSet<>(); protected Set<SavingsAccountCharge> charges = new HashSet<>();
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true)
private Set<SavingsOfficerAssignmentHistory> savingsOfficerHistory;
@Transient @Transient
protected boolean accountNumberRequiresAutoGeneration = false; protected boolean accountNumberRequiresAutoGeneration = false;
@Transient @Transient
@@ -279,7 +286,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
protected SavingsAccount() { protected SavingsAccount() {
// //
} }
public static SavingsAccount createNewApplicationForSubmittal(final Client client, final Group group, final SavingsProduct product, public static SavingsAccount createNewApplicationForSubmittal(final Client client, final Group group, final SavingsProduct product,
final Staff fieldOfficer, final String accountNo, final String externalId, final AccountType accountType, final Staff fieldOfficer, final String accountNo, final String externalId, final AccountType accountType,
final LocalDate submittedOnDate, final AppUser submittedBy, final BigDecimal interestRate, final LocalDate submittedOnDate, final AppUser submittedBy, final BigDecimal interestRate,
@@ -314,7 +321,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, false, null); withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, false, null);
} }
protected SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer, protected SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff savingsOfficer,
final String accountNo, final String externalId, final SavingsAccountStatusType status, final AccountType accountType, final String accountNo, final String externalId, final SavingsAccountStatusType status, final AccountType accountType,
final LocalDate submittedOnDate, final AppUser submittedBy, final BigDecimal nominalAnnualInterestRate, final LocalDate submittedOnDate, final AppUser submittedBy, final BigDecimal nominalAnnualInterestRate,
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
@@ -327,7 +334,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.client = client; this.client = client;
this.group = group; this.group = group;
this.product = product; this.product = product;
this.fieldOfficer = fieldOfficer; this.savingsOfficer = savingsOfficer;
if (StringUtils.isBlank(accountNo)) { if (StringUtils.isBlank(accountNo)) {
this.accountNumber = new RandomPasswordGenerator(19).generate(); this.accountNumber = new RandomPasswordGenerator(19).generate();
this.accountNumberRequiresAutoGeneration = true; this.accountNumberRequiresAutoGeneration = true;
@@ -364,6 +371,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.enforceMinRequiredBalance = enforceMinRequiredBalance; this.enforceMinRequiredBalance = enforceMinRequiredBalance;
this.minRequiredBalance = minRequiredBalance; this.minRequiredBalance = minRequiredBalance;
this.minBalanceForInterestCalculation = product.minBalanceForInterestCalculation(); this.minBalanceForInterestCalculation = product.minBalanceForInterestCalculation();
this.savingsOfficerHistory = null;
} }
/** /**
@@ -991,7 +999,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
actualChanges.put(SavingsApiConstants.productIdParamName, newValue); actualChanges.put(SavingsApiConstants.productIdParamName, newValue);
} }
if (command.isChangeInLongParameterNamed(SavingsApiConstants.fieldOfficerIdParamName, fieldOfficerId())) { if (command.isChangeInLongParameterNamed(SavingsApiConstants.fieldOfficerIdParamName, hasSavingsOfficerId())) {
final Long newValue = command.longValueOfParameterNamed(SavingsApiConstants.fieldOfficerIdParamName); final Long newValue = command.longValueOfParameterNamed(SavingsApiConstants.fieldOfficerIdParamName);
actualChanges.put(SavingsApiConstants.fieldOfficerIdParamName, newValue); actualChanges.put(SavingsApiConstants.fieldOfficerIdParamName, newValue);
} }
@@ -1196,8 +1204,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.minBalanceForInterestCalculation = product.minBalanceForInterestCalculation(); this.minBalanceForInterestCalculation = product.minBalanceForInterestCalculation();
} }
public void update(final Staff fieldOfficer) { public void update(final Staff savingsOfficer) {
this.fieldOfficer = fieldOfficer; this.savingsOfficer = savingsOfficer;
} }
public void updateAccountNo(final String newAccountNo) { public void updateAccountNo(final String newAccountNo) {
@@ -1241,16 +1249,16 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return office; return office;
} }
public Staff getFieldOfficer() { public Staff getSavingsOfficer() {
return this.fieldOfficer; return this.savingsOfficer;
} }
public void unassignFieldOfficer() { public void unassignSavingsOfficer() {
this.fieldOfficer = null; this.savingsOfficer = null;
} }
public void assignFieldOfficer(final Staff fieldOfficer) { public void assignSavingsOfficer(final Staff fieldOfficer) {
this.fieldOfficer = fieldOfficer; this.savingsOfficer = fieldOfficer;
} }
public Long clientId() { public Long clientId() {
@@ -1269,14 +1277,149 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return id; return id;
} }
public Long fieldOfficerId() { public Long hasSavingsOfficerId() {
Long id = null; Long id = null;
if (this.fieldOfficer != null) { if (this.savingsOfficer != null) {
id = this.fieldOfficer.getId(); id = this.savingsOfficer.getId();
} }
return id; return id;
} }
public boolean hasSavingsOfficer(final Staff fromSavingsOfficer) {
boolean matchesCurrentSavingsOfficer = false;
if (this.savingsOfficer != null) {
matchesCurrentSavingsOfficer = this.savingsOfficer.identifiedBy(fromSavingsOfficer);
} else {
matchesCurrentSavingsOfficer = fromSavingsOfficer == null;
}
return matchesCurrentSavingsOfficer;
}
public void reassignSavingsOfficer(final Staff newSavingsOfficer,final LocalDate assignmentDate) {
final SavingsOfficerAssignmentHistory latestHistoryRecord = findLatestIncompleteHistoryRecord();
final SavingsOfficerAssignmentHistory lastAssignmentRecord = findLastAssignmentHistoryRecord(newSavingsOfficer);
// assignment date should not be less than savings account submitted date
if (isSubmittedOnDateAfter(assignmentDate)) {
final String errorMessage = "The Savings Officer assignment date (" + assignmentDate.toString()
+ ") cannot be before savings submitted date (" + getSubmittedOnDate().toString() + ").";
throw new SavingsOfficerAssignmentDateException("cannot.be.before.savings.submitted.date", errorMessage, assignmentDate,
getSubmittedOnDate());
} else if (lastAssignmentRecord != null && lastAssignmentRecord.isEndDateAfter(assignmentDate)) {
final String errorMessage = "The Savings Officer assignment date (" + assignmentDate
+ ") cannot be before previous Savings Officer unassigned date (" + lastAssignmentRecord.getEndDate() + ").";
throw new SavingsOfficerAssignmentDateException("cannot.be.before.previous.unassignement.date", errorMessage, assignmentDate,
lastAssignmentRecord.getEndDate());
} else if (DateUtils.getLocalDateOfTenant().isBefore(assignmentDate)) {
final String errorMessage = "The Savings Officer assignment date (" + assignmentDate + ") cannot be in the future.";
throw new SavingsOfficerAssignmentDateException("cannot.be.a.future.date", errorMessage, assignmentDate);
} else if (latestHistoryRecord != null && this.savingsOfficer.identifiedBy(newSavingsOfficer)) {
latestHistoryRecord.updateStartDate(assignmentDate);
} else if (latestHistoryRecord != null && latestHistoryRecord.matchesStartDateOf(assignmentDate)) {
latestHistoryRecord.updateSavingsOfficer(newSavingsOfficer);
this.savingsOfficer = newSavingsOfficer;
} else if (latestHistoryRecord != null && latestHistoryRecord.hasStartDateBefore(assignmentDate)) {
final String errorMessage = "Savings account with identifier " + getId() + " was already assigned before date " + assignmentDate;
throw new SavingsOfficerAssignmentDateException("is.before.last.assignment.date", errorMessage, getId(), assignmentDate);
} else {
if (latestHistoryRecord != null) {
// savings officer correctly changed from previous savings officer to
// new savings officer
latestHistoryRecord.updateEndDate(assignmentDate);
}
this.savingsOfficer = newSavingsOfficer;
if (isNotSubmittedAndPendingApproval()) {
final SavingsOfficerAssignmentHistory savingsOfficerAssignmentHistory =
SavingsOfficerAssignmentHistory.createNew(this,this.savingsOfficer,assignmentDate);
this.savingsOfficerHistory.add(savingsOfficerAssignmentHistory);
}
}
}
private SavingsOfficerAssignmentHistory findLastAssignmentHistoryRecord(final Staff newSavingsOfficer) {
SavingsOfficerAssignmentHistory lastAssignmentRecordLatestEndDate = null;
for (final SavingsOfficerAssignmentHistory historyRecord : this.savingsOfficerHistory) {
if (historyRecord.isCurrentRecord() && !historyRecord.isSameSavingsOfficer(newSavingsOfficer)) {
lastAssignmentRecordLatestEndDate = historyRecord;
break;
}
if (lastAssignmentRecordLatestEndDate == null) {
lastAssignmentRecordLatestEndDate = historyRecord;
} else if (historyRecord.isEndDateAfter(lastAssignmentRecordLatestEndDate.getEndDate())
&& !historyRecord.isSameSavingsOfficer(newSavingsOfficer)) {
lastAssignmentRecordLatestEndDate = historyRecord;
}
}
return lastAssignmentRecordLatestEndDate;
}
public boolean isSubmittedOnDateAfter(final LocalDate compareDate) {
return this.submittedOnDate == null ? false : new LocalDate(this.submittedOnDate).isAfter(compareDate);
}
public LocalDate getSubmittedOnDate() {
return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.submittedOnDate), null);
}
public void removeSavingsOfficer(final LocalDate unassignDate) {
final SavingsOfficerAssignmentHistory latestHistoryRecord = findLatestIncompleteHistoryRecord();
if (latestHistoryRecord != null) {
validateUnassignDate(latestHistoryRecord, unassignDate);
latestHistoryRecord.updateEndDate(unassignDate);
}
this.savingsOfficer = null;
}
private SavingsOfficerAssignmentHistory findLatestIncompleteHistoryRecord() {
SavingsOfficerAssignmentHistory latestRecordWithNoEndDate = null;
for (final SavingsOfficerAssignmentHistory historyRecord : this.savingsOfficerHistory) {
if (historyRecord.isCurrentRecord()) {
latestRecordWithNoEndDate = historyRecord;
break;
}
}
return latestRecordWithNoEndDate;
}
private void validateUnassignDate(final SavingsOfficerAssignmentHistory latestHistoryRecord, final LocalDate unassignDate) {
final LocalDate today = DateUtils.getLocalDateOfTenant();
if (latestHistoryRecord.getStartDate().isAfter(unassignDate)) {
final String errorMessage = "The Savings officer Unassign date(" + unassignDate + ") cannot be before its assignment date ("
+ latestHistoryRecord.getStartDate() + ").";
throw new SavingsOfficerUnassignmentDateException("cannot.be.before.assignment.date", errorMessage, getId(), getSavingsOfficer()
.getId(), latestHistoryRecord.getStartDate(), unassignDate);
} else if (unassignDate.isAfter(today)) {
final String errorMessage = "The Savings Officer Unassign date (" + unassignDate + ") cannot be in the future.";
throw new SavingsOfficerUnassignmentDateException("cannot.be.a.future.date", errorMessage, unassignDate);
}
}
public MonetaryCurrency getCurrency() { public MonetaryCurrency getCurrency() {
return this.currency; return this.currency;
} }
@@ -0,0 +1,106 @@
/**
* 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.savings.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.ObjectUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.useradministration.domain.AppUser;
@Entity
@Table(name = "m_savings_officer_assignment_history")
public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@JoinColumn(name = "account_id", nullable = false)
private SavingsAccount savingsAccount;
@ManyToOne
@JoinColumn(name = "savings_officer_id", nullable = true)
private Staff savingsOfficer;
@Temporal(TemporalType.DATE)
@Column(name = "start_date")
private Date startDate;
@Temporal(TemporalType.DATE)
@Column(name = "end_date")
private Date endDate;
public static SavingsOfficerAssignmentHistory createNew(final SavingsAccount account, final Staff savingsOfficer,final LocalDate assignmentDate) {
return new SavingsOfficerAssignmentHistory(account, savingsOfficer,assignmentDate.toDate(),null);
}
protected SavingsOfficerAssignmentHistory() {
//
}
private SavingsOfficerAssignmentHistory(final SavingsAccount account, final Staff savingsOfficer,final Date startDate, final Date endDate) {
this.savingsAccount = account;
this.savingsOfficer = savingsOfficer;
this.startDate = startDate;
this.endDate = endDate;
}
public void updateSavingsOfficer(final Staff savingsOfficer) {
this.savingsOfficer = savingsOfficer;
}
public boolean isSameSavingsOfficer(final Staff staff) {
return this.savingsOfficer.identifiedBy(staff);
}
public void updateStartDate(final LocalDate startDate) {
this.startDate = startDate.toDate();
}
public void updateEndDate(final LocalDate endDate) {
this.endDate = endDate.toDate();
}
public boolean matchesStartDateOf(final LocalDate matchingDate) {
return getStartDate().isEqual(matchingDate);
}
public LocalDate getStartDate() {
return new LocalDate(this.startDate);
}
public boolean hasStartDateBefore(final LocalDate matchingDate) {
return matchingDate.isBefore(getStartDate());
}
public boolean isCurrentRecord() {
return this.endDate == null;
}
/**
* If endDate is null then return false.
*
* @param compareDate
* @return
*/
public boolean isEndDateAfter(final LocalDate compareDate) {
return this.endDate == null ? false : new LocalDate(this.endDate).isAfter(compareDate);
}
public LocalDate getEndDate() {
return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.endDate), null);
}
}
@@ -0,0 +1,16 @@
/**
* 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.savings.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class SavingsOfficerAssignmentDateException extends AbstractPlatformDomainRuleException {
public SavingsOfficerAssignmentDateException(final String postFix, final String defaultUserMessage, final Object... defaultUserMessageArgs) {
super("error.msg.savings.assignment.date." + postFix, defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -0,0 +1,16 @@
/**
* 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.savings.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class SavingsOfficerAssignmentException extends AbstractPlatformDomainRuleException {
public SavingsOfficerAssignmentException(final Long accountId, final Long fromSavingsOfficerId) {
super("error.msg.savings.account.not.assigned.to.savings.officer", "Savings Account Identifier " + accountId
+ " is not assigned to Savings Officer with identifier " + fromSavingsOfficerId + ".", accountId);
}
}
@@ -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.savings.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class SavingsOfficerUnassignmentDateException extends AbstractPlatformDomainRuleException {
public SavingsOfficerUnassignmentDateException(final String postFix, final String defaultUserMessage,
final Object... defaultUserMessageArgs) {
super("error.msg.savings.savingsofficer.unassign.date." + postFix, defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -0,0 +1,15 @@
/**
* 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.savings.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class SavingsOfficerUnassignmentException extends AbstractPlatformDomainRuleException {
public SavingsOfficerUnassignmentException(final Long accountId) {
super("error.msg.savings.account.not.assigned.to.savings.officer", "Savings Account Identifier" + accountId + " is not assigned to any savings officer.");
}
}
@@ -14,12 +14,12 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class UnassignFieldOfficerSavingsAccountCommandHandler implements NewCommandSourceHandler { public class RemoveSavingsOfficerCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService savingsWritePlatformService; private final SavingsAccountWritePlatformService savingsWritePlatformService;
@Autowired @Autowired
public UnassignFieldOfficerSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) { public RemoveSavingsOfficerCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.savingsWritePlatformService = savingAccountWritePlatformService; this.savingsWritePlatformService = savingAccountWritePlatformService;
} }
@@ -14,12 +14,12 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class AssignFieldOfficerSavingsAccountCommandHandler implements NewCommandSourceHandler { public class UpdateSavingsOfficerCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService savingsWritePlatformService; private final SavingsAccountWritePlatformService savingsWritePlatformService;
@Autowired @Autowired
public AssignFieldOfficerSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) { public UpdateSavingsOfficerCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.savingsWritePlatformService = savingAccountWritePlatformService; this.savingsWritePlatformService = savingAccountWritePlatformService;
} }
@@ -81,6 +81,8 @@ import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionRepository; import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionRepository;
import org.mifosplatform.portfolio.savings.exception.SavingsAccountClosingNotAllowedException; import org.mifosplatform.portfolio.savings.exception.SavingsAccountClosingNotAllowedException;
import org.mifosplatform.portfolio.savings.exception.SavingsAccountTransactionNotFoundException; import org.mifosplatform.portfolio.savings.exception.SavingsAccountTransactionNotFoundException;
import org.mifosplatform.portfolio.savings.exception.SavingsOfficerAssignmentException;
import org.mifosplatform.portfolio.savings.exception.SavingsOfficerUnassignmentException;
import org.mifosplatform.portfolio.savings.exception.TransactionUpdateNotAllowedException; import org.mifosplatform.portfolio.savings.exception.TransactionUpdateNotAllowedException;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -1021,66 +1023,72 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
return null; return null;
} }
@Transactional
@Override @Override
public CommandProcessingResult assignFieldOfficer(Long savingsAccountId, JsonCommand command) { public CommandProcessingResult assignFieldOfficer(Long savingsAccountId, JsonCommand command) {
this.context.authenticatedUser(); this.context.authenticatedUser();
final Map<String, Object> actualChanges = new LinkedHashMap<>(5); final Map<String, Object> actualChanges = new LinkedHashMap<>(5);
this.fromApiJsonDeserializer.validateForAssignFieldOfficer(command.json()); Staff fromSavingsOfficer = null;
Staff toSavingsOfficer = null;
this.fromApiJsonDeserializer.validateForAssignSavingsOfficer(command.json());
final SavingsAccount savingsForUpdate = this.savingsRepository.findOneWithNotFoundDetection(savingsAccountId); final SavingsAccount savingsForUpdate = this.savingsRepository.findOneWithNotFoundDetection(savingsAccountId);
final Long fromSavingsOfficerId = command.longValueOfParameterNamed("fromSavingsOfficerId");
Staff staff = null; final Long toSavingsOfficerId = command.longValueOfParameterNamed("toSavingsOfficerId");
final Long staffId = command.longValueOfParameterNamed(SavingsApiConstants.staffIdParamName); final LocalDate dateOfSavingsOfficerAssignment = command.localDateValueOfParameterNamed("assignmentDate");
if (staffId != null) {
staff = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(staffId, savingsForUpdate.office().getHierarchy()); if(fromSavingsOfficerId != null)
{
savingsForUpdate.assignFieldOfficer(staff); fromSavingsOfficer = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(fromSavingsOfficerId, savingsForUpdate.office().getHierarchy());
} }
if(toSavingsOfficerId != null)
{
toSavingsOfficer = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(toSavingsOfficerId, savingsForUpdate.office().getHierarchy());
}
if (!savingsForUpdate.hasSavingsOfficer(fromSavingsOfficer)) { throw new SavingsOfficerAssignmentException(savingsAccountId, fromSavingsOfficerId); }
savingsForUpdate.reassignSavingsOfficer(toSavingsOfficer,dateOfSavingsOfficerAssignment);
this.savingsRepository.saveAndFlush(savingsForUpdate); this.savingsRepository.saveAndFlush(savingsForUpdate);
actualChanges.put(SavingsApiConstants.staffIdParamName, staffId); actualChanges.put("toSavingsOfficerId", toSavingsOfficer.getId());
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
.withOfficeId(savingsForUpdate.officeId()) // .withOfficeId(savingsForUpdate.officeId()) //
.withEntityId(savingsForUpdate.getId()) // .withEntityId(savingsForUpdate.getId()) //
.withClientId(savingsAccountId) // .withSavingsId(savingsAccountId) //
.with(actualChanges) // .with(actualChanges) //
.build(); .build();
} }
@Transactional
@Override @Override
public CommandProcessingResult unassignFieldOfficer(Long savingsAccountId, JsonCommand command) { public CommandProcessingResult unassignFieldOfficer(Long savingsAccountId, JsonCommand command) {
this.context.authenticatedUser();
this.context.authenticatedUser();
final Map<String, Object> actualChanges = new LinkedHashMap<>(5); final Map<String, Object> actualChanges = new LinkedHashMap<>(5);
this.fromApiJsonDeserializer.validateForUnAssignSavingsOfficer(command.json());
final SavingsAccount savingsForUpdate = this.savingsRepository.findOneWithNotFoundDetection(savingsAccountId);
if (savingsForUpdate.getSavingsOfficer() == null) { throw new SavingsOfficerUnassignmentException(savingsAccountId); }
this.fromApiJsonDeserializer.validateForUnAssignFieldOfficer(command.json()); final LocalDate dateOfSavingsOfficerUnassigned = command.localDateValueOfParameterNamed("unassignedDate");
savingsForUpdate.removeSavingsOfficer(dateOfSavingsOfficerUnassigned);
final SavingsAccount savingsForUpdate = this.savingsRepository.findOneWithNotFoundDetection(savingsAccountId);
final Staff presentStaff = savingsForUpdate.getFieldOfficer();
Long presentStaffId = null;
if (presentStaff == null) { throw new ClientHasNoStaffException(savingsAccountId); }
presentStaffId = presentStaff.getId();
final String staffIdParamName = SavingsApiConstants.staffIdParamName;
if (!command.isChangeInLongParameterNamed(staffIdParamName, presentStaffId)) {
savingsForUpdate.unassignFieldOfficer();
}
this.savingsRepository.saveAndFlush(savingsForUpdate); this.savingsRepository.saveAndFlush(savingsForUpdate);
actualChanges.put(staffIdParamName, presentStaffId); actualChanges.put("toSavingsOfficerId", null);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
.withOfficeId(savingsForUpdate.officeId()) // .withOfficeId(savingsForUpdate.officeId()) //
.withEntityId(savingsForUpdate.getId()) // .withEntityId(savingsForUpdate.getId()) //
.withClientId(savingsAccountId) // .withSavingsId(savingsAccountId) //
.with(actualChanges) // .with(actualChanges) //
.build(); .build();
} }
} }