public void WhenBorrowingAllowedAndFinePaidBorrowingAllowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            Assert.False(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);

            member.AddFine(5.00f);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);

            member.PayFine(5.00f);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButStillOverFineLimitBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            member.AddFine(fineAmount);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount - BookConstants.FINE_LIMIT);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButHasOverdueLoansBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var loan = Substitute.For<ILoan>();

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            member.AddLoan(loan);

            member.AddFine(fineAmount);

            loan.IsOverDue.Returns(true);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButLoanLimitStillReachedBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            while (!member.HasReachedLoanLimit)
            {
                var loan = Substitute.For<ILoan>();

                member.AddLoan(loan);
            }

            member.AddFine(fineAmount);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.True(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButLoanLimitStillReachedBorrowingDisallowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            while (!member.HasReachedLoanLimit)
            {
                var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

                member.AddLoan(loan);
            }

            member.AddFine(fineAmount);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.True(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButHasOverdueLoansBorrowingDisallowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            member.AddLoan(loan);

            member.AddFine(fineAmount);

            foreach (var l in member.Loans) l.CheckOverDue(DateTime.Today.AddMonths(1));

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void PayFineThrowsArgumentExceptionIfPaymentExceedsFines()
        {
            const float fine = 5.50f;
            const float payment = 6.00f;

            var member = new Member("test", "member", "phone", "email", 1);

            member.AddFine(fine);

            Assert.Equal(fine, member.FineAmount);

            var fineAmount = member.FineAmount;

            var ex = Assert.Throws<ArgumentException>(() => member.PayFine(payment));

            Assert.Equal($"Payment must not exceed fines of {fineAmount}", ex.Message);
        }
        public void PayFineThrowsArgumentExceptionIfNegative()
        {
            const float fine = 5.50f;
            const float payment = -1.00f;

            var member = new Member("test", "member", "phone", "email", 1);

            member.AddFine(fine);

            Assert.Equal(fine, member.FineAmount);

            var ex = Assert.Throws<ArgumentException>(() => member.PayFine(payment));

            Assert.Equal("Payment must not be negative value", ex.Message);
        }
        public void CanPayFineByMember()
        {
            const float fine = 5.50f;
            const float payment = 2.50f;

            var member = new Member("test", "member", "phone", "email", 1);

            member.AddFine(fine);

            Assert.Equal(fine, member.FineAmount);

            member.PayFine(payment);

            Assert.Equal(fine - payment, member.FineAmount);
        }