@Override
  @Transactional
  public Long transferFunds(final AccountTransferDTO accountTransferDTO) {
    Long transferTransactionId = null;
    if (isSavingsToLoanAccountTransfer(
        accountTransferDTO.getFromAccountType(), accountTransferDTO.getToAccountType())) {
      //
      final SavingsAccount fromSavingsAccount =
          this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());

      final SavingsAccountTransaction withdrawal =
          this.savingsAccountDomainService.handleWithdrawal(
              fromSavingsAccount,
              accountTransferDTO.getFmt(),
              accountTransferDTO.getTransactionDate(),
              accountTransferDTO.getTransactionAmount(),
              accountTransferDTO.getPaymentDetail(),
              fromSavingsAccount.isWithdrawalFeeApplicableForTransfer());

      final Loan toLoanAccount =
          this.loanAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());

      final LoanTransaction loanRepaymentTransaction =
          this.loanAccountDomainService.makeChargePayment(
              toLoanAccount,
              accountTransferDTO.getChargeId(),
              accountTransferDTO.getTransactionDate(),
              accountTransferDTO.getTransactionAmount(),
              accountTransferDTO.getPaymentDetail(),
              null,
              null,
              accountTransferDTO.getToTransferType(),
              accountTransferDTO.getLoanInstallmentNumber());

      final AccountTransfer transferTransaction =
          this.accountTransferAssembler.assembleSavingsToLoanTransfer(
              accountTransferDTO,
              fromSavingsAccount,
              toLoanAccount,
              withdrawal,
              loanRepaymentTransaction);
      this.accountTransferRepository.saveAndFlush(transferTransaction);
      transferTransactionId = transferTransaction.getId();
    }

    return transferTransactionId;
  }
  @Transactional
  @Override
  public CommandProcessingResult create(final JsonCommand command) {

    this.accountTransfersDataValidator.validate(command);

    final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName);
    final BigDecimal transactionAmount =
        command.bigDecimalValueOfParameterNamed(transferAmountParamName);

    final Locale locale = command.extractLocale();
    final DateTimeFormatter fmt =
        DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);

    final Integer fromAccountTypeId =
        command.integerValueSansLocaleOfParameterNamed(fromAccountTypeParamName);
    final PortfolioAccountType fromAccountType = PortfolioAccountType.fromInt(fromAccountTypeId);

    final Integer toAccountTypeId =
        command.integerValueSansLocaleOfParameterNamed(toAccountTypeParamName);
    final PortfolioAccountType toAccountType = PortfolioAccountType.fromInt(toAccountTypeId);

    final PaymentDetail paymentDetail = null;
    Long fromSavingsAccountId = null;
    Long transferTransactionId = null;
    if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {

      fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
      final SavingsAccount fromSavingsAccount =
          this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId);

      final SavingsAccountTransaction withdrawal =
          this.savingsAccountDomainService.handleWithdrawal(
              fromSavingsAccount,
              fmt,
              transactionDate,
              transactionAmount,
              paymentDetail,
              fromSavingsAccount.isWithdrawalFeeApplicableForTransfer());

      final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
      final SavingsAccount toSavingsAccount =
          this.savingsAccountAssembler.assembleFrom(toSavingsId);

      final SavingsAccountTransaction deposit =
          this.savingsAccountDomainService.handleDeposit(
              toSavingsAccount, fmt, transactionDate, transactionAmount, paymentDetail);

      final AccountTransfer transferTransaction =
          this.accountTransferAssembler.assembleSavingsToSavingsTransfer(
              command, withdrawal, deposit);
      this.accountTransferRepository.saveAndFlush(transferTransaction);
      transferTransactionId = transferTransaction.getId();

    } else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) {
      //
      fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
      final SavingsAccount fromSavingsAccount =
          this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId);

      final SavingsAccountTransaction withdrawal =
          this.savingsAccountDomainService.handleWithdrawal(
              fromSavingsAccount,
              fmt,
              transactionDate,
              transactionAmount,
              paymentDetail,
              fromSavingsAccount.isWithdrawalFeeApplicableForTransfer());

      final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
      final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId);

      final LoanTransaction loanRepaymentTransaction =
          this.loanAccountDomainService.makeRepayment(
              toLoanAccount,
              new CommandProcessingResultBuilder(),
              transactionDate,
              transactionAmount,
              paymentDetail,
              null,
              null);

      final AccountTransfer transferTransaction =
          this.accountTransferAssembler.assembleSavingsToLoanTransfer(
              command, fromSavingsAccount, toLoanAccount, withdrawal, loanRepaymentTransaction);
      this.accountTransferRepository.saveAndFlush(transferTransaction);
      transferTransactionId = transferTransaction.getId();

    } else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) {
      // FIXME - kw - ADD overpaid loan to savings account transfer
      // support.

      //
      final Long fromLoanAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
      final Loan fromLoanAccount = this.loanAccountAssembler.assembleFrom(fromLoanAccountId);

      final LoanTransaction loanRefundTransaction =
          this.loanAccountDomainService.makeRefund(
              fromLoanAccountId,
              new CommandProcessingResultBuilder(),
              transactionDate,
              transactionAmount,
              paymentDetail,
              null,
              null);

      final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
      final SavingsAccount toSavingsAccount =
          this.savingsAccountAssembler.assembleFrom(toSavingsAccountId);

      final SavingsAccountTransaction deposit =
          this.savingsAccountDomainService.handleDeposit(
              toSavingsAccount, fmt, transactionDate, transactionAmount, paymentDetail);

      final AccountTransfer transferTransaction =
          this.accountTransferAssembler.assembleLoanToSavingsTransfer(
              command, fromLoanAccount, toSavingsAccount, deposit, loanRefundTransaction);
      this.accountTransferRepository.saveAndFlush(transferTransaction);
      transferTransactionId = transferTransaction.getId();

    } else {

    }

    final CommandProcessingResultBuilder builder =
        new CommandProcessingResultBuilder().withEntityId(transferTransactionId);

    if (fromAccountType.isSavingsAccount()) {

      builder.withSavingsId(fromSavingsAccountId);
    }

    return builder.build();
  }