@Test
  public void testGetPaymentsAmortizedFully() {

    AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
    MonetaryAmount loanAmount = ofUSD(10000);
    amAttrs.setLoanAmount(loanAmount);
    amAttrs.setInterestRateAsPercent(7.);
    amAttrs.setInterestOnly(false);
    amAttrs.setPaymentFrequency(TimePeriod.Monthly.getPeriodsPerYear());
    int termInMonths = 12;
    amAttrs.setTermInMonths(termInMonths);
    amAttrs.setAmortizationPeriodInMonths(12);
    amAttrs.setCompoundingPeriodsPerYear(2);
    amAttrs.setRegularPayment(AmortizationCalculator.getPeriodicPayment(amAttrs));

    List<ScheduledPayment> schedule = AmortizationCalculator.generateSchedule(amAttrs);

    MonetaryAmount interestTotal =
        schedule.stream().map(payment -> payment.getInterest()).reduce((a, b) -> a.add(b)).get();

    assertEquals("Amortized Interest total", ofUSD(377.67), interestTotal);

    MonetaryAmount principalTotal =
        schedule.stream().map(payment -> payment.getPrincipal()).reduce((a, b) -> a.add(b)).get();

    assertEquals("Amortized Principal fully paid", loanAmount, principalTotal);
  }
 @Test
 public void testGetActualPaymentWithNullRegularPayment() {
   AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
   amAttrs.setRegularPayment(null);
   MonetaryAmount periodicPayment = AmortizationCalculator.getPeriodicPayment(amAttrs);
   assertNotNull("Regular payment computed when initialized as null", periodicPayment);
 }
  @Test
  public void testGetPeriodicPaymentInterestOnlyMonthly() {

    AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
    amAttrs.setLoanAmount(USD50000);
    amAttrs.setPaymentFrequency(12);
    amAttrs.setInterestRateAsPercent(12.);
    amAttrs.setInterestOnly(true);
    MonetaryAmount result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    assertEquals("Monthly interest-only payment", USD500, result);
  }
 @Test
 public void testGetPeriodicPaymentAmortizedMonthlyCompoundPeriod() {
   AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
   amAttrs.setLoanAmount(USD50000.multiply(2));
   amAttrs.setInterestRateAsPercent(12.);
   amAttrs.setCompoundingPeriodsPerYear(12);
   amAttrs.setPaymentFrequency(12);
   MonetaryAmount result = AmortizationCalculator.getPeriodicPayment(amAttrs);
   MonetaryAmount expectedResult = ofUSD(1053.23);
   assertEquals("Monthly amortized payment compounded monthly", expectedResult, result);
 }
 @Test
 public void testGetPeriodicPaymentCompoundSemiPaymentSemiAnnually() {
   AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
   amAttrs.setLoanAmount(USD50000.divide(5));
   amAttrs.setInterestRateAsPercent(10.);
   amAttrs.setCompoundingPeriodsPerYear(TimePeriod.SemiAnnually.getPeriodsPerYear());
   amAttrs.setAmortizationPeriodInMonths(12);
   amAttrs.setPaymentFrequency(TimePeriod.SemiAnnually.getPeriodsPerYear());
   MonetaryAmount result = AmortizationCalculator.getPeriodicPayment(amAttrs);
   MonetaryAmount expectedResult = ofUSD(5378.05);
   assertEquals("Amortized, compounded semi-annual, payment semimonthly", expectedResult, result);
 }
  @Test
  public void testGetPeriodicPaymentInterestOnlyTimePeriods() {

    AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
    amAttrs.setLoanAmount(USD50000);
    amAttrs.setInterestRateAsPercent(10.);
    amAttrs.setInterestOnly(true);

    amAttrs.setPaymentFrequency(52);
    MonetaryAmount result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    MonetaryAmount expectedResult = ofUSD(96.16);
    assertEquals("Weekly interest-only", expectedResult, result);

    amAttrs.setPaymentFrequency(26);
    result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    expectedResult = ofUSD(192.31);
    assertEquals("BiWeekly interest-only", expectedResult, result);

    amAttrs.setPaymentFrequency(26);
    result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    expectedResult = ofUSD(192.31);
    assertEquals("BiWeekly interest-only", expectedResult, result);

    amAttrs.setPaymentFrequency(12);
    result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    expectedResult = ofUSD(416.67);
    assertEquals("Monthly interest-only", expectedResult, result);

    amAttrs.setPaymentFrequency(6);
    result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    expectedResult = ofUSD(833.34);
    assertEquals("BiMonthly interest-only", expectedResult, result);

    amAttrs.setPaymentFrequency(4);
    result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    expectedResult = ofUSD(1250);
    assertEquals("Quarterly interest-only", expectedResult, result);

    amAttrs.setPaymentFrequency(2);
    result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    expectedResult = ofUSD(2500);
    assertEquals("Semiannual interest-only", expectedResult, result);

    amAttrs.setPaymentFrequency(1);
    result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    expectedResult = ofUSD(5000);
    assertEquals("Annual interest-only", expectedResult, result);
  }
  @Test
  public void testGetPeriodicPaymentInterestOnlyMonthlyRoundsCeiling() {

    AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
    amAttrs.setLoanAmount(USD50000);
    amAttrs.setPaymentFrequency(12);
    amAttrs.setInterestRateAsPercent(11.);
    amAttrs.setInterestOnly(true);

    MonetaryAmount expectedResult =
        Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(458.34).create();

    MonetaryAmount result = AmortizationCalculator.getPeriodicPayment(amAttrs);
    assertEquals(
        "Monthly interest-only payment fractional penny, less than half a cent, rounds UP",
        expectedResult,
        result);
  }
  @Test
  public void testGetPeriodInterest_InterestOnly() {

    AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
    amAttrs.setLoanAmount(USD50000);
    amAttrs.setPaymentFrequency(12);
    amAttrs.setInterestRateAsPercent(11.);
    amAttrs.setInterestOnly(true);

    //        MonetaryAmount expectedResult = Monetary.getDefaultAmountFactory()
    //                .setCurrency("USD")
    //                .setNumber(458.34)
    //                .create();

    MonetaryAmount periodicPaymentResult = AmortizationCalculator.getPeriodicPayment(amAttrs);
    MonetaryAmount periodInterestRestult = AmortizationCalculator.getPeriodInterest(amAttrs);
    assertEquals(
        "Monthly interest-only payment should match interest computed for period.",
        periodicPaymentResult,
        periodInterestRestult);
  }
  @Test
  public void testGetPaymentsAmortized() {

    AmortizationAttributes amAttrs = generateAmortizationAttributesObjectTemplate();
    amAttrs.setLoanAmount(ofUSD(200000));
    amAttrs.setInterestRateAsPercent(8.);
    amAttrs.setInterestOnly(false);
    amAttrs.setPaymentFrequency(TimePeriod.Monthly.getPeriodsPerYear());
    int termInMonths = 36;
    amAttrs.setTermInMonths(termInMonths);
    amAttrs.setAmortizationPeriodInMonths(20 * 12);
    amAttrs.setCompoundingPeriodsPerYear(2);
    amAttrs.setRegularPayment(AmortizationCalculator.getPeriodicPayment(amAttrs));

    List<ScheduledPayment> schedule = AmortizationCalculator.generateSchedule(amAttrs);

    assertEquals("Amortized payment count", termInMonths, schedule.size());

    MonetaryAmount interestTotal =
        schedule.stream().map(payment -> payment.getInterest()).reduce((a, b) -> a.add(b)).get();

    assertEquals("Amortized Interest total", ofUSD(45681.29), interestTotal);
  }