def sortOutCredits()

in membership-common/src/main/scala/com/gu/memsub/BillingSchedule.scala [73:94]


    def sortOutCredits(z: Zipper[Bill]): NonEmptyList[Bill] = z match {

      // the end of the list
      case Zipper(l, normal, Empty) =>
        (l.toList :+ normal).toNel.toOption.get

      // we have a negative bill, so we want to zero it and credit the next bill
      case Zipper(l, bill, r #:: rs) if bill.totalGross > 0 && bill.amount < 0 =>
        val creditAmount = bill.totalDeductions - bill.totalGross
        val debitAmount = bill.totalGross - bill.totalDeductions
        val cbCredit = BillItem("Credit balance", creditAmount, creditAmount)
        val cbDebit = BillItem(s"Credit from ${bill.date}", debitAmount, debitAmount)
        sortOutCredits(Zipper(l.append(Stream(bill.addItem(cbCredit))), r.addItem(cbDebit), rs))

      // we have a credit note which we want to remove and assign to the next bill
      case Zipper(l, credit, r #:: rs) if credit.totalGross == 0 && credit.amount < 0 =>
        sortOutCredits(Zipper(l, r.copy(items = r.items.append(credit.items)), rs))

      // we have a normal invoice
      case Zipper(l, f, r #:: rs) =>
        sortOutCredits(Zipper(l :+ f, r, rs))
    }