@Override
  public CenterDto retrieveCenterDetailsForUpdate(Integer centerId) {

    MifosUser user =
        (MifosUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    UserContext userContext = toUserContext(user);

    CustomerBO center = customerDao.findCustomerById(centerId);

    Short officeId = center.getOffice().getOfficeId();
    String searchId = center.getSearchId();
    Short loanOfficerId = extractLoanOfficerId(center);

    CenterCreation centerCreation =
        new CenterCreation(
            officeId,
            userContext.getId(),
            userContext.getLevelId(),
            userContext.getPreferredLocale());
    List<PersonnelDto> activeLoanOfficersForBranch =
        personnelDao.findActiveLoanOfficersForOffice(centerCreation);

    List<CustomerDto> customerList =
        customerDao.findClientsThatAreNotCancelledOrClosed(searchId, officeId);

    List<CustomerPositionDto> customerPositionDtos =
        generateCustomerPositionViews(center, userContext.getLocaleId());

    DateTime mfiJoiningDate = new DateTime();
    String mfiJoiningDateAsString = "";
    if (center.getMfiJoiningDate() != null) {
      mfiJoiningDate = new DateTime(center.getMfiJoiningDate());
      mfiJoiningDateAsString =
          DateUtils.getUserLocaleDate(
              userContext.getPreferredLocale(), center.getMfiJoiningDate().toString());
    }

    AddressDto address = null;
    if (center.getAddress() != null) {
      address = Address.toDto(center.getAddress());
    }
    return new CenterDto(
        loanOfficerId,
        center.getCustomerId(),
        center.getGlobalCustNum(),
        mfiJoiningDate,
        mfiJoiningDateAsString,
        center.getExternalId(),
        address,
        customerPositionDtos,
        customerList,
        activeLoanOfficersForBranch,
        true);
  }
  @Test
  public void shouldRetrieveSalutations() {

    List<ValueListElement> salutations = customerDao.retrieveSalutations();

    assertThat(salutations, is(notNullValue()));
  }
  @Test
  public void countOfGroupsIsZero() {

    int count = customerDao.countOfGroups();

    assertThat(count, is(0));
  }
  @Test
  public void shouldRetrieveGenders() {

    List<ValueListElement> genders = customerDao.retrieveGenders();

    assertThat(genders, is(notNullValue()));
    assertThat(genders.size(), is(2));
  }
  @Test
  public void shouldRetrieveEducationLevels() {

    List<ValueListElement> educationLevels = customerDao.retrieveEducationLevels();

    assertThat(educationLevels, is(notNullValue()));
    assertThat(educationLevels.size(), is(4));
  }
  @Test
  public void shouldRetrieveBusinessActivities() {

    List<ValueListElement> businessActivities = customerDao.retrieveBusinessActivities();

    assertThat(businessActivities, is(notNullValue()));
    assertThat(businessActivities.size(), is(6));
  }
  @Test
  public void shouldRetrieveCitizenship() {

    List<ValueListElement> salutations = customerDao.retrieveCitizenship();

    assertThat(salutations, is(notNullValue()));
    assertThat(salutations.size(), is(3));
  }
  @Test
  public void shouldRetrieveHandicapped() {

    List<ValueListElement> handicaped = customerDao.retrieveHandicapped();

    assertThat(handicaped, is(notNullValue()));
    assertThat(handicaped.size(), is(2));
  }
  @Test
  public void canRetrieveConfigurableMandatoryFieldsForCenterThatAreNotHidden() {

    List<FieldConfigurationEntity> centerMandatoryFields =
        customerDao.findMandatoryConfigurableFieldsApplicableToCenter();

    assertThat(centerMandatoryFields.isEmpty(), is(true));
  }
  @Test
  public void groupPendingStatusShouldBeOptionalByDefault() {

    CustomerStatusEntity customerStatus = customerDao.findGroupPendingStatus();

    assertThat(customerStatus.getId(), is(CustomerStatus.GROUP_PENDING.getValue()));
    assertThat(customerStatus.getIsOptional(), is(true));
  }
  @Test
  public void clientPendingStatusShouldBeOptionalByDefault() {

    CustomerStatusEntity customerStatus = customerDao.findClientPendingStatus();

    assertThat(customerStatus.getId(), is(CustomerStatus.CLIENT_PENDING.getValue()));
    assertThat(customerStatus.getIsOptional(), is(true));
  }
  @Test
  public void shouldRetrieveLivingStatus() {

    List<ValueListElement> livingStatus = customerDao.retrieveLivingStatus();

    assertThat(livingStatus, is(notNullValue()));
    assertThat(livingStatus.size(), is(2));
  }
  @Test
  public void shouldRetrievePoverty() {

    List<ValueListElement> poverty = customerDao.retrievePoverty();

    assertThat(poverty, is(notNullValue()));
    assertThat(poverty.size(), is(3));
  }
  @Test
  public void shouldRetrieveEthnicity() {

    List<ValueListElement> ethnicity = customerDao.retrieveEthnicity();

    assertThat(ethnicity, is(notNullValue()));
    assertThat(ethnicity.size(), is(5));
  }
  @Test
  public void countOfCustomersInOfficeWithNoParent() {

    int count =
        customerDao.retrieveLastSearchIdValueForNonParentCustomersInOffice(
            IntegrationTestObjectMother.sampleBranchOffice().getOfficeId());

    assertThat(count, is(0));
  }
  @Test
  public void countOfAccounts() {

    Integer customerId = Integer.valueOf(1);
    Integer customerWithActiveAccount = Integer.valueOf(1);
    List<AccountBO> accounts =
        customerDao.findGLIMLoanAccountsApplicableTo(customerId, customerWithActiveAccount);

    assertThat(accounts.size(), is(0));
  }
  @Override
  public CenterFormCreationDto retrieveCenterFormCreationData(CenterCreation centerCreation) {

    MifosUser user =
        (MifosUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    UserContext userContext = toUserContext(user);

    List<PersonnelDto> activeLoanOfficersForBranch =
        personnelDao.findActiveLoanOfficersForOffice(centerCreation);

    List<FeeBO> fees = customerDao.retrieveFeesApplicableToCenters();
    CustomerApplicableFeesDto applicableFees = CustomerApplicableFeesDto.toDto(fees, userContext);

    List<ApplicableAccountFeeDto> applicableDefaultAccountFees =
        new ArrayList<ApplicableAccountFeeDto>();
    for (FeeDto fee : applicableFees.getDefaultFees()) {
      applicableDefaultAccountFees.add(
          new ApplicableAccountFeeDto(
              fee.getFeeIdValue().intValue(),
              fee.getFeeName(),
              fee.getAmount(),
              fee.isRemoved(),
              fee.isWeekly(),
              fee.isMonthly(),
              fee.isPeriodic(),
              fee.getFeeSchedule()));
    }

    List<ApplicableAccountFeeDto> applicableDefaultAdditionalFees =
        new ArrayList<ApplicableAccountFeeDto>();
    for (FeeDto fee : applicableFees.getAdditionalFees()) {
      applicableDefaultAdditionalFees.add(
          new ApplicableAccountFeeDto(
              fee.getFeeIdValue().intValue(),
              fee.getFeeName(),
              fee.getAmount(),
              fee.isRemoved(),
              fee.isWeekly(),
              fee.isMonthly(),
              fee.isPeriodic(),
              fee.getFeeSchedule()));
    }

    return new CenterFormCreationDto(
        activeLoanOfficersForBranch, applicableDefaultAdditionalFees, applicableDefaultAccountFees);
  }
  @Override
  public CenterInformationDto getCenterInformationDto(String globalCustNum) {

    MifosUser user =
        (MifosUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    UserContext userContext = toUserContext(user);

    CenterBO center = customerDao.findCenterBySystemId(globalCustNum);
    if (center == null) {
      throw new MifosRuntimeException("Center not found for globalCustNum" + globalCustNum);
    }

    try {
      personnelDao.checkAccessPermission(
          userContext, center.getOfficeId(), center.getLoanOfficerId());
    } catch (AccountException e) {
      throw new MifosRuntimeException("Access denied!", e);
    }

    CenterDisplayDto centerDisplay =
        customerDao.getCenterDisplayDto(center.getCustomerId(), userContext);

    Integer centerId = center.getCustomerId();
    String searchId = center.getSearchId();
    Short branchId = centerDisplay.getBranchId();

    CustomerAccountSummaryDto customerAccountSummary =
        customerDao.getCustomerAccountSummaryDto(centerId);

    CenterPerformanceHistoryDto centerPerformanceHistory =
        customerDao.getCenterPerformanceHistory(searchId, branchId);

    CustomerAddressDto centerAddress = customerDao.getCustomerAddressDto(center);

    List<CustomerDetailDto> groups =
        customerDao.getGroupsOtherThanClosedAndCancelledForGroup(searchId, branchId);

    List<CustomerNoteDto> recentCustomerNotes = customerDao.getRecentCustomerNoteDto(centerId);

    List<CustomerPositionOtherDto> customerPositions =
        customerDao.getCustomerPositionDto(centerId, userContext);

    List<SavingsDetailDto> savingsDetail = customerDao.getSavingsDetailDto(centerId, userContext);

    CustomerMeetingDto customerMeeting =
        customerDao.getCustomerMeetingDto(center.getCustomerMeeting(), userContext);

    Boolean activeSurveys =
        Boolean.FALSE; // new SurveysPersistence().isActiveSurveysForSurveyType(SurveyType.CENTER);

    List<SurveyDto> customerSurveys = new ArrayList<SurveyDto>();

    List<CustomFieldDto> customFields = new ArrayList<CustomFieldDto>();

    return new CenterInformationDto(
        centerDisplay,
        customerAccountSummary,
        centerPerformanceHistory,
        centerAddress,
        groups,
        recentCustomerNotes,
        customerPositions,
        savingsDetail,
        customerMeeting,
        activeSurveys,
        customerSurveys,
        customFields);
  }
  @Override
  public ParsedClientsDto save(ParsedClientsDto parsedClientsDto) {
    MifosUser user =
        (MifosUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    UserContext userContext = toUserContext(user);

    OfficeBO userOffice = this.officeDao.findOfficeById(userContext.getBranchId());
    userContext.setBranchGlobalNum(userOffice.getGlobalOfficeNum());

    DateTimeService dateTimeService = new DateTimeService();

    /* Construct ClientBO objects */
    List<NewClientDto> newClients = new ArrayList<NewClientDto>();

    for (ImportedClientDetail importedClient : parsedClientsDto.getSuccessfullyParsedRows()) {
      String secondMiddleName = null;
      ClientCreationDetail clientCreationDetail = importedClient.getClientCreationDetail();

      PersonnelBO formedBy = null;

      /* Client name details */
      ClientNameDetailDto clientNameDetails = clientCreationDetail.getClientNameDetailDto();
      ClientNameDetailEntity clientNameDetailEntity =
          new ClientNameDetailEntity(null, secondMiddleName, clientNameDetails);

      ClientDetailEntity clientDetailEntity = new ClientDetailEntity();
      clientDetailEntity.updateClientDetails(clientCreationDetail.getClientPersonalDetailDto());

      String clientFirstName = clientNameDetails.getFirstName();
      String clientLastName = clientNameDetails.getLastName();
      String secondLastName = clientNameDetails.getSecondLastName();

      /* Spouse/father name details */
      ClientNameDetailEntity spouseFatherNameDetailEntity = null;
      if (clientCreationDetail.getSpouseFatherName() != null) {
        spouseFatherNameDetailEntity =
            new ClientNameDetailEntity(
                null, secondMiddleName, clientCreationDetail.getSpouseFatherName());
      }
      /* Data conversion */
      DateTime dateOfBirth = new DateTime(clientCreationDetail.getDateOfBirth());
      DateTime mfiJoiningDate = new DateTime(clientCreationDetail.getMfiJoiningDate());
      DateTime trainedDateTime = null;
      if (clientCreationDetail.getTrainedDate() != null) {
        trainedDateTime = new DateTime(clientCreationDetail.getTrainedDate());
      }
      /* Status */
      CustomerStatus clientStatus = CustomerStatus.fromInt(clientCreationDetail.getClientStatus());
      CustomerStatus finalStatus = clientStatus;
      if (clientStatus == CustomerStatus.CLIENT_ACTIVE
          && clientCreationDetail.getActivationDate() == null) {
        clientStatus = CustomerStatus.CLIENT_PENDING;
      }
      /* Address */
      Address address = null;
      if (clientCreationDetail.getAddress() != null) {
        AddressDto dto = clientCreationDetail.getAddress();
        address =
            new Address(
                dto.getLine1(),
                dto.getLine2(),
                dto.getLine3(),
                dto.getCity(),
                dto.getState(),
                dto.getCountry(),
                dto.getZip(),
                dto.getPhoneNumber());
      }
      // empty list
      List<ClientInitialSavingsOfferingEntity> associatedOfferings =
          new ArrayList<ClientInitialSavingsOfferingEntity>();
      // client object
      ClientBO client;
      if (clientCreationDetail.getGroupFlag() == 1) {
        CustomerBO group =
            customerDao.findCustomerBySystemId(clientCreationDetail.getParentGroupId());

        if (clientCreationDetail.getFormedBy() != null) {
          formedBy = this.personnelDao.findPersonnelById(clientCreationDetail.getFormedBy());
        } else {
          formedBy = group.getPersonnel();
        }

        client =
            ClientBO.createNewInGroupHierarchy(
                userContext,
                clientCreationDetail.getClientName(),
                clientStatus,
                mfiJoiningDate,
                group,
                formedBy,
                clientNameDetailEntity,
                dateOfBirth,
                clientCreationDetail.getGovernmentId(),
                clientCreationDetail.isTrained(),
                trainedDateTime,
                clientCreationDetail.getGroupFlag(),
                clientFirstName,
                clientLastName,
                secondLastName,
                spouseFatherNameDetailEntity,
                clientDetailEntity,
                associatedOfferings,
                clientCreationDetail.getExternalId(),
                address,
                clientCreationDetail.getActivationDate());
      } else {
        Short officeId = clientCreationDetail.getOfficeId();
        Short officerId = clientCreationDetail.getLoanOfficerId();

        PersonnelBO loanOfficer = personnelDao.findPersonnelById(officerId);
        OfficeBO office = this.officeDao.findOfficeById(officeId);

        if (clientCreationDetail.getFormedBy() != null) {
          formedBy = this.personnelDao.findPersonnelById(clientCreationDetail.getFormedBy());
        } else {
          formedBy = loanOfficer;
        }

        int lastSearchIdCustomerValue =
            customerDao.retrieveLastSearchIdValueForNonParentCustomersInOffice(officeId);

        /* meeting */
        final MeetingDto meetingDto = importedClient.getMeeting();
        MeetingBO clientMeeting = null;
        if (meetingDto != null) {
          clientMeeting = new MeetingFactory().create(meetingDto);
          clientMeeting.setUserContext(userContext);
        }

        client =
            ClientBO.createNewOutOfGroupHierarchy(
                userContext,
                clientCreationDetail.getClientName(),
                clientStatus,
                mfiJoiningDate,
                office,
                loanOfficer,
                clientMeeting,
                formedBy,
                clientNameDetailEntity,
                dateOfBirth,
                clientCreationDetail.getGovernmentId(),
                clientCreationDetail.isTrained(),
                trainedDateTime,
                clientCreationDetail.getGroupFlag(),
                clientFirstName,
                clientLastName,
                secondLastName,
                spouseFatherNameDetailEntity,
                clientDetailEntity,
                associatedOfferings,
                clientCreationDetail.getExternalId(),
                address,
                lastSearchIdCustomerValue);

        if (clientCreationDetail.getActivationDate() != null) {
          client.setCustomerActivationDate(
              clientCreationDetail.getActivationDate().toDateMidnight().toDate());
        }
      }
      // global id
      if (importedClient.getClientGlobalNum() != null) {
        client.setGlobalCustNum(importedClient.getClientGlobalNum());
      }

      NewClientDto newClient = new NewClientDto(client, finalStatus);

      newClients.add(newClient);
    }

    /* Validate client data */
    for (NewClientDto newClient : newClients) {
      ClientBO client = newClient.getClientBO();
      try {
        client.validate();
        customerDao.validateClientForDuplicateNameOrGovtId(
            client.getDisplayName(), client.getDateOfBirth(), client.getGovernmentId());
      } catch (CustomerException ex) {
        throw new MifosRuntimeException(ex);
      }
    }

    /* Save clients */
    List<AccountFeesEntity> accountFees = new ArrayList<AccountFeesEntity>(); // empty list
    try {
      hibernateTransactionHelper.startTransaction();
      for (NewClientDto newClient : newClients) {

        ClientBO client = newClient.getClientBO();
        CustomerStatus finalStatus = newClient.getCustomerStatus();
        // status to pending approval if active

        MeetingBO meeting = client.getCustomerMeetingValue();

        customerDao.save(client);
        hibernateTransactionHelper.flushSession();

        CalendarEvent applicableCalendarEvents =
            holidayDao.findCalendarEventsForThisYearAndNext(client.getOfficeId());
        CustomerAccountBO customerAccount =
            customerAccountFactory.create(client, accountFees, meeting, applicableCalendarEvents);
        client.addAccount(customerAccount);
        customerDao.save(client);
        hibernateTransactionHelper.flushSession();

        if (client.getParentCustomer() != null) {
          customerDao.save(client.getParentCustomer());
        }

        if (client.getGlobalCustNum() == null) {
          client.generateGlobalCustomerNumber();
        }
        client.generateSearchId();
        customerDao.save(client);
        hibernateTransactionHelper.flushSession();

        if (client.getParentCustomer() != null) {
          customerDao.save(client.getParentCustomer());
        }

        /* activate client */
        if (finalStatus == CustomerStatus.CLIENT_ACTIVE) {
          hibernateTransactionHelper.flushSession();
          hibernateTransactionHelper.beginAuditLoggingFor(client);
          client.clearCustomerFlagsIfApplicable(client.getStatus(), finalStatus);

          client.updateCustomerStatus(finalStatus);
          // changeStatus(client, oldStatus, newStatus);
          if (client.getParentCustomer() != null) {
            CustomerHierarchyEntity hierarchy =
                new CustomerHierarchyEntity(client, client.getParentCustomer());
            client.addCustomerHierarchy(hierarchy);
          }

          if (client.getCustomerActivationDate() != null) {
            client.setCustomerActivationDate(client.getCustomerActivationDate());
          } else {
            client.setCustomerActivationDate(dateTimeService.getCurrentJavaDateTime());
          }
          customerAccount.createSchedulesAndFeeSchedulesForFirstTimeActiveCustomer(
              client,
              accountFees,
              meeting,
              applicableCalendarEvents,
              new DateTime(client.getCustomerActivationDate()));

          customerDao.save(client);
        }
      }
      hibernateTransactionHelper.commitTransaction();
    } catch (Exception ex) {
      hibernateTransactionHelper.rollbackTransaction();
      throw new MifosRuntimeException(ex);
    }

    return parsedClientsDto;
  }