@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 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 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 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 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);
    }
  }
  @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 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);
  }
 @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 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());
 }
  @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);
    }
  }