public void GetMyAccountsDetail_WhenProvideLowellReference_RetrievesAccount_CallsStatusDeriver()
        {
            // Note: using mock Status Deriver, so as to avoid exhaustively testing statuses here, as responsibility
            // for deriving statuses is with concrete Status Deriver class

            // Mock will apply a status value, allowing us to ensure it is called

            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            _mockStatusDeriverProcess.Setup(x => x.DeriveStatusAndStatusSort(
                                                It.IsAny <ICaseFlowAccountCommon>(),
                                                It.IsAny <MyAccountsSummaryResultDto>()))
            .Callback <ICaseFlowAccountCommon, MyAccountsSummaryResultDto>(
                (caseFlowAccountDto, resultDto) =>
            {
                // Status deriver places 'ClientName' into status to facilitate testing
                Debug.Assert(caseFlowAccountDto.ClientName != null);
                resultDto.AccountStatus = caseFlowAccountDto.ClientName;
            });

            CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
            {
                ClientName = "Def"
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

            // Act
            MyAccountsDetailResultDto outputDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            Assert.AreEqual("Def", outputDto.AccountStatus);
        }
        public void GetMyAccountsDetail_WhenProvideLowellReference_AndDiscountedBalanceEqualToOutstandingBalance_RetrievesAccount_DiscountBalanceNOTOutput(
            double?testOutstandingBalance, double?testDiscountedBalance)
        {
            // Discount Balance will EQUAL Outstanding Balance if there isn't a discount

            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
            {
                OutstandingBalance = (decimal?)testOutstandingBalance,    // doubles in params, because MSTest does not support decimal
                DiscountedBalance  = (decimal?)testDiscountedBalance
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

            // Act
            MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            // Assert
            Assert.AreEqual(null, resultDto.DiscountedBalance);

            // Ensure outstanding balance unaffected
            Assert.AreEqual((decimal?)testOutstandingBalance ?? 0, resultDto.OutstandingBalance);
        }
        [DataRow(false, true, false)]       // with Solicitors - stays false

        public void GetMyAccountsDetail_WhenProvideLowellReference_AndAccountWithSolicitors_RetrievesAccount_OverridesCanMakePaymentToFalse(
            bool testCanMakePaymentFlagFromCaseFlow,
            bool testIsWithSolicitorsFromStatusDeriver,
            bool expectedCanMakePaymentOutput)
        {
            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
            {
                // Flag that may be overridden
                CanMakePayment = testCanMakePaymentFlagFromCaseFlow
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

            _mockStatusDeriverProcess.Setup(x => x.DeriveStatusAndStatusSort(caseFlowDto, It.IsAny <MyAccountsSummaryResultDto>()))
            .Callback <ICaseFlowAccountCommon, MyAccountsSummaryResultDto>(
                (caseFlowAccountDto, deriverResultDto) =>
            {
                // Status deriver places 'Is With Solicitors' flag into output DTO to facilitate testing
                deriverResultDto.AccountStatusIsWithSolicitors = testIsWithSolicitorsFromStatusDeriver;
            });

            // Act
            MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            // Assert
            Assert.AreEqual(expectedCanMakePaymentOutput, resultDto.CanMakePayment);
        }
        public void GetMyAccountsDetail_WhenProvideLowellReference_With_FiveTransactions_Then_OutputsFiveTransactions()
        {
            // NOTE: Not testing 5 transactions (or more) because the number of transactions is controlled
            // by the proxy call (to CaseFlow)

            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowAccountDto = new CaseFlowMyAccountsDetailDto();
            RecievedTransactionsDto     caseFlowReceivedTransactionsDto = new RecievedTransactionsDto()
            {
                Payments = new List <PaymentDetails>()
                {
                    new PaymentDetails()
                    {
                        Date           = new DateTime(2018, 11, 25),
                        Amount         = 123.45M,
                        Type           = "Type",
                        RollingBalance = 678.91M
                    },
                    new PaymentDetails()
                    {
                        Date           = new DateTime(2017, 10, 13),
                        Amount         = 9999.99M,
                        Type           = "Type II",
                        RollingBalance = 1000000.01M
                    }
                }
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowAccountDto));
            _mockMyAccountDetailGetTransactionsRecentProcess.Setup(x => x.GetTransactionsRecent(lowellReference, 5)).Returns(Task.FromResult(caseFlowReceivedTransactionsDto));

            // Act
            MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            // Assert
            Assert.AreEqual(2, resultDto.RecentTransactions.Count);
            {
                MyAccountsDetailResultDto.RecentTransaction transaction = resultDto.RecentTransactions[0];
                Assert.AreEqual(new DateTime(2018, 11, 25), transaction.Date);
                Assert.AreEqual(123.45M, transaction.Amount);
                Assert.AreEqual("Type", transaction.Type);
                Assert.AreEqual(678.91M, transaction.RollingBalance);
            }
            {
                MyAccountsDetailResultDto.RecentTransaction transaction = resultDto.RecentTransactions[1];
                Assert.AreEqual(new DateTime(2017, 10, 13), transaction.Date);
                Assert.AreEqual(9999.99M, transaction.Amount);
                Assert.AreEqual("Type II", transaction.Type);
                Assert.AreEqual(1000000.01M, transaction.RollingBalance);
            }

            _mockMyAccountDetailGetTransactionsRecentProcess.Verify(x => x.GetTransactionsRecent(lowellReference, 5), Times.Once);
        }
        public void GetMyAccountsDetail_WhenProvideLowellReference_With_NoTransactions_Then_OutputsEmptyTransactionsList()
        {
            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowAccountDto = new CaseFlowMyAccountsDetailDto();
            RecievedTransactionsDto     caseFlowReceivedTransactionsDto = new RecievedTransactionsDto();

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowAccountDto));
            _mockMyAccountDetailGetTransactionsRecentProcess.Setup(x => x.GetTransactionsRecent(lowellReference, 5)).Returns(Task.FromResult(caseFlowReceivedTransactionsDto));

            // Act
            MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            // Assert
            Assert.AreEqual(0, resultDto.RecentTransactions.Count);
        }
        public void GetMyAccounts_ShouldCallProxy_Once()
        {
            const string testLoginId = "anything123";

            // Arrange
            // Content does not matter, as straight pass through of objects
            var caseFlowDto = new CaseFlowMyAccountsDetailDto();

            _mockProxy.Setup(x => x.GetMyAccountsDetailAsync(testLoginId))
            .Returns(Task.FromResult(caseFlowDto));

            //Act
            var result = _process.GetMyAccountsDetail(testLoginId).Result;

            //Assert
            Assert.AreEqual(caseFlowDto, result);

            _mockProxy.Verify(x => x.GetMyAccountsDetailAsync(testLoginId), Times.Once);
        }
        public void GetMyAccountsDetail_WhenProvideLowellReference_RetrievesAccount_OutputsTransformedModel()
        {
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            {
                // Arrange
                CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
                {
                    LowellReference    = "1234",
                    ClientName         = "BarclayBob",
                    OutstandingBalance = 1234.56M,
                    CanMakePayment     = false,

                    HasArrangement = true,
                    PlanType       = "Direct Debit",
                    PlanFrequency  = "Monthly",
                    RegularAccountPaymentAmount = 123.45M,

                    ExcludedMessage = "Test excl"
                };

                _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

                // Act
                MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

                // Assert
                {
                    Assert.AreEqual("1234", resultDto.AccountReference);
                    Assert.AreEqual("BarclayBob", resultDto.OriginalCompany);
                    Assert.AreEqual(1234.56M, resultDto.OutstandingBalance);
                    Assert.AreEqual(false, resultDto.CanMakePayment);

                    Assert.AreEqual("Direct Debit", resultDto.PaymentPlanMethod);
                    Assert.AreEqual("Monthly", resultDto.PaymentPlanFrequency);
                    Assert.AreEqual(123.45M, resultDto.PaymentPlanAmount);

                    Assert.AreEqual("Test excl", resultDto.AccountMessage);
                }
            }
        }
        public void GetMyAccountsDetail_WhenProvideLowellReference_RetrievesAccount_OutputsPaymentPlanIsAutomated(
            bool testHasArrangement, string testPlanType,
            bool expectedPaymentPlanIsAutomated)
        {
            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
            {
                HasArrangement = testHasArrangement,
                PlanType       = testPlanType
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

            // Act
            MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            // Assert
            Assert.AreEqual(expectedPaymentPlanIsAutomated, resultDto.PaymentPlanIsAutomated);
        }
        public void GetMyAccountsDetail_WhenProvideLowellReference_RetrievesAccount_OutputsArrears(
            double?testArrears, bool testHasArrangement,
            double?expectedPaymentPlanArrearsAmount)
        {
            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
            {
                Arrears        = (decimal?)testArrears,
                HasArrangement = testHasArrangement
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

            // Act
            MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            // Assert
            Assert.AreEqual((decimal?)expectedPaymentPlanArrearsAmount, resultDto.PaymentPlanArrearsAmount);
        }
        // Provides interface to allow unit testing without being tied to 'now'
        internal async Task <MyAccountsDetailResultDto> GetMyAccountsDetail(string userId, string lowellReference, DateTime currentDateTime)
        {
            CaseFlowMyAccountsDetailDto caseFlowAccount = await _getDetailProcess.GetMyAccountsDetail(lowellReference);

            RecievedTransactionsDto caseFlowTransactions = await _getTransactionProcess.GetTransactionsRecent(lowellReference, 5);

            MyAccountsDetailResultDto resultDto = new MyAccountsDetailResultDto();

            PopulateCommonFields(caseFlowAccount, resultDto, currentDateTime);

            // Fields included in Detail only (not on My Accounts summary)
            resultDto.AccountMessage = caseFlowAccount.ExcludedMessage;

            resultDto.PlanMessages = caseFlowAccount.PlanMessages;

            resultDto.RecentTransactions = new List <MyAccountsDetailResultDto.RecentTransaction>();

            // CaseFlow returns empty content (and 204) if there are no transactions, rather than empty list
            if (caseFlowTransactions != null)
            {
                foreach (PaymentDetails payment in caseFlowTransactions.Payments)
                {
                    MyAccountsDetailResultDto.RecentTransaction transaction =
                        new MyAccountsDetailResultDto.RecentTransaction()
                    {
                        Date           = payment.Date,
                        Amount         = payment.Amount,
                        Description    = payment.Description,
                        Type           = payment.Type,
                        RollingBalance = payment.RollingBalance
                    };

                    resultDto.RecentTransactions.Add(transaction);
                }
            }

            return(resultDto);
        }
        public void GetMyAccountsDetail_WhenProvideLowellReference_AndSatisfiesPlanConditions_RetrievesAccount_OutputsPlan(
            bool testHasArrangement,
            double?testOutstandingBalance,
            string testPlanType,
            string testPlanFrequency,
            double?testRegularAccountPaymentAmount,

            string expectedPaymentPlanMethod,
            string expectedPaymentPlanFrequency,
            double?expectedPaymentPlanAmount)
        {
            // Arrange
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
            {
                HasArrangement              = testHasArrangement,
                OutstandingBalance          = (decimal?)testOutstandingBalance, // doubles in params, because MSTest does not support decimal
                PlanType                    = testPlanType,
                PlanFrequency               = testPlanFrequency,
                RegularAccountPaymentAmount = (decimal?)testRegularAccountPaymentAmount
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

            // Act
            MyAccountsDetailResultDto resultDto = _service.GetMyAccountsDetail(userId, lowellReference).Result;

            // Assert
            Assert.AreEqual(expectedPaymentPlanMethod, resultDto.PaymentPlanMethod);
            Assert.AreEqual(expectedPaymentPlanFrequency, resultDto.PaymentPlanFrequency);
            Assert.AreEqual((decimal?)expectedPaymentPlanAmount, resultDto.PaymentPlanAmount);

            // Ensure outstanding balance unaffected
            Assert.AreEqual((decimal?)testOutstandingBalance ?? 0, resultDto.OutstandingBalance);
        }
        [DataRow(81, 100.0D, 100.0D, 55.99D, "15/06/2012", "15/06/2012 23:59", 0L, true, "Direct Debit", null, null)]     // on expiry date (end minute of day)

        public void GetMyAccountsDetail_WhenProvideLowellReference_AndSatisfiesDiscountOfferConditions_RetrievesAccount_OutputsDiscountOffer(
            int testNumber,
            double?testOutstandingBalance,
            double?testDiscountedBalance,
            double?testDiscountAmount,      // indicates offer
            string testDiscountExpiryString,
            string testCurrentDateTimeString,
            long?testCompany,
            bool testHasArrangement,
            string testPlanType,

            double?expectedDiscountOfferAmount,
            string expectedDiscountOfferExpiryString)
        {
            // Can't use DateTime in attribute, therefore need to convert from strings
            DateTime?testDiscountExpiry          = ConvertTestStringToNullableDateTime(testDiscountExpiryString, "d");
            DateTime testCurrentDateTime         = ConvertTestStringToDateTime(testCurrentDateTimeString, "g");
            DateTime?expectedDiscountOfferExpiry = ConvertTestStringToNullableDateTime(expectedDiscountOfferExpiryString, "d");

            // Test assumption - 'Local' date can be compared with 'Unspecified' date
            {
                DateTime dtNow = DateTime.Now;
                Assert.AreEqual(DateTimeKind.Local, dtNow.Kind);

                DateTime dtNowMinusHour = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, dtNow.Hour, dtNow.Minute, dtNow.Second).AddHours(-1);
                Assert.AreEqual(DateTimeKind.Unspecified, dtNowMinusHour.Kind);

                Assert.IsTrue(dtNowMinusHour < dtNow);
                Assert.IsTrue(dtNow > dtNowMinusHour);

                DateTime dtNowPlusHour = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, dtNow.Hour, dtNow.Minute, dtNow.Second).AddHours(1);
                Assert.AreEqual(DateTimeKind.Unspecified, dtNowMinusHour.Kind);

                Assert.IsTrue(dtNowPlusHour > dtNow);
                Assert.IsTrue(dtNow < dtNowPlusHour);
            }

            //
            // Arrange
            //
            const string userId          = "anyuser123";
            const string lowellReference = "wibble";

            CaseFlowMyAccountsDetailDto caseFlowDto = new CaseFlowMyAccountsDetailDto()
            {
                OutstandingBalance = (decimal?)testOutstandingBalance,  // doubles in params, because MSTest does not support decimal
                DiscountedBalance  = (decimal?)testDiscountedBalance,
                DiscountAmount     = (decimal?)testDiscountAmount,
                DiscountExpiry     = testDiscountExpiry,
                Company            = testCompany,
                HasArrangement     = testHasArrangement,
                PlanType           = testPlanType
            };

            _mockGetDetailsProcess.Setup(x => x.GetMyAccountsDetail(lowellReference)).Returns(Task.FromResult(caseFlowDto));

            // Must use concrete Status Deriver, so that Solicitor (company 2) logic is followed
            MyAccountsService service = new MyAccountsService(_mockLogger.Object,
                                                              _mockGetProcess.Object,
                                                              _mockGetDetailsProcess.Object,
                                                              _mockMyAccountDetailGetTransactionsRecentProcess.Object,
                                                              new MyAccountsStatusDeriver(_mockMyAccountsStatusDeriverlogger.Object)); // **** IMPORTANT BIT

            //
            // Act
            //

            // Using service created above, so as to utilise concrete Status Deriver
            MyAccountsDetailResultDto resultDto = service.GetMyAccountsDetail(userId, lowellReference, testCurrentDateTime).Result;

            //
            // Assert
            //
            Assert.AreEqual((decimal?)expectedDiscountOfferAmount, resultDto.DiscountOfferAmount);
            Assert.AreEqual(expectedDiscountOfferExpiry, resultDto.DiscountOfferExpiry);
        }