@Override
  public void createCustomerNote(CustomerNoteFormDto customerNoteForm) {

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

    CustomerBO customer = this.customerDao.findCustomerBySystemId(customerNoteForm.getGlobalNum());
    customer.updateDetails(userContext);

    PersonnelBO loggedInUser = this.personnelDao.findPersonnelById(userContext.getId());

    CustomerNoteEntity customerNote =
        new CustomerNoteEntity(
            customerNoteForm.getComment(),
            new DateTimeService().getCurrentJavaSqlDate(),
            loggedInUser,
            customer);
    customer.addCustomerNotes(customerNote);

    try {
      this.transactionHelper.startTransaction();
      this.customerDao.save(customer);
      this.transactionHelper.commitTransaction();
    } catch (Exception e) {
      this.transactionHelper.rollbackTransaction();
      throw new BusinessRuleException(customer.getCustomerAccount().getAccountId().toString(), e);
    } finally {
      this.transactionHelper.closeSession();
    }
  }
  @Override
  public List<TransactionHistoryDto> retrieveAccountTransactionHistory(String globalAccountNum) {

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

    try {
      AccountBO account = new AccountBusinessService().findBySystemId(globalAccountNum);
      account.updateDetails(userContext);

      List<TransactionHistoryDto> transactionHistories = account.getTransactionHistoryView();
      for (TransactionHistoryDto transactionHistoryDto : transactionHistories) {
        transactionHistoryDto.setUserPrefferedPostedDate(
            DateUtils.getUserLocaleDate(
                userContext.getPreferredLocale(),
                transactionHistoryDto.getPostedDate().toString()));
        transactionHistoryDto.setUserPrefferedTransactionDate(
            DateUtils.getUserLocaleDate(
                userContext.getPreferredLocale(),
                transactionHistoryDto.getTransactionDate().toString()));
      }
      return transactionHistories;
    } catch (ServiceException e) {
      throw new MifosRuntimeException(e);
    }
  }
  @Override
  public void addNoteToPersonnel(Short personnelId, String comment) {

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

    try {
      PersonnelBO personnel = this.personnelDao.findPersonnelById(personnelId);
      PersonnelBO loggedInUser = this.personnelDao.findPersonnelById(userContext.getId());
      if (personnel != null) {
        checkPermissionForAddingNotesToPersonnel(
            userContext, personnel.getOffice().getOfficeId(), personnel.getPersonnelId());
      }

      this.transactionHelper.startTransaction();
      PersonnelNotesEntity personnelNote =
          new PersonnelNotesEntity(comment, loggedInUser, personnel);
      personnel.addNotes(userContext.getId(), personnelNote);
      this.personnelDao.save(personnel);
      this.transactionHelper.commitTransaction();
    } catch (Exception e) {
      this.transactionHelper.rollbackTransaction();
      throw new MifosRuntimeException(e);
    } finally {
      this.transactionHelper.closeSession();
    }
  }
  @Override
  public boolean isPaymentPermitted(Integer accountId) {

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

    try {
      AccountBO account = new AccountBusinessService().getAccount(accountId);

      CustomerLevel customerLevel = null;
      if (account.getType().equals(AccountTypes.CUSTOMER_ACCOUNT)) {
        customerLevel = account.getCustomer().getLevel();
      }

      Short personnelId = userContext.getId();
      if (account.getPersonnel() != null) {
        personnelId = account.getPersonnel().getPersonnelId();
      }

      return ActivityMapper.getInstance()
          .isPaymentPermittedForAccounts(
              account.getType(),
              customerLevel,
              userContext,
              account.getOffice().getOfficeId(),
              personnelId);
    } catch (ServiceException e) {
      throw new MifosRuntimeException(e);
    }
  }
 private SavingsBO createSavingsAccount(
     String globalAccountNum, SavingsOfferingBO savingsOffering, AccountState state)
     throws Exception {
   UserContext userContext = new UserContext(Locale.getDefault(), Short.valueOf("1"));
   userContext.setId(PersonnelConstants.SYSTEM_USER);
   userContext.setBranchGlobalNum("1001");
   return TestObjectFactory.createSavingsAccount(
       globalAccountNum, group, state, new Date(), savingsOffering, userContext);
 }
  @Override
  public void waiveChargesDue(Integer accountId, Integer waiveType) {

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

    try {
      AccountBO account = new AccountBusinessService().getAccount(accountId);
      account.updateDetails(userContext);
      PersonnelBO loggedInUser = this.personnelDao.findPersonnelById(userContext.getId());

      WaiveEnum waiveEnum = WaiveEnum.fromInt(waiveType);
      if (account.getPersonnel() != null) {
        new AccountBusinessService()
            .checkPermissionForWaiveDue(
                waiveEnum,
                account.getType(),
                account.getCustomer().getLevel(),
                userContext,
                account.getOffice().getOfficeId(),
                account.getPersonnel().getPersonnelId());
      } else {
        new AccountBusinessService()
            .checkPermissionForWaiveDue(
                waiveEnum,
                account.getType(),
                account.getCustomer().getLevel(),
                userContext,
                account.getOffice().getOfficeId(),
                userContext.getId());
      }

      if (account.isLoanAccount()) {
        ((LoanBO) account).waiveAmountDue(waiveEnum);
      } else if (account.isSavingsAccount()) {
        ((SavingsBO) account).waiveNextDepositAmountDue(loggedInUser);
      } else {
        try {
          this.transactionHelper.startTransaction();
          ((CustomerAccountBO) account).waiveAmountDue();
          this.customerDao.save(account);
          this.transactionHelper.commitTransaction();
        } catch (Exception e) {
          this.transactionHelper.rollbackTransaction();
          throw new BusinessRuleException(account.getAccountId().toString(), e);
        } finally {
          this.transactionHelper.closeSession();
        }
      }
    } catch (ServiceException e) {
      throw new MifosRuntimeException(e);
    } catch (ApplicationException e) {
      throw new BusinessRuleException(e.getKey(), e);
    }
  }
  @Override
  public CustomerDetailsDto createNewCenter(
      CenterCreationDetail createCenterDetail, MeetingDto meetingDto) {

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

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

    String centerName = createCenterDetail.getDisplayName();
    String externalId = createCenterDetail.getExternalId();
    AddressDto addressDto = createCenterDetail.getAddressDto();
    Address centerAddress =
        new Address(
            addressDto.getLine1(),
            addressDto.getLine2(),
            addressDto.getLine3(),
            addressDto.getCity(),
            addressDto.getState(),
            addressDto.getCountry(),
            addressDto.getZip(),
            addressDto.getPhoneNumber());
    PersonnelBO loanOfficer =
        this.personnelDao.findPersonnelById(createCenterDetail.getLoanOfficerId());
    OfficeBO centerOffice = this.officeDao.findOfficeById(createCenterDetail.getOfficeId());

    List<AccountFeesEntity> feesForCustomerAccount =
        createAccountFeeEntities(createCenterDetail.getFeesToApply());

    DateTime mfiJoiningDate = null;
    if (createCenterDetail.getMfiJoiningDate() != null) {
      mfiJoiningDate = createCenterDetail.getMfiJoiningDate().toDateMidnight().toDateTime();
    }

    MeetingBO meeting = new MeetingFactory().create(meetingDto);
    meeting.setUserContext(userContext);

    CenterBO center =
        CenterBO.createNew(
            userContext,
            centerName,
            mfiJoiningDate,
            meeting,
            loanOfficer,
            centerOffice,
            centerAddress,
            externalId,
            new DateMidnight().toDateTime());

    this.customerService.createCenter(center, meeting, feesForCustomerAccount);

    return new CustomerDetailsDto(center.getCustomerId(), center.getGlobalCustNum());
  }
 private Locale getUserLocale(final HttpServletRequest request) {
   Locale locale = null;
   HttpSession session = request.getSession();
   if (session != null) {
     UserContext userContext = (UserContext) session.getAttribute(LoginConstants.USERCONTEXT);
     if (null != userContext) {
       locale = userContext.getCurrentLocale();
     }
   }
   return locale;
 }
  @TransactionDemarcate(joinToken = true)
  public ActionForward load(
      final ActionMapping mapping,
      final ActionForm form,
      final HttpServletRequest request,
      @SuppressWarnings("unused") final HttpServletResponse response)
      throws Exception {

    LoanDisbursementActionForm loanDisbursementActionForm = (LoanDisbursementActionForm) form;
    loanDisbursementActionForm.clear();
    loanDisbursementActionForm.setAmountCannotBeZero(false);

    Integer loanAccountId = Integer.valueOf(loanDisbursementActionForm.getAccountId());
    LoanDisbursalDto loanDisbursalDto =
        loanAccountServiceFacade.retrieveLoanDisbursalDetails(loanAccountId);

    UserContext uc = getUserContext(request);
    SessionUtils.setAttribute(
        LoanConstants.PROPOSED_DISBURSAL_DATE, loanDisbursalDto.getProposedDate(), request);
    loanDisbursementActionForm.setTransactionDate(
        getUserLocaleDate(uc.getPreferredLocale(), loanDisbursalDto.getProposedDate()));

    loanDisbursementActionForm.setAmount(loanDisbursalDto.getAmountPaidAtDisbursement());
    loanDisbursementActionForm.setLoanAmount(loanDisbursalDto.getLoanAmount());
    if (loanDisbursalDto.isMultiCurrencyEnabled()) {
      loanDisbursementActionForm.setCurrencyId(loanDisbursalDto.getCurrencyId());
    }

    Short repaymentIndependentOfMeetingScheduleValue =
        loanDisbursalDto.isRepaymentIndependentOfMeetingSchedule()
            ? Short.valueOf("1")
            : Short.valueOf("0");
    SessionUtils.setAttribute(
        LoanConstants.REPAYMENT_SCHEDULES_INDEPENDENT_OF_MEETING_IS_ENABLED,
        repaymentIndependentOfMeetingScheduleValue,
        request);
    SessionUtils.setAttribute(
        AccountingRulesConstants.BACKDATED_TRANSACTIONS_ALLOWED,
        loanDisbursalDto.isBackDatedTransactionsAllowed(),
        request);

    List<PaymentTypeEntity> disbursementTypes =
        legacyAcceptedPaymentTypeDao.getAcceptedPaymentTypesForATransaction(
            uc.getLocaleId(), TrxnTypes.loan_disbursement.getValue());
    SessionUtils.setCollectionAttribute(MasterConstants.PAYMENT_TYPE, disbursementTypes, request);

    List<PaymentTypeEntity> feesTypes =
        legacyAcceptedPaymentTypeDao.getAcceptedPaymentTypesForATransaction(
            uc.getLocaleId(), TrxnTypes.loan_repayment.getValue());
    SessionUtils.setCollectionAttribute(MasterConstants.FEE_PAYMENT_TYPE, feesTypes, request);

    return mapping.findForward(Constants.LOAD_SUCCESS);
  }
 @Override
 protected void setUp() throws Exception {
   super.setUp();
   userContext = TestUtils.makeUser();
   request.getSession().setAttribute(Constants.USERCONTEXT, userContext);
   addRequestParameter("recordLoanOfficerId", "1");
   addRequestParameter("recordOfficeId", "1");
   ActivityContext ac =
       new ActivityContext(
           (short) 0, userContext.getBranchId().shortValue(), userContext.getId().shortValue());
   request.getSession(false).setAttribute("ActivityContext", ac);
   flowKey = createFlow(request, CollectionSheetEntryAction.class);
 }
 private void checkPermissionForAdjustment(AccountBO accountBO) throws ServiceException {
   AccountPaymentEntity lastPmntToBeAdjusted = accountBO.getLastPmntToBeAdjusted();
   if (lastPmntToBeAdjusted == null) return;
   UserContext userContext = accountBO.getUserContext();
   Date lastPaymentDate = lastPmntToBeAdjusted.getPaymentDate();
   PersonnelBO personnel = accountBO.getPersonnel();
   Short personnelId = personnel != null ? personnel.getPersonnelId() : userContext.getId();
   Short officeId = accountBO.getOfficeId();
   accountBusinessService.checkPermissionForAdjustment(
       AccountTypes.LOAN_ACCOUNT, null, userContext, officeId, personnelId);
   accountBusinessService.checkPermissionForAdjustmentOnBackDatedPayments(
       lastPaymentDate, userContext, officeId, personnelId);
 }
  @Override
  public void removeAccountFee(Integer accountId, Short feeId) {

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

    try {
      AccountBO account = new AccountBusinessService().getAccount(accountId);

      account.updateDetails(userContext);

      if (account.getPersonnel() != null) {
        new AccountBusinessService()
            .checkPermissionForRemoveFees(
                account.getType(),
                account.getCustomer().getLevel(),
                userContext,
                account.getOffice().getOfficeId(),
                account.getPersonnel().getPersonnelId());
      } else {
        new AccountBusinessService()
            .checkPermissionForRemoveFees(
                account.getType(),
                account.getCustomer().getLevel(),
                userContext,
                account.getOffice().getOfficeId(),
                userContext.getId());
      }

      this.transactionHelper.startTransaction();
      account.removeFeesAssociatedWithUpcomingAndAllKnownFutureInstallments(
          feeId, userContext.getId());
      this.customerDao.save(account);
      this.transactionHelper.commitTransaction();
    } catch (ServiceException e) {
      this.transactionHelper.rollbackTransaction();
      throw new MifosRuntimeException(e);
    } catch (AccountException e) {
      this.transactionHelper.rollbackTransaction();
      throw new BusinessRuleException(e.getKey(), e);
    } catch (ApplicationException e) {
      this.transactionHelper.rollbackTransaction();
      throw new BusinessRuleException(e.getKey(), e);
    } finally {
      this.transactionHelper.closeSession();
    }
  }
  private PersonnelBO createPersonnel(OfficeBO office, PersonnelLevel personnelLevel)
      throws Exception {
    List<CustomFieldDto> customFieldDto = new ArrayList<CustomFieldDto>();
    customFieldDto.add(
        new CustomFieldDto(Short.valueOf("9"), "123456", CustomFieldType.NUMERIC.getValue()));
    Address address = new Address("abcd", "abcd", "abcd", "abcd", "abcd", "abcd", "abcd", "abcd");
    Name name = new Name("XYZ", null, null, null);
    java.util.Date date = new java.util.Date();
    personnel =
        new PersonnelBO(
            personnelLevel,
            office,
            Integer.valueOf("1"),
            Short.valueOf("1"),
            "ABCD",
            "XYZ",
            "*****@*****.**",
            null,
            customFieldDto,
            name,
            "111111",
            date,
            Integer.valueOf("1"),
            Integer.valueOf("1"),
            date,
            date,
            address,
            userContext.getId());

    IntegrationTestObjectMother.createPersonnel(personnel);
    return IntegrationTestObjectMother.findPersonnelById(personnel.getPersonnelId());
  }
  @Override
  public void revertLastChargesPayment(String globalCustNum, String adjustmentNote) {

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

    PersonnelBO loggedInUser = this.personnelDao.findPersonnelById(userContext.getId());
    CustomerBO customerBO = this.customerDao.findCustomerBySystemId(globalCustNum);
    customerBO.updateDetails(userContext);

    if (customerBO.getCustomerAccount().findMostRecentNonzeroPaymentByPaymentDate() != null) {
      customerBO.getCustomerAccount().updateDetails(userContext);

      try {
        if (customerBO.getPersonnel() != null) {
          new AccountBusinessService()
              .checkPermissionForAdjustment(
                  AccountTypes.CUSTOMER_ACCOUNT,
                  customerBO.getLevel(),
                  userContext,
                  customerBO.getOffice().getOfficeId(),
                  customerBO.getPersonnel().getPersonnelId());
        } else {
          new AccountBusinessService()
              .checkPermissionForAdjustment(
                  AccountTypes.CUSTOMER_ACCOUNT,
                  customerBO.getLevel(),
                  userContext,
                  customerBO.getOffice().getOfficeId(),
                  userContext.getId());
        }

        this.transactionHelper.startTransaction();
        customerBO.adjustPmnt(adjustmentNote, loggedInUser);
        this.customerDao.save(customerBO);
        this.transactionHelper.commitTransaction();
      } catch (SystemException e) {
        this.transactionHelper.rollbackTransaction();
        throw new MifosRuntimeException(e);
      } catch (ApplicationException e) {
        this.transactionHelper.rollbackTransaction();
        throw new BusinessRuleException(e.getKey(), e);
      }
    }
  }
 @CloseSession
 @TransactionDemarcate(validateAndResetToken = true)
 public ActionForward create(
     ActionMapping mapping,
     ActionForm form,
     HttpServletRequest request,
     HttpServletResponse response)
     throws Exception {
   logger.debug("In CustomerNotesAction::create()");
   ActionForward forward = null;
   CustomerNotesActionForm notesActionForm = (CustomerNotesActionForm) form;
   CustomerBO customerBO =
       getCustomerBusinessService()
           .getCustomer(Integer.valueOf(((CustomerNotesActionForm) form).getCustomerId()));
   UserContext uc = getUserContext(request);
   if (customerBO.getPersonnel() != null) {
     checkPermissionForAddingNotes(
         AccountTypes.CUSTOMER_ACCOUNT,
         customerBO.getLevel(),
         uc,
         customerBO.getOffice().getOfficeId(),
         customerBO.getPersonnel().getPersonnelId());
   } else {
     checkPermissionForAddingNotes(
         AccountTypes.CUSTOMER_ACCOUNT,
         customerBO.getLevel(),
         uc,
         customerBO.getOffice().getOfficeId(),
         uc.getId());
   }
   PersonnelBO personnelBO = new PersonnelPersistence().getPersonnel(uc.getId());
   CustomerNoteEntity customerNote =
       new CustomerNoteEntity(
           notesActionForm.getComment(),
           new DateTimeService().getCurrentJavaSqlDate(),
           personnelBO,
           customerBO);
   customerBO.addCustomerNotes(customerNote);
   customerBO.setUserContext(uc);
   customerBO.update();
   forward = mapping.findForward(getDetailCustomerPage(notesActionForm));
   customerBO = null;
   return forward;
 }
  @Override
  public CustomerNoteFormDto retrieveCustomerNote(String globalCustNum) {

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

    CustomerBO customer = this.customerDao.findCustomerBySystemId(globalCustNum);
    PersonnelBO loggedInUser = this.personnelDao.findPersonnelById(userContext.getId());

    Integer customerLevel = customer.getCustomerLevel().getId().intValue();
    String globalNum = customer.getGlobalCustNum();
    String displayName = customer.getDisplayName();
    LocalDate commentDate = new LocalDate();
    String commentUser = loggedInUser.getDisplayName();

    return new CustomerNoteFormDto(
        globalNum, displayName, customerLevel, commentDate, commentUser, "");
  }
 @TransactionDemarcate(joinToken = true)
 public ActionForward load(
     ActionMapping mapping,
     ActionForm form,
     HttpServletRequest request,
     HttpServletResponse response)
     throws Exception {
   logger.debug("In CustomerNotesAction::load()");
   clearActionForm(form);
   UserContext userContext = getUserContext(request);
   CustomerBO customerBO =
       getCustomerBusinessService()
           .getCustomer(Integer.valueOf(((CustomerNotesActionForm) form).getCustomerId()));
   customerBO.setUserContext(userContext);
   setFormAttributes(userContext, form, customerBO);
   PersonnelBO personnelBO = new PersonnelPersistence().getPersonnel(userContext.getId());
   SessionUtils.removeAttribute(Constants.BUSINESS_KEY, request);
   SessionUtils.setAttribute(Constants.BUSINESS_KEY, customerBO, request);
   SessionUtils.setAttribute(
       CustomerConstants.PERSONNEL_NAME, personnelBO.getDisplayName(), request);
   return mapping.findForward(ActionForwards.load_success.toString());
 }
 private void setFormAttributes(UserContext userContext, ActionForm form, CustomerBO customerBO)
     throws ApplicationException, InvalidDateException {
   CustomerNotesActionForm notesActionForm = (CustomerNotesActionForm) form;
   notesActionForm.setLevelId(customerBO.getCustomerLevel().getId().toString());
   notesActionForm.setGlobalCustNum(customerBO.getGlobalCustNum());
   notesActionForm.setCustomerName(customerBO.getDisplayName());
   notesActionForm.setCommentDate(DateUtils.getCurrentDate(userContext.getPreferredLocale()));
   if (customerBO instanceof CenterBO) {
     notesActionForm.setInput("center");
   } else if (customerBO instanceof GroupBO) {
     notesActionForm.setInput("group");
   } else if (customerBO instanceof ClientBO) {
     notesActionForm.setInput("client");
   }
 }
  @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);
  }
  private ActionErrors mandatoryCheck(UserContext userContext) {
    Locale locale = userContext.getPreferredLocale();
    ResourceBundle resources =
        ResourceBundle.getBundle(FilePaths.SIMPLE_ACCOUNTING_RESOURCE, locale);

    String trxn_Date = resources.getString(SimpleAccountingConstants.TRXNDATE);
    String officeId = resources.getString(SimpleAccountingConstants.OFFICE);

    ActionErrors errors = new ActionErrors();
    if (branch == null || "".equals(branch.trim())) {
      errors.add(
          SimpleAccountingConstants.MANDATORYFIELDS,
          new ActionMessage(SimpleAccountingConstants.MANDATORYFIELDS, officeId));
    }

    return errors;
  }
  @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;
  }
  private ActionErrors mandatoryCheck(
      Date meetingDate, UserContext userContext, short isCenterHierarchyExists) {
    Locale locale = userContext.getPreferredLocale();
    ResourceBundle resources = ResourceBundle.getBundle(FilePaths.BULKENTRY_RESOURCE, locale);
    String loanOfficer = resources.getString(CollectionSheetEntryConstants.LOANOFFICERS);
    String modeOfPayment = resources.getString(CollectionSheetEntryConstants.MODE_OF_PAYMENT);
    String dateOfTransaction = resources.getString(CollectionSheetEntryConstants.DATEOFTRXN);
    ActionErrors errors = receiptDateValidate(new ActionErrors(), locale);
    java.sql.Date currentDate = null;
    try {
      currentDate =
          DateUtils.getLocaleDate(
              userContext.getPreferredLocale(),
              DateUtils.getCurrentDate(userContext.getPreferredLocale()));
    } catch (InvalidDateException ide) {
      errors.add(
          CollectionSheetEntryConstants.INVALIDDATE,
          new ActionMessage(CollectionSheetEntryConstants.INVALIDDATE));
    }

    java.sql.Date trxnDate = null;
    String customerLabel =
        isCenterHierarchyExists == Constants.YES
            ? ConfigurationConstants.CENTER
            : ConfigurationConstants.GROUP;

    if (officeId == null || "".equals(officeId.trim())) {
      errors.add(
          CollectionSheetEntryConstants.MANDATORYFIELDS,
          new ActionMessage(
              CollectionSheetEntryConstants.MANDATORYFIELDS,
              getMessageText(ConfigurationConstants.BRANCHOFFICE, userContext)));
    }

    if (loanOfficerId == null || "".equals(loanOfficerId.trim())) {
      errors.add(
          CollectionSheetEntryConstants.MANDATORYFIELDS,
          new ActionMessage(CollectionSheetEntryConstants.MANDATORYFIELDS, loanOfficer));
    }

    if (customerId == null || "".equals(customerId.trim())) {
      errors.add(
          CollectionSheetEntryConstants.MANDATORYFIELDS,
          new ActionMessage(
              CollectionSheetEntryConstants.MANDATORYFIELDS, getLabel(customerLabel, userContext)));
    }

    if (getTransactionDate() != null && !getTransactionDate().equals("")) {
      try {
        trxnDate = DateUtils.getDateAsSentFromBrowser(getTransactionDate());
      } catch (InvalidDateException ide) {
        errors.add(
            CollectionSheetEntryConstants.MANDATORYFIELDS,
            new ActionMessage(AccountConstants.ERROR_INVALID_TRXN));
      }
    } else {
      errors.add(
          CollectionSheetEntryConstants.MANDATORYFIELDS,
          new ActionMessage(CollectionSheetEntryConstants.MANDATORYENTER, dateOfTransaction));
    }

    if (currentDate != null
        && meetingDate != null
        && trxnDate != null
        && (meetingDate.compareTo(trxnDate) > 0 || trxnDate.compareTo(currentDate) > 0)) {
      errors.add(
          CollectionSheetEntryConstants.MANDATORYFIELDS,
          new ActionMessage(CollectionSheetEntryConstants.INVALIDENDDATE, dateOfTransaction));
    } else if (meetingDate == null && trxnDate != null && trxnDate.compareTo(currentDate) != 0) {
      errors.add(
          CollectionSheetEntryConstants.MANDATORYFIELDS,
          new ActionMessage(CollectionSheetEntryConstants.MEETINGDATEEXCEPTION, dateOfTransaction));
    }

    if (paymentId == null || "".equals(paymentId.trim())) {
      errors.add(
          CollectionSheetEntryConstants.MANDATORYFIELDS,
          new ActionMessage(CollectionSheetEntryConstants.MANDATORYFIELDS, modeOfPayment));
    }

    return errors;
  }
  @TransactionDemarcate(validateAndResetToken = true)
  @CloseSession
  public ActionForward update(
      final ActionMapping mapping,
      final ActionForm form,
      final HttpServletRequest request,
      @SuppressWarnings("unused") final HttpServletResponse response)
      throws Exception {

    LoanDisbursementActionForm actionForm = (LoanDisbursementActionForm) form;

    UserContext uc = getUserContext(request);
    Date trxnDate = getDateFromString(actionForm.getTransactionDate(), uc.getPreferredLocale());
    trxnDate = DateUtils.getDateWithoutTimeStamp(trxnDate.getTime());
    Date receiptDate = getDateFromString(actionForm.getReceiptDate(), uc.getPreferredLocale());

    Integer loanAccountId = Integer.valueOf(actionForm.getAccountId());
    AccountBO accountBO = new AccountBusinessService().getAccount(loanAccountId);

    createGroupQuestionnaire.saveResponses(request, actionForm, loanAccountId);

    try {
      String paymentTypeIdStringForDisbursement = actionForm.getPaymentTypeId();
      Short paymentTypeIdForDisbursement =
          StringUtils.isEmpty(paymentTypeIdStringForDisbursement)
              ? PaymentTypes.CASH.getValue()
              : Short.valueOf(paymentTypeIdStringForDisbursement);

      Short paymentTypeId = Short.valueOf(paymentTypeIdForDisbursement);
      final String comment = "";
      final BigDecimal disbursalAmount = new BigDecimal(actionForm.getLoanAmount());
      CustomerDto customerDto = null;

      PaymentTypeDto paymentType = null;
      AccountPaymentParametersDto loanDisbursement =
          new AccountPaymentParametersDto(
              new UserReferenceDto(uc.getId()),
              new AccountReferenceDto(loanAccountId),
              disbursalAmount,
              new LocalDate(trxnDate),
              paymentType,
              comment,
              new LocalDate(receiptDate),
              actionForm.getReceiptId(),
              customerDto);

      monthClosingServiceFacade.validateTransactionDate(trxnDate);

      // GLIM
      List<LoanBO> individualLoans = this.loanDao.findIndividualLoans(loanAccountId);
      for (LoanBO individual : individualLoans) {
        if (!loanAccountServiceFacade.isTrxnDateValid(
            Integer.valueOf(individual.getAccountId()), trxnDate)) {
          throw new BusinessRuleException("errors.invalidTxndateOfDisbursal");
        }
      }

      this.loanAccountServiceFacade.disburseLoan(loanDisbursement, paymentTypeId);

      for (LoanBO individual : individualLoans) {
        loanDisbursement =
            new AccountPaymentParametersDto(
                new UserReferenceDto(uc.getId()),
                new AccountReferenceDto(individual.getAccountId()),
                individual.getLoanAmount().getAmount(),
                new LocalDate(trxnDate),
                paymentType,
                comment,
                new LocalDate(receiptDate),
                actionForm.getReceiptId(),
                customerDto);

        this.loanAccountServiceFacade.disburseLoan(loanDisbursement, paymentTypeId);
      }
    } catch (BusinessRuleException e) {
      throw new AccountException(e.getMessage());
    } catch (MifosRuntimeException e) {
      if (e.getCause() != null && e.getCause() instanceof AccountException) {
        throw new AccountException(e.getCause().getMessage());
      }
      String msg = "errors.cannotDisburseLoan.because.disburseFailed";
      logger.error(msg, e);
      throw new AccountException(msg);
    } catch (Exception e) {
      String msg = "errors.cannotDisburseLoan.because.disburseFailed";
      logger.error(msg, e);
      throw new AccountException(msg);
    }

    return mapping.findForward(Constants.UPDATE_SUCCESS);
  }
  @Override
  public void applyCharge(Integer accountId, Short feeId, Double chargeAmount) {

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

    try {
      AccountBO account = new AccountBusinessService().getAccount(accountId);

      if (account instanceof LoanBO) {
        List<LoanBO> individualLoans = this.loanDao.findIndividualLoans(account.getAccountId());

        if (individualLoans != null && individualLoans.size() > 0) {
          for (LoanBO individual : individualLoans) {
            individual.updateDetails(userContext);

            FeeBO fee = this.feeDao.findById(feeId);

            if (fee instanceof RateFeeBO) {
              individual.applyCharge(feeId, chargeAmount);
            } else {
              Double radio =
                  individual.getLoanAmount().getAmount().doubleValue()
                      / ((LoanBO) account).getLoanAmount().getAmount().doubleValue();

              individual.applyCharge(feeId, chargeAmount * radio);
            }
          }
        }
      }

      account.updateDetails(userContext);

      CustomerLevel customerLevel = null;
      if (account.isCustomerAccount()) {
        customerLevel = account.getCustomer().getLevel();
      }
      if (account.getPersonnel() != null) {
        checkPermissionForApplyCharges(
            account.getType(),
            customerLevel,
            userContext,
            account.getOffice().getOfficeId(),
            account.getPersonnel().getPersonnelId());
      } else {
        checkPermissionForApplyCharges(
            account.getType(),
            customerLevel,
            userContext,
            account.getOffice().getOfficeId(),
            userContext.getId());
      }

      this.transactionHelper.startTransaction();
      account.applyCharge(feeId, chargeAmount);
      this.transactionHelper.commitTransaction();
    } catch (ServiceException e) {
      this.transactionHelper.rollbackTransaction();
      throw new MifosRuntimeException(e);
    } catch (ApplicationException e) {
      this.transactionHelper.rollbackTransaction();
      throw new BusinessRuleException(e.getKey(), e);
    }
  }