/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.customers.personnel.business;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Years;
import org.mifos.customers.office.business.OfficeBO;
import org.mifos.customers.personnel.exceptions.PersonnelException;
import org.mifos.customers.personnel.util.helpers.LockStatus;
import org.mifos.customers.personnel.util.helpers.PersonnelLevel;
import org.mifos.customers.personnel.util.helpers.PersonnelStatus;
import org.mifos.dto.domain.CustomFieldDto;
import org.mifos.dto.domain.UserDetailDto;
import org.mifos.framework.business.AbstractBusinessObject;
import org.mifos.framework.business.util.Address;
import org.mifos.framework.business.util.Name;
import org.mifos.framework.exceptions.SystemException;
import org.mifos.framework.util.helpers.Constants;
import org.mifos.security.authentication.EncryptionService;
import org.mifos.security.rolesandpermission.business.RoleBO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PersonnelBO extends AbstractBusinessObject {
private static final Logger logger = LoggerFactory.getLogger(PersonnelBO.class);
private static final String INVALIDOLDPASSWORD = "errors.invalidoldpassword";
public static PersonnelBO ALL_PERSONNEL = new PersonnelBO();
static {
ALL_PERSONNEL.setDisplayName("ALL");
}
private Short personnelId;
private String globalPersonnelNum;
private String searchId;
//business attributes
private PersonnelLevelEntity level;
private PersonnelStatusEntity status;
private Set<PersonnelMovementEntity> personnelMovements;
private Integer maxChildCount;
//associations
private OfficeBO office;
//business meta data
private Integer title;
private String displayName;
private Set<PersonnelNotesEntity> personnelNotes;
private Set<PersonnelCustomFieldEntity> customFields;
private PersonnelDetailsEntity personnelDetails;
//system attributes
private String userName;
private String emailId;
private Short passwordChanged = 0;
private Date lastLogin;
private Short locked = 0;
private Short noOfTries = 0;
private Set<PersonnelRoleEntity> personnelRoles;
private Short preferredLocale;
private Short sitePreference;
private byte[] encryptedPassword;
private Date passwordExpirationDate;
private Set<PersonnelUsedPasswordEntity> personnelUsedPasswords;
public PersonnelBO(final PersonnelLevel level, final OfficeBO office, final Integer title, final Short preferredLocale, final String password,
final String userName, final String emailId, final List<RoleBO> roles, final List<CustomFieldDto> customFields, final Name name,
final String governmentIdNumber, final Date dob, final Integer maritalStatus, final Integer gender, final Date dateOfJoiningMFI,
final Date dateOfJoiningBranch, final Address address, final Short createdBy, Date passwordExpirationDate, Set<PersonnelUsedPasswordEntity> personnelUsedPasswords) {
super();
setCreateDetails(createdBy, new DateTime().toDate());
this.displayName = name.getDisplayName();
this.level = new PersonnelLevelEntity(level);
this.office = office;
this.title = title;
this.preferredLocale = preferredLocale;
this.userName = userName;
this.emailId = emailId;
this.personnelDetails = new PersonnelDetailsEntity(name, governmentIdNumber, dob, maritalStatus, gender,
dateOfJoiningMFI, dateOfJoiningBranch, this, address);
this.personnelRoles = new HashSet<PersonnelRoleEntity>();
if (roles != null) {
for (RoleBO role : roles) {
this.personnelRoles.add(new PersonnelRoleEntity(role, this));
}
}
this.customFields = new HashSet<PersonnelCustomFieldEntity>();
this.personnelMovements = new HashSet<PersonnelMovementEntity>();
this.personnelNotes = new HashSet<PersonnelNotesEntity>();
this.personnelId = null;
this.globalPersonnelNum = new Long(new DateTime().toDate().getTime()).toString();
this.status = new PersonnelStatusEntity(PersonnelStatus.ACTIVE);
this.passwordChanged = Constants.NO;
this.locked = LockStatus.UNLOCK.getValue();
this.noOfTries = 0;
this.encryptedPassword = getEncryptedPassword(password);
this.status = new PersonnelStatusEntity(PersonnelStatus.ACTIVE);
this.passwordExpirationDate = passwordExpirationDate;
this.personnelUsedPasswords = personnelUsedPasswords;
}
public Date getPasswordExpirationDate() {
return passwordExpirationDate;
}
public void setPasswordExpirationDate(Date passwordExpirationDate) {
this.passwordExpirationDate = passwordExpirationDate;
}
public Set<PersonnelUsedPasswordEntity> getPersonnelUsedPasswords() {
return personnelUsedPasswords;
}
public void setPersonnelUsedPasswords(
Set<PersonnelUsedPasswordEntity> personnelUsedPasswords) {
this.personnelUsedPasswords = personnelUsedPasswords;
}
/**
* default constructor for hibernate
*/
@Deprecated
public PersonnelBO() {
this(null, null, null, null);
this.personnelDetails = new PersonnelDetailsEntity();
this.preferredLocale = 1; //default locale is 1 (english)
this.customFields = new HashSet<PersonnelCustomFieldEntity>();
this.personnelNotes = new HashSet<PersonnelNotesEntity>();
}
public PersonnelBO(final Short personnelId, final String userName, final String displayName, final PersonnelLevelEntity level) {
this(userName, displayName, level, 0);
this.personnelId = personnelId;
}
public PersonnelBO(final String userName, final String displayName, final PersonnelLevelEntity level, int createdBy) {
this.userName = userName;
this.displayName = displayName;
this.level = level;
setCreateDetails(createdBy);
}
public String getAge() {
if (this.personnelDetails != null && this.personnelDetails.getDob() != null
&& !this.personnelDetails.getDob().equals("")) {
LocalDate fromDate = new LocalDate(this.personnelDetails.getDob());
Years years = Years.yearsBetween(new LocalDate(), fromDate);
return Integer.valueOf(years.getYears()).toString();
}
return "";
}
public Set<PersonnelCustomFieldEntity> getCustomFields() {
return customFields;
}
public void setCustomFields(final Set<PersonnelCustomFieldEntity> customFields) {
this.customFields = customFields;
}
public String getEmailId() {
return emailId;
}
public String getGlobalPersonnelNum() {
return globalPersonnelNum;
}
public Date getLastLogin() {
return lastLogin;
}
public PersonnelLevelEntity getLevel() {
return level;
}
public PersonnelLevel getLevelEnum() {
return PersonnelLevel.fromInt(level.getId());
}
public Integer getMaxChildCount() {
return maxChildCount;
}
public OfficeBO getOffice() {
return office;
}
public boolean isPasswordChanged() {
return this.passwordChanged > 0;
}
public PersonnelDetailsEntity getPersonnelDetails() {
return personnelDetails;
}
public void setPersonnelDetails(final PersonnelDetailsEntity personnelDetails) {
this.personnelDetails = personnelDetails;
}
public Short getPersonnelId() {
return personnelId;
}
public Short getPreferredLocale() {
return preferredLocale;
}
public Integer getTitle() {
return title;
}
public String getUserName() {
return userName;
}
public String getDisplayName() {
return displayName;
}
public boolean isLocked() {
return this.locked > 0;
}
private void lock() {
this.locked = LockStatus.LOCK.getValue();
}
private void unLock() {
this.locked = LockStatus.UNLOCK.getValue();
}
public Set<PersonnelRoleEntity> getPersonnelRoles() {
return personnelRoles;
}
public void setPersonnelRoles(final Set<PersonnelRoleEntity> personnelRoles) {
this.personnelRoles = personnelRoles;
}
public Set<PersonnelMovementEntity> getPersonnelMovements() {
return personnelMovements;
}
public Set<PersonnelNotesEntity> getPersonnelNotes() {
return personnelNotes;
}
public Short getNoOfTries() {
return noOfTries;
}
public Short getPasswordChanged() {
return passwordChanged;
}
public void setPasswordChanged(final Short passwordChanged) {
this.passwordChanged = passwordChanged;
}
public String getSearchId() {
return searchId;
}
void setSearchId(final String searchId) {
this.searchId = searchId;
}
public byte[] getEncryptedPassword() {
return encryptedPassword;
}
public void setDisplayName(final String displayName) {
this.displayName = displayName;
}
public void setEmailId(final String emailId) {
this.emailId = emailId;
}
void setGlobalPersonnelNum(final String globalPersonnelNum) {
this.globalPersonnelNum = globalPersonnelNum;
}
void setLastLogin(final Date lastLogin) {
this.lastLogin = lastLogin;
}
public void setLevel(final PersonnelLevelEntity level) {
this.level = level;
}
public void setMaxChildCount(final Integer maxChildCount) {
this.maxChildCount = maxChildCount;
}
public void setOffice(final OfficeBO office) {
this.office = office;
}
public void setPersonnelMovements(final Set<PersonnelMovementEntity> personnelMovements) {
this.personnelMovements = personnelMovements;
}
public void setPersonnelNotes(final Set<PersonnelNotesEntity> personnelNotes) {
this.personnelNotes = personnelNotes;
}
public void setPreferredLocale(final Short preferredLocale) {
this.preferredLocale = preferredLocale;
}
public void setStatus(final PersonnelStatusEntity status) {
this.status = status;
}
public void setTitle(final Integer title) {
this.title = title;
}
public void setEncryptedPassword(final byte[] encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
public PersonnelStatusEntity getStatus() {
return status;
}
public PersonnelStatus getStatusAsEnum() {
return PersonnelStatus.getPersonnelStatus(status.getId());
}
public void addPersonnelMovement(final PersonnelMovementEntity personnelMovement) {
if (personnelMovement != null) {
this.personnelMovements.add(personnelMovement);
}
}
public void addNotes(final Short userId, final PersonnelNotesEntity personnelNotes) {
setUpdateDetails(userId);
this.personnelNotes.add(personnelNotes);
}
public void generateGlobalPersonnelNum() {
String paddedSystemId = generateGlobalPersonnelNum(this.office.getGlobalOfficeNum(), this.personnelId);
this.globalPersonnelNum = paddedSystemId;
}
private String generateGlobalPersonnelNum(final String officeGlobalNum, final int maxPersonnelId) {
logger.debug("Passed office global no is : ".concat(officeGlobalNum).concat(
" and maxpersonnelid is : " + maxPersonnelId));
String userId = "";
int numberOfZeros = 5 - String.valueOf(maxPersonnelId).length();
for (int i = 0; i < numberOfZeros; i++) {
userId = userId + "0";
}
userId = userId + maxPersonnelId;
String userGlobalNum = officeGlobalNum + "-" + userId;
logger.debug("Generated userGlobalNum is : ".concat(userGlobalNum));
return userGlobalNum;
}
private byte[] getEncryptedPassword(final String password) {
byte[] encryptedPassword = null;
encryptedPassword = EncryptionService.getInstance().createEncryptedPassword(password);
return encryptedPassword;
}
private void updatePersonnelRoles(final List<RoleBO> roles) {
this.personnelRoles.clear();
if (roles != null) {
for (RoleBO role : roles) {
this.personnelRoles.add(new PersonnelRoleEntity(role, this));
}
}
}
public void update(final String emailId, final Name name, final Integer maritalStatus, final Integer gender, final Address address, final Short preferredLocaleId, final Short sitePreferenceId) {
this.emailId = emailId;
if (preferredLocaleId != null && preferredLocaleId != 0) {
this.preferredLocale = preferredLocaleId;
}
if (sitePreferenceId != null && sitePreferenceId != 0) {
this.sitePreference = sitePreferenceId;
}
setDisplayName(name.getDisplayName());
updatePersonnelDetails(name, maritalStatus, gender, address, null);
}
public void updatePersonnelDetails(final Name name, final Integer maritalStatus, final Integer gender, final Address address,
final Date dateOfJoiningBranch) {
if (this.personnelDetails != null) {
this.personnelDetails.updateNameDetails(name.getFirstName(), name.getMiddleName(), name.getSecondLastName(), name.getLastName());
this.personnelDetails.updateDetails(maritalStatus, gender);
this.personnelDetails.updateAddress(address);
this.personnelDetails.setDateOfJoiningBranch(dateOfJoiningBranch);
}
}
public List<PersonnelNotesEntity> getRecentPersonnelNotes() {
List<PersonnelNotesEntity> notes = new ArrayList<PersonnelNotesEntity>();
int count = 0;
for (PersonnelNotesEntity personnelNotes : getPersonnelNotes()) {
if (count > 2) {
break;
}
notes.add(personnelNotes);
count++;
}
return notes;
}
public PersonnelMovementEntity getActiveCustomerMovement() {
PersonnelMovementEntity movement = null;
for (PersonnelMovementEntity personnelMovementEntity : personnelMovements) {
if (personnelMovementEntity.isActive()) {
movement = personnelMovementEntity;
break;
}
}
return movement;
}
public boolean isActive() {
return getStatusAsEnum() == PersonnelStatus.ACTIVE;
}
public boolean isLoanOfficer() {
return getLevelEnum() == PersonnelLevel.LOAN_OFFICER;
}
public void login(final String password) throws PersonnelException {
if (!isPasswordValid(password)) {
updateNoOfTries();
} else {
resetNoOfTries();
if (isPasswordChanged()) {
this.lastLogin = new DateTime().toDate();
}
logger.info("Login successful for user=" + this.userName + ", branchID=" + this.office.getGlobalOfficeNum());
}
}
public void updatePassword(final String oldPassword, final String newPassword) throws PersonnelException {
byte[] encryptedPassword = getEncryptedPassword(oldPassword, newPassword);
this.setEncryptedPassword(encryptedPassword);
this.setPasswordChanged(passwordChangedShortValue());
if (this.getLastLogin() == null) {
this.setLastLogin(new DateTime().toDate());
}
}
private Short passwordChangedShortValue() {
return Short.valueOf("1");
}
public void changePasswordTo(String newPassword, final Short changedByUserId, boolean setPasswordChnged) {
byte[] encryptedPassword = getEncryptedPassword(newPassword);
this.setEncryptedPassword(encryptedPassword);
if (setPasswordChnged) {
this.setPasswordChanged(passwordChangedShortValue());
}
if (this.getLastLogin() == null) {
this.setLastLogin(new DateTime().toDate());
}
setUpdateDetails(changedByUserId);
}
public void unlockPersonnel() {
if (isLocked()) {
this.unLock();
this.noOfTries = 0;
}
}
private void updateNoOfTries() {
final Short MAXTRIES = 5;
if (!isLocked()) {
Short newNoOfTries = (short) (getNoOfTries() + 1);
if (newNoOfTries.equals(MAXTRIES)) {
lock();
}
this.noOfTries = newNoOfTries;
}
}
private void resetNoOfTries() {
if (noOfTries.intValue() > 0) {
this.noOfTries = 0;
}
}
public boolean isPasswordValid(final String password) throws PersonnelException {
logger.debug("Checking password valid or not");
try {
return EncryptionService.getInstance().verifyPassword(password, getEncryptedPassword());
} catch (SystemException se) {
throw new PersonnelException(se);
}
}
public Set<Short> getRoles() {
Set<Short> roles = new HashSet<Short>();
for (PersonnelRoleEntity personnelRole : getPersonnelRoles()) {
roles.add(personnelRole.getRole().getId());
}
return roles;
}
private byte[] getEncryptedPassword(final String oldPassword, final String newPassword) throws PersonnelException {
logger.debug("Matching oldpassword with entered password.");
byte[] newEncryptedPassword = null;
if (isPasswordValid(oldPassword)) {
newEncryptedPassword = getEncryptedPassword(newPassword);
} else {
throw new PersonnelException(INVALIDOLDPASSWORD);
}
logger.debug("New encrypted password returned.");
return newEncryptedPassword;
}
public String getOfficeSearchId() {
return office.getSearchId();
}
@Override
public String toString() {
return "{" + getDisplayName() + ", " + getPersonnelId() + "}";
}
public boolean isDifferentIdentityTo(PersonnelBO personnel) {
return !this.personnelId.equals(personnel.getPersonnelId());
}
public UserDetailDto toDto() {
boolean loanOfficer = isLoanOfficer();
return new UserDetailDto(this.office.getOfficeName(), this.personnelId.intValue(), this.globalPersonnelNum, this.personnelDetails.getName().getFirstName(), this.personnelDetails.getName().getLastName(), loanOfficer);
}
public void updateUserDetails(String firstName, String middleName, String secondLastName, String lastName,
String email, Integer gender, Integer maritalStatus,
Short preferredLocaleId, PersonnelStatusEntity personnelStatus,
Address address, Integer title, PersonnelLevelEntity personnelLevel, List<RoleBO> roles,
OfficeBO newOffice) {
this.emailId = email;
this.personnelDetails.updateNameDetails(firstName, middleName, secondLastName, lastName);
this.personnelDetails.updateDetails(maritalStatus, gender);
this.personnelDetails.updateAddress(address);
this.displayName = this.personnelDetails.getDisplayName();
if (title != null && title.intValue() == 0) {
this.title = null;
} else {
this.title = title;
}
if (this.isOfficeDifferent(newOffice)) {
this.office = newOffice;
}
this.preferredLocale = preferredLocaleId;
this.status = personnelStatus;
this.level = personnelLevel;
updatePersonnelRoles(roles);
}
public boolean isNonLoanOfficer() {
return getLevelEnum().equals(PersonnelLevel.NON_LOAN_OFFICER);
}
public boolean isLevelDifferent(PersonnelLevel newLevel) {
return !newLevel.getValue().equals(this.level.getId());
}
public boolean isOfficeDifferent(OfficeBO newOffice) {
return this.office.isDifferent(newOffice);
}
public boolean isInActive() {
return !isActive();
}
public void setUserName(String userName) {
this.userName = userName;
}
public Short getSitePreference() {
return sitePreference;
}
public void setSitePreference(Short sitePreference) {
this.sitePreference = sitePreference;
}
}